diff --git a/.appveyor.yml b/.appveyor.yml index d24b929ee..0f89793ba 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -68,7 +68,7 @@ before_build: build_script: - mkdir build - cd build - - cmake -DCMAKE_BUILD_TYPE=%CONFIGURATION% -GNinja .. + - cmake -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DLLVM_ROOT_DIR=C:\projects\deps\llvm -GNinja .. - ninja urde #notifications: diff --git a/.clang-format b/.clang-format index 6ed326e11..60bd33c2a 100644 --- a/.clang-format +++ b/.clang-format @@ -2,6 +2,7 @@ BasedOnStyle: LLVM ColumnLimit: 120 UseTab: Never +TabWidth: 4 --- Language: Cpp DerivePointerAlignment: false @@ -25,4 +26,4 @@ BinPackParameters: true SortIncludes: false AccessModifierOffset: -2 ConstructorInitializerIndentWidth: 0 -ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerAllOnOneLineOrOnePerLine: true \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index ba71b695e..72f1932a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,8 +40,8 @@ project(urde VERSION 0.1.0) # when available. GCC and Clang posess no such flag, and must be # manually enforced. CMake, curiously, also doesn't have a "latest" # standard flag either. -if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(CMAKE_CXX_STANDARD 17) +if (NOT MSVC) + set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() @@ -86,30 +86,45 @@ if(MSVC) add_compile_options(/IGNORE:4221 /wd4018 /wd4800 /wd4005 /wd4311 /wd4068 /wd4267 /wd4244 /wd4200 /wd4305 /wd4067 /wd4146 /wd4309 /wd4805 ${VS_OPTIONS}) - if(WINDOWS_STORE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /AI\"$ENV{PROGRAMFILES\(X86\)}/Microsoft Visual Studio/2017/Community/Common7/IDE/VC/vcpackages\" /AI\"$ENV{PROGRAMFILES\(X86\)}/Windows Kits/10/UnionMetadata\"") - set(HAVE_WORDS_BIGENDIAN_EXITCODE 0) - endif() + add_compile_options( + # Disable exceptions + $<$:/EHsc-> - add_compile_options(/EHsc) + # Disable RTTI + $<$:/GR-> + + # Enforce various standards compliant behavior. + $<$:/permissive-> + + # Enable standard volatile semantics. + $<$:/volatile:iso> + + # Reports the proper value for the __cplusplus preprocessor macro. + $<$:/Zc:__cplusplus> + + # Use latest C++ standard. + $<$:/std:c++latest> + ) + add_compile_definitions(FMT_EXCEPTIONS=0 _HAS_EXCEPTIONS=0) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + # Flags for MSVC (not clang-cl) add_compile_options( - /std:c++latest # Use latest C++ standard. - /permissive- # Enforce various standards compliance features. - /Zc:externConstexpr # Allow extern constexpr variables according to the standard. - /Zc:throwingNew # Assume new throws, allowing for better code generation. + # Allow constexpr variables to have explicit external linkage. + $<$:/Zc:externConstexpr> + + # Assume that new throws exceptions, allowing better code generation. + $<$:/Zc:throwingNew> + + # Link-time Code Generation for Release builds + $<$,$>:/GL> ) - # Link-time Code Generation for Release builds (excluding clang-cl) - set(CMAKE_C_FLAGS_RELEASE "/DNDEBUG /O2 /Oy /GL /Gy /MD") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "/DNDEBUG /Zi /O2 /Oy- /GL /Gy /MD") + # Link-time Code Generation for Release builds set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/LTCG") set(CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "/LTCG") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO") set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/DEBUG /RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO /DEBUGTYPE:cv,fixup") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") endif() else() @@ -144,21 +159,19 @@ else() endif() if(URDE_MSAN) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") - add_compile_options(-fsanitize=memory -fsanitize-memory-track-origins -fsanitize-recover=all) + add_compile_options($<$:-stdlib=libc++> -fsanitize=memory + -fsanitize-memory-track-origins -fsanitize-recover=all) endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") - add_compile_options(-Wall -Wno-multichar -Werror=implicit-fallthrough -Wno-unknown-warning-option + add_compile_options($<$:-fno-rtti> + $<$:-fno-exceptions> + -Wall -Wno-multichar -Werror=implicit-fallthrough -Wno-unknown-warning-option -Wno-lto-type-mismatch -Wno-unused-variable -Wno-unused-private-field -Wno-unused-function -Wno-sign-compare -Wno-unknown-pragmas -Werror) add_compile_definitions(FMT_EXCEPTIONS=0) if(APPLE) - add_compile_options(-Wno-error=deprecated-declarations) - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -flto=thin") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -flto=thin") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto=thin") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -flto=thin") + add_compile_options(-Wno-error=deprecated-declarations + $<$,$>:-flto=thin>) endif() endif() diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 000000000..7dfcfe1d9 --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,186 @@ +{ + "configurations": [ + { + "name": "x64-Clang-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "clang_cl_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "variables": [ + { + "name": "CMAKE_PREFIX_PATH", + "value": "C:\\Qt\\5.14.2\\msvc2017_64", + "type": "FILEPATH" + }, + { + "name": "CMAKE_CXX_FLAGS", + "value": "-m64 -fdiagnostics-absolute-paths", + "type": "STRING" + }, + { + "name": "CMAKE_C_FLAGS", + "value": "-m64 -fdiagnostics-absolute-paths", + "type": "STRING" + }, + { + "name": "CMAKE_LINKER", + "value": "C:\\Program Files\\LLVM\\bin\\lld-link.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_C_COMPILER", + "value": "C:\\Program Files\\LLVM\\bin\\clang-cl.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_CXX_COMPILER", + "value": "C:\\Program Files\\LLVM\\bin\\clang-cl.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_C_COMPILER_RANLIB", + "value": "C:\\Program Files\\LLVM\\bin\\llvm-ranlib.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_C_COMPILER_AR", + "value": "C:\\Program Files\\LLVM\\bin\\llvm-ar.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_CXX_COMPILER_AR", + "value": "C:\\Program Files\\LLVM\\bin\\llvm-ar.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_CXX_COMPILER_RANLIB", + "value": "C:\\Program Files\\LLVM\\bin\\llvm-ranlib.exe", + "type": "FILEPATH" + } + ] + }, + { + "name": "x64-Clang-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64" ], + "variables": [ + { + "name": "CMAKE_PREFIX_PATH", + "value": "C:\\Qt\\5.14.2\\msvc2017_64", + "type": "FILEPATH" + }, + { + "name": "CMAKE_CXX_FLAGS", + "value": "-m64 -fdiagnostics-absolute-paths", + "type": "STRING" + }, + { + "name": "CMAKE_C_FLAGS", + "value": "-m64 -fdiagnostics-absolute-paths", + "type": "STRING" + }, + { + "name": "CMAKE_LINKER", + "value": "C:\\Program Files\\LLVM\\bin\\lld-link.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_C_COMPILER", + "value": "C:\\Program Files\\LLVM\\bin\\clang-cl.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_CXX_COMPILER", + "value": "C:\\Program Files\\LLVM\\bin\\clang-cl.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_C_COMPILER_RANLIB", + "value": "C:\\Program Files\\LLVM\\bin\\llvm-ranlib.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_C_COMPILER_AR", + "value": "C:\\Program Files\\LLVM\\bin\\llvm-ar.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_CXX_COMPILER_AR", + "value": "C:\\Program Files\\LLVM\\bin\\llvm-ar.exe", + "type": "FILEPATH" + }, + { + "name": "CMAKE_CXX_COMPILER_RANLIB", + "value": "C:\\Program Files\\LLVM\\bin\\llvm-ranlib.exe", + "type": "FILEPATH" + } + ] + }, + { + "name": "x64-MSVC-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64" ], + "variables": [ + { + "name": "CMAKE_PREFIX_PATH", + "value": "C:\\Qt\\5.14.2\\msvc2017_64", + "type": "FILEPATH" + }, + { + "name": "CMAKE_CXX_FLAGS", + "value": "", + "type": "STRING" + }, + { + "name": "CMAKE_C_FLAGS", + "value": "", + "type": "STRING" + } + ] + }, + { + "name": "x64-MSVC-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64" ], + "variables": [ + { + "name": "CMAKE_PREFIX_PATH", + "value": "C:\\Qt\\5.14.2\\msvc2017_64", + "type": "FILEPATH" + }, + { + "name": "CMAKE_CXX_FLAGS", + "value": "", + "type": "STRING" + }, + { + "name": "CMAKE_C_FLAGS", + "value": "", + "type": "STRING" + } + ] + } + ] +} \ No newline at end of file diff --git a/DataSpec/AssetNameMap.cpp b/DataSpec/AssetNameMap.cpp index ace70701c..a720d15e0 100644 --- a/DataSpec/AssetNameMap.cpp +++ b/DataSpec/AssetNameMap.cpp @@ -32,7 +32,7 @@ void LoadAssetMap(athena::io::MemoryReader& ar) { ar.readBytesToBuf(&magic, 4); if (magic != FOURCC('AIDM')) Log.report(logvisor::Warning, - fmt(_SYS_STR("Unable to load asset map; Assets will not have proper filenames for most files."))); + FMT_STRING(_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); @@ -50,7 +50,7 @@ void InitAssetNameMap() { if (g_AssetNameMapInit) return; - Log.report(logvisor::Info, fmt("Initializing asset name database...")); + Log.report(logvisor::Info, FMT_STRING("Initializing asset name database...")); /* First load the 32bit map for MP1/2 */ { diff --git a/DataSpec/Blender/RetroMasterShader.py b/DataSpec/Blender/RetroMasterShader.py index 6e49ee676..4749aa409 100644 --- a/DataSpec/Blender/RetroMasterShader.py +++ b/DataSpec/Blender/RetroMasterShader.py @@ -58,6 +58,8 @@ def make_retro_shader(): lightmap_input.default_value = (0.0, 0.0, 0.0, 0.0) diffuse_input = new_grp.inputs.new('NodeSocketColor', 'Diffuse') diffuse_input.default_value = (0.0, 0.0, 0.0, 0.0) + diffuse_mod_input = new_grp.inputs.new('NodeSocketColor', 'DiffuseMod') + diffuse_mod_input.default_value = (1.0, 1.0, 1.0, 1.0) emissive_input = new_grp.inputs.new('NodeSocketColor', 'Emissive') emissive_input.default_value = (0.0, 0.0, 0.0, 0.0) specular_input = new_grp.inputs.new('NodeSocketColor', 'Specular') @@ -72,6 +74,10 @@ def make_retro_shader(): alpha_input.default_value = 1.0 alpha_input.min_value = 0.0 alpha_input.max_value = 1.0 + alpha_mod_input = new_grp.inputs.new('NodeSocketFloatFactor', 'AlphaMod') + alpha_mod_input.default_value = 1.0 + alpha_mod_input.min_value = 0.0 + alpha_mod_input.max_value = 1.0 new_grp.use_fake_user = True # Group inputs @@ -108,6 +114,17 @@ def make_retro_shader(): new_shader_model_mix1 = new_grp.nodes.new('ShaderNodeMixShader') new_shader_model_mix1.location = (-760, 340) + # Multiply (Multiples diffuse with diffusemod) + diffuse_mult = new_grp.nodes.new('ShaderNodeMixRGB') + diffuse_mult.location = (-1094, 122) + diffuse_mult.blend_type = 'MULTIPLY' + diffuse_mult.inputs['Fac'].default_value = 1.0 + + # Multiply (Multiples alpha with alphamod) + alpha_mult = new_grp.nodes.new('ShaderNodeMath') + alpha_mult.location = (-1094, -178) + alpha_mult.operation = 'MULTIPLY' + # Multiply (Multiplies static lightmap with diffuse) lightmap_mult = new_grp.nodes.new('ShaderNodeMixRGB') lightmap_mult.location = (-944, 122) @@ -164,17 +181,21 @@ def make_retro_shader(): mat_out.location = (150, -88) # Links + new_grp.links.new(grp_in.outputs['Diffuse'], diffuse_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['DiffuseMod'], diffuse_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Alpha'], alpha_mult.inputs[0]) + new_grp.links.new(grp_in.outputs['AlphaMod'], alpha_mult.inputs[1]) new_grp.links.new(grp_in.outputs['Lightmap'], lightmap_mult.inputs['Color1']) - new_grp.links.new(grp_in.outputs['Diffuse'], lightmap_mult.inputs['Color2']) - new_grp.links.new(grp_in.outputs['Diffuse'], diffuse_bdsf.inputs['Color']) - new_grp.links.new(grp_in.outputs['Diffuse'], principled_bsdf.inputs['Base Color']) + new_grp.links.new(diffuse_mult.outputs['Color'], lightmap_mult.inputs['Color2']) + new_grp.links.new(diffuse_mult.outputs['Color'], diffuse_bdsf.inputs['Color']) + new_grp.links.new(diffuse_mult.outputs['Color'], principled_bsdf.inputs['Base Color']) new_grp.links.new(grp_in.outputs['Emissive'], emissive_add_shader.inputs[0]) new_grp.links.new(grp_in.outputs['Specular'], specular_mult.inputs['Color1']) new_grp.links.new(grp_in.outputs['Specular'], principled_bsdf.inputs['Specular']) new_grp.links.new(grp_in.outputs['ExtendedSpecular'], extended_specular_mult.inputs['Color1']) new_grp.links.new(grp_in.outputs['Reflection'], specular_mult.inputs['Color2']) new_grp.links.new(grp_in.outputs['Reflection'], extended_specular_mult.inputs['Color2']) - new_grp.links.new(grp_in.outputs['Alpha'], alpha_mix.inputs['Fac']) + new_grp.links.new(alpha_mult.outputs[0], alpha_mix.inputs['Fac']) new_grp.links.new(new_shader_model.outputs['Value'], new_shader_model_mix1.inputs[0]) new_grp.links.new(diffuse_bdsf.outputs['BSDF'], new_shader_model_mix1.inputs[1]) new_grp.links.new(grp_in.outputs['Specular'], invert.inputs['Color']) @@ -700,11 +721,661 @@ def make_retro_dynamic_character_shader(): new_grp.links.new(final_add_shader.outputs['Shader'], alpha_mix.inputs[2]) new_grp.links.new(alpha_mix.outputs['Shader'], mat_out.inputs['Surface']) +# MP3 / DKCR Material Passes: +# https://wiki.axiodl.com/w/Materials_(Metroid_Prime_3) + +def make_retro_shader_mp3_color(): + new_grp = bpy.data.node_groups.new("__RetroShaderMP3Color", "ShaderNodeTree") + new_grp.use_fake_user = True + input = new_grp.inputs.new("NodeSocketColor", "DIFFC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "DIFBC") + input.default_value = (1.0, 1.0, 1.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "CLRC") + input.default_value = (0.5, 0.5, 0.5, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "CLRA") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "TRAN") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "RFLDC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "RFLDA") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "RFLV") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "LRLD") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "LURDC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "LURDA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "INCAC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketInt", "Add INCA") + input.default_value = 0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "OPAC") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + new_grp.outputs.new("NodeSocketShader", "Shader") + nodes = {} + node = new_grp.nodes.new("ShaderNodeBsdfDiffuse") + node.name = "Diffuse BSDF.004" + nodes["Diffuse BSDF.004"] = node + node.label = "" + node.location = (-196.910400390625, -503.60546875) + node.inputs[0].default_value = (0.800000011920929, 0.800000011920929, 0.800000011920929, 1.0) + node.inputs[1].default_value = 0.0 + node.inputs[2].default_value = (0.0, 0.0, 0.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.009" + nodes["Add Shader.009"] = node + node.label = "" + node.location = (14.618888854980469, -571.516357421875) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.008" + nodes["Add Shader.008"] = node + node.label = "" + node.location = (6.4276123046875, -926.3602905273438) + node = new_grp.nodes.new("ShaderNodeBsdfDiffuse") + node.name = "Diffuse BSDF.005" + nodes["Diffuse BSDF.005"] = node + node.label = "" + node.location = (-189.85516357421875, -865.79345703125) + node.inputs[0].default_value = (0.800000011920929, 0.800000011920929, 0.800000011920929, 1.0) + node.inputs[1].default_value = 0.0 + node.inputs[2].default_value = (0.0, 0.0, 0.0) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.005" + nodes["Mix.005"] = node + node.label = "" + node.location = (-190.5804901123047, -1017.0886840820312) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.004" + nodes["Mix.004"] = node + node.label = "" + node.location = (-381.6676940917969, -870.815673828125) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.006" + nodes["Add Shader.006"] = node + node.label = "" + node.location = (220.7507781982422, -724.6066284179688) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.005" + nodes["Add Shader.005"] = node + node.label = "" + node.location = (218.0698699951172, -528.0934448242188) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.007" + nodes["Add Shader.007"] = node + node.label = "" + node.location = (388.0714416503906, -600.8295288085938) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.002" + nodes["Mix.002"] = node + node.label = "" + node.location = (-192.1793212890625, -281.65264892578125) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.010" + nodes["Add Shader.010"] = node + node.label = "" + node.location = (522.2215576171875, -284.7532653808594) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.001" + nodes["Mix.001"] = node + node.label = "" + node.location = (-198.2812957763672, -13.079503059387207) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeBsdfDiffuse") + node.name = "Diffuse BSDF.001" + nodes["Diffuse BSDF.001"] = node + node.label = "" + node.location = (-200.4605255126953, 138.9542694091797) + node.inputs[0].default_value = (0.800000011920929, 0.800000011920929, 0.800000011920929, 1.0) + node.inputs[1].default_value = 0.0 + node.inputs[2].default_value = (0.0, 0.0, 0.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.001" + nodes["Add Shader.001"] = node + node.label = "" + node.location = (-14.161624908447266, 32.61324691772461) + node = new_grp.nodes.new("NodeGroupOutput") + node.name = "Group Output" + nodes["Group Output"] = node + node.label = "" + node.location = (948.8831176757812, -299.1160583496094) + node = new_grp.nodes.new("ShaderNodeBsdfTransparent") + node.name = "Transparent BSDF.001" + nodes["Transparent BSDF.001"] = node + node.label = "" + node.location = (604.5911254882812, -88.7776870727539) + node.inputs[0].default_value = (1.0, 1.0, 1.0, 1.0) + node = new_grp.nodes.new("ShaderNodeMixShader") + node.name = "Mix Shader" + nodes["Mix Shader"] = node + node.label = "" + node.location = (772.179443359375, -91.1546401977539) + node.inputs[0].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.012" + nodes["Add Shader.012"] = node + node.label = "" + node.location = (776.751953125, -432.8694152832031) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.011" + nodes["Add Shader.011"] = node + node.label = "" + node.location = (779.857177734375, -294.9550476074219) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.006" + nodes["Mix.006"] = node + node.label = "" + node.location = (-192.534912109375, -643.984619140625) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.003" + nodes["Mix.003"] = node + node.label = "" + node.location = (-374.2341003417969, -515.1140747070312) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix" + nodes["Mix"] = node + node.label = "" + node.location = (-500.3056640625, -114.82369995117188) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math" + nodes["Math"] = node + node.label = "" + node.location = (454.39404296875, 96.02081298828125) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.001" + nodes["Math.001"] = node + node.label = "" + node.location = (619.3079223632812, 90.52423095703125) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.002" + nodes["Math.002"] = node + node.label = "" + node.location = (785.3211059570312, 81.7295913696289) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeBsdfTransparent") + node.name = "Transparent BSDF" + nodes["Transparent BSDF"] = node + node.label = "" + node.location = (597.9944458007812, -480.7802734375) + node.inputs[0].default_value = (1.0, 1.0, 1.0, 1.0) + node = new_grp.nodes.new("NodeGroupInput") + node.name = "Group Input" + nodes["Group Input"] = node + node.label = "" + node.location = (-669.6587524414062, -193.9534149169922) + new_grp.links.new(nodes["Group Input"].outputs[0], nodes["Mix"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[1], nodes["Mix"].inputs[2]) + new_grp.links.new(nodes["Mix"].outputs[0], nodes["Mix.001"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[2], nodes["Mix.001"].inputs[2]) + new_grp.links.new(nodes["Mix.001"].outputs[0], nodes["Add Shader.001"].inputs[1]) + new_grp.links.new(nodes["Diffuse BSDF.001"].outputs[0], nodes["Add Shader.001"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[2], nodes["Diffuse BSDF.001"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[5], nodes["Mix.002"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[7], nodes["Mix.002"].inputs[2]) + new_grp.links.new(nodes["Mix.002"].outputs[0], nodes["Add Shader.005"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[5], nodes["Mix.003"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[8], nodes["Mix.003"].inputs[2]) + new_grp.links.new(nodes["Mix.003"].outputs[0], nodes["Diffuse BSDF.004"].inputs[0]) + new_grp.links.new(nodes["Diffuse BSDF.004"].outputs[0], nodes["Add Shader.009"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[5], nodes["Mix.004"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[10], nodes["Mix.004"].inputs[2]) + new_grp.links.new(nodes["Mix.004"].outputs[0], nodes["Diffuse BSDF.005"].inputs[0]) + new_grp.links.new(nodes["Diffuse BSDF.005"].outputs[0], nodes["Add Shader.008"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[9], nodes["Add Shader.006"].inputs[0]) + new_grp.links.new(nodes["Add Shader.005"].outputs[0], nodes["Add Shader.007"].inputs[0]) + new_grp.links.new(nodes["Add Shader.006"].outputs[0], nodes["Add Shader.007"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[10], nodes["Mix.005"].inputs[2]) + new_grp.links.new(nodes["Mix"].outputs[0], nodes["Mix.005"].inputs[1]) + new_grp.links.new(nodes["Add Shader.008"].outputs[0], nodes["Add Shader.006"].inputs[1]) + new_grp.links.new(nodes["Mix.005"].outputs[0], nodes["Add Shader.008"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[8], nodes["Mix.006"].inputs[2]) + new_grp.links.new(nodes["Mix"].outputs[0], nodes["Mix.006"].inputs[1]) + new_grp.links.new(nodes["Add Shader.009"].outputs[0], nodes["Add Shader.005"].inputs[1]) + new_grp.links.new(nodes["Mix.006"].outputs[0], nodes["Add Shader.009"].inputs[1]) + new_grp.links.new(nodes["Add Shader.007"].outputs[0], nodes["Add Shader.010"].inputs[1]) + new_grp.links.new(nodes["Add Shader.001"].outputs[0], nodes["Add Shader.010"].inputs[0]) + new_grp.links.new(nodes["Transparent BSDF"].outputs[0], nodes["Add Shader.012"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[11], nodes["Add Shader.012"].inputs[0]) + new_grp.links.new(nodes["Add Shader.012"].outputs[0], nodes["Add Shader.011"].inputs[1]) + new_grp.links.new(nodes["Add Shader.011"].outputs[0], nodes["Group Output"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[3], nodes["Math"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[13], nodes["Math"].inputs[1]) + new_grp.links.new(nodes["Math"].outputs[0], nodes["Math.001"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[4], nodes["Math.001"].inputs[1]) + new_grp.links.new(nodes["Math.001"].outputs[0], nodes["Math.002"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[6], nodes["Math.002"].inputs[0]) + new_grp.links.new(nodes["Math.002"].outputs[0], nodes["Mix Shader"].inputs[0]) + new_grp.links.new(nodes["Transparent BSDF.001"].outputs[0], nodes["Mix Shader"].inputs[1]) + new_grp.links.new(nodes["Add Shader.010"].outputs[0], nodes["Mix Shader"].inputs[2]) + new_grp.links.new(nodes["Mix Shader"].outputs[0], nodes["Add Shader.011"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[12], nodes["Transparent BSDF"].inputs[0]) + +def make_retro_shader_mp3_bloom(): + new_grp = bpy.data.node_groups.new("__RetroShaderMP3Bloom", "ShaderNodeTree") + new_grp.use_fake_user = True + input = new_grp.inputs.new("NodeSocketFloatFactor", "DIFFA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "DIFBA") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOL") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOD") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLODB") + input.default_value = 0.5 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "TRAN") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "INCAA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BNIF") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOI") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOIB") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "OPAC") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketInt", "Add INCA") + input.default_value = 0 + input.min_value = 0.000000 + input.max_value = 1.000000 + new_grp.outputs.new("NodeSocketShader", "Shader") + nodes = {} + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.003" + nodes["Math.003"] = node + node.label = "" + node.location = (-131.26889038085938, -228.6888885498047) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math" + nodes["Math"] = node + node.label = "" + node.location = (-501.6487731933594, -144.7719268798828) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.002" + nodes["Math.002"] = node + node.label = "" + node.location = (-328.3370666503906, -209.53160095214844) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("NodeGroupOutput") + node.name = "Group Output" + nodes["Group Output"] = node + node.label = "" + node.location = (1109.7938232421875, -257.2006530761719) + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.001" + nodes["Math.001"] = node + node.label = "" + node.location = (129.59579467773438, -299.0679626464844) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeBsdfDiffuse") + node.name = "Diffuse BSDF.002" + nodes["Diffuse BSDF.002"] = node + node.label = "" + node.location = (122.80331420898438, -150.7427520751953) + node.inputs[0].default_value = (0.800000011920929, 0.800000011920929, 0.800000011920929, 1.0) + node.inputs[1].default_value = 0.0 + node.inputs[2].default_value = (0.0, 0.0, 0.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.002" + nodes["Add Shader.002"] = node + node.label = "" + node.location = (312.7171325683594, -220.0266571044922) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.005" + nodes["Add Shader.005"] = node + node.label = "" + node.location = (-165.06072998046875, -549.3956298828125) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.006" + nodes["Add Shader.006"] = node + node.label = "" + node.location = (20.3157958984375, -545.8302612304688) + node = new_grp.nodes.new("ShaderNodeBsdfTransparent") + node.name = "Transparent BSDF.001" + nodes["Transparent BSDF.001"] = node + node.label = "" + node.location = (205.5854034423828, -558.1273803710938) + node.inputs[0].default_value = (1.0, 1.0, 1.0, 1.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.001" + nodes["Add Shader.001"] = node + node.label = "" + node.location = (399.876708984375, -533.2184448242188) + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.004" + nodes["Math.004"] = node + node.label = "" + node.location = (-354.23876953125, -508.8504943847656) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader" + nodes["Add Shader"] = node + node.label = "" + node.location = (875.3080444335938, -248.47450256347656) + node = new_grp.nodes.new("ShaderNodeBsdfTransparent") + node.name = "Transparent BSDF" + nodes["Transparent BSDF"] = node + node.label = "" + node.location = (502.63671875, -341.6871032714844) + node.inputs[0].default_value = (1.0, 1.0, 1.0, 1.0) + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.006" + nodes["Math.006"] = node + node.label = "" + node.location = (505.8763122558594, -171.7743377685547) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeMixShader") + node.name = "Mix Shader" + nodes["Mix Shader"] = node + node.label = "" + node.location = (682.0885620117188, -169.31057739257812) + node.inputs[0].default_value = 0.5 + node = new_grp.nodes.new("NodeGroupInput") + node.name = "Group Input" + nodes["Group Input"] = node + node.label = "" + node.location = (-669.6587524414062, -193.9534149169922) + new_grp.links.new(nodes["Group Input"].outputs[0], nodes["Math"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[1], nodes["Math"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[3], nodes["Math.002"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[4], nodes["Math.003"].inputs[1]) + new_grp.links.new(nodes["Math.002"].outputs[0], nodes["Math.003"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[2], nodes["Math.002"].inputs[0]) + new_grp.links.new(nodes["Math"].outputs[0], nodes["Math.001"].inputs[0]) + new_grp.links.new(nodes["Diffuse BSDF.002"].outputs[0], nodes["Add Shader.002"].inputs[0]) + new_grp.links.new(nodes["Math.001"].outputs[0], nodes["Add Shader.002"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[10], nodes["Math.006"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[5], nodes["Math.006"].inputs[0]) + new_grp.links.new(nodes["Math.006"].outputs[0], nodes["Mix Shader"].inputs[0]) + new_grp.links.new(nodes["Transparent BSDF"].outputs[0], nodes["Mix Shader"].inputs[1]) + new_grp.links.new(nodes["Transparent BSDF.001"].outputs[0], nodes["Add Shader.001"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[6], nodes["Math.004"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[7], nodes["Math.004"].inputs[1]) + new_grp.links.new(nodes["Math.003"].outputs[0], nodes["Math.001"].inputs[1]) + new_grp.links.new(nodes["Math.003"].outputs[0], nodes["Diffuse BSDF.002"].inputs[0]) + new_grp.links.new(nodes["Math.004"].outputs[0], nodes["Add Shader.005"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[8], nodes["Add Shader.005"].inputs[1]) + new_grp.links.new(nodes["Add Shader.005"].outputs[0], nodes["Add Shader.006"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[9], nodes["Add Shader.006"].inputs[1]) + new_grp.links.new(nodes["Add Shader.006"].outputs[0], nodes["Add Shader.001"].inputs[1]) + new_grp.links.new(nodes["Add Shader"].outputs[0], nodes["Group Output"].inputs[0]) + new_grp.links.new(nodes["Mix Shader"].outputs[0], nodes["Add Shader"].inputs[0]) + new_grp.links.new(nodes["Add Shader.002"].outputs[0], nodes["Mix Shader"].inputs[2]) + new_grp.links.new(nodes["Add Shader.001"].outputs[0], nodes["Add Shader"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[11], nodes["Transparent BSDF.001"].inputs[0]) + +def make_retro_shader_mp3(): + new_grp = bpy.data.node_groups.new("RetroShaderMP3", "ShaderNodeTree") + new_grp.use_fake_user = True + input = new_grp.inputs.new("NodeSocketColor", "DIFFC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "DIFFA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "DIFBC") + input.default_value = (1.0, 1.0, 1.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "DIFBA") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOL") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOD") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLODB") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "CLR") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "CLRA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "TRAN") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "RFLD") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "RFLDA") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "RFLV") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "LRLD") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "LURDC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "LURDA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "INCAC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "INCAA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketInt", "Add INCA") + input.default_value = 0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BNIF") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOI") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOIB") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "OPAC") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "XRAYC") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "XRAYA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "XRBR") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + nodes = {} + node = new_grp.nodes.new("ShaderNodeMixShader") + node.name = "Mix Shader" + nodes["Mix Shader"] = node + node.label = "" + node.location = (-118.33348846435547, -291.9857482910156) + node.inputs[0].default_value = 0.0 + node = new_grp.nodes.new("ShaderNodeOutputMaterial") + node.name = "Material Output" + nodes["Material Output"] = node + node.label = "" + node.location = (81.25957489013672, -265.6065368652344) + node.inputs[2].default_value = (0.0, 0.0, 0.0) + node = new_grp.nodes.new("ShaderNodeGroup") + node.name = "Group.001" + nodes["Group.001"] = node + node.label = "" + node.location = (-358.6896057128906, -60.17391586303711) + node.node_tree = bpy.data.node_groups["__RetroShaderMP3Color"] + node.inputs[0].default_value = (1.0, 1.0, 1.0, 1.0) + node.inputs[1].default_value = (1.0, 1.0, 1.0, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[3].default_value = 0.5 + node.inputs[4].default_value = 0.5 + node.inputs[5].default_value = (0.0, 0.0, 0.0, 1.0) + node.inputs[6].default_value = 0.5 + node.inputs[7].default_value = (0.0, 0.0, 0.0, 1.0) + node.inputs[8].default_value = (0.0, 0.0, 0.0, 1.0) + node.inputs[9].default_value = (0.0, 0.0, 0.0, 1.0) + node.inputs[10].default_value = 0.0 + node.inputs[11].default_value = (0.0, 0.0, 0.0, 1.0) + node.inputs[12].default_value = 0 + node.inputs[13].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeGroup") + node.name = "Group" + nodes["Group"] = node + node.label = "" + node.location = (-356.9021301269531, -446.9474182128906) + node.node_tree = bpy.data.node_groups["__RetroShaderMP3Bloom"] + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = 1.0 + node.inputs[2].default_value = 0.0 + node.inputs[3].default_value = 0.0 + node.inputs[4].default_value = 0.5 + node.inputs[5].default_value = 0.5 + node.inputs[6].default_value = 0.0 + node.inputs[7].default_value = 0.0 + node.inputs[8].default_value = 0.0 + node.inputs[9].default_value = 0.0 + node.inputs[10].default_value = 0.5 + node.inputs[11].default_value = 0 + node = new_grp.nodes.new("NodeGroupInput") + node.name = "Group Input" + nodes["Group Input"] = node + node.label = "" + node.location = (-669.6587524414062, -193.9534149169922) + new_grp.links.new(nodes["Group Input"].outputs[0], nodes["Group.001"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[1], nodes["Group"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[3], nodes["Group"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[4], nodes["Group"].inputs[2]) + new_grp.links.new(nodes["Group Input"].outputs[5], nodes["Group"].inputs[3]) + new_grp.links.new(nodes["Group Input"].outputs[6], nodes["Group"].inputs[4]) + new_grp.links.new(nodes["Group Input"].outputs[17], nodes["Group"].inputs[6]) + new_grp.links.new(nodes["Group Input"].outputs[19], nodes["Group"].inputs[7]) + new_grp.links.new(nodes["Group Input"].outputs[20], nodes["Group"].inputs[8]) + new_grp.links.new(nodes["Group Input"].outputs[2], nodes["Group.001"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[7], nodes["Group.001"].inputs[2]) + new_grp.links.new(nodes["Group Input"].outputs[10], nodes["Group.001"].inputs[5]) + new_grp.links.new(nodes["Group Input"].outputs[12], nodes["Group.001"].inputs[7]) + new_grp.links.new(nodes["Group Input"].outputs[13], nodes["Group.001"].inputs[8]) + new_grp.links.new(nodes["Group Input"].outputs[14], nodes["Group.001"].inputs[9]) + new_grp.links.new(nodes["Group Input"].outputs[15], nodes["Group.001"].inputs[10]) + new_grp.links.new(nodes["Group Input"].outputs[16], nodes["Group.001"].inputs[11]) + new_grp.links.new(nodes["Group.001"].outputs[0], nodes["Mix Shader"].inputs[1]) + new_grp.links.new(nodes["Group"].outputs[0], nodes["Mix Shader"].inputs[2]) + new_grp.links.new(nodes["Mix Shader"].outputs[0], nodes["Material Output"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[21], nodes["Group"].inputs[9]) + new_grp.links.new(nodes["Group Input"].outputs[8], nodes["Group.001"].inputs[3]) + new_grp.links.new(nodes["Group Input"].outputs[9], nodes["Group.001"].inputs[4]) + new_grp.links.new(nodes["Group Input"].outputs[11], nodes["Group.001"].inputs[6]) + new_grp.links.new(nodes["Group Input"].outputs[22], nodes["Group.001"].inputs[13]) + new_grp.links.new(nodes["Group Input"].outputs[9], nodes["Group"].inputs[5]) + new_grp.links.new(nodes["Group Input"].outputs[22], nodes["Group"].inputs[10]) + new_grp.links.new(nodes["Group Input"].outputs[18], nodes["Group.001"].inputs[12]) + new_grp.links.new(nodes["Group Input"].outputs[18], nodes["Group"].inputs[11]) + ROOT_SHADER_GROUPS = ( make_retro_shader, make_retro_dynamic_shader, make_retro_dynamic_alpha_shader, - make_retro_dynamic_character_shader + make_retro_dynamic_character_shader, + make_retro_shader_mp3_color, + make_retro_shader_mp3_bloom, + make_retro_shader_mp3 ) # UV animation nodes: @@ -1175,414 +1846,6 @@ UV_ANIMATION_GROUPS = ( make_uva8 ) -# MP3 / DKCR Material Passes: -# https://wiki.axiodl.com/w/Materials_(Metroid_Prime_3) - -# Lightmap -def make_pass_diff(): - new_grp = bpy.data.node_groups.new('RetroPassDIFF', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply1 - mult1 = new_grp.nodes.new('ShaderNodeMixRGB') - mult1.blend_type = 'ADD' - mult1.inputs[0].default_value = 1.0 - mult1.location = (-600, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], mult1.inputs[1]) - new_grp.links.new(grp_in.outputs[2], mult1.inputs[2]) - new_grp.links.new(mult1.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - - -# Rim Lighting Map -def make_pass_riml(): - new_grp = bpy.data.node_groups.new('RetroPassRIML', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Bloom Lightmap -def make_pass_blol(): - new_grp = bpy.data.node_groups.new('RetroPassBLOL', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Bloom Diffuse Map -def make_pass_blod(): - new_grp = bpy.data.node_groups.new('RetroPassBLOD', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Diffuse Map -def make_pass_clr(): - new_grp = bpy.data.node_groups.new('RetroPassCLR', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply - mult1 = new_grp.nodes.new('ShaderNodeMixRGB') - mult1.blend_type = 'MULTIPLY' - mult1.inputs[0].default_value = 1.0 - grp_in.location = (-400, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], mult1.inputs[1]) - new_grp.links.new(grp_in.outputs[2], mult1.inputs[2]) - new_grp.links.new(mult1.outputs[0], grp_out.inputs[0]) - grp_out.inputs[1].default_value = 1.0 - -# Opacity Map -def make_pass_tran(): - new_grp = bpy.data.node_groups.new('RetroPassTRAN', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply - mul1 = new_grp.nodes.new('ShaderNodeMath') - mul1.operation = 'MULTIPLY' - mul1.inputs[0].default_value = 1.0 - mul1.location = (-400, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], mul1.inputs[0]) - new_grp.links.new(grp_in.outputs[2], mul1.inputs[1]) - new_grp.links.new(mul1.outputs[0], grp_out.inputs[1]) - -# Opacity Map Inverted -def make_pass_tran_inv(): - new_grp = bpy.data.node_groups.new('RetroPassTRANInv', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply - mul1 = new_grp.nodes.new('ShaderNodeMath') - mul1.operation = 'MULTIPLY' - mul1.inputs[0].default_value = 1.0 - mul1.location = (-400, 0) - - # Invert - inv1 = new_grp.nodes.new('ShaderNodeInvert') - inv1.inputs[0].default_value = 1.0 - inv1.location = (-600, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], mul1.inputs[1]) - new_grp.links.new(grp_in.outputs[2], inv1.inputs[1]) - new_grp.links.new(inv1.outputs[0], mul1.inputs[0]) - new_grp.links.new(mul1.outputs[0], grp_out.inputs[1]) - -# Incandescence Map -def make_pass_inca(): - new_grp = bpy.data.node_groups.new('RetroPassINCA', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply - add1 = new_grp.nodes.new('ShaderNodeMixRGB') - add1.blend_type = 'ADD' - add1.inputs[0].default_value = 1.0 - grp_in.location = (-400, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], add1.inputs[1]) - new_grp.links.new(grp_in.outputs[2], add1.inputs[2]) - new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - grp_out.inputs[1].default_value = 1.0 - -# Reflection Map -def make_pass_rfld(): - new_grp = bpy.data.node_groups.new('RetroPassRFLD', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Mask Color') - new_grp.inputs.new('NodeSocketFloat', 'Mask Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply - mult1 = new_grp.nodes.new('ShaderNodeMixRGB') - mult1.location = (-600, 0) - mult1.blend_type = 'MULTIPLY' - mult1.inputs[0].default_value = 1.0 - - # Add - add1 = new_grp.nodes.new('ShaderNodeMixRGB') - add1.location = (-400, 0) - add1.blend_type = 'ADD' - add1.inputs[0].default_value = 1.0 - - # Links - new_grp.links.new(grp_in.outputs[0], add1.inputs[1]) - new_grp.links.new(grp_in.outputs[2], mult1.inputs[1]) - new_grp.links.new(grp_in.outputs[4], mult1.inputs[2]) - new_grp.links.new(mult1.outputs[0], add1.inputs[2]) - new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Unk1 -def make_pass_lrld(): - new_grp = bpy.data.node_groups.new('RetroPassLRLD', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Unk2 -def make_pass_lurd(): - new_grp = bpy.data.node_groups.new('RetroPassLURD', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Bloom Incandescence Map -def make_pass_bloi(): - new_grp = bpy.data.node_groups.new('RetroPassBLOI', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# X-ray Reflection Map -def make_pass_xray(): - new_grp = bpy.data.node_groups.new('RetroPassXRAY', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Unused -def make_pass_toon(): - new_grp = bpy.data.node_groups.new('RetroPassTOON', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -MP3_PASS_GROUPS = ( - make_pass_diff, - make_pass_riml, - make_pass_blol, - make_pass_blod, - make_pass_clr, - make_pass_tran, - make_pass_tran_inv, - make_pass_inca, - make_pass_rfld, - make_pass_lrld, - make_pass_lurd, - make_pass_bloi, - make_pass_xray, - make_pass_toon -) - def make_master_shader_library(): make_additive_output() make_blend_opaque_output() @@ -1590,6 +1853,4 @@ def make_master_shader_library(): shad() for uva in UV_ANIMATION_GROUPS: uva() - for aPass in MP3_PASS_GROUPS: - aPass() diff --git a/DataSpec/DNACommon/ANCS.cpp b/DataSpec/DNACommon/ANCS.cpp index cbe208d8d..03f89f3a9 100644 --- a/DataSpec/DNACommon/ANCS.cpp +++ b/DataSpec/DNACommon/ANCS.cpp @@ -15,10 +15,11 @@ namespace DataSpec::DNAANCS { template -bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath, +bool ReadANCSToBlender(hecl::blender::Token& btok, 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 */ + auto& conn = btok.getBlenderConnection(); + /* Extract character CMDL/CSKR/CINF first */ std::vector> chResInfo; ancs.getCharacterResInfo(chResInfo); for (const auto& info : chResInfo) { @@ -49,11 +50,19 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con conn.saveBlend(); } } + if (const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(info.cinf, &node, true, false)) { + hecl::ProjectPath cinfPath = pakRouter.getWorking(cinfE); + if (cinfPath.getPathType() == hecl::ProjectPath::Type::None) { + PAKEntryReadStream rs = cinfE->beginReadStream(*node); + ANCSDNA::CINFType::Extract(dataspec, rs, cinfPath, pakRouter, *cinfE, false, btok, fileChanged); + } + } } - /* Extract attachment CMDL/CSKRs first */ + /* Extract attachment CMDL/CSKR/CINFs first */ auto attRange = pakRouter.lookupCharacterAttachmentRigs(entry.id); for (auto it = attRange.first; it != attRange.second; ++it) { + auto cinfid = it->second.first.cinf; auto cmdlid = it->second.first.cmdl; const nod::Node* node; @@ -61,8 +70,9 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); if (force || cmdlPath.isNone()) { cmdlPath.makeDirChain(false); - if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh)) + if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh)) { return false; + } std::string bestName = pakRouter.getBestEntryName(*cmdlE); hecl::SystemStringConv bestNameView(bestName); @@ -84,6 +94,15 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con conn.saveBlend(); } } + if (cinfid.isValid()) { + if (const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(cinfid, &node, true, false)) { + hecl::ProjectPath cinfPath = pakRouter.getWorking(cinfE); + if (cinfPath.getPathType() == hecl::ProjectPath::Type::None) { + PAKEntryReadStream rs = cinfE->beginReadStream(*node); + ANCSDNA::CINFType::Extract(dataspec, rs, cinfPath, pakRouter, *cinfE, false, btok, fileChanged); + } + } + } } std::string bestName = pakRouter.getBestEntryName(entry); @@ -99,7 +118,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con { hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format(fmt( + os.format(FMT_STRING( "import bpy\n" "from mathutils import Vector\n" "bpy.context.scene.name = '{}'\n" @@ -116,7 +135,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con std::unordered_set cinfsDone; for (const auto& info : chResInfo) { /* Provide data to add-on */ - os.format(fmt( + os.format(FMT_STRING( "actor_subtype = actor_data.subtypes.add()\n" "actor_subtype.name = '{}'\n\n"), info.name); @@ -125,7 +144,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con if (cinfsDone.find(info.cinf) == cinfsDone.end()) { if (const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(info.cinf, nullptr, true, false)) { hecl::ProjectPath cinfPath = pakRouter.getWorking(cinfE); - os.linkArmature(cinfPath.getAbsolutePathUTF8(), fmt::format(fmt("CINF_{}"), info.cinf)); + os.linkArmature(cinfPath.getAbsolutePathUTF8(), fmt::format(FMT_STRING("CINF_{}"), info.cinf)); os << "if obj.name not in bpy.context.scene.objects:\n" " bpy.context.scene.collection.objects.link(obj)\n"; } @@ -135,7 +154,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con } cinfsDone.insert(info.cinf); } - os.format(fmt("arm_obj = bpy.data.objects['CINF_{}']\n"), info.cinf); + os.format(FMT_STRING("arm_obj = bpy.data.objects['CINF_{}']\n"), info.cinf); os << "actor_subtype.linked_armature = arm_obj.name\n"; /* Link CMDL */ @@ -154,7 +173,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con /* Link overlays */ for (const auto& overlay : info.overlays) { os << "overlay = actor_subtype.overlays.add()\n"; - os.format(fmt("overlay.name = '{}'\n"), overlay.first); + os.format(FMT_STRING("overlay.name = '{}'\n"), overlay.first); /* Link CMDL */ if (const typename PAKRouter::EntryType* cmdlE = @@ -175,7 +194,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con /* Link attachments */ for (auto it = attRange.first; it != attRange.second; ++it) { os << "attachment = actor_data.attachments.add()\n"; - os.format(fmt("attachment.name = '{}'\n"), it->second.second); + os.format(FMT_STRING("attachment.name = '{}'\n"), it->second.second); auto cinfid = it->second.first.cinf; auto cmdlid = it->second.first.cmdl; @@ -185,7 +204,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con if (cinfsDone.find(cinfid) == cinfsDone.end()) { if (const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(cinfid, nullptr, true, false)) { hecl::ProjectPath cinfPath = pakRouter.getWorking(cinfE); - os.linkArmature(cinfPath.getAbsolutePathUTF8(), fmt::format(fmt("CINF_{}"), cinfid)); + os.linkArmature(cinfPath.getAbsolutePathUTF8(), fmt::format(FMT_STRING("CINF_{}"), cinfid)); os << "if obj.name not in bpy.context.scene.objects:\n" " bpy.context.scene.collection.objects.link(obj)\n"; } @@ -195,7 +214,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con } cinfsDone.insert(cinfid); } - os.format(fmt("arm_obj = bpy.data.objects['CINF_{}']\n"), cinfid); + os.format(FMT_STRING("arm_obj = bpy.data.objects['CINF_{}']\n"), cinfid); os << "attachment.linked_armature = arm_obj.name\n"; } @@ -230,7 +249,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con for (const auto& id : animResInfo) { typename ANCSDNA::ANIMType anim; if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true)) { - os.format(fmt( + os.format(FMT_STRING( "act = bpy.data.actions.new('{}')\n" "act.use_fake_user = True\n" "act.anim_id = '{}'\n"), @@ -238,7 +257,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con anim.sendANIMToBlender(os, inverter, id.second.additive); } - os.format(fmt( + os.format(FMT_STRING( "actor_action = actor_data.actions.add()\n" "actor_action.name = '{}'\n"), id.second.name); @@ -253,17 +272,17 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con template bool ReadANCSToBlender, DNAMP1::ANCS, DNAMP1::MaterialSet, DNACMDL::SurfaceHeader_1, 2>( - hecl::blender::Connection& conn, const DNAMP1::ANCS& ancs, const hecl::ProjectPath& outPath, + hecl::blender::Token& btok, 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, + hecl::blender::Token& btok, 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, + hecl::blender::Token& btok, const DNAMP3::CHAR& ancs, const hecl::ProjectPath& outPath, PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec, std::function fileChanged, bool force); diff --git a/DataSpec/DNACommon/ANCS.hpp b/DataSpec/DNACommon/ANCS.hpp index 6064fa6bd..2cf7ef811 100644 --- a/DataSpec/DNACommon/ANCS.hpp +++ b/DataSpec/DNACommon/ANCS.hpp @@ -41,7 +41,7 @@ struct AnimationResInfo { }; template -bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath, +bool ReadANCSToBlender(hecl::blender::Token& btok, const ANCSDNA& ancs, const hecl::ProjectPath& outPath, PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec, std::function fileChanged, bool force = false); diff --git a/DataSpec/DNACommon/ANIM.cpp b/DataSpec/DNACommon/ANIM.cpp index 895de4afe..42079d125 100644 --- a/DataSpec/DNACommon/ANIM.cpp +++ b/DataSpec/DNACommon/ANIM.cpp @@ -175,7 +175,7 @@ std::vector> BitstreamReader::read(const atUint8* data, size_ for (size_t f = 0; f < keyFrameCount; ++f) { #if DUMP_KEYS - fmt::print(stderr, fmt("\nFRAME {} {} {}\n"), f, (m_bitCur / 32) * 4, m_bitCur % 32); + fmt::print(stderr, FMT_STRING("\nFRAME {} {} {}\n"), f, (m_bitCur / 32) * 4, m_bitCur % 32); int lastId = -1; #endif auto kit = chanKeys.begin(); @@ -197,7 +197,7 @@ std::vector> BitstreamReader::read(const atUint8* data, size_ QuantizedRot qr = {{p[0], p[1], p[2]}, wBit}; kit->emplace_back(DequantizeRotation(qr, rotDiv)); #if DUMP_KEYS - fmt::print(stderr, fmt("{} R: {} {} {} {}\t"), chan.id, wBit, p[0], p[1], p[2]); + fmt::print(stderr, FMT_STRING("{} R: {} {} {} {}\t"), chan.id, wBit, p[0], p[1], p[2]); #endif break; } @@ -210,7 +210,7 @@ std::vector> BitstreamReader::read(const atUint8* data, size_ p[2] += val3; kit->push_back({p[0] * transMult, p[1] * transMult, p[2] * transMult}); #if DUMP_KEYS - fmt::print(stderr, fmt("{} T: {} {} {}\t"), chan.id, p[0], p[1], p[2]); + fmt::print(stderr, FMT_STRING("{} T: {} {} {}\t"), chan.id, p[0], p[1], p[2]); #endif break; } @@ -220,7 +220,7 @@ std::vector> BitstreamReader::read(const atUint8* data, size_ p[2] += dequantize(data, chan.q[2]); kit->push_back({p[0] * scaleMult, p[1] * scaleMult, p[2] * scaleMult}); #if DUMP_KEYS - fmt::print(stderr, fmt("{} S: {} {} {}\t"), chan.id, p[0], p[1], p[2]); + fmt::print(stderr, FMT_STRING("{} S: {} {} {}\t"), chan.id, p[0], p[1], p[2]); #endif break; } diff --git a/DataSpec/DNACommon/AROTBuilder.cpp b/DataSpec/DNACommon/AROTBuilder.cpp index fbe48dd41..30a2ede2d 100644 --- a/DataSpec/DNACommon/AROTBuilder.cpp +++ b/DataSpec/DNACommon/AROTBuilder.cpp @@ -4,7 +4,7 @@ #include #include "hecl/Blender/Connection.hpp" -#include "../DNAMP1/PATH.hpp" +#include "PATH.hpp" namespace DataSpec { logvisor::Module Log("AROTBuilder"); @@ -140,7 +140,7 @@ void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPo sz += 1; poolIdx = bmpPool.addIndices(childIndices); if (poolIdx > 65535) - Log.report(logvisor::Fatal, fmt("AROT bitmap exceeds 16-bit node addressing; area too complex")); + Log.report(logvisor::Fatal, FMT_STRING("AROT bitmap exceeds 16-bit node addressing; area too complex")); uint32_t childCount = AROTChildCounts[compSubdivs]; nodeOff = curOff; @@ -180,7 +180,7 @@ void AROTBuilder::Node::writeNodes(athena::io::MemoryWriter& w, int nodeIdx) { if (childNodes.size()) { int curIdx = nodeIdx + 1; if (curIdx > 65535) - Log.report(logvisor::Fatal, fmt("AROT node exceeds 16-bit node addressing; area too complex")); + Log.report(logvisor::Fatal, FMT_STRING("AROT node exceeds 16-bit node addressing; area too complex")); std::array childIndices; @@ -278,10 +278,10 @@ void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& look } } -void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB) { +template +void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB) { if (childNodes.empty()) { - path.octree.emplace_back(); - DNAMP1::PATH::OctreeNode& n = path.octree.back(); + auto& n = path.octree.emplace_back(); n.isLeaf = 1; n.aabb[0] = curAABB.min; n.aabb[1] = curAABB.max; @@ -299,8 +299,7 @@ void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAAB children[i] = path.octree.size() - 1; } - path.octree.emplace_back(); - DNAMP1::PATH::OctreeNode& n = path.octree.back(); + auto& n = path.octree.emplace_back(); n.isLeaf = 0; n.aabb[0] = curAABB.min; n.aabb[1] = curAABB.max; @@ -311,6 +310,10 @@ void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAAB } } +template void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); +template void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); +template void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); + void AROTBuilder::build(std::vector>& secs, const zeus::CAABox& fullAabb, const std::vector& meshAabbs, const std::vector& meshes) { /* Recursively split */ @@ -406,15 +409,14 @@ std::pair, uint32_t> AROTBuilder::buildCol(const ColM return {std::move(ret), totalSize}; } -void AROTBuilder::buildPath(DNAMP1::PATH& path) { +template +void AROTBuilder::buildPath(DNAPATH::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()); - } + for (const auto& r : path.regions) + fullAABB.accumulateBounds(regionBoxes.emplace_back(r.aabb[0], r.aabb[1])); /* Recursively split */ BspNodeType dontCare; @@ -431,4 +433,8 @@ void AROTBuilder::buildPath(DNAMP1::PATH& path) { rootNode.pathWrite(path, fullAABB); } +template void AROTBuilder::buildPath(DNAPATH::PATH& path); +template void AROTBuilder::buildPath(DNAPATH::PATH& path); +template void AROTBuilder::buildPath(DNAPATH::PATH& path); + } // namespace DataSpec diff --git a/DataSpec/DNACommon/AROTBuilder.hpp b/DataSpec/DNACommon/AROTBuilder.hpp index 1ecabbce7..a10a00128 100644 --- a/DataSpec/DNACommon/AROTBuilder.hpp +++ b/DataSpec/DNACommon/AROTBuilder.hpp @@ -7,10 +7,12 @@ #include namespace DataSpec { -namespace DNAMP1 { +namespace DNAPATH { +template struct PATH; } + struct AROTBuilder { using ColMesh = hecl::blender::ColMesh; @@ -42,13 +44,15 @@ struct AROTBuilder { 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); + template + void pathWrite(DNAPATH::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); + template + void buildPath(DNAPATH::PATH& path); }; } // namespace DataSpec diff --git a/DataSpec/DNACommon/ATBL.cpp b/DataSpec/DNACommon/ATBL.cpp index 10e5f3ead..38757305e 100644 --- a/DataSpec/DNACommon/ATBL.cpp +++ b/DataSpec/DNACommon/ATBL.cpp @@ -24,7 +24,7 @@ bool ATBL::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { uint16_t idx = rs.readUint16Big(); if (idx == 0xffff) continue; - w.writeUint16(fmt::format(fmt("0x{:04X}"), i), idx); + w.writeUint16(fmt::format(FMT_STRING("0x{:04X}"), i), idx); } athena::io::FileWriter fw(outPath.getAbsolutePath()); diff --git a/DataSpec/DNACommon/BabeDead.cpp b/DataSpec/DNACommon/BabeDead.cpp index 2b4d8eed9..51a43ea19 100644 --- a/DataSpec/DNACommon/BabeDead.cpp +++ b/DataSpec/DNACommon/BabeDead.cpp @@ -18,13 +18,13 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi switch (light.lightType) { case BabeDeadLight::LightType::LocalAmbient: case BabeDeadLight::LightType::LocalAmbient2: - os.format(fmt( + os.format(FMT_STRING( "bg_node.inputs[0].default_value = ({},{},{},1.0)\n" "bg_node.inputs[1].default_value = {}\n"), light.color.simd[0], light.color.simd[1], light.color.simd[2], light.q / 8.f); return; case BabeDeadLight::LightType::Directional: - os.format(fmt( + os.format(FMT_STRING( "lamp = bpy.data.lights.new('LAMP_{:01d}_{:03d}', 'SUN')\n" "lamp.color = ({},{},{})\n" "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" @@ -36,7 +36,7 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi light.direction.simd[1], light.direction.simd[2], light.castShadows ? "True" : "False"); return; case BabeDeadLight::LightType::Custom: - os.format(fmt( + os.format(FMT_STRING( "lamp = bpy.data.lights.new('LAMP_{:01d}_{:03d}', 'POINT')\n" "lamp.color = ({},{},{})\n" "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" @@ -48,7 +48,7 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi break; case BabeDeadLight::LightType::Spot: case BabeDeadLight::LightType::Spot2: - os.format(fmt( + os.format(FMT_STRING( "lamp = bpy.data.lights.new('LAMP_{:01d}_{:03d}', 'SPOT')\n" "lamp.color = ({},{},{})\n" "lamp.spot_size = {:.6g}\n" @@ -66,7 +66,7 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi return; } - os.format(fmt( + os.format(FMT_STRING( "lamp.retro_layer = {}\n" "lamp.retro_origtype = {}\n" "lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n" @@ -90,17 +90,17 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi 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(fmt("lamp.constant_coefficient = 2.0 / {}\n"), light.q); + os.format(FMT_STRING("lamp.constant_coefficient = 2.0 / {}\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(fmt("lamp.linear_coefficient = 250 / {}\n"), light.q); + os.format(FMT_STRING("lamp.linear_coefficient = 250 / {}\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(fmt("lamp.quadratic_coefficient = 25000 / {}\n"), light.q); + os.format(FMT_STRING("lamp.quadratic_coefficient = 25000 / {}\n"), light.q); break; default: break; diff --git a/DataSpec/DNACommon/CMDL.cpp b/DataSpec/DNACommon/CMDL.cpp index 394d437fe..bbb099792 100644 --- a/DataSpec/DNACommon/CMDL.cpp +++ b/DataSpec/DNACommon/CMDL.cpp @@ -84,7 +84,7 @@ void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os, const Material } hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex); hecl::SystemUTF8Conv resPathView(resPath); - os.format(fmt( + os.format(FMT_STRING( "if '{}' in bpy.data.images:\n" " image = bpy.data.images['{}']\n" "else:\n" @@ -148,7 +148,7 @@ public: for (const std::pair>>& ev : m_extraVerts) { for (const std::pair& se : ev.second) { if (se.second == nextVert) { - os.format(fmt( + os.format(FMT_STRING( "bm.verts.ensure_lookup_table()\n" "orig_vert = bm.verts[{}]\n" "vert = bm.verts.new(orig_vert.co)\n"), @@ -466,7 +466,7 @@ void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectP "\n"; /* Link master shader library */ - os.format(fmt( + os.format(FMT_STRING( "# Master shader library\n" "with bpy.data.libraries.load('{}', link=True, relative=True) as (data_from, data_to):\n" " data_to.node_groups = data_from.node_groups\n" @@ -485,13 +485,13 @@ void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int "obj = bpy.data.objects.new(mesh.name, mesh)\n" "obj.show_transparent = True\n" "coll.objects.link(obj)\n"; - os.format(fmt("mesh.hecl_material_count = {}\n"), matSetCount); + os.format(FMT_STRING("mesh.hecl_material_count = {}\n"), matSetCount); } else { - os.format(fmt("mesh = bpy.data.meshes.new(bpy.context.scene.name + '_{:03d}')\n"), meshIdx); + os.format(FMT_STRING("mesh = bpy.data.meshes.new(bpy.context.scene.name + '_{:03d}')\n"), meshIdx); os << "obj = bpy.data.objects.new(mesh.name, mesh)\n" "obj.show_transparent = True\n" "coll.objects.link(obj)\n"; - os.format(fmt("mesh.hecl_material_count = {}\n"), matSetCount); + os.format(FMT_STRING("mesh.hecl_material_count = {}\n"), matSetCount); } os << "mesh.use_auto_smooth = True\n" @@ -521,7 +521,10 @@ void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int " 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" + " try:\n" + " if bm.faces.get(merge_verts) is not None:\n" + " continue\n" + " except:\n" " continue\n" " merge_face = bm.faces.new(merge_verts)\n" " for i in range(len(face.loops)):\n" @@ -598,7 +601,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I DLReader::DLPrimVert maxIdxs; std::vector skinIndices; DLReader::ExtraVertTracker extraTracker; - for (size_t s = 0; s < lastDlSec; ++s) { + for (atUint32 s = 0; s < lastDlSec; ++s) { atUint64 secStart = reader.position(); if (s < matSecCount) { if (!s) { @@ -680,7 +683,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I unsigned createdUVLayers = 0; unsigned surfIdx = 0; - for (size_t s = 0; s < lastDlSec; ++s) { + for (atUint32 s = 0; s < lastDlSec; ++s) { atUint64 secStart = reader.position(); if (s < matSecCount) { MaterialSet matSet; @@ -695,10 +698,10 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I atUint32 vertCount = maxIdxs.pos + 1; std::vector positions; positions.reserve(vertCount); - for (size_t i = 0; i <= maxIdxs.pos; ++i) { + for (atUint16 i = 0; i <= maxIdxs.pos; ++i) { positions.push_back(reader.readVec3fBig()); const atVec3f& pos = positions.back(); - os.format(fmt("vert = bm.verts.new(({},{},{}))\n"), pos.simd[0], pos.simd[1], pos.simd[2]); + os.format(FMT_STRING("vert = bm.verts.new(({},{},{}))\n"), pos.simd[0], pos.simd[1], pos.simd[2]); if (rp.first.second) { if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) rp.first.second->weightVertex(os, *rp.second.second, skinIndices[i]); @@ -708,10 +711,10 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I } if (rp.first.second && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) vertCount += extraTracker.sendAdditionalVertsToBlender(os, rp, 0); - os.format(fmt("two_face_vert = {}\n"), vertCount); - for (size_t i = 0; i <= maxIdxs.pos; ++i) { + os.format(FMT_STRING("two_face_vert = {}\n"), vertCount); + for (atUint16 i = 0; i <= maxIdxs.pos; ++i) { const atVec3f& pos = positions[i]; - os.format(fmt("vert = bm.verts.new(({},{},{}))\n"), pos.simd[0], pos.simd[1], pos.simd[2]); + os.format(FMT_STRING("vert = bm.verts.new(({},{},{}))\n"), pos.simd[0], pos.simd[1], pos.simd[2]); if (rp.first.second) { if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) rp.first.second->weightVertex(os, *rp.second.second, skinIndices[i]); @@ -727,18 +730,18 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I /* Normals */ os << "norm_list = []\n"; if (shortNormals) { - size_t normCount = secSizes[s] / 6; - for (size_t i = 0; i < normCount; ++i) { + atUint32 normCount = secSizes[s] / 6; + for (atUint32 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(fmt("norm_list.append(({},{},{}))\n"), x, y, z); + os.format(FMT_STRING("norm_list.append(({},{},{}))\n"), x, y, z); } } else { - size_t normCount = secSizes[s] / 12; - for (size_t i = 0; i < normCount; ++i) { + atUint32 normCount = secSizes[s] / 12; + for (atUint32 i = 0; i < normCount; ++i) { const atVec3f norm = reader.readVec3fBig(); - os.format(fmt("norm_list.append(({},{},{}))\n"), norm.simd[0], norm.simd[1], norm.simd[2]); + os.format(FMT_STRING("norm_list.append(({},{},{}))\n"), norm.simd[0], norm.simd[1], norm.simd[2]); } } break; @@ -750,10 +753,10 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I case 3: { /* Float UVs */ os << "uv_list = []\n"; - size_t uvCount = secSizes[s] / 8; - for (size_t i = 0; i < uvCount; ++i) { + atUint32 uvCount = secSizes[s] / 8; + for (atUint32 i = 0; i < uvCount; ++i) { const atVec2f uv = reader.readVec2fBig(); - os.format(fmt("uv_list.append(({},{}))\n"), uv.simd[0], uv.simd[1]); + os.format(FMT_STRING("uv_list.append(({},{}))\n"), uv.simd[0], uv.simd[1]); } break; } @@ -765,11 +768,11 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I /* Short UVs */ os << "suv_list = []\n"; if (shortUVs) { - size_t uvCount = secSizes[s] / 4; - for (size_t i = 0; i < uvCount; ++i) { + atUint32 uvCount = secSizes[s] / 4; + for (atUint32 i = 0; i < uvCount; ++i) { float x = reader.readInt16Big() / 32768.0f; float y = reader.readInt16Big() / 32768.0f; - os.format(fmt("suv_list.append(({},{}))\n"), x, y); + os.format(FMT_STRING("suv_list.append(({},{}))\n"), x, y); } break; } @@ -796,10 +799,10 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I if (SurfaceHeader::UseMatrixSkinning() && rp.first.second) bankIn = rp.first.second->getMatrixBank(sHead.skinMatrixBankIdx()); - os.format(fmt("materials[{}].pass_index = {}\n"), sHead.matIdx, surfIdx++); + os.format(FMT_STRING("materials[{}].pass_index = {}\n"), sHead.matIdx, surfIdx++); if (matUVCount > createdUVLayers) { for (unsigned l = createdUVLayers; l < matUVCount; ++l) - os.format(fmt("bm.loops.layers.uv.new('UV_{}')\n"), l); + os.format(FMT_STRING("bm.loops.layers.uv.new('UV_{}')\n"), l); createdUVLayers = matUVCount; } @@ -821,7 +824,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I atUint8 flip = 0; for (int v = 0; v < vertCount - 2; ++v) { if (flip) { - os.format(fmt( + os.format(FMT_STRING( "last_face, last_mesh = add_triangle(bm, bm.verts, ({},{},{}), norm_list, ({},{},{}), {}, od_list, " "two_face_vert)\n"), primVerts[c % 3].pos, primVerts[(c + 2) % 3].pos, primVerts[(c + 1) % 3].pos, primVerts[c % 3].norm, @@ -830,7 +833,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I os << "if last_face is not None:\n"; for (unsigned j = 0; j < matUVCount; ++j) { if (j == 0 && matShortUVs) - os.format(fmt( + os.format(FMT_STRING( " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[{}], suv_list[{}], " "suv_list[{}])\n" " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " @@ -842,7 +845,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I 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(fmt( + os.format(FMT_STRING( " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " "uv_list[{}]\n" " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " @@ -854,7 +857,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I } } } else { - os.format(fmt( + os.format(FMT_STRING( "last_face, last_mesh = add_triangle(bm, bm.verts, ({},{},{}), norm_list, ({},{},{}), {}, od_list, " "two_face_vert)\n"), primVerts[c % 3].pos, primVerts[(c + 1) % 3].pos, primVerts[(c + 2) % 3].pos, primVerts[c % 3].norm, @@ -863,7 +866,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I os << "if last_face is not None:\n"; for (unsigned j = 0; j < matUVCount; ++j) { if (j == 0 && matShortUVs) - os.format(fmt( + os.format(FMT_STRING( " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[{}], suv_list[{}], " "suv_list[{}])\n" " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " @@ -875,7 +878,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I 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(fmt( + os.format(FMT_STRING( " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " "uv_list[{}]\n" " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " @@ -898,7 +901,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I } else if (ptype == GX::TRIANGLES) { for (int v = 0; v < vertCount; v += 3) { - os.format(fmt( + os.format(FMT_STRING( "last_face, last_mesh = add_triangle(bm, bm.verts, ({},{},{}), norm_list, ({},{},{}), {}, od_list, " "two_face_vert)\n"), primVerts[0].pos, primVerts[1].pos, primVerts[2].pos, primVerts[0].norm, primVerts[1].norm, @@ -907,7 +910,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I os << "if last_face is not None:\n"; for (unsigned j = 0; j < matUVCount; ++j) { if (j == 0 && matShortUVs) - os.format(fmt( + os.format(FMT_STRING( " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[{}], suv_list[{}], " "suv_list[{}])\n" " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " @@ -919,7 +922,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I 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(fmt( + os.format(FMT_STRING( " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " "uv_list[{}]\n" " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " @@ -942,7 +945,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I } else if (ptype == GX::TRIANGLEFAN) { ++c; for (int v = 0; v < vertCount - 2; ++v) { - os.format(fmt( + os.format(FMT_STRING( "last_face, last_mesh = add_triangle(bm, bm.verts, ({},{},{}), norm_list, ({},{},{}), {}, od_list, " "two_face_vert)\n"), firstPrimVert.pos, primVerts[c % 3].pos, primVerts[(c + 1) % 3].pos, firstPrimVert.norm, @@ -951,7 +954,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I os << "if last_face is not None:\n"; for (unsigned j = 0; j < matUVCount; ++j) { if (j == 0 && matShortUVs) - os.format(fmt( + os.format(FMT_STRING( " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[{}], suv_list[{}], " "suv_list[{}])\n" " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " @@ -963,7 +966,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I 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(fmt( + os.format(FMT_STRING( " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " "uv_list[{}]\n" " loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = " @@ -999,7 +1002,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I FinishBlenderMesh(os, matSetCount, meshIdx); if (rp.first.second) { - os.format(fmt("mesh.cskr_id = '{}'\n"), rp.first.first); + os.format(FMT_STRING("mesh.cskr_id = '{}'\n"), rp.first.first); rp.second.second->sendVertexGroupsToBlender(os); } @@ -1013,18 +1016,18 @@ bool ReadCMDLToBlender(hecl::blender::Connection& conn, athena::io::IStreamReade head.read(reader); if (head.magic != 0xDEADBABE) { - LogDNACommon.report(logvisor::Error, fmt("invalid CMDL magic")); + LogDNACommon.report(logvisor::Error, FMT_STRING("invalid CMDL magic")); return false; } if (head.version != Version) { - LogDNACommon.report(logvisor::Error, fmt("invalid CMDL version")); + LogDNACommon.report(logvisor::Error, FMT_STRING("invalid CMDL version")); return false; } /* Open Py Stream and read sections */ hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format(fmt( + os.format(FMT_STRING( "import bpy\n" "import bmesh\n" "\n" @@ -1075,14 +1078,14 @@ void NameCMDL(athena::io::IStreamReader& reader, PAKRouter& pakRouter, typename const SpecBase& dataspec) { Header head; head.read(reader); - std::string bestName = fmt::format(fmt("CMDL_{}"), entry.id); + std::string bestName = fmt::format(FMT_STRING("CMDL_{}"), entry.id); /* 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 < lastDlSec; ++s) { + for (atUint32 s = 0; s < lastDlSec; ++s) { atUint64 secStart = reader.position(); if (s < matSecCount) { MaterialSet matSet; @@ -1149,7 +1152,7 @@ bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath size_t endOff = 0; for (const Material& mat : mset) { - std::string diagName = fmt::format(fmt("{}:{}"), inPath.getLastComponentUTF8(), mat.name); + std::string diagName = fmt::format(FMT_STRING("{}:{}"), inPath.getLastComponentUTF8(), mat.name); hecl::Frontend::IR matIR = FE.compileSource(mat.source, diagName); setBackends.emplace_back(); hecl::Backend::GX& matGX = setBackends.back(); @@ -1242,7 +1245,7 @@ bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath 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, fmt("GX DisplayList overflow")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("GX DisplayList overflow")); size_t secSz = 64; for (auto it = surf.verts.cbegin(); it != surf.verts.cend();) { atUint16 vertCount = 0; @@ -1336,7 +1339,7 @@ bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath else if (mesh.topology == hecl::HMDLTopology::TriStrips) prim = GX::TRIANGLESTRIP; else - LogDNACommon.report(logvisor::Fatal, fmt("unrecognized mesh output mode")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("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(); @@ -1784,7 +1787,7 @@ bool WriteMREASecs(std::vector>& secsOut, const hecl::Proje else if (mesh.topology == hecl::HMDLTopology::TriStrips) prim = GX::TRIANGLESTRIP; else - LogDNACommon.report(logvisor::Fatal, fmt("unrecognized mesh output mode")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("unrecognized mesh output mode")); auto surfEndOffIt = surfEndOffs.begin(); size_t lastEndOff = 0; for (const Mesh::Surface& surf : mesh.surfaces) { diff --git a/DataSpec/DNACommon/CMakeLists.txt b/DataSpec/DNACommon/CMakeLists.txt index 39a616532..b4387de34 100644 --- a/DataSpec/DNACommon/CMakeLists.txt +++ b/DataSpec/DNACommon/CMakeLists.txt @@ -4,10 +4,12 @@ make_dnalist(CMDL FSM2 MAPA MAPU + PATH MayaSpline EGMC SAVWCommon ParticleCommon + URDEVersionInfo Tweaks/ITweakPlayerGun) set(DNACOMMON_SOURCES @@ -19,6 +21,7 @@ set(DNACOMMON_SOURCES CMDL.cpp MAPA.cpp MAPU.cpp + PATH.hpp PATH.cpp STRG.hpp STRG.cpp TXTR.hpp TXTR.cpp ANCS.hpp ANCS.cpp @@ -38,6 +41,7 @@ set(DNACOMMON_SOURCES RigInverter.hpp RigInverter.cpp AROTBuilder.hpp AROTBuilder.cpp OBBTreeBuilder.hpp OBBTreeBuilder.cpp + URDEVersionInfo.hpp Tweaks/ITweak.hpp Tweaks/TweakWriter.hpp Tweaks/ITweakGame.hpp diff --git a/DataSpec/DNACommon/DNACommon.cpp b/DataSpec/DNACommon/DNACommon.cpp index 0ddf8c344..dcf816b81 100644 --- a/DataSpec/DNACommon/DNACommon.cpp +++ b/DataSpec/DNACommon/DNACommon.cpp @@ -26,11 +26,11 @@ hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const IDType& id, bool si if (!project) { if (pakRouter) { if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id.isValid()) - LogDNACommon.report(logvisor::Warning, fmt("unable to translate {} to path"), id); + LogDNACommon.report(logvisor::Warning, FMT_STRING("unable to translate {} to path"), id); return {}; } LogDNACommon.report(logvisor::Fatal, - fmt("g_PakRouter or s_Project must be set to non-null before " + FMT_STRING("g_PakRouter or s_Project must be set to non-null before " "calling UniqueIDBridge::TranslatePakIdToPath")); return {}; } @@ -38,7 +38,7 @@ hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const IDType& id, bool si const hecl::ProjectPath* search = project->lookupBridgePath(id.toUint64()); if (!search) { if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id.isValid()) - LogDNACommon.report(logvisor::Warning, fmt("unable to translate {} to path"), id); + LogDNACommon.report(logvisor::Warning, FMT_STRING("unable to translate {} to path"), id); return {}; } return *search; @@ -53,7 +53,7 @@ hecl::ProjectPath UniqueIDBridge::MakePathFromString(std::string_view str) { return {}; hecl::Database::Project* project = s_Project.get(); if (!project) - LogDNACommon.report(logvisor::Fatal, fmt("UniqueIDBridge::setGlobalProject must be called before MakePathFromString")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("UniqueIDBridge::setGlobalProject must be called before MakePathFromString")); hecl::ProjectPath path = hecl::ProjectPath(*project, str); project->addBridgePathToCache(IDType(path).toUint64(), path); return path; @@ -91,7 +91,7 @@ void UniqueID32::Enumerate(typename BinarySize::StreamT& s) } std::string UniqueID32::toString() const { - return fmt::format(fmt("{}"), *this); + return fmt::format(FMT_STRING("{}"), *this); } template <> @@ -143,7 +143,7 @@ void UniqueID64::Enumerate(typename BinarySize::StreamT& s) } std::string UniqueID64::toString() const { - return fmt::format(fmt("{}"), *this); + return fmt::format(FMT_STRING("{}"), *this); } /** PAK 128-bit Unique ID */ @@ -176,7 +176,7 @@ void UniqueID128::Enumerate(typename BinarySize::StreamT& s) } std::string UniqueID128::toString() const { - return fmt::format(fmt("{}"), *this); + return fmt::format(FMT_STRING("{}"), *this); } /** Word Bitmap reader/writer */ diff --git a/DataSpec/DNACommon/DNACommon.hpp b/DataSpec/DNACommon/DNACommon.hpp index 08587bb3d..6ef5263fb 100644 --- a/DataSpec/DNACommon/DNACommon.hpp +++ b/DataSpec/DNACommon/DNACommon.hpp @@ -79,15 +79,15 @@ 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, fmt("PAKRouter IDType mismatch; expected UniqueID32 specialization")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter IDType mismatch; expected UniqueID32 specialization")); return hecl::ProjectPath(); } virtual hecl::ProjectPath getWorking(const UniqueID64&, bool silenceWarnings = false) const { - LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter IDType mismatch; expected UniqueID64 specialization")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter IDType mismatch; expected UniqueID64 specialization")); return hecl::ProjectPath(); } virtual hecl::ProjectPath getWorking(const UniqueID128&, bool silenceWarnings = false) const { - LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter IDType mismatch; expected UniqueID128 specialization")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter IDType mismatch; expected UniqueID128 specialization")); return hecl::ProjectPath(); } }; diff --git a/DataSpec/DNACommon/DeafBabe.cpp b/DataSpec/DNACommon/DeafBabe.cpp index 5f93be382..c18bb7162 100644 --- a/DataSpec/DNACommon/DeafBabe.cpp +++ b/DataSpec/DNACommon/DeafBabe.cpp @@ -22,7 +22,7 @@ void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, b "col_bm = bmesh.new()\n"; for (const atVec3f& vert : db.verts) { zeus::simd_floats f(vert.simd); - os.format(fmt("col_bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]); + os.format(FMT_STRING("col_bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]); } os << "col_bm.verts.ensure_lookup_table()\n"; @@ -49,11 +49,11 @@ void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, b } os << "tri_verts = []\n"; - os.format(fmt("tri_verts.append(col_bm.verts[{}])\n"), vindices[0]); - os.format(fmt("tri_verts.append(col_bm.verts[{}])\n"), vindices[1]); - os.format(fmt("tri_verts.append(col_bm.verts[{}])\n"), vindices[2]); + os.format(FMT_STRING("tri_verts.append(col_bm.verts[{}])\n"), vindices[0]); + os.format(FMT_STRING("tri_verts.append(col_bm.verts[{}])\n"), vindices[1]); + os.format(FMT_STRING("tri_verts.append(col_bm.verts[{}])\n"), vindices[2]); - os.format(fmt( + os.format(FMT_STRING( "face = col_bm.faces.get(tri_verts)\n" "if face is None:\n" " face = col_bm.faces.new(tri_verts)\n" @@ -72,7 +72,7 @@ void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, b db.insertNoClimb(os); if (isDcln) - os.format(fmt("col_mesh = bpy.data.meshes.new('CMESH_{}')\n"), idx); + os.format(FMT_STRING("col_mesh = bpy.data.meshes.new('CMESH_{}')\n"), idx); else os << "col_mesh = bpy.data.meshes.new('CMESH')\n"; diff --git a/DataSpec/DNACommon/FONT.cpp b/DataSpec/DNACommon/FONT.cpp index 7cab85f3c..3e3e652b8 100644 --- a/DataSpec/DNACommon/FONT.cpp +++ b/DataSpec/DNACommon/FONT.cpp @@ -13,7 +13,7 @@ void FONT::_read(athena::io::IStreamReader& __dna_reader) { DNAFourCC magic; magic.read(__dna_reader); if (magic != SBIG('FONT')) { - LogModule.report(logvisor::Fatal, fmt("Invalid FONT magic '{}'"), magic); + LogModule.report(logvisor::Fatal, FMT_STRING("Invalid FONT magic '{}'"), magic); return; } /* version */ diff --git a/DataSpec/DNACommon/FSM2.cpp b/DataSpec/DNACommon/FSM2.cpp index e13d4753a..27b73f457 100644 --- a/DataSpec/DNACommon/FSM2.cpp +++ b/DataSpec/DNACommon/FSM2.cpp @@ -16,7 +16,7 @@ template void FSM2::Enumerate(typename Op::StreamT& s) { Do(athena::io::PropId{"header"}, header, s); if (header.magic != SBIG('FSM2')) { - LogDNAFSM2.report(logvisor::Fatal, fmt("Invalid FSM2 magic '{}' expected 'FSM2'"), header.magic); + LogDNAFSM2.report(logvisor::Fatal, FMT_STRING("Invalid FSM2 magic '{}' expected 'FSM2'"), header.magic); return; } @@ -29,7 +29,7 @@ void FSM2::Enumerate(typename Op::StreamT& s) { detail.reset(new FSMV2); Do(athena::io::PropId{"detail"}, static_cast(*detail), s); } else { - LogDNAFSM2.report(logvisor::Fatal, fmt("Invalid FSM2 version '{}'"), header.version); + LogDNAFSM2.report(logvisor::Fatal, FMT_STRING("Invalid FSM2 version '{}'"), header.version); return; } } diff --git a/DataSpec/DNACommon/MAPA.cpp b/DataSpec/DNACommon/MAPA.cpp index 3e8a868f5..2cc8e85d9 100644 --- a/DataSpec/DNACommon/MAPA.cpp +++ b/DataSpec/DNACommon/MAPA.cpp @@ -21,7 +21,7 @@ void MAPA::Enumerate(typename Read::StreamT& __dna_reader) { /* magic */ magic = __dna_reader.readUint32Big(); if (magic != 0xDEADD00D) { - LogDNACommon.report(logvisor::Error, fmt("invalid MAPA magic")); + LogDNACommon.report(logvisor::Error, FMT_STRING("invalid MAPA magic")); return; } /* version */ @@ -33,7 +33,7 @@ void MAPA::Enumerate(typename Read::StreamT& __dna_reader) { else if (version == 5) header = std::make_unique(); else { - LogDNACommon.report(logvisor::Error, fmt("invalid MAPA version")); + LogDNACommon.report(logvisor::Error, FMT_STRING("invalid MAPA version")); return; } @@ -146,7 +146,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const " edge.seam = True\n" "\n"; - os.format(fmt( + os.format(FMT_STRING( "bpy.context.scene.name = 'MAPA_{}'\n" "bpy.context.scene.retro_map_vis_mode = '{}'\n"), entry.id, RetroMapVisModes[mapa.header->visMode()]); @@ -159,7 +159,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const zeus::simd_floats mtxF[3]; for (int i = 0; i < 3; ++i) moMP12->transformMtx[i].simd.copy_to(mtxF[i]); - os.format(fmt( + os.format(FMT_STRING( "obj = bpy.data.objects.new('MAPOBJ_{:02d}', None)\n" "bpy.context.scene.collection.objects.link(obj)\n" "obj.retro_mappable_type = {}\n" @@ -181,7 +181,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const zeus::simd_floats mtxF[3]; for (int i = 0; i < 3; ++i) moMP3->transformMtx[i].simd.copy_to(mtxF[i]); - os.format(fmt( + os.format(FMT_STRING( "obj = bpy.data.objects.new('MAPOBJ_{:02d}', None)\n" "bpy.context.scene.collection.objects.link(obj)\n" "obj.retro_mappable_type = {}\n" @@ -208,7 +208,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const /* Read in verts */ for (const atVec3f& vert : mapa.vertices) { zeus::simd_floats f(vert.simd); - os.format(fmt("bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]); + os.format(FMT_STRING("bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]); } os << "bm.verts.ensure_lookup_table()\n"; @@ -225,10 +225,10 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const atUint8 flip = 0; for (size_t v = 0; v < prim.indexCount - 2; ++v) { if (flip) { - os.format(fmt("add_triangle(bm, ({},{},{}))\n"), primVerts[c % 3], primVerts[(c + 2) % 3], + os.format(FMT_STRING("add_triangle(bm, ({},{},{}))\n"), primVerts[c % 3], primVerts[(c + 2) % 3], primVerts[(c + 1) % 3]); } else { - os.format(fmt("add_triangle(bm, ({},{},{}))\n"), primVerts[c % 3], primVerts[(c + 1) % 3], + os.format(FMT_STRING("add_triangle(bm, ({},{},{}))\n"), primVerts[c % 3], primVerts[(c + 1) % 3], primVerts[(c + 2) % 3]); } flip ^= 1; @@ -248,7 +248,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const } } else if (GX::Primitive(prim.type) == GX::TRIANGLES) { for (size_t v = 0; v < prim.indexCount; v += 3) { - os.format(fmt("add_triangle(bm, ({},{},{}))\n"), primVerts[0], primVerts[1], primVerts[2]); + os.format(FMT_STRING("add_triangle(bm, ({},{},{}))\n"), primVerts[0], primVerts[1], primVerts[2]); /* Break if done */ if (v + 3 >= prim.indexCount) @@ -264,7 +264,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const 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(fmt("add_border(bm, ({},{}))\n"), *iit, *(iit + 1)); + os.format(FMT_STRING("add_border(bm, ({},{}))\n"), *iit, *(iit + 1)); ++iit; } } @@ -278,7 +278,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const const zeus::CMatrix4f* tmpMtx = pakRouter.lookupMAPATransform(entry.id); const zeus::CMatrix4f& mtx = tmpMtx ? *tmpMtx : zeus::skIdentityMatrix4f; - os.format(fmt( + os.format(FMT_STRING( "mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n" "mtxd = mtx.decompose()\n" "obj.rotation_mode = 'QUATERNION'\n" @@ -294,7 +294,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const if (hecl::StringUtils::BeginsWith(ent.m_name, _SYS_STR("!world_")) && hecl::StringUtils::EndsWith(ent.m_name, _SYS_STR(".blend"))) { hecl::SystemUTF8Conv conv(ent.m_name); - os.linkBackground(fmt::format(fmt("//../{}"), conv), "World"sv); + os.linkBackground(fmt::format(FMT_STRING("//../{}"), conv), "World"sv); break; } } @@ -326,7 +326,7 @@ template bool ReadMAPAToBlender>(hecl::blender::Con template bool Cook(const hecl::blender::MapArea& mapaIn, const hecl::ProjectPath& out) { if (mapaIn.verts.size() >= 256) { - Log.report(logvisor::Error, fmt(_SYS_STR("MAPA {} vertex range exceeded [{}/{}]")), out.getRelativePath(), + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("MAPA {} vertex range exceeded [{}/{}]")), out.getRelativePath(), mapaIn.verts.size(), 255); return false; } diff --git a/DataSpec/DNACommon/MAPU.cpp b/DataSpec/DNACommon/MAPU.cpp index d6f1210f4..e3e7dcf9f 100644 --- a/DataSpec/DNACommon/MAPU.cpp +++ b/DataSpec/DNACommon/MAPU.cpp @@ -43,7 +43,7 @@ bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const for (int i = 0; i < 3; ++i) wldXf.xf[i].simd.copy_to(wldXfF[i]); zeus::simd_floats hexColorF(wld.hexColor.mSimd); - os.format(fmt( + os.format(FMT_STRING( "wldObj = bpy.data.objects.new('{}', None)\n" "mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n" "mtxd = mtx.decompose()\n" @@ -62,7 +62,7 @@ bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const zeus::simd_floats hexXfF[3]; for (int i = 0; i < 3; ++i) hexXf.xf[i].simd.copy_to(hexXfF[i]); - os.format(fmt( + os.format(FMT_STRING( "obj = bpy.data.objects.new('{}_{}', hexMesh)\n" "mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n" "mtxd = mtx.decompose()\n" diff --git a/DataSpec/DNACommon/MLVL.cpp b/DataSpec/DNACommon/MLVL.cpp index 1db5939b1..94df2d0ca 100644 --- a/DataSpec/DNACommon/MLVL.cpp +++ b/DataSpec/DNACommon/MLVL.cpp @@ -41,7 +41,7 @@ bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const zeus::simd_floats xfMtxF[3]; for (int i = 0; i < 3; ++i) area.transformMtx[i].simd.copy_to(xfMtxF[i]); - os.format(fmt( + os.format(FMT_STRING( "box_mesh = bpy.data.meshes.new('''{}''')\n" "bm.to_mesh(box_mesh)\n" "bm.free()\n" @@ -67,7 +67,7 @@ bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const int idx = 0; for (const atVec3f& pv : dock.planeVerts) { const zeus::CVector3f pvRel = zeus::CVector3f(pv) - pvAvg; - os.format(fmt( + os.format(FMT_STRING( "bm.verts.new(({},{},{}))\n" "bm.verts.ensure_lookup_table()\n"), pvRel[0], pvRel[1], pvRel[2]); @@ -76,13 +76,13 @@ bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const ++idx; } os << "bm.edges.new((bm.verts[-1], bm.verts[0]))\n"; - os.format(fmt("dockMesh = bpy.data.meshes.new('DOCK_{:02d}_{:02d}')\n"), areaIdx, dockIdx); + os.format(FMT_STRING("dockMesh = bpy.data.meshes.new('DOCK_{:02d}_{:02d}')\n"), areaIdx, dockIdx); os << "dockObj = bpy.data.objects.new(dockMesh.name, dockMesh)\n" "bpy.context.scene.collection.objects.link(dockObj)\n" "bm.to_mesh(dockMesh)\n" "bm.free()\n" "dockObj.parent = box\n"; - os.format(fmt("dockObj.location = ({},{},{})\n"), float(pvAvg[0]), float(pvAvg[1]), float(pvAvg[2])); + os.format(FMT_STRING("dockObj.location = ({},{},{})\n"), float(pvAvg[0]), float(pvAvg[1]), float(pvAvg[2])); ++dockIdx; } ++areaIdx; diff --git a/DataSpec/DNACommon/MayaSpline.hpp b/DataSpec/DNACommon/MayaSpline.hpp index 00b48fae3..700f78833 100644 --- a/DataSpec/DNACommon/MayaSpline.hpp +++ b/DataSpec/DNACommon/MayaSpline.hpp @@ -14,6 +14,8 @@ struct MayaSpline : public BigDNA { Value amplitude; Value unk1; Value unk2; + Vector unk1Floats; + Vector unk2Floats; }; Vector knots; diff --git a/DataSpec/DNACommon/PAK.cpp b/DataSpec/DNACommon/PAK.cpp index 6758ed3a9..c285742cf 100644 --- a/DataSpec/DNACommon/PAK.cpp +++ b/DataSpec/DNACommon/PAK.cpp @@ -207,7 +207,7 @@ void PAKRouter::enterPAKBridge(const BRIDGETYPE& pakBridge) { ++pit; ++bridgeIdx; } - LogDNACommon.report(logvisor::Fatal, fmt("PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()")); } template @@ -287,7 +287,7 @@ hecl::ProjectPath PAKRouter::getWorking(const EntryType* entry, return sharedPath.ensureAuxInfo(auxInfo); } - LogDNACommon.report(logvisor::Fatal, fmt("Unable to find entry {}"), entry->id); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("Unable to find entry {}"), entry->id); return hecl::ProjectPath(); } @@ -338,7 +338,7 @@ hecl::ProjectPath PAKRouter::getCooked(const EntryType* entry) const if (sharedSearch != m_sharedEntries.end()) { return hecl::ProjectPath(m_sharedCooked, getBestEntryName(*entry)); } - LogDNACommon.report(logvisor::Fatal, fmt("Unable to find entry {}"), entry->id); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("Unable to find entry {}"), entry->id); return hecl::ProjectPath(); } @@ -353,7 +353,7 @@ hecl::SystemString PAKRouter::getResourceRelativePath(const EntryTyp const PAKType* pak = m_pak.get(); if (!pak) LogDNACommon.report(logvisor::Fatal, - fmt("PAKRouter::enterPAKBridge() must be called before PAKRouter::getResourceRelativePath()")); + FMT_STRING("PAKRouter::enterPAKBridge() must be called before PAKRouter::getResourceRelativePath()")); const typename BRIDGETYPE::PAKType::Entry* be = lookupEntry(b); if (!be) return hecl::SystemString(); @@ -377,17 +377,17 @@ std::string PAKRouter::getBestEntryName(const EntryType& entry, bool if (stdOverride && !pak.m_noShare) { if (entry.type == FOURCC('MLVL')) - return fmt::format(fmt("!world_{}"), entry.id); + return fmt::format(FMT_STRING("!world_{}"), entry.id); else if (entry.type == FOURCC('MREA')) - return fmt::format(fmt("!area_{}"), entry.id); + return fmt::format(FMT_STRING("!area_{}"), entry.id); else if (entry.type == FOURCC('MAPA')) - return fmt::format(fmt("!map_{}"), entry.id); + return fmt::format(FMT_STRING("!map_{}"), entry.id); else if (entry.type == FOURCC('PATH')) - return fmt::format(fmt("!path_{}"), entry.id); + return fmt::format(FMT_STRING("!path_{}"), entry.id); else if (entry.type == FOURCC('MAPW')) - return fmt::format(fmt("!mapw_{}"), entry.id); + return fmt::format(FMT_STRING("!mapw_{}"), entry.id); else if (entry.type == FOURCC('SAVW')) - return fmt::format(fmt("!savw_{}"), entry.id); + return fmt::format(FMT_STRING("!savw_{}"), entry.id); } std::string catalogueName; @@ -409,17 +409,17 @@ std::string PAKRouter::getBestEntryName(const IDType& entry, bool st if (stdOverride && !pak.m_noShare) { if (e->type == FOURCC('MLVL')) - return fmt::format(fmt("!world_{}"), e->id); + return fmt::format(FMT_STRING("!world_{}"), e->id); else if (e->type == FOURCC('MREA')) - return fmt::format(fmt("!area_{}"), e->id); + return fmt::format(FMT_STRING("!area_{}"), e->id); else if (e->type == FOURCC('MAPA')) - return fmt::format(fmt("!map_{}"), e->id); + return fmt::format(FMT_STRING("!map_{}"), e->id); else if (e->type == FOURCC('PATH')) - return fmt::format(fmt("!path_{}"), e->id); + return fmt::format(FMT_STRING("!path_{}"), e->id); else if (e->type == FOURCC('MAPW')) - return fmt::format(fmt("!mapw_{}"), e->id); + return fmt::format(FMT_STRING("!mapw_{}"), e->id); else if (e->type == FOURCC('SAVW')) - return fmt::format(fmt("!savw_{}"), e->id); + return fmt::format(FMT_STRING("!savw_{}"), e->id); } std::string catalogueName; @@ -495,7 +495,7 @@ const typename BRIDGETYPE::PAKType::Entry* PAKRouter::lookupEntry(co return nullptr; if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::lookupEntry()")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter::build() must be called before PAKRouter::lookupEntry()")); const PAKType* pak = m_pak.get(); const nod::Node* node = m_node.get(); @@ -511,7 +511,7 @@ const typename BRIDGETYPE::PAKType::Entry* PAKRouter::lookupEntry(co if (currentPAK) { #ifndef NDEBUG if (!silenceWarnings) - LogDNACommon.report(logvisor::Warning, fmt("unable to find PAK entry {} in current PAK"), entry); + LogDNACommon.report(logvisor::Warning, FMT_STRING("unable to find PAK entry {} in current PAK"), entry); #endif return nullptr; } @@ -528,7 +528,7 @@ const typename BRIDGETYPE::PAKType::Entry* PAKRouter::lookupEntry(co #ifndef NDEBUG if (!silenceWarnings) - LogDNACommon.report(logvisor::Warning, fmt("unable to find PAK entry {}"), entry); + LogDNACommon.report(logvisor::Warning, FMT_STRING("unable to find PAK entry {}"), entry); #endif if (nodeOut) *nodeOut = nullptr; @@ -561,7 +561,7 @@ const zeus::CMatrix4f* PAKRouter::lookupMAPATransform(const IDType& template hecl::ProjectPath PAKRouter::getAreaLayerWorking(const IDType& areaId, int layerIdx) const { if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("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) @@ -583,7 +583,7 @@ hecl::ProjectPath PAKRouter::getAreaLayerWorking(const IDType& areaI bool& activeOut) const { activeOut = false; if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("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) @@ -605,7 +605,7 @@ hecl::ProjectPath PAKRouter::getAreaLayerWorking(const IDType& areaI template hecl::ProjectPath PAKRouter::getAreaLayerCooked(const IDType& areaId, int layerIdx) const { if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("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) @@ -626,7 +626,7 @@ template hecl::ProjectPath PAKRouter::getAreaLayerCooked(const IDType& areaId, int layerIdx, bool& activeOut) const { activeOut = false; if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("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) @@ -648,7 +648,7 @@ hecl::ProjectPath PAKRouter::getAreaLayerCooked(const IDType& areaId template void PAKRouter::enumerateResources(const std::function& func) { if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::enumerateResources()")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter::build() must be called before PAKRouter::enumerateResources()")); for (const auto& entryPair : m_uniqueEntries) if (!func(entryPair.second.second)) return; @@ -662,7 +662,7 @@ bool PAKRouter::mreaHasDupeResources(const IDType& id) const { const PAKType* pak = m_pak.get(); if (!pak) LogDNACommon.report(logvisor::Fatal, - fmt("PAKRouter::enterPAKBridge() must be called before PAKRouter::mreaHasDupeResources()")); + FMT_STRING("PAKRouter::enterPAKBridge() must be called before PAKRouter::mreaHasDupeResources()")); return pak->mreaHasDupeResources(id); } diff --git a/DataSpec/DNACommon/PAK.hpp b/DataSpec/DNACommon/PAK.hpp index c7723eea0..35ca2802e 100644 --- a/DataSpec/DNACommon/PAK.hpp +++ b/DataSpec/DNACommon/PAK.hpp @@ -31,7 +31,7 @@ public: 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, fmt("PAK stream cursor overrun")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAK stream cursor overrun")); } void seek(atInt64 pos, athena::SeekOrigin origin) override { if (origin == athena::SeekOrigin::Begin) { @@ -42,7 +42,7 @@ public: m_pos = m_sz + pos; } if (m_pos > m_sz) { - LogDNACommon.report(logvisor::Fatal, fmt("PAK stream cursor overrun")); + LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAK stream cursor overrun")); } } atUint64 position() const override { return m_pos; } diff --git a/DataSpec/DNACommon/PATH.cpp b/DataSpec/DNACommon/PATH.cpp new file mode 100644 index 000000000..212cdad6f --- /dev/null +++ b/DataSpec/DNACommon/PATH.cpp @@ -0,0 +1,248 @@ +#include "PATH.hpp" +#include "hecl/Blender/Connection.hpp" +#include "zeus/CAABox.hpp" +#include "DataSpec/DNACommon/AROTBuilder.hpp" + +namespace DataSpec::DNAPATH { + +#define DUMP_OCTREE 0 + +#if DUMP_OCTREE +/* octree dumper */ +static void OutputOctreeNode(hecl::blender::PyOutStream& os, int idx, const zeus::CAABox& aabb) { + const zeus::CVector3f pos = aabb.center(); + const zeus::CVector3f extent = aabb.extents(); + os.format( + "obj = bpy.data.objects.new('Leaf_%d', None)\n" + "bpy.context.scene.collection.objects.link(obj)\n" + "obj.location = (%f,%f,%f)\n" + "obj.scale = (%f,%f,%f)\n" + "obj.empty_display_type = 'CUBE'\n" + "obj.layers[1] = True\n" + "obj.layers[0] = False\n", + idx, pos.x(), pos.y(), pos.z(), extent.x(), extent.y(), extent.z()); +} +#endif + +template +void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, + const zeus::CMatrix4f* xf, const std::string& areaPath) { + /* Open Py Stream and read sections */ + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os << "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, 1.0)\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, 1.0)\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, 1.0)\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"; + os.format(FMT_STRING("bpy.context.scene.name = '{}'\n"), entryName); + os << "# Clear Scene\n" + "if len(bpy.data.collections):\n" + " bpy.data.collections.remove(bpy.data.collections[0])\n" + "\n" + "bm = bmesh.new()\n" + "height_lay = bm.faces.layers.float.new('Height')\n"; + + for (const Node& n : nodes) { + zeus::simd_floats f(n.position.simd); + os.format(FMT_STRING("bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]); + } + + os << "bm.verts.ensure_lookup_table()\n"; + + for (const Region& r : regions) { + os << "tri_verts = []\n"; + for (atUint32 i = 0; i < r.nodeCount; ++i) + os.format(FMT_STRING("tri_verts.append(bm.verts[{}])\n"), r.nodeStart + i); + + os.format(FMT_STRING("face = bm.faces.get(tri_verts)\n" + "if face is None:\n" + " face = bm.faces.new(tri_verts)\n" + " face.normal_flip()\n" + "face.material_index = select_material(0x{:04X}, 0x{:04X})\n" + "face.smooth = False\n" + "face[height_lay] = {}\n" + "\n"), + r.meshIndexMask, r.meshTypeMask, r.height); + +#if 0 + const zeus::CVector3f center = xf->multiplyOneOverW(r.centroid); + zeus::CAABox aabb(xf->multiplyOneOverW(r.aabb[0]), xf->multiplyOneOverW(r.aabb[1])); + os.format(FMT_STRING("aabb = bpy.data.objects.new('AABB', None)\n") + "aabb.location = (%f,%f,%f)\n" + "aabb.scale = (%f,%f,%f)\n" + "aabb.empty_display_type = 'CUBE'\n" + "bpy.context.scene.collection.objects.link(aabb)\n" + "centr = bpy.data.objects.new('Center', None)\n" + "centr.location = (%f,%f,%f)\n" + "bpy.context.scene.collection.objects.link(centr)\n", + aabb.min[0] + (aabb.max[0] - aabb.min[0]) / 2.f, + aabb.min[1] + (aabb.max[1] - aabb.min[1]) / 2.f, + aabb.min[2] + (aabb.max[2] - aabb.min[2]) / 2.f, + (aabb.max[0] - aabb.min[0]) / 2.f, + (aabb.max[1] - aabb.min[1]) / 2.f, + (aabb.max[2] - aabb.min[2]) / 2.f, + center.x(), center.y(), center.z()); +#endif + } + +#if 0 + for (const Node& n : nodes) { + zeus::simd_floats f(n.position.simd); + zeus::simd_floats no(n.position.simd + n.normal.simd); + os.format(FMT_STRING("v = bm.verts.new((%f,%f,%f))\n") + "v2 = bm.verts.new((%f,%f,%f))\n" + "bm.edges.new((v, v2))\n", f[0], f[1], f[2], no[0], no[1], no[2]); + } +#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.collection.objects.link(path_mesh_obj)\n" + "path_mesh_obj.display_type = 'SOLID'\n" + "bpy.context.scene.hecl_path_obj = path_mesh_obj.name\n" + "\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(FMT_STRING("mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(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 DUMP_OCTREE + { + int idx = 0; + for (const auto& n : octree) { + if (n.isLeaf) + OutputOctreeNode(os, idx, zeus::CAABox(n.aabb[0], n.aabb[1])); + ++idx; + } + } +#endif + + os.linkBackground(fmt::format(FMT_STRING("//{}"), areaPath)); + os.centerView(); + os.close(); +} + +template +bool PATH::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKBridge::PAKType::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; + + std::string areaPath; + for (const auto& ent : hecl::DirectoryEnumerator(outPath.getParentPath().getAbsolutePath())) { + if (hecl::StringUtils::BeginsWith(ent.m_name, _SYS_STR("!area_"))) { + areaPath = hecl::SystemUTF8Conv(ent.m_name).str(); + break; + } + } + + const zeus::CMatrix4f* xf = pakRouter.lookupMAPATransform(entry.id); + path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf, areaPath); + return conn.saveBlend(); +} + +template +bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const PathMesh& mesh, + hecl::blender::Token& btok) { + 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; + } + +#if DUMP_OCTREE + { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".octree.blend"), true), hecl::blender::BlendType::PathMesh)) + return false; + + zeus::CMatrix4f xf; + path.sendToBlender(conn, "PATH"sv, &xf); + conn.saveBlend(); + } +#endif + + 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; +} + +template struct PATH; +template struct PATH; +template struct PATH; + +} // namespace DataSpec::DNAPATH \ No newline at end of file diff --git a/DataSpec/DNACommon/PATH.hpp b/DataSpec/DNACommon/PATH.hpp new file mode 100644 index 000000000..2a3f8d793 --- /dev/null +++ b/DataSpec/DNACommon/PATH.hpp @@ -0,0 +1,112 @@ +#pragma once + +#include "DataSpec/DNACommon/DNACommon.hpp" +#include "DataSpec/DNACommon/PAK.hpp" +#include "DataSpec/DNAMP1/DNAMP1.hpp" +#include "DataSpec/DNAMP2/DNAMP2.hpp" +#include "DataSpec/DNAMP3/DNAMP3.hpp" + +namespace DataSpec::DNAPATH { +template +struct RegionPointers {}; +template <> +struct RegionPointers : BigDNA { + AT_DECL_DNA + Value regionIdxPtr; +}; +template <> +struct RegionPointers : BigDNA { + AT_DECL_DNA + Value unk0; + Value unk1; + Value unk2; + Value regionIdxPtr; +}; +template <> +struct RegionPointers : BigDNA { + AT_DECL_DNA + Value unk0; + Value unk1; + Value unk2; + Value regionIdxPtr; +}; + +template +struct AT_SPECIALIZE_PARMS(DataSpec::DNAMP1::PAKBridge, DataSpec::DNAMP2::PAKBridge, DataSpec::DNAMP3::PAKBridge) PATH +: BigDNA { + using PathMesh = hecl::blender::PathMesh; + + AT_DECL_DNA + Value version; + + struct Node : BigDNA { + AT_DECL_DNA + Value position; + Value normal; + }; + Value nodeCount; + Vector nodes; + + 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; + Value nodeStart; + Value linkCount; + Value linkStart; + Value meshIndexMask; + Value meshTypeMask; + Value height; + Value normal; + Value regionIdx; + Value centroid; + Value aabb[2]; + Value> pointers; + }; + Value regionCount; + Vector regions; + + Vector bitmap1; + Vector bitmap2; + + /* Unused in all games, removed in MP3 */ + Vector + ? 0 + : (((((regionCount * regionCount) + 31) / 32) - bitmap1.size()) * 2))> + bitmap3; + + Value octreeRegionLookupCount; + Vector octreeRegionLookup; + + 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, + const std::string& areaPath); + + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKBridge::PAKType::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged); + + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const PathMesh& mesh, + hecl::blender::Token& btok); +}; +} // namespace DataSpec::DNAPATH diff --git a/DataSpec/DNACommon/ParticleCommon.hpp b/DataSpec/DNACommon/ParticleCommon.hpp index 159cc85fd..7f80f582c 100644 --- a/DataSpec/DNACommon/ParticleCommon.hpp +++ b/DataSpec/DNACommon/ParticleCommon.hpp @@ -45,7 +45,7 @@ struct PPImpl : BigDNA, _Basis { constexpr FourCC RefType = uint32_t(_Basis::Type); DNAFourCC clsId(r); if (clsId != RefType) { - LogModule.report(logvisor::Warning, fmt("non {} provided to {} parser"), RefType, RefType); + LogModule.report(logvisor::Warning, FMT_STRING("non {} provided to {} parser"), RefType, RefType); return; } clsId.read(r); @@ -68,7 +68,7 @@ struct PPImpl : BigDNA, _Basis { p.read(r); } })) { - LogModule.report(logvisor::Fatal, fmt("Unknown {} class {} @{}"), RefType, clsId, r.position()); + LogModule.report(logvisor::Fatal, FMT_STRING("Unknown {} class {} @{}"), RefType, clsId, r.position()); } clsId.read(r); } @@ -124,7 +124,7 @@ struct PPImpl : BigDNA, _Basis { if (key == "DNAType"sv) continue; if (key.size() < 4) { - LogModule.report(logvisor::Warning, fmt("short FourCC in element '{}'"), key); + LogModule.report(logvisor::Warning, FMT_STRING("short FourCC in element '{}'"), key); continue; } @@ -142,7 +142,7 @@ struct PPImpl : BigDNA, _Basis { p.read(r); } })) { - LogModule.report(logvisor::Fatal, fmt("Unknown {} class {}"), RefType, clsId); + LogModule.report(logvisor::Fatal, FMT_STRING("Unknown {} class {}"), RefType, clsId); } } } @@ -201,7 +201,7 @@ struct PEImpl : BigDNA { m_elem = std::make_unique(); m_elem->read(r); })) { - LogModule.report(logvisor::Fatal, fmt("Unknown {} class {} @{}"), _PtrType::TypeName, clsId, r.position()); + LogModule.report(logvisor::Fatal, FMT_STRING("Unknown {} class {} @{}"), _PtrType::TypeName, clsId, r.position()); } } @@ -229,7 +229,7 @@ struct PEImpl : BigDNA { const auto& [key, value] = mapChildren[0]; if (key.size() < 4) - LogModule.report(logvisor::Fatal, fmt("short FourCC in element '{}'"), key); + LogModule.report(logvisor::Fatal, FMT_STRING("short FourCC in element '{}'"), key); if (auto rec = r.enterSubRecord(key)) { const DNAFourCC clsId = key.c_str(); @@ -238,7 +238,7 @@ struct PEImpl : BigDNA { m_elem = std::make_unique(); m_elem->read(r); })) { - LogModule.report(logvisor::Fatal, fmt("Unknown {} class {}"), _PtrType::TypeName, clsId); + LogModule.report(logvisor::Fatal, FMT_STRING("Unknown {} class {}"), _PtrType::TypeName, clsId); } } } @@ -253,7 +253,7 @@ struct PEImpl : BigDNA { _Basis::gatherDependencies(deps, m_elem); } - operator bool() const { return m_elem.operator bool(); } + explicit operator bool() const { return m_elem.operator bool(); } auto* get() const { return m_elem.get(); } auto* operator->() const { return get(); } void reset() { m_elem.reset(); } @@ -565,7 +565,7 @@ struct IUVElement : IElement { struct BoolHelper : IElement { AT_DECL_EXPLICIT_DNA_YAMLV_NO_TYPE bool value = false; - operator bool() const { return value; } + explicit operator bool() const { return value; } BoolHelper& operator=(bool val) { value = val; return *this; @@ -610,7 +610,7 @@ struct ValueHelper : BigDNA { std::optional value = {}; void emplace(Tp val) { value.emplace(val); } Tp operator*() const { return *value; } - operator bool() const { return value.operator bool(); } + explicit operator bool() const { return value.operator bool(); } }; struct RELifetimeTween : IRealElement { @@ -1333,7 +1333,7 @@ struct SpawnSystemKeyframeData : BigDNA { AT_DECL_EXPLICIT_DNA_YAML AT_SUBDECL_DNA - operator bool() const { return spawns.size() != 0; } + explicit operator bool() const { return spawns.size() != 0; } void gatherDependencies(std::vector& pathsOut) const { for (const auto& p : spawns) @@ -1347,7 +1347,7 @@ struct ChildResourceFactory : BigDNA { IDType id; AT_DECL_EXPLICIT_DNA_YAML AT_SUBDECL_DNA - operator bool() const { return id.isValid(); } + explicit operator bool() const { return id.isValid(); } void gatherDependencies(std::vector& pathsOut) const { if (id.isValid()) g_curSpec->flattenDependencies(id, pathsOut); diff --git a/DataSpec/DNACommon/RigInverter.cpp b/DataSpec/DNACommon/RigInverter.cpp index a22f997c4..e1c6078ef 100644 --- a/DataSpec/DNACommon/RigInverter.cpp +++ b/DataSpec/DNACommon/RigInverter.cpp @@ -141,6 +141,5 @@ zeus::CVector3f RigInverter::restorePosition(atUint32 boneId, const ze template class RigInverter; template class RigInverter; -template class RigInverter; } // namespace DataSpec::DNAANIM diff --git a/DataSpec/DNACommon/STRG.cpp b/DataSpec/DNACommon/STRG.cpp index d49339bee..868f808b0 100644 --- a/DataSpec/DNACommon/STRG.cpp +++ b/DataSpec/DNACommon/STRG.cpp @@ -13,7 +13,7 @@ void ISTRG::gatherDependencies(std::vector& pathsOut) const { std::unique_ptr LoadSTRG(athena::io::IStreamReader& reader) { uint32_t magic = reader.readUint32Big(); if (magic != 0x87654321) { - LogDNACommon.report(logvisor::Error, fmt("invalid STRG magic")); + LogDNACommon.report(logvisor::Error, FMT_STRING("invalid STRG magic")); return std::unique_ptr(); } diff --git a/DataSpec/DNACommon/TXTR.cpp b/DataSpec/DNACommon/TXTR.cpp index 413b6f0ba..815164cc2 100644 --- a/DataSpec/DNACommon/TXTR.cpp +++ b/DataSpec/DNACommon/TXTR.cpp @@ -826,9 +826,9 @@ static void EncodeCMPR(const uint8_t* rgbaIn, uint8_t* texels, int width, int he } } -static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::Error, fmt("{}"), msg); } +static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::Error, FMT_STRING("{}"), msg); } -static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, fmt("{}"), msg); } +static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, FMT_STRING("{}"), msg); } bool TXTR::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { const uint32_t format = rs.readUint32Big(); @@ -838,7 +838,7 @@ bool TXTR::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { auto fp = hecl::FopenUnique(outPath.getAbsolutePath().data(), _SYS_STR("wb")); if (fp == nullptr) { - Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath()); return false; } png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, PNGErr, PNGWarn); @@ -1041,7 +1041,7 @@ static int GetNumPaletteEntriesForGCN(png_structp png, png_infop info) { bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { auto inf = hecl::FopenUnique(inPath.getAbsolutePath().data(), _SYS_STR("rb")); if (inf == nullptr) { - Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for reading")), inPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for reading")), inPath.getAbsolutePath()); return false; } @@ -1049,25 +1049,25 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat char header[8]; std::fread(header, 1, sizeof(header), inf.get()); if (png_sig_cmp((png_const_bytep)header, 0, 8)) { - Log.report(logvisor::Error, fmt(_SYS_STR("invalid PNG signature in '{}'")), inPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("invalid PNG signature in '{}'")), inPath.getAbsolutePath()); 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, fmt("unable to initialize libpng")); + Log.report(logvisor::Error, FMT_STRING("unable to initialize libpng")); return false; } png_infop info = png_create_info_struct(pngRead); if (!info) { - Log.report(logvisor::Error, fmt("unable to initialize libpng info")); + Log.report(logvisor::Error, FMT_STRING("unable to initialize libpng info")); png_destroy_read_struct(&pngRead, nullptr, nullptr); return false; } if (setjmp(png_jmpbuf(pngRead))) { - Log.report(logvisor::Error, fmt(_SYS_STR("unable to initialize libpng I/O for '{}'")), inPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to initialize libpng I/O for '{}'")), inPath.getAbsolutePath()); png_destroy_read_struct(&pngRead, &info, nullptr); return false; } @@ -1083,7 +1083,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat const png_byte bitDepth = png_get_bit_depth(pngRead, info); if (width < 4 || height < 4) { - Log.report(logvisor::Error, fmt("image must be 4x4 or larger")); + Log.report(logvisor::Error, FMT_STRING("image must be 4x4 or larger")); png_destroy_read_struct(&pngRead, &info, nullptr); return false; } @@ -1112,7 +1112,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat } if (bitDepth != 8) { - Log.report(logvisor::Error, fmt(_SYS_STR("'{}' is not 8 bits-per-channel")), inPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("'{}' is not 8 bits-per-channel")), inPath.getAbsolutePath()); png_destroy_read_struct(&pngRead, &info, nullptr); return false; } @@ -1143,7 +1143,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat nComps = 1; break; default: - Log.report(logvisor::Error, fmt(_SYS_STR("unsupported color type in '{}'")), inPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unsupported color type in '{}'")), inPath.getAbsolutePath()); png_destroy_read_struct(&pngRead, &info, nullptr); return false; } @@ -1163,7 +1163,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat bufOut.reset(new uint8_t[bufLen]); if (setjmp(png_jmpbuf(pngRead))) { - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to read image in '{}'")), inPath.getAbsolutePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to read image in '{}'")), inPath.getAbsolutePath()); png_destroy_read_struct(&pngRead, &info, nullptr); return false; } @@ -1344,7 +1344,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat /* Do write out */ athena::io::FileWriter outf(outPath.getAbsolutePath(), true, false); if (outf.hasError()) { - Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath()); return false; } @@ -1360,7 +1360,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { auto inf = hecl::FopenUnique(inPath.getAbsolutePath().data(), _SYS_STR("rb")); if (inf == nullptr) { - Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for reading")), inPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for reading")), inPath.getAbsolutePath()); return false; } @@ -1368,25 +1368,25 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP char header[8]; std::fread(header, 1, sizeof(header), inf.get()); if (png_sig_cmp((png_const_bytep)header, 0, 8)) { - Log.report(logvisor::Error, fmt(_SYS_STR("invalid PNG signature in '{}'")), inPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("invalid PNG signature in '{}'")), inPath.getAbsolutePath()); 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, fmt("unable to initialize libpng")); + Log.report(logvisor::Error, FMT_STRING("unable to initialize libpng")); return false; } png_infop info = png_create_info_struct(pngRead); if (!info) { - Log.report(logvisor::Error, fmt("unable to initialize libpng info")); + Log.report(logvisor::Error, FMT_STRING("unable to initialize libpng info")); png_destroy_read_struct(&pngRead, nullptr, nullptr); return false; } if (setjmp(png_jmpbuf(pngRead))) { - Log.report(logvisor::Error, fmt(_SYS_STR("unable to initialize libpng I/O for '{}'")), inPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to initialize libpng I/O for '{}'")), inPath.getAbsolutePath()); png_destroy_read_struct(&pngRead, &info, nullptr); return false; } @@ -1425,7 +1425,7 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP } if (bitDepth != 8) { - Log.report(logvisor::Error, fmt(_SYS_STR("'{}' is not 8 bits-per-channel")), inPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("'{}' is not 8 bits-per-channel")), inPath.getAbsolutePath()); png_destroy_read_struct(&pngRead, &info, nullptr); return false; } @@ -1454,7 +1454,7 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP paletteBuf = ReadPalette(pngRead, info, paletteSize); break; default: - Log.report(logvisor::Error, fmt(_SYS_STR("unsupported color type in '{}'")), inPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unsupported color type in '{}'")), inPath.getAbsolutePath()); png_destroy_read_struct(&pngRead, &info, nullptr); return false; } @@ -1472,7 +1472,7 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP bufOut.reset(new uint8_t[bufLen]); if (setjmp(png_jmpbuf(pngRead))) { - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to read image in '{}'")), inPath.getAbsolutePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to read image in '{}'")), inPath.getAbsolutePath()); png_destroy_read_struct(&pngRead, &info, nullptr); return false; } @@ -1593,7 +1593,7 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP /* Do write out */ athena::io::FileWriter outf(outPath.getAbsolutePath(), true, false); if (outf.hasError()) { - Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath()); return false; } diff --git a/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp b/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp index 85a9a8636..213528a23 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp @@ -21,6 +21,9 @@ struct ITweakPlayerRes : ITweak { ResId x18_minesBreakSecondTopIcon; ResId x1c_minesBreakSecondBottomIcon; + ResId rs5_mapArrowUp; + ResId rs5_mapArrowDown; + /* N, U, UL, L, DL, D, DR, R, UR */ std::array x24_lStick; std::array x4c_cStick; diff --git a/DataSpec/DNACommon/URDEVersionInfo.hpp b/DataSpec/DNACommon/URDEVersionInfo.hpp new file mode 100644 index 000000000..74813af4b --- /dev/null +++ b/DataSpec/DNACommon/URDEVersionInfo.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include "DataSpec/DNACommon/DNACommon.hpp" + +namespace DataSpec { +enum class ERegion { Invalid = -1, NTSC_U = 'E', PAL = 'P', NTSC_J = 'J' }; +enum class EGame { + Invalid = 0, + MetroidPrime1, + MetroidPrime2, + MetroidPrime3, +}; + +struct URDEVersionInfo : BigDNA { + AT_DECL_DNA_YAML + + String<-1> version; + Value region; + Value game; + Value isTrilogy; +}; +} // namespace DataSpec diff --git a/DataSpec/DNAMP1/ANCS.cpp b/DataSpec/DNAMP1/ANCS.cpp index 3a9337759..642da411f 100644 --- a/DataSpec/DNAMP1/ANCS.cpp +++ b/DataSpec/DNAMP1/ANCS.cpp @@ -975,9 +975,8 @@ bool ANCS::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: } 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); + btok, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force); } } @@ -988,19 +987,19 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat /* Search for yaml */ hecl::ProjectPath yamlPath = inPath.getWithExtension(_SYS_STR(".yaml"), true); if (!yamlPath.isFile()) - Log.report(logvisor::Fatal, fmt(_SYS_STR("'{}' not found as file")), yamlPath.getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("'{}' not found as file")), yamlPath.getRelativePath()); athena::io::FileReader reader(yamlPath.getAbsolutePath()); if (!reader.isOpen()) - Log.report(logvisor::Fatal, fmt(_SYS_STR("can't open '{}' for reading")), yamlPath.getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("can't open '{}' for reading")), yamlPath.getRelativePath()); if (!athena::io::ValidateFromYAMLStream(reader)) { - Log.report(logvisor::Fatal, fmt(_SYS_STR("'{}' is not urde::DNAMP1::ANCS type")), yamlPath.getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("'{}' is not urde::DNAMP1::ANCS type")), yamlPath.getRelativePath()); } athena::io::YAMLDocReader yamlReader; if (!yamlReader.parse(&reader)) { - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to parse '{}'")), yamlPath.getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to parse '{}'")), yamlPath.getRelativePath()); } ANCS ancs; ancs.read(yamlReader); @@ -1020,9 +1019,9 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat hecl::SystemStringConv chSysName(ch.name); if (!sub.cskrId.empty()) { hecl::SystemStringConv cskrSysName(sub.cskrId); - ch.cskr = inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.CSKR")), chSysName, cskrSysName)); + ch.cskr = inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.CSKR")), chSysName, cskrSysName)); } else { - ch.cskr = inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.CSKR")), chSysName)); + ch.cskr = inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.CSKR")), chSysName)); } /* Add subtype AABBs */ @@ -1048,10 +1047,10 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat if (!search->cskrId.empty()) { hecl::SystemStringConv cskrSys(search->cskrId); ch.cskrIce = inPath.ensureAuxInfo( - fmt::format(fmt(_SYS_STR("{}.{}_{}.CSKR")), chSysName, overlaySys, cskrSys)); + fmt::format(FMT_STRING(_SYS_STR("{}.{}_{}.CSKR")), chSysName, overlaySys, cskrSys)); } else { ch.cskrIce = inPath.ensureAuxInfo( - fmt::format(fmt(_SYS_STR("{}.{}.CSKR")), chSysName, overlaySys)); + fmt::format(FMT_STRING(_SYS_STR("{}.{}.CSKR")), chSysName, overlaySys)); } } } @@ -1074,9 +1073,9 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat hecl::ProjectPath pathOut; if (!act.animId.empty()) { hecl::SystemStringConv idSys(act.animId); - pathOut = inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.ANIM")), sysStr, idSys)); + pathOut = inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.ANIM")), sysStr, idSys)); } else { - inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.ANIM")), sysStr)); + inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.ANIM")), sysStr)); } prim.animId = pathOut; break; @@ -1093,9 +1092,9 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat hecl::ProjectPath pathOut; if (!act.animId.empty()) { hecl::SystemStringConv animIdSys(act.animId); - pathOut = inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.ANIM")), sysStr, animIdSys)); + pathOut = inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.ANIM")), sysStr, animIdSys)); } else { - pathOut = inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.ANIM")), sysStr)); + pathOut = inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.ANIM")), sysStr)); } ancs.animationSet.animResources.emplace_back(); @@ -1103,7 +1102,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat /* Check for associated EVNT YAML */ hecl::SystemString testPrefix(inPath.getWithExtension( - fmt::format(fmt(_SYS_STR(".{}_")), sysStr).c_str(), true).getLastComponent()); + fmt::format(FMT_STRING(_SYS_STR(".{}_")), sysStr).c_str(), true).getLastComponent()); hecl::ProjectPath evntYamlPath; for (const auto& ent : dEnum) { if (hecl::StringUtils::BeginsWith(ent.m_name, testPrefix.c_str()) && @@ -1163,7 +1162,7 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i } } if (!subtype) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to find subtype '{}'")), subName); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to find subtype '{}'")), subName); } const hecl::ProjectPath* modelPath = nullptr; @@ -1176,7 +1175,7 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i } } if (!attachment) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to find attachment '{}'")), overName); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to find attachment '{}'")), overName); modelPath = &attachment->mesh; } else if (overName.empty()) { modelPath = &subtype->mesh; @@ -1188,15 +1187,15 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i } } if (!modelPath) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to resolve model path of {}:{}")), subName, overName); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to resolve model path of {}:{}")), subName, overName); if (!modelPath->isFile()) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to resolve '{}'")), modelPath->getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to resolve '{}'")), modelPath->getRelativePath()); hecl::ProjectPath skinIntPath = modelPath->getCookedPath(SpecEntMP1).getWithExtension(_SYS_STR(".skinint")); if (!skinIntPath.isFileOrGlob() || skinIntPath.getModtime() < modelPath->getModtime()) if (!modelCookFunc(*modelPath)) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to cook '{}'")), modelPath->getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to cook '{}'")), modelPath->getRelativePath()); std::vector>, uint32_t>> skins; uint32_t posCount = 0; @@ -1221,7 +1220,7 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i const std::string& name = boneNames[bIdx]; auto search = boneIdMap.find(name); if (search == boneIdMap.cend()) - Log.report(logvisor::Fatal, fmt("unable to find bone '{}' in {}"), name, + Log.report(logvisor::Fatal, FMT_STRING("unable to find bone '{}' in {}"), name, inPath.getRelativePathUTF8()); virtualBone.first.emplace_back(search->second, weight); } @@ -1287,7 +1286,7 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath& } } if (!subtype) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to find subtype '{}'")), subName); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to find subtype '{}'")), subName); } const hecl::ProjectPath* modelPath = nullptr; @@ -1300,7 +1299,7 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath& } } if (!attachment) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to find attachment '{}'")), overName); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to find attachment '{}'")), overName); modelPath = &attachment->mesh; } else if (overName.empty()) { modelPath = &subtype->mesh; @@ -1312,15 +1311,15 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath& } } if (!modelPath) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to resolve model path of {}:{}")), subName, overName); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to resolve model path of {}:{}")), subName, overName); if (!modelPath->isFile()) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to resolve '{}'")), modelPath->getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to resolve '{}'")), modelPath->getRelativePath()); hecl::ProjectPath skinIntPath = modelPath->getCookedPath(SpecEntMP1PC).getWithExtension(_SYS_STR(".skinint")); if (!skinIntPath.isFileOrGlob() || skinIntPath.getModtime() < modelPath->getModtime()) if (!modelCookFunc(*modelPath)) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to cook '{}'")), modelPath->getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to cook '{}'")), modelPath->getRelativePath()); uint32_t bankCount = 0; std::vector> skinBanks; @@ -1360,7 +1359,7 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath& const std::string& name = boneNames[bIdx]; auto search = boneIdMap.find(name); if (search == boneIdMap.cend()) - Log.report(logvisor::Fatal, fmt("unable to find bone '{}' in {}"), name, + Log.report(logvisor::Fatal, FMT_STRING("unable to find bone '{}' in {}"), name, inPath.getRelativePathUTF8()); virtualBone.emplace_back(search->second, weight); } @@ -1381,7 +1380,7 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath& const std::string& name = boneNames[bIdx]; auto search = boneIdMap.find(name); if (search == boneIdMap.cend()) - Log.report(logvisor::Fatal, fmt("unable to find bone '{}' in {}"), name, + Log.report(logvisor::Fatal, FMT_STRING("unable to find bone '{}' in {}"), name, inPath.getRelativePathUTF8()); skinOut.writeUint32Big(search->second); } @@ -1420,7 +1419,7 @@ bool ANCS::CookANIM(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i DNAANCS::Action action = ds.compileActionChannelsOnly(actNameView.str()); if (!actor.armatures.size()) - Log.report(logvisor::Fatal, fmt(_SYS_STR("0 armatures in {}")), inPath.getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("0 armatures in {}")), inPath.getRelativePath()); /* Build bone ID map */ std::unordered_map boneIdMap; @@ -1440,7 +1439,7 @@ bool ANCS::CookANIM(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i /* Check for associated EVNT YAML */ hecl::SystemString testPrefix(inPath.getWithExtension( - fmt::format(fmt(_SYS_STR(".{}_")), actName).c_str(), true).getLastComponent()); + fmt::format(FMT_STRING(_SYS_STR(".{}_")), actName).c_str(), true).getLastComponent()); hecl::ProjectPath evntYamlPath; for (const auto& ent : hecl::DirectoryEnumerator(inPath.getParentPath().getAbsolutePath())) { if (hecl::StringUtils::BeginsWith(ent.m_name, testPrefix.c_str()) && diff --git a/DataSpec/DNAMP1/ANIM.cpp b/DataSpec/DNAMP1/ANIM.cpp index 0fce2c36a..b00bb3988 100644 --- a/DataSpec/DNAMP1/ANIM.cpp +++ b/DataSpec/DNAMP1/ANIM.cpp @@ -7,7 +7,7 @@ namespace DataSpec::DNAMP1 { using ANIMOutStream = hecl::blender::ANIMOutStream; void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig) const { - os.format(fmt( + os.format(FMT_STRING( "act.hecl_fps = round({})\n" "act.hecl_looping = {}\n"), (1.0f / mainInterval), looping ? "True" : "False"); @@ -26,7 +26,7 @@ void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANI continue; } - os.format(fmt("bone_string = '{}'\n"), *bName); + os.format(FMT_STRING("bone_string = '{}'\n"), *bName); os << "action_group = act.groups.new(bone_string)\n" "\n" "rotCurves = []\n" @@ -111,7 +111,7 @@ UniqueID32 ANIM::GetEVNTId(athena::io::IStreamReader& reader) { reader.seek(4); return reader.readUint32Big(); default: - Log.report(logvisor::Error, fmt("unrecognized ANIM version")); + Log.report(logvisor::Error, FMT_STRING("unrecognized ANIM version")); break; } return {}; @@ -134,7 +134,7 @@ void ANIM::Enumerate(typename Read::StreamT& reader) { m_anim->read(reader); break; default: - Log.report(logvisor::Error, fmt("unrecognized ANIM version")); + Log.report(logvisor::Error, FMT_STRING("unrecognized ANIM version")); break; } } @@ -559,7 +559,7 @@ ANIM::ANIM(const BlenderAction& act, const std::unordered_mapsecond) != addedBones.cend()) diff --git a/DataSpec/DNAMP1/ANIM.hpp b/DataSpec/DNAMP1/ANIM.hpp index d6a771d73..e1dda6619 100644 --- a/DataSpec/DNAMP1/ANIM.hpp +++ b/DataSpec/DNAMP1/ANIM.hpp @@ -192,7 +192,7 @@ struct ANIM : BigDNA { if (m_anim->evnt.isValid()) { hecl::SystemStringConv sysStr(animInfo.name); hecl::ProjectPath evntYamlPath = outPath.getWithExtension( - fmt::format(fmt(_SYS_STR(".{}_{}.evnt.yaml")), sysStr, m_anim->evnt).c_str(), true); + fmt::format(FMT_STRING(_SYS_STR(".{}_{}.evnt.yaml")), sysStr, m_anim->evnt).c_str(), true); hecl::ProjectPath::Type evntYamlType = evntYamlPath.getPathType(); if (force || evntYamlType == hecl::ProjectPath::Type::None) { diff --git a/DataSpec/DNAMP1/CINF.cpp b/DataSpec/DNAMP1/CINF.cpp index 974f26d10..9eec50834 100644 --- a/DataSpec/DNAMP1/CINF.cpp +++ b/DataSpec/DNAMP1/CINF.cpp @@ -34,7 +34,7 @@ void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const { for (atUint32 bid : boneIds) { for (const Name& name : names) { if (name.boneId == bid) { - os.format(fmt("obj.vertex_groups.new(name='{}')\n"), name.name); + os.format(FMT_STRING("obj.vertex_groups.new(name='{}')\n"), name.name); break; } } @@ -44,7 +44,7 @@ void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const { void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const { DNAANIM::RigInverter inverter(*this); - os.format(fmt( + os.format(FMT_STRING( "arm = bpy.data.armatures.new('CINF_{}')\n" "arm_obj = bpy.data.objects.new(arm.name, arm)\n" "bpy.context.scene.collection.objects.link(arm_obj)\n" @@ -56,7 +56,7 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c 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(fmt( + os.format(FMT_STRING( "bone = arm.edit_bones.new('{}')\n" "bone.head = ({},{},{})\n" "bone.tail = ({},{},{})\n" @@ -68,16 +68,16 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c for (const Bone& bone : bones) if (bone.parentId != 2) - os.format(fmt("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId); + os.format(FMT_STRING("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId); os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - os.format(fmt("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"), + os.format(FMT_STRING("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"), *getBoneNameFromId(bone.m_origBone.id)); } -std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return fmt::format(fmt("CINF_{}"), cinfId); } +std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return fmt::format(FMT_STRING("CINF_{}"), cinfId); } int CINF::RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId, std::unordered_map& idMap, @@ -167,7 +167,7 @@ bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: return false; auto os = conn.beginPythonOut(true); - os.format(fmt("import bpy\n" + os.format(FMT_STRING("import bpy\n" "from mathutils import Vector\n" "bpy.context.scene.name = 'CINF_{}'\n" "bpy.context.scene.hecl_arm_obj = bpy.context.scene.name\n" diff --git a/DataSpec/DNAMP1/CMDLMaterials.cpp b/DataSpec/DNAMP1/CMDLMaterials.cpp index 1d7543c3f..e8d0babd4 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.cpp +++ b/DataSpec/DNAMP1/CMDLMaterials.cpp @@ -26,7 +26,7 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t if (mtxIdx == -1) mtxLabel = "IDENTITY"; else - mtxLabel = fmt::format(fmt("MTX_{}"), mtxIdx); + mtxLabel = fmt::format(FMT_STRING("MTX_{}"), mtxIdx); std::string texLabel; if (diffuse) @@ -34,15 +34,14 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t else texLabel = "Texture"; - out.format(fmt( - "# Texture\n" - "tex_node = new_nodetree.nodes.new('ShaderNodeTexImage')\n" - "tex_node.label = '{} {}'\n" - "texture_nodes.append(tex_node)\n"), - texLabel, texIdx); + out.format(FMT_STRING("# Texture\n" + "tex_node = new_nodetree.nodes.new('ShaderNodeTexImage')\n" + "tex_node.label = '{} {}'\n" + "texture_nodes.append(tex_node)\n"), + texLabel, texIdx); if (texIdx != 0xff) - out.format(fmt("tex_node.image = tex_maps[{}]\n"), texIdx); + out.format(FMT_STRING("tex_node.image = tex_maps[{}]\n"), texIdx); if (type == GX::TG_POS) out << "tex_uv_node = new_nodetree.nodes.new('ShaderNodeTexCoord')\n" @@ -52,14 +51,13 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t "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(fmt( - "tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n" - "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" - "tex_uv_node.uv_map = 'UV_{}'\n"), - texIdx); + out.format(FMT_STRING("tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" + "tex_uv_node.uv_map = 'UV_{}'\n"), + texIdx); } - out.format(fmt("tex_uv_node.label = '{}'\n"), mtxLabel); + out.format(FMT_STRING("tex_uv_node.label = '{}'\n"), mtxLabel); out << "gridder.place_node(tex_uv_node, 0)\n" "gridder.place_node(tex_node, 0)\n" @@ -72,171 +70,162 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx, const float* vals) { switch (type) { case UVAnimation::Mode::MvInvNoTranslation: - out.format(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\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); + out.format(FMT_STRING("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\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(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\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); + out.format(FMT_STRING("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\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(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\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 = ({},{},0)\n" - " node.inputs[2].default_value = ({},{},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]); + out.format(FMT_STRING("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\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 = ({},{},0)\n" + " node.inputs[2].default_value = ({},{},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(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\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 = {}\n" - " node.inputs[2].default_value = {}\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]); + out.format(FMT_STRING("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\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 = {}\n" + " node.inputs[2].default_value = {}\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(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\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 = {}\n" - " node.inputs[2].default_value = {}\n" - " node.inputs[3].default_value = {}\n" - " node.inputs[4].default_value = {}\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]); + out.format(FMT_STRING("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\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 = {}\n" + " node.inputs[2].default_value = {}\n" + " node.inputs[3].default_value = {}\n" + " node.inputs[4].default_value = {}\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(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\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 = {}\n" - " node.inputs[2].default_value = {}\n" - " node.inputs[3].default_value = {}\n" - " node.inputs[4].default_value = {}\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]); + out.format(FMT_STRING("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\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 = {}\n" + " node.inputs[2].default_value = {}\n" + " node.inputs[3].default_value = {}\n" + " node.inputs[4].default_value = {}\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(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\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); + out.format(FMT_STRING("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\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(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\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 = {}\n" - " node.inputs[2].default_value = {}\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]); + out.format(FMT_STRING("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\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 = {}\n" + " node.inputs[2].default_value = {}\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(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\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 = {}\n" - " node.inputs[2].default_value = {}\n" - " node.inputs[3].default_value = {}\n" - " node.inputs[4].default_value = {}\n" - " node.inputs[5].default_value = {}\n" - " node.inputs[6].default_value = {}\n" - " node.inputs[7].default_value = {}\n" - " node.inputs[8].default_value = {}\n" - " node.inputs[9].default_value = {}\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]); + out.format(FMT_STRING("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\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 = {}\n" + " node.inputs[2].default_value = {}\n" + " node.inputs[3].default_value = {}\n" + " node.inputs[4].default_value = {}\n" + " node.inputs[5].default_value = {}\n" + " node.inputs[6].default_value = {}\n" + " node.inputs[7].default_value = {}\n" + " node.inputs[8].default_value = {}\n" + " node.inputs[9].default_value = {}\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; @@ -244,12 +233,12 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx, } void Material::AddKcolor(Stream& out, const GX::Color& col, unsigned idx) { - out.format(fmt( - "kcolors[{}] = ({}, {}, {}, {})\n" - "kalphas[{}] = {}\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); + out.format(FMT_STRING("kcolors[{}] = ({}, {}, {}, {})\n" + "kalphas[{}] = {}\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); } template @@ -354,15 +343,14 @@ template static void _DescribeTEV(const MAT& mat) { for (uint32_t i = 0; i < mat.tevStageCount; ++i) { const auto& stage = mat.tevStages[i]; - fmt::print(stderr, fmt("A:{} B:{} C:{} D:{} -> {} | A:{} B:{} C:{} D:{} -> {}\n"), - ToString(stage.colorInA()), ToString(stage.colorInB()), - ToString(stage.colorInC()), ToString(stage.colorInD()), ToString(stage.colorOpOutReg()), - ToString(stage.alphaInA()), ToString(stage.alphaInB()), - ToString(stage.alphaInC()), ToString(stage.alphaInD()), ToString(stage.alphaOpOutReg())); + fmt::print(stderr, FMT_STRING("A:{} B:{} C:{} D:{} -> {} | A:{} B:{} C:{} D:{} -> {}\n"), ToString(stage.colorInA()), + ToString(stage.colorInB()), ToString(stage.colorInC()), ToString(stage.colorInD()), + ToString(stage.colorOpOutReg()), ToString(stage.alphaInA()), ToString(stage.alphaInB()), + ToString(stage.alphaInC()), ToString(stage.alphaInD()), ToString(stage.alphaOpOutReg())); } bool hasInd = mat.flags.samusReflectionIndirectTexture(); bool hasLm = mat.flags.lightmap(); - fmt::print(stderr, fmt("HasIndirect: {} HasLightmap: {}\n"), hasInd, hasLm); + fmt::print(stderr, FMT_STRING("HasIndirect: {} HasLightmap: {}\n"), hasInd, hasLm); } struct TexLink { @@ -388,12 +376,10 @@ struct KColLink { struct WhiteColorLink { const char* shaderInput; - explicit WhiteColorLink(const char* shaderInput) - : shaderInput(shaderInput) {} + explicit WhiteColorLink(const char* shaderInput) : shaderInput(shaderInput) {} }; -static void _GenerateRootShader(Stream& out, int) { - /* End of shader links */ +static void _GenerateRootShader(Stream& out, int) { /* End of shader links */ } template @@ -401,8 +387,8 @@ static void _GenerateRootShader(Stream& out, int tidx, TexLink tex, Targs... arg int texIdx = tex.texidx == -1 ? tidx : tex.texidx; out << "texture_nodes[" << texIdx << "].name = '" << tex.shaderInput << "'\n"; out << "texture_nodes[" << texIdx << "].label = '" << tex.shaderInput << "'\n"; - out << "new_nodetree.links.new(texture_nodes[" << texIdx << "].outputs['" << - (tex.alpha ? "Alpha" : "Color") << "'], node.inputs['" << tex.shaderInput << "'])\n"; + out << "new_nodetree.links.new(texture_nodes[" << texIdx << "].outputs['" << (tex.alpha ? "Alpha" : "Color") + << "'], node.inputs['" << tex.shaderInput << "'])\n"; if (tex.texidx == -1) ++tidx; _GenerateRootShader(out, tidx, args...); @@ -422,8 +408,8 @@ static void _GenerateRootShader(Stream& out, int tidx, ExtendedSpecularLink tex, template static void _GenerateRootShader(Stream& out, int tidx, KColLink kcol, Targs... args) { - out << "node.inputs['" << kcol.shaderInput << "'].default_value = " << - (kcol.alpha ? "kalphas[" : "kcolors[") << kcol.kcidx << "]\n"; + out << "node.inputs['" << kcol.shaderInput << "'].default_value = " << (kcol.alpha ? "kalphas[" : "kcolors[") + << kcol.kcidx << "]\n"; _GenerateRootShader(out, tidx, args...); } @@ -437,22 +423,24 @@ template static void _GenerateRootShader(Stream& out, const char* type, Targs... args) { out << "node = new_nodetree.nodes.new('ShaderNodeGroup')\n" "node.name = 'Output'\n" - "node.node_tree = bpy.data.node_groups['" << type << "']\n" + "node.node_tree = bpy.data.node_groups['" + << type + << "']\n" "gridder.place_node(node, 1)\n" "new_nodetree.links.new(node.outputs['Surface'], blend_node.inputs['Surface'])\n"; _GenerateRootShader(out, 0, args...); } -static TexLink operator "" _tex(const char* str, size_t) { return TexLink(str); } -static TexLink operator "" _texa(const char* str, size_t) { return TexLink(str, -1, true); } -static KColLink operator "" _kcol(const char* str, size_t) { return KColLink(str); } -static KColLink operator "" _kcola(const char* str, size_t) { return KColLink(str, 0, true); } +static TexLink operator"" _tex(const char* str, size_t) { return TexLink(str); } +static TexLink operator"" _texa(const char* str, size_t) { return TexLink(str, -1, true); } +static KColLink operator"" _kcol(const char* str, size_t) { return KColLink(str); } +static KColLink operator"" _kcola(const char* str, size_t) { return KColLink(str, 0, true); } template static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupIdx, unsigned matIdx) { unsigned i; - out.format(fmt("new_material = bpy.data.materials.new('MAT_{}_{}')\n"), groupIdx, matIdx); + out.format(FMT_STRING("new_material = bpy.data.materials.new('MAT_{}_{}')\n"), groupIdx, matIdx); out << "new_material.use_fake_user = True\n" "new_material.use_nodes = True\n" "new_material.use_backface_culling = True\n" @@ -470,27 +458,26 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI "\n"; /* Material Flags */ - out.format(fmt( - "new_material.retro_depth_sort = {}\n" - "new_material.retro_alpha_test = {}\n" - "new_material.retro_samus_reflection = {}\n" - "new_material.retro_depth_write = {}\n" - "new_material.retro_samus_reflection_persp = {}\n" - "new_material.retro_shadow_occluder = {}\n" - "new_material.retro_samus_reflection_indirect = {}\n" - "new_material.retro_lightmapped = {}\n" - "new_material.diffuse_color = (1, 1, 1, {})\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() ? "0" : "1"); + out.format(FMT_STRING("new_material.retro_depth_sort = {}\n" + "new_material.retro_alpha_test = {}\n" + "new_material.retro_samus_reflection = {}\n" + "new_material.retro_depth_write = {}\n" + "new_material.retro_samus_reflection_persp = {}\n" + "new_material.retro_shadow_occluder = {}\n" + "new_material.retro_samus_reflection_indirect = {}\n" + "new_material.retro_lightmapped = {}\n" + "new_material.diffuse_color = (1, 1, 1, {})\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() ? "0" : "1"); /* Texture Indices */ out << "tex_maps = []\n"; for (atUint32 idx : material.textureIdxs) - out.format(fmt("tex_maps.append(texmap_list[{}])\n"), idx); + out.format(FMT_STRING("tex_maps.append(texmap_list[{}])\n"), idx); /* KColor entries */ if (material.flags.konstValuesEnabled()) { @@ -537,131 +524,268 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI /* Select appropriate root shader and link textures */ uint32_t hash = _HashTextureConfig(material); switch (hash) { + case 0x03FEE002: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Reflection"_tex); + break; case 0x0473AE40: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); + break; case 0x072D2CB3: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), + "Reflection"_tex); + break; + case 0x07AA75D7: /* RetroShader: Diffuse, Emissive, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 0, true)); + break; case 0x0879D346: /* RetroShader: KColorDiffuse, Alpha=Texture */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_tex); + break; case 0x0DA256BB: /* Lightmap, Diffuse, Specular, Reflection, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, + "Alpha"_kcola); + break; case 0x11C41DA4: /* RetroDynamicCharacterShader: Diffuse, DynamicMaskTex, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicCharacterShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroDynamicCharacterShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, + "Reflection"_tex); + break; case 0x1218F83E: /* RetroShader: ObjLightmap, Diffuse, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, + TexLink("Alpha", 1, true)); + break; case 0x129B8578: /* RetroShader: KColorDiffuse, Emissive, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola); + break; + case 0x15A00948: /* RetroShader: Diffuse, Emissive, Specular, ExtendedSpecular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "ExtendedSpecular"_tex, + "Reflection"_tex); + break; case 0x15A3E6E5: /* RetroShader: Diffuse, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); + break; case 0x1BEB3E15: /* RetroShader: Diffuse, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); + break; case 0x2261E0EB: /* RetroShader: Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); + break; case 0x239C7724: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); + break; case 0x240C4C84: /* RetroShader: Lightmap, KColorDiffuse, Specular, Reflection, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Specular"_tex, "Reflection"_tex, + "Alpha"_kcola); + break; case 0x2523A379: /* RetroDynamicShader: Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); + break; case 0x25E85017: /* RetroShader: Lightmap, KColorDiffuse, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); + break; case 0x27FD5C6C: /* RetroShader: ObjLightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, + TexLink("Alpha", 1, true)); + break; case 0x2AD9F535: /* RetroShader: Emissive, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); + break; case 0x2C9F5104: /* RetroShader: Diffuse, Specular, Reflection, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); + break; case 0x2D059429: /* RetroShader: Diffuse, Emissive, ExtendedSpecular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); + break; case 0x30AC64BB: /* RetroShader: Diffuse, Specular, Reflection, Alpha=KAlpha, IndirectTex */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, "Alpha"_kcola); break; - case 0x39BC4809: /* RetroDynamicShader: ObjLightmap*Dynamic, Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, + "Alpha"_kcola); + break; + case 0x39BC4809: /* RetroDynamicShader: ObjLightmap*Dynamic, Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection, + Alpha=1.0 */ + _GenerateRootShader(out, "RetroDynamicShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, + "Reflection"_tex); + break; case 0x3BF97299: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=KAlpha, IndirectTex */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, + "IndirectTex"_tex, "Alpha"_kcola); + break; + case 0x4184FBCA: /* RetroShader: Lightmap, Diffuse, Emissive, DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 1, true)); + break; case 0x47ECF3ED: /* RetroShader: Diffuse, Specular, Reflection, Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Emissive"_tex); + break; case 0x4BBDFFA6: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); + break; case 0x4D4127A3: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, + TexLink("Alpha", 1, true)); + break; case 0x54A92F25: /* RetroShader: ObjLightmap, KColorDiffuse, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); + break; + case 0x58BAA415: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */ + // TODO: Last stage assigns into unused reg2, perhaps for runtime material mod? + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); + break; case 0x54C6204C: - _GenerateRootShader(out, "RetroShader"); break; + _GenerateRootShader(out, "RetroShader"); + break; case 0x5A62D5F0: /* RetroShader: Lightmap, Diffuse, UnusedExtendedSpecular?, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; case 0x5CB59821: /* RetroShader: Diffuse, UnusedSpecular?, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); + break; case 0x5D0F0069: /* RetroShader: Diffuse, Emissive, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 0, true)); + break; case 0x5D80E53C: /* RetroShader: Emissive, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); + break; case 0x5F0AB0E9: /* RetroShader: Lightmap, Diffuse, UnusedSpecular?, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; case 0x5F189425: /* RetroShader: Lightmap, Diffuse, UnusedSpecular?, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); + break; case 0x6601D113: /* RetroShader: Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Emissive"_tex); + break; case 0x694287FA: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), + "Reflection"_tex); + break; case 0x6D98D689: /* RetroDynamicAlphaShader: Diffuse*Dynamic, Specular, Reflection, Alpha=KAlpha*Dynamic */ - _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); + break; case 0x7252CB90: /* RetroShader: Lightmap, Diffuse, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); + break; + case 0x72BEDDAC: /* RetroShader: DiffuseMod, Diffuse, Emissive, Specular, Reflection Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "DiffuseMod"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, + "Reflection"_tex); + break; case 0x76BEA57E: /* RetroShader: Lightmap, Diffuse, Emissive, Specular, Reflection, Alpha=1.0, IndirectTex */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, + "Reflection"_tex, "IndirectTex"_tex); + break; case 0x7D6A4487: /* RetroShader: Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 0, true)); + break; + case 0x81106196: /* RetroDynamicShader: Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex); + break; case 0x84319328: /* RetroShader: Reflection, UnusedSpecular?, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", WhiteColorLink("Specular"), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", WhiteColorLink("Specular"), "Reflection"_tex); + break; case 0x846215DA: /* RetroShader: Diffuse, Specular, Reflection, Alpha=DiffuseAlpha, IndirectTex */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, + TexLink("Alpha", 0, true)); + break; + case 0x8C562AB1: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); + break; case 0x8E916C01: /* RetroShader: NULL, all inputs 0 */ - _GenerateRootShader(out, "RetroShader"); break; + _GenerateRootShader(out, "RetroShader"); + break; case 0x957709F8: /* RetroShader: Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Emissive"_tex); + break; case 0x96ABB2D3: /* RetroShader: Lightmap, Diffuse, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; case 0x985A0B67: /* RetroShader: Diffuse, UnusedSpecular?, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); + break; case 0x9B4453A2: /* RetroShader: Diffuse, Emissive, ExtendedSpecular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); + break; case 0xA187C630: /* RetroShader: Diffuse, Emissive, UnusedReflection?, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); + break; + case 0xB26E9E2E: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ + // TODO: Last two stages assign into unused reg2, perhaps for runtime material mod? + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); + break; + case 0xC0E3FF1F: /* RetroShader: KColorDiffuse, Specular, Reflection, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); + break; case 0xC138DCFA: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); + break; case 0xC3C8B1C8: /* RetroShader: KColorDiffuse, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_kcola); + break; case 0xC689C8C6: /* RetroShader: Diffuse, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, + TexLink("Alpha", 0, true)); + break; case 0xC6B18B28: /* RetroShader: Diffuse, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); + break; case 0xCD92D4C5: /* RetroShader: Diffuse, Reflection, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, WhiteColorLink("Specular"), "Reflection"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, WhiteColorLink("Specular"), "Reflection"_tex, "Alpha"_kcola); + break; + case 0xCE06F3F2: /* RetroShader: Diffuse, Alpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; case 0xD73E7728: /* RetroShader: ObjLightmap, Diffuse, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; case 0xDB8F01AD: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, UnusedSpecular?, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); + break; + case 0xE64D1085: /* RetroShader: Lightmap, Diffuse, Emissive, Reflection, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Reflection"_tex, + TexLink("Alpha", 1, true)); + break; case 0xE6784B10: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha, IndirectTex */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, + "IndirectTex"_tex, TexLink("Alpha", 1, true)); + break; case 0xE68FF182: /* RetroShader: Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); + break; + case 0xE92F1340: /* RetroShader: Diffuse, Alpha=DiffuseAlpha*AlphaMod */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true), TexLink("AlphaMod", 1, true)); + break; case 0xEB4645CF: /* RetroDynamicAlphaShader: Diffuse*Dynamic, Alpha=DiffuseAlpha*Dynamic */ - _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); + break; case 0xECEF8D1F: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); + break; case 0xF1C26570: /* RetroShader: Lightmap, Diffuse, Specular, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "ExtendedSpecular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "ExtendedSpecular"_tex, + "Reflection"_tex, TexLink("Alpha", 1, true)); + break; + case 0xF345C16E: /* RetroShader: Emissive, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Emissive"_tex, "Reflection"_tex); + break; + case 0xF4DA0A86: /* RetroShader: KColorDiffuse, Emissive, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola); break; + break; case 0xF559DB08: /* RetroShader: Lightmap, Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, + "Reflection"_tex); + break; case 0xF9324367: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); + break; + case 0xFC2761B8: /* RetroShader: Lightmap, Diffuse, Alpha=DiffuseAlpha*AlphaMod */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true), + TexLink("AlphaMod", 2, true)); + break; case 0xFD95D7FD: /* RetroShader: ObjLightmap, Diffuse, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; + case 0xFFF3CEBB: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 3, true)); + break; default: _DescribeTEV(material); - Log.report(logvisor::Fatal, fmt("Unable to resolve shader hash {:08X}\n"), hash); break; + Log.report(logvisor::Fatal, FMT_STRING("Unable to resolve shader hash {:08X}\n"), hash); + break; } /* Has Lightmap? */ @@ -682,8 +806,7 @@ void MaterialSet::ConstructMaterial(Stream& out, const MaterialSet::Material& ma _ConstructMaterial(out, material, groupIdx, matIdx); } -MaterialSet::Material::Material(const hecl::blender::Material& mat, - std::vector& texPathsOut, +MaterialSet::Material::Material(const hecl::blender::Material& mat, std::vector& texPathsOut, int colorCount, bool lightmapUVs, bool matrixSkinning) { /* TODO: Rewrite for new shader rep */ XXH32_state_t xxHash; @@ -1009,7 +1132,7 @@ MaterialSet::Material::UVAnimation::UVAnimation(const std::string& gameFunction, else if (gameFunction == "RetroUVMode2Node") { mode = Mode::Scroll; if (gameArgs.size() < 2) - Log.report(logvisor::Fatal, fmt("Mode2 UV anim requires 2 vector arguments")); + Log.report(logvisor::Fatal, FMT_STRING("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]; @@ -1017,13 +1140,13 @@ MaterialSet::Material::UVAnimation::UVAnimation(const std::string& gameFunction, } else if (gameFunction == "RetroUVMode3Node") { mode = Mode::Rotation; if (gameArgs.size() < 2) - Log.report(logvisor::Fatal, fmt("Mode3 UV anim requires 2 arguments")); + Log.report(logvisor::Fatal, FMT_STRING("Mode3 UV anim requires 2 arguments")); vals[0] = gameArgs[0].simd[0]; vals[1] = gameArgs[1].simd[0]; } else if (gameFunction == "RetroUVMode4Node") { mode = Mode::HStrip; if (gameArgs.size() < 4) - Log.report(logvisor::Fatal, fmt("Mode4 UV anim requires 4 arguments")); + Log.report(logvisor::Fatal, FMT_STRING("Mode4 UV anim requires 4 arguments")); vals[0] = gameArgs[0].simd[0]; vals[1] = gameArgs[1].simd[0]; vals[2] = gameArgs[2].simd[0]; @@ -1031,7 +1154,7 @@ MaterialSet::Material::UVAnimation::UVAnimation(const std::string& gameFunction, } else if (gameFunction == "RetroUVMode5Node") { mode = Mode::VStrip; if (gameArgs.size() < 4) - Log.report(logvisor::Fatal, fmt("Mode5 UV anim requires 4 arguments")); + Log.report(logvisor::Fatal, FMT_STRING("Mode5 UV anim requires 4 arguments")); vals[0] = gameArgs[0].simd[0]; vals[1] = gameArgs[1].simd[0]; vals[2] = gameArgs[2].simd[0]; @@ -1041,11 +1164,11 @@ MaterialSet::Material::UVAnimation::UVAnimation(const std::string& gameFunction, else if (gameFunction == "RetroUVMode7NodeN") { mode = Mode::CylinderEnvironment; if (gameArgs.size() < 2) - Log.report(logvisor::Fatal, fmt("Mode7 UV anim requires 2 arguments")); + Log.report(logvisor::Fatal, FMT_STRING("Mode7 UV anim requires 2 arguments")); vals[0] = gameArgs[0].simd[0]; vals[1] = gameArgs[1].simd[0]; } else - Log.report(logvisor::Fatal, fmt("unsupported UV anim '{}'"), gameFunction); + Log.report(logvisor::Fatal, FMT_STRING("unsupported UV anim '{}'"), gameFunction); } template @@ -1090,7 +1213,6 @@ void HMDLMaterialSet::Material::PASS::Enumerate(typename Op::StreamT& s) { AT_SPECIALIZE_DNA(HMDLMaterialSet::Material::PASS) - std::string_view HMDLMaterialSet::Material::PASS::DNAType() { return "DataSpec::DNAMP1::HMDLMaterialSet::Material::PASS"sv; } diff --git a/DataSpec/DNAMP1/CMDLMaterials.hpp b/DataSpec/DNAMP1/CMDLMaterials.hpp index 78744e4d3..2a1e3269f 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.hpp +++ b/DataSpec/DNAMP1/CMDLMaterials.hpp @@ -506,9 +506,9 @@ struct MaterialSet : BigDNA { continue; } if (setIdx < 0) - texEntry->name = fmt::format(fmt("{}_{}_{}"), prefix, matIdx, stageIdx); + texEntry->name = fmt::format(FMT_STRING("{}_{}_{}"), prefix, matIdx, stageIdx); else - texEntry->name = fmt::format(fmt("{}_{}_{}_{}"), prefix, setIdx, matIdx, stageIdx); + texEntry->name = fmt::format(FMT_STRING("{}_{}_{}_{}"), prefix, setIdx, matIdx, stageIdx); if (mat.flags.lightmap() && stageIdx == 0) { texEntry->name += "light"; diff --git a/DataSpec/DNAMP1/CMakeLists.txt b/DataSpec/DNAMP1/CMakeLists.txt index 3520e76c4..51ebe4bfe 100644 --- a/DataSpec/DNAMP1/CMakeLists.txt +++ b/DataSpec/DNAMP1/CMakeLists.txt @@ -11,7 +11,6 @@ make_dnalist(PAK CINF CSKR EVNT - PATH CMDLMaterials MREA DeafBabe @@ -50,7 +49,7 @@ set(DNAMP1_SOURCES ANIM.cpp CINF.cpp EVNT.cpp - PATH.cpp + PATH.hpp CMDL.hpp CMDL.cpp CMDLMaterials.cpp DCLN.cpp diff --git a/DataSpec/DNAMP1/CSKR.cpp b/DataSpec/DNAMP1/CSKR.cpp index df5139dd9..7c4083a11 100644 --- a/DataSpec/DNAMP1/CSKR.cpp +++ b/DataSpec/DNAMP1/CSKR.cpp @@ -8,7 +8,7 @@ void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint for (const SkinningRule& rule : skinningRules) { if (idx >= accum && idx < accum + rule.vertCount) for (const SkinningRule::Weight& weight : rule.weights) - os.format(fmt("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight); + os.format(FMT_STRING("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight); accum += rule.vertCount; } } diff --git a/DataSpec/DNAMP1/CSNG.cpp b/DataSpec/DNAMP1/CSNG.cpp index 5138a0d3b..9fb3f2fdc 100644 --- a/DataSpec/DNAMP1/CSNG.cpp +++ b/DataSpec/DNAMP1/CSNG.cpp @@ -44,8 +44,8 @@ bool CSNG::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { r.emplace(songsPath.getAbsolutePath()); athena::io::YAMLDocWriter ydw("amuse::Songs", r ? &*r : nullptr); r = std::nullopt; - ydw.writeString(fmt::format(fmt("{:04X}"), head.midiSetupId), - fmt::format(fmt("../MidiData/{}"), midPath.getLastComponentUTF8())); + ydw.writeString(fmt::format(FMT_STRING("{:04X}"), head.midiSetupId), + fmt::format(FMT_STRING("../MidiData/{}"), midPath.getLastComponentUTF8())); athena::io::FileWriter w(songsPath.getAbsolutePath()); ydw.finish(&w); diff --git a/DataSpec/DNAMP1/DCLN.cpp b/DataSpec/DNAMP1/DCLN.cpp index 8d1496450..383056e8a 100644 --- a/DataSpec/DNAMP1/DCLN.cpp +++ b/DataSpec/DNAMP1/DCLN.cpp @@ -30,7 +30,7 @@ void DCLN::Collision::Node::sendToBlender(hecl::blender::PyOutStream& os) const 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(fmt( + os.format(FMT_STRING( "import bpy\n" "import bmesh\n" "from mathutils import Vector, Matrix\n" diff --git a/DataSpec/DNAMP1/DNAMP1.cpp b/DataSpec/DNAMP1/DNAMP1.cpp index 386059ff9..30704552c 100644 --- a/DataSpec/DNAMP1/DNAMP1.cpp +++ b/DataSpec/DNAMP1/DNAMP1.cpp @@ -30,6 +30,7 @@ #include "PATH.hpp" #include "DataSpec/DNACommon/Tweaks/TweakWriter.hpp" +#include "DataSpec/DNACommon/URDEVersionInfo.hpp" #include "Tweaks/CTweakPlayerRes.hpp" #include "Tweaks/CTweakGunRes.hpp" #include "Tweaks/CTweakPlayer.hpp" @@ -154,7 +155,7 @@ void PAKBridge::build() { std::string idStr = area.areaMREAId.toString(); areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str(); } - hecl::SystemString num = fmt::format(fmt(_SYS_STR("{:02d} ")), ai); + hecl::SystemString num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), ai); areaDeps.name = num + areaDeps.name; std::string lowerName(hecl::SystemUTF8Conv(areaDeps.name).str()); @@ -178,7 +179,7 @@ void PAKBridge::build() { layer.active = layerFlags.flags >> (l - 1) & 0x1; layer.name = hecl::StringUtils::TrimWhitespace(layer.name); - num = fmt::format(fmt(_SYS_STR("{:02d} ")), l - 1); + num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), l - 1); layer.name = num + layer.name; layer.resources.reserve(area.depLayers[l] - r); @@ -210,35 +211,35 @@ void PAKBridge::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssoci for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) { charAssoc.m_cmdlRigs[ci.cmdl] = {ci.cskr, ci.cinf}; charAssoc.m_cskrToCharacter[ci.cskr] = - std::make_pair(entry.id, fmt::format(fmt("{}_{}.CSKR"), ci.name, ci.cskr)); + std::make_pair(entry.id, fmt::format(FMT_STRING("{}_{}.CSKR"), ci.name, ci.cskr)); 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 = fmt::format(fmt("ANCS_{}_{}_model"), id, ci.name); - cskrEnt->name = fmt::format(fmt("ANCS_{}_{}_skin"), id, ci.name); - cinfEnt->name = fmt::format(fmt("ANCS_{}_{}_skel"), id, ci.name); + cmdlEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_model"), id, ci.name); + cskrEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_skin"), id, ci.name); + cinfEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_skel"), id, ci.name); if (ci.cmdlIce.isValid() && ci.cskrIce.isValid()) { charAssoc.m_cmdlRigs[ci.cmdlIce] = {ci.cskrIce, ci.cinf}; charAssoc.m_cskrToCharacter[ci.cskrIce] = - std::make_pair(entry.id, fmt::format(fmt("{}.ICE_{}.CSKR"), ci.name, ci.cskrIce)); + std::make_pair(entry.id, fmt::format(FMT_STRING("{}.ICE_{}.CSKR"), ci.name, ci.cskrIce)); PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdlIce); PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskrIce); - cmdlEnt->name = fmt::format(fmt("ANCS_{}_{}_icemodel"), id, ci.name); - cskrEnt->name = fmt::format(fmt("ANCS_{}_{}_iceskin"), id, ci.name); + cmdlEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_icemodel"), id, ci.name); + cskrEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_iceskin"), id, ci.name); } } std::map> animInfo; ancs.getAnimationResInfo(&pakRouter, animInfo); for (auto& [animIdx, animResInfo] : animInfo) { PAK::Entry* animEnt = (PAK::Entry*)m_pak.lookupEntry(animResInfo.animId); - animEnt->name = fmt::format(fmt("ANCS_{}_{}"), id, animResInfo.name); + animEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}"), id, animResInfo.name); charAssoc.m_cskrToCharacter[animResInfo.animId] = - std::make_pair(entry.id, fmt::format(fmt("{}_{}.ANIM"), animResInfo.name, animResInfo.animId)); + std::make_pair(entry.id, fmt::format(FMT_STRING("{}_{}.ANIM"), animResInfo.name, animResInfo.animId)); if (animResInfo.evntId.isValid()) { PAK::Entry* evntEnt = (PAK::Entry*)m_pak.lookupEntry(animResInfo.evntId); - evntEnt->name = fmt::format(fmt("ANCS_{}_{}_evnt"), id, animResInfo.name); - charAssoc.m_cskrToCharacter[animResInfo.evntId] = - std::make_pair(entry.id, fmt::format(fmt("{}_{}.evnt.yaml"), animResInfo.name, animResInfo.evntId)); + evntEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_evnt"), id, animResInfo.name); + charAssoc.m_cskrToCharacter[animResInfo.evntId] = std::make_pair( + entry.id, fmt::format(FMT_STRING("{}_{}.evnt.yaml"), animResInfo.name, animResInfo.evntId)); } } } else if (entry.type == FOURCC('MREA')) { @@ -275,8 +276,8 @@ void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry).getParentPath(); if (mlvl.worldNameId.isValid()) - pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, - fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId)); + pathOverrides[mlvl.worldNameId] = + hecl::ProjectPath(mlvlDirPath, fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId)); for (const MLVL::Area& area : mlvl.areas) { { @@ -292,8 +293,8 @@ void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath(); if (area.areaNameId.isValid()) - pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, - fmt::format(fmt(_SYS_STR("!name_{}.yaml")), area.areaNameId)); + pathOverrides[area.areaNameId] = + hecl::ProjectPath(areaDirPath, fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), area.areaNameId)); } if (mlvl.worldMap.isValid()) { @@ -383,8 +384,14 @@ ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, con std::string catalogueName; std::string name = pak.bestEntryName(pakNode, entry, catalogueName); if (!catalogueName.empty()) { - if (catalogueName == "PlayerRes"sv) - return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (catalogueName == "PlayerRes"sv) { + if (isCurrentSpecWii() || getCurrentRegion() == ERegion::PAL || getCurrentRegion() == ERegion::NTSC_J) { + /* We need to use the new rep for these tweaks */ + return {ExtractTweak>, {_SYS_STR(".yaml")}}; + } + /* We need to use the old rep for these tweaks */ + return {ExtractTweak>, {_SYS_STR(".yaml")}}; + } if (catalogueName == "GunRes"sv) return {ExtractTweak, {_SYS_STR(".yaml")}}; if (catalogueName == "Player"sv) @@ -395,8 +402,14 @@ ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, con return {ExtractTweak, {_SYS_STR(".yaml")}}; if (catalogueName == "Game"sv) return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (catalogueName == "Targeting"sv) - return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (catalogueName == "Targeting"sv) { + if (isCurrentSpecWii() || getCurrentRegion() == ERegion::PAL || getCurrentRegion() == ERegion::NTSC_J) { + /* We need to use the new rep for these tweaks */ + return {ExtractTweak>, {_SYS_STR(".yaml")}}; + } + /* We need to use the old rep for these tweaks */ + return {ExtractTweak>, {_SYS_STR(".yaml")}}; + } if (catalogueName == "Gui"sv) return {ExtractTweak, {_SYS_STR(".yaml")}}; if (catalogueName == "AutoMapper"sv) diff --git a/DataSpec/DNAMP1/FRME.cpp b/DataSpec/DNAMP1/FRME.cpp index 4fdced531..16b83bbcc 100644 --- a/DataSpec/DNAMP1/FRME.cpp +++ b/DataSpec/DNAMP1/FRME.cpp @@ -93,7 +93,7 @@ void FRME::Widget::Enumerate(athena::io::IStreamReader& __dna_read widgetInfo = std::make_unique(); break; default: - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unsupported FRME widget type {}")), type); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unsupported FRME widget type {}")), type); } /* widgetInfo */ @@ -174,7 +174,7 @@ void FRME::Widget::CAMRInfo::Enumerate(athena::io::IStreamReader& } else if (projectionType == ProjectionType::Orthographic) { projection = std::make_unique(); } else { - Log.report(logvisor::Fatal, fmt(_SYS_STR("Invalid CAMR projection mode! {}")), int(projectionType)); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Invalid CAMR projection mode! {}")), int(projectionType)); } projection->read(__dna_reader); @@ -183,9 +183,9 @@ void FRME::Widget::CAMRInfo::Enumerate(athena::io::IStreamReader& template <> void FRME::Widget::CAMRInfo::Enumerate(athena::io::IStreamWriter& __dna_writer) { if (!projection) - Log.report(logvisor::Fatal, fmt(_SYS_STR("Invalid CAMR projection object!"))); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Invalid CAMR projection object!"))); if (projection->type != projectionType) - Log.report(logvisor::Fatal, fmt(_SYS_STR("CAMR projection type does not match actual projection type!"))); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("CAMR projection type does not match actual projection type!"))); __dna_writer.writeUint32Big(atUint32(projectionType)); projection->write(__dna_writer); @@ -306,7 +306,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: " bpy.context.scene.collection.objects.link(ob_new)\n" " return ob_new\n"; - os.format(fmt( + os.format(FMT_STRING( "bpy.context.scene.name = '{}'\n" "bpy.context.scene.render.resolution_x = 640\n" "bpy.context.scene.render.resolution_y = 480\n" @@ -321,7 +321,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: "angle = Quaternion((1.0, 0.0, 0.0), 0)\n"; if (w.type == SBIG('CAMR')) { using CAMRInfo = Widget::CAMRInfo; - os.format(fmt( + os.format(FMT_STRING( "cam = bpy.data.cameras.new(name='{}')\n" "binding = cam\n"), w.header.name); @@ -329,7 +329,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: if (info->projectionType == CAMRInfo::ProjectionType::Orthographic) { CAMRInfo::OrthographicProjection* proj = static_cast(info->projection.get()); - os.format(fmt( + os.format(FMT_STRING( "cam.type = 'ORTHO'\n" "cam.ortho_scale = {}\n" "cam.clip_start = {}\n" @@ -337,7 +337,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: 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(fmt( + os.format(FMT_STRING( "cam.type = 'PERSP'\n" "cam.lens_unit = 'FOV'\n" "cam.clip_start = {}\n" @@ -345,10 +345,10 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: "bpy.context.scene.render.resolution_x = 480 * {}\n"), proj->znear, proj->zfar, proj->aspect); if (proj->aspect > 1.f) - os.format(fmt("cam.angle = math.atan2({}, 1.0 / math.tan(math.radians({} / 2.0))) * 2.0\n"), proj->aspect, + os.format(FMT_STRING("cam.angle = math.atan2({}, 1.0 / math.tan(math.radians({} / 2.0))) * 2.0\n"), proj->aspect, proj->fov); else - os.format(fmt("cam.angle = math.radians({})\n"), proj->fov); + os.format(FMT_STRING("cam.angle = math.radians({})\n"), proj->fov); } } os << "angle = Quaternion((1.0, 0.0, 0.0), math.radians(90.0))\n"; @@ -358,7 +358,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: switch (info->type) { case LITEInfo::ELightType::LocalAmbient: { zeus::simd_floats colorF(w.header.color.simd); - os.format(fmt( + os.format(FMT_STRING( "bg_node.inputs[0].default_value = ({},{},{},1.0)\n" "bg_node.inputs[1].default_value = {}\n"), colorF[0], colorF[1], colorF[2], info->distQ / 8.0); @@ -370,7 +370,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: [[fallthrough]]; default: { zeus::simd_floats colorF(w.header.color.simd); - os.format(fmt( + os.format(FMT_STRING( "lamp = bpy.data.lights.new(name='{}', type='POINT')\n" "lamp.color = ({}, {}, {})\n" "lamp.hecl_falloff_constant = {}\n" @@ -384,7 +384,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: w.header.name, 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(fmt( + os.format(FMT_STRING( "lamp.type = 'SPOT'\n" "lamp.spot_size = {}\n"), info->cutoff); @@ -413,7 +413,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: if (resPath.size()) { hecl::SystemUTF8Conv resPathView(resPath); - os.format(fmt( + os.format(FMT_STRING( "if '{}' in bpy.data.images:\n" " image = bpy.data.images['{}']\n" "else:\n" @@ -424,7 +424,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: os << "image = None\n"; } - os.format(fmt( + os.format(FMT_STRING( "material = bpy.data.materials.new('{}')\n" "material.use_nodes = True\n" "new_nodetree = material.node_tree\n" @@ -445,7 +445,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: else ti = i; zeus::simd_floats f(info->quadCoords[ti].simd); - os.format(fmt("verts.append(bm.verts.new(({},{},{})))\n"), f[0], f[1], f[2]); + os.format(FMT_STRING("verts.append(bm.verts.new(({},{},{})))\n"), f[0], f[1], f[2]); } os << "bm.faces.new(verts)\n" "bm.loops.layers.uv.new('UV')\n" @@ -459,9 +459,9 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: else ti = i; zeus::simd_floats f(info->uvCoords[ti].simd); - os.format(fmt("bm.verts[{}].link_loops[0][bm.loops.layers.uv[0]].uv = ({},{})\n"), i, f[0], f[1]); + os.format(FMT_STRING("bm.verts[{}].link_loops[0][bm.loops.layers.uv[0]].uv = ({},{})\n"), i, f[0], f[1]); } - os.format(fmt( + os.format(FMT_STRING( "binding = bpy.data.meshes.new('{}')\n" "bm.to_mesh(binding)\n" "bm.free()\n" @@ -471,7 +471,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: } zeus::simd_floats colorF(w.header.color.simd); - os.format(fmt( + os.format(FMT_STRING( "frme_obj = bpy.data.objects.new(name='{}', object_data=binding)\n" "frme_obj.pass_index = {}\n" "parentName = '{}'\n" @@ -501,7 +501,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: os.linkMesh(modelPath.getAbsolutePathUTF8(), pakRouter.getBestEntryName(*cmdlE)); - os.format(fmt("frme_obj.retro_model_light_mask = {}\n"), info->lightMask); + os.format(FMT_STRING("frme_obj.retro_model_light_mask = {}\n"), info->lightMask); os << "print(obj.name)\n" "copy_obj = duplicateObject(obj)\n" "copy_obj.parent = frme_obj\n" @@ -516,7 +516,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: using PANEInfo = Widget::PANEInfo; if (PANEInfo* info = static_cast(w.widgetInfo.get())) { zeus::simd_floats f(info->scaleCenter.simd); - os.format(fmt( + os.format(FMT_STRING( "frme_obj.retro_pane_dimensions = ({},{})\n" "frme_obj.retro_pane_scale_center = ({},{},{})\n"), info->xDim, info->zDim, f[0], f[1], f[2]); @@ -533,7 +533,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: zeus::simd_floats fillF(info->fillColor.simd); zeus::simd_floats outlineF(info->outlineColor.simd); zeus::simd_floats extentF(info->blockExtent.simd); - os.format(fmt( + os.format(FMT_STRING( "frme_obj.retro_pane_dimensions = ({},{})\n" "frme_obj.retro_pane_scale_center = ({},{},{})\n" "frme_obj.retro_textpane_font_path = '{}'\n" @@ -557,7 +557,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: } else if (w.type == SBIG('TBGP')) { using TBGPInfo = Widget::TBGPInfo; if (TBGPInfo* info = static_cast(w.widgetInfo.get())) { - os.format(fmt( + os.format(FMT_STRING( "frme_obj.retro_tablegroup_elem_count = {}\n" "frme_obj.retro_tablegroup_elem_default = {}\n" "frme_obj.retro_tablegroup_wraparound = {}\n"), @@ -566,12 +566,12 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: } else if (w.type == SBIG('GRUP')) { using GRUPInfo = Widget::GRUPInfo; if (GRUPInfo* info = static_cast(w.widgetInfo.get())) { - os.format(fmt("frme_obj.retro_group_default_worker = {}\n"), info->defaultWorker); + os.format(FMT_STRING("frme_obj.retro_group_default_worker = {}\n"), info->defaultWorker); } } else if (w.type == SBIG('SLGP')) { using SLGPInfo = Widget::SLGPInfo; if (SLGPInfo* info = static_cast(w.widgetInfo.get())) { - os.format(fmt( + os.format(FMT_STRING( "frme_obj.retro_slider_min = {}\n" "frme_obj.retro_slider_max = {}\n" "frme_obj.retro_slider_default = {}\n" @@ -583,12 +583,12 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: if (ENRGInfo* info = static_cast(w.widgetInfo.get())) { hecl::ProjectPath txtrPath = pakRouter.getWorking(info->texture); if (txtrPath) - os.format(fmt("frme_obj.retro_energybar_texture_path = '{}'\n"), txtrPath.getRelativePathUTF8()); + os.format(FMT_STRING("frme_obj.retro_energybar_texture_path = '{}'\n"), txtrPath.getRelativePathUTF8()); } } else if (w.type == SBIG('METR')) { using METRInfo = Widget::METRInfo; if (METRInfo* info = static_cast(w.widgetInfo.get())) { - os.format(fmt( + os.format(FMT_STRING( "frme_obj.retro_meter_no_round_up = {}\n" "frme_obj.retro_meter_max_capacity = {}\n" "frme_obj.retro_meter_worker_count = {}\n"), @@ -600,7 +600,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: for (int i = 0; i < 3; ++i) w.basis[i].simd.copy_to(xfMtxF[i]); zeus::simd_floats originF(w.origin.simd); - os.format(fmt( + os.format(FMT_STRING( "mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n" "mtxd = mtx.decompose()\n" "frme_obj.rotation_mode = 'QUATERNION'\n" diff --git a/DataSpec/DNAMP1/MLVL.cpp b/DataSpec/DNAMP1/MLVL.cpp index 5e447ea3d..4eb5c1ee4 100644 --- a/DataSpec/DNAMP1/MLVL.cpp +++ b/DataSpec/DNAMP1/MLVL.cpp @@ -137,7 +137,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat if (!areaPath.isFile()) continue; - Log.report(logvisor::Info, fmt(_SYS_STR("Visiting {}")), area.path.getRelativePath()); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Visiting {}")), area.path.getRelativePath()); hecl::ProjectPath memRelayPath(area.path, _SYS_STR("!memoryrelays.yaml")); @@ -311,7 +311,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat } if (!areaInit) - Log.report(logvisor::Info, fmt(_SYS_STR("No layer directories for area {}")), area.path.getRelativePath()); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("No layer directories for area {}")), area.path.getRelativePath()); /* Build deplist */ MLVL::Area& areaOut = mlvl.areas.back(); diff --git a/DataSpec/DNAMP1/MREA.cpp b/DataSpec/DNAMP1/MREA.cpp index 89c9e4f0a..2babb2763 100644 --- a/DataSpec/DNAMP1/MREA.cpp +++ b/DataSpec/DNAMP1/MREA.cpp @@ -20,7 +20,7 @@ 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, fmt("invalid BABEDEAD magic")); + Log.report(logvisor::Fatal, FMT_STRING("invalid BABEDEAD magic")); os << "bpy.context.scene.world.use_nodes = True\n" "bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n" "bg_node.inputs[1].default_value = 0.0\n"; @@ -202,7 +202,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: "from mathutils import Vector\n" "bpy.context.scene.render.fps = 60\n" "\n"; - os.format(fmt("bpy.context.scene.name = '{}'\n"), + os.format(FMT_STRING("bpy.context.scene.name = '{}'\n"), pakRouter.getBestEntryName(entry, false)); DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath()); MaterialSet::RegisterMaterialProps(os); @@ -244,7 +244,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: rs.seek(secStart + head.secSizes[curSec++], athena::SeekOrigin::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(fmt( + os.format(FMT_STRING( "obj.retro_disable_enviro_visor = {}\n" "obj.retro_disable_thermal_visor = {}\n" "obj.retro_disable_xray_visor = {}\n" @@ -314,7 +314,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: "bpy.context.view_layer.layer_collection.children['Collision'].hide_viewport = True\n"; /* Link MLVL scene as background */ - os.linkBackground(fmt::format(fmt("//../!world_{}.blend"), + os.linkBackground(fmt::format(FMT_STRING("//../!world_{}.blend"), pakRouter.getCurrentBridge().getLevelId()), "World"sv); os.centerView(); @@ -332,7 +332,7 @@ void MREA::Name(const SpecBase& dataSpec, PAKEntryReadStream& rs, PAKRouter(GetCurrentProcess())); + parPid = fmt::format(FMT_STRING(_SYS_STR("{}")), reinterpret_cast(GetCurrentProcess())); #else - parPid = fmt::format(fmt(_SYS_STR("{}")), (unsigned long long)getpid()); + parPid = fmt::format(FMT_STRING(_SYS_STR("{}")), (unsigned long long)getpid()); #endif const hecl::SystemChar* args[] = {VisiGenPath.c_str(), visiIntOut.getAbsolutePath().data(), @@ -720,7 +720,7 @@ bool MREA::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat r.readBytesToBuf(secs.back().data(), length); visiGood = true; } else { - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to launch {}")), VisiGenPath); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to launch {}")), VisiGenPath); } } #endif diff --git a/DataSpec/DNAMP1/PAK.cpp b/DataSpec/DNAMP1/PAK.cpp index 4b7835662..516f6b110 100644 --- a/DataSpec/DNAMP1/PAK.cpp +++ b/DataSpec/DNAMP1/PAK.cpp @@ -10,7 +10,7 @@ template <> void PAK::Enumerate(typename Read::StreamT& reader) { atUint32 version = reader.readUint32Big(); if (version != 0x00030005) - Log.report(logvisor::Fatal, fmt("unexpected PAK magic")); + Log.report(logvisor::Fatal, FMT_STRING("unexpected PAK magic")); reader.readUint32Big(); atUint32 nameCount = reader.readUint32Big(); @@ -147,6 +147,7 @@ const PAK::Entry* PAK::lookupEntry(const UniqueID32& id) const { } const PAK::Entry* PAK::lookupEntry(std::string_view name) const { + // TODO: Heterogeneous lookup when C++20 available auto result = m_nameMap.find(name.data()); if (result != m_nameMap.end()) { auto result1 = m_entries.find(result->second); @@ -164,19 +165,19 @@ std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, std AGSC::Header header; header.read(rs); catalogueName = header.groupName; - return fmt::format(fmt("{}_{}"), header.groupName, entry.id); + return fmt::format(FMT_STRING("{}_{}"), header.groupName, entry.id); } /* Prefer named entries first */ for (const NameEntry& nentry : m_nameEntries) { if (nentry.id == entry.id) { catalogueName = nentry.name; - return fmt::format(fmt("{}_{}"), nentry.name, entry.id); + return fmt::format(FMT_STRING("{}_{}"), nentry.name, entry.id); } } /* Otherwise return ID format string */ - return fmt::format(fmt("{}_{}"), entry.type, entry.id); + return fmt::format(FMT_STRING("{}_{}"), entry.type, entry.id); } } // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/PATH.cpp b/DataSpec/DNAMP1/PATH.cpp deleted file mode 100644 index 506995484..000000000 --- a/DataSpec/DNAMP1/PATH.cpp +++ /dev/null @@ -1,244 +0,0 @@ -#include "PATH.hpp" -#include "hecl/Blender/Connection.hpp" -#include "zeus/CAABox.hpp" -#include "DataSpec/DNACommon/AROTBuilder.hpp" - -namespace DataSpec::DNAMP1 { - -#define DUMP_OCTREE 0 - -#if DUMP_OCTREE -/* octree dumper */ -static void OutputOctreeNode(hecl::blender::PyOutStream& os, int idx, const zeus::CAABox& aabb) { - const zeus::CVector3f pos = aabb.center(); - const zeus::CVector3f extent = aabb.extents(); - os.format( - "obj = bpy.data.objects.new('Leaf_%d', None)\n" - "bpy.context.scene.collection.objects.link(obj)\n" - "obj.location = (%f,%f,%f)\n" - "obj.scale = (%f,%f,%f)\n" - "obj.empty_display_type = 'CUBE'\n" - "obj.layers[1] = True\n" - "obj.layers[0] = False\n", idx, - pos.x(), pos.y(), pos.z(), extent.x(), extent.y(), extent.z()); -} -#endif - -void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf, - const std::string& areaPath) { - /* Open Py Stream and read sections */ - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os << - "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, 1.0)\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, 1.0)\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, 1.0)\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"; - os.format(fmt("bpy.context.scene.name = '{}'\n"), entryName); - os << - "# Clear Scene\n" - "if len(bpy.data.collections):\n" - " bpy.data.collections.remove(bpy.data.collections[0])\n" - "\n" - "bm = bmesh.new()\n" - "height_lay = bm.faces.layers.float.new('Height')\n"; - - for (const Node& n : nodes) { - zeus::simd_floats f(n.position.simd); - os.format(fmt("bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]); - } - - os << "bm.verts.ensure_lookup_table()\n"; - - for (const Region& r : regions) { - os << "tri_verts = []\n"; - for (atUint32 i = 0; i < r.nodeCount; ++i) - os.format(fmt("tri_verts.append(bm.verts[{}])\n"), r.nodeStart + i); - - os.format(fmt( - "face = bm.faces.get(tri_verts)\n" - "if face is None:\n" - " face = bm.faces.new(tri_verts)\n" - " face.normal_flip()\n" - "face.material_index = select_material(0x{:04X}, 0x{:04X})\n" - "face.smooth = False\n" - "face[height_lay] = {}\n" - "\n"), - r.meshIndexMask, r.meshTypeMask, r.height); - -#if 0 - const zeus::CVector3f center = xf->multiplyOneOverW(r.centroid); - zeus::CAABox aabb(xf->multiplyOneOverW(r.aabb[0]), xf->multiplyOneOverW(r.aabb[1])); - os.format(fmt("aabb = bpy.data.objects.new('AABB', None)\n") - "aabb.location = (%f,%f,%f)\n" - "aabb.scale = (%f,%f,%f)\n" - "aabb.empty_display_type = 'CUBE'\n" - "bpy.context.scene.collection.objects.link(aabb)\n" - "centr = bpy.data.objects.new('Center', None)\n" - "centr.location = (%f,%f,%f)\n" - "bpy.context.scene.collection.objects.link(centr)\n", - aabb.min[0] + (aabb.max[0] - aabb.min[0]) / 2.f, - aabb.min[1] + (aabb.max[1] - aabb.min[1]) / 2.f, - aabb.min[2] + (aabb.max[2] - aabb.min[2]) / 2.f, - (aabb.max[0] - aabb.min[0]) / 2.f, - (aabb.max[1] - aabb.min[1]) / 2.f, - (aabb.max[2] - aabb.min[2]) / 2.f, - center.x(), center.y(), center.z()); -#endif - } - -#if 0 - for (const Node& n : nodes) { - zeus::simd_floats f(n.position.simd); - zeus::simd_floats no(n.position.simd + n.normal.simd); - os.format(fmt("v = bm.verts.new((%f,%f,%f))\n") - "v2 = bm.verts.new((%f,%f,%f))\n" - "bm.edges.new((v, v2))\n", f[0], f[1], f[2], no[0], no[1], no[2]); - } -#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.collection.objects.link(path_mesh_obj)\n" - "path_mesh_obj.display_type = 'SOLID'\n" - "bpy.context.scene.hecl_path_obj = path_mesh_obj.name\n" - "\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(fmt( - "mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(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 DUMP_OCTREE - { - int idx = 0; - for (const auto& n : octree) { - if (n.isLeaf) - OutputOctreeNode(os, idx, zeus::CAABox(n.aabb[0], n.aabb[1])); - ++idx; - } - } -#endif - - os.linkBackground(fmt::format(fmt("//{}"), areaPath)); - 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; - - std::string areaPath; - for (const auto& ent : hecl::DirectoryEnumerator(outPath.getParentPath().getAbsolutePath())) { - if (hecl::StringUtils::BeginsWith(ent.m_name, _SYS_STR("!area_"))) { - areaPath = hecl::SystemUTF8Conv(ent.m_name).str(); - break; - } - } - - const zeus::CMatrix4f* xf = pakRouter.lookupMAPATransform(entry.id); - path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf, areaPath); - return conn.saveBlend(); -} - -bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, - const PathMesh& mesh, hecl::blender::Token& btok) { - 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; - } - -#if DUMP_OCTREE - { - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".octree.blend"), true), hecl::blender::BlendType::PathMesh)) - return false; - - zeus::CMatrix4f xf; - path.sendToBlender(conn, "PATH"sv, &xf); - conn.saveBlend(); - } -#endif - - 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; -} - -} // namespace DataSpec::DNAMP1 \ No newline at end of file diff --git a/DataSpec/DNAMP1/PATH.hpp b/DataSpec/DNAMP1/PATH.hpp index 284a27fa0..07f0179f8 100644 --- a/DataSpec/DNAMP1/PATH.hpp +++ b/DataSpec/DNAMP1/PATH.hpp @@ -1,79 +1,6 @@ #pragma once - -#include "DataSpec/DNACommon/DNACommon.hpp" -#include "DataSpec/DNACommon/PAK.hpp" -#include "DNAMP1.hpp" +#include "DataSpec/DNACommon/PATH.hpp" namespace DataSpec::DNAMP1 { -struct PATH : BigDNA { - using PathMesh = hecl::blender::PathMesh; - - AT_DECL_DNA - Value version; - - struct Node : BigDNA { - AT_DECL_DNA - Value position; - Value normal; - }; - Value nodeCount; - Vector nodes; - - 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; - Value nodeStart; - Value linkCount; - Value linkStart; - Value meshIndexMask; - Value meshTypeMask; - Value height; - Value normal; - Value regionIdx; - Value centroid; - Value aabb[2]; - Value regionIdxPtr; - }; - Value regionCount; - Vector regions; - - 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; - Value regionStart; - }; - Value octreeNodeCount; - Vector octree; - - void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf, - const std::string& areaPath); - - 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 PathMesh& mesh, hecl::blender::Token& btok); -}; +using PATH = DNAPATH::PATH; } // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/SCAN.hpp b/DataSpec/DNAMP1/SCAN.hpp index 701070ddd..f806fe69d 100644 --- a/DataSpec/DNAMP1/SCAN.hpp +++ b/DataSpec/DNAMP1/SCAN.hpp @@ -87,13 +87,13 @@ struct SCAN : BigDNA { scan.read(rs); if (scan.string.isValid()) { PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(scan.string); - ent->name = fmt::format(fmt("SCAN_{}_strg"), entry.id); + ent->name = fmt::format(FMT_STRING("SCAN_{}_strg"), entry.id); } for (int i = 0; i < 4; ++i) { const Texture& tex = scan.textures[i]; if (tex.texture.isValid()) { PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(tex.texture); - ent->name = fmt::format(fmt("SCAN_{}_tex{}"), entry.id, i + 1); + ent->name = fmt::format(FMT_STRING("SCAN_{}_tex{}"), entry.id, i + 1); } } } diff --git a/DataSpec/DNAMP1/SCLY.cpp b/DataSpec/DNAMP1/SCLY.cpp index 108391b04..6e24003bf 100644 --- a/DataSpec/DNAMP1/SCLY.cpp +++ b/DataSpec/DNAMP1/SCLY.cpp @@ -115,12 +115,12 @@ void SCLY::ScriptLayer::Enumerate(athena::io::IStreamReader& rs) { size_t actualLen = rs.position() - start; if (actualLen != len) Log.report(logvisor::Fatal, - fmt(_SYS_STR("Error while reading object of type 0x{:02X}, did not read the expected amount of " + FMT_STRING(_SYS_STR("Error while reading object of type 0x{:02X}, did not read the expected amount of " "data, read 0x{:x}, expected 0x{:x}")), (atUint32)type, actualLen, len); rs.seek(start + len, athena::SeekOrigin::Begin); } else { - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to find type 0x{:X} in object database")), (atUint32)type); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to find type 0x{:X} in object database")), (atUint32)type); } } } @@ -145,7 +145,7 @@ void SCLY::ScriptLayer::Enumerate(athena::io::YAMLDocReader& r obj->type = type; objects.push_back(std::move(obj)); } else - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to find type 0x{:X} in object database")), (atUint32)type); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to find type 0x{:X} in object database")), (atUint32)type); } } } else @@ -165,7 +165,7 @@ void SCLY::ScriptLayer::Enumerate(athena::io::IStreamWriter& ws) obj->write(ws); auto wrote = ws.position() - start; if (wrote != expLen) - Log.report(logvisor::Error, fmt("expected writing {} byte SCLY obj; wrote {}"), expLen, wrote); + Log.report(logvisor::Error, FMT_STRING("expected writing {} byte SCLY obj; wrote {}"), expLen, wrote); } } diff --git a/DataSpec/DNAMP1/STRG.cpp b/DataSpec/DNAMP1/STRG.cpp index 6acf994ba..6e893b60c 100644 --- a/DataSpec/DNAMP1/STRG.cpp +++ b/DataSpec/DNAMP1/STRG.cpp @@ -62,7 +62,7 @@ static std::u16string_view::const_iterator CookTextureList(std::u16string& ret, while (true) { auto end = str.find_first_of(u",;", it - str.begin()); if (end == std::u16string::npos) - Log.report(logvisor::Fatal, fmt("Missing comma/semicolon token while pasing font tag")); + Log.report(logvisor::Fatal, FMT_STRING("Missing comma/semicolon token while pasing font tag")); auto endIt = str.begin() + end; hecl::ProjectPath path = UniqueIDBridge::MakePathFromString(hecl::Char16ToUTF8(std::u16string(it, endIt))); @@ -92,7 +92,7 @@ static std::u16string_view::const_iterator GatherTextureList(std::vector(hecl::Char16ToUTF8(std::u16string(it, endIt))); @@ -198,7 +198,7 @@ static std::u16string CookString(std::u16string_view str) { it += 5; auto scpos = str.find(u';', it - str.begin()); if (scpos == std::u16string::npos) - Log.report(logvisor::Fatal, fmt("Missing semicolon token while pasing font tag")); + Log.report(logvisor::Fatal, FMT_STRING("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())); @@ -249,7 +249,7 @@ void STRG::gatherDependencies(std::vector& pathsOut) const { it += 5; auto scpos = str.find(u';', it - strView.begin()); if (scpos == std::u16string::npos) - Log.report(logvisor::Fatal, fmt("Missing semicolon token while pasing font tag")); + Log.report(logvisor::Fatal, FMT_STRING("Missing semicolon token while pasing font tag")); hecl::ProjectPath path = UniqueIDBridge::MakePathFromString( hecl::Char16ToUTF8(std::u16string(it, strView.begin() + scpos))); if (path) @@ -311,11 +311,11 @@ template <> void STRG::Enumerate(typename Read::StreamT& reader) { atUint32 magic = reader.readUint32Big(); if (magic != 0x87654321) - Log.report(logvisor::Error, fmt("invalid STRG magic")); + Log.report(logvisor::Error, FMT_STRING("invalid STRG magic")); atUint32 version = reader.readUint32Big(); if (version != 0) - Log.report(logvisor::Error, fmt("invalid STRG version")); + Log.report(logvisor::Error, FMT_STRING("invalid STRG version")); _read(reader); } @@ -412,22 +412,22 @@ void STRG::Enumerate(typename ReadYaml::StreamT& reader) { continue; if (lang.first.size() != 4) { - Log.report(logvisor::Warning, fmt("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first); + Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first); return; } if (lang.second->m_type != YAML_SEQUENCE_NODE) { - Log.report(logvisor::Warning, fmt("STRG language string '{}' must contain a sequence; skipping"), lang.first); + Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must contain a sequence; skipping"), lang.first); return; } for (const auto& str : lang.second->m_seqChildren) { if (str->m_type != YAML_SCALAR_NODE) { - Log.report(logvisor::Warning, fmt("STRG language '{}' must contain all scalars; skipping"), lang.first); + Log.report(logvisor::Warning, FMT_STRING("STRG language '{}' must contain all scalars; skipping"), lang.first); return; } } } } else { - Log.report(logvisor::Warning, fmt("STRG must have a mapping root node; skipping")); + Log.report(logvisor::Warning, FMT_STRING("STRG must have a mapping root node; skipping")); return; } diff --git a/DataSpec/DNAMP1/ScriptObjects/Babygoth.hpp b/DataSpec/DNAMP1/ScriptObjects/Babygoth.hpp index a396d6616..37c3c7607 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Babygoth.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Babygoth.hpp @@ -49,7 +49,7 @@ struct Babygoth : IScriptObject { charAssoc.m_cmdlRigs[noShellModel] = {noShellSkin, cinf}; charAssoc.m_cskrToCharacter[noShellSkin] = std::make_pair(patternedInfo.animationParameters.animationCharacterSet, - fmt::format(fmt("ATTACH.SHELLESS_{}.CSKR"), noShellSkin)); + fmt::format(FMT_STRING("ATTACH.SHELLESS_{}.CSKR"), noShellSkin)); charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, {}, noShellModel, "SHELLESS"); } } diff --git a/DataSpec/DNAMP1/ScriptObjects/Magdolite.hpp b/DataSpec/DNAMP1/ScriptObjects/Magdolite.hpp index b1e787d6c..59a06adb7 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Magdolite.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Magdolite.hpp @@ -47,7 +47,7 @@ struct Magdolite : IScriptObject { charAssoc.m_cmdlRigs[cmdlHeadless] = {cskrHeadless, cinf}; charAssoc.m_cskrToCharacter[cskrHeadless] = std::make_pair(patternedInfo.animationParameters.animationCharacterSet, - fmt::format(fmt("ATTACH.HEADLESS_{}.CSKR"), cskrHeadless)); + fmt::format(FMT_STRING("ATTACH.HEADLESS_{}.CSKR"), cskrHeadless)); charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, {}, cmdlHeadless, "HEADLESS"); } } diff --git a/DataSpec/DNAMP1/ScriptObjects/OmegaPirate.hpp b/DataSpec/DNAMP1/ScriptObjects/OmegaPirate.hpp index 3e28ec6bd..c65cf752c 100644 --- a/DataSpec/DNAMP1/ScriptObjects/OmegaPirate.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/OmegaPirate.hpp @@ -60,7 +60,7 @@ struct OmegaPirate : IScriptObject { charAssoc.m_cmdlRigs[cmdlPhazonVeins] = {cskrPhazonVeins, cinfPhazonVeins}; charAssoc.m_cskrToCharacter[cskrPhazonVeins] = std::make_pair(patternedInfo.animationParameters.animationCharacterSet, - fmt::format(fmt("ATTACH.VEINS_{}.CSKR"), cskrPhazonVeins)); + fmt::format(FMT_STRING("ATTACH.VEINS_{}.CSKR"), cskrPhazonVeins)); charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, cinfPhazonVeins, cmdlPhazonVeins, "VEINS"); } diff --git a/DataSpec/DNAMP1/ScriptObjects/Parameters.hpp b/DataSpec/DNAMP1/ScriptObjects/Parameters.hpp index 6ec46990b..8685fd832 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Parameters.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Parameters.hpp @@ -380,13 +380,13 @@ struct ActorParameters : BigDNA { if (cmdlXray.isValid() && cskrXray.isValid()) { charAssoc.m_cmdlRigs[cmdlXray] = {cskrXray, cinf}; charAssoc.m_cskrToCharacter[cskrXray] = std::make_pair(animParms.animationCharacterSet, - fmt::format(fmt("ATTACH.XRAY_{}.CSKR"), cskrXray)); + fmt::format(FMT_STRING("ATTACH.XRAY_{}.CSKR"), cskrXray)); charAssoc.addAttachmentRig(animParms.animationCharacterSet, {}, cmdlXray, "XRAY"); } if (cmdlThermal.isValid() && cskrThermal.isValid()) { charAssoc.m_cmdlRigs[cmdlThermal] = {cskrThermal, cinf}; charAssoc.m_cskrToCharacter[cskrThermal] = - std::make_pair(animParms.animationCharacterSet, fmt::format(fmt("ATTACH.THERMAL_{}.CSKR"), cskrThermal)); + std::make_pair(animParms.animationCharacterSet, fmt::format(FMT_STRING("ATTACH.THERMAL_{}.CSKR"), cskrThermal)); charAssoc.addAttachmentRig(animParms.animationCharacterSet, {}, cmdlThermal, "THERMAL"); } } diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGame.cpp b/DataSpec/DNAMP1/Tweaks/CTweakGame.cpp index ea63571c6..f2f7a923a 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakGame.cpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakGame.cpp @@ -8,10 +8,12 @@ namespace DataSpec::DNAMP1 { hecl::CVar* tw_fov = nullptr; hecl::CVar* tw_hardmodeDMult = nullptr; hecl::CVar* tw_hardmodeWMult = nullptr; +hecl::CVar* tw_splashScreensDisabled = nullptr; namespace { constexpr std::string_view skFov = "tweak.game.FieldOfView"sv; constexpr std::string_view skHardModeDamageMultName = "tweak.game.HardModeDamageMult"sv; constexpr std::string_view skHardModeWeaponMultName = "tweak.game.HardModeWeaponMult"sv; +constexpr std::string_view skSplashScreensDisabled = "tweak.game.SplashScreensDisabled"sv; } // anonymous namespace void CTweakGame::_tweakGameListener(hecl::CVar* cv) { @@ -21,6 +23,8 @@ void CTweakGame::_tweakGameListener(hecl::CVar* cv) { x60_hardmodeDamageMult = cv->toReal(); } else if (cv == tw_hardmodeWMult) { x64_hardmodeWeaponMult = cv->toReal(); + } else if (cv == tw_splashScreensDisabled) { + x2b_splashScreensDisabled = cv->toBoolean(); } } @@ -33,14 +37,23 @@ void CTweakGame::initCVars(hecl::CVarManager* mgr) { cv->addListener([this](hecl::CVar* cv) { _tweakGameListener(cv); }); return cv; }; + auto assignBoolValue = [this, mgr](std::string_view name, std::string_view desc, bool& v, hecl::CVar::EFlags flags) { + hecl::CVar* cv = mgr->findOrMakeCVar(name, desc, v, flags); + // Check if the CVar was deserialized, this avoid an unnecessary conversion + if (cv->wasDeserialized()) + v = cv->toBoolean(); + cv->addListener([this](hecl::CVar* cv) { _tweakGameListener(cv); }); + return cv; + }; - tw_fov = assignRealValue(skFov, "", x24_fov, - hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive); + tw_fov = assignRealValue(skFov, "", x24_fov, hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive); tw_hardmodeDMult = assignRealValue(skHardModeDamageMultName, "", x60_hardmodeDamageMult, hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::Cheat); tw_hardmodeWMult = assignRealValue(skHardModeWeaponMultName, "", x64_hardmodeWeaponMult, hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::Cheat); + tw_splashScreensDisabled = assignBoolValue(skSplashScreensDisabled, "", x2b_splashScreensDisabled, + hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive); } } // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakPlayerRes.hpp b/DataSpec/DNAMP1/Tweaks/CTweakPlayerRes.hpp index bf0370606..d784efd52 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakPlayerRes.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakPlayerRes.hpp @@ -1,10 +1,11 @@ #pragma once -#include "../../DNACommon/Tweaks/ITweakPlayerRes.hpp" +#include "DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp" namespace DataSpec::DNAMP1 { -struct CTweakPlayerRes final : ITweakPlayerRes { +template +struct AT_SPECIALIZE_PARMS(true, false) CTweakPlayerRes final : ITweakPlayerRes { AT_DECL_DNA_YAML String<-1> m_saveStationIcon; @@ -16,6 +17,9 @@ struct CTweakPlayerRes final : ITweakPlayerRes { String<-1> m_minesBreakSecondTopIcon; String<-1> m_minesBreakSecondBottomIcon; + String m_mapArrowDown; + String m_mapArrowUp; + String<-1> m_lStickN; String<-1> m_lStickU; String<-1> m_lStickUL; diff --git a/DataSpec/DNAMP1/Tweaks/CTweakTargeting.hpp b/DataSpec/DNAMP1/Tweaks/CTweakTargeting.hpp index 8c4c68db1..5ac3535f3 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakTargeting.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakTargeting.hpp @@ -1,9 +1,10 @@ #pragma once -#include "../../DNACommon/Tweaks/ITweakTargeting.hpp" +#include "DataSpec/DNACommon/Tweaks/ITweakTargeting.hpp" namespace DataSpec::DNAMP1 { -struct CTweakTargeting final : public ITweakTargeting { +template +struct AT_SPECIALIZE_PARMS(true, false) CTweakTargeting final : public ITweakTargeting { AT_DECL_DNA_YAML Value x4_targetRadiusMode; Value x8_currLockOnExitDuration; @@ -132,6 +133,69 @@ struct CTweakTargeting final : public ITweakTargeting { Value x220_scanTargetClampMax; Value x224_angularLagSpeed; + // RS5 + Vector x218_; + Vector x21c_; + bool x224_ = true; + bool x225_ = false; + bool x226_ = true; + bool x227_ = true; + bool x22c_ = true; + bool x22d_ = false; + bool x22e_ = true; + bool x22f_ = true; + bool x234_ = true; + bool x235_ = false; + bool x236_ = true; + bool x237_ = true; + zeus::CVector3f x23c_ = zeus::skZero3f; + + float x2c8_ = 0.25f; + float x2cc_ = 0.35f; + zeus::CColor x2d0_ = (zeus::Comp32)0xb6e6ffff; + float x2d4_ = 0.39215687f; + zeus::CColor x2d8_ = (zeus::Comp32)0xa82a00ff; + float x2dc_ = 0.78431374f; + zeus::CVector3f x2e0_ = zeus::CVector3f(0.f, 0.f, 0.46f); + float x2ec_ = 0.25f; + float x2f0_ = 0.25f; + float x2f4_ = 120.f; + float x2f8_ = 0.25f; + float x2fc_ = 3.5f; + float x300_ = 0.35f; + zeus::CColor x304_ = (zeus::Comp32)0xa82a00ff; + float x308_ = 0.78431374f; + zeus::CColor x30c_ = (zeus::Comp32)0x89d6ffff; + float x310_ = 0.5019608f; + float x314_ = 11.25f; + float x318_ = 0.25f; + float x31c_ = 0.125f; + zeus::CColor x320_ = (zeus::Comp32)0xffca28ff; + float x324_ = 0.78431374f; + zeus::CColor x328_ = (zeus::Comp32)0x89d6ffff; + float x32c_ = 0.19607843f; + float x330_ = 0.f; + float x334_ = 0.25f; + float x338_ = 3.f; + float x33c_ = 0.25f; + float x340_ = 0.25f; + float x344_ = 0.25f; + float x348_ = 0.25f; + float x34c_ = 45.f; + float x350_ = 0.5f; + float x354_ = 0.65f; + float x358_ = 1.5f; + float x35c_ = 0.18f; + float x360_ = 0.15f; + float x364_ = 0.25f; + zeus::CColor x368_ = (zeus::Comp32)0x56c1fb9f; + zeus::CColor x36c_ = (zeus::Comp32)0x49c3f6a0; + zeus::CColor x370_ = (zeus::Comp32)0x49c3f631; + zeus::CColor x374_ = (zeus::Comp32)0xff8930ff; + zeus::CColor x378_ = (zeus::Comp32)0xff2f28ff; + zeus::CColor x37c_ = (zeus::Comp32)0x93e9ffff; + zeus::CColor x380_ = (zeus::Comp32)0xff6b60ff; + CTweakTargeting() = default; CTweakTargeting(athena::io::IStreamReader& r) { this->read(r); diff --git a/DataSpec/DNAMP2/ANCS.hpp b/DataSpec/DNAMP2/ANCS.hpp index e78d4a558..7a2e48ef1 100644 --- a/DataSpec/DNAMP2/ANCS.hpp +++ b/DataSpec/DNAMP2/ANCS.hpp @@ -215,9 +215,8 @@ struct ANCS : BigDNA { } 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); + btok, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force); } } diff --git a/DataSpec/DNAMP2/ANIM.cpp b/DataSpec/DNAMP2/ANIM.cpp index 333d543a1..ee7973e05 100644 --- a/DataSpec/DNAMP2/ANIM.cpp +++ b/DataSpec/DNAMP2/ANIM.cpp @@ -6,7 +6,7 @@ namespace DataSpec::DNAMP2 { using ANIMOutStream = hecl::blender::ANIMOutStream; void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig) const { - os.format(fmt( + os.format(FMT_STRING( "act.hecl_fps = round({})\n" "act.hecl_looping = {}\n"), (1.0f / mainInterval), looping ? "True" : "False"); @@ -28,7 +28,7 @@ void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANI continue; } - os.format(fmt("bone_string = '{}'\n"), *bName); + os.format(FMT_STRING("bone_string = '{}'\n"), *bName); os << "action_group = act.groups.new(bone_string)\n" "\n"; @@ -134,7 +134,7 @@ void ANIM::Enumerate(typename Read::StreamT& reader) { m_anim->read(reader); break; default: - Log.report(logvisor::Fatal, fmt("unrecognized ANIM version")); + Log.report(logvisor::Fatal, FMT_STRING("unrecognized ANIM version")); break; } } diff --git a/DataSpec/DNAMP2/CINF.cpp b/DataSpec/DNAMP2/CINF.cpp index ab7cb48ab..5d413320f 100644 --- a/DataSpec/DNAMP2/CINF.cpp +++ b/DataSpec/DNAMP2/CINF.cpp @@ -1,5 +1,6 @@ #include "CINF.hpp" #include "hecl/Blender/Connection.hpp" +#include "DataSpec/DNAMP3/DNAMP3.hpp" namespace DataSpec::DNAMP2 { @@ -34,17 +35,18 @@ void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const { for (atUint32 bid : boneIds) { for (const Name& name : names) { if (name.boneId == bid) { - os.format(fmt("obj.vertex_groups.new(name='{}')\n"), name.name); + os.format(FMT_STRING("obj.vertex_groups.new(name='{}')\n"), name.name); break; } } } } -void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const { +template +void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const typename PAKBridge::PAKType::IDType& cinfId) const { DNAANIM::RigInverter inverter(*this); - os.format(fmt( + os.format(FMT_STRING( "arm = bpy.data.armatures.new('CINF_{}')\n" "arm_obj = bpy.data.objects.new(arm.name, arm)\n" "bpy.context.scene.collection.objects.link(arm_obj)\n" @@ -56,7 +58,7 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c 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(fmt( + os.format(FMT_STRING( "bone = arm.edit_bones.new('{}')\n" "bone.head = ({},{},{})\n" "bone.tail = ({},{},{})\n" @@ -66,17 +68,159 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c tailF[2], bone.m_origBone.id); } - for (const Bone& bone : bones) - if (bone.parentId != 97) - os.format(fmt("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId); + if constexpr (std::is_same_v) { + if (bones.size()) { + atUint32 nullId = bones[0].parentId; + for (const Bone& bone : bones) + if (bone.parentId != nullId) + os.format(FMT_STRING("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId); + } + } else { + for (const Bone& bone : bones) + if (bone.parentId != 97) + os.format(FMT_STRING("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId); + } os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - os.format(fmt("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"), + os.format(FMT_STRING("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"), *getBoneNameFromId(bone.m_origBone.id)); } +template void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const; +template void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, + const UniqueID64& cinfId) const; -std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return fmt::format(fmt("CINF_{}"), cinfId); } +template +std::string CINF::GetCINFArmatureName(const UniqueID& cinfId) { return fmt::format(FMT_STRING("CINF_{}"), cinfId); } +template std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId); +template std::string CINF::GetCINFArmatureName(const UniqueID64& cinfId); + +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)); + } 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); + } + + 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}; + } + } + + 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; + } + + boneIdCount = boneCount; + boneIds.reserve(boneIdCount); + for (auto it = bones.crbegin(); it != bones.crend(); ++it) + boneIds.push_back(it->id); +} + +template +bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKBridge::PAKType::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged) { + if (!force && outPath.isFile()) + return true; + + auto& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::Armature)) + return false; + auto os = conn.beginPythonOut(true); + + os.format(FMT_STRING("import bpy\n" + "from mathutils import Vector\n" + "bpy.context.scene.name = 'CINF_{}'\n" + "bpy.context.scene.hecl_arm_obj = bpy.context.scene.name\n" + "\n" + "# Clear Scene\n" + "if len(bpy.data.collections):\n" + " bpy.data.collections.remove(bpy.data.collections[0])\n" + "\n"), entry.id); + + CINF cinf; + cinf.read(rs); + cinf.sendCINFToBlender(os, entry.id); + os.centerView(); + os.close(); + return conn.saveBlend(); +} + +template bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKBridge::PAKType::Entry& entry, + bool force, hecl::blender::Token& btok, + std::function fileChanged); +template bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename DNAMP3::PAKBridge::PAKType::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged); + +bool CINF::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const hecl::blender::Armature& armature) { + std::unordered_map boneIdMap; + CINF cinf(armature, boneIdMap); + + /* Write out CINF resource */ + athena::io::TransactionalFileWriter w(outPath.getAbsolutePath()); + cinf.write(w); + return true; +} } // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/CINF.hpp b/DataSpec/DNAMP2/CINF.hpp index 6cebbd0c1..85831eb66 100644 --- a/DataSpec/DNAMP2/CINF.hpp +++ b/DataSpec/DNAMP2/CINF.hpp @@ -2,6 +2,7 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DataSpec/DNACommon/RigInverter.hpp" +#include "DNAMP2.hpp" namespace DataSpec::DNAMP2 { @@ -35,8 +36,27 @@ struct CINF : BigDNA { 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); + template + void sendCINFToBlender(hecl::blender::PyOutStream& os, const typename PAKBridge::PAKType::IDType& cinfId) const; + template + static std::string GetCINFArmatureName(const UniqueID& cinfId); + + 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); + + CINF(const Armature& armature, std::unordered_map& idMap); + + template + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKBridge::PAKType::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged); + + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const hecl::blender::Armature& armature); }; } // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/CMakeLists.txt b/DataSpec/DNAMP2/CMakeLists.txt index 504d14541..e04014768 100644 --- a/DataSpec/DNAMP2/CMakeLists.txt +++ b/DataSpec/DNAMP2/CMakeLists.txt @@ -23,6 +23,7 @@ set(DNAMP2_SOURCES MREA.cpp MAPA.hpp MAPU.hpp + PATH.hpp AFSM.hpp STRG.hpp STRG.cpp) diff --git a/DataSpec/DNAMP2/CSKR.cpp b/DataSpec/DNAMP2/CSKR.cpp index 5d9353cbf..16ab4f450 100644 --- a/DataSpec/DNAMP2/CSKR.cpp +++ b/DataSpec/DNAMP2/CSKR.cpp @@ -8,7 +8,7 @@ void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint for (const SkinningRule& rule : skinningRules) { if (idx >= accum && idx < accum + rule.vertCount) for (const SkinningRule::Weight& weight : rule.weights) - os.format(fmt("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight); + os.format(FMT_STRING("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight); accum += rule.vertCount; } } diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index f0e1d7bc9..dd08e1b78 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -4,9 +4,11 @@ #include "MLVL.hpp" #include "CMDL.hpp" #include "ANCS.hpp" +#include "CINF.hpp" #include "MREA.hpp" #include "MAPA.hpp" #include "MAPU.hpp" +#include "PATH.hpp" #include "AFSM.hpp" #include "SAVW.hpp" #include "AGSC.hpp" @@ -25,7 +27,9 @@ 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")) + if (lowerName.compare(0, 7, "metroid") == 0) + return false; + if (lowerName.compare(0, 8, "frontend") == 0) return false; return true; } @@ -115,7 +119,7 @@ void PAKBridge::build() { areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str(); } } - hecl::SystemString num = fmt::format(fmt(_SYS_STR("{:02d} ")), ai); + hecl::SystemString num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), ai); areaDeps.name = num + areaDeps.name; areaDeps.layers.reserve(area.depLayerCount - 1); @@ -126,7 +130,7 @@ void PAKBridge::build() { layer.name = LayerName(mlvl.layerNames[layerIdx++]); layer.active = layerFlags.flags >> (l - 1) & 0x1; layer.name = hecl::StringUtils::TrimWhitespace(layer.name); - num = fmt::format(fmt(_SYS_STR("{:02d} ")), l - 1); + num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), l - 1); layer.name = num + layer.name; layer.resources.reserve(area.depLayers[l] - r); @@ -159,17 +163,29 @@ void PAKBridge::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssoci for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) { charAssoc.m_cmdlRigs[ci.cmdl] = {ci.cskr, ci.cinf}; charAssoc.m_cskrToCharacter[ci.cskr] = - std::make_pair(entry.second.id, fmt::format(fmt("{}_{}.CSKR"), ci.name, ci.cskr)); + std::make_pair(entry.second.id, fmt::format(FMT_STRING("{}_{}.CSKR"), ci.name, ci.cskr)); if (ci.cmdlIce.isValid()) { charAssoc.m_cmdlRigs[ci.cmdlIce] = {ci.cskrIce, ci.cinf}; charAssoc.m_cskrToCharacter[ci.cskrIce] = - std::make_pair(entry.second.id, fmt::format(fmt("{}.ICE_{}.CSKR"), ci.name, ci.cskrIce)); + std::make_pair(entry.second.id, fmt::format(FMT_STRING("{}.ICE_{}.CSKR"), ci.name, ci.cskrIce)); } } } } } +void PAKBridge::addPATHToMREA(PAKRouter& pakRouter, + std::unordered_map& pathToMrea) const { + for (const auto& [id, entry] : m_pak.m_entries) { + if (entry.type == FOURCC('MREA')) { + PAKEntryReadStream rs = entry.beginReadStream(m_node); + UniqueID32 pathID = MREA::GetPATHId(rs); + if (pathID.isValid()) + pathToMrea[pathID] = id; + } + } +} + static const atVec4f BottomRow = {{0.f, 0.f, 0.f, 1.f}}; void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, @@ -186,13 +202,23 @@ void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, if (mlvl.worldNameId.isValid()) pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, - fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId)); + fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId)); 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.isValid()) + 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.isValid()) pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, - fmt::format(fmt(_SYS_STR("!name_{}.yaml")), area.areaNameId)); + fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), area.areaNameId)); } if (mlvl.worldMap.isValid()) { @@ -234,6 +260,8 @@ ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, con return {SAVWCommon::ExtractSAVW, {_SYS_STR(".yaml")}}; case SBIG('CMDL'): return {CMDL::Extract, {_SYS_STR(".blend")}, 1}; + case SBIG('CINF'): + return {CINF::Extract, {_SYS_STR(".blend")}, 1}; case SBIG('ANCS'): return {ANCS::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; case SBIG('MLVL'): @@ -244,6 +272,8 @@ ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, con 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('FSM2'): return {DNAFSM2::ExtractFSM2, {_SYS_STR(".yaml")}}; case SBIG('FONT'): diff --git a/DataSpec/DNAMP2/DNAMP2.hpp b/DataSpec/DNAMP2/DNAMP2.hpp index 279bba2c3..ee62edc12 100644 --- a/DataSpec/DNAMP2/DNAMP2.hpp +++ b/DataSpec/DNAMP2/DNAMP2.hpp @@ -31,6 +31,9 @@ public: void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; + void addPATHToMREA(PAKRouter& pakRouter, + std::unordered_map& pathToMrea) const; + void addMAPATransforms(PAKRouter& pakRouter, std::unordered_map& addTo, std::unordered_map& pathOverrides) const; }; diff --git a/DataSpec/DNAMP2/DeafBabe.cpp b/DataSpec/DNAMP2/DeafBabe.cpp index 36a5e9b3c..e33b2893e 100644 --- a/DataSpec/DNAMP2/DeafBabe.cpp +++ b/DataSpec/DNAMP2/DeafBabe.cpp @@ -26,12 +26,15 @@ void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) { " 'Rubber':(0.09, 0.02, 0.01)}\n" "\n" "# Diffuse Color Maker\n" + "from mathutils import Color\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" + " new_mat.diffuse_color = TYPE_COLORS[mat_type] + (1.0,)\n" " else:\n" - " new_mat.diffuse_color.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n" + " col = Color()\n" + " col.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n" + " new_mat.diffuse_color = tuple(col) + (1.0,)\n" " return new_mat\n" "\n" "bpy.types.Material.retro_unknown = bpy.props.BoolProperty(description='Retro: Unknown (U)')\n" @@ -262,7 +265,7 @@ void DeafBabe::insertNoClimb(hecl::blender::PyOutStream& os) const { if (edgeIdx == -1) continue; const Edge& edge = edgeVertConnections[edgeIdx]; - os.format(fmt( + os.format(FMT_STRING( "edge = col_bm.edges.get((col_bm.verts[{}], col_bm.verts[{}]))\n" "if edge:\n" " edge.seam = True\n"), diff --git a/DataSpec/DNAMP2/MREA.cpp b/DataSpec/DNAMP2/MREA.cpp index ba2bd6adb..57d9f828b 100644 --- a/DataSpec/DNAMP2/MREA.cpp +++ b/DataSpec/DNAMP2/MREA.cpp @@ -13,7 +13,7 @@ namespace DNAMP2 { void MREA::StreamReader::nextBlock() { if (m_nextBlk >= m_blkCount) - Log.report(logvisor::Fatal, fmt("MREA stream overrun")); + Log.report(logvisor::Fatal, FMT_STRING("MREA stream overrun")); BlockInfo& info = m_blockInfos[m_nextBlk++]; @@ -68,8 +68,7 @@ MREA::StreamReader::StreamReader(athena::io::IStreamReader& source, atUint32 blk , m_blkCount(blkCount) { m_blockInfos.reserve(blkCount); for (atUint32 i = 0; i < blkCount; ++i) { - m_blockInfos.emplace_back(); - BlockInfo& info = m_blockInfos.back(); + BlockInfo& info = m_blockInfos.emplace_back(); info.read(source); m_totalDecompLen += info.decompSize; } @@ -87,7 +86,7 @@ void MREA::StreamReader::seek(atInt64 diff, athena::SeekOrigin whence) { } if (target >= m_totalDecompLen) - Log.report(logvisor::Fatal, fmt("MREA stream seek overrun")); + Log.report(logvisor::Fatal, FMT_STRING("MREA stream seek overrun")); /* Determine which block contains position */ atUint32 dAccum = 0; @@ -98,11 +97,11 @@ void MREA::StreamReader::seek(atInt64 diff, athena::SeekOrigin whence) { if (newAccum > target) break; dAccum = newAccum; - ++bIdx; if (info.compSize) cAccum += ROUND_UP_32(info.compSize); else cAccum += info.decompSize; + ++bIdx; } /* Seek source if needed */ @@ -116,6 +115,41 @@ void MREA::StreamReader::seek(atInt64 diff, athena::SeekOrigin whence) { m_posInBlk = target - dAccum; } +void MREA::StreamReader::seekToSection(atUint32 sec, const std::vector& secSizes) { + /* Determine which block contains section */ + atUint32 sAccum = 0; + atUint32 dAccum = 0; + atUint32 cAccum = 0; + atUint32 bIdx = 0; + for (BlockInfo& info : m_blockInfos) { + atUint32 newSAccum = sAccum + info.secCount; + if (newSAccum > sec) + break; + sAccum = newSAccum; + dAccum += info.decompSize; + if (info.compSize) + cAccum += ROUND_UP_32(info.compSize); + else + cAccum += info.decompSize; + ++bIdx; + } + + /* Seek source if needed */ + if (bIdx != m_nextBlk - 1) { + m_source.seek(m_blkBase + cAccum, athena::SeekOrigin::Begin); + m_nextBlk = bIdx; + nextBlock(); + } + + /* Seek within block */ + atUint32 target = dAccum; + while (sAccum != sec) + target += secSizes[sAccum++]; + + m_pos = target; + m_posInBlk = target - dAccum; +} + atUint64 MREA::StreamReader::readUBytesToBuf(void* buf, atUint64 len) { atUint8* bufCur = reinterpret_cast(buf); atUint64 rem = len; @@ -191,7 +225,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: /* Open Py Stream and read sections */ hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format(fmt( + os.format(FMT_STRING( "import bpy\n" "import bmesh\n" "from mathutils import Vector\n" @@ -238,7 +272,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: drs.seek(secStart + head.secSizes[curSec++], athena::SeekOrigin::Begin); curSec += DNACMDL::ReadGeomSectionsToBlender, MaterialSet, RigPair, DNACMDL::SurfaceHeader_2>( os, drs, pakRouter, entry, dummy, true, true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]); - os.format(fmt( + os.format(FMT_STRING( "obj.retro_disable_enviro_visor = {}\n" "obj.retro_disable_thermal_visor = {}\n" "obj.retro_disable_xray_visor = {}\n" @@ -296,5 +330,19 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: return conn.saveBlend(); } +UniqueID32 MREA::GetPATHId(PAKEntryReadStream& rs) { + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); + + /* MREA decompression stream */ + StreamReader drs(rs, head.compressedBlockCount); + + /* Skip to PATH */ + drs.seekToSection(head.pathSecIdx, head.secSizes); + return {drs}; +} + } // namespace DNAMP2 } // namespace DataSpec diff --git a/DataSpec/DNAMP2/MREA.hpp b/DataSpec/DNAMP2/MREA.hpp index 5e678d5b7..65950865b 100644 --- a/DataSpec/DNAMP2/MREA.hpp +++ b/DataSpec/DNAMP2/MREA.hpp @@ -43,6 +43,7 @@ struct MREA { public: StreamReader(athena::io::IStreamReader& source, atUint32 blkCount); void seek(atInt64 diff, athena::SeekOrigin whence) override; + void seekToSection(atUint32 sec, const std::vector& secSizes); atUint64 position() const override { return m_pos; } atUint64 length() const override { return m_totalDecompLen; } atUint64 readUBytesToBuf(void* buf, atUint64 len) override; @@ -118,6 +119,8 @@ struct MREA { Value aabb[2]; }; + static UniqueID32 GetPATHId(PAKEntryReadStream& rs); + 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); diff --git a/DataSpec/DNAMP2/PAK.cpp b/DataSpec/DNAMP2/PAK.cpp index a3e209702..b7352cadc 100644 --- a/DataSpec/DNAMP2/PAK.cpp +++ b/DataSpec/DNAMP2/PAK.cpp @@ -11,7 +11,7 @@ std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, std AGSC::Header header; header.read(rs); catalogueName = header.groupName; - return fmt::format(fmt("{}_{}"), header.groupName, entry.id); + return fmt::format(FMT_STRING("{}_{}"), header.groupName, entry.id); } return DNAMP1::PAK::bestEntryName(pakNode, entry, catalogueName); diff --git a/DataSpec/DNAMP2/PATH.hpp b/DataSpec/DNAMP2/PATH.hpp new file mode 100644 index 000000000..676f4479d --- /dev/null +++ b/DataSpec/DNAMP2/PATH.hpp @@ -0,0 +1,6 @@ +#pragma once +#include "DataSpec/DNACommon/PATH.hpp" + +namespace DataSpec::DNAMP2 { +using PATH = DNAPATH::PATH; +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/STRG.cpp b/DataSpec/DNAMP2/STRG.cpp index 30d0cb24a..16c0632f1 100644 --- a/DataSpec/DNAMP2/STRG.cpp +++ b/DataSpec/DNAMP2/STRG.cpp @@ -49,11 +49,11 @@ template <> void STRG::Enumerate(athena::io::IStreamReader& reader) { atUint32 magic = reader.readUint32Big(); if (magic != 0x87654321) - Log.report(logvisor::Error, fmt("invalid STRG magic")); + Log.report(logvisor::Error, FMT_STRING("invalid STRG magic")); atUint32 version = reader.readUint32Big(); if (version != 1) - Log.report(logvisor::Error, fmt("invalid STRG version")); + Log.report(logvisor::Error, FMT_STRING("invalid STRG version")); _read(reader); } @@ -158,22 +158,22 @@ void STRG::Enumerate(athena::io::YAMLDocReader& reader) { if (lang.first == "names") continue; if (lang.first.size() != 4) { - Log.report(logvisor::Warning, fmt("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first); + Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first); return; } if (lang.second->m_type != YAML_SEQUENCE_NODE) { - Log.report(logvisor::Warning, fmt("STRG language string '{}' must contain a sequence; skipping"), lang.first); + Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must contain a sequence; skipping"), lang.first); return; } for (const auto& str : lang.second->m_seqChildren) { if (str->m_type != YAML_SCALAR_NODE) { - Log.report(logvisor::Warning, fmt("STRG language '{}' must contain all scalars; skipping"), lang.first); + Log.report(logvisor::Warning, FMT_STRING("STRG language '{}' must contain all scalars; skipping"), lang.first); return; } } } } else { - Log.report(logvisor::Warning, fmt("STRG must have a mapping root node; skipping")); + Log.report(logvisor::Warning, FMT_STRING("STRG must have a mapping root node; skipping")); return; } diff --git a/DataSpec/DNAMP2/STRG.hpp b/DataSpec/DNAMP2/STRG.hpp index 5775a96b9..5ec8fd5e1 100644 --- a/DataSpec/DNAMP2/STRG.hpp +++ b/DataSpec/DNAMP2/STRG.hpp @@ -14,6 +14,7 @@ struct STRG : ISTRG { std::map names; int32_t lookupIdx(std::string_view name) const override { + // TODO: Heterogeneous lookup when C++20 available auto search = names.find(name.data()); if (search == names.end()) return -1; diff --git a/DataSpec/DNAMP3/ANIM.cpp b/DataSpec/DNAMP3/ANIM.cpp index 9abfea7ac..38e91c41a 100644 --- a/DataSpec/DNAMP3/ANIM.cpp +++ b/DataSpec/DNAMP3/ANIM.cpp @@ -9,7 +9,7 @@ using ANIMOutStream = hecl::blender::ANIMOutStream; void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig, bool additive) const { - os.format(fmt( + os.format(FMT_STRING( "act.hecl_fps = round({})\n" "act.hecl_additive = {}\n" "act.hecl_looping = {}\n"), @@ -32,7 +32,7 @@ void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANI continue; } - os.format(fmt("bone_string = '{}'\n"), *bName); + os.format(FMT_STRING("bone_string = '{}'\n"), *bName); os << "action_group = act.groups.new(bone_string)\n" "\n"; @@ -138,7 +138,7 @@ void ANIM::Enumerate(typename Read::StreamT& reader) { m_anim->read(reader); break; default: - Log.report(logvisor::Fatal, fmt("unrecognized ANIM version")); + Log.report(logvisor::Fatal, FMT_STRING("unrecognized ANIM version")); break; } } diff --git a/DataSpec/DNAMP3/CHAR.hpp b/DataSpec/DNAMP3/CHAR.hpp index 0ee8b495b..af6e71b75 100644 --- a/DataSpec/DNAMP3/CHAR.hpp +++ b/DataSpec/DNAMP3/CHAR.hpp @@ -283,9 +283,8 @@ struct CHAR : BigDNA { } 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); + btok, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force); } } diff --git a/DataSpec/DNAMP3/CINF.cpp b/DataSpec/DNAMP3/CINF.cpp deleted file mode 100644 index d8cf6ec82..000000000 --- a/DataSpec/DNAMP3/CINF.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "CINF.hpp" -#include "hecl/Blender/Connection.hpp" - -namespace DataSpec::DNAMP3 { - -void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& cinfId) const { - DNAANIM::RigInverter inverter(*this); - - os.format(fmt("arm = bpy.data.armatures.new('CINF_{}')\n" - "arm_obj = bpy.data.objects.new(arm.name, arm)\n" - "bpy.context.scene.collection.objects.link(arm_obj)\n" - "bpy.context.view_layer.objects.active = arm_obj\n" - "bpy.ops.object.mode_set(mode='EDIT')\n" - "arm_bone_table = {{}}\n"), - cinfId); - - 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(fmt( - "bone = arm.edit_bones.new('{}')\n" - "bone.head = ({},{},{})\n" - "bone.tail = ({},{},{})\n" - "bone.use_inherit_scale = False\n" - "arm_bone_table[{}] = bone\n"), - *getBoneNameFromId(bone.m_origBone.id), 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(fmt("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId); - } - - os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; - - for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - os.format(fmt("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"), - *getBoneNameFromId(bone.m_origBone.id)); -} - -std::string CINF::GetCINFArmatureName(const UniqueID64& cinfId) { - return fmt::format(fmt("CINF_{}"), cinfId); -} - -} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CINF.hpp b/DataSpec/DNAMP3/CINF.hpp index 353f21bb8..d40286143 100644 --- a/DataSpec/DNAMP3/CINF.hpp +++ b/DataSpec/DNAMP3/CINF.hpp @@ -1,14 +1,8 @@ #pragma once #include "DataSpec/DNACommon/DNACommon.hpp" -#include "../DNAMP2/CINF.hpp" +#include "DataSpec/DNAMP2/CINF.hpp" 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); -}; - +using CINF = DNAMP2::CINF; } // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CMDLMaterials.cpp b/DataSpec/DNAMP3/CMDLMaterials.cpp index 75f82dae7..3466f1122 100644 --- a/DataSpec/DNAMP3/CMDLMaterials.cpp +++ b/DataSpec/DNAMP3/CMDLMaterials.cpp @@ -6,341 +6,295 @@ using Stream = hecl::blender::PyOutStream; 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 = std::make_unique(); - section->read(reader); - break; - case ISection::Type::CLR: - section = std::make_unique(); - section->read(reader); - break; - case ISection::Type::INT: - section = std::make_unique(); - section->read(reader); - break; - default: - section.reset(); - 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(); + chunks.clear(); + do { chunks.emplace_back().read(reader); } while (!chunks.back().holds_alternative()); + chunks.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); + for (const auto& chunk : chunks) + chunk.visit([&](auto& arg) { arg.write(writer); }); + DNAFourCC(FOURCC('END ')).write(writer); } template <> void MaterialSet::Material::Enumerate(typename BinarySize::StreamT& s) { header.binarySize(s); - for (const SectionFactory& section : sections) - section.binarySize(s); + for (const auto& chunk : chunks) + chunk.visit([&](auto& arg) { arg.binarySize(s); }); s += 4; } void MaterialSet::RegisterMaterialProps(Stream& out) { - out << "bpy.types.Material.retro_alpha_test = bpy.props.BoolProperty(name='Retro: Punchthrough Alpha')\n" + out << "bpy.types.Material.retro_enable_bloom = bpy.props.BoolProperty(name='Retro: Enable Bloom')\n" + "bpy.types.Material.retro_force_lighting_stage = bpy.props.BoolProperty(name='Retro: Force Lighting Stage')\n" + "bpy.types.Material.retro_pre_inca_transparency = bpy.props.BoolProperty(name='Retro: Pre-INCA Transparency')\n" + "bpy.types.Material.retro_alpha_test = bpy.props.BoolProperty(name='Retro: Alpha Test')\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" + "bpy.types.Material.retro_solid_white = bpy.props.BoolProperty(name='Retro: Solid White Only')\n" + "bpy.types.Material.retro_reflection_alpha_target = bpy.props.BoolProperty(name='Retro: Reflection Alpha Target')\n" + "bpy.types.Material.retro_solid_color = bpy.props.BoolProperty(name='Retro: Solid Color Only')\n" + "bpy.types.Material.retro_exclude_scan = bpy.props.BoolProperty(name='Retro: Exclude From Scan Visor')\n" + "bpy.types.Material.retro_xray_opaque = bpy.props.BoolProperty(name='Retro: XRay Opaque')\n" + "bpy.types.Material.retro_xray_alpha_target = bpy.props.BoolProperty(name='Retro: XRay Alpha Target')\n" + "bpy.types.Material.retro_inca_color_mod = bpy.props.BoolProperty(name='Retro: INCA Color Mod')\n" "\n"; } +static void LoadTexture(Stream& out, const UniqueID64& tex, + const PAKRouter& pakRouter, const PAK::Entry& entry) { + if (!tex.isValid()) { + out << "image = None\n"; + return; + } + 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); + out.format(FMT_STRING("if '{}' in bpy.data.images:\n" + " image = bpy.data.images['{}']\n" + "else:\n" + " image = bpy.data.images.load('''//{}''')\n" + " image.name = '{}'\n" + "\n"), texName, texName, resPathView, texName); +} + void MaterialSet::ConstructMaterial(Stream& out, const PAKRouter& pakRouter, const PAK::Entry& entry, const Material& material, unsigned groupIdx, unsigned matIdx) { - unsigned i; - - out.format(fmt( - "new_material = bpy.data.materials.new('MAT_{}_{}')\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.use_nodes = True\n" - "new_material.blend_method = 'BLEND'\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); + out.format(FMT_STRING("new_material = bpy.data.materials.new('MAT_{}_{}')\n"), groupIdx, matIdx); + out << "new_material.use_fake_user = True\n" + "new_material.use_nodes = True\n" + "new_material.use_backface_culling = True\n" + "new_material.show_transparent_back = False\n" + "new_material.blend_method = 'BLEND'\n" + "new_nodetree = new_material.node_tree\n" + "for n in new_nodetree.nodes:\n" + " new_nodetree.nodes.remove(n)\n" + "\n" + "gridder = hecl.Nodegrid(new_nodetree)\n" + "new_nodetree.nodes.remove(gridder.frames[2])\n" + "\n" + "texture_nodes = []\n" + "kcolors = {}\n" + "kalphas = {}\n" + "tex_links = []\n" + "\n"; /* Material Flags */ - out.format(fmt( + out.format(FMT_STRING( + "new_material.retro_enable_bloom = {}\n" + "new_material.retro_force_lighting_stage = {}\n" + "new_material.retro_pre_inca_transparency = {}\n" "new_material.retro_alpha_test = {}\n" "new_material.retro_shadow_occluder = {}\n" - "new_material.diffuse_color = (1, 1, 1, {})\n"), + "new_material.retro_solid_white = {}\n" + "new_material.retro_reflection_alpha_target = {}\n" + "new_material.retro_solid_color = {}\n" + "new_material.retro_exclude_scan = {}\n" + "new_material.retro_xray_opaque = {}\n" + "new_material.retro_xray_alpha_target = {}\n" + "new_material.retro_inca_color_mod = False\n"), + material.header.flags.enableBloom() ? "True" : "False", + material.header.flags.forceLightingStage() ? "True" : "False", + material.header.flags.preIncaTransparency() ? "True" : "False", material.header.flags.alphaTest() ? "True" : "False", material.header.flags.shadowOccluderMesh() ? "True" : "False", - material.header.flags.shadowOccluderMesh() ? "0" : "1"); + material.header.flags.justWhite() ? "True" : "False", + material.header.flags.reflectionAlphaTarget() ? "True" : "False", + material.header.flags.justSolidColor() ? "True" : "False", + material.header.flags.excludeFromScanVisor() ? "True" : "False", + material.header.flags.xrayOpaque() ? "True" : "False", + material.header.flags.xrayAlphaTarget() ? "True" : "False"); - /* Blend factors */ - out << "blend_node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - "blend_node.name = 'Blend'\n" - "gridder.place_node(blend_node, 2)\n"; - if (material.header.flags.alphaBlending()) - out << "blend_node.node_tree = bpy.data.node_groups['HECLBlendOutput']\n"; - else if (material.header.flags.additiveBlending()) - out << "blend_node.node_tree = bpy.data.node_groups['HECLAdditiveOutput']\n"; - else { - out << "blend_node.node_tree = bpy.data.node_groups['HECLOpaqueOutput']\n" - "new_material.blend_method = 'OPAQUE'\n"; - } + out << "pnode = new_nodetree.nodes.new('ShaderNodeGroup')\n" + "pnode.name = 'Output'\n" + "pnode.node_tree = bpy.data.node_groups['RetroShaderMP3']\n" + "gridder.place_node(pnode, 1)\n"; - /* Texmap list */ - out << "tex_maps = []\n" - "pnode = None\n" - "anode = None\n" - "rflv_tex_node = None\n"; + if (material.header.flags.additiveIncandecence()) + out << "pnode.inputs['Add INCA'].default_value = 1\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(); - } + int texMtxIdx = 0; + for (const auto& chunk : material.chunks) { + if (const Material::PASS* pass = chunk.get_if()) { + LoadTexture(out, pass->txtrId, pakRouter, entry); + out << "# Texture\n" + "tex_node = new_nodetree.nodes.new('ShaderNodeTexImage')\n" + "texture_nodes.append(tex_node)\n" + "tex_node.image = image\n"; - /* 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"; -} + if (!pass->uvAnim.empty()) { + const auto& uva = pass->uvAnim[0]; + switch (uva.uvSource) { + case Material::UVAnimationUVSource::Position: + default: + out << "tex_uv_node = new_nodetree.nodes.new('ShaderNodeTexCoord')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Window'], tex_node.inputs['Vector']))\n"; + break; + case Material::UVAnimationUVSource::Normal: + out << "tex_uv_node = new_nodetree.nodes.new('ShaderNodeTexCoord')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Normal'], tex_node.inputs['Vector']))\n"; + break; + case Material::UVAnimationUVSource::UV: + out.format(FMT_STRING("tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" + "tex_uv_node.uv_map = 'UV_{}'\n"), pass->uvSrc); + break; + } + out.format(FMT_STRING("tex_uv_node.label = 'MTX_{}'\n"), texMtxIdx); + } else { + out.format(FMT_STRING("tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" + "tex_uv_node.uv_map = 'UV_{}'\n"), pass->uvSrc); + } -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.isValid()) { - 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); + out << "gridder.place_node(tex_uv_node, 0)\n" + "gridder.place_node(tex_node, 0)\n" + "tex_uv_node.location[0] -= 120\n" + "tex_node.location[0] += 120\n" + "tex_node.location[1] += 176\n" + "\n"; + + if (!pass->uvAnim.empty()) { + const auto& uva = pass->uvAnim[0]; + DNAMP1::MaterialSet::Material::AddTextureAnim(out, uva.anim.mode, texMtxIdx++, uva.anim.vals); + } + + auto DoSwap = [&]() { + if (pass->flags.swapColorComponent() == Material::SwapColorComponent::Alpha) { + out << "swap_output = tex_node.outputs['Alpha']\n"; + } else { + out << "separate_node = new_nodetree.nodes.new('ShaderNodeSeparateRGB')\n" + "gridder.place_node(separate_node, 0, False)\n" + "separate_node.location[0] += 350\n" + "separate_node.location[1] += 350\n" + "new_nodetree.links.new(tex_node.outputs['Color'], separate_node.inputs[0])\n"; + out.format(FMT_STRING("swap_output = separate_node.outputs[{}]\n"), int(pass->flags.swapColorComponent())); + } + }; + + using Subtype = Material::PASS::Subtype; + switch (Subtype(pass->subtype.toUint32())) { + case Subtype::DIFF: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['DIFFC'])\n" + "new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['DIFFA'])\n"; + break; + case Subtype::BLOL: + DoSwap(); + out << "new_nodetree.links.new(swap_output, pnode.inputs['BLOL'])\n"; + break; + case Subtype::BLOD: + DoSwap(); + out << "new_nodetree.links.new(swap_output, pnode.inputs['BLOD'])\n"; + break; + case Subtype::CLR: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['CLR'])\n" + "new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['CLRA'])\n"; + break; + case Subtype::TRAN: + DoSwap(); + if (pass->flags.TRANInvert()) + out << "invert_node = new_nodetree.nodes.new('ShaderNodeInvert')\n" + "gridder.place_node(invert_node, 0, False)\n" + "invert_node.location[0] += 400\n" + "invert_node.location[1] += 350\n" + "new_nodetree.links.new(swap_output, invert_node.inputs['Color'])\n" + "swap_output = invert_node.outputs['Color']\n"; + out << "new_nodetree.links.new(swap_output, pnode.inputs['TRAN'])\n"; + break; + case Subtype::INCA: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['INCAC'])\n"; + if (pass->flags.alphaContribution()) { + DoSwap(); + out << "new_nodetree.links.new(swap_output, pnode.inputs['INCAA'])\n"; + } + out.format(FMT_STRING("new_material.retro_inca_color_mod = {}\n"), pass->flags.INCAColorMod() ? "True" : "False"); + break; + case Subtype::RFLV: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['RFLV'])\n"; + break; + case Subtype::RFLD: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['RFLD'])\n" + "new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['RFLDA'])\n"; + break; + case Subtype::LRLD: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['LRLD'])\n"; + break; + case Subtype::LURD: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['LURDC'])\n" + "new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['LURDA'])\n"; + break; + case Subtype::BLOI: + DoSwap(); + out << "new_nodetree.links.new(swap_output, pnode.inputs['BLOI'])\n"; + break; + case Subtype::XRAY: + DoSwap(); + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['XRAYC'])\n" + "new_nodetree.links.new(swap_output, pnode.inputs['XRAYA'])\n"; + break; + default: + Log.report(logvisor::Fatal, FMT_STRING("Unknown PASS subtype")); + break; + } + } else if (const Material::CLR* clr = chunk.get_if()) { + using Subtype = Material::CLR::Subtype; + athena::simd_floats vec4; + clr->color.toVec4f().simd.copy_to(vec4); + switch (Subtype(clr->subtype.toUint32())) { + case Subtype::CLR: + out.format(FMT_STRING("pnode.inputs['CLR'].default_value = ({}, {}, {}, 1.0)\n" + "pnode.inputs['CLRA'].default_value = {}\n"), + vec4[0], vec4[1], vec4[2], vec4[3]); + break; + case Subtype::DIFB: + out.format(FMT_STRING("pnode.inputs['DIFBC'].default_value = ({}, {}, {}, 1.0)\n" + "pnode.inputs['DIFBA'].default_value = {}\n"), + vec4[0], vec4[1], vec4[2], vec4[3]); + break; + default: + Log.report(logvisor::Fatal, FMT_STRING("Unknown CLR subtype")); + break; + } + } else if (const Material::INT* val = chunk.get_if()) { + using Subtype = Material::INT::Subtype; + switch (Subtype(val->subtype.toUint32())) { + case Subtype::OPAC: + out.format(FMT_STRING("pnode.inputs['OPAC'].default_value = {}\n"), val->value / 255.f); + break; + case Subtype::BLOD: + out.format(FMT_STRING("pnode.inputs['BLOD'].default_value = {}\n"), val->value / 255.f); + break; + case Subtype::BLOI: + out.format(FMT_STRING("pnode.inputs['BLOI'].default_value = {}\n"), val->value / 255.f); + break; + case Subtype::BNIF: + out.format(FMT_STRING("pnode.inputs['BNIF'].default_value = {}\n"), val->value / 255.f); + break; + case Subtype::XRBR: + out.format(FMT_STRING("pnode.inputs['XRBR'].default_value = {}\n"), val->value / 255.f); + break; + default: + Log.report(logvisor::Fatal, FMT_STRING("Unknown INT subtype")); + break; + } } - hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, txtrId); - hecl::SystemUTF8Conv resPathView(resPath); - out.format(fmt( - "if '{}' in bpy.data.textures:\n" - " image = bpy.data.images['{}']\n" - " texture = bpy.data.textures[image.name]\n" - "else:\n" - " image = bpy.data.images.load('''//{}''')\n" - " image.name = '{}'\n" - " texture = bpy.data.textures.new(image.name, 'IMAGE')\n" - " texture.image = image\n" - "tex_maps.append(texture)\n" - "\n"), - texName, texName, resPathView, texName); - if (uvAnim.size()) { - const UVAnimation& uva = uvAnim[0]; - DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uva.unk1 + (uva.unk1 < 2 ? 0 : 2)), texMtxIdx, - texMapIdx++, false); - DNAMP1::MaterialSet::Material::AddTextureAnim(out, uva.anim.mode, texMtxIdx++, uva.anim.vals); - } else - DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uvSrc + 4), -1, texMapIdx++, false); - } - - /* Special case for RFLV (environment UV mask) */ - if (Subtype(subtype.toUint32()) == Subtype::RFLV) { - if (txtrId.isValid()) - 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.isValid()) { - 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.isValid()) { - 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"; - } - - /* 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::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(fmt( - "anode = new_nodetree.nodes.new('ShaderNodeValue')\n" - "anode.outputs['Value'].default_value = {}\n"), - float(clr[3]) / float(0xff)); - out << "gridder.place_node(anode, 1)\n"; - } break; - case Subtype::BLOD: - out.format(fmt("new_material.retro_blod = {}\n"), value); - break; - case Subtype::BLOI: - out.format(fmt("new_material.retro_bloi = {}\n"), value); - break; - case Subtype::BNIF: - out.format(fmt("new_material.retro_bnif = {}\n"), value); - break; - case Subtype::XRBR: - out.format(fmt("new_material.retro_xrbr = {}\n"), value); - break; - default: - break; } } } // namespace DataSpec::DNAMP3 + +AT_SPECIALIZE_TYPED_VARIANT_BIGDNA(DataSpec::DNAMP3::MaterialSet::Material::PASS, + DataSpec::DNAMP3::MaterialSet::Material::CLR, + DataSpec::DNAMP3::MaterialSet::Material::INT, + DataSpec::DNAMP3::MaterialSet::Material::END) diff --git a/DataSpec/DNAMP3/CMDLMaterials.hpp b/DataSpec/DNAMP3/CMDLMaterials.hpp index df73b62e0..89d562a72 100644 --- a/DataSpec/DNAMP3/CMDLMaterials.hpp +++ b/DataSpec/DNAMP3/CMDLMaterials.hpp @@ -18,6 +18,10 @@ struct MaterialSet : BigDNA { void addMaterialEndOff(atUint32) { ++materialCount; } struct Material : BigDNA { + enum class SwapColorComponent { Red, Green, Blue, Alpha }; + enum class UVAnimationUVSource : atUint16 { Position, Normal, UV }; + enum class UVAnimationMatrixConfig : atUint16 { NoMtxNoPost, MtxNoPost, NoMtxPost, MtxPost }; + AT_DECL_EXPLICIT_DNA using VAFlags = DNAMP1::MaterialSet::Material::VAFlags; struct Header : BigDNA { @@ -26,8 +30,18 @@ struct MaterialSet : BigDNA { struct Flags : BigDNA { AT_DECL_DNA Value flags; - bool alphaBlending() const { return (flags & 0x8) != 0; } - void setAlphaBlending(bool enabled) { + bool enableBloom() const { return (flags & 0x1) != 0; } + void setEnableBloom(bool enabled) { + flags &= ~0x1; + flags |= atUint32(enabled) << 0; + } + bool forceLightingStage() const { return (flags & 0x4) != 0; } + void setForceLightingStage(bool enabled) { + flags &= ~0x4; + flags |= atUint32(enabled) << 2; + } + bool preIncaTransparency() const { return (flags & 0x8) != 0; } + void setPreIncaTransparency(bool enabled) { flags &= ~0x8; flags |= atUint32(enabled) << 3; } @@ -36,8 +50,8 @@ struct MaterialSet : BigDNA { flags &= ~0x10; flags |= atUint32(enabled) << 4; } - bool additiveBlending() const { return (flags & 0x20) != 0; } - void setAdditiveBlending(bool enabled) { + bool additiveIncandecence() const { return (flags & 0x20) != 0; } + void setAdditiveIncandecence(bool enabled) { flags &= ~0x20; flags |= atUint32(enabled) << 5; } @@ -46,6 +60,36 @@ struct MaterialSet : BigDNA { flags &= ~0x100; flags |= atUint32(enabled) << 8; } + bool justWhite() const { return (flags & 0x200) != 0; } + void setJustWhite(bool enabled) { + flags &= ~0x200; + flags |= atUint32(enabled) << 9; + } + bool reflectionAlphaTarget() const { return (flags & 0x400) != 0; } + void setReflectionAlphaTarget(bool enabled) { + flags &= ~0x400; + flags |= atUint32(enabled) << 10; + } + bool justSolidColor() const { return (flags & 0x800) != 0; } + void setJustSolidColor(bool enabled) { + flags &= ~0x800; + flags |= atUint32(enabled) << 11; + } + bool excludeFromScanVisor() const { return (flags & 0x4000) != 0; } + void setExcludeFromScanVisor(bool enabled) { + flags &= ~0x4000; + flags |= atUint32(enabled) << 14; + } + bool xrayOpaque() const { return (flags & 0x8000) != 0; } + void setXRayOpaque(bool enabled) { + flags &= ~0x8000; + flags |= atUint32(enabled) << 15; + } + bool xrayAlphaTarget() const { return (flags & 0x10000) != 0; } + void setXRayAlphaTarget(bool enabled) { + flags &= ~0x10000; + flags |= atUint32(enabled) << 16; + } bool lightmapUVArray() const { return false; } /* For polymorphic compatibility with MP1/2 */ } flags; Value uniqueIdx; @@ -58,20 +102,12 @@ struct MaterialSet : BigDNA { 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; + enum class ChunkType : atUint32 { + PASS = 'PASS', CLR = 'CLR ', INT = 'INT ', END = 'END ' }; - 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_DNAV + + struct PASS : hecl::TypedRecordBigDNA { + AT_DECL_DNA Value size; enum class Subtype : atUint32 { DIFF = SBIG('DIFF'), @@ -93,6 +129,21 @@ struct MaterialSet : BigDNA { struct Flags : BigDNA { AT_DECL_DNA Value flags; + SwapColorComponent swapColorComponent() const { return SwapColorComponent(flags & 0x3); } + void setSwapColorComponent(SwapColorComponent comp) { + flags &= ~0x3; + flags |= atUint32(comp) << 0; + } + bool alphaContribution() const { return (flags & 0x4) != 0; } + void setAlphaContribution(bool enabled) { + flags &= ~0x4; + flags |= atUint32(enabled) << 2; + } + bool INCAColorMod() const { return (flags & 0x8) != 0; } + void setINCAColorMod(bool enabled) { + flags &= ~0x8; + flags |= atUint32(enabled) << 3; + } bool TRANInvert() const { return (flags & 0x10) != 0; } void setTRANInvert(bool enabled) { flags &= ~0x10; @@ -104,36 +155,21 @@ struct MaterialSet : BigDNA { Value uvAnimSize; struct UVAnimation : BigDNA { AT_DECL_DNA - Value unk1; - Value unk2; + Value uvSource; + Value mtxConfig; 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 override; }; - 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_DNAV + struct CLR : hecl::TypedRecordBigDNA { + AT_DECL_DNA 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 override; + CLR() = default; }; - 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_DNAV + struct INT : hecl::TypedRecordBigDNA { + AT_DECL_DNA enum class Subtype : atUint32 { OPAC = SBIG('OPAC'), BLOD = SBIG('BLOD'), @@ -143,16 +179,12 @@ struct MaterialSet : BigDNA { }; 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 override; }; - struct SectionFactory : BigDNA { - AT_DECL_EXPLICIT_DNA - std::unique_ptr section; + struct END : hecl::TypedRecordBigDNA { + AT_DECL_DNA }; - std::vector sections; + using Chunk = hecl::TypedVariantBigDNA; + std::vector chunks; }; Vector materials; diff --git a/DataSpec/DNAMP3/CMakeLists.txt b/DataSpec/DNAMP3/CMakeLists.txt index 0c0ea91a6..e4950978b 100644 --- a/DataSpec/DNAMP3/CMakeLists.txt +++ b/DataSpec/DNAMP3/CMakeLists.txt @@ -14,11 +14,12 @@ set(DNAMP3_SOURCES DNAMP3.hpp DNAMP3.cpp PAK.cpp ANIM.cpp - CINF.cpp + CINF.hpp CHAR.cpp CMDL.hpp CMDL.cpp CMDLMaterials.cpp CSKR.cpp + PATH.hpp STRG.hpp STRG.cpp MAPA.hpp MREA.cpp) diff --git a/DataSpec/DNAMP3/CSKR.cpp b/DataSpec/DNAMP3/CSKR.cpp index b798f7ec7..11711dd5d 100644 --- a/DataSpec/DNAMP3/CSKR.cpp +++ b/DataSpec/DNAMP3/CSKR.cpp @@ -8,7 +8,7 @@ void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atInt1 return; const DNAMP2::CSKR::SkinningRule& rule = data.skinningRules[skinIdx]; for (const DNAMP2::CSKR::SkinningRule::Weight& weight : rule.weights) - os.format(fmt("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight); + os.format(FMT_STRING("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight); } } // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/DNAMP3.cpp b/DataSpec/DNAMP3/DNAMP3.cpp index a2b8199b0..e5b4e3461 100644 --- a/DataSpec/DNAMP3/DNAMP3.cpp +++ b/DataSpec/DNAMP3/DNAMP3.cpp @@ -9,6 +9,7 @@ #include "CHAR.hpp" #include "MREA.hpp" #include "MAPA.hpp" +#include "PATH.hpp" #include "SAVW.hpp" #include "HINT.hpp" #include "DataSpec/DNACommon/TXTR.hpp" @@ -23,9 +24,8 @@ 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; + return !lowerName.starts_with("metroid"sv) && !lowerName.starts_with("frontend"sv) && + !lowerName.starts_with("rs5fe"sv) && !lowerName.starts_with("universearea"sv); } PAKBridge::PAKBridge(const nod::Node& node, bool doExtract) @@ -119,7 +119,7 @@ void PAKBridge::build() { areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str(); } } - hecl::SystemString num = fmt::format(fmt(_SYS_STR("{:02d} ")), ai); + hecl::SystemString num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), ai); areaDeps.name = num + areaDeps.name; const MLVL::LayerFlags& layerFlags = *layerFlagsIt++; @@ -131,7 +131,7 @@ void PAKBridge::build() { layer.name = LayerName(mlvl.layerNames[layerIdx++]); layer.active = layerFlags.flags >> (l - 1) & 0x1; layer.name = hecl::StringUtils::TrimWhitespace(layer.name); - num = fmt::format(fmt(_SYS_STR("{:02d} ")), l - 1); + num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), l - 1); layer.name = num + layer.name; } } @@ -165,11 +165,11 @@ void PAKBridge::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssoci const CHAR::CharacterInfo& ci = aChar.characterInfo; charAssoc.m_cmdlRigs[ci.cmdl] = {ci.cskr, ci.cinf}; charAssoc.m_cskrToCharacter[ci.cskr] = - std::make_pair(entry.second.id, fmt::format(fmt("{}_{}.CSKR"), ci.name, ci.cskr)); + std::make_pair(entry.second.id, fmt::format(FMT_STRING("{}_{}.CSKR"), ci.name, ci.cskr)); for (const CHAR::CharacterInfo::Overlay& overlay : ci.overlays) { charAssoc.m_cmdlRigs[overlay.cmdl] = {overlay.cskr, ci.cinf}; charAssoc.m_cskrToCharacter[overlay.cskr] = - std::make_pair(entry.second.id, fmt::format(fmt("{}.{}_{}.CSKR"), ci.name, overlay.type, overlay.cskr)); + std::make_pair(entry.second.id, fmt::format(FMT_STRING("{}.{}_{}.CSKR"), ci.name, overlay.type, overlay.cskr)); } } } @@ -191,13 +191,23 @@ void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, if (mlvl.worldNameId.isValid()) pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, - fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId)); + fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId)); 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); + UniqueID64 pathId = MREA::GetPATHId(rs); + if (pathId.isValid()) + 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.isValid()) pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, - fmt::format(fmt(_SYS_STR("!name_{}.yaml")), area.areaNameId)); + fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), area.areaNameId)); } if (mlvl.worldMap.isValid()) { @@ -236,16 +246,20 @@ ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, con 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('CMDL'): + return {CMDL::Extract, {_SYS_STR(".blend")}, 1}; + case SBIG('CINF'): + return {CINF::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('PATH'): + return {PATH::Extract, {_SYS_STR(".blend")}, 5}; case SBIG('FSM2'): return {DNAFSM2::ExtractFSM2, {_SYS_STR(".yaml")}}; case SBIG('FONT'): diff --git a/DataSpec/DNAMP3/MREA.cpp b/DataSpec/DNAMP3/MREA.cpp index a54712423..474acb865 100644 --- a/DataSpec/DNAMP3/MREA.cpp +++ b/DataSpec/DNAMP3/MREA.cpp @@ -14,16 +14,14 @@ MREA::StreamReader::StreamReader(athena::io::IStreamReader& source, atUint32 blk m_blkCount = blkCount; m_blockInfos.reserve(blkCount); for (atUint32 i = 0; i < blkCount; ++i) { - m_blockInfos.emplace_back(); - BlockInfo& info = m_blockInfos.back(); + BlockInfo& info = m_blockInfos.emplace_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(); + std::pair& idx = m_secIdxs.emplace_back(); idx.first.read(source); idx.second = source.readUint32Big(); } @@ -39,10 +37,19 @@ void MREA::StreamReader::writeSecIdxs(athena::io::IStreamWriter& writer) const { } } +bool MREA::StreamReader::seekToSection(FourCC sec, const std::vector& secSizes) { + auto search = std::find_if(m_secIdxs.begin(), m_secIdxs.end(), [sec](const auto& s) { return s.first == sec; }); + if (search != m_secIdxs.end()) { + DNAMP2::MREA::StreamReader::seekToSection(search->second, secSizes); + return true; + } + return false; +} + void MREA::ReadBabeDeadToBlender_3(hecl::blender::PyOutStream& os, athena::io::IStreamReader& rs) { atUint32 bdMagic = rs.readUint32Big(); if (bdMagic != 0xBABEDEAD) - Log.report(logvisor::Fatal, fmt("invalid BABEDEAD magic")); + Log.report(logvisor::Fatal, FMT_STRING("invalid BABEDEAD magic")); os << "bpy.context.scene.world.use_nodes = True\n" "bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n" "bg_node.inputs[1].default_value = 0.0\n"; @@ -93,7 +100,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: /* Open Py Stream and read sections */ hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format(fmt( + os.format(FMT_STRING( "import bpy\n" "import bmesh\n" "from mathutils import Vector\n" @@ -254,5 +261,20 @@ bool MREA::ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Level::Area& area return false; } +UniqueID64 MREA::GetPATHId(PAKEntryReadStream& rs) { + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); + + /* MREA decompression stream */ + StreamReader drs(rs, head.compressedBlockCount, head.secIndexCount); + + /* Skip to PATH */ + if (drs.seekToSection(FOURCC('PFL2'), head.secSizes)) + return {drs}; + return {}; +} + } // namespace DNAMP3 } // namespace DataSpec diff --git a/DataSpec/DNAMP3/MREA.hpp b/DataSpec/DNAMP3/MREA.hpp index 35d234d54..5747b4393 100644 --- a/DataSpec/DNAMP3/MREA.hpp +++ b/DataSpec/DNAMP3/MREA.hpp @@ -13,6 +13,7 @@ struct MREA { 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; + bool seekToSection(FourCC sec, const std::vector& secSizes); }; struct Header : BigDNA { @@ -84,6 +85,8 @@ struct MREA { static void ReadBabeDeadToBlender_3(hecl::blender::PyOutStream& os, athena::io::IStreamReader& rs); + static UniqueID64 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); diff --git a/DataSpec/DNAMP3/PAK.cpp b/DataSpec/DNAMP3/PAK.cpp index 2eddb7f08..81a4b016a 100644 --- a/DataSpec/DNAMP3/PAK.cpp +++ b/DataSpec/DNAMP3/PAK.cpp @@ -9,7 +9,7 @@ template <> void PAK::Enumerate(athena::io::IStreamReader& reader) { m_header.read(reader); if (m_header.version != 2) - Log.report(logvisor::Fatal, fmt("unexpected PAK magic")); + Log.report(logvisor::Fatal, FMT_STRING("unexpected PAK magic")); reader.seek(8, athena::SeekOrigin::Current); atUint32 strgSz = reader.readUint32Big(); @@ -141,7 +141,7 @@ std::unique_ptr PAK::Entry::getBuffer(const nod::Node& pak, atUint64& } head; strm->read(&head, 8); if (head.magic != CMPD) { - Log.report(logvisor::Error, fmt("invalid CMPD block")); + Log.report(logvisor::Error, FMT_STRING("invalid CMPD block")); return nullptr; } head.blockCount = hecl::SBig(head.blockCount); @@ -206,6 +206,7 @@ const PAK::Entry* PAK::lookupEntry(const UniqueID64& id) const { } const PAK::Entry* PAK::lookupEntry(std::string_view name) const { + // TODO: Heterogeneous lookup when C++20 available auto result = m_nameMap.find(name.data()); if (result != m_nameMap.end()) { auto result1 = m_entries.find(result->second); @@ -220,11 +221,11 @@ std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, std for (const NameEntry& nentry : m_nameEntries) if (nentry.id == entry.id) { catalogueName = nentry.name; - return fmt::format(fmt("{}_{}"), nentry.name, entry.id); + return fmt::format(FMT_STRING("{}_{}"), nentry.name, entry.id); } /* Otherwise return ID format string */ - return fmt::format(fmt("{}_{}"), entry.type, entry.id); + return fmt::format(FMT_STRING("{}_{}"), entry.type, entry.id); } } // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/PATH.hpp b/DataSpec/DNAMP3/PATH.hpp new file mode 100644 index 000000000..f2b218055 --- /dev/null +++ b/DataSpec/DNAMP3/PATH.hpp @@ -0,0 +1,6 @@ +#pragma once +#include "DataSpec/DNACommon/PATH.hpp" + +namespace DataSpec::DNAMP3 { +using PATH = DNAPATH::PATH; +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/STRG.cpp b/DataSpec/DNAMP3/STRG.cpp index a5de8ac98..b40dd735d 100644 --- a/DataSpec/DNAMP3/STRG.cpp +++ b/DataSpec/DNAMP3/STRG.cpp @@ -59,13 +59,13 @@ template <> void STRG::Enumerate(athena::io::IStreamReader& reader) { atUint32 magic = reader.readUint32Big(); if (magic != 0x87654321) { - Log.report(logvisor::Error, fmt("invalid STRG magic")); + Log.report(logvisor::Error, FMT_STRING("invalid STRG magic")); return; } atUint32 version = reader.readUint32Big(); if (version != 3) { - Log.report(logvisor::Error, fmt("invalid STRG version")); + Log.report(logvisor::Error, FMT_STRING("invalid STRG version")); return; } @@ -82,22 +82,22 @@ void STRG::Enumerate(athena::io::YAMLDocReader& reader) { if (lang.first == "names") continue; if (lang.first.size() != 4) { - Log.report(logvisor::Warning, fmt("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first); + Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first); return; } if (lang.second->m_type != YAML_SEQUENCE_NODE) { - Log.report(logvisor::Warning, fmt("STRG language string '{}' must contain a sequence; skipping"), lang.first); + Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must contain a sequence; skipping"), lang.first); return; } for (const auto& str : lang.second->m_seqChildren) { if (str->m_type != YAML_SCALAR_NODE) { - Log.report(logvisor::Warning, fmt("STRG language '{}' must contain all scalars; skipping"), lang.first); + Log.report(logvisor::Warning, FMT_STRING("STRG language '{}' must contain all scalars; skipping"), lang.first); return; } } } } else { - Log.report(logvisor::Warning, fmt("STRG must have a mapping root node; skipping")); + Log.report(logvisor::Warning, FMT_STRING("STRG must have a mapping root node; skipping")); return; } diff --git a/DataSpec/DNAMP3/STRG.hpp b/DataSpec/DNAMP3/STRG.hpp index c43858955..8f8d44f50 100644 --- a/DataSpec/DNAMP3/STRG.hpp +++ b/DataSpec/DNAMP3/STRG.hpp @@ -14,6 +14,7 @@ struct STRG : ISTRG { std::map names; int32_t lookupIdx(std::string_view name) const override { + // TODO: Heterogeneous lookup when C++20 available auto search = names.find(name.data()); if (search == names.end()) return -1; diff --git a/DataSpec/SpecBase.cpp b/DataSpec/SpecBase.cpp index a9e762be6..ed0074ae5 100644 --- a/DataSpec/SpecBase.cpp +++ b/DataSpec/SpecBase.cpp @@ -3,11 +3,12 @@ #include #endif -#include "SpecBase.hpp" -#include "Blender/BlenderSupport.hpp" -#include "DNACommon/DNACommon.hpp" -#include "DNACommon/TXTR.hpp" -#include "AssetNameMap.hpp" +#include "DataSpec/SpecBase.hpp" +#include "DataSpec/Blender/BlenderSupport.hpp" +#include "DataSpec/DNACommon/DNACommon.hpp" +#include "DataSpec/DNACommon/TXTR.hpp" +#include "DataSpec/AssetNameMap.hpp" +#include "DataSpec/DNACommon/URDEVersionInfo.hpp" #include "hecl/ClientProcess.hpp" #include "nod/DiscBase.hpp" #include "nod/nod.hpp" @@ -38,11 +39,19 @@ static const hecl::SystemChar* MomErr[] = {_SYS_STR("Your metroid is in another constexpr uint32_t MomErrCount = std::extent::value; +static ERegion g_CurRegion = ERegion::Invalid; +static bool g_CurSpecIsWii = false; + +ERegion getCurrentRegion() { return g_CurRegion; } +bool isCurrentSpecWii() { return g_CurSpecIsWii; } + 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") { +, m_masterShader(project.getProjectWorkingPath(), ".hecl/RetroMasterShader.blend") +, m_region(ERegion::Invalid) +, m_game(EGame::Invalid) { AssetNameMap::InitAssetNameMap(); SpecBase::setThreadProject(); } @@ -65,7 +74,7 @@ bool SpecBase::canExtract(const ExtractPassInfo& info, std::vectorgetHeader().m_gameID[3]; + m_region = ERegion(m_disc->getHeader().m_gameID[3]); const hecl::SystemString* regstr = ®NONE; - switch (region) { - case 'E': + switch (m_region) { + case ERegion::NTSC_U: regstr = ®E; break; - case 'J': + case ERegion::NTSC_J: regstr = ®J; break; - case 'P': + case ERegion::PAL: regstr = ®P; break; + default: + break; } + setCurRegion(m_region); + setCurSpecIsWii(m_isWii); + if (m_standalone) return checkFromStandaloneDisc(*m_disc, *regstr, info.extractArgs, reps); else @@ -99,7 +113,7 @@ void SpecBase::doExtract(const ExtractPassInfo& info, const hecl::MultiProgressP setThreadProject(); DataSpec::g_curSpec.reset(this); if (!Blender::BuildMasterShader(m_masterShader)) - Log.report(logvisor::Fatal, fmt("Unable to build master shader blend")); + Log.report(logvisor::Fatal, FMT_STRING("Unable to build master shader blend")); if (m_isWii) { /* Extract root files for repacking later */ hecl::ProjectPath outDir(m_project.getProjectWorkingPath(), _SYS_STR("out")); @@ -126,8 +140,7 @@ bool IsPathAudioGroup(const hecl::ProjectPath& path) { } static bool IsPathSong(const hecl::ProjectPath& path) { - if (path.getPathType() != hecl::ProjectPath::Type::Glob || - !path.getWithExtension(_SYS_STR(".mid"), true).isFile() || + if (path.getPathType() != hecl::ProjectPath::Type::Glob || !path.getWithExtension(_SYS_STR(".mid"), true).isFile() || !path.getWithExtension(_SYS_STR(".yaml"), true).isFile()) { return path.isFile() && path.getLastComponentExt() == _SYS_STR("mid") && path.getWithExtension(_SYS_STR(".yaml"), true).isFile(); @@ -182,7 +195,7 @@ const hecl::Database::DataSpecEntry* SpecBase::overrideDataSpec(const hecl::Proj hecl::blender::BlendType type = hecl::blender::GetBlendType(asBlend.getAbsolutePath()); if (type == hecl::blender::BlendType::None) { - Log.report(logvisor::Error, fmt(_SYS_STR("unable to cook '{}'")), path.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to cook '{}'")), path.getAbsolutePath()); return nullptr; } if (type == hecl::blender::BlendType::Mesh || type == hecl::blender::BlendType::Area) @@ -309,9 +322,10 @@ void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in, std::vector hecl::SystemStringConv chSysName(sub.name); if (!sub.cskrId.empty()) { hecl::SystemStringConv cskrSysName(sub.cskrId); - pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.CSKR")), chSysName, cskrSysName))); + pathsOut.push_back( + asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.CSKR")), chSysName, cskrSysName))); } else { - pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.CSKR")), chSysName))); + pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.CSKR")), chSysName))); } const auto& arm = actor.armatures[sub.armature]; @@ -325,7 +339,8 @@ void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in, std::vector flattenDependenciesBlend(overlay.mesh, pathsOut, btok); pathsOut.push_back(overlay.mesh); } - pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.{}_{}.CSKR")), chSysName, overlaySys, overlayCskrId))); + pathsOut.push_back(asGlob.ensureAuxInfo( + fmt::format(FMT_STRING(_SYS_STR("{}.{}_{}.CSKR")), chSysName, overlaySys, overlayCskrId))); } } }; @@ -343,7 +358,8 @@ void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in, std::vector hecl::SystemStringConv chSysName(att.name); hecl::SystemStringConv sysCskrId(att.cskrId); - pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("ATTACH.{}_{}.CSKR")), chSysName, sysCskrId))); + pathsOut.push_back( + asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("ATTACH.{}_{}.CSKR")), chSysName, sysCskrId))); if (att.armature >= 0) { const auto& arm = actor.armatures[att.armature]; @@ -355,9 +371,10 @@ void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in, std::vector for (const auto& act : actNames) { hecl::SystemStringConv actSysName(act.first); hecl::SystemStringConv actAnimId(act.second); - pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.ANIM")), actSysName, actAnimId))); - hecl::SystemString searchPrefix(asGlob.getWithExtension( - fmt::format(fmt(_SYS_STR(".{}_")), actSysName).c_str(), true).getLastComponent()); + pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.ANIM")), actSysName, actAnimId))); + hecl::SystemString searchPrefix( + asGlob.getWithExtension(fmt::format(FMT_STRING(_SYS_STR(".{}_")), actSysName).c_str(), true) + .getLastComponent()); hecl::ProjectPath evntPath; for (const auto& ent : dEnum) { if (hecl::StringUtils::BeginsWith(ent.m_name, searchPrefix.c_str()) && @@ -468,7 +485,7 @@ void SpecBase::copyBuildListData(std::vector>& fileIndex.reserve(buildList.size()); int loadIdx = 0; for (const auto& tag : buildList) { - hecl::SystemString str = fmt::format(fmt(_SYS_STR("Copying {}")), tag); + hecl::SystemString str = fmt::format(FMT_STRING(_SYS_STR("Copying {}")), tag); progress.print(str.c_str(), nullptr, ++loadIdx / float(buildList.size())); auto& [positionOut, sizeOut, compressedOut] = fileIndex.emplace_back(); @@ -476,7 +493,7 @@ void SpecBase::copyBuildListData(std::vector>& if (tag.type == FOURCC('MLVL')) { auto search = mlvlData.find(tag.id); if (search == mlvlData.end()) - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to find MLVL {}")), tag.id); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to find MLVL {}")), tag.id); positionOut = pakOut.position(); sizeOut = ROUND_UP_32(search->second.size()); @@ -492,7 +509,7 @@ void SpecBase::copyBuildListData(std::vector>& hecl::ProjectPath cooked = getCookedPath(path, true); athena::io::FileReader r(cooked.getAbsolutePath()); if (r.hasError()) - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to open resource {}")), cooked.getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to open resource {}")), cooked.getRelativePath()); atUint64 size = r.length(); auto data = r.readUBytes(size); auto compData = compressPakData(tag, data.get(), size); @@ -616,7 +633,7 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da /* Async cook resource list if using ClientProcess */ if (cp) { - Log.report(logvisor::Info, fmt(_SYS_STR("Validating resources"))); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Validating resources"))); progress.setMainIndeterminate(true); std::vector cookTags; cookTags.reserve(buildList.size()); @@ -626,8 +643,7 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da std::unordered_set addedTags; addedTags.reserve(buildList.size()); for (auto& tag : buildList) { - if ((i == 0 && tag.type == FOURCC('CMDL')) || - (i == 1 && tag.type != FOURCC('CMDL'))) { + if ((i == 0 && tag.type == FOURCC('CMDL')) || (i == 1 && tag.type != FOURCC('CMDL'))) { if (addedTags.find(tag) != addedTags.end()) continue; addedTags.insert(tag); @@ -640,7 +656,7 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da for (auto& tag : cookTags) { hecl::ProjectPath depPath = pathFromTag(tag); if (!depPath) - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to resolve {}")), tag); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to resolve {}")), tag); m_project.cookPath(depPath, progress, false, false, fast, entry, cp); } progress.setMainIndeterminate(false); @@ -650,7 +666,7 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da /* Write resource data and build file index */ std::vector> fileIndex; - Log.report(logvisor::Info, fmt(_SYS_STR("Copying data into {}")), outPath.getRelativePath()); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Copying data into {}")), outPath.getRelativePath()); copyBuildListData(fileIndex, buildList, entry, fast, progress, pakOut, mlvlData); /* Write file index */ @@ -688,9 +704,9 @@ hecl::ProjectPath SpecBase::getCookedPath(const hecl::ProjectPath& working, bool return working.getCookedPath(*spec); } -static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::Error, fmt("{}"), msg); } +static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::Error, FMT_STRING("{}"), msg); } -static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, fmt("{}"), msg); } +static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, FMT_STRING("{}"), msg); } constexpr uint8_t Convert4To8(uint8_t v) { /* Swizzle bits: 00001234 -> 12341234 */ @@ -703,12 +719,12 @@ void SpecBase::extractRandomStaticEntropy(const uint8_t* buf, const hecl::Projec entropyPath.makeDirChain(false); if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) { - fmt::print(fp.get(), fmt("RandomStaticEntropy: {}\n"), entropyPath.getRelativePathUTF8()); + fmt::print(fp.get(), FMT_STRING("RandomStaticEntropy: {}\n"), entropyPath.getRelativePathUTF8()); } auto fp = hecl::FopenUnique(entropyPath.getAbsolutePath().data(), _SYS_STR("wb")); if (fp == nullptr) { - Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for writing")), entropyPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for writing")), entropyPath.getAbsolutePath()); return; } png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, PNGErr, PNGWarn); @@ -746,7 +762,7 @@ void SpecBase::clearTagCache() { } hecl::ProjectPath SpecBase::pathFromTag(const urde::SObjectTag& tag) const { - std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); + std::unique_lock lk(m_backgroundIndexMutex); auto search = m_tagToPath.find(tag); if (search != m_tagToPath.cend()) return search->second; @@ -761,7 +777,7 @@ urde::SObjectTag SpecBase::tagFromPath(const hecl::ProjectPath& path) const { } bool SpecBase::waitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut) { - std::unique_lock lk(m_backgroundIndexMutex); + std::unique_lock lk(m_backgroundIndexMutex); auto search = m_tagToPath.find(tag); if (search == m_tagToPath.end()) { if (m_backgroundRunning) { @@ -787,7 +803,7 @@ const urde::SObjectTag* SpecBase::getResourceIdByName(std::string_view name) con std::string lower(name); std::transform(lower.cbegin(), lower.cend(), lower.begin(), tolower); - std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); + std::unique_lock lk(m_backgroundIndexMutex); auto search = m_catalogNameToTag.find(lower); if (search == m_catalogNameToTag.end()) { if (m_backgroundRunning) { @@ -811,7 +827,7 @@ FourCC SpecBase::getResourceTypeById(urde::CAssetId id) const { if (!id.IsValid()) return {}; - std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); + std::unique_lock lk(m_backgroundIndexMutex); urde::SObjectTag searchTag = {FourCC(), id}; auto search = m_tagToPath.find(searchTag); if (search == m_tagToPath.end()) { @@ -852,7 +868,7 @@ void SpecBase::enumerateNamedResources( static void WriteTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObjectTag& pathTag, const hecl::ProjectPath& path) { - auto key = fmt::format(fmt("{}"), pathTag.id); + auto key = fmt::format(FMT_STRING("{}"), pathTag.id); if (auto* existing = cacheWriter.getCurNode()->findMapChild(key)) { existing->m_seqChildren.emplace_back(athena::io::ValToNode(path.getEncodableStringUTF8())); } else if (auto v = cacheWriter.enterSubVector(key)) { @@ -863,7 +879,7 @@ static void WriteTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObject static void WriteNameTag(athena::io::YAMLDocWriter& nameWriter, const urde::SObjectTag& pathTag, std::string_view name) { - nameWriter.writeString(name.data(), fmt::format(fmt("{}"), pathTag.id)); + nameWriter.writeString(name.data(), fmt::format(FMT_STRING("{}"), pathTag.id)); } void SpecBase::readCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAMLDocWriter& nameWriter) { @@ -901,13 +917,13 @@ void SpecBase::readCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAM continue; urde::SObjectTag pathTag = tagFromPath(path); if (pathTag) { - std::unique_lock lk(m_backgroundIndexMutex); + std::unique_lock lk(m_backgroundIndexMutex); m_catalogNameToTag[pLower] = pathTag; m_catalogTagToNames[pathTag].insert(p.first); WriteNameTag(nameWriter, pathTag, p.first); #if 0 - fmt::print(stderr, fmt("{} {} {:08X}\n"), p.first, pathTag.type.toString(), pathTag.id.Value()); + fmt::print(stderr, FMT_STRING("{} {} {:08X}\n"), p.first, pathTag.type.toString(), pathTag.id.Value()); #endif } } @@ -948,7 +964,7 @@ void SpecBase::insertPathTag(athena::io::YAMLDocWriter& cacheWriter, const urde: if (search != m_tagToPath.end() && search->second != path && tag.type != FOURCC('CINF') && tag.type != FOURCC('CSKR') && tag.type != FOURCC('ANIM') && tag.type != FOURCC('EVNT')) { - Log.report(logvisor::Fatal, fmt(_SYS_STR("'{}|{}' already exists for tag {} as '{}|{}'")), + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("'{}|{}' already exists for tag {} as '{}|{}'")), path.getRelativePath(), path.getAuxInfo(), tag, search->second.getRelativePath(), search->second.getAuxInfo()); } @@ -958,7 +974,7 @@ void SpecBase::insertPathTag(athena::io::YAMLDocWriter& cacheWriter, const urde: WriteTag(cacheWriter, tag, path); #if DUMP_CACHE_FILL if (dump) - fmt::print(stderr, fmt("{} {}\n"), tag, path.getRelativePathUTF8()); + fmt::print(stderr, FMT_STRING("{} {}\n"), tag, path.getRelativePathUTF8()); #endif } @@ -997,9 +1013,9 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc hecl::ProjectPath subPath; if (!sub.second.empty()) { hecl::SystemStringConv cskrId(sub.second); - subPath = asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.CSKR")), subName, cskrId)); + subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.CSKR")), subName, cskrId)); } else { - subPath = asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.CSKR")), subName)); + subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.CSKR")), subName)); } insertPathTag(cacheWriter, buildTagFromPath(subPath), subPath); @@ -1008,11 +1024,10 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc hecl::SystemStringConv overlaySys(overlay.first); hecl::SystemStringConv overlayCskrId(overlay.second); if (!overlay.second.empty()) { - subPath = - asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.{}_{}.CSKR")), subName, overlaySys, overlayCskrId)); + subPath = asGlob.ensureAuxInfo( + fmt::format(FMT_STRING(_SYS_STR("{}.{}_{}.CSKR")), subName, overlaySys, overlayCskrId)); } else { - subPath = - asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.{}.CSKR")), subName, overlaySys)); + subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.{}.CSKR")), subName, overlaySys)); } insertPathTag(cacheWriter, buildTagFromPath(subPath), subPath); } @@ -1024,11 +1039,10 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc hecl::SystemStringConv attachmentCskrId(attachment.second); hecl::ProjectPath subPath; if (!attachment.second.empty()) { - subPath = - asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("ATTACH.{}_{}.CSKR")), attachmentSys, attachmentCskrId)); + subPath = asGlob.ensureAuxInfo( + fmt::format(FMT_STRING(_SYS_STR("ATTACH.{}_{}.CSKR")), attachmentSys, attachmentCskrId)); } else { - subPath = - asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("ATTACH.{}.CSKR")), attachmentSys)); + subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("ATTACH.{}.CSKR")), attachmentSys)); } insertPathTag(cacheWriter, buildTagFromPath(subPath), subPath); } @@ -1038,9 +1052,9 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc hecl::SystemStringConv animId(act.second); hecl::ProjectPath subPath; if (!act.second.empty()) { - subPath = asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.ANIM")), sysStr, animId)); + subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.ANIM")), sysStr, animId)); } else { - subPath = asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.ANIM")), sysStr)); + subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.ANIM")), sysStr)); } insertPathTag(cacheWriter, buildTagFromPath(subPath), subPath); } @@ -1108,10 +1122,10 @@ void SpecBase::backgroundIndexProc() { if (tagCachePath.isFile()) { athena::io::FileReader reader(tagCachePath.getAbsolutePath()); if (reader.isOpen()) { - Log.report(logvisor::Info, fmt(_SYS_STR("Cache index of '{}' loading")), getOriginalSpec().m_name); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Cache index of '{}' loading")), getOriginalSpec().m_name); athena::io::YAMLDocReader cacheReader; if (cacheReader.parse(&reader)) { - std::unique_lock lk(m_backgroundIndexMutex); + std::unique_lock lk(m_backgroundIndexMutex); size_t tagCount = cacheReader.getRootNode()->m_mapChildren.size(); m_tagToPath.reserve(tagCount); m_pathToTag.reserve(tagCount); @@ -1134,20 +1148,20 @@ void SpecBase::backgroundIndexProc() { ++loadIdx; if (!(loadIdx % 100)) - fmt::print(stderr, fmt("\r {} / {}"), loadIdx, tagCount); + fmt::print(stderr, FMT_STRING("\r {} / {}"), loadIdx, tagCount); } - fmt::print(stderr, fmt("\r {} / {}\n"), loadIdx, tagCount); + fmt::print(stderr, FMT_STRING("\r {} / {}\n"), loadIdx, tagCount); } - Log.report(logvisor::Info, fmt(_SYS_STR("Cache index of '{}' loaded; {} tags")), getOriginalSpec().m_name, + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Cache index of '{}' loaded; {} tags")), getOriginalSpec().m_name, m_tagToPath.size()); if (nameCachePath.isFile()) { /* Read in name cache */ - Log.report(logvisor::Info, fmt(_SYS_STR("Name index of '{}' loading")), getOriginalSpec().m_name); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Name index of '{}' loading")), getOriginalSpec().m_name); athena::io::FileReader nreader(nameCachePath.getAbsolutePath()); athena::io::YAMLDocReader nameReader; if (nameReader.parse(&nreader)) { - std::unique_lock lk(m_backgroundIndexMutex); + 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) { @@ -1162,13 +1176,13 @@ void SpecBase::backgroundIndexProc() { } } } - Log.report(logvisor::Info, fmt(_SYS_STR("Name index of '{}' loaded; {} names")), getOriginalSpec().m_name, - m_catalogNameToTag.size()); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Name index of '{}' loaded; {} names")), + getOriginalSpec().m_name, m_catalogNameToTag.size()); } } } - Log.report(logvisor::Info, fmt(_SYS_STR("Background index of '{}' started")), getOriginalSpec().m_name); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Background index of '{}' started")), getOriginalSpec().m_name); backgroundIndexRecursiveProc(specRoot, cacheWriter, nameWriter, 0); tagCachePath.makeDirChain(false); @@ -1179,7 +1193,7 @@ void SpecBase::backgroundIndexProc() { nameWriter.finish(&nwriter); m_backgroundBlender.shutdown(); - Log.report(logvisor::Info, fmt(_SYS_STR("Background index of '{}' complete; {} tags, {} names")), + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Background index of '{}' complete; {} tags, {} names")), getOriginalSpec().m_name, m_tagToPath.size(), m_catalogNameToTag.size()); m_backgroundRunning = false; } @@ -1198,7 +1212,7 @@ void SpecBase::beginBackgroundIndex() { } void SpecBase::waitForIndexComplete() const { - std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); + std::unique_lock lk(m_backgroundIndexMutex); while (m_backgroundRunning) { lk.unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(2)); @@ -1206,4 +1220,23 @@ void SpecBase::waitForIndexComplete() const { } } +void SpecBase::WriteVersionInfo(hecl::Database::Project& project, const hecl::ProjectPath& pakPath) { + hecl::ProjectPath versionPath(pakPath, _SYS_STR("version.yaml")); + versionPath.makeDirChain(false); + + URDEVersionInfo info; + info.version = m_version; + info.region = m_region; + info.game = m_game; + info.isTrilogy = !m_standalone; + athena::io::FileWriter writer(versionPath.getAbsolutePath()); + athena::io::ToYAMLStream(info, writer); +} +void SpecBase::setCurRegion(ERegion region) { + g_CurRegion = region; +} +void SpecBase::setCurSpecIsWii(bool isWii) { + g_CurSpecIsWii = isWii; +} + } // namespace DataSpec diff --git a/DataSpec/SpecBase.hpp b/DataSpec/SpecBase.hpp index 1e62eab09..00a41d7b3 100644 --- a/DataSpec/SpecBase.hpp +++ b/DataSpec/SpecBase.hpp @@ -23,6 +23,10 @@ class YAMLDocWriter; } // namespace athena::io namespace DataSpec { +enum class ERegion; +enum class EGame; +ERegion getCurrentRegion(); +bool isCurrentSpecWii(); struct SpecBase : hecl::Database::IDataSpec { /* HECL Adaptors */ @@ -175,12 +179,12 @@ protected: hecl::blender::Token m_backgroundBlender; std::thread m_backgroundIndexTh; - std::mutex m_backgroundIndexMutex; + mutable std::mutex m_backgroundIndexMutex; bool m_backgroundRunning = false; void readCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAMLDocWriter& nameWriter); - void insertPathTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObjectTag& tag, - const hecl::ProjectPath& path, bool dump = true); + void insertPathTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObjectTag& tag, const hecl::ProjectPath& path, + bool dump = true); 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); @@ -197,8 +201,16 @@ protected: const std::unordered_map>& mlvlData); std::unique_ptr m_disc; - bool m_isWii; - bool m_standalone; + bool m_isWii{}; + bool m_standalone{}; + ERegion m_region; + EGame m_game; + std::string m_version; + + void WriteVersionInfo(hecl::Database::Project& project, const hecl::ProjectPath& pakPath); + + static void setCurRegion(ERegion region); + static void setCurSpecIsWii(bool isWii); }; bool IsPathAudioGroup(const hecl::ProjectPath& path); diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index c98a0a940..a7dea7ec6 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -29,6 +29,7 @@ #include "DNACommon/DPSC.hpp" #include "DNACommon/DGRP.hpp" #include "DNACommon/MAPU.hpp" +#include "DNACommon/URDEVersionInfo.hpp" #include "DNACommon/Tweaks/TweakWriter.hpp" #include "DNAMP1/Tweaks/CTweakPlayerRes.hpp" #include "DNAMP1/Tweaks/CTweakGunRes.hpp" @@ -46,7 +47,6 @@ #include "DNAMP1/Tweaks/CTweakPlayerGun.hpp" #include "DNAMP1/MazeSeeds.hpp" #include "DNAMP1/SnowForces.hpp" - #include "hecl/ClientProcess.hpp" #include "hecl/MultiProgressPrinter.hpp" #include "hecl/Blender/Connection.hpp" @@ -63,15 +63,17 @@ extern hecl::Database::DataSpecEntry SpecEntMP1PC; extern hecl::Database::DataSpecEntry SpecEntMP1ORIG; struct TextureCache { - static void Generate(PAKRouter& pakRouter, hecl::Database::Project& project, const hecl::ProjectPath& pakPath) { + static void Generate(PAKRouter& pakRouter, hecl::Database::Project& project, + const hecl::ProjectPath& pakPath) { hecl::ProjectPath texturePath(pakPath, _SYS_STR("texture_cache.yaml")); hecl::ProjectPath catalogPath(pakPath, _SYS_STR("!catalog.yaml")); + texturePath.makeDirChain(false); if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) { - fmt::print(fp.get(), fmt("TextureCache: {}\n"), texturePath.getRelativePathUTF8()); + fmt::print(fp.get(), FMT_STRING("TextureCache: {}\n"), texturePath.getRelativePathUTF8()); } - Log.report(logvisor::Level::Info, fmt("Gathering Texture metadata (this can take up to 10 seconds)...")); + Log.report(logvisor::Level::Info, FMT_STRING("Gathering Texture metadata (this can take up to 10 seconds)...")); std::unordered_map metaMap; pakRouter.enumerateResources([&](const DNAMP1::PAK::Entry* ent) { @@ -91,7 +93,7 @@ struct TextureCache { athena::io::FileWriter fileW(texturePath.getAbsolutePath()); yamlW.finish(&fileW); - Log.report(logvisor::Level::Info, fmt("Done...")); + Log.report(logvisor::Level::Info, FMT_STRING("Done...")); } static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { @@ -111,9 +113,8 @@ struct TextureCache { metaPairs.emplace_back(projectPath.parsedHash32(), meta); } - std::sort(metaPairs.begin(), metaPairs.end(), [](const auto& a, const auto& b) -> bool { - return a.first < b.first; - }); + std::sort(metaPairs.begin(), metaPairs.end(), + [](const auto& a, const auto& b) -> bool { return a.first < b.first; }); athena::io::FileWriter w(outPath.getAbsolutePath()); w.writeUint32Big(metaPairs.size()); @@ -144,7 +145,8 @@ struct SpecMP1 : SpecBase { , m_workPath(project.getProjectWorkingPath(), _SYS_STR("MP1")) , m_cookPath(project.getProjectCookedPath(SpecEntMP1), _SYS_STR("MP1")) , m_pakRouter(*this, m_workPath, m_cookPath) { - setThreadProject(); + m_game = EGame::MetroidPrime1; + SpecBase::setThreadProject(); } void buildPaks(nod::Node& root, const std::vector& args, ExtractReport& rep) { @@ -196,8 +198,9 @@ struct SpecMP1 : SpecBase { /* Sort PAKs alphabetically */ m_orderedPaks.clear(); - for (DNAMP1::PAKBridge& dpak : m_paks) + for (DNAMP1::PAKBridge& dpak : m_paks) { m_orderedPaks[std::string(dpak.getName())] = &dpak; + } /* Assemble extract report */ rep.childOpts.reserve(m_orderedPaks.size()); @@ -217,18 +220,19 @@ struct SpecMP1 : SpecBase { const std::vector& args, std::vector& reps) override { nod::IPartition* partition = disc.getDataPartition(); m_dolBuf = partition->getDOLBuf(); - const char* buildInfo = (char*)memmem(m_dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19; + const char* buildInfo = + static_cast(memmem(m_dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16)) + 19; - if (!buildInfo) + if (buildInfo == nullptr) return false; + m_version = std::string(buildInfo); /* Root Report */ ExtractReport& rep = reps.emplace_back(); rep.name = _SYS_STR("MP1"); rep.desc = _SYS_STR("Metroid Prime ") + regstr; if (buildInfo) { - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); + hecl::SystemStringConv buildView(m_version); rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); } @@ -274,15 +278,15 @@ struct SpecMP1 : SpecBase { } m_dolBuf = dolIt->getBuf(); - const char* buildInfo = (char*)memmem(m_dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19; + const char* buildInfo = static_cast(memmem(m_dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16)) + 19; /* Root Report */ ExtractReport& rep = reps.emplace_back(); rep.name = _SYS_STR("MP1"); rep.desc = _SYS_STR("Metroid Prime ") + regstr; - if (buildInfo) { - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); + if (buildInfo != nullptr) { + m_version = std::string(buildInfo); + hecl::SystemStringConv buildView(m_version); rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); } @@ -377,6 +381,14 @@ struct SpecMP1 : SpecBase { /* Generate Texture Cache containing meta data for every texture file */ TextureCache::Generate(m_pakRouter, m_project, noAramPath); + /* Write version data */ + hecl::ProjectPath versionPath; + if (m_standalone) { + versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files")); + } else { + versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files/MP1")); + } + WriteVersionInfo(m_project, versionPath); return true; } @@ -416,7 +428,9 @@ struct SpecMP1 : SpecBase { return true; else if (classType == DNAFont::FONT::DNAType()) return true; - else if (classType == DNAMP1::CTweakPlayerRes::DNAType()) + else if (classType == DNAMP1::CTweakPlayerRes::DNAType()) + return true; + else if (classType == DNAMP1::CTweakPlayerRes::DNAType()) return true; else if (classType == DNAMP1::CTweakGunRes::DNAType()) return true; @@ -430,7 +444,9 @@ struct SpecMP1 : SpecBase { return true; else if (classType == DNAMP1::CTweakAutoMapper::DNAType()) return true; - else if (classType == DNAMP1::CTweakTargeting::DNAType()) + else if (classType == DNAMP1::CTweakTargeting::DNAType()) + return true; + else if (classType == DNAMP1::CTweakTargeting::DNAType()) return true; else if (classType == DNAMP1::CTweakGui::DNAType()) return true; @@ -571,13 +587,15 @@ struct SpecMP1 : SpecBase { } else if (className == DataSpec::DNAMP1::SCAN::DNAType()) { resTag.type = SBIG('SCAN'); return true; - } else if (className == DataSpec::DNAMP1::CTweakPlayerRes::DNAType() || + } else if (className == DataSpec::DNAMP1::CTweakPlayerRes::DNAType() || + className == DataSpec::DNAMP1::CTweakPlayerRes::DNAType() || className == DataSpec::DNAMP1::CTweakGunRes::DNAType() || className == DataSpec::DNAMP1::CTweakSlideShow::DNAType() || className == DataSpec::DNAMP1::CTweakPlayer::DNAType() || className == DataSpec::DNAMP1::CTweakCameraBob::DNAType() || className == DataSpec::DNAMP1::CTweakGame::DNAType() || - className == DataSpec::DNAMP1::CTweakTargeting::DNAType() || + className == DataSpec::DNAMP1::CTweakTargeting::DNAType() || + className == DataSpec::DNAMP1::CTweakTargeting::DNAType() || className == DataSpec::DNAMP1::CTweakAutoMapper::DNAType() || className == DataSpec::DNAMP1::CTweakGui::DNAType() || className == DataSpec::DNAMP1::CTweakPlayerControl::DNAType() || @@ -626,7 +644,7 @@ struct SpecMP1 : SpecBase { pathPrefix += pakName; pathPrefix += '/'; - std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); + std::unique_lock lk(m_backgroundIndexMutex); for (const auto& tag : m_tagToPath) if (!tag.second.getRelativePathUTF8().compare(0, pathPrefix.size(), pathPrefix)) out.push_back(tag.first); @@ -739,7 +757,8 @@ struct SpecMP1 : SpecBase { } if (!colMesh) - Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to find mesh named 'CMESH' in {}")), in.getAbsolutePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to find mesh named 'CMESH' in {}")), + in.getAbsolutePath()); std::vector lights = ds.compileLights(); @@ -821,8 +840,12 @@ struct SpecMP1 : SpecBase { DNAFont::FONT font; font.read(reader); DNAFont::WriteFONT(font, out); - } else if (classStr == DNAMP1::CTweakPlayerRes::DNAType()) { - DNAMP1::CTweakPlayerRes playerRes; + } else if (classStr == DNAMP1::CTweakPlayerRes::DNAType()) { + DNAMP1::CTweakPlayerRes playerRes; + playerRes.read(reader); + WriteTweak(playerRes, out); + } else if (classStr == DNAMP1::CTweakPlayerRes::DNAType()) { + DNAMP1::CTweakPlayerRes playerRes; playerRes.read(reader); WriteTweak(playerRes, out); } else if (classStr == DNAMP1::CTweakGunRes::DNAType()) { @@ -849,8 +872,12 @@ struct SpecMP1 : SpecBase { DNAMP1::CTweakAutoMapper autoMapper; autoMapper.read(reader); WriteTweak(autoMapper, out); - } else if (classStr == DNAMP1::CTweakTargeting::DNAType()) { - DNAMP1::CTweakTargeting targeting; + } else if (classStr == DNAMP1::CTweakTargeting::DNAType()) { + DNAMP1::CTweakTargeting targeting; + targeting.read(reader); + WriteTweak(targeting, out); + } else if (classStr == DNAMP1::CTweakTargeting::DNAType()) { + DNAMP1::CTweakTargeting targeting; targeting.read(reader); WriteTweak(targeting, out); } else if (classStr == DNAMP1::CTweakGui::DNAType()) { @@ -977,7 +1004,7 @@ struct SpecMP1 : SpecBase { { athena::io::FileReader r(worldPathCooked.getAbsolutePath()); if (r.hasError()) - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to open world {}")), worldPathCooked.getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to open world {}")), worldPathCooked.getRelativePath()); mlvl.read(r); } @@ -1073,10 +1100,10 @@ struct SpecMP1 : SpecBase { if (hecl::ProjectPath mapCookedPath = getCookedPath(mapPath, true)) { athena::io::FileReader r(mapCookedPath.getAbsolutePath()); if (r.hasError()) - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to open {}")), mapCookedPath.getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to open {}")), mapCookedPath.getRelativePath()); if (r.readUint32Big() != 0xDEADF00D) - Log.report(logvisor::Fatal, fmt(_SYS_STR("Corrupt MAPW {}")), mapCookedPath.getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Corrupt MAPW {}")), mapCookedPath.getRelativePath()); r.readUint32Big(); atUint32 mapaCount = r.readUint32Big(); for (atUint32 i = 0; i < mapaCount; ++i) { @@ -1099,7 +1126,7 @@ struct SpecMP1 : SpecBase { for (const auto& tex : textures) { urde::SObjectTag texTag = tagFromPath(tex); if (!texTag) - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to resolve {}")), tex.getRelativePath()); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to resolve {}")), tex.getRelativePath()); listOut.push_back(texTag); } } @@ -1130,7 +1157,8 @@ struct SpecMP1 : SpecBase { } void buildPakList(hecl::blender::Token& btok, athena::io::FileWriter& w, const std::vector& list, - const std::vector>& nameList, atUint64& resTableOffset) override { + const std::vector>& nameList, + atUint64& resTableOffset) override { w.writeUint32Big(m_pc ? 0x80030005 : 0x00030005); w.writeUint32Big(0); diff --git a/DataSpec/SpecMP2.cpp b/DataSpec/SpecMP2.cpp index 8111b2400..dad6eaa58 100644 --- a/DataSpec/SpecMP2.cpp +++ b/DataSpec/SpecMP2.cpp @@ -6,9 +6,13 @@ #include "DNAMP2/MLVL.hpp" #include "DNAMP2/STRG.hpp" #include "DNAMP2/AGSC.hpp" +#include "DNAMP2/PATH.hpp" #include "DNAMP2/MAPA.hpp" #include "DNAMP1/CSNG.hpp" #include "DNACommon/MAPU.hpp" +#include "DNACommon/PATH.hpp" +#include "DNACommon/TXTR.hpp" +#include "DNACommon/URDEVersionInfo.hpp" #include "hecl/ClientProcess.hpp" #include "hecl/Blender/Connection.hpp" @@ -25,6 +29,69 @@ static logvisor::Module Log("urde::SpecMP2"); extern hecl::Database::DataSpecEntry SpecEntMP2; extern hecl::Database::DataSpecEntry SpecEntMP2ORIG; +struct TextureCache { + static void Generate(PAKRouter& pakRouter, hecl::Database::Project& project, const hecl::ProjectPath& pakPath) { + hecl::ProjectPath texturePath(pakPath, _SYS_STR("texture_cache.yaml")); + hecl::ProjectPath catalogPath(pakPath, _SYS_STR("!catalog.yaml")); + texturePath.makeDirChain(false); + + if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) { + fmt::print(fp.get(), FMT_STRING("TextureCache: {}\n"), texturePath.getRelativePathUTF8()); + } + + Log.report(logvisor::Level::Info, FMT_STRING("Gathering Texture metadata (this can take up to 10 seconds)...")); + std::unordered_map metaMap; + + pakRouter.enumerateResources([&](const DNAMP2::PAK::Entry* ent) { + if (ent->type == FOURCC('TXTR') && metaMap.find(ent->id) == metaMap.end()) { + PAKEntryReadStream rs = pakRouter.beginReadStreamForId(ent->id); + metaMap[ent->id] = TXTR::GetMetaData(rs); + } + return true; + }); + + athena::io::YAMLDocWriter yamlW("MP2TextureCache"); + for (const auto& pair : metaMap) { + hecl::ProjectPath path = pakRouter.getWorking(pair.first); + auto rec = yamlW.enterSubRecord(path.getRelativePathUTF8()); + pair.second.write(yamlW); + } + + athena::io::FileWriter fileW(texturePath.getAbsolutePath()); + yamlW.finish(&fileW); + Log.report(logvisor::Level::Info, FMT_STRING("Done...")); + } + + 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> metaPairs; + metaPairs.reserve(r.getRootNode()->m_mapChildren.size()); + for (const auto& node : r.getRootNode()->m_mapChildren) { + hecl::ProjectPath projectPath(project, node.first); + auto rec = r.enterSubRecord(node.first.c_str()); + TXTR::Meta meta; + meta.read(r); + metaPairs.emplace_back(projectPath.parsedHash32(), meta); + } + + std::sort(metaPairs.begin(), metaPairs.end(), [](const auto& a, const auto& b) -> bool { + return a.first < b.first; + }); + + athena::io::FileWriter w(outPath.getAbsolutePath()); + w.writeUint32Big(metaPairs.size()); + for (const auto& pair : metaPairs) { + pair.first.write(w); + pair.second.write(w); + } + } +}; + struct SpecMP2 : SpecBase { bool checkStandaloneID(const char* id) const override { if (!memcmp(id, "G2M", 3)) @@ -45,7 +112,8 @@ struct SpecMP2 : SpecBase { , m_workPath(project.getProjectWorkingPath(), _SYS_STR("MP2")) , m_cookPath(project.getProjectCookedPath(SpecEntMP2), _SYS_STR("MP2")) , m_pakRouter(*this, m_workPath, m_cookPath) { - setThreadProject(); + m_game = EGame::MetroidPrime2; + SpecBase::setThreadProject(); } void buildPaks(nod::Node& root, const std::vector& args, ExtractReport& rep) { @@ -117,16 +185,17 @@ struct SpecMP2 : SpecBase { const std::vector& args, std::vector& reps) override { 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) + const char* buildInfo = static_cast(memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16)) + 19; + if (buildInfo == nullptr) { return false; + } + m_version = std::string(buildInfo); /* Root Report */ ExtractReport& rep = reps.emplace_back(); rep.name = _SYS_STR("MP2"); rep.desc = _SYS_STR("Metroid Prime 2 ") + regstr; - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); + hecl::SystemStringConv buildView(m_version); rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); /* Iterate PAKs and build level options */ @@ -140,7 +209,7 @@ struct SpecMP2 : SpecBase { const std::vector& args, std::vector& reps) override { std::vector mp2args; bool doExtract = false; - if (args.size()) { + if (!args.empty()) { /* Needs filter */ for (const hecl::SystemString& arg : args) { hecl::SystemString lowerArg = arg; @@ -171,15 +240,15 @@ struct SpecMP2 : SpecBase { } std::unique_ptr dolBuf = dolIt->getBuf(); - const char* buildInfo = (char*)memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19; + const char* buildInfo = static_cast(memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16)) + 19; /* Root Report */ ExtractReport& rep = reps.emplace_back(); rep.name = _SYS_STR("MP2"); rep.desc = _SYS_STR("Metroid Prime 2 ") + regstr; - if (buildInfo) { - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); + if (buildInfo != nullptr) { + m_version = std::string(buildInfo); + hecl::SystemStringConv buildView(m_version); rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); } @@ -247,6 +316,18 @@ struct SpecMP2 : SpecBase { process.waitUntilComplete(); + /* Generate Texture Cache containing meta data for every texture file */ + hecl::ProjectPath noAramPath(m_project.getProjectWorkingPath(), _SYS_STR("MP2/URDE")); + TextureCache::Generate(m_pakRouter, m_project, noAramPath); + + /* Write version data */ + hecl::ProjectPath versionPath; + if (m_standalone) { + versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files")); + } else { + versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files/MP2")); + } + WriteVersionInfo(m_project, versionPath); return true; } @@ -286,7 +367,11 @@ struct SpecMP2 : SpecBase { hecl::blender::Token& btok, FCookProgress progress) override {} void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, - hecl::blender::Token& btok, FCookProgress progress) override {} + hecl::blender::Token& btok, FCookProgress progress) override { + PathMesh mesh = ds.compilePathMesh(); + ds.close(); + DNAMP2::PATH::Cook(out, in, mesh, btok); + } void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, hecl::blender::Token& btok, FCookProgress progress) override {} diff --git a/DataSpec/SpecMP3.cpp b/DataSpec/SpecMP3.cpp index 632d3c68d..83bd3da8e 100644 --- a/DataSpec/SpecMP3.cpp +++ b/DataSpec/SpecMP3.cpp @@ -1,13 +1,15 @@ #include #include -#include "SpecBase.hpp" -#include "DNAMP3/DNAMP3.hpp" +#include "DataSpec/SpecBase.hpp" +#include "DataSpec/DNAMP3/DNAMP3.hpp" -#include "DNAMP3/MLVL.hpp" -#include "DNAMP3/STRG.hpp" -#include "DNAMP3/MAPA.hpp" -#include "DNAMP2/STRG.hpp" +#include "DataSpec/DNAMP3/MLVL.hpp" +#include "DataSpec/DNAMP3/STRG.hpp" +#include "DataSpec/DNAMP3/MAPA.hpp" +#include "DataSpec/DNAMP2/STRG.hpp" +#include "DataSpec/DNACommon/TXTR.hpp" +#include "DataSpec/DNACommon/URDEVersionInfo.hpp" #include "hecl/ClientProcess.hpp" #include "hecl/Blender/Connection.hpp" @@ -24,13 +26,72 @@ static logvisor::Module Log("urde::SpecMP3"); extern hecl::Database::DataSpecEntry SpecEntMP3; extern hecl::Database::DataSpecEntry SpecEntMP3ORIG; -struct SpecMP3 : SpecBase { - bool checkStandaloneID(const char* id) const override { - if (!memcmp(id, "RM3", 3)) +struct TextureCache { + static void Generate(PAKRouter& pakRouter, hecl::Database::Project& project, const hecl::ProjectPath& pakPath) { + hecl::ProjectPath texturePath(pakPath, _SYS_STR("texture_cache.yaml")); + hecl::ProjectPath catalogPath(pakPath, _SYS_STR("!catalog.yaml")); + texturePath.makeDirChain(false); + + if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) { + fmt::print(fp.get(), FMT_STRING("TextureCache: {}\n"), texturePath.getRelativePathUTF8()); + } + + Log.report(logvisor::Level::Info, FMT_STRING("Gathering Texture metadata (this can take up to 10 seconds)...")); + std::unordered_map metaMap; + + pakRouter.enumerateResources([&](const DNAMP3::PAK::Entry* ent) { + if (ent->type == FOURCC('TXTR') && metaMap.find(ent->id) == metaMap.end()) { + PAKEntryReadStream rs = pakRouter.beginReadStreamForId(ent->id); + metaMap[ent->id] = TXTR::GetMetaData(rs); + } return true; - return false; + }); + + athena::io::YAMLDocWriter yamlW("MP3TextureCache"); + for (const auto& pair : metaMap) { + hecl::ProjectPath path = pakRouter.getWorking(pair.first); + auto rec = yamlW.enterSubRecord(path.getRelativePathUTF8()); + pair.second.write(yamlW); + } + + athena::io::FileWriter fileW(texturePath.getAbsolutePath()); + yamlW.finish(&fileW); + Log.report(logvisor::Level::Info, FMT_STRING("Done...")); } + 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> metaPairs; + metaPairs.reserve(r.getRootNode()->m_mapChildren.size()); + for (const auto& node : r.getRootNode()->m_mapChildren) { + hecl::ProjectPath projectPath(project, node.first); + auto rec = r.enterSubRecord(node.first.c_str()); + TXTR::Meta meta; + meta.read(r); + metaPairs.emplace_back(projectPath.parsedHash32(), meta); + } + + std::sort(metaPairs.begin(), metaPairs.end(), [](const auto& a, const auto& b) -> bool { + return a.first < b.first; + }); + + athena::io::FileWriter w(outPath.getAbsolutePath()); + w.writeUint32Big(metaPairs.size()); + for (const auto& pair : metaPairs) { + pair.first.write(w); + pair.second.write(w); + } + } +}; + +struct SpecMP3 : SpecBase { + bool checkStandaloneID(const char* id) const override { return memcmp(id, "RM3", 3) == 0; } + bool doMP3 = false; std::vector m_nonPaks; std::vector m_paks; @@ -58,7 +119,8 @@ struct SpecMP3 : SpecBase { , m_feWorkPath(project.getProjectWorkingPath(), _SYS_STR("fe")) , m_feCookPath(project.getProjectCookedPath(SpecEntMP3), _SYS_STR("fe")) , m_fePakRouter(*this, m_feWorkPath, m_feCookPath) { - setThreadProject(); + m_game = EGame::MetroidPrime3; + SpecBase::setThreadProject(); } void buildPaks(nod::Node& root, const std::vector& args, ExtractReport& rep, bool fe) { @@ -159,20 +221,22 @@ struct SpecMP3 : SpecBase { 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) + const char* buildInfo = static_cast(memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16)) + 19; + if (buildInfo == nullptr) { return false; + } /* We don't want no stinking demo dammit */ - if (!strcmp(buildInfo, "Build v3.068 3/2/2006 14:55:13")) + if (strcmp(buildInfo, "Build v3.068 3/2/2006 14:55:13") == 0) { return false; + } + m_version = std::string(buildInfo); /* Root Report */ ExtractReport& rep = reps.emplace_back(); rep.name = _SYS_STR("MP3"); rep.desc = _SYS_STR("Metroid Prime 3 ") + regstr; - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); + hecl::SystemStringConv buildView(m_version); rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); /* Iterate PAKs and build level options */ @@ -253,8 +317,8 @@ struct SpecMP3 : SpecBase { rep.name = _SYS_STR("MP3"); rep.desc = _SYS_STR("Metroid Prime 3 ") + regstr; - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); + m_version = std::string(buildInfo); + hecl::SystemStringConv buildView(m_version); rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); /* Iterate PAKs and build level options */ @@ -410,6 +474,19 @@ struct SpecMP3 : SpecBase { process.waitUntilComplete(); } + + /* Extract part of .dol for RandomStatic entropy */ + hecl::ProjectPath noAramPath(m_project.getProjectWorkingPath(), _SYS_STR("MP3/URDE")); + /* Generate Texture Cache containing meta data for every texture file */ + TextureCache::Generate(m_pakRouter, m_project, noAramPath); + /* Write version data */ + hecl::ProjectPath versionPath; + if (m_standalone) { + versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files")); + } else { + versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files/MP3")); + } + WriteVersionInfo(m_project, versionPath); return true; } diff --git a/Editor/ProjectManager.cpp b/Editor/ProjectManager.cpp index a32454488..90ab66886 100644 --- a/Editor/ProjectManager.cpp +++ b/Editor/ProjectManager.cpp @@ -48,7 +48,7 @@ ProjectManager::ProjectManager(ViewManager& vm) bool ProjectManager::newProject(hecl::SystemStringView path) { hecl::ProjectRootPath projPath = hecl::SearchForProject(path); if (projPath) { - Log.report(logvisor::Warning, fmt(_SYS_STR("project already exists at '{}'")), path); + Log.report(logvisor::Warning, FMT_STRING(_SYS_STR("project already exists at '{}'")), path); return false; } @@ -63,7 +63,7 @@ bool ProjectManager::newProject(hecl::SystemStringView path) { m_vm.SetupEditorView(); saveProject(); - m_vm.m_mainWindow->setTitle(fmt::format(fmt(_SYS_STR("{} - URDE [{}]")), + m_vm.m_mainWindow->setTitle(fmt::format(FMT_STRING(_SYS_STR("{} - URDE [{}]")), m_proj->getProjectRootPath().getLastComponent(), m_vm.platformName())); m_vm.DismissSplash(); m_vm.FadeInEditors(); @@ -75,7 +75,7 @@ bool ProjectManager::openProject(hecl::SystemStringView path) { hecl::SystemString subPath; hecl::ProjectRootPath projPath = hecl::SearchForProject(path, subPath); if (!projPath) { - Log.report(logvisor::Warning, fmt(_SYS_STR("project doesn't exist at '{}'")), path); + Log.report(logvisor::Warning, FMT_STRING(_SYS_STR("project doesn't exist at '{}'")), path); return false; } @@ -103,7 +103,7 @@ bool ProjectManager::openProject(hecl::SystemStringView path) { if (needsSave) saveProject(); - m_vm.m_mainWindow->setTitle(fmt::format(fmt(_SYS_STR("{} - URDE [{}]")), + m_vm.m_mainWindow->setTitle(fmt::format(FMT_STRING(_SYS_STR("{} - URDE [{}]")), m_proj->getProjectRootPath().getLastComponent(), m_vm.platformName())); m_vm.DismissSplash(); m_vm.FadeInEditors(); diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index 52a398036..5bf32e6ea 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -22,7 +22,7 @@ void ProjectResourceFactoryBase::BeginBackgroundIndex(hecl::Database::Project& p } bool ProjectResourceFactoryBase::SyncCook(const hecl::ProjectPath& working) { - Log.report(logvisor::Warning, fmt(_SYS_STR("sync-cooking {}")), working.getRelativePath()); + Log.report(logvisor::Warning, FMT_STRING(_SYS_STR("sync-cooking {}")), working.getRelativePath()); return m_clientProc.syncCook(working, m_cookSpec.get(), hecl::blender::SharedBlenderToken, false, false); } @@ -38,12 +38,12 @@ CFactoryFnReturn ProjectResourceFactoryBase::BuildSync(const SObjectTag& tag, co 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, fmt("sync-built {}"), tag); + Log.report(logvisor::Info, FMT_STRING("sync-built {}"), tag); return ret; } CFactoryFnReturn ret = m_factoryMgr.MakeObject(tag, *fr, paramXfer, selfRef); - Log.report(logvisor::Info, fmt("sync-built {}"), tag); + Log.report(logvisor::Info, FMT_STRING("sync-built {}"), tag); return ret; } @@ -53,7 +53,7 @@ void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& t /* Ensure requested resource is on the filesystem */ if (!path.isFileOrGlob()) { - Log.report(logvisor::Error, fmt(_SYS_STR("unable to find resource path '{}'")), path.getRelativePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to find resource path '{}'")), path.getRelativePath()); m_failed = true; return; } @@ -66,7 +66,7 @@ void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& t /* Last chance type validation */ urde::SObjectTag verifyTag = m_parent.TagFromPath(path); if (verifyTag.type != tag.type) { - Log.report(logvisor::Error, fmt(_SYS_STR("{}: expected type '{}', found '{}'")), path.getRelativePath(), + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("{}: expected type '{}', found '{}'")), path.getRelativePath(), tag.type, verifyTag.type); m_failed = true; return; @@ -91,7 +91,7 @@ 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, fmt(_SYS_STR("unable to open cooked resource path '{}'")), m_cookedPath.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to open cooked resource path '{}'")), m_cookedPath.getAbsolutePath()); m_failed = true; return; } @@ -171,7 +171,7 @@ bool ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, const he std::optional& fr) { /* Ensure requested resource is on the filesystem */ if (!path.isFileOrGlob()) { - Log.report(logvisor::Error, fmt(_SYS_STR("unable to find resource path '{}'")), path.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to find resource path '{}'")), path.getAbsolutePath()); return false; } @@ -183,7 +183,7 @@ bool ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, const he /* Last chance type validation */ urde::SObjectTag verifyTag = TagFromPath(path); if (verifyTag.type != tag.type) { - Log.report(logvisor::Error, fmt(_SYS_STR("{}: expected type '{}', found '{}'")), path.getRelativePath(), + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("{}: expected type '{}', found '{}'")), path.getRelativePath(), tag.type, verifyTag.type); return false; } @@ -195,7 +195,7 @@ bool ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, const he if (!cooked.isFile() || cooked.getModtime() < path.getModtime()) { /* Do a blocking cook here */ if (!SyncCook(path)) { - Log.report(logvisor::Error, fmt(_SYS_STR("unable to cook resource path '{}'")), path.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to cook resource path '{}'")), path.getAbsolutePath()); return false; } } @@ -204,7 +204,7 @@ bool ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, const he /* Ensure cooked rep is on the filesystem */ fr.emplace(cooked.getAbsolutePath(), 32 * 1024, false); if (fr->hasError()) { - Log.report(logvisor::Error, fmt(_SYS_STR("unable to open cooked resource path '{}'")), cooked.getAbsolutePath()); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to open cooked resource path '{}'")), cooked.getAbsolutePath()); return false; } @@ -215,7 +215,7 @@ std::unique_ptr ProjectResourceFactoryBase::Build(const urde::SObjec const urde::CVParamTransfer& paramXfer, CObjectReference* selfRef) { if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, fmt("attempted to access null id on type '{}'"), tag.type); + Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id on type '{}'"), tag.type); const hecl::ProjectPath* resPath = nullptr; if (!WaitForTagReady(tag, resPath)) @@ -243,14 +243,14 @@ std::unique_ptr ProjectResourceFactoryBase::Build(const urde::SObjec } //*task.xc_targetObjPtr = newObj.get(); - Log.report(logvisor::Warning, fmt("spin-built {}"), task.x0_tag); + Log.report(logvisor::Warning, FMT_STRING("spin-built {}"), task.x0_tag); _RemoveTask(asyncSearch); return newObj; } else if (task.m_complete) { - Log.report(logvisor::Error, fmt("unable to spin-build {}; Resource requested as cook-only"), task.x0_tag); + Log.report(logvisor::Error, FMT_STRING("unable to spin-build {}; Resource requested as cook-only"), task.x0_tag); } else { - Log.report(logvisor::Error, fmt("unable to spin-build {}"), task.x0_tag); + Log.report(logvisor::Error, FMT_STRING("unable to spin-build {}"), task.x0_tag); } _RemoveTask(asyncSearch); @@ -273,14 +273,14 @@ std::shared_ptr ProjectResourceFactoryBase::BuildAsyncInternal(const 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, fmt("attempted to access null id on type '{}'"), tag.type); + Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id on type '{}'"), tag.type); BuildAsyncInternal(tag, paramXfer, objOut, selfRef); } u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag) { if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, fmt("attempted to access null id on type '{}'"), tag.type); + Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id on type '{}'"), tag.type); /* Ensure resource at requested path is indexed and not cooking */ const hecl::ProjectPath* resPath = nullptr; @@ -298,7 +298,7 @@ u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag) { std::shared_ptr ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag, void* target) { if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, fmt("attempted to access null id")); + Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id")); if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) return {}; return std::static_pointer_cast( @@ -308,7 +308,7 @@ std::shared_ptr ProjectResourceFactoryBase::LoadResourceAsync std::shared_ptr ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, void* target) { if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, fmt("attempted to access null id")); + Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id")); if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) return {}; return std::static_pointer_cast( @@ -317,7 +317,7 @@ std::shared_ptr ProjectResourceFactoryBase::LoadResourcePartA std::unique_ptr ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag) { if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, fmt("attempted to access null id")); + Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id")); /* Ensure resource at requested path is indexed and not cooking */ const hecl::ProjectPath* resPath = nullptr; @@ -335,7 +335,7 @@ std::unique_ptr ProjectResourceFactoryBase::LoadResourceSync(const urde::S std::unique_ptr ProjectResourceFactoryBase::LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size) { if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, fmt("attempted to access null id")); + Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id")); /* Ensure resource at requested path is indexed and not cooking */ const hecl::ProjectPath* resPath = nullptr; @@ -354,7 +354,7 @@ std::unique_ptr ProjectResourceFactoryBase::LoadNewResourcePartSync(const std::shared_ptr ProjectResourceFactoryBase::CookResourceAsync(const urde::SObjectTag& tag) { if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, fmt("attempted to access null id")); + Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id")); if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) return {}; return _AddTask(std::make_shared(*this, tag)); @@ -364,7 +364,7 @@ void ProjectResourceFactoryBase::CancelBuild(const urde::SObjectTag& tag) { _Rem bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag) { if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, fmt("attempted to access null id")); + Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id")); const hecl::ProjectPath* resPath = nullptr; if (!WaitForTagReady(tag, resPath)) @@ -400,7 +400,7 @@ bool ProjectResourceFactoryBase::AsyncPumpTask(ItType& it) { hecl::ProjectPath path = static_cast(*m_cookSpec).pathFromTag(task.x0_tag); if (!path) { if (!static_cast(*m_cookSpec).backgroundIndexRunning()) { - Log.report(logvisor::Error, fmt(_SYS_STR("unable to find async load resource ({})")), task.x0_tag); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to find async load resource ({})")), task.x0_tag); it = _RemoveTask(it); } return true; @@ -423,14 +423,14 @@ bool ProjectResourceFactoryBase::AsyncPumpTask(ItType& it) { } *task.xc_targetObjPtr = std::move(newObj); - Log.report(logvisor::Info, fmt("async-built {}"), task.x0_tag); + Log.report(logvisor::Info, FMT_STRING("async-built {}"), task.x0_tag); } else if (task.xc_targetDataPtr) { /* Buffer only */ *task.xc_targetDataPtr = std::move(task.x10_loadBuffer); - Log.report(logvisor::Info, fmt("async-loaded {}"), task.x0_tag); + Log.report(logvisor::Info, FMT_STRING("async-loaded {}"), task.x0_tag); } else if (task.xc_targetDataRawPtr) { /* Buffer only raw */ - Log.report(logvisor::Info, fmt("async-loaded {}"), task.x0_tag); + Log.report(logvisor::Info, FMT_STRING("async-loaded {}"), task.x0_tag); } } diff --git a/Editor/Space.cpp b/Editor/Space.cpp index 02abd50ee..1f1b02a42 100644 --- a/Editor/Space.cpp +++ b/Editor/Space.cpp @@ -100,7 +100,7 @@ specter::View* SplitSpace::buildContentView(specter::ViewResources& res) { void SplitSpace::setChildSlot(unsigned slot, std::unique_ptr&& space) { if (slot > 1) - Log.report(logvisor::Fatal, fmt("invalid slot {} for SplitView"), slot); + Log.report(logvisor::Fatal, FMT_STRING("invalid slot {} for SplitView"), slot); m_slots[slot] = std::move(space); m_slots[slot]->m_parent = this; } @@ -162,7 +162,7 @@ std::unique_ptr RootSpace::exchangeSpaceSplitJoin(Space* removeSpace, std m_spaceTree.swap(ret); m_spaceTree->m_parent = this; } else - Log.report(logvisor::Fatal, fmt("RootSpace::exchangeSpaceSplitJoin() failure")); + Log.report(logvisor::Fatal, FMT_STRING("RootSpace::exchangeSpaceSplitJoin() failure")); return ret; } @@ -177,7 +177,7 @@ std::unique_ptr SplitSpace::exchangeSpaceSplitJoin(Space* removeSpace, st m_slots[1].swap(ret); m_slots[1]->m_parent = this; } else - Log.report(logvisor::Fatal, fmt("SplitSpace::exchangeSpaceSplitJoin() failure")); + Log.report(logvisor::Fatal, FMT_STRING("SplitSpace::exchangeSpaceSplitJoin() failure")); return ret; } diff --git a/Editor/SplashScreen.cpp b/Editor/SplashScreen.cpp index d0469e6e8..712c92f9c 100644 --- a/Editor/SplashScreen.cpp +++ b/Editor/SplashScreen.cpp @@ -36,12 +36,12 @@ SplashScreen::SplashScreen(ViewManager& vm, specter::ViewResources& res) if (GIT_COMMIT_DATE[0] != '\0' && GIT_COMMIT_HASH[0] != '\0' && GIT_BRANCH[0] != '\0') { #ifdef URDE_DLPACKAGE if ((URDE_DLPACKAGE)[0]) - m_buildInfoStr = fmt::format(fmt("{}: {}\n{}: {}\n{}: {}"), vm.translate(), + m_buildInfoStr = fmt::format(FMT_STRING("{}: {}\n{}: {}\n{}: {}"), vm.translate(), URDE_DLPACKAGE, vm.translate(), GIT_COMMIT_HASH, vm.translate(), GIT_COMMIT_DATE); else #endif - m_buildInfoStr = fmt::format(fmt("{}: {}\n{}: {}\n{}: {}"), vm.translate(), GIT_BRANCH, + m_buildInfoStr = fmt::format(FMT_STRING("{}: {}\n{}: {}\n{}: {}"), vm.translate(), GIT_BRANCH, vm.translate(), GIT_COMMIT_HASH, vm.translate(), GIT_COMMIT_DATE); } @@ -65,15 +65,15 @@ void SplashScreen::think() { m_openButt.m_view->think(); if (m_newProjBind.m_deferPath.size()) { - Log.report(logvisor::Info, fmt(_SYS_STR("Making project '{}'")), m_newProjBind.m_deferPath); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Making project '{}'")), m_newProjBind.m_deferPath); m_vm.projectManager().newProject(m_newProjBind.m_deferPath); m_newProjBind.m_deferPath.clear(); } else if (m_openProjBind.m_deferPath.size()) { - Log.report(logvisor::Info, fmt(_SYS_STR("Opening project '{}'")), m_openProjBind.m_deferPath); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Opening project '{}'")), m_openProjBind.m_deferPath); m_vm.projectManager().openProject(m_openProjBind.m_deferPath); m_openProjBind.m_deferPath.clear(); } else if (m_extractProjBind.m_deferPath.size()) { - Log.report(logvisor::Info, fmt(_SYS_STR("Extracting game '{}'")), m_extractProjBind.m_deferPath); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Extracting game '{}'")), m_extractProjBind.m_deferPath); m_vm.projectManager().extractGame(m_extractProjBind.m_deferPath); m_extractProjBind.m_deferPath.clear(); } diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index 11b29bfeb..5252498ee 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -29,7 +29,7 @@ void ViewManager::InitMP1(MP1::CMain& main) { 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_cvarManager)); m_rootView->accessContentViews().clear(); m_rootView->accessContentViews().push_back(m_testGameView.get()); @@ -62,30 +62,24 @@ void ViewManager::TestGameView::think() { if (m_debugText) { 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"); - const hecl::CVar* showInGameTime = hecl::CVarManager::instance()->findCVar("debugOverlay.showInGameTime"); - const hecl::CVar* showResourceStats = hecl::CVarManager::instance()->findCVar("debugOverlay.showResourceStats"); if (g_StateManager) { - if (showFrameIdx && showFrameIdx->toBoolean()) - overlayText += fmt::format(fmt("Frame: {}\n"), g_StateManager->GetUpdateFrameIndex()); + if (m_cvarCommons.m_debugOverlayShowFrameCounter->toBoolean()) + overlayText += fmt::format(FMT_STRING("Frame: {}\n"), g_StateManager->GetUpdateFrameIndex()); - if (showInGameTime && showInGameTime->toBoolean()) { + if (m_cvarCommons.m_debugOverlayShowInGameTime->toBoolean()) { double igt = g_GameState->GetTotalPlayTime(); u32 ms = u64(igt * 1000) % 1000; auto pt = std::div(igt, 3600); overlayText += - fmt::format(fmt("PlayTime: {:02d}:{:02d}:{:02d}.{:03d}\n"), pt.quot, pt.rem / 60, pt.rem % 60, ms); + fmt::format(FMT_STRING("PlayTime: {:02d}:{:02d}:{:02d}.{:03d}\n"), pt.quot, pt.rem / 60, pt.rem % 60, ms); } - if (g_StateManager->Player() && playerInfo && playerInfo->toBoolean()) { + if (g_StateManager->Player() && m_cvarCommons.m_debugOverlayPlayerInfo->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 += fmt::format(fmt("Player Position: x {}, y {}, z {}\n" + overlayText += fmt::format(FMT_STRING("Player Position: x {}, y {}, z {}\n" " Roll: {}, Pitch: {}, Yaw: {}\n" " Momentum: x {}, y: {}, z: {}\n" " Velocity: x {}, y: {}, z: {}\n" @@ -98,16 +92,16 @@ void ViewManager::TestGameView::think() { camXf.origin.y(), camXf.origin.z(), zeus::radToDeg(camQ.roll()), zeus::radToDeg(camQ.pitch()), zeus::radToDeg(camQ.yaw())); } - if (worldInfo && worldInfo->toBoolean()) { + if (m_cvarCommons.m_debugOverlayWorldInfo->toBoolean()) { TLockedToken tbl = g_SimplePool->GetObj({FOURCC('STRG'), g_StateManager->GetWorld()->IGetStringTableAssetId()}); const urde::TAreaId aId = g_GameState->CurrentWorldState().GetCurrentAreaId(); - overlayText += fmt::format(fmt("World: 0x{}{}, Area: {}\n"), g_GameState->CurrentWorldAssetId(), + overlayText += fmt::format(FMT_STRING("World: 0x{}{}, Area: {}\n"), g_GameState->CurrentWorldAssetId(), (tbl.IsLoaded() ? (" " + hecl::Char16ToUTF8(tbl->GetString(0))).c_str() : ""), aId); } const urde::TAreaId aId = g_GameState->CurrentWorldState().GetCurrentAreaId(); - if (areaInfo && areaInfo->toBoolean() && g_StateManager->GetWorld() && + if (m_cvarCommons.m_debugOverlayAreaInfo->toBoolean() && g_StateManager->GetWorld() && g_StateManager->GetWorld()->DoesAreaExist(aId)) { const auto& layerStates = g_GameState->CurrentWorldState().GetLayerState(); std::string layerBits; @@ -119,15 +113,15 @@ void ViewManager::TestGameView::think() { } else layerBits += "0"; } - overlayText += fmt::format(fmt("Area AssetId: 0x{}, Total Objects: {}\n" + overlayText += fmt::format(FMT_STRING("Area AssetId: 0x{}, Total Objects: {}\n" "Active Layer bits: {}\n"), g_StateManager->GetWorld()->GetArea(aId)->GetAreaAssetId(), g_StateManager->GetAllObjectList().size(), layerBits); } } - if (showResourceStats && showResourceStats->toBoolean()) - overlayText += fmt::format(fmt("Resource Objects: {}\n"), g_SimplePool->GetLiveObjects()); + if (m_cvarCommons.m_debugOverlayShowResourceStats->toBoolean()) + overlayText += fmt::format(FMT_STRING("Resource Objects: {}\n"), g_SimplePool->GetLiveObjects()); if (!overlayText.empty()) m_debugText->typesetGlyphs(overlayText); @@ -200,8 +194,8 @@ ViewManager::ViewManager(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarMan , m_projManager(*this) , m_fontCache(fileMgr) , m_locale(locale::SystemLocaleOrEnglish()) -, m_recentProjectsPath(fmt::format(fmt(_SYS_STR("{}/recent_projects.txt")), fileMgr.getStoreRoot())) -, m_recentFilesPath(fmt::format(fmt(_SYS_STR("{}/recent_files.txt")), fileMgr.getStoreRoot())) { +, m_recentProjectsPath(fmt::format(FMT_STRING(_SYS_STR("{}/recent_projects.txt")), fileMgr.getStoreRoot())) +, m_recentFilesPath(fmt::format(FMT_STRING(_SYS_STR("{}/recent_files.txt")), fileMgr.getStoreRoot())) { Space::SpaceMenuNode::InitializeStrings(*this); char path[2048]; hecl::Sstat theStat; @@ -246,7 +240,7 @@ void ViewManager::pushRecentProject(hecl::SystemStringView path) { } for (const hecl::SystemString& pPath : m_recentProjects) { - fmt::print(fp.get(), fmt("{}\n"), hecl::SystemUTF8Conv(pPath)); + fmt::print(fp.get(), FMT_STRING("{}\n"), hecl::SystemUTF8Conv(pPath)); } } @@ -263,7 +257,7 @@ void ViewManager::pushRecentFile(hecl::SystemStringView path) { } for (const hecl::SystemString& pPath : m_recentFiles) { - fmt::print(fp.get(), fmt("{}\n"), hecl::SystemUTF8Conv(pPath)); + fmt::print(fp.get(), FMT_STRING("{}\n"), hecl::SystemUTF8Conv(pPath)); } } @@ -278,7 +272,7 @@ void ViewManager::init(boo::IApplication* app) { m_pipelineConv = hecl::NewPipelineConverter(m_mainBooFactory); hecl::conv = m_pipelineConv.get(); m_mainPlatformName = m_mainBooFactory->platformName(); - m_mainWindow->setTitle(fmt::format(fmt(_SYS_STR("URDE [{}]")), m_mainPlatformName)); + m_mainWindow->setTitle(fmt::format(FMT_STRING(_SYS_STR("URDE [{}]")), m_mainPlatformName)); m_mainCommandQueue = m_mainWindow->getCommandQueue(); m_viewResources.init(m_mainBooFactory, &m_fontCache, &m_themeData, pixelFactor); InitializeIcons(m_viewResources); diff --git a/Editor/ViewManager.hpp b/Editor/ViewManager.hpp index 3ca27a896..d37a4213c 100644 --- a/Editor/ViewManager.hpp +++ b/Editor/ViewManager.hpp @@ -1,6 +1,7 @@ #pragma once #include "hecl/CVarManager.hpp" +#include "hecl/CVarCommons.hpp" #include "boo/audiodev/IAudioVoiceEngine.hpp" #include "amuse/BooBackend.hpp" #include "ProjectManager.hpp" @@ -57,9 +58,11 @@ class ViewManager final : public specter::IViewManager { class TestGameView : public specter::View { ViewManager& m_vm; std::unique_ptr m_debugText; + hecl::CVarCommons m_cvarCommons; public: - TestGameView(ViewManager& vm, specter::ViewResources& res, specter::View& parent) : View(res, parent), m_vm(vm) {} + TestGameView(ViewManager& vm, specter::ViewResources& res, specter::View& parent, hecl::CVarManager& cvarMgr) + : View(res, parent), m_vm(vm), m_cvarCommons(cvarMgr) {} void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) override; void draw(boo::IGraphicsCommandQueue* gfxQ) override; void think() override; diff --git a/Editor/badging/Badging.cpp b/Editor/badging/Badging.cpp index 43b9b9ee6..45215a55a 100644 --- a/Editor/badging/Badging.cpp +++ b/Editor/badging/Badging.cpp @@ -16,7 +16,7 @@ void InitializeBadging(specter::ViewResources& viewRes) { size_t fmt = r.readUint32Big(); if (fmt != 16) - Log.report(logvisor::Fatal, fmt("incorrect icon texture format")); + Log.report(logvisor::Fatal, FMT_STRING("incorrect icon texture format")); size_t width = r.readUint16Big(); size_t height = r.readUint16Big(); size_t mips = r.readUint32Big(); @@ -26,7 +26,7 @@ void InitializeBadging(specter::ViewResources& viewRes) { 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, fmt("unable to decompress badge")); + Log.report(logvisor::Fatal, FMT_STRING("unable to decompress badge")); viewRes.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) { specter::IconAtlas<1, 1> atlas; diff --git a/Editor/icons/icons.cpp b/Editor/icons/icons.cpp index 660b635db..4701c20b5 100644 --- a/Editor/icons/icons.cpp +++ b/Editor/icons/icons.cpp @@ -14,7 +14,7 @@ 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, fmt("incorrect icon texture format")); + Log.report(logvisor::Fatal, FMT_STRING("incorrect icon texture format")); size_t width = r.readUint16Big(); size_t height = r.readUint16Big(); size_t mips = r.readUint32Big(); @@ -24,7 +24,7 @@ void InitializeIcons(specter::ViewResources& viewRes) { 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, fmt("unable to decompress icons")); + Log.report(logvisor::Fatal, FMT_STRING("unable to decompress icons")); viewRes.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) { g_IconAtlas.initializeAtlas(ctx.newStaticTexture(width, height, mips, boo::TextureFormat::RGBA8, diff --git a/Editor/locale b/Editor/locale index 9b765b58c..c595cf725 160000 --- a/Editor/locale +++ b/Editor/locale @@ -1 +1 @@ -Subproject commit 9b765b58cf7389014f7e89a9dfb92da98ce89962 +Subproject commit c595cf725f657f3542264d7a244c14716ec41bfa diff --git a/Editor/main.cpp b/Editor/main.cpp index 6fe7f1edb..8fdb3c0fd 100644 --- a/Editor/main.cpp +++ b/Editor/main.cpp @@ -89,21 +89,20 @@ struct Application : boo::IApplicationCallback { 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, fmt("Set verbosity level to {}"), hecl::VerbosityLevel); + hecl::LogModule.report(logvisor::Info, FMT_STRING("Set verbosity level to {}"), hecl::VerbosityLevel); } } m_cvarManager.parseCommandLine(app->getArgs()); const zeus::CPUInfo& cpuInf = zeus::cpuFeatures(); - Log.report(logvisor::Info, fmt("CPU Name: {}"), cpuInf.cpuBrand); - Log.report(logvisor::Info, fmt("CPU Vendor: {}"), cpuInf.cpuVendor); - Log.report(logvisor::Info, fmt(_SYS_STR("CPU Features: {}")), CPUFeatureString(cpuInf)); + Log.report(logvisor::Info, FMT_STRING("CPU Name: {}"), cpuInf.cpuBrand); + Log.report(logvisor::Info, FMT_STRING("CPU Vendor: {}"), cpuInf.cpuVendor); + Log.report(logvisor::Info, FMT_STRING(_SYS_STR("CPU Features: {}")), CPUFeatureString(cpuInf)); } std::string getGraphicsApi() const { return m_cvarCommons.getGraphicsApi(); } @@ -113,27 +112,6 @@ struct Application : boo::IApplicationCallback { 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); - m_cvarManager.findOrMakeCVar("debugOverlay.showInGameTime"sv, "Displays the current in game time"sv, false, - hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly); - m_cvarManager.findOrMakeCVar("debugOverlay.showResourceStats"sv, - "Displays the current live resource object and token counts"sv, false, - hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly); - } }; } // namespace urde @@ -145,11 +123,11 @@ static void SetupBasics(bool logging) { auto result = zeus::validateCPU(); if (!result.first) { #if _WIN32 && !WINDOWS_STORE - std::wstring msg = fmt::format(fmt(L"ERROR: This build of URDE requires the following CPU features:\n{}\n"), + std::wstring msg = fmt::format(FMT_STRING(L"ERROR: This build of URDE requires the following CPU features:\n{}\n"), urde::CPUFeatureString(result.second)); MessageBoxW(nullptr, msg.c_str(), L"CPU error", MB_OK | MB_ICONERROR); #else - fmt::print(stderr, fmt("ERROR: This build of URDE requires the following CPU features:\n{}\n"), + fmt::print(stderr, FMT_STRING("ERROR: This build of URDE requires the following CPU features:\n{}\n"), urde::CPUFeatureString(result.second)); #endif exit(1); @@ -176,7 +154,7 @@ int main(int argc, const boo::SystemChar** argv) #endif { if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage"))) { - fmt::print(fmt("{}\n"), URDE_DLPACKAGE); + fmt::print(FMT_STRING("{}\n"), URDE_DLPACKAGE); return 100; } @@ -229,7 +207,8 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) { for (int i = 0; i < argc; ++i) booArgv[i + 1] = argv[i]; - if (IsClientLoggingEnabled(argc + 1, booArgv)) + const DWORD outType = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); + if (IsClientLoggingEnabled(argc + 1, booArgv) && outType == FILE_TYPE_UNKNOWN) logvisor::CreateWin32Console(); return wmain(argc + 1, booArgv); } diff --git a/NESEmulator/CNESEmulator.cpp b/NESEmulator/CNESEmulator.cpp index fee792896..e408e9e34 100644 --- a/NESEmulator/CNESEmulator.cpp +++ b/NESEmulator/CNESEmulator.cpp @@ -183,7 +183,7 @@ static logvisor::Module Log("CNESEmulator"); CNESEmulator::CNESEmulator() { if (EmulatorConstructed) - Log.report(logvisor::Fatal, fmt("Attempted constructing more than 1 CNESEmulator")); + Log.report(logvisor::Fatal, FMT_STRING("Attempted constructing more than 1 CNESEmulator")); EmulatorConstructed = true; CDvdFile NESEmuFile("NESemuP.rel"); @@ -191,7 +191,7 @@ CNESEmulator::CNESEmulator() { m_nesEmuPBuf.reset(new u8[0x20000]); m_dvdReq = NESEmuFile.AsyncSeekRead(m_nesEmuPBuf.get(), 0x20000, ESeekOrigin::Begin, NESEMUP_ROM_OFFSET); } else { - Log.report(logvisor::Fatal, fmt("Unable to open NESemuP.rel")); + Log.report(logvisor::Fatal, FMT_STRING("Unable to open NESemuP.rel")); } } diff --git a/README.md b/README.md index 9758b90d1..62b6934ab 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,10 @@ **Official Discord Channel:** https://discord.gg/AMBVFuf +![URDE screenshot](assets/urde-screen1.png) + ### Download -Precompiled builds of the command-line extraction utility (`hecl`) with embedded dataspec libraries are available at https://github.com/AxioDL/urde/releases. This will give you intermediate dumps of original formats as *blender* and *yaml* representations. +Precompiled builds of the command-line extraction utility (`hecl`) with embedded dataspec libraries are available at https://releases.axiodl.com. This will give you intermediate dumps of original formats as *blender* and *yaml* representations. Everything else is much too experimental to make portable/stable release builds (for now) @@ -19,9 +21,10 @@ Everything else is much too experimental to make portable/stable release builds ### Usage -* Extract ISO: `hecl extract [path].iso` -* Repackage game for URDE: `cd [extracted dir]; hecl package` -* Run URDE: `urde [path to hecl dir]/out` +* Extract ISO: `hecl extract [path].iso -o mp1` + * `mp1` can be substituted with the directory name of your choice +* Repackage game for URDE: `cd mp1; hecl package` +* Run URDE: `urde mp1/out` #### URDE options (non-exhaustive) @@ -38,7 +41,7 @@ Everything else is much too experimental to make portable/stable release builds * LLVM development package *(headers and libs)* * [Specialized Windows Package](https://axiodl.com/files/LLVM-9.0.1-win64.exe) * [Specialized macOS Package](https://axiodl.com/files/LLVM-9.0.1-Darwin.tar.xz) -* **[Windows]** [Visual Studio 2017/2019 Community](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) +* **[Windows]** [Visual Studio 2019 Community](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) * Select `C++ Development` and verify the following packages are included: * `Windows 10 SDK` * `CMake Tools` @@ -50,7 +53,7 @@ Everything else is much too experimental to make portable/stable release builds ### Prep Directions ```sh -git clone --recurse-submodules https://github.com/AxioDL/urde.git +git clone --recursive https://github.com/AxioDL/urde.git mkdir urde-build cd urde-build ``` @@ -66,7 +69,7 @@ ninja #### CMake options - Build release optimized (better runtime performance): `-DCMAKE_BUILD_TYPE=Release` -- Use clang+lld (faster linking): `-DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++` +- Use clang+lld (faster linking): `-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++` - Optimize for current CPU (resulting binaries are not portable): `-DURDE_VECTOR_ISA=native` #### CLion diff --git a/Runtime/Audio/CAudioSys.cpp b/Runtime/Audio/CAudioSys.cpp index ec1f82722..eb1c03818 100644 --- a/Runtime/Audio/CAudioSys.cpp +++ b/Runtime/Audio/CAudioSys.cpp @@ -22,6 +22,7 @@ s16 s_DefaultVolumeScale = 0x7f; CAudioSys* CAudioSys::g_SharedSys = nullptr; TLockedToken CAudioSys::FindGroupSet(std::string_view name) { + // TODO: Heterogeneous lookup when C++20 available auto search = mpGroupSetDB.find(name.data()); if (search == mpGroupSetDB.cend()) return {}; diff --git a/Runtime/Audio/CStreamAudioManager.cpp b/Runtime/Audio/CStreamAudioManager.cpp index 51ee8d788..ba6c4db21 100644 --- a/Runtime/Audio/CStreamAudioManager.cpp +++ b/Runtime/Audio/CStreamAudioManager.cpp @@ -446,14 +446,9 @@ public: 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 - }; - }; + 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; @@ -465,13 +460,16 @@ private: static std::array g_Streams; public: - CDSPStreamManager() { x70_24_unclaimed = true; } + CDSPStreamManager() : x70_24_unclaimed(true), x70_25_headerReadCancelled(false), x70_26_headerReadState(0) {} 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; - } + : x60_fileName(fileName) + , x70_24_unclaimed(!CDvdFile::FileExists(fileName)) + , x70_25_headerReadCancelled(false) + , x70_26_headerReadState(0) + , x73_volume(volume) + , x74_oneshot(oneshot) + , x78_handleId(handle) {} static s32 FindUnclaimedStreamIdx() { for (size_t i = 0; i < g_Streams.size(); ++i) { diff --git a/Runtime/AutoMapper/CAutoMapper.cpp b/Runtime/AutoMapper/CAutoMapper.cpp index 487b48324..f13e03012 100644 --- a/Runtime/AutoMapper/CAutoMapper.cpp +++ b/Runtime/AutoMapper/CAutoMapper.cpp @@ -1048,15 +1048,15 @@ void CAutoMapper::ProcessControllerInput(const CFinalInput& input, CStateManager x308_textpane_instructions2->TextSupport().SetText(u""); } else { x2fc_textpane_hint->TextSupport().SetText(u""); - std::u16string str = fmt::format(fmt(u"&image=SI,0.6,1.0,{};"), g_tweakPlayerRes->x24_lStick[x2e4_lStickPos]); - str += g_MainStringTable->GetString(46); // Rotate + std::u16string str = fmt::format(FMT_STRING(u"&image=SI,0.6,1.0,{};"), g_tweakPlayerRes->x24_lStick[x2e4_lStickPos]); + str += g_MainStringTable->GetString(46 + (!g_Main->IsUSA() || g_Main->IsTrilogy())); // Rotate x300_textpane_instructions->TextSupport().SetText(str); - str = fmt::format(fmt(u"&image=SI,0.6,1.0,{};"), g_tweakPlayerRes->x4c_cStick[x2e8_rStickPos]); - str += g_MainStringTable->GetString(47); // Move + str = fmt::format(FMT_STRING(u"&image=SI,0.6,1.0,{};"), g_tweakPlayerRes->x4c_cStick[x2e8_rStickPos]); + str += g_MainStringTable->GetString(47 + (!g_Main->IsUSA() || g_Main->IsTrilogy())); // Move x304_textpane_instructions1->TextSupport().SetText(str); - str = fmt::format(fmt(u"&image={};"), g_tweakPlayerRes->x74_lTrigger[x2ec_lTriggerPos]); - str += g_MainStringTable->GetString(48); // Zoom - str += fmt::format(fmt(u"&image={};"), g_tweakPlayerRes->x80_rTrigger[x2f0_rTriggerPos]); + str = fmt::format(FMT_STRING(u"&image={};"), g_tweakPlayerRes->x74_lTrigger[x2ec_lTriggerPos]); + str += g_MainStringTable->GetString(48 + (!g_Main->IsUSA() || g_Main->IsTrilogy())); // Zoom + str += fmt::format(FMT_STRING(u"&image={};"), g_tweakPlayerRes->x80_rTrigger[x2f0_rTriggerPos]); x308_textpane_instructions2->TextSupport().SetText(str); } } @@ -1104,10 +1104,10 @@ void CAutoMapper::Update(float dt, CStateManager& mgr) { m_frmeInitialized = true; static_cast(x28_frmeMapScreen->FindWidget("textpane_left")) ->TextSupport() - .SetText(g_MainStringTable->GetString(42)); + .SetText(g_MainStringTable->GetString(42 + (!g_Main->IsUSA() || g_Main->IsTrilogy()))); static_cast(x28_frmeMapScreen->FindWidget("textpane_yicon")) ->TextSupport() - .SetText(g_MainStringTable->GetString(43)); + .SetText(g_MainStringTable->GetString(43 + (!g_Main->IsUSA() || g_Main->IsTrilogy()))); 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")); @@ -1115,7 +1115,7 @@ void CAutoMapper::Update(float dt, CStateManager& mgr) { CGuiTextPane* mapLegend = static_cast(x28_frmeMapScreen->FindWidget("textpane_mapLegend")); mapLegend->TextSupport().ClearRenderBuffer(); mapLegend->TextSupport().SetImageBaseline(true); - mapLegend->TextSupport().SetText(g_MainStringTable->GetString(49)); + mapLegend->TextSupport().SetText(g_MainStringTable->GetString(49 + (!g_Main->IsUSA() || g_Main->IsTrilogy()))); x30c_basewidget_leftPane = x28_frmeMapScreen->FindWidget("basewidget_leftPane"); x310_basewidget_yButtonPane = x28_frmeMapScreen->FindWidget("basewidget_yButtonPane"); x314_basewidget_bottomPane = x28_frmeMapScreen->FindWidget("basewidget_bottomPane"); @@ -1129,7 +1129,7 @@ void CAutoMapper::Update(float dt, CStateManager& mgr) { std::u16string string; if (x1bc_state == EAutoMapperState::MapScreenUniverse || (x1bc_state == EAutoMapperState::MapScreen && HasCurrentMapUniverseWorld())) - string = fmt::format(fmt(u"&image={};"), g_tweakPlayerRes->x98_aButton[x2f4_aButtonPos]); + string = fmt::format(FMT_STRING(u"&image={};"), g_tweakPlayerRes->x98_aButton[x2f4_aButtonPos]); right1->TextSupport().SetText(string); CGuiTextPane* right = static_cast(x28_frmeMapScreen->FindWidget("textpane_right")); if (x1bc_state == EAutoMapperState::MapScreenUniverse) diff --git a/Runtime/AutoMapper/CMapWorldInfo.hpp b/Runtime/AutoMapper/CMapWorldInfo.hpp index 7a468cd37..69ac18b65 100644 --- a/Runtime/AutoMapper/CMapWorldInfo.hpp +++ b/Runtime/AutoMapper/CMapWorldInfo.hpp @@ -18,17 +18,17 @@ class CMapWorldInfo { public: CMapWorldInfo() = default; - explicit CMapWorldInfo(CBitStreamReader&, const CSaveWorld& saveWorld, CAssetId mlvlId); + explicit CMapWorldInfo(CBitStreamReader& reader, const CSaveWorld& saveWorld, CAssetId mlvlId); void PutTo(CBitStreamWriter& writer, const CSaveWorld& savw, CAssetId mlvlId) const; - bool IsMapped(TAreaId) const; - void SetIsMapped(TAreaId, bool); + bool IsMapped(TAreaId aid) const; + void SetIsMapped(TAreaId aid, bool mapped); void SetDoorVisited(TEditorId eid, bool val); bool IsDoorVisited(TEditorId eid) const; - bool IsAreaVisited(TAreaId) const; - void SetAreaVisited(TAreaId, bool); - bool IsWorldVisible(TAreaId) const; - bool IsAreaVisible(TAreaId) const; + bool IsAreaVisited(TAreaId aid) const; + void SetAreaVisited(TAreaId aid, bool visited); + bool IsWorldVisible(TAreaId aid) const; + bool IsAreaVisible(TAreaId aid) const; bool IsAnythingSet() const; - void SetMapStationUsed(bool val) { x38_mapStationUsed = val; } + void SetMapStationUsed(bool isUsed) { x38_mapStationUsed = isUsed; } }; } // namespace urde diff --git a/Runtime/CDvdFile.cpp b/Runtime/CDvdFile.cpp index 35bfbccee..33b109ac4 100644 --- a/Runtime/CDvdFile.cpp +++ b/Runtime/CDvdFile.cpp @@ -19,7 +19,7 @@ class CFileDvdRequest : public IDvdRequest { std::function m_callback; public: - ~CFileDvdRequest() override { PostCancelRequest(); } + ~CFileDvdRequest() override { CFileDvdRequest::PostCancelRequest(); } void WaitUntilComplete() override { while (!m_complete.load() && !m_cancel.load()) { @@ -32,14 +32,15 @@ public: m_cancel.store(true); } - EMediaType GetMediaType() const override { return EMediaType::File; } + [[nodiscard]] EMediaType GetMediaType() const override { 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)) {} void DoRequest() { - if (m_cancel.load()) + if (m_cancel.load()) { return; + } u32 readLen; if (m_whence == ESeekOrigin::Cur && m_offset == 0) { readLen = m_reader->readBytesToBuf(m_buf, m_len); @@ -47,8 +48,9 @@ public: m_reader->seek(m_offset, athena::SeekOrigin(m_whence)); readLen = m_reader->readBytesToBuf(m_buf, m_len); } - if (m_callback) + if (m_callback) { m_callback(readLen); + } m_complete.store(true); } }; @@ -63,21 +65,22 @@ void CDvdFile::WorkerProc() { logvisor::RegisterThreadName("CDvdFile"); while (m_WorkerRun.load()) { std::unique_lock lk(CDvdFile::m_WorkerMutex); - while (CDvdFile::m_RequestQueue.size()) { + while (!CDvdFile::m_RequestQueue.empty()) { 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); + auto& concreteReq = static_cast(*req); concreteReq.DoRequest(); } waitlk.unlock(); swapQueue.clear(); lk.lock(); } - if (!m_WorkerRun.load()) + if (!m_WorkerRun.load()) { break; + } m_WorkerCV.wait(lk); } } @@ -94,12 +97,15 @@ std::shared_ptr CDvdFile::AsyncSeekRead(void* buf, u32 len, ESeekOr hecl::ProjectPath CDvdFile::ResolvePath(std::string_view path) { auto start = path.begin(); - while (*start == '/') ++start; + while (*start == '/') { + ++start; + } std::string lowerChStr(start, path.end()); std::transform(lowerChStr.begin(), lowerChStr.end(), lowerChStr.begin(), ::tolower); auto search = m_caseInsensitiveMap.find(lowerChStr); - if (search == m_caseInsensitiveMap.end()) + if (search == m_caseInsensitiveMap.end()) { return {}; + } return hecl::ProjectPath(m_DvdRoot, search->second); } @@ -120,19 +126,22 @@ void CDvdFile::RecursiveBuildCaseInsensitiveMap(const hecl::ProjectPath& path, s void CDvdFile::Initialize(const hecl::ProjectPath& path) { m_DvdRoot = path; RecursiveBuildCaseInsensitiveMap(path, path.getAbsolutePathUTF8().length() + 1); - if (m_WorkerRun.load()) + if (m_WorkerRun.load()) { return; + } m_WorkerRun.store(true); m_WorkerThread = std::thread(WorkerProc); } void CDvdFile::Shutdown() { - if (!m_WorkerRun.load()) + if (!m_WorkerRun.load()) { return; + } m_WorkerRun.store(false); m_WorkerCV.notify_one(); - if (m_WorkerThread.joinable()) + if (m_WorkerThread.joinable()) { m_WorkerThread.join(); + } m_RequestQueue.clear(); } diff --git a/Runtime/CGameAllocator.cpp b/Runtime/CGameAllocator.cpp index 399ee3610..59b045635 100644 --- a/Runtime/CGameAllocator.cpp +++ b/Runtime/CGameAllocator.cpp @@ -44,7 +44,7 @@ u8* CGameAllocator::Alloc(size_t len) { void CGameAllocator::Free(u8* ptr) { SChunkDescription* info = reinterpret_cast(ptr - sizeof(SChunkDescription)); if (info->magic != 0xE8E8E8E8 || info->sentinal != 0xEFEFEFEF) { - AllocLog.report(logvisor::Fatal, fmt(_SYS_STR("Invalid chunk description, memory corruption!"))); + AllocLog.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Invalid chunk description, memory corruption!"))); return; } diff --git a/Runtime/CGameOptions.cpp b/Runtime/CGameOptions.cpp index fff4226eb..1f662ef9d 100644 --- a/Runtime/CGameOptions.cpp +++ b/Runtime/CGameOptions.cpp @@ -49,7 +49,38 @@ constexpr std::array ControllerOpts{{ {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults}, }}; -const std::array, 5> GameOptionsRegistry{{ +constexpr std::array VisorOptsNew{{ + {EGameOption::VisorOpacity, 23, 0.f, 255.f, 1.f, EOptionType::Float}, + {EGameOption::HelmetOpacity, 24, 0.f, 255.f, 1.f, EOptionType::Float}, + {EGameOption::HUDLag, 25, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, + {EGameOption::HintSystem, 26, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, + {EGameOption::RestoreDefaults, 38, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults}, +}}; + +constexpr std::array DisplayOptsNew{{ + //{EGameOption::ScreenBrightness, 25, 0.f, 8.f, 1.f, EOptionType::Float}, + {EGameOption::ScreenBrightness, 28, -100.f, 100.f, 1.f, EOptionType::Float}, + {EGameOption::ScreenOffsetX, 29, -30.f, 30.f, 1.f, EOptionType::Float}, + {EGameOption::ScreenOffsetY, 30, -30.f, 30.f, 1.f, EOptionType::Float}, + {EGameOption::ScreenStretch, 31, -10.f, 10.f, 1.f, EOptionType::Float}, + {EGameOption::RestoreDefaults, 38, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults}, +}}; + +constexpr std::array SoundOptsNew{{ + {EGameOption::SFXVolume, 32, 0.f, 127.f, 1.f, EOptionType::Float}, + {EGameOption::MusicVolume, 33, 0.f, 127.f, 1.f, EOptionType::Float}, + {EGameOption::SoundMode, 34, 0.f, 1.f, 1.f, EOptionType::TripleEnum}, + {EGameOption::RestoreDefaults, 38, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults}, +}}; + +constexpr std::array ControllerOptsNew{{ + {EGameOption::ReverseYAxis, 35, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, + {EGameOption::Rumble, 37, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, + {EGameOption::SwapBeamControls, 37, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, + {EGameOption::RestoreDefaults, 38, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults}, +}}; + +constexpr std::array, 5> GameOptionsRegistry{{ {VisorOpts.size(), VisorOpts.data()}, {DisplayOpts.size(), DisplayOpts.data()}, {SoundOpts.size(), SoundOpts.data()}, @@ -57,23 +88,33 @@ const std::array, 5> GameOptionsRegistry{{ {0, nullptr}, }}; -CPersistentOptions::CPersistentOptions(CBitStreamReader& stream) { - for (u8& entry : x0_nesState) - entry = stream.ReadEncoded(8); +constexpr std::array, 5> GameOptionsRegistryNew{{ + {VisorOptsNew.size(), VisorOptsNew.data()}, + {DisplayOptsNew.size(), DisplayOptsNew.data()}, + {SoundOptsNew.size(), SoundOptsNew.data()}, + {ControllerOptsNew.size(), ControllerOptsNew.data()}, + {0, nullptr}, +}}; - for (bool& entry : x68_) +CPersistentOptions::CPersistentOptions(CBitStreamReader& stream) { + for (u8& entry : x0_nesState) { entry = stream.ReadEncoded(8); + } + + for (bool& entry : x68_) { + entry = stream.ReadEncoded(8) != 0; + } 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_24_fusionLinked = stream.ReadEncoded(1) != 0; + xd0_25_normalModeBeat = stream.ReadEncoded(1) != 0; + xd0_26_hardModeBeat = stream.ReadEncoded(1) != 0; + xd0_27_fusionBeat = stream.ReadEncoded(1) != 0; xd0_28_fusionSuitActive = false; - xd0_29_allItemsCollected = stream.ReadEncoded(1); + xd0_29_allItemsCollected = stream.ReadEncoded(1) != 0; xbc_autoMapperKeyState = stream.ReadEncoded(2); auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); @@ -86,8 +127,9 @@ CPersistentOptions::CPersistentOptions(CBitStreamReader& stream) { std::vector cinematicStates; cinematicStates.reserve(cinematicCount); - for (size_t i = 0; i < cinematicCount; ++i) - cinematicStates.push_back(stream.ReadEncoded(1)); + for (size_t i = 0; i < cinematicCount; ++i) { + cinematicStates.push_back(stream.ReadEncoded(1) != 0); + } for (const auto& world : memWorlds) { TLockedToken saveWorld = @@ -101,11 +143,13 @@ CPersistentOptions::CPersistentOptions(CBitStreamReader& stream) { } void CPersistentOptions::PutTo(CBitStreamWriter& w) const { - for (const u8 entry : x0_nesState) + for (const u8 entry : x0_nesState) { w.WriteEncoded(entry, 8); + } - for (const bool entry : x68_) - w.WriteEncoded(entry, 8); + for (const bool entry : x68_) { + w.WriteEncoded(u32(entry), 8); + } w.WriteEncoded(xc0_frozenFpsCount, 2); w.WriteEncoded(xc4_frozenBallCount, 2); @@ -120,11 +164,12 @@ void CPersistentOptions::PutTo(CBitStreamWriter& w) const { auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); for (const auto& world : memWorlds) { - TLockedToken saveWorld = + const TLockedToken saveWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.second.GetSaveWorldAssetId()}); - for (TEditorId cineId : saveWorld->GetCinematics()) - w.WriteEncoded(GetCinematicState(world.first, cineId), 1); + for (const TEditorId cineId : saveWorld->GetCinematics()) { + w.WriteEncoded(u32(GetCinematicState(world.first, cineId)), 1); + } } } @@ -164,11 +209,11 @@ CGameOptions::CGameOptions(CBitStreamReader& stream) { 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) != 0; + x68_28_hintSystem = stream.ReadEncoded(1) != 0; + x68_25_invertY = stream.ReadEncoded(1) != 0; + x68_26_rumble = stream.ReadEncoded(1) != 0; + x68_27_swapBeamsControls = stream.ReadEncoded(1) != 0; } void CGameOptions::ResetToDefaults() { @@ -212,22 +257,28 @@ void CGameOptions::PutTo(CBitStreamWriter& writer) const { writer.WriteEncoded(x68_27_swapBeamsControls, 1); } -CGameOptions::CGameOptions() { - x68_24_hudLag = true; - x68_26_rumble = true; - x68_28_hintSystem = true; +CGameOptions::CGameOptions() +: x68_24_hudLag(true) +, x68_25_invertY(false) +, x68_26_rumble(true) +, x68_27_swapBeamsControls(false) +, x68_28_hintSystem(true) { InitSoundMode(); } -float CGameOptions::TuneScreenBrightness() { return (0.375f * 1.f) + (float(x48_screenBrightness) * 0.25f); } +float CGameOptions::TuneScreenBrightness() const { 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 value, bool apply) { + x48_screenBrightness = zeus::clamp(0, value, 8); - if (apply) - BrightnessCopyFilter = TuneScreenBrightness(); + if (!apply) { + return; + } + + BrightnessCopyFilter = TuneScreenBrightness(); } void CGameOptions::ApplyGamma() { @@ -239,51 +290,60 @@ void CGameOptions::ApplyGamma() { CGraphics::g_BooFactory->setDisplayGamma(gammaT); } -void CGameOptions::SetGamma(s32 val, bool apply) { - m_gamma = zeus::clamp(-100, val, 100); +void CGameOptions::SetGamma(s32 value, bool apply) { + m_gamma = zeus::clamp(-100, value, 100); - if (apply) - ApplyGamma(); + if (!apply) { + return; + } + + ApplyGamma(); } -void CGameOptions::SetScreenPositionX(s32 pos, bool apply) { - x4c_screenXOffset = zeus::clamp(-30, pos, 30); +void CGameOptions::SetScreenPositionX(s32 position, bool apply) { + x4c_screenXOffset = zeus::clamp(-30, position, 30); if (apply) { /* TOOD: CGraphics related funcs */ } } -void CGameOptions::SetScreenPositionY(s32 pos, bool apply) { - x50_screenYOffset = zeus::clamp(-30, pos, 30); +void CGameOptions::SetScreenPositionY(s32 position, bool apply) { + x50_screenYOffset = zeus::clamp(-30, position, 30); if (apply) { /* TOOD: CGraphics related funcs */ } } -void CGameOptions::SetScreenStretch(s32 st, bool apply) { - x54_screenStretch = zeus::clamp(-10, st, 10); +void CGameOptions::SetScreenStretch(s32 stretch, bool apply) { + x54_screenStretch = zeus::clamp(-10, stretch, 10); if (apply) { /* TOOD: CGraphics related funcs */ } } -void CGameOptions::SetSfxVolume(s32 vol, bool apply) { - x58_sfxVol = zeus::clamp(0, vol, 0x7f); +void CGameOptions::SetSfxVolume(s32 volume, bool apply) { + x58_sfxVol = zeus::clamp(0, volume, 0x7f); - if (apply) { - CAudioSys::SysSetSfxVolume(x58_sfxVol, 1, 1, 1); - CStreamAudioManager::SetSfxVolume(x58_sfxVol); - CMoviePlayer::SetSfxVolume(x58_sfxVol); + if (!apply) { + return; } + + CAudioSys::SysSetSfxVolume(x58_sfxVol, 1, true, true); + 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 volume, bool apply) { + x5c_musicVol = zeus::clamp(0, volume, 0x7f); + + if (!apply) { + return; + } + + CStreamAudioManager::SetMusicVolume(x5c_musicVol); } void CGameOptions::SetHUDAlpha(u32 alpha) { x60_hudAlpha = alpha; } @@ -323,7 +383,7 @@ void CGameOptions::SetControls(int controls) { ResetControllerAssets(controls); } -const std::array, 5> CStickToDPadRemap{{ +constexpr std::array, 5> CStickToDPadRemap{{ {0x2A13C23E, 0xF13452F8}, {0xA91A7703, 0xC042EC91}, {0x12A12131, 0x5F556002}, @@ -331,7 +391,7 @@ const std::array, 5> CStickToDPadRemap{{ {0xCD7B1ACA, 0x8ADA8184}, }}; -const std::array, 5> CStickOutlineToDPadRemap{{ +constexpr std::array, 5> CStickOutlineToDPadRemap{{ {0x1A29C0E6, 0xF13452F8}, {0x5D9F9796, 0xC042EC91}, {0x951546A8, 0x5F556002}, @@ -440,10 +500,10 @@ void CGameOptions::SetOption(EGameOption option, int value) { options.SetHelmetAlpha(value); break; case EGameOption::HUDLag: - options.SetHUDLag(value); + options.SetHUDLag(value != 0); break; case EGameOption::HintSystem: - options.SetIsHintSystemEnabled(value); + options.SetIsHintSystemEnabled(value != 0); break; case EGameOption::ScreenBrightness: options.SetGamma(value, true); @@ -467,13 +527,13 @@ void CGameOptions::SetOption(EGameOption option, int value) { options.SetSurroundMode(value, true); break; case EGameOption::ReverseYAxis: - options.SetInvertYAxis(value); + options.SetInvertYAxis(value != 0); break; case EGameOption::Rumble: - options.SetIsRumbleEnabled(value); + options.SetIsRumbleEnabled(value != 0); break; case EGameOption::SwapBeamControls: - options.SetSwapBeamControls(value); + options.SetSwapBeamControls(value != 0); break; default: break; @@ -489,9 +549,9 @@ int CGameOptions::GetOption(EGameOption option) { case EGameOption::HelmetOpacity: return options.GetHelmetAlpha(); case EGameOption::HUDLag: - return options.GetHUDLag(); + return int(options.GetHUDLag()); case EGameOption::HintSystem: - return options.GetIsHintSystemEnabled(); + return int(options.GetIsHintSystemEnabled()); case EGameOption::ScreenBrightness: return options.GetGamma(); case EGameOption::ScreenOffsetX: @@ -507,11 +567,11 @@ int CGameOptions::GetOption(EGameOption option) { case EGameOption::SoundMode: return int(options.GetSurroundMode()); case EGameOption::ReverseYAxis: - return options.GetInvertYAxis(); + return int(options.GetInvertYAxis()); case EGameOption::Rumble: - return options.GetIsRumbleEnabled(); + return int(options.GetIsRumbleEnabled()); case EGameOption::SwapBeamControls: - return options.GetSwapBeamControls(); + return int(options.GetSwapBeamControls()); default: break; } diff --git a/Runtime/CGameOptions.hpp b/Runtime/CGameOptions.hpp index 554ecea86..5d6325b34 100644 --- a/Runtime/CGameOptions.hpp +++ b/Runtime/CGameOptions.hpp @@ -44,6 +44,7 @@ struct SGameOption { /** Static registry of Option UI presentation information */ extern const std::array, 5> GameOptionsRegistry; +extern const std::array, 5> GameOptionsRegistryNew; /** Options tracked persistently between game sessions */ class CPersistentOptions { @@ -56,41 +57,41 @@ class CPersistentOptions { 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; - }; + 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; public: - CPersistentOptions() = default; + CPersistentOptions() + : xd0_24_fusionLinked(false) + , xd0_25_normalModeBeat(false) + , xd0_26_hardModeBeat(false) + , xd0_27_fusionBeat(false) + , xd0_28_fusionSuitActive(false) + , xd0_29_allItemsCollected(false) {} explicit 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; } + void SetAutoMapperKeyState(u32 state) { xbc_autoMapperKeyState = state; } bool GetPlayerLinkedFusion() const { return xd0_24_fusionLinked; } - void SetPlayerLinkedFusion(bool v) { xd0_24_fusionLinked = v; } + void SetPlayerLinkedFusion(bool fusionLinked) { xd0_24_fusionLinked = fusionLinked; } bool GetPlayerBeatNormalMode() const { return xd0_25_normalModeBeat; } - void SetPlayerBeatNormalMode(bool v) { xd0_25_normalModeBeat = v; } + void SetPlayerBeatNormalMode(bool normalModeBeat) { xd0_25_normalModeBeat = normalModeBeat; } bool GetPlayerBeatHardMode() const { return xd0_26_hardModeBeat; } - void SetPlayerBeatHardMode(bool v) { xd0_26_hardModeBeat = v; } + void SetPlayerBeatHardMode(bool hardModeBeat) { xd0_26_hardModeBeat = hardModeBeat; } bool GetPlayerBeatFusion() const { return xd0_27_fusionBeat; } - void SetPlayerBeatFusion(bool v) { xd0_27_fusionBeat = v; } + void SetPlayerBeatFusion(bool fusionBeat) { xd0_27_fusionBeat = fusionBeat; } bool GetPlayerFusionSuitActive() const { return xd0_28_fusionSuitActive; } - void SetPlayerFusionSuitActive(bool v) { xd0_28_fusionSuitActive = v; } + void SetPlayerFusionSuitActive(bool fusionSuitActive) { xd0_28_fusionSuitActive = fusionSuitActive; } bool GetAllItemsCollected() const { return xd0_29_allItemsCollected; } - void SetAllItemsCollected(bool v) { xd0_29_allItemsCollected = v; } + void SetAllItemsCollected(bool allItemsCollected) { xd0_29_allItemsCollected = allItemsCollected; } u32 GetLogScanPercent() const { return xcc_logScanPercent; } - void SetLogScanPercent(u32 v) { xcc_logScanPercent = v; } + void SetLogScanPercent(u32 percent) { xcc_logScanPercent = percent; } 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); } @@ -116,22 +117,15 @@ class CGameOptions { u32 x5c_musicVol = 0x7f; u32 x60_hudAlpha = 0xff; u32 x64_helmetAlpha = 0xff; + 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; + std::vector> x6c_controlTxtrMap; 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; - }; - - std::vector> x6c_controlTxtrMap; - public: CGameOptions(); explicit CGameOptions(CBitStreamReader& stream); @@ -140,37 +134,37 @@ public: void EnsureSettings(); void PutTo(CBitStreamWriter& writer) const; - float TuneScreenBrightness(); - void SetScreenBrightness(s32, bool); + float TuneScreenBrightness() const; + void SetScreenBrightness(s32 value, bool apply); s32 GetScreenBrightness() const { return x48_screenBrightness; } void ApplyGamma(); - void SetGamma(s32, bool); + void SetGamma(s32 value, bool apply); s32 GetGamma() const { return m_gamma; } - void SetScreenPositionX(s32, bool); + void SetScreenPositionX(s32 position, bool apply); s32 GetScreenPositionX() const { return x4c_screenXOffset; } - void SetScreenPositionY(s32, bool); + void SetScreenPositionY(s32 position, bool apply); s32 GetScreenPositionY() const { return x50_screenYOffset; } - void SetScreenStretch(s32, bool); + void SetScreenStretch(s32 stretch, bool apply); s32 GetScreenStretch() const { return x54_screenStretch; } - void SetSfxVolume(s32, bool); + void SetSfxVolume(s32 volume, bool apply); s32 GetSfxVolume() const { return x58_sfxVol; } - void SetMusicVolume(s32, bool); + void SetMusicVolume(s32 volume, bool apply); s32 GetMusicVolume() const { return x5c_musicVol; } - void SetHUDAlpha(u32); + void SetHUDAlpha(u32 alpha); u32 GetHUDAlpha() const { return x60_hudAlpha; } - void SetHelmetAlpha(u32); + void SetHelmetAlpha(u32 alpha); u32 GetHelmetAlpha() const { return x64_helmetAlpha; } - void SetHUDLag(bool); + void SetHUDLag(bool lag); bool GetHUDLag() const { return x68_24_hudLag; } void SetSurroundMode(int mode, bool apply); CAudioSys::ESurroundModes GetSurroundMode() const; - void SetInvertYAxis(bool); + void SetInvertYAxis(bool invert); bool GetInvertYAxis() const { return x68_25_invertY; } - void SetIsRumbleEnabled(bool); + void SetIsRumbleEnabled(bool rumble); bool GetIsRumbleEnabled() const { return x68_26_rumble; } - void SetSwapBeamControls(bool); + void SetSwapBeamControls(bool swap); bool GetSwapBeamControls() const { return x68_27_swapBeamsControls; } - void SetIsHintSystemEnabled(bool); + void SetIsHintSystemEnabled(bool hints); bool GetIsHintSystemEnabled() const { return x68_28_hintSystem; } void SetControls(int controls); void ResetControllerAssets(int controls); diff --git a/Runtime/CGameState.cpp b/Runtime/CGameState.cpp index 2bd9531f6..0289bdc44 100644 --- a/Runtime/CGameState.cpp +++ b/Runtime/CGameState.cpp @@ -24,15 +24,16 @@ union BitsToDouble { }; CWorldLayerState::CWorldLayerState(CBitStreamReader& reader, const CSaveWorld& saveWorld) { - u32 bitCount = reader.ReadEncoded(10); + const u32 bitCount = reader.ReadEncoded(10); x10_saveLayers.reserve(bitCount); for (u32 i = 0; i < bitCount; ++i) { - bool bit = reader.ReadEncoded(1); - if (bit) + const bool bit = reader.ReadEncoded(1) != 0; + if (bit) { x10_saveLayers.setBit(i); - else + } else { x10_saveLayers.unsetBit(i); + } } } @@ -53,11 +54,14 @@ void CWorldLayerState::PutTo(CBitStreamWriter& writer) const { } void CWorldLayerState::InitializeWorldLayers(const std::vector& layers) { - if (x0_areaLayers.size()) + if (!x0_areaLayers.empty()) { return; + } + x0_areaLayers = layers; - if (x10_saveLayers.getBitCount() == 0) + if (x10_saveLayers.getBitCount() == 0) { return; + } u32 a = 0; u32 b = 0; @@ -102,9 +106,9 @@ CGameState::GameFileStateInfo CGameState::LoadGameFileState(const u8* data) { } ret.x14_timestamp = stream.ReadEncoded(32); - ret.x20_hardMode = stream.ReadEncoded(1); + ret.x20_hardMode = stream.ReadEncoded(1) != 0; stream.ReadEncoded(1); - CAssetId origMLVL = u32(stream.ReadEncoded(32)); + const CAssetId origMLVL = u32(stream.ReadEncoded(32)); ret.x8_mlvlId = origMLVL; BitsToDouble conv; @@ -137,13 +141,17 @@ CGameState::GameFileStateInfo CGameState::LoadGameFileState(const u8* data) { CGameState::CGameState() { x98_playerState = std::make_shared(); x9c_transManager = std::make_shared(); + x228_24_hardMode = false; x228_25_initPowerupsAtFirstSpawn = true; - if (g_MemoryCardSys) + + if (g_MemoryCardSys != nullptr) { InitializeMemoryStates(); + } } CGameState::CGameState(CBitStreamReader& stream, u32 saveIdx) : x20c_saveFileIdx(saveIdx) { x9c_transManager = std::make_shared(); + x228_24_hardMode = false; x228_25_initPowerupsAtFirstSpawn = true; for (bool& value : x0_) { @@ -151,8 +159,8 @@ CGameState::CGameState(CBitStreamReader& stream, u32 saveIdx) : x20c_saveFileIdx } stream.ReadEncoded(32); - x228_24_hardMode = stream.ReadEncoded(1); - x228_25_initPowerupsAtFirstSpawn = stream.ReadEncoded(1); + x228_24_hardMode = stream.ReadEncoded(1) != 0; + x228_25_initPowerupsAtFirstSpawn = stream.ReadEncoded(1) != 0; x84_mlvlId = u32(stream.ReadEncoded(32)); MP1::CMain::EnsureWorldPakReady(x84_mlvlId); diff --git a/Runtime/CGameState.hpp b/Runtime/CGameState.hpp index 32349f8d9..ab63a1a28 100644 --- a/Runtime/CGameState.hpp +++ b/Runtime/CGameState.hpp @@ -69,7 +69,7 @@ class CGameState { friend class CStateManager; std::array x0_{}; - u32 x80_; + u32 x80_ = 0; CAssetId x84_mlvlId; std::vector x88_worldStates; std::shared_ptr x98_playerState; @@ -81,14 +81,8 @@ class CGameState { 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; - }; + bool x228_24_hardMode : 1; + bool x228_25_initPowerupsAtFirstSpawn : 1; public: CGameState(); diff --git a/Runtime/CInGameTweakManagerBase.hpp b/Runtime/CInGameTweakManagerBase.hpp index 126098f00..32e205ecf 100644 --- a/Runtime/CInGameTweakManagerBase.hpp +++ b/Runtime/CInGameTweakManagerBase.hpp @@ -67,7 +67,7 @@ public: bool ReadFromMemoryCard(std::string_view name) { return true; } static std::string GetIdentifierForMidiEvent(CAssetId world, CAssetId area, std::string_view midiObj) { - return fmt::format(fmt("World {} Area {} MidiObject: {}"), world, area, midiObj); + return fmt::format(FMT_STRING("World {} Area {} MidiObject: {}"), world, area, midiObj); } }; diff --git a/Runtime/CMemoryCardSys.cpp b/Runtime/CMemoryCardSys.cpp index a3de34a70..45b885485 100644 --- a/Runtime/CMemoryCardSys.cpp +++ b/Runtime/CMemoryCardSys.cpp @@ -525,7 +525,10 @@ void CMemoryCardSys::CommitToDisk(kabufuda::ECardSlot port) { kabufuda::SystemString CMemoryCardSys::CreateDolphinCard(kabufuda::ECardSlot slot) { kabufuda::SystemString path = _CreateDolphinCard(slot); - CardProbe(slot); + if (CardProbe(slot).x0_error != ECardResult::READY) { + return {}; + } + MountCard(slot); FormatCard(slot); kabufuda::Card& card = g_CardStates[int(slot)]; diff --git a/Runtime/CMemoryCardSysNix.cpp b/Runtime/CMemoryCardSysNix.cpp index 8c4921a17..fa31b6cc8 100644 --- a/Runtime/CMemoryCardSysNix.cpp +++ b/Runtime/CMemoryCardSysNix.cpp @@ -1,50 +1,59 @@ #include "CMemoryCardSys.hpp" +#include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/IMain.hpp" 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"); - - /* XDG-selected data path */ - kabufuda::SystemString path = - ((dataHome && dataHome[0] == '/') ? dataHome : hecl::SystemString(home)) + "/.local/share/dolphin-emu"; - path += fmt::format(fmt("/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)) { - /* legacy case for older dolphin versions */ - path = home; - path += fmt::format(fmt("/.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)) + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + const char* home = getenv("HOME"); + if (!home || home[0] != '/') return {}; - } + const char* dataHome = getenv("XDG_DATA_HOME"); - return path; + /* XDG-selected data path */ + kabufuda::SystemString path = + ((dataHome && dataHome[0] == '/') ? dataHome : hecl::SystemString(home)) + "/.local/share/dolphin-emu"; + path += fmt::format(FMT_STRING("/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)) { + /* legacy case for older dolphin versions */ + path = home; + path += fmt::format(FMT_STRING("/.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 path; + } + return {}; } kabufuda::SystemString CMemoryCardSys::_CreateDolphinCard(kabufuda::ECardSlot slot) { - const char* home = getenv("HOME"); - if (!home || home[0] != '/') - return {}; - const char* dataHome = getenv("XDG_DATA_HOME"); + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + 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 += fmt::format(fmt("/MemoryCard{:c}.USA.raw"), slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); - const auto fp = hecl::FopenUnique(path.c_str(), "wb"); - if (fp == nullptr) { - return {}; + path += fmt::format(FMT_STRING("/MemoryCard{:c}.USA.raw"), slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); + const auto fp = hecl::FopenUnique(path.c_str(), "wb"); + if (fp == nullptr) { + return {}; + } + + return path; } - - return path; + return {}; } } // namespace urde diff --git a/Runtime/CMemoryCardSysOSX.cpp b/Runtime/CMemoryCardSysOSX.cpp index e1e659506..b62be99b8 100644 --- a/Runtime/CMemoryCardSysOSX.cpp +++ b/Runtime/CMemoryCardSysOSX.cpp @@ -1,40 +1,47 @@ #include "CMemoryCardSys.hpp" - +#include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/IMain.hpp" namespace urde { kabufuda::SystemString CMemoryCardSys::ResolveDolphinCardPath(kabufuda::ECardSlot slot) { - const char* home = getenv("HOME"); - if (!home) - return {}; + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + const char* home = getenv("HOME"); + if (!home) + return {}; - kabufuda::SystemString path = home; - path += fmt::format(fmt("/Library/Application Support/Dolphin/GC/MemoryCard{:c}.USA.raw"), - slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); + kabufuda::SystemString path = home; + path += fmt::format(FMT_STRING("/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; + } + return {}; } kabufuda::SystemString CMemoryCardSys::_CreateDolphinCard(kabufuda::ECardSlot slot) { - const char* home = getenv("HOME"); - if (!home) - return {}; + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + 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 += fmt::format(fmt("/MemoryCard{:c}.USA.raw"), slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); - const auto fp = hecl::FopenUnique(path.c_str(), "wb"); - if (fp == nullptr) { - return {}; + path += fmt::format(FMT_STRING("/MemoryCard{:c}.USA.raw"), slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); + const auto fp = hecl::FopenUnique(path.c_str(), "wb"); + if (fp == nullptr) { + return {}; + } + + return path; } - - return path; + return {}; } } // namespace urde diff --git a/Runtime/CMemoryCardSysWin.cpp b/Runtime/CMemoryCardSysWin.cpp index bfdd2406f..fa869cd8a 100644 --- a/Runtime/CMemoryCardSysWin.cpp +++ b/Runtime/CMemoryCardSysWin.cpp @@ -1,5 +1,8 @@ #include "Runtime/CMemoryCardSys.hpp" +#include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/IMain.hpp" + #include namespace urde { @@ -12,101 +15,109 @@ using namespace Windows::Storage; * 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) { + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { #if !WINDOWS_STORE - /* Detect where the User directory is. There are two different cases + /* 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 += fmt::format(fmt(_SYS_STR("/GC/MemoryCard{}.USA.raw")), - slot == kabufuda::ECardSlot::SlotA ? _SYS_STR('A') : _SYS_STR('B')); + path += fmt::format(FMT_STRING(_SYS_STR("/GC/MemoryCard{}.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; + } + return {}; } kabufuda::SystemString CMemoryCardSys::_CreateDolphinCard(kabufuda::ECardSlot slot) { + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { #if !WINDOWS_STORE - /* Detect where the User directory is. There are two different cases + /* 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 += fmt::format(fmt(_SYS_STR("/MemoryCard{}.USA.raw")), - slot == kabufuda::ECardSlot::SlotA ? _SYS_STR('A') : _SYS_STR('B')); - const auto fp = hecl::FopenUnique(path.c_str(), _SYS_STR("wb")); - if (fp == nullptr) { - return {}; + path += fmt::format(FMT_STRING(_SYS_STR("/MemoryCard{}.USA.raw")), + slot == kabufuda::ECardSlot::SlotA ? _SYS_STR('A') : _SYS_STR('B')); + const auto fp = hecl::FopenUnique(path.c_str(), _SYS_STR("wb")); + if (fp == nullptr) { + return {}; + } + + return path; } - - return path; + return {}; } } // namespace urde diff --git a/Runtime/CObjectList.cpp b/Runtime/CObjectList.cpp index 332d7e4a3..e0c6a89de 100644 --- a/Runtime/CObjectList.cpp +++ b/Runtime/CObjectList.cpp @@ -13,7 +13,7 @@ void CObjectList::AddObject(CEntity& entity) { #ifndef NDEBUG if (x0_list[entity.GetUniqueId().Value()].entity != nullptr && x0_list[entity.GetUniqueId().Value()].entity != &entity) - Log.report(logvisor::Level::Fatal, fmt("INVALID USAGE DETECTED: Attempting to assign entity '{} ({})' to existing node '{}'!!!"), + Log.report(logvisor::Level::Fatal, FMT_STRING("INVALID USAGE DETECTED: Attempting to assign entity '{} ({})' to existing node '{}'!!!"), entity.GetName(), entity.GetEditorId(), entity.GetUniqueId().Value()); #endif s16 prevFirst = -1; diff --git a/Runtime/CPakFile.cpp b/Runtime/CPakFile.cpp index 8d29f7367..92e73081c 100644 --- a/Runtime/CPakFile.cpp +++ b/Runtime/CPakFile.cpp @@ -5,9 +5,10 @@ static logvisor::Module Log("urde::CPakFile"); CPakFile::CPakFile(std::string_view filename, bool buildDepList, bool worldPak, bool override) : CDvdFile(filename) { if (!CDvdFile::operator bool()) - Log.report(logvisor::Fatal, fmt("{}: Unable to open"), GetPath()); + Log.report(logvisor::Fatal, FMT_STRING("{}: Unable to open"), GetPath()); x28_24_buildDepList = buildDepList; //x28_24_buildDepList = true; // Always do this so URDE can rapidly pre-warm shaders + x28_25_aramFile = false; x28_26_worldPak = worldPak; x28_27_stashedInARAM = false; m_override = override; @@ -66,7 +67,7 @@ void CPakFile::InitialHeaderLoad() { u32 version = r.readUint32Big(); if (version != 0x80030005) { Log.report(logvisor::Fatal, - fmt("{}: Incompatible pak file version -- Current version is {:08X}, you're using {:08X}"), + FMT_STRING("{}: Incompatible pak file version -- Current version is {:08X}, you're using {:08X}"), GetPath(), 0x80030005, version); return; } diff --git a/Runtime/CPakFile.hpp b/Runtime/CPakFile.hpp index d978d7fc6..f0b1ec91a 100644 --- a/Runtime/CPakFile.hpp +++ b/Runtime/CPakFile.hpp @@ -36,16 +36,11 @@ public: }; private: - union { - struct { - bool x28_24_buildDepList : 1; - bool x28_25_aramFile : 1; - bool x28_26_worldPak : 1; - bool x28_27_stashedInARAM : 1; - bool m_override : 1; - }; - u32 _dummy = 0; - }; + bool x28_24_buildDepList : 1; + bool x28_25_aramFile : 1; + bool x28_26_worldPak : 1; + bool x28_27_stashedInARAM : 1; + bool m_override : 1; enum class EAsyncPhase { Warmup = 0, InitialHeader = 1, diff --git a/Runtime/CPlayerState.cpp b/Runtime/CPlayerState.cpp index 38e9e9841..210a7f4e0 100644 --- a/Runtime/CPlayerState.cpp +++ b/Runtime/CPlayerState.cpp @@ -74,13 +74,13 @@ constexpr std::array ComboAmmoPeriods{ }; } // Anonymous namespace -CPlayerState::CPlayerState() : x188_staticIntf(5) { - x0_24_alive = true; +CPlayerState::CPlayerState() +: x0_24_alive(true), x0_25_firingComboBeam(false), x0_26_fusion(false), x188_staticIntf(5) { x24_powerups.resize(41); } -CPlayerState::CPlayerState(CBitStreamReader& stream) : x188_staticIntf(5) { - x0_24_alive = true; +CPlayerState::CPlayerState(CBitStreamReader& stream) +: x0_24_alive(true), x0_25_firingComboBeam(false), x0_26_fusion(false), x188_staticIntf(5) { x4_enabledItems = u32(stream.ReadEncoded(32)); const u32 integralHP = u32(stream.ReadEncoded(32)); diff --git a/Runtime/CPlayerState.hpp b/Runtime/CPlayerState.hpp index 22134070d..192095668 100644 --- a/Runtime/CPlayerState.hpp +++ b/Runtime/CPlayerState.hpp @@ -94,15 +94,9 @@ private: constexpr CPowerUp() = default; constexpr 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; - }; - + bool x0_24_alive : 1; + bool x0_25_firingComboBeam : 1; + bool x0_26_fusion : 1; u32 x4_enabledItems = 0; EBeamId x8_currentBeam = EBeamId::Power; CHealthInfo xc_health = {99.f, 50.f}; diff --git a/Runtime/CRandom16.hpp b/Runtime/CRandom16.hpp index 3d82cd886..4b3354286 100644 --- a/Runtime/CRandom16.hpp +++ b/Runtime/CRandom16.hpp @@ -9,7 +9,7 @@ class CRandom16 { static CRandom16* g_randomNumber; public: - CRandom16(s32 p = 99) : m_seed(p) {} + explicit CRandom16(s32 seed = 99) : m_seed(seed) {} s32 Next() { m_seed = (m_seed * 0x41c64e6d) + 0x00003039; @@ -18,7 +18,7 @@ public: s32 GetSeed() const { return m_seed; } - void SetSeed(s32 p) { m_seed = p; } + void SetSeed(s32 seed) { m_seed = seed; } float Float() { return Next() * 0.000015259022f; } diff --git a/Runtime/CResFactory.cpp b/Runtime/CResFactory.cpp index a90a48835..2968b6d02 100644 --- a/Runtime/CResFactory.cpp +++ b/Runtime/CResFactory.cpp @@ -28,7 +28,7 @@ CFactoryFnReturn CResFactory::BuildSync(const SObjectTag& tag, const CVParamTran else ret = std::make_unique(nullptr); } - Log.report(logvisor::Warning, fmt("sync-built {}"), tag); + Log.report(logvisor::Warning, FMT_STRING("sync-built {}"), tag); return ret; } @@ -38,7 +38,7 @@ bool CResFactory::PumpResource(SLoadingData& data) { *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, fmt("async-built {}"), data.x0_tag); + Log.report(logvisor::Info, FMT_STRING("async-built {}"), data.x0_tag); return true; } return false; diff --git a/Runtime/CResLoader.cpp b/Runtime/CResLoader.cpp index 075e8288b..24318ad84 100644 --- a/Runtime/CResLoader.cpp +++ b/Runtime/CResLoader.cpp @@ -210,7 +210,7 @@ bool CResLoader::FindResource(CAssetId id) const { return true; } - Log.report(logvisor::Warning, fmt("Unable to find asset {}"), id); + Log.report(logvisor::Warning, FMT_STRING("Unable to find asset {}"), id); return false; } @@ -234,7 +234,7 @@ CPakFile* CResLoader::FindResourceForLoad(CAssetId id) { } } - Log.report(logvisor::Error, fmt("Unable to find asset {}"), id); + Log.report(logvisor::Error, FMT_STRING("Unable to find asset {}"), id); return nullptr; } diff --git a/Runtime/CScannableObjectInfo.cpp b/Runtime/CScannableObjectInfo.cpp index f0658f7e3..c4e8a8c58 100644 --- a/Runtime/CScannableObjectInfo.cpp +++ b/Runtime/CScannableObjectInfo.cpp @@ -4,26 +4,30 @@ namespace urde { CScannableObjectInfo::CScannableObjectInfo(CInputStream& in, CAssetId resId) : x0_scannableObjectId(resId) { - u32 version = in.readUint32Big(); + const u32 version = in.readUint32Big(); Load(in, version); - for (u32 i = 0; i < x14_buckets.size(); ++i) { - x14_buckets[i].x4_appearanceRange *= x8_totalDownloadTime; + for (auto& bucket : x14_buckets) { + bucket.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; + const float appearanceOffset = g_tweakGui->GetScanAppearanceDuration(); + for (size_t i = 0; i < x14_buckets.size(); ++i) { + if (x14_buckets[i].x8_imagePos == UINT32_MAX) { + continue; + } + + x8_totalDownloadTime += appearanceOffset; + for (size_t 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 (size_t i = 0; i < x14_buckets.size() - 1; ++i) { + for (size_t j = i + 1; j < x14_buckets.size(); ++j) { + if (x14_buckets[i].x8_imagePos == x14_buckets[j].x8_imagePos && x14_buckets[i].x8_imagePos != UINT32_MAX) { + x14_buckets[j].x8_imagePos = UINT32_MAX; + } } } } @@ -32,18 +36,20 @@ void CScannableObjectInfo::Load(CInputStream& in, u32 version) { in.readUint32Big(); in.readUint32Big(); x4_stringId = in.readUint32Big(); - if (version < 4) + if (version < 4) { x8_totalDownloadTime = in.readFloatBig(); - else { - u32 scanSpeed = in.readUint32Big(); + } else { + const u32 scanSpeed = in.readUint32Big(); x8_totalDownloadTime = g_tweakGui->GetScanSpeed(scanSpeed); } xc_category = in.readUint32Big(); - if (version > 4) + if (version > 4) { x10_important = in.readBool(); + } - for (u32 i = 0; i < 4; i++) + for (size_t i = 0; i < x14_buckets.capacity(); i++) { x14_buckets.emplace_back(in, version); + } } CScannableObjectInfo::SBucket::SBucket(CInputStream& in, u32 version) { diff --git a/Runtime/CScannableObjectInfo.hpp b/Runtime/CScannableObjectInfo.hpp index 79096333e..565a382f8 100644 --- a/Runtime/CScannableObjectInfo.hpp +++ b/Runtime/CScannableObjectInfo.hpp @@ -12,6 +12,8 @@ class CScannableObjectInfo { public: enum class EPanelType {}; + static constexpr size_t NumBuckets = 4; + struct SBucket { CAssetId x0_texture; float x4_appearanceRange = 0.f; @@ -29,14 +31,14 @@ private: float x8_totalDownloadTime = 0.f; u32 xc_category = 0; bool x10_important = false; - rstl::reserved_vector x14_buckets; + 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]; } + const SBucket& GetBucket(size_t idx) const { return x14_buckets[idx]; } u32 GetCategory() const { return xc_category; } bool IsImportant() const { return x10_important; } }; diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index fda9eeb25..bbc581345 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -62,7 +62,14 @@ CStateManager::CStateManager(const std::weak_ptr& relayTracker, , x8bc_relayTracker(relayTracker) , x8c0_mapWorldInfo(mwInfo) , x8c4_worldTransManager(wtMgr) -, x8c8_worldLayerState(layerState) { +, x8c8_worldLayerState(layerState) +, xf94_24_readyToRender(false) +, xf94_25_quitGame(false) +, xf94_26_generatingObject(false) +, xf94_27_inMapScreen(false) +, xf94_28_inSaveUI(false) +, xf94_29_cinematicPause(false) +, xf94_30_fullThreat(false) { x86c_stateManagerContainer = std::make_unique(); x870_cameraManager = &x86c_stateManagerContainer->x0_cameraManager; x874_sortedListManager = &x86c_stateManagerContainer->x3c0_sortedListManager; @@ -410,12 +417,7 @@ void CStateManager::SetupParticleHook(const CActor& actor) const { void CStateManager::MurderScriptInstanceNames() { xb40_uniqueInstanceNames.clear(); } std::string CStateManager::HashInstanceName(CInputStream& in) { - if (hecl::com_developer && hecl::com_developer->toBoolean()) { - return in.readString(); - } else { - while (in.readByte() != 0) {}; - return ""; - } + return in.readString(); } void CStateManager::SetActorAreaId(CActor& actor, TAreaId aid) { @@ -510,6 +512,7 @@ void CStateManager::BuildDynamicLightListForWorld() { } void CStateManager::DrawDebugStuff() const { +#ifndef NDEBUG for (CEntity* ent : GetActorObjectList()) { if (TCastToPtr ai = ent) { if (CPathFindSearch* path = ai->GetSearchPath()) { @@ -517,6 +520,7 @@ void CStateManager::DrawDebugStuff() const { } } } +#endif } void CStateManager::RenderCamerasAndAreaLights() { @@ -909,7 +913,7 @@ void CStateManager::DrawActorCubeFaces(CActor& actor, int& cubeInst) const { } for (int f = 0; f < 6; ++f) { - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CStateManager::DrawActorCubeFaces [{}] {} {} {}"), f, + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CStateManager::DrawActorCubeFaces [{}] {} {} {}"), f, actor.GetUniqueId(), actor.GetEditorId(), actor.GetName()) .c_str(), zeus::skOrange); @@ -1204,7 +1208,7 @@ void CStateManager::RecursiveDrawTree(TUniqueId node) { 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, fmt("Sending '{}' to '{}' id= {}"), ScriptObjectMessageToStr(msg), + LogModule.report(logvisor::Info, FMT_STRING("Sending '{}' to '{}' id= {}"), ScriptObjectMessageToStr(msg), dest->GetName(), dest->GetUniqueId()); dest->AcceptScriptMsg(msg, src, *this); } @@ -1219,7 +1223,7 @@ void CStateManager::SendScriptMsgAlways(TUniqueId dest, TUniqueId src, EScriptOb CEntity* dst = ObjectById(dest); if (dst) { if (sm_logScripting && sm_logScripting->toBoolean()) - LogModule.report(logvisor::Info, fmt("Sending '{}' to '{}' id= {}"), ScriptObjectMessageToStr(msg), + LogModule.report(logvisor::Info, FMT_STRING("Sending '{}' to '{}' id= {}"), ScriptObjectMessageToStr(msg), dst->GetName(), dst->GetUniqueId()); dst->AcceptScriptMsg(msg, src, *this); } @@ -1275,7 +1279,7 @@ void CStateManager::FreeScriptObject(TUniqueId id) { } if (sm_logScripting && sm_logScripting->toBoolean()) - LogModule.report(logvisor::Info, fmt("Removed '{}'"), ent->GetName()); + LogModule.report(logvisor::Info, FMT_STRING("Removed '{}'"), ent->GetName()); } std::pair CStateManager::GetBuildForScript(TEditorId id) const { @@ -1367,16 +1371,16 @@ std::pair CStateManager::LoadScriptObject(TAreaId aid, ESc u32 readAmt = in.position() - startPos; if (readAmt > length) - LogModule.report(logvisor::Fatal, fmt("Script object overread while reading {}"), ScriptObjectTypeToStr(type)); + LogModule.report(logvisor::Fatal, FMT_STRING("Script object overread while reading {}"), ScriptObjectTypeToStr(type)); u32 leftover = length - readAmt; for (u32 i = 0; i < leftover; ++i) in.readByte(); if (error || ent == nullptr) { - LogModule.report(logvisor::Error, fmt("Script load error while loading {}"), ScriptObjectTypeToStr(type)); + LogModule.report(logvisor::Error, FMT_STRING("Script load error while loading {}"), ScriptObjectTypeToStr(type)); return {kInvalidEditorId, kInvalidUniqueId}; } else { - LogModule.report(logvisor::Info, fmt("Loaded {} in area {}"), ent->GetName(), ent->GetAreaIdAlways()); + LogModule.report(logvisor::Info, FMT_STRING("Loaded {} in area {}"), ent->GetName(), ent->GetAreaIdAlways()); return {id, ent->GetUniqueId()}; } } @@ -1421,11 +1425,14 @@ void CStateManager::InformListeners(const zeus::CVector3f& pos, EListenNoiseType 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) + if (vuln.GetVulnerability(info.GetWeaponMode(), false) == EVulnerability::Deflect) { return; + } + CHealthInfo* hInfo = actor.HealthInfo(*this); - if (!hInfo) + if (hInfo == nullptr) { return; + } float dampedPower = (1.f - dampen) * info.GetKnockBackPower(); if (TCastToPtr player = actor) { @@ -1439,30 +1446,34 @@ void CStateManager::ApplyKnockBack(CActor& actor, const CDamageInfo& info, const 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)) + !physActor->GetMaterialList().HasMaterial(EMaterialTypes::Solid)) { return; + } physActor->ApplyImpulseWR(kbVec, zeus::CAxisAngle()); return; } } } - if (ai) + 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)) + 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) + if (surface != CPlayer::ESurfaceRestraints::Normal && player.GetOrbitState() == CPlayer::EPlayerOrbitState::NoOrbit) { usePower /= 7.f; + } } else { usePower = power * 500.f; } @@ -1489,15 +1500,17 @@ void CStateManager::ApplyDamageToWorld(TUniqueId damager, const CActor& actor, c bool bomb = false; TCastToConstPtr weapon = actor; - if (weapon) + if (weapon) { bomb = True(weapon->GetAttribField() & (EProjectileAttrib::Bombs | EProjectileAttrib::PowerBombs)); + } rstl::reserved_vector nearList; BuildNearList(nearList, aabb, filter, &actor); for (TUniqueId id : nearList) { CEntity* ent = ObjectById(id); - if (!ent) + if (ent == nullptr) { continue; + } TCastToPtr player = ent; if (bomb && player) { @@ -1506,20 +1519,24 @@ void CStateManager::ApplyDamageToWorld(TUniqueId damager, const CActor& actor, c MP1::CSamusHud::DisplayHudMemo(u"", CHUDMemoParms{0.f, true, true, true}); player->UnFreeze(*this); } else { - if ((weapon->GetAttribField() & EProjectileAttrib::Bombs) == EProjectileAttrib::Bombs) + 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)) + if (TestRayDamage(pos, static_cast(*ent), nearList)) { ApplyRadiusDamage(actor, pos, static_cast(*ent), info); + } } - if (TCastToPtr swarm = ent) + if (TCastToPtr swarm = ent) { swarm->ApplyRadiusDamage(pos, info, *this); + } - if (TCastToPtr swarm = ent) + if (TCastToPtr swarm = ent) { swarm->ApplyRadiusDamage(pos, info, *this); + } } } @@ -1548,28 +1565,29 @@ void CStateManager::ApplyRadiusDamage(const CActor& a1, const zeus::CVector3f& p ((bounds = a2.GetTouchBounds()) && CCollidableSphere::Sphere_AABox_Bool(zeus::CSphere{pos, info.GetRadius()}, *bounds))) { float rad = info.GetRadius(); - if (rad > FLT_EPSILON) + if (rad > FLT_EPSILON) { rad = delta.magnitude() / rad; - else + } else { rad = 0.f; - if (rad > 0.f) + } + if (rad > 0.f) { delta.normalize(); + } bool alive = false; - if (CHealthInfo* hInfo = a2.HealthInfo(*this)) - if (hInfo->GetHP() > 0.f) + 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 = rad > 0.f ? a2.GetDamageVulnerability(pos, delta, info) : a2.GetDamageVulnerability(); if (vuln->WeaponHurts(info.GetWeaponMode(), true)) { float dam = info.GetRadiusDamage(*vuln); - if (dam > 0.f) + 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 { @@ -1577,8 +1595,9 @@ void CStateManager::ApplyRadiusDamage(const CActor& a1, const zeus::CVector3f& p SendScriptMsg(&a2, a1.GetUniqueId(), EScriptObjectMessage::InvulnDamage); } - if (alive && info.GetKnockBackPower() > 0.f) + if (alive && info.GetKnockBackPower() > 0.f) { ApplyKnockBack(a2, info, *vuln, (a2.GetTranslation() - a1.GetTranslation()).normalized(), rad); + } } } @@ -2464,7 +2483,7 @@ void CStateManager::AddObject(CEntity& ent) { } if (sm_logScripting && sm_logScripting->toBoolean()) - LogModule.report(logvisor::Info, fmt("Added '{}'"), ent.GetName()); + LogModule.report(logvisor::Info, FMT_STRING("Added '{}'"), ent.GetName()); } void CStateManager::AddObject(CEntity* ent) { @@ -2509,7 +2528,7 @@ TUniqueId CStateManager::AllocateUniqueId() { ourIndex = x0_nextFreeIndex; x0_nextFreeIndex = (x0_nextFreeIndex + 1) & 0x3ff; if (x0_nextFreeIndex == lastIndex) - LogModule.report(logvisor::Fatal, fmt("Object List Full!")); + LogModule.report(logvisor::Fatal, FMT_STRING("Object List Full!")); } while (GetAllObjectList().GetObjectByIndex(ourIndex) != nullptr); x8_idArr[ourIndex] = (x8_idArr[ourIndex] + 1) & 0x3f; @@ -2558,7 +2577,7 @@ std::pair CStateManager::CalculateScanCompletionRate() const { void CStateManager::SetBossParams(TUniqueId bossId, float maxEnergy, u32 stringIdx) { xf18_bossId = bossId; xf1c_totalBossEnergy = maxEnergy; - xf20_bossStringIdx = stringIdx; + xf20_bossStringIdx = stringIdx - (g_Main->IsUSA() && !g_Main->IsTrilogy() ? 0 : 6); } float CStateManager::IntegrateVisorFog(float f) const { diff --git a/Runtime/CStateManager.hpp b/Runtime/CStateManager.hpp index 225c79e07..1b138b7b7 100644 --- a/Runtime/CStateManager.hpp +++ b/Runtime/CStateManager.hpp @@ -202,19 +202,13 @@ private: 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; - }; + 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; CColoredQuadFilter m_deathWhiteout{EFilterType::Add}; CColoredQuadFilter m_escapeWhiteout{EFilterType::Add}; diff --git a/Runtime/CStopwatch.hpp b/Runtime/CStopwatch.hpp index 8d1d5fa30..301dff669 100644 --- a/Runtime/CStopwatch.hpp +++ b/Runtime/CStopwatch.hpp @@ -12,13 +12,17 @@ public: double report(const char* name) const { double t = std::chrono::duration_cast( std::chrono::steady_clock::now() - m_start).count() / 1000000.0; - fmt::print(fmt("{} {}\n"), name, t); +#ifndef NDEBUG + fmt::print(FMT_STRING("{} {}\n"), name, t); +#endif return t; } double reportReset(const char* name) { std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); double t = std::chrono::duration_cast(now - m_start).count() / 1000000.0; - fmt::print(fmt("{} {}\n"), name, t); +#ifndef NDEBUG + fmt::print(FMT_STRING("{} {}\n"), name, t); +#endif m_start = now; return t; } diff --git a/Runtime/Camera/CBallCamera.cpp b/Runtime/Camera/CBallCamera.cpp index d2b285ae8..0f24b66e9 100644 --- a/Runtime/Camera/CBallCamera.cpp +++ b/Runtime/Camera/CBallCamera.cpp @@ -275,7 +275,7 @@ void CBallCamera::SetState(EBallCameraState state, CStateManager& mgr) { x400_state = state; } -static const CMaterialFilter BallCameraFilter = CMaterialFilter::MakeIncludeExclude( +constexpr CMaterialFilter BallCameraFilter = CMaterialFilter::MakeIncludeExclude( {EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player, EMaterialTypes::Character, EMaterialTypes::CameraPassthrough}); diff --git a/Runtime/Camera/CCameraManager.cpp b/Runtime/Camera/CCameraManager.cpp index b73158140..f2a61f4f7 100644 --- a/Runtime/Camera/CCameraManager.cpp +++ b/Runtime/Camera/CCameraManager.cpp @@ -21,9 +21,15 @@ namespace urde { float CCameraManager::sFirstPersonFOV = 55.f; -CCameraManager::CCameraManager(TUniqueId curCameraId) : x0_curCameraId(curCameraId) { - CSfxManager::AddListener(CSfxManager::ESfxChannels::Game, zeus::skZero3f, zeus::skZero3f, - {1.f, 0.f, 0.f}, {0.f, 0.f, 1.f}, 50.f, 50.f, 1000.f, 1, 1.f); +CCameraManager::CCameraManager(TUniqueId curCameraId) +: x0_curCameraId(curCameraId) +, xa0_24_pendingRumble(false) +, xa0_25_rumbling(false) +, xa0_26_inWater(false) +, x3b8_24_(false) +, x3b8_25_(false) { + CSfxManager::AddListener(CSfxManager::ESfxChannels::Game, zeus::skZero3f, zeus::skZero3f, {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(); } @@ -398,8 +404,7 @@ void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) { } } else { if (const TCastToConstPtr act = mgr.GetObjectById(bestHint->GetFirstHelper())) { - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - zeus::CVector3f f26 = act->GetTranslation() - ballPos; + const zeus::CVector3f f26 = act->GetTranslation() - mgr.GetPlayer().GetBallPosition(); zeus::CVector3f ballToHelper = f26; if (ballToHelper.canBeNormalized()) { ballToHelper.normalize(); diff --git a/Runtime/Camera/CCameraManager.hpp b/Runtime/Camera/CCameraManager.hpp index 7268b6bf8..60b5edd40 100644 --- a/Runtime/Camera/CCameraManager.hpp +++ b/Runtime/Camera/CCameraManager.hpp @@ -40,16 +40,9 @@ class CCameraManager { 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; - }; - + bool xa0_24_pendingRumble : 1; + bool xa0_25_rumbling : 1; + bool xa0_26_inWater : 1; TUniqueId xa2_spindleCamId = kInvalidUniqueId; TUniqueId xa4_pathCamId = kInvalidUniqueId; TUniqueId xa6_camHintId = kInvalidUniqueId; @@ -57,15 +50,8 @@ class CCameraManager { 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; - }; - + bool x3b8_24_ : 1; + bool x3b8_25_ : 1; float x3bc_curFov = 60.f; void SetPathCamera(TUniqueId id, CStateManager& mgr); diff --git a/Runtime/Camera/CCameraShakeData.cpp b/Runtime/Camera/CCameraShakeData.cpp index 6de888378..ab926ad7f 100644 --- a/Runtime/Camera/CCameraShakeData.cpp +++ b/Runtime/Camera/CCameraShakeData.cpp @@ -100,29 +100,29 @@ float CCameraShakeData::GetMaxFMComponent() const { } CCameraShakeData CCameraShakeData::LoadCameraShakeData(CInputStream& in) { - float xMag = in.readFloatBig(); + const float xMag = in.readFloatBig(); in.readFloatBig(); - float yMag = in.readFloatBig(); + const float yMag = in.readFloatBig(); in.readFloatBig(); - float zMag = in.readFloatBig(); + const float zMag = in.readFloatBig(); in.readFloatBig(); - float duration = in.readFloatBig(); + const 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); + const SCameraShakePoint xAM(false, 0.f, 0.f, duration, 2.f * xMag); + const SCameraShakePoint yAM(false, 0.f, 0.f, duration, 2.f * yMag); + const SCameraShakePoint zAM(false, 0.f, 0.f, duration, 2.f * zMag); + const SCameraShakePoint xFM(false, 0.f, 0.f, 0.5f * duration, 3.f); + const SCameraShakePoint yFM(false, 0.f, 0.f, 0.5f * duration, 0.f); + const SCameraShakePoint zFM(false, 0.f, 0.f, 0.5f * duration, 3.f); - CCameraShakerComponent shakerX(1, xAM, xFM); - CCameraShakerComponent shakerY; - CCameraShakerComponent shakerZ(1, zAM, zFM); + const CCameraShakerComponent shakerX(true, xAM, xFM); + const CCameraShakerComponent shakerY; + const CCameraShakerComponent shakerZ(true, zAM, zFM); return {duration, 100.f, 0, zeus::skZero3f, shakerX, shakerY, shakerZ}; } -const CCameraShakeData CCameraShakeData::skChargedShotCameraShakeData{ +constexpr CCameraShakeData CCameraShakeData::skChargedShotCameraShakeData{ 0.3f, 100.f, 0, diff --git a/Runtime/Camera/CPathCamera.cpp b/Runtime/Camera/CPathCamera.cpp index ef43a8111..ea39057ae 100644 --- a/Runtime/Camera/CPathCamera.cpp +++ b/Runtime/Camera/CPathCamera.cpp @@ -79,7 +79,7 @@ void CPathCamera::ProcessInput(const CFinalInput&, CStateManager& mgr) { // Empty } -static const CMaterialFilter kLineOfSightFilter = +constexpr CMaterialFilter kLineOfSightFilter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough}); void CPathCamera::Reset(const zeus::CTransform&, CStateManager& mgr) { diff --git a/Runtime/Character/CActorLights.cpp b/Runtime/Character/CActorLights.cpp index 3317c506e..4144aa614 100644 --- a/Runtime/Character/CActorLights.cpp +++ b/Runtime/Character/CActorLights.cpp @@ -18,20 +18,22 @@ 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) +: x298_24_dirty(true) +, x298_25_castShadows(true) +, x298_26_hasAreaLights(false) +, x298_27_findShadowLight(false) +, x298_28_inArea(!disableWorldLights && maxAreaLights > 0) +, x298_29_ambienceGenerated(ambientChannelOverflow) +, x298_30_layer2(layer2) +, x298_31_disableWorldLights(disableWorldLights) +, x299_24_inBrightLight(true) +, x299_25_useBrightLightLag(false) +, x299_26_ambientOnly(false) +, 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; - x298_29_ambienceGenerated = ambientChannelOverflow; - x298_30_layer2 = layer2; - x298_31_disableWorldLights = disableWorldLights; - x299_24_inBrightLight = true; - sFrameSchedulerCount++; sFrameSchedulerCount &= 7; } diff --git a/Runtime/Character/CActorLights.hpp b/Runtime/Character/CActorLights.hpp index a6af5e8bd..4a5044786 100644 --- a/Runtime/Character/CActorLights.hpp +++ b/Runtime/Character/CActorLights.hpp @@ -20,23 +20,17 @@ class CActorLights { std::vector x144_dynamicLights; zeus::CColor x288_ambientColor = zeus::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; - }; + 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; diff --git a/Runtime/Character/CAllFormatsAnimSource.cpp b/Runtime/Character/CAllFormatsAnimSource.cpp index b36b72b7f..025eed532 100644 --- a/Runtime/Character/CAllFormatsAnimSource.cpp +++ b/Runtime/Character/CAllFormatsAnimSource.cpp @@ -21,7 +21,7 @@ void CAnimFormatUnion::SubConstruct(u8* storage, EAnimFormat fmt, CInputStream& new (storage) CFBStreamedCompression(in, store, true); break; default: - Log.report(logvisor::Fatal, fmt("unable to read ANIM format {}"), int(fmt)); + Log.report(logvisor::Fatal, FMT_STRING("unable to read ANIM format {}"), int(fmt)); } } diff --git a/Runtime/Character/CAnimData.cpp b/Runtime/Character/CAnimData.cpp index f201b064b..9c6431c96 100644 --- a/Runtime/Character/CAnimData.cpp +++ b/Runtime/Character/CAnimData.cpp @@ -45,9 +45,9 @@ CAnimData::CAnimData(CAssetId id, const CCharacterInfo& character, int defaultAn const std::weak_ptr& ctx, std::shared_ptr animMgr, std::shared_ptr transMgr, TLockedToken charFactory, int drawInstCount) -: x0_charFactory(std::move(charFactory)) +: x0_charFactory(charFactory) , xc_charInfo(character) -, xcc_layoutData(std::move(layout)) +, xcc_layoutData(layout) , xd8_modelData(std::move(model)) , xfc_animCtx(ctx.lock()) , x100_animMgr(std::move(animMgr)) @@ -55,6 +55,14 @@ CAnimData::CAnimData(CAssetId id, const CCharacterInfo& character, int defaultAn , x1fc_transMgr(std::move(transMgr)) , x204_charIdx(charIdx) , x208_defaultAnim(defaultAnim) +, x220_24_animating(false) +, x220_25_loop(false) +, x220_26_aligningPos(false) +, x220_27_(false) +, x220_28_(false) +, x220_29_animationJustStarted(false) +, x220_30_poseBuilt(false) +, x220_31_poseCached(false) , x224_pose(layout->GetSegIdList().GetList().size()) , x2fc_poseBuilder(CLayoutDescription{layout}) , m_drawInstCount(drawInstCount) { @@ -78,7 +86,7 @@ CAnimData::CAnimData(CAssetId id, const CCharacterInfo& character, int defaultAn if (defaultAnim == -1) { defaultAnim = 0; - Log.report(logvisor::Warning, fmt("Character {} has invalid initial animation, so defaulting to first."), + Log.report(logvisor::Warning, FMT_STRING("Character {} has invalid initial animation, so defaulting to first."), character.GetCharacterName()); } @@ -135,11 +143,13 @@ SAdvancementDeltas CAnimData::AdvanceAdditiveAnims(float dt) { 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); + x210_passedIntCount += + u32(anim->GetInt32POIList(time, g_Int32POINodes.data(), g_Int32POINodes.size(), x210_passedIntCount, 0)); + x20c_passedBoolCount += + u32(anim->GetBoolPOIList(time, g_BoolPOINodes.data(), g_BoolPOINodes.size(), 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); + u32(anim->GetParticlePOIList(time, g_ParticlePOINodes.data(), 8, x214_passedParticleCount, 0)); + x218_passedSoundCount += u32(anim->GetSoundPOIList(time, g_SoundPOINodes.data(), 8, x218_passedSoundCount, 0)); SAdvancementResults results = AdvanceAdditiveAnim(anim, time); deltas.x0_posDelta += results.x8_deltas.x0_posDelta; @@ -149,11 +159,13 @@ SAdvancementDeltas CAnimData::AdvanceAdditiveAnims(float dt) { } 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); + x210_passedIntCount += + u32(anim->GetInt32POIList(time, g_Int32POINodes.data(), g_Int32POINodes.size(), x210_passedIntCount, 0)); + x20c_passedBoolCount += + u32(anim->GetBoolPOIList(time, g_BoolPOINodes.data(), g_BoolPOINodes.size(), 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); + u32(anim->GetParticlePOIList(time, g_ParticlePOINodes.data(), 8, x214_passedParticleCount, 0)); + x218_passedSoundCount += u32(anim->GetSoundPOIList(time, g_SoundPOINodes.data(), 8, x218_passedSoundCount, 0)); SAdvancementResults results = AdvanceAdditiveAnim(anim, time); deltas.x0_posDelta += results.x8_deltas.x0_posDelta; @@ -263,8 +275,9 @@ SAdvancementDeltas CAnimData::GetAdvancementDeltas(const CCharAnimTime& a, const } CCharAnimTime CAnimData::GetTimeOfUserEvent(EUserEventType type, const CCharAnimTime& time) const { - u32 count = x1f8_animRoot->GetInt32POIList(time, g_TransientInt32POINodes.data(), 16, 0, 64); - for (u32 i = 0; i < count; ++i) { + const size_t count = + x1f8_animRoot->GetInt32POIList(time, g_TransientInt32POINodes.data(), g_TransientInt32POINodes.size(), 0, 64); + for (size_t i = 0; i < count; ++i) { CInt32POINode& poi = g_TransientInt32POINodes[i]; if (poi.GetPoiType() == EPOIType::UserEvent && EUserEventType(poi.GetValue()) == type) { CCharAnimTime ret = poi.GetTime(); @@ -283,8 +296,8 @@ void CAnimData::MultiplyPlaybackRate(float mul) { x200_speedScale *= mul; } void CAnimData::SetPlaybackRate(float set) { x200_speedScale = set; } void CAnimData::SetRandomPlaybackRate(CRandom16& r) { - for (u32 i = 0; i < x210_passedIntCount; ++i) { - CInt32POINode& poi = g_Int32POINodes[i]; + for (size_t i = 0; i < x210_passedIntCount; ++i) { + const CInt32POINode& poi = g_Int32POINodes[i]; if (poi.GetPoiType() == EPOIType::RandRate) { float tmp = (r.Next() % poi.GetValue()) / 100.f; if ((r.Next() % 100) < 50) @@ -304,10 +317,10 @@ void CAnimData::CalcPlaybackAlignmentParms(const CAnimPlaybackParms& parms, x220_27_ = false; if (parms.GetDeltaOrient() && parms.GetObjectXform()) { ResetPOILists(); - x210_passedIntCount += - node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), 16, x210_passedIntCount, 64); - for (u32 i = 0; i < x210_passedIntCount; ++i) { - CInt32POINode& poi = g_Int32POINodes[i]; + x210_passedIntCount += u32(node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), + g_Int32POINodes.size(), x210_passedIntCount, 64)); + for (size_t i = 0; i < x210_passedIntCount; ++i) { + const 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(), @@ -328,10 +341,10 @@ void CAnimData::CalcPlaybackAlignmentParms(const CAnimPlaybackParms& parms, CCharAnimTime timeStart, timeAlign; if (parms.GetTargetPos() && parms.GetObjectXform()) { ResetPOILists(); - x210_passedIntCount += - node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), 16, x210_passedIntCount, 64); - for (u32 i = 0; i < x210_passedIntCount; ++i) { - CInt32POINode& poi = g_Int32POINodes[i]; + x210_passedIntCount += u32(node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), + g_Int32POINodes.size(), x210_passedIntCount, 64)); + for (size_t i = 0; i < x210_passedIntCount; ++i) { + const CInt32POINode& poi = g_Int32POINodes[i]; if (poi.GetPoiType() == EPOIType::UserEvent) { if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPosStart) { didStart = true; @@ -380,9 +393,9 @@ void CAnimData::CalcPlaybackAlignmentParms(const CAnimPlaybackParms& parms, zeus::CVector3f startPos; if (parms.GetTargetPos() && parms.GetObjectXform()) { ResetPOILists(); - x210_passedIntCount += - node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), 16, x210_passedIntCount, 64); - for (u32 i = 0; i < x210_passedIntCount; ++i) { + x210_passedIntCount += u32(node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), + g_Int32POINodes.size(), x210_passedIntCount, 64)); + for (size_t i = 0; i < x210_passedIntCount; ++i) { CInt32POINode& poi = g_Int32POINodes[i]; if (poi.GetPoiType() == EPOIType::UserEvent) { if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPosStart) { @@ -678,23 +691,27 @@ SAdvancementDeltas CAnimData::DoAdvance(float dt, bool& suspendParticles, CRando 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); + x210_passedIntCount += u32(x1f8_animRoot->GetInt32POIList(time, g_Int32POINodes.data(), g_Int32POINodes.size(), + x210_passedIntCount, 0)); + x20c_passedBoolCount += u32( + x1f8_animRoot->GetBoolPOIList(time, g_BoolPOINodes.data(), g_BoolPOINodes.size(), x20c_passedBoolCount, 0)); x214_passedParticleCount += - x1f8_animRoot->GetParticlePOIList(time, g_ParticlePOINodes.data(), 16, x214_passedParticleCount, 0); + u32(x1f8_animRoot->GetParticlePOIList(time, g_ParticlePOINodes.data(), 16, x214_passedParticleCount, 0)); x218_passedSoundCount += - x1f8_animRoot->GetSoundPOIList(time, g_SoundPOINodes.data(), 16, x218_passedSoundCount, 0); + u32(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); + x210_passedIntCount += u32(x1f8_animRoot->GetInt32POIList(time, g_Int32POINodes.data(), g_Int32POINodes.size(), + x210_passedIntCount, 0)); + x20c_passedBoolCount += u32( + x1f8_animRoot->GetBoolPOIList(time, g_BoolPOINodes.data(), g_BoolPOINodes.size(), x20c_passedBoolCount, 0)); x214_passedParticleCount += - x1f8_animRoot->GetParticlePOIList(time, g_ParticlePOINodes.data(), 16, x214_passedParticleCount, 0); + u32(x1f8_animRoot->GetParticlePOIList(time, g_ParticlePOINodes.data(), 16, x214_passedParticleCount, 0)); x218_passedSoundCount += - x1f8_animRoot->GetSoundPOIList(time, g_SoundPOINodes.data(), 16, x218_passedSoundCount, 0); + u32(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())); @@ -721,8 +738,8 @@ SAdvancementDeltas CAnimData::Advance(float dt, const zeus::CVector3f& scale, CS if (suspendParticles) x120_particleDB.SuspendAllActiveEffects(stateMgr); - for (u32 i = 0; i < x214_passedParticleCount; ++i) { - CParticlePOINode& node = g_ParticlePOINodes[i]; + for (size_t i = 0; i < x214_passedParticleCount; ++i) { + const 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); @@ -750,8 +767,8 @@ void CAnimData::AdvanceAnim(CCharAnimTime& time, zeus::CVector3f& offset, zeus:: x1f8_animRoot = CAnimTreeNode::Cast(std::move(*simplified)); if ((x220_28_ || x220_27_) && x210_passedIntCount > 0) { - for (u32 i = 0; i < x210_passedIntCount; ++i) { - CInt32POINode& node = g_Int32POINodes[i]; + for (size_t i = 0; i < x210_passedIntCount; ++i) { + const CInt32POINode& node = g_Int32POINodes[i]; if (node.GetPoiType() == EPOIType::UserEvent) { switch (EUserEventType(node.GetValue())) { case EUserEventType::AlignTargetPosStart: { diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index 184874263..ce488f2a2 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -124,21 +124,14 @@ private: 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; - }; - }; - + 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; diff --git a/Runtime/Character/CAnimPlaybackParms.hpp b/Runtime/Character/CAnimPlaybackParms.hpp index 988e55242..0515185d1 100644 --- a/Runtime/Character/CAnimPlaybackParms.hpp +++ b/Runtime/Character/CAnimPlaybackParms.hpp @@ -20,28 +20,29 @@ class CAnimPlaybackParms { const zeus::CVector3f* x24_objectScale = nullptr; public: - CAnimPlaybackParms() = default; - CAnimPlaybackParms(s32 animA, s32 animB, float blendWeight, bool animating) + constexpr CAnimPlaybackParms() = default; + constexpr 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) + constexpr 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; } + + constexpr const zeus::CTransform* GetObjectXform() const { return x20_objectXf; } + constexpr const zeus::CQuaternion* GetDeltaOrient() const { return x1c_deltaOrient; } + constexpr const zeus::CVector3f* GetTargetPos() const { return x14_targetPos; } + constexpr bool GetIsUseLocator() const { return x18_useLocator; } + constexpr const zeus::CVector3f* GetObjectScale() const { return x24_objectScale; } + constexpr s32 GetAnimationId() const { return x0_animA; } + constexpr s32 GetSecondAnimationId() const { return x4_animB; } + constexpr float GetBlendFactor() const { return x8_blendWeight; } + constexpr void SetAnimationId(s32 id) { x0_animA = id; } + constexpr void SetSecondAnimationId(s32 id) { x4_animB = id; } + constexpr void SetBlendFactor(float f) { x8_blendWeight = f; } + constexpr bool GetIsPlayAnimation() const { return xc_animating; } }; } // namespace urde diff --git a/Runtime/Character/CAnimSourceReader.cpp b/Runtime/Character/CAnimSourceReader.cpp index 29c01fb9e..88c72f7eb 100644 --- a/Runtime/Character/CAnimSourceReader.cpp +++ b/Runtime/Character/CAnimSourceReader.cpp @@ -132,8 +132,8 @@ void CAnimSourceReaderBase::UpdatePOIStates() { } } -u32 CAnimSourceReaderBase::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, - u32 unk) const { +size_t CAnimSourceReaderBase::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, + size_t 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, @@ -142,8 +142,8 @@ u32 CAnimSourceReaderBase::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINo return 0; } -u32 CAnimSourceReaderBase::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, - u32 iterator, u32 unk) const { +size_t CAnimSourceReaderBase::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, + size_t 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, @@ -152,8 +152,8 @@ u32 CAnimSourceReaderBase::VGetInt32POIList(const CCharAnimTime& time, CInt32POI return 0; } -u32 CAnimSourceReaderBase::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, - u32 iterator, u32 unk) const { +size_t CAnimSourceReaderBase::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, + size_t 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, @@ -162,8 +162,8 @@ u32 CAnimSourceReaderBase::VGetParticlePOIList(const CCharAnimTime& time, CParti return 0; } -u32 CAnimSourceReaderBase::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, - u32 iterator, u32 unk) const { +size_t CAnimSourceReaderBase::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, + size_t 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, diff --git a/Runtime/Character/CAnimSourceReader.hpp b/Runtime/Character/CAnimSourceReader.hpp index 2628f3655..8509d1885 100644 --- a/Runtime/Character/CAnimSourceReader.hpp +++ b/Runtime/Character/CAnimSourceReader.hpp @@ -61,13 +61,13 @@ protected: public: CAnimSourceReaderBase(std::unique_ptr&& sourceInfo, const CCharAnimTime& time); - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const override; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, - u32) const override; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, + size_t VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, size_t iterator, u32) const override; + size_t VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, size_t iterator, u32) const override; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, - u32) const override; bool VGetBoolPOIState(std::string_view name) const override; s32 VGetInt32POIState(std::string_view name) const override; CParticleData::EParentedMode VGetParticlePOIState(std::string_view name) const override; diff --git a/Runtime/Character/CAnimTreeAnimReaderContainer.cpp b/Runtime/Character/CAnimTreeAnimReaderContainer.cpp index f508095a8..325205bb6 100644 --- a/Runtime/Character/CAnimTreeAnimReaderContainer.cpp +++ b/Runtime/Character/CAnimTreeAnimReaderContainer.cpp @@ -38,23 +38,23 @@ zeus::CQuaternion CAnimTreeAnimReaderContainer::VGetRotation(const CSegId& seg) return x14_reader->VGetRotation(seg); } -u32 CAnimTreeAnimReaderContainer::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, - u32 iterator, u32 unk) const { +size_t CAnimTreeAnimReaderContainer::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, + size_t 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 { +size_t CAnimTreeAnimReaderContainer::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, + size_t capacity, size_t 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 { +size_t CAnimTreeAnimReaderContainer::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, + size_t capacity, size_t 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 { +size_t CAnimTreeAnimReaderContainer::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, + size_t capacity, size_t iterator, u32 unk) const { return x14_reader->GetSoundPOIList(time, listOut, capacity, iterator, unk); } diff --git a/Runtime/Character/CAnimTreeAnimReaderContainer.hpp b/Runtime/Character/CAnimTreeAnimReaderContainer.hpp index 5df66319e..44d55afe0 100644 --- a/Runtime/Character/CAnimTreeAnimReaderContainer.hpp +++ b/Runtime/Character/CAnimTreeAnimReaderContainer.hpp @@ -30,13 +30,13 @@ public: bool VHasOffset(const CSegId& seg) const override; zeus::CVector3f VGetOffset(const CSegId& seg) const override; zeus::CQuaternion VGetRotation(const CSegId& seg) const override; - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const override; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, - u32) const override; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, + size_t VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, size_t iterator, u32) const override; + size_t VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, size_t iterator, u32) const override; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, - u32) const override; bool VGetBoolPOIState(std::string_view name) const override; s32 VGetInt32POIState(std::string_view name) const override; CParticleData::EParentedMode VGetParticlePOIState(std::string_view name) const override; diff --git a/Runtime/Character/CAnimTreeDoubleChild.cpp b/Runtime/Character/CAnimTreeDoubleChild.cpp index bd401390a..2a9d251c0 100644 --- a/Runtime/Character/CAnimTreeDoubleChild.cpp +++ b/Runtime/Character/CAnimTreeDoubleChild.cpp @@ -53,48 +53,52 @@ SAdvancementResults CAnimTreeDoubleChild::VAdvanceView(const CCharAnimTime& 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); +size_t CAnimTreeDoubleChild::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { + size_t newCapacity = x14_a->GetBoolPOIList(time, listOut, capacity, iterator, unk); newCapacity += x18_b->GetBoolPOIList(time, listOut, capacity, newCapacity + iterator, unk); - if (newCapacity > capacity) + 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); +size_t CAnimTreeDoubleChild::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { + size_t newCapacity = x14_a->GetInt32POIList(time, listOut, capacity, iterator, unk); newCapacity += x18_b->GetInt32POIList(time, listOut, capacity, newCapacity + iterator, unk); - if (newCapacity > capacity) + 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); +size_t CAnimTreeDoubleChild::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { + size_t newCapacity = x14_a->GetParticlePOIList(time, listOut, capacity, iterator, unk); newCapacity += x18_b->GetParticlePOIList(time, listOut, capacity, newCapacity + iterator, unk); - if (newCapacity > capacity) + 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); +size_t CAnimTreeDoubleChild::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { + size_t newCapacity = x14_a->GetSoundPOIList(time, listOut, capacity, iterator, unk); newCapacity += x18_b->GetSoundPOIList(time, listOut, capacity, newCapacity + iterator, unk); - if (newCapacity > capacity) + if (newCapacity > capacity) { newCapacity = capacity; + } std::sort(listOut, listOut + newCapacity); diff --git a/Runtime/Character/CAnimTreeDoubleChild.hpp b/Runtime/Character/CAnimTreeDoubleChild.hpp index aa54957c9..22ddbbb2b 100644 --- a/Runtime/Character/CAnimTreeDoubleChild.hpp +++ b/Runtime/Character/CAnimTreeDoubleChild.hpp @@ -34,13 +34,13 @@ public: CAnimTreeDoubleChild(const std::weak_ptr& a, const std::weak_ptr& b, std::string_view name); SAdvancementResults VAdvanceView(const CCharAnimTime& a) override; - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const override; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, - u32) const override; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, + size_t VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, size_t iterator, u32) const override; + size_t VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, size_t iterator, u32) const override; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, - u32) const override; bool VGetBoolPOIState(std::string_view name) const override; s32 VGetInt32POIState(std::string_view name) const override; CParticleData::EParentedMode VGetParticlePOIState(std::string_view name) const override; diff --git a/Runtime/Character/CAnimTreeLoopIn.cpp b/Runtime/Character/CAnimTreeLoopIn.cpp index c8dff7e74..b3c655cbb 100644 --- a/Runtime/Character/CAnimTreeLoopIn.cpp +++ b/Runtime/Character/CAnimTreeLoopIn.cpp @@ -57,26 +57,26 @@ std::unique_ptr CAnimTreeLoopIn::VClone() const { x20_animCtx, x4_name, x30_fundamentals, x88_curTime); } -u32 CAnimTreeLoopIn::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, - u32 unk) const { +size_t CAnimTreeLoopIn::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { return _getPOIList(time, listOut, capacity, iterator, unk, x30_fundamentals.GetBoolPointsOfInterest(), x88_curTime); } -u32 CAnimTreeLoopIn::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, - u32 unk) const { +size_t CAnimTreeLoopIn::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { return _getPOIList(time, listOut, capacity, iterator, unk, x30_fundamentals.GetInt32PointsOfInterest(), x88_curTime); } -u32 CAnimTreeLoopIn::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, - u32 iterator, u32 unk) const { +size_t CAnimTreeLoopIn::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { return _getPOIList(time, listOut, capacity, iterator, unk, x30_fundamentals.GetParticlePointsOfInterest(), x88_curTime); } -u32 CAnimTreeLoopIn::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, - u32 unk) const { +size_t CAnimTreeLoopIn::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { return _getPOIList(time, listOut, capacity, iterator, unk, x30_fundamentals.GetSoundPointsOfInterest(), x88_curTime); } diff --git a/Runtime/Character/CAnimTreeLoopIn.hpp b/Runtime/Character/CAnimTreeLoopIn.hpp index 29dc6202e..f1c30730a 100644 --- a/Runtime/Character/CAnimTreeLoopIn.hpp +++ b/Runtime/Character/CAnimTreeLoopIn.hpp @@ -30,13 +30,13 @@ public: std::optional> VSimplified() override; std::shared_ptr VGetBestUnblendedChild() const override; std::unique_ptr VClone() const override; - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const override; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, - u32) const override; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, + size_t VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, size_t iterator, u32) const override; + size_t VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, size_t iterator, u32) const override; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, - u32) const override; CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const override; CCharAnimTime VGetTimeRemaining() const override; SAdvancementResults VAdvanceView(const CCharAnimTime& dt) override; diff --git a/Runtime/Character/CAnimTreeSequence.cpp b/Runtime/Character/CAnimTreeSequence.cpp index 0308eae34..782401c7b 100644 --- a/Runtime/Character/CAnimTreeSequence.cpp +++ b/Runtime/Character/CAnimTreeSequence.cpp @@ -93,24 +93,24 @@ CSteadyStateAnimInfo CAnimTreeSequence::VGetSteadyStateAnimInfo() const { return x3c_fundamentals.GetSteadyStateAnimInfo(); } -u32 CAnimTreeSequence::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, - u32 unk) const { +size_t CAnimTreeSequence::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, + size_t 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 { +size_t CAnimTreeSequence::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, + size_t 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 { +size_t CAnimTreeSequence::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, + size_t 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 { +size_t CAnimTreeSequence::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { return _getPOIList(time, listOut, capacity, iterator, unk, x3c_fundamentals.GetSoundPointsOfInterest(), x94_curTime); } diff --git a/Runtime/Character/CAnimTreeSequence.hpp b/Runtime/Character/CAnimTreeSequence.hpp index 82e796982..56e038097 100644 --- a/Runtime/Character/CAnimTreeSequence.hpp +++ b/Runtime/Character/CAnimTreeSequence.hpp @@ -32,13 +32,13 @@ public: SAdvancementResults VAdvanceView(const CCharAnimTime& dt) override; CCharAnimTime VGetTimeRemaining() const override; CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const override; - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const override; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, - u32) const override; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, + size_t VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, size_t iterator, u32) const override; + size_t VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, size_t iterator, u32) const override; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, - u32) const override; std::unique_ptr VClone() const override; }; diff --git a/Runtime/Character/CAnimTreeSingleChild.cpp b/Runtime/Character/CAnimTreeSingleChild.cpp index 258225459..0100c0797 100644 --- a/Runtime/Character/CAnimTreeSingleChild.cpp +++ b/Runtime/Character/CAnimTreeSingleChild.cpp @@ -15,23 +15,23 @@ zeus::CVector3f CAnimTreeSingleChild::VGetOffset(const CSegId& seg) const { retu 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 { +size_t CAnimTreeSingleChild::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { return x14_child->GetBoolPOIList(time, listOut, capacity, iterator, unk); } -u32 CAnimTreeSingleChild::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, - u32 iterator, u32 unk) const { +size_t CAnimTreeSingleChild::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { return x14_child->GetInt32POIList(time, listOut, capacity, iterator, unk); } -u32 CAnimTreeSingleChild::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, - u32 iterator, u32 unk) const { +size_t CAnimTreeSingleChild::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { return x14_child->GetParticlePOIList(time, listOut, capacity, iterator, unk); } -u32 CAnimTreeSingleChild::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, - u32 iterator, u32 unk) const { +size_t CAnimTreeSingleChild::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { return x14_child->GetSoundPOIList(time, listOut, capacity, iterator, unk); } diff --git a/Runtime/Character/CAnimTreeSingleChild.hpp b/Runtime/Character/CAnimTreeSingleChild.hpp index 801ef9e97..9ed59f795 100644 --- a/Runtime/Character/CAnimTreeSingleChild.hpp +++ b/Runtime/Character/CAnimTreeSingleChild.hpp @@ -20,13 +20,13 @@ public: bool VHasOffset(const CSegId& seg) const override; zeus::CVector3f VGetOffset(const CSegId& seg) const override; zeus::CQuaternion VGetRotation(const CSegId& seg) const override; - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const override; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, - u32) const override; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, + size_t VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, size_t iterator, u32) const override; + size_t VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, size_t iterator, u32) const override; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, - u32) const override; bool VGetBoolPOIState(std::string_view name) const override; s32 VGetInt32POIState(std::string_view name) const override; CParticleData::EParentedMode VGetParticlePOIState(std::string_view name) const override; diff --git a/Runtime/Character/CAnimTreeTimeScale.cpp b/Runtime/Character/CAnimTreeTimeScale.cpp index c1651e289..a7c2ecba1 100644 --- a/Runtime/Character/CAnimTreeTimeScale.cpp +++ b/Runtime/Character/CAnimTreeTimeScale.cpp @@ -59,43 +59,55 @@ std::optional> CAnimTreeTimeScale::VSimplified() { return std::nullopt; } -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 (u32 i = 0; i < ret; ++i) +size_t CAnimTreeTimeScale::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { + const CCharAnimTime useTime = + time == CCharAnimTime::Infinity() ? x14_child->VGetTimeRemaining() : GetRealLifeTime(time); + const size_t ret = x14_child->GetBoolPOIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) { + for (size_t 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 (u32 i = 0; i < ret; ++i) +size_t CAnimTreeTimeScale::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { + const CCharAnimTime useTime = + time == CCharAnimTime::Infinity() ? x14_child->VGetTimeRemaining() : GetRealLifeTime(time); + const size_t ret = x14_child->GetInt32POIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) { + for (size_t 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 (u32 i = 0; i < ret; ++i) +size_t CAnimTreeTimeScale::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { + const CCharAnimTime useTime = + time == CCharAnimTime::Infinity() ? x14_child->VGetTimeRemaining() : GetRealLifeTime(time); + const size_t ret = x14_child->GetParticlePOIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) { + for (size_t 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 (u32 i = 0; i < ret; ++i) +size_t CAnimTreeTimeScale::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { + const CCharAnimTime useTime = + (time == CCharAnimTime::Infinity()) ? x14_child->VGetTimeRemaining() : GetRealLifeTime(time); + const size_t ret = x14_child->GetSoundPOIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) { + for (size_t i = 0; i < ret; ++i) { listOut[iterator + i].SetTime(GetRealLifeTime(listOut[i].GetTime())); + } + } return ret; } diff --git a/Runtime/Character/CAnimTreeTimeScale.hpp b/Runtime/Character/CAnimTreeTimeScale.hpp index 7439b55de..f591e10a6 100644 --- a/Runtime/Character/CAnimTreeTimeScale.hpp +++ b/Runtime/Character/CAnimTreeTimeScale.hpp @@ -27,13 +27,13 @@ public: void VSetPhase(float) override; std::optional> VSimplified() override; - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const override; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, - u32) const override; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, + size_t VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, size_t iterator, u32) const override; + size_t VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, size_t iterator, + u32) const override; + size_t VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, size_t iterator, u32) const override; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, - u32) const override; bool VGetBoolPOIState(std::string_view name) const override; s32 VGetInt32POIState(std::string_view name) const override; CParticleData::EParentedMode VGetParticlePOIState(std::string_view name) const override; diff --git a/Runtime/Character/CBodyController.cpp b/Runtime/Character/CBodyController.cpp index ddd92cf35..94f86a935 100644 --- a/Runtime/Character/CBodyController.cpp +++ b/Runtime/Character/CBodyController.cpp @@ -12,8 +12,15 @@ 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; +: x0_actor(actor) +, x2a4_bodyStateInfo(actor, bodyType) +, x2f4_bodyType(bodyType) +, x2fc_turnSpeed(turnSpeed) +, x300_24_animationOver(false) +, x300_25_active(false) +, x300_26_frozen(false) +, x300_27_hasBeenFrozen(false) +, x300_28_playDeathAnims(true) { x2a4_bodyStateInfo.x18_bodyController = this; } diff --git a/Runtime/Character/CBodyController.hpp b/Runtime/Character/CBodyController.hpp index ac9839dae..a50d2663d 100644 --- a/Runtime/Character/CBodyController.hpp +++ b/Runtime/Character/CBodyController.hpp @@ -28,16 +28,11 @@ class CBodyController { 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; - }; + 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; diff --git a/Runtime/Character/CBodyState.hpp b/Runtime/Character/CBodyState.hpp index 9dfce3539..17b83075a 100644 --- a/Runtime/Character/CBodyState.hpp +++ b/Runtime/Character/CBodyState.hpp @@ -202,22 +202,23 @@ class CBSJump : public CBodyState { 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; - }; + 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, const CBodyController& bc) const; bool CheckForWallJump(CBodyController& bc, CStateManager& mgr); void CheckForLand(CBodyController& bc, CStateManager& mgr); void PlayJumpLoop(CStateManager& mgr, CBodyController& bc); public: + CBSJump() + : x30_24_bodyForceSet(false) + , x30_25_wallJump(false) + , x30_26_wallBounceRight(false) + , x30_27_wallBounceComplete(false) + , x30_28_startInJumpLoop(false) {} bool IsMoving() const override { return true; } bool ApplyHeadTracking() const override { return false; } bool CanShoot() const override; @@ -277,17 +278,13 @@ public: }; class CBSScripted : public CBodyState { - union { - struct { - bool x4_24_loopAnim : 1; - bool x4_25_timedLoop : 1; - }; - u32 _dummy = 0; - }; + bool x4_24_loopAnim : 1; + bool x4_25_timedLoop : 1; float x8_remTime = 0.f; pas::EAnimationState GetBodyStateTransition(float dt, const CBodyController& bc) const; public: + CBSScripted() : x4_24_loopAnim(false), x4_25_timedLoop(false) {} bool ApplyHeadTracking() const override { return false; } void Start(CBodyController& bc, CStateManager& mgr) override; pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) override; @@ -313,13 +310,8 @@ 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; - }; + bool x18_24_launched : 1; + bool x18_25_needsExit : 1; pas::EAnimationState GetBodyStateTransition(float dt, const CBodyController& bc) const; void FixInPlace(CBodyController& bc); bool CheckForLand(CBodyController& bc, CStateManager& mgr); @@ -327,6 +319,7 @@ class CBSWallHang : public CBodyState { void SetLaunchVelocity(CBodyController& bc); public: + CBSWallHang() : x18_24_launched(false), x18_25_needsExit(false) {} bool IsMoving() const override { return true; } bool CanShoot() const override { return x4_state == pas::EWallHangState::WallHang; } bool IsInAir(const CBodyController& bc) const override; diff --git a/Runtime/Character/CBoneTracking.cpp b/Runtime/Character/CBoneTracking.cpp index 0814f4be2..b6afda934 100644 --- a/Runtime/Character/CBoneTracking.cpp +++ b/Runtime/Character/CBoneTracking.cpp @@ -15,6 +15,8 @@ CBoneTracking::CBoneTracking(const CAnimData& animData, std::string_view bone, : x14_segId(animData.GetCharLayoutInfo().GetSegIdFromString(bone)) , x1c_maxTrackingAngle(maxTrackingAngle) , x20_angSpeed(angSpeed) +, x36_24_active(false) +, x36_25_hasTrackedRotation(false) , x36_26_noParent(True(flags & EBoneTrackingFlags::NoParent)) , x36_27_noParentOrigin(True(flags & EBoneTrackingFlags::NoParentOrigin)) , x36_28_noHorizontalAim(True(flags & EBoneTrackingFlags::NoHorizontalAim)) @@ -107,4 +109,4 @@ void CBoneTracking::UnsetTarget() { x34_target = kInvalidUniqueId; } void CBoneTracking::SetTargetPosition(const zeus::CVector3f& targetPos) { x24_targetPosition = targetPos; } void CBoneTracking::SetNoHorizontalAim(bool b) { x36_28_noHorizontalAim = b; } -} // namespace urde \ No newline at end of file +} // namespace urde diff --git a/Runtime/Character/CBoneTracking.hpp b/Runtime/Character/CBoneTracking.hpp index 148c8de06..94d9456aa 100644 --- a/Runtime/Character/CBoneTracking.hpp +++ b/Runtime/Character/CBoneTracking.hpp @@ -33,17 +33,12 @@ class CBoneTracking { float x20_angSpeed; std::optional x24_targetPosition; TUniqueId x34_target = kInvalidUniqueId; - union { - struct { - bool x36_24_active : 1; - bool x36_25_hasTrackedRotation : 1; - bool x36_26_noParent : 1; - bool x36_27_noParentOrigin : 1; - bool x36_28_noHorizontalAim : 1; - bool x36_29_parentIk : 1; - }; - u32 _dummy = 0; - }; + bool x36_24_active : 1; + bool x36_25_hasTrackedRotation : 1; + bool x36_26_noParent : 1; + bool x36_27_noParentOrigin : 1; + bool x36_28_noHorizontalAim : 1; + bool x36_29_parentIk : 1; public: CBoneTracking(const CAnimData& animData, std::string_view bone, @@ -60,4 +55,4 @@ public: void SetNoHorizontalAim(bool b); }; -} // namespace urde \ No newline at end of file +} // namespace urde diff --git a/Runtime/Character/CIkChain.hpp b/Runtime/Character/CIkChain.hpp index 4df48d3b2..c572dc836 100644 --- a/Runtime/Character/CIkChain.hpp +++ b/Runtime/Character/CIkChain.hpp @@ -21,16 +21,10 @@ class CIkChain { zeus::CQuaternion x24_holdRot; zeus::CVector3f x34_holdPos; float x40_time = 0.f; - - union { - struct { - bool x44_24_activated : 1; - }; - u32 x44_dummy = 0; - }; + bool x44_24_activated : 1; public: - CIkChain() = default; + CIkChain() : x44_24_activated(false) {} bool GetActive() const { return x44_24_activated; } void Update(float); diff --git a/Runtime/Character/CModelData.cpp b/Runtime/Character/CModelData.cpp index b5ee3efda..a9db25302 100644 --- a/Runtime/Character/CModelData.cpp +++ b/Runtime/Character/CModelData.cpp @@ -25,14 +25,16 @@ CModelData::~CModelData() = default; CModelData::CModelData() {} CModelData CModelData::CModelDataNull() { return CModelData(); } -CModelData::CModelData(const CStaticRes& res, int instCount) : x0_scale(res.GetScale()), m_drawInstCount(instCount) { +CModelData::CModelData(const CStaticRes& res, int instCount) +: x0_scale(res.GetScale()), x14_24_renderSorted(false), x14_25_sortThermal(false), m_drawInstCount(instCount) { x1c_normalModel = g_SimplePool->GetObj({SBIG('CMDL'), res.GetId()}); if (!x1c_normalModel) - Log.report(logvisor::Fatal, fmt("unable to find CMDL {}"), res.GetId()); + Log.report(logvisor::Fatal, FMT_STRING("unable to find CMDL {}"), res.GetId()); m_normalModelInst = x1c_normalModel->MakeNewInstance(0, instCount); } -CModelData::CModelData(const CAnimRes& res, int instCount) : x0_scale(res.GetScale()), m_drawInstCount(instCount) { +CModelData::CModelData(const CAnimRes& res, int instCount) +: x0_scale(res.GetScale()), x14_24_renderSorted(false), x14_25_sortThermal(false), m_drawInstCount(instCount) { TToken factory = g_CharFactoryBuilder->GetFactory(res); x10_animData = factory->CreateCharacter(res.GetCharacterNodeId(), res.CanLoop(), factory, res.GetDefaultAnim(), instCount); @@ -76,13 +78,13 @@ bool CModelData::IsLoaded(int shaderIdx) const { } u32 CModelData::GetNumMaterialSets() const { - if (x10_animData) - return x10_animData->GetModelData()->GetModel()->GetNumMaterialSets(); + if (x10_animData) + return x10_animData->GetModelData()->GetModel()->GetNumMaterialSets(); - if (x1c_normalModel) - return x1c_normalModel->GetNumMaterialSets(); + if (x1c_normalModel) + return x1c_normalModel->GetNumMaterialSets(); - return 1; + return 1; } CModelData::EWhichModel CModelData::GetRenderingModel(const CStateManager& stateMgr) { @@ -144,7 +146,7 @@ void CModelData::SetXRayModel(const std::pair& modelSkin) { } else { x2c_xrayModel = g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}); if (!x2c_xrayModel) - Log.report(logvisor::Fatal, fmt("unable to find CMDL {}"), modelSkin.first); + Log.report(logvisor::Fatal, FMT_STRING("unable to find CMDL {}"), modelSkin.first); m_xrayModelInst = x2c_xrayModel->MakeNewInstance(0, m_drawInstCount); } } @@ -161,7 +163,7 @@ void CModelData::SetInfraModel(const std::pair& modelSkin) { } else { x3c_infraModel = g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}); if (!x3c_infraModel) - Log.report(logvisor::Fatal, fmt("unable to find CMDL {}"), modelSkin.first); + Log.report(logvisor::Fatal, FMT_STRING("unable to find CMDL {}"), modelSkin.first); m_infraModelInst = x3c_infraModel->MakeNewInstance(0, m_drawInstCount); } } diff --git a/Runtime/Character/CModelData.hpp b/Runtime/Character/CModelData.hpp index ab746220f..57e1680c7 100644 --- a/Runtime/Character/CModelData.hpp +++ b/Runtime/Character/CModelData.hpp @@ -62,13 +62,8 @@ class CModelData { 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; - }; + bool x14_24_renderSorted : 1; + bool x14_25_sortThermal : 1; zeus::CColor x18_ambientColor; TLockedToken x1c_normalModel; diff --git a/Runtime/Character/CPOINode.cpp b/Runtime/Character/CPOINode.cpp index cd631ad4e..07beb5ce5 100644 --- a/Runtime/Character/CPOINode.cpp +++ b/Runtime/Character/CPOINode.cpp @@ -36,22 +36,24 @@ bool CPOINode::operator>(const CPOINode& other) const { return x1c_time < other. 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; +size_t _getPOIList(const CCharAnimTime& time, T* listOut, size_t capacity, size_t iterator, u32 unk1, + const std::vector& stream, const CCharAnimTime& curTime, const IAnimSourceInfo& animInfo, + size_t passedCount) { + size_t ret = 0; if (animInfo.HasPOIData() && stream.size()) { - CCharAnimTime dur = animInfo.GetAnimationDuration(); + const CCharAnimTime dur = animInfo.GetAnimationDuration(); CCharAnimTime targetTime = curTime + time; - if (targetTime >= dur) + if (targetTime >= dur) { targetTime = dur; + } - if (passedCount >= stream.size()) + if (passedCount >= stream.size()) { return ret; + } CCharAnimTime nodeTime = stream[passedCount].GetTime(); while (passedCount < stream.size() && nodeTime <= targetTime) { - u32 idx = iterator + ret; + const size_t idx = iterator + ret; if (idx < capacity) { listOut[idx] = T::CopyNodeMinusStartTime(stream[passedCount], curTime); ++ret; @@ -65,17 +67,18 @@ u32 _getPOIList(const CCharAnimTime& time, T* listOut, u32 capacity, u32 iterato } template -u32 _getPOIList(const CCharAnimTime& time, T* listOut, u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, const CCharAnimTime& curTime) { - u32 ret = 0; +size_t _getPOIList(const CCharAnimTime& time, T* listOut, size_t capacity, size_t iterator, u32 unk1, + const std::vector& stream, const CCharAnimTime& curTime) { + size_t ret = 0; - CCharAnimTime targetTime = curTime + time; + const CCharAnimTime targetTime = curTime + time; - for (u32 it = iterator; it < stream.size(); ++it) { - CCharAnimTime nodeTime = stream[it].GetTime(); - if (nodeTime > targetTime) + for (size_t it = iterator; it < stream.size(); ++it) { + const CCharAnimTime nodeTime = stream[it].GetTime(); + if (nodeTime > targetTime) { return ret; - u32 idx = iterator + ret; + } + const size_t idx = iterator + ret; if (nodeTime >= curTime && idx < capacity) { listOut[idx] = T::CopyNodeMinusStartTime(stream[it], curTime); ++ret; @@ -85,32 +88,36 @@ u32 _getPOIList(const CCharAnimTime& time, T* listOut, u32 capacity, u32 iterato 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 size_t _getPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, + size_t iterator, u32 unk1, const std::vector& stream, + const CCharAnimTime& curTime, const IAnimSourceInfo& animInfo, + size_t passedCount); +template size_t _getPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, + size_t 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, +template size_t _getPOIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, + size_t 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, + size_t passedCount); +template size_t _getPOIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, + size_t 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, - const CCharAnimTime& curTime); +template size_t _getPOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, + size_t iterator, u32 unk1, const std::vector& stream, + const CCharAnimTime& curTime, const IAnimSourceInfo& animInfo, + size_t passedCount); +template size_t _getPOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, + size_t iterator, u32 unk1, const std::vector& stream, + const CCharAnimTime& curTime); + +template size_t _getPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, + size_t iterator, u32 unk1, const std::vector& stream, + const CCharAnimTime& curTime, const IAnimSourceInfo& animInfo, + size_t passedCount); +template size_t _getPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, + size_t 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 3cc4c89b3..8c58fd4f7 100644 --- a/Runtime/Character/CPOINode.hpp +++ b/Runtime/Character/CPOINode.hpp @@ -53,12 +53,12 @@ public: }; 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); +size_t _getPOIList(const CCharAnimTime& time, T* listOut, size_t capacity, size_t iterator, u32 unk1, + const std::vector& stream, const CCharAnimTime& curTime, const IAnimSourceInfo& animInfo, + size_t passedCount); template -u32 _getPOIList(const CCharAnimTime& time, T* listOut, u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, const CCharAnimTime& curTime); +size_t _getPOIList(const CCharAnimTime& time, T* listOut, size_t capacity, size_t iterator, u32 unk1, + const std::vector& stream, const CCharAnimTime& curTime); } // namespace urde diff --git a/Runtime/Character/CParticleDatabase.cpp b/Runtime/Character/CParticleDatabase.cpp index 573561484..82df24852 100644 --- a/Runtime/Character/CParticleDatabase.cpp +++ b/Runtime/Character/CParticleDatabase.cpp @@ -273,6 +273,7 @@ void CParticleDatabase::AddToRendererClipped(const zeus::CFrustum& frustum) cons } CParticleGenInfo* CParticleDatabase::GetParticleEffect(std::string_view name) const { + // TODO: Heterogeneous lookup when C++20 available auto search = x3c_rendererDrawLoop.find(name.data()); if (search != x3c_rendererDrawLoop.end()) return search->second.get(); diff --git a/Runtime/Character/CRagDoll.cpp b/Runtime/Character/CRagDoll.cpp index 77f6a7f43..0ca6d8b0a 100644 --- a/Runtime/Character/CRagDoll.cpp +++ b/Runtime/Character/CRagDoll.cpp @@ -59,11 +59,15 @@ void CRagDoll::CRagDollPlaneConstraint::Update() { } 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_24_prevMovingSlowly(false) +, x68_25_over(false) +, x68_26_primed(false) +, 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; diff --git a/Runtime/Character/CRagDoll.hpp b/Runtime/Character/CRagDoll.hpp index 678861df7..3f383e68b 100644 --- a/Runtime/Character/CRagDoll.hpp +++ b/Runtime/Character/CRagDoll.hpp @@ -94,17 +94,12 @@ protected: 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; - }; + 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; 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); diff --git a/Runtime/Character/CSequenceHelper.cpp b/Runtime/Character/CSequenceHelper.cpp index 71325fa09..85adad75e 100644 --- a/Runtime/Character/CSequenceHelper.cpp +++ b/Runtime/Character/CSequenceHelper.cpp @@ -1,5 +1,7 @@ #include "Runtime/Character/CSequenceHelper.hpp" +#include + #include "Runtime/Character/CAnimSysContext.hpp" #include "Runtime/Character/CBoolPOINode.hpp" #include "Runtime/Character/CInt32POINode.hpp" @@ -45,37 +47,41 @@ CSequenceFundamentals CSequenceHelper::ComputeSequenceFundamentals() { if (x10_treeNodes.size() > 0) { std::shared_ptr node = CAnimTreeNode::Cast(x10_treeNodes[0]->Clone()); for (size_t i = 0; i < x10_treeNodes.size(); ++i) { - CBoolPOINode boolNodeArr[64]; - u32 numBools = node->GetBoolPOIList(CCharAnimTime::Infinity(), boolNodeArr, 64, 0, 0); + std::array boolNodeArr; + const size_t numBools = + node->GetBoolPOIList(CCharAnimTime::Infinity(), boolNodeArr.data(), boolNodeArr.size(), 0, 0); boolNodes.reserve(boolNodes.size() + numBools); - for (u32 j = 0; j < numBools; ++j) { + for (size_t 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); + std::array int32NodeArr; + const size_t numInt32s = + node->GetInt32POIList(CCharAnimTime::Infinity(), int32NodeArr.data(), int32NodeArr.size(), 0, 0); int32Nodes.reserve(int32Nodes.size() + numInt32s); - for (u32 j = 0; j < numInt32s; ++j) { + for (size_t 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); + std::array particleNodeArr; + const size_t numParticles = + node->GetParticlePOIList(CCharAnimTime::Infinity(), particleNodeArr.data(), particleNodeArr.size(), 0, 0); particleNodes.reserve(particleNodes.size() + numParticles); - for (u32 j = 0; j < numParticles; ++j) { + for (size_t 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); + std::array soundNodeArr; + const size_t numSounds = + node->GetSoundPOIList(CCharAnimTime::Infinity(), soundNodeArr.data(), soundNodeArr.size(), 0, 0); soundNodes.reserve(soundNodes.size() + numSounds); - for (u32 j = 0; j < numSounds; ++j) { + for (size_t j = 0; j < numSounds; ++j) { CSoundPOINode& n = soundNodeArr[j]; n.SetTime(n.GetTime() + duration); soundNodes.push_back(n); diff --git a/Runtime/Character/CTransitionDatabaseGame.cpp b/Runtime/Character/CTransitionDatabaseGame.cpp index c29369ce4..37a09bbdc 100644 --- a/Runtime/Character/CTransitionDatabaseGame.cpp +++ b/Runtime/Character/CTransitionDatabaseGame.cpp @@ -27,14 +27,18 @@ CTransitionDatabaseGame::CTransitionDatabaseGame(const std::vector& } const std::shared_ptr& CTransitionDatabaseGame::GetMetaTrans(u32 a, u32 b) const { - auto it = rstl::binary_find(x14_transitions.cbegin(), x14_transitions.cend(), std::make_pair(a, b), - [](const std::pair, std::shared_ptr>& p) { return p.first; }); - if (it != x14_transitions.cend()) + const auto it = rstl::binary_find(x14_transitions.cbegin(), x14_transitions.cend(), std::make_pair(a, b), + [](const auto& p) { return p.first; }); + if (it != x14_transitions.cend()) { return it->second; - auto it2 = rstl::binary_find(x24_halfTransitions.cbegin(), x24_halfTransitions.cend(), b, - [](const std::pair>& p) { return p.first; }); - if (it2 != x24_halfTransitions.cend()) + } + + const auto it2 = rstl::binary_find(x24_halfTransitions.cbegin(), x24_halfTransitions.cend(), b, + [](const auto& p) { return p.first; }); + if (it2 != x24_halfTransitions.cend()) { return it2->second; + } + return x10_defaultTrans; } diff --git a/Runtime/Character/IAnimReader.cpp b/Runtime/Character/IAnimReader.cpp index 4a4264343..fcb5f8009 100644 --- a/Runtime/Character/IAnimReader.cpp +++ b/Runtime/Character/IAnimReader.cpp @@ -22,31 +22,35 @@ SAdvancementResults IAnimReader::VGetAdvancementResults(const CCharAnimTime& a, return ret; } -u32 IAnimReader::GetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, - u32 unk) const { - if (time.GreaterThanZero()) +size_t IAnimReader::GetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, size_t 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::GetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, +size_t IAnimReader::GetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, size_t iterator, u32 unk) const { - if (time.GreaterThanZero()) - return VGetParticlePOIList(time, listOut, capacity, iterator, unk); + if (time.GreaterThanZero()) { + return VGetInt32POIList(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()) +size_t IAnimReader::GetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, + size_t iterator, u32 unk) const { + if (time.GreaterThanZero()) { + return VGetParticlePOIList(time, listOut, capacity, iterator, unk); + } + return 0; +} + +size_t IAnimReader::GetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, size_t iterator, + u32 unk) const { + if (time.GreaterThanZero()) { return VGetSoundPOIList(time, listOut, capacity, iterator, unk); + } return 0; } diff --git a/Runtime/Character/IAnimReader.hpp b/Runtime/Character/IAnimReader.hpp index 59f7e1df9..eb005e741 100644 --- a/Runtime/Character/IAnimReader.hpp +++ b/Runtime/Character/IAnimReader.hpp @@ -114,14 +114,14 @@ public: 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, + virtual size_t VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, size_t iterator, + u32) const = 0; + virtual size_t VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, size_t iterator, + u32) const = 0; + virtual size_t VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, size_t iterator, + u32) const = 0; + virtual size_t VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, size_t iterator, u32) const = 0; - virtual u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, - u32) const = 0; virtual bool VGetBoolPOIState(std::string_view name) const = 0; virtual s32 VGetInt32POIState(std::string_view name) const = 0; virtual CParticleData::EParentedMode VGetParticlePOIState(std::string_view name) const = 0; @@ -133,10 +133,13 @@ public: 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; + size_t GetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, size_t capacity, size_t iterator, u32) const; + size_t GetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, size_t capacity, size_t iterator, + u32) const; + size_t GetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, size_t capacity, size_t iterator, + u32) const; + size_t GetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, size_t capacity, size_t iterator, + u32) const; std::optional> Simplified() { return VSimplified(); } diff --git a/Runtime/Character/IMetaAnim.cpp b/Runtime/Character/IMetaAnim.cpp index 22c3715a1..58a350985 100644 --- a/Runtime/Character/IMetaAnim.cpp +++ b/Runtime/Character/IMetaAnim.cpp @@ -1,5 +1,7 @@ #include "Runtime/Character/IMetaAnim.hpp" +#include + #include "Runtime/Character/CAnimTreeNode.hpp" #include "Runtime/Character/CBoolPOINode.hpp" #include "Runtime/Character/CCharAnimTime.hpp" @@ -29,17 +31,19 @@ void IMetaAnim::AdvanceAnim(IAnimReader& anim, const CCharAnimTime& dt) { } CCharAnimTime IMetaAnim::GetTime(const CPreAdvanceIndicator& ind, const IAnimReader& anim) { - if (ind.IsTime()) + if (ind.IsTime()) { return ind.GetTime(); + } - CBoolPOINode nodes[64]; - CCharAnimTime rem = anim.VGetTimeRemaining(); - u32 count = anim.VGetBoolPOIList(rem, nodes, 64, 0, 0); + std::array nodes; + const CCharAnimTime rem = anim.VGetTimeRemaining(); + const size_t count = anim.VGetBoolPOIList(rem, nodes.data(), nodes.size(), 0, 0); const char* cmpStr = ind.GetString(); - for (u32 i = 0; i < count; ++i) { - CBoolPOINode& node = nodes[i]; - if (node.GetString() != cmpStr || !node.GetValue()) + for (size_t i = 0; i < count; ++i) { + const CBoolPOINode& node = nodes[i]; + if (node.GetString() != cmpStr || !node.GetValue()) { continue; + } return node.GetTime(); } diff --git a/Runtime/Collision/CAreaOctTree.cpp b/Runtime/Collision/CAreaOctTree.cpp index 0b40613aa..3e8fada5b 100644 --- a/Runtime/Collision/CAreaOctTree.cpp +++ b/Runtime/Collision/CAreaOctTree.cpp @@ -52,18 +52,39 @@ static bool BoxLineTest(const zeus::CAABox& aabb, const zeus::CLine& line, float return lT <= hT; } -static const int SomeIndexA[] = {1, 2, 4}; +constexpr std::array SomeIndexA{1, 2, 4}; -static const int SomeIndexB[] = {1, 2, 0}; +constexpr std::array 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}}; +constexpr std::array, 8> SomeIndexC{{ + {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}}}; +constexpr std::array>, 16> SubdivIndex{{ + {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 { @@ -149,7 +170,7 @@ bool CAreaOctTree::Node::LineTestInternal(const zeus::CLine& line, const CMateri int r28 = 0; int r25 = 0; int r26 = 0; - for (int i = 0; i < 3; ++i) { + for (size_t i = 0; i < 3; ++i) { if (r6[i] >= center[i]) r28 |= SomeIndexA[i]; if (r7[i] >= center[i]) diff --git a/Runtime/Collision/CCollisionActorManager.cpp b/Runtime/Collision/CCollisionActorManager.cpp index 963546c4e..81b8b6d35 100644 --- a/Runtime/Collision/CCollisionActorManager.cpp +++ b/Runtime/Collision/CCollisionActorManager.cpp @@ -122,12 +122,12 @@ CCollisionActorManager::CCollisionActorManager(CStateManager& mgr, TUniqueId own } } -void CCollisionActorManager::Destroy(CStateManager& mgr) const { +void CCollisionActorManager::Destroy(CStateManager& mgr) { for (const CJointCollisionDescription& desc : x0_jointDescriptions) { mgr.FreeScriptObject(desc.GetCollisionActorId()); } - const_cast(*this).x13_destroyed = true; + x13_destroyed = true; } void CCollisionActorManager::SetActive(CStateManager& mgr, bool active) { diff --git a/Runtime/Collision/CCollisionActorManager.hpp b/Runtime/Collision/CCollisionActorManager.hpp index 5e78946ae..158632851 100644 --- a/Runtime/Collision/CCollisionActorManager.hpp +++ b/Runtime/Collision/CCollisionActorManager.hpp @@ -30,8 +30,8 @@ public: 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 Update(float dt, CStateManager& mgr, EUpdateOptions opts); + void Destroy(CStateManager& mgr); void SetActive(CStateManager& mgr, bool active); bool GetActive() const { return x12_active; } void AddMaterial(CStateManager& mgr, const CMaterialList& list); diff --git a/Runtime/Collision/CMaterialFilter.cpp b/Runtime/Collision/CMaterialFilter.cpp index 813662ca4..7a37f3bed 100644 --- a/Runtime/Collision/CMaterialFilter.cpp +++ b/Runtime/Collision/CMaterialFilter.cpp @@ -1,6 +1,5 @@ #include "Runtime/Collision/CMaterialFilter.hpp" namespace urde { -const CMaterialFilter CMaterialFilter::skPassEverything({0x00000000FFFFFFFF}, {0}, - CMaterialFilter::EFilterType::Always); +constexpr CMaterialFilter CMaterialFilter::skPassEverything({0x00000000FFFFFFFF}, {0}, EFilterType::Always); } // namespace urde diff --git a/Runtime/Collision/CMetroidAreaCollider.hpp b/Runtime/Collision/CMetroidAreaCollider.hpp index 7f34f557c..97a0a9e6d 100644 --- a/Runtime/Collision/CMetroidAreaCollider.hpp +++ b/Runtime/Collision/CMetroidAreaCollider.hpp @@ -173,16 +173,12 @@ public: 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; - }; + bool x1b40_24_leafOverflow : 1; + bool x1b40_25_cacheOverflow : 1; public: - explicit CAreaCollisionCache(const zeus::CAABox& aabb) : x0_aabb(aabb) {} + explicit CAreaCollisionCache(const zeus::CAABox& aabb) + : x0_aabb(aabb), x1b40_24_leafOverflow(false), x1b40_25_cacheOverflow(false) {} void ClearCache(); const zeus::CAABox& GetCacheBounds() const { return x0_aabb; } void SetCacheBounds(const zeus::CAABox& aabb) { x0_aabb = aabb; } diff --git a/Runtime/GameGlobalObjects.hpp b/Runtime/GameGlobalObjects.hpp index 117796887..5ddcf4c4b 100644 --- a/Runtime/GameGlobalObjects.hpp +++ b/Runtime/GameGlobalObjects.hpp @@ -57,11 +57,9 @@ extern class CStateManager* g_StateManager; #if USE_DOWNCAST_TWEAKS using ITweakGame = DataSpec::DNAMP1::CTweakGame; using ITweakPlayer = DataSpec::DNAMP1::CTweakPlayer; -using ITweakPlayerRes = DataSpec::DNAMP1::CTweakPlayerRes; using ITweakPlayerControl = DataSpec::DNAMP1::CTweakPlayerControl; using ITweakPlayerGun = DataSpec::DNAMP1::CTweakPlayerGun; using ITweakGunRes = DataSpec::DNAMP1::CTweakGunRes; -using ITweakTargeting = DataSpec::DNAMP1::CTweakTargeting; using ITweakAutoMapper = DataSpec::DNAMP1::CTweakAutoMapper; using ITweakGui = DataSpec::DNAMP1::CTweakGui; using ITweakSlideShow = DataSpec::DNAMP1::CTweakSlideShow; @@ -71,11 +69,9 @@ using ITweakGuiColors = DataSpec::DNAMP1::CTweakGuiColors; #else using ITweakGame = DataSpec::ITweakGame; using ITweakPlayer = DataSpec::ITweakPlayer; -using ITweakPlayerRes = DataSpec::ITweakPlayerRes; using ITweakPlayerControl = DataSpec::ITweakPlayerControl; using ITweakPlayerGun = DataSpec::ITweakPlayerGun; using ITweakGunRes = DataSpec::ITweakGunRes; -using ITweakTargeting = DataSpec::ITweakTargeting; using ITweakAutoMapper = DataSpec::ITweakAutoMapper; using ITweakGui = DataSpec::ITweakGui; using ITweakSlideShow = DataSpec::ITweakSlideShow; @@ -83,6 +79,8 @@ using ITweakParticle = DataSpec::ITweakParticle; using ITweakBall = DataSpec::ITweakBall; using ITweakGuiColors = DataSpec::ITweakGuiColors; #endif +using ITweakPlayerRes = DataSpec::ITweakPlayerRes; +using ITweakTargeting = DataSpec::ITweakTargeting; extern ITweakGame* g_tweakGame; extern ITweakPlayer* g_tweakPlayer; diff --git a/Runtime/Graphics/CBooRenderer.cpp b/Runtime/Graphics/CBooRenderer.cpp index 1007d117c..c0c5ebee8 100644 --- a/Runtime/Graphics/CBooRenderer.cpp +++ b/Runtime/Graphics/CBooRenderer.cpp @@ -148,7 +148,7 @@ void Buckets::Sort() { if (bucket.size() < bucket.capacity()) bucket.push_back(&drawable); // else - // Log.report(logvisor::Fatal, fmt("Full bucket!!!")); + // Log.report(logvisor::Fatal, FMT_STRING("Full bucket!!!")); } u16 bucketIdx = u16(sBuckets->size()); @@ -183,7 +183,7 @@ void Buckets::InsertPlaneObject(float closeDist, float farDist, const zeus::CAAB void Buckets::Insert(const zeus::CVector3f& pos, const zeus::CAABox& aabb, EDrawableType dtype, void* data, const zeus::CPlane& plane, u16 extraSort) { if (sData->size() == sData->capacity()) { - Log.report(logvisor::Fatal, fmt("Rendering buckets filled to capacity")); + Log.report(logvisor::Fatal, FMT_STRING("Rendering buckets filled to capacity")); return; } @@ -681,7 +681,16 @@ void CBooRenderer::LoadBallFade() { } CBooRenderer::CBooRenderer(IObjectStore& store, IFactory& resFac) -: x8_factory(resFac), xc_store(store), x2a8_thermalRand(20) { +: x8_factory(resFac), xc_store(store), x2a8_thermalRand(20) +, x318_24_refectionDirty(false) +, x318_25_drawWireframe(false) +, x318_26_requestRGBA6(false) +, x318_27_currentRGBA6(false) +, x318_28_disableFog(false) +, x318_29_thermalVisor(false) +, x318_30_inAreaDraw(false) +, x318_31_persistRGBA6(false) +, m_thermalHotPass(false) { g_Renderer = this; xee_24_ = true; @@ -1397,9 +1406,9 @@ void CBooRenderer::DrawOverlappingWorldModelShadows(int alphaVal, const std::vec return; flags.x4_color.r() = alphaVal / 255.f; - const CBooModel& model = *item.x10_models[wordModel + j]; - const_cast(model).UpdateUniformData(flags, nullptr, nullptr, 2); - const_cast(model).VerifyCurrentShader(0); + CBooModel& model = *item.x10_models[wordModel + j]; + model.UpdateUniformData(flags, nullptr, nullptr, 2); + model.VerifyCurrentShader(0); for (const CBooSurface* surf = model.x38_firstUnsortedSurface; surf; surf = surf->m_next) if (surf->GetBounds().intersects(aabb)) model.DrawSurface(*surf, flags); diff --git a/Runtime/Graphics/CBooRenderer.hpp b/Runtime/Graphics/CBooRenderer.hpp index 7c3016297..81e4e47cb 100644 --- a/Runtime/Graphics/CBooRenderer.hpp +++ b/Runtime/Graphics/CBooRenderer.hpp @@ -152,20 +152,15 @@ class CBooRenderer final : public IRenderer { // 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; - bool m_thermalHotPass : 1; - }; - u16 dummy = 0; - }; + 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; + bool m_thermalHotPass : 1; void GenerateFogVolumeRampTex(boo::IGraphicsDataFactory::Context& ctx); void GenerateSphereRampTex(boo::IGraphicsDataFactory::Context& ctx); diff --git a/Runtime/Graphics/CGraphics.cpp b/Runtime/Graphics/CGraphics.cpp index 48171d31c..21202380a 100644 --- a/Runtime/Graphics/CGraphics.cpp +++ b/Runtime/Graphics/CGraphics.cpp @@ -35,7 +35,7 @@ SViewport g_Viewport = { }; u32 CGraphics::g_FrameCounter = 0; -const std::array CGraphics::skCubeBasisMats{{ +constexpr std::array CGraphics::skCubeBasisMats{{ /* Right */ {0.f, 1.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, -1.f}, /* Left */ diff --git a/Runtime/Graphics/CLineRenderer.cpp b/Runtime/Graphics/CLineRenderer.cpp index d8b4b3472..340377476 100644 --- a/Runtime/Graphics/CLineRenderer.cpp +++ b/Runtime/Graphics/CLineRenderer.cpp @@ -24,7 +24,7 @@ CLineRenderer::CLineRenderer(boo::IGraphicsDataFactory::Context& ctx, EPrimitive const boo::ObjToken& texture, bool additive, bool zTest, bool zGEqual) : m_mode(mode), m_maxVerts(maxVerts) { if (maxVerts < 2) { - LineRendererLog.report(logvisor::Fatal, fmt(_SYS_STR("maxVerts < 2, maxVerts = {}")), maxVerts); + LineRendererLog.report(logvisor::Fatal, FMT_STRING(_SYS_STR("maxVerts < 2, maxVerts = {}")), maxVerts); return; } m_textured = bool(texture); @@ -55,7 +55,7 @@ CLineRenderer::CLineRenderer(EPrimitiveMode mode, u32 maxVerts, const boo::ObjTo bool additive, bool zTest, bool zGEqual) : m_mode(mode), m_maxVerts(maxVerts) { if (maxVerts < 2) { - LineRendererLog.report(logvisor::Fatal, fmt(_SYS_STR("maxVerts < 2, maxVerts = {}")), maxVerts); + LineRendererLog.report(logvisor::Fatal, FMT_STRING(_SYS_STR("maxVerts < 2, maxVerts = {}")), maxVerts); return; } m_textured = bool(texture); diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index 9460599f3..b6ef2e16f 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -37,12 +37,12 @@ struct CModelFlags { zeus::CColor addColor = zeus::skClear; zeus::CAABox mbShadowBox; - CModelFlags() = default; - CModelFlags(u8 blendMode, u8 shadIdx, u16 flags, const zeus::CColor& col) + constexpr CModelFlags() = default; + constexpr 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 */ - m_noZWrite = !(x2_flags & 0x2); - m_depthGreater = (x2_flags & 0x8); + m_noZWrite = (x2_flags & 0x2) == 0; + m_depthGreater = (x2_flags & 0x8) != 0; } /* Flags diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index bb30f753e..983274ef1 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -268,7 +268,7 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) { } if (m_instances.size() >= 512) { - Log.report(logvisor::Fatal, fmt("Model buffer overflow")); + Log.report(logvisor::Fatal, FMT_STRING("Model buffer overflow")); } ModelInstance& newInst = m_instances.emplace_back(); @@ -309,29 +309,37 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) { 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()}; + const std::array, 4> bufs{ + geomUniformBuf.get(), + geomUniformBuf.get(), + newInst.m_uniformBuffer.get(), + newInst.m_uniformBuffer.get(), + }; /* Binding for each surface */ newInst.m_shaderDataBindings.reserve(x0_surfaces->size()); - size_t thisOffs[4]; - size_t thisSizes[4]; + std::array thisOffs; + std::array thisSizes; - static const boo::PipelineStage stages[4] = {boo::PipelineStage::Vertex, boo::PipelineStage::Vertex, - boo::PipelineStage::Fragment, boo::PipelineStage::Vertex}; + static constexpr std::array stages{ + 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[12] = {g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), - g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), - g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), - g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), - g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get()}; + std::array, 12> texs{ + g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), + g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), + g_Renderer->m_whiteTexture.get(), g_Renderer->m_clearTexture.get(), g_Renderer->x220_sphereRamp.get(), + g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), + }; if (!g_DummyTextures) { for (const auto& ch : mat.chunks) { if (auto pass = ch.get_if()) { @@ -401,9 +409,9 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) { else texs[11] = g_Renderer->x220_sphereRamp.get(); } - extendeds.push_back(ctx.newShaderDataBinding(pipeline, newInst.GetBooVBO(*this, ctx), nullptr, - m_staticIbo.get(), 4, bufs, stages, thisOffs, thisSizes, 12, texs, - nullptr, nullptr)); + extendeds.push_back(ctx.newShaderDataBinding( + pipeline, newInst.GetBooVBO(*this, ctx), nullptr, m_staticIbo.get(), bufs.size(), bufs.data(), + stages.data(), thisOffs.data(), thisSizes.data(), texs.size(), texs.data(), nullptr, nullptr)); idx = EExtendedShader(size_t(idx) + 1); } } @@ -640,7 +648,7 @@ static EExtendedShader ResolveExtendedShader(const MaterialSet::Material& data, void CBooModel::DrawSurface(const CBooSurface& surf, const CModelFlags& flags) const { // if (m_uniUpdateCount == 0) - // Log.report(logvisor::Fatal, fmt("UpdateUniformData() not called")); + // Log.report(logvisor::Fatal, FMT_STRING("UpdateUniformData() not called")); if (m_uniUpdateCount == 0 || m_uniUpdateCount > m_instances.size()) return; const ModelInstance& inst = m_instances[m_uniUpdateCount - 1]; @@ -1175,7 +1183,7 @@ CModel::CModel(std::unique_ptr&& in, u32 /* dataLen */, IObjectStore* stor 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, fmt("invalid CMDL for loading with boo")); + Log.report(logvisor::Fatal, FMT_STRING("invalid CMDL for loading with boo")); u32 secCount = hecl::SBig(*reinterpret_cast(data.get() + 0x24)); u32 matSetCount = hecl::SBig(*reinterpret_cast(data.get() + 0x28)); diff --git a/Runtime/Graphics/CMoviePlayer.cpp b/Runtime/Graphics/CMoviePlayer.cpp index f4af28744..6771971e0 100644 --- a/Runtime/Graphics/CMoviePlayer.cpp +++ b/Runtime/Graphics/CMoviePlayer.cpp @@ -140,10 +140,12 @@ u32 CMoviePlayer::THPAudioDecode(s16* buffer, const u8* audioFrame, bool stereo) } 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) +, xf4_25_hasAudio(false) +, xf4_26_fieldFlip(false) +, m_deinterlace(deinterlace) { /* Read THP header information */ u8 buf[64]; SyncRead(buf, 64); diff --git a/Runtime/Graphics/CMoviePlayer.hpp b/Runtime/Graphics/CMoviePlayer.hpp index f32d47fe1..7d74267cf 100644 --- a/Runtime/Graphics/CMoviePlayer.hpp +++ b/Runtime/Graphics/CMoviePlayer.hpp @@ -99,21 +99,15 @@ private: float xe8_curSeconds = 0.f; float xec_preLoadSeconds; u32 xf0_preLoadFrames = 0; + bool xf4_24_loop : 1; + bool xf4_25_hasAudio : 1; + bool xf4_26_fieldFlip : 1; + bool m_deinterlace : 1; 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; diff --git a/Runtime/Graphics/CRainSplashGenerator.cpp b/Runtime/Graphics/CRainSplashGenerator.cpp index dd91613c3..05f5d750f 100644 --- a/Runtime/Graphics/CRainSplashGenerator.cpp +++ b/Runtime/Graphics/CRainSplashGenerator.cpp @@ -22,7 +22,7 @@ CRainSplashGenerator::CRainSplashGenerator(const zeus::CVector3f& scale, u32 max } BooTrace); } -void CRainSplashGenerator::SSplashLine::Draw(float alpha, float dt, const zeus::CVector3f& pos) const { +void CRainSplashGenerator::SSplashLine::Draw(float alpha, float dt, const zeus::CVector3f& pos) { if (x0_t > 0.f) { float delta = dt * xc_speed; float vt = std::max(0.f, x0_t - delta * x15_length); @@ -39,36 +39,40 @@ void CRainSplashGenerator::SSplashLine::Draw(float alpha, float dt, const zeus:: } } -void CRainSplashGenerator::SRainSplash::Draw(float alpha, float dt, const zeus::CVector3f& pos) const { - for (const SSplashLine& line : x0_lines) +void CRainSplashGenerator::SRainSplash::Draw(float alpha, float dt, const zeus::CVector3f& pos) { + for (SSplashLine& line : x0_lines) { line.Draw(alpha, dt, pos); + } } -void CRainSplashGenerator::DoDraw(const zeus::CTransform& xf) const { +void CRainSplashGenerator::DoDraw(const zeus::CTransform& xf) { SCOPED_GRAPHICS_DEBUG_GROUP("CRainSplashGenerator::DoDraw", zeus::skYellow); CGraphics::SetModelMatrix(xf); if (x40_queueSize > 0) { if (x38_queueTail <= x3c_queueHead) { for (size_t i = x3c_queueHead; i < x0_rainSplashes.size(); ++i) { - const SRainSplash& splash = x0_rainSplashes[i]; + SRainSplash& splash = x0_rainSplashes[i]; splash.Draw(x30_alpha, x28_dt, splash.x64_pos); } for (size_t i = 0; i < x38_queueTail; ++i) { - const SRainSplash& splash = x0_rainSplashes[i]; + SRainSplash& splash = x0_rainSplashes[i]; splash.Draw(x30_alpha, x28_dt, splash.x64_pos); } } else { for (size_t i = x3c_queueHead; i < x38_queueTail; ++i) { - const SRainSplash& splash = x0_rainSplashes[i]; + 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) { + if (!x48_25_raining) { + return; + } + + DoDraw(xf); } CRainSplashGenerator::SSplashLine::SSplashLine(boo::IGraphicsDataFactory::Context& ctx) diff --git a/Runtime/Graphics/CRainSplashGenerator.hpp b/Runtime/Graphics/CRainSplashGenerator.hpp index 3f2ade690..5f2f9e514 100644 --- a/Runtime/Graphics/CRainSplashGenerator.hpp +++ b/Runtime/Graphics/CRainSplashGenerator.hpp @@ -23,10 +23,10 @@ class CRainSplashGenerator { u8 x14_ = 3; u8 x15_length = 1; bool x16_active = true; // used to be one-bit bitfield - mutable CLineRenderer m_renderer; + 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 Draw(float alpha, float dt, const zeus::CVector3f& pos); void SetActive() { x16_active = true; } }; struct SRainSplash { @@ -40,11 +40,11 @@ class CRainSplashGenerator { 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 Draw(float alpha, float dt, const zeus::CVector3f& pos); void SetPoint(const zeus::CVector3f& pos); }; std::vector x0_rainSplashes; - CRandom16 x10_random = {99}; + CRandom16 x10_random{99}; zeus::CVector3f x14_scale; float x20_generateTimer = 0.0f; float x24_generateInterval = 0.0f; @@ -60,7 +60,7 @@ class CRainSplashGenerator { 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; + void DoDraw(const zeus::CTransform& xf); static u32 GetNextBestPt(u32 pt, const std::vector>& vn, CRandom16& rand, float minZ); void AddPoint(const zeus::CVector3f& pos); @@ -69,7 +69,7 @@ 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; + void Draw(const zeus::CTransform& xf); bool IsRaining() const { return x48_25_raining; } }; diff --git a/Runtime/Graphics/CSimpleShadow.cpp b/Runtime/Graphics/CSimpleShadow.cpp index 7beb2d5b9..8e9f6164c 100644 --- a/Runtime/Graphics/CSimpleShadow.cpp +++ b/Runtime/Graphics/CSimpleShadow.cpp @@ -27,7 +27,7 @@ zeus::CAABox CSimpleShadow::GetBounds() const { {x0_xf.origin.x() + extent, x0_xf.origin.y() + extent, x0_xf.origin.z() + extent}}; } -void CSimpleShadow::Render(const TLockedToken& tex) const { +void CSimpleShadow::Render(const TLockedToken& tex) { if (!x48_24_collision) return; SCOPED_GRAPHICS_DEBUG_GROUP("CSimpleShadow::Render", zeus::skGrey); diff --git a/Runtime/Graphics/CSimpleShadow.hpp b/Runtime/Graphics/CSimpleShadow.hpp index 43f368a70..ca6736f7e 100644 --- a/Runtime/Graphics/CSimpleShadow.hpp +++ b/Runtime/Graphics/CSimpleShadow.hpp @@ -22,7 +22,7 @@ class CSimpleShadow { bool x48_24_collision : 1; bool x48_25_alwaysCalculateRadius : 1; bool x48_26_radiusCalculated : 1; - mutable std::optional m_filter; + std::optional m_filter; public: CSimpleShadow(float scale, float userAlpha, float maxObjHeight, float displacement); @@ -33,7 +33,7 @@ public: 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 Render(const TLockedToken& tex); 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 709a12a22..757859689 100644 --- a/Runtime/Graphics/CSkinnedModel.cpp +++ b/Runtime/Graphics/CSkinnedModel.cpp @@ -12,13 +12,13 @@ CSkinnedModel::CSkinnedModel(TLockedToken model, TLockedToken layoutInfo, int shaderIdx, int drawInsts) : x4_model(std::move(model)), x10_skinRules(std::move(skinRules)), x1c_layoutInfo(std::move(layoutInfo)) { if (!x4_model) { - Log.report(logvisor::Fatal, fmt("bad model token provided to CSkinnedModel")); + Log.report(logvisor::Fatal, FMT_STRING("bad model token provided to CSkinnedModel")); } if (!x10_skinRules) { - Log.report(logvisor::Fatal, fmt("bad skin token provided to CSkinnedModel")); + Log.report(logvisor::Fatal, FMT_STRING("bad skin token provided to CSkinnedModel")); } if (!x1c_layoutInfo) { - Log.report(logvisor::Fatal, fmt("bad character layout token provided to CSkinnedModel")); + Log.report(logvisor::Fatal, FMT_STRING("bad character layout token provided to CSkinnedModel")); } m_modelInst = x4_model->MakeNewInstance(shaderIdx, drawInsts); } diff --git a/Runtime/Graphics/CTextureBoo.cpp b/Runtime/Graphics/CTextureBoo.cpp index 931a497e6..d271c0cad 100644 --- a/Runtime/Graphics/CTextureBoo.cpp +++ b/Runtime/Graphics/CTextureBoo.cpp @@ -552,7 +552,7 @@ 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, fmt("insufficient TXTR length ({}/{})"), length, expectedSize); + Log.report(logvisor::Fatal, FMT_STRING("insufficient TXTR length ({}/{})"), 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, @@ -565,7 +565,7 @@ void CTexture::BuildRGBA8(const void* data, size_t length) { void CTexture::BuildC8(const void* data, size_t length) { size_t texelCount = ComputeMippedTexelCount(); if (texelCount > length) - Log.report(logvisor::Fatal, fmt("insufficient TXTR length ({}/{})"), length, texelCount); + Log.report(logvisor::Fatal, FMT_STRING("insufficient TXTR length ({}/{})"), length, texelCount); CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { uint32_t nentries = hecl::SBig(*reinterpret_cast(data)); @@ -763,7 +763,7 @@ CTexture::CTexture(std::unique_ptr&& in, u32 length, bool otex, const CTex BuildDXT3(owned.get() + 12, length - 12); break; default: - Log.report(logvisor::Fatal, fmt("invalid texture type {} for boo"), int(x0_fmt)); + Log.report(logvisor::Fatal, FMT_STRING("invalid texture type {} for boo"), int(x0_fmt)); } if (otex) @@ -775,7 +775,7 @@ 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, fmt("MemoryCard TXTR not loaded with 'otex'")); + Log.report(logvisor::Fatal, FMT_STRING("MemoryCard TXTR not loaded with 'otex'")); size_t texelCount = x4_w * x6_h; std::unique_ptr ret; @@ -851,7 +851,7 @@ std::unique_ptr CTexture::BuildMemoryCardTex(u32& sizeOut, ETexelFormat& f } } } else - Log.report(logvisor::Fatal, fmt("MemoryCard texture may only use RGBA8PC or C8PC format")); + Log.report(logvisor::Fatal, FMT_STRING("MemoryCard texture may only use RGBA8PC or C8PC format")); return ret; } diff --git a/Runtime/Graphics/Shaders/CColoredQuadFilter.cpp b/Runtime/Graphics/Shaders/CColoredQuadFilter.cpp index 0e51076ec..b7a19e217 100644 --- a/Runtime/Graphics/Shaders/CColoredQuadFilter.cpp +++ b/Runtime/Graphics/Shaders/CColoredQuadFilter.cpp @@ -34,7 +34,7 @@ static boo::ObjToken SelectPipeline(EFilterType type) { case EFilterType::Multiply: return s_MultPipeline; default: - return {}; + return s_AlphaPipeline; } } @@ -115,6 +115,6 @@ void CWideScreenFilter::SetViewportToFull() { CGraphics::g_BooMainCommandQueue->setViewport(rect); } -const zeus::CRectangle CColoredQuadFilter::DefaultRect = {0.f, 0.f, 1.f, 1.f}; +constexpr zeus::CRectangle CColoredQuadFilter::DefaultRect{0.f, 0.f, 1.f, 1.f}; } // namespace urde diff --git a/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp b/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp index 02e56af04..8d83479e6 100644 --- a/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp +++ b/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp @@ -96,7 +96,7 @@ void CParticleSwooshShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::C }; const std::array, 1> uniforms{gen.m_uniformBuf.get()}; - for (size_t i = 0; i < std::size(gen.m_dataBind); ++i) { + for (size_t i = 0; i < gen.m_dataBind.size(); ++i) { gen.m_dataBind[i] = ctx.newShaderDataBinding((*pipeline)[i], gen.m_vertBuf.get(), nullptr, nullptr, uniforms.size(), uniforms.data(), nullptr, texr ? 1 : 0, textures.data(), nullptr, nullptr); diff --git a/Runtime/Graphics/Shaders/CTexturedQuadFilter.cpp b/Runtime/Graphics/Shaders/CTexturedQuadFilter.cpp index a9a1be609..a9a9f78e3 100644 --- a/Runtime/Graphics/Shaders/CTexturedQuadFilter.cpp +++ b/Runtime/Graphics/Shaders/CTexturedQuadFilter.cpp @@ -322,7 +322,7 @@ void CTexturedQuadFilter::DrawFilter(EFilterShape shape, const zeus::CColor& col } } -const zeus::CRectangle CTexturedQuadFilter::DefaultRect = {0.f, 0.f, 1.f, 1.f}; +constexpr zeus::CRectangle CTexturedQuadFilter::DefaultRect{0.f, 0.f, 1.f, 1.f}; CTexturedQuadFilterAlpha::CTexturedQuadFilterAlpha(EFilterType type, const boo::ObjToken& tex) : CTexturedQuadFilter(tex) { diff --git a/Runtime/GuiSys/CAuiEnergyBarT01.cpp b/Runtime/GuiSys/CAuiEnergyBarT01.cpp index 4da50045c..d30345c86 100644 --- a/Runtime/GuiSys/CAuiEnergyBarT01.cpp +++ b/Runtime/GuiSys/CAuiEnergyBarT01.cpp @@ -57,7 +57,7 @@ void CAuiEnergyBarT01::Draw(const CGuiWidgetDrawParms& drawParms) { if (!xbc_tex || !xbc_tex.IsLoaded() || !xd8_coordFunc) { return; } - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CAuiEnergyBarT01::Draw {}"), m_name).c_str(), zeus::skCyan); + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CAuiEnergyBarT01::Draw {}"), m_name).c_str(), zeus::skCyan); CGraphics::SetModelMatrix(x34_worldXF); m_energyBarShader.updateModelMatrix(); diff --git a/Runtime/GuiSys/CAuiImagePane.cpp b/Runtime/GuiSys/CAuiImagePane.cpp index 996e1ad4f..d8a033087 100644 --- a/Runtime/GuiSys/CAuiImagePane.cpp +++ b/Runtime/GuiSys/CAuiImagePane.cpp @@ -106,7 +106,7 @@ void CAuiImagePane::Draw(const CGuiWidgetDrawParms& params) { if (!GetIsVisible() || !xb8_tex0Tok.IsLoaded()) { return; } - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CAuiImagePane::Draw {}"), m_name).c_str(), zeus::skCyan); + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CAuiImagePane::Draw {}"), m_name).c_str(), zeus::skCyan); GetIsFinishedLoadingWidgetSpecific(); if (!m_filters || m_filters->m_texId != xb8_tex0Tok.GetObjectTag()->id) { m_filters.emplace(xb8_tex0Tok); diff --git a/Runtime/GuiSys/CCompoundTargetReticle.cpp b/Runtime/GuiSys/CCompoundTargetReticle.cpp index 956a653fd..684a56455 100644 --- a/Runtime/GuiSys/CCompoundTargetReticle.cpp +++ b/Runtime/GuiSys/CCompoundTargetReticle.cpp @@ -36,8 +36,8 @@ float offshoot_func(float f1, float f2, float f3) { return (f1 * 0.5f) + std::si float calculate_premultiplied_overshoot_offset(float f1) { return 2.f * (M_PIF - std::asin(1.f / f1)); } } // Anonymous namespace -const CTargetReticleRenderState CTargetReticleRenderState::skZeroRenderState(kInvalidUniqueId, 1.f, - zeus::skZero3f, 0.f, 1.f, true); +constexpr CTargetReticleRenderState CTargetReticleRenderState::skZeroRenderState(kInvalidUniqueId, 1.f, zeus::skZero3f, + 0.f, 1.f, true); CCompoundTargetReticle::SOuterItemInfo::SOuterItemInfo(std::string_view res) : x0_model(g_SimplePool->GetObj(res)) {} @@ -64,17 +64,19 @@ CCompoundTargetReticle::CCompoundTargetReticle(const CStateManager& mgr) , x100_laggingTargetPos(CalculateOrbitZoneReticlePosition(mgr, true)) , x208_lockonTimer(g_tweakTargeting->GetLockonDuration()) { xe0_outerBeamIconSquares.reserve(9); - for (u32 i = 0; i < 9; ++i) - xe0_outerBeamIconSquares.emplace_back(fmt::format(fmt("{}{}"), skOuterBeamIconSquareNameBase, i)); + for (size_t i = 0; i < xe0_outerBeamIconSquares.capacity(); ++i) { + xe0_outerBeamIconSquares.emplace_back(fmt::format(FMT_STRING("{}{}"), skOuterBeamIconSquareNameBase, i)); + } x34_crosshairs.Lock(); } CCompoundTargetReticle::SScanReticuleRenderer::SScanReticuleRenderer() { CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { - for (int i = 0; i < 2; ++i) { + for (size_t i = 0; i < m_lineRenderers.size(); ++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); + for (auto& stripRenderer : m_stripRenderers[i]) { + stripRenderer.emplace(ctx, CLineRenderer::EPrimitiveMode::LineStrip, 4, nullptr, true, true); + } } return true; } BooTrace); @@ -95,12 +97,13 @@ CCompoundTargetReticle::EReticleState CCompoundTargetReticle::GetDesiredReticleS } void CCompoundTargetReticle::Update(float dt, const CStateManager& mgr) { - float angle = x10_laggingOrientation.angleFrom(x0_leadingOrientation).asDegrees(); + const float angle = x10_laggingOrientation.angleFrom(x0_leadingOrientation).asDegrees(); float t; - if (angle < 0.1f || angle > 45.f) + if (angle < 0.1f || angle > 45.f) { t = 1.f; - else + } 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); @@ -108,17 +111,17 @@ void CCompoundTargetReticle::Update(float dt, const CStateManager& mgr) { UpdateCurrLockOnGroup(dt, mgr); UpdateNextLockOnGroup(dt, mgr); UpdateOrbitZoneGroup(dt, mgr); - EReticleState desiredState = GetDesiredReticleState(mgr); + const 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; + bool combat = false; + bool scan = false; + bool xray = false; + bool thermal = false; switch (x24_nextState) { case EReticleState::Combat: combat = true; @@ -135,90 +138,110 @@ void CCompoundTargetReticle::Update(float dt, const CStateManager& mgr) { default: break; } - if (combat) + if (combat) { x40_seeker.Lock(); - else + } else { x40_seeker.Unlock(); - if (combat) + } + if (combat) { x4c_lockConfirm.Lock(); - else + } else { x4c_lockConfirm.Unlock(); - if (combat) + } + if (combat) { x58_targetFlower.Lock(); - else + } else { x58_targetFlower.Unlock(); - if (combat) + } + if (combat) { x64_missileBracket.Lock(); - else + } else { x64_missileBracket.Unlock(); - if (combat) + } + if (combat) { x70_innerBeamIcon.Lock(); - else + } else { x70_innerBeamIcon.Unlock(); - if (combat) + } + if (combat) { x7c_lockFire.Lock(); - else + } else { x7c_lockFire.Unlock(); - if (combat) + } + if (combat) { x88_lockDagger.Lock(); - else + } else { x88_lockDagger.Unlock(); - if (combat) + } + if (combat) { xa0_chargeTickFirst.Lock(); - else + } else { xa0_chargeTickFirst.Unlock(); - if (xray) + } + if (xray) { xac_xrayRetRing.Lock(); - else + } else { xac_xrayRetRing.Unlock(); - if (thermal) + } + if (thermal) { xb8_thermalReticle.Lock(); - else + } else { xb8_thermalReticle.Unlock(); - if (combat) + } + if (combat) { xc4_chargeGauge.x0_model.Lock(); - else + } else { xc4_chargeGauge.x0_model.Unlock(); - if (!scan) + } + if (!scan) { x94_grapple.Lock(); - else + } else { x94_grapple.Unlock(); + } for (SOuterItemInfo& info : xe0_outerBeamIconSquares) { - if (combat) + if (combat) { info.x0_model.Lock(); - else + } else { info.x0_model.Unlock(); + } } } - CPlayerGun* gun = mgr.GetPlayer().GetPlayerGun(); - bool fullyCharged = (gun->IsCharging() ? gun->GetChargeBeamFactor() : 0.f) >= 1.f; - if (fullyCharged != x21a_fullyCharged) + + const CPlayerGun* gun = mgr.GetPlayer().GetPlayerGun(); + const bool fullyCharged = (gun->IsCharging() ? gun->GetChargeBeamFactor() : 0.f) >= 1.f; + if (fullyCharged != x21a_fullyCharged) { x21a_fullyCharged = fullyCharged; - if (x21a_fullyCharged) + } + if (x21a_fullyCharged) { x214_fullChargeFadeTimer = std::min(dt / g_tweakTargeting->GetFullChargeFadeDuration() + x214_fullChargeFadeTimer, g_tweakTargeting->GetFullChargeFadeDuration()); - else + } else { x214_fullChargeFadeTimer = std::max(x214_fullChargeFadeTimer - dt / g_tweakTargeting->GetFullChargeFadeDuration(), 0.f); - bool missileActive = gun->GetMissleMode() == CPlayerGun::EMissleMode::Active; + } + + const bool missileActive = gun->GetMissleMode() == CPlayerGun::EMissleMode::Active; if (missileActive != x1f4_missileActive) { - if (x1f8_missileBracketTimer != 0.f) + if (x1f8_missileBracketTimer != 0.f) { x1f8_missileBracketTimer = FLT_EPSILON - x1f8_missileBracketTimer; - else + } else { x1f8_missileBracketTimer = FLT_EPSILON; + } x1f4_missileActive = missileActive; } - CPlayerState::EBeamId beam = gun->GetCurrentBeam(); + + const CPlayerState::EBeamId beam = gun->GetCurrentBeam(); if (beam != x200_beam) { x204_chargeGaugeOvershootTimer = g_tweakTargeting->GetChargeGaugeOvershootDuration(); - for (int i = 0; i < 9; ++i) { + for (size_t i = 0; i < xe0_outerBeamIconSquares.size(); ++i) { zeus::CRelAngle baseAngle = g_tweakTargeting->GetOuterBeamSquareAngles(int(beam))[i]; baseAngle.makeRel(); SOuterItemInfo& icon = xe0_outerBeamIconSquares[i]; zeus::CRelAngle offshootAngleDelta = baseAngle.asRadians() - icon.x10_rotAng; - if ((i & 0x1) == 1) + 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; @@ -226,36 +249,43 @@ void CCompoundTargetReticle::Update(float dt, const CStateManager& mgr) { zeus::CRelAngle baseAngle = g_tweakTargeting->GetChargeGaugeAngle(int(beam)); baseAngle.makeRel(); float offshootAngleDelta = baseAngle.asRadians() - xc4_chargeGauge.x10_rotAng; - if ((rand() & 0x1) == 1) + 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) + + if ((gun->GetLastFireButtonStates() & 0x1) != 0) { + if (!x218_beamShot) { x210_lockFireTimer = g_tweakTargeting->GetLockFireDuration(); + } x218_beamShot = true; } else { x218_beamShot = false; } - if (gun->GetLastFireButtonStates() & 0x2) { - if (!x219_missileShot) + + if ((gun->GetLastFireButtonStates() & 0x2) != 0) { + if (!x219_missileShot) { x1fc_missileBracketScaleTimer = g_tweakTargeting->GetMissileBracketScaleDuration(); + } x219_missileShot = true; } else { x219_missileShot = false; } - if (TCastToConstPtr point = mgr.GetObjectById(xf2_nextTargetId)) { + + if (const TCastToConstPtr point = mgr.GetObjectById(xf2_nextTargetId)) { if (point->GetUniqueId() != x1dc_grapplePoint0) { float tmp; - if (point->GetUniqueId() == x1de_grapplePoint1) + if (point->GetUniqueId() == x1de_grapplePoint1) { tmp = std::max(FLT_EPSILON, x1e4_grapplePoint1T); - else + } else { tmp = FLT_EPSILON; + } x1de_grapplePoint1 = x1dc_grapplePoint0; x1e4_grapplePoint1T = x1e0_grapplePoint0T; x1e0_grapplePoint0T = tmp; @@ -267,13 +297,18 @@ void CCompoundTargetReticle::Update(float dt, const CStateManager& mgr) { x1e0_grapplePoint0T = 0.f; x1dc_grapplePoint0 = kInvalidUniqueId; } - if (x1e0_grapplePoint0T > 0.f) + + 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) + if (x1e4_grapplePoint1T == 0.f) { x1de_grapplePoint1 = kInvalidUniqueId; + } } + x1f0_xrayRetAngle = zeus::CRelAngle(zeus::degToRad(g_tweakTargeting->GetXRayRetAngleSpeed() * dt) + x1f0_xrayRetAngle).asRel(); x1ec_seekerAngle = zeus::CRelAngle(zeus::degToRad(g_tweakTargeting->GetSeekerAngleSpeed() * dt) + x1ec_seekerAngle). @@ -283,18 +318,19 @@ void CCompoundTargetReticle::Update(float dt, const CStateManager& mgr) { 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; + const 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) + if (t == 1.f) { out.x0_target = b.x0_target; - else if (t == 0.f) + } else if (t == 0.f) { out.x0_target = a.x0_target; - else + } else { out.x0_target = kInvalidUniqueId; + } } static bool IsDamageOrbit(CPlayer::EPlayerOrbitRequest req) { @@ -311,13 +347,14 @@ static bool IsDamageOrbit(CPlayer::EPlayerOrbitRequest req) { } void CCompoundTargetReticle::UpdateCurrLockOnGroup(float dt, const CStateManager& mgr) { - TUniqueId targetId = mgr.GetPlayer().GetOrbitTargetId(); + const TUniqueId targetId = mgr.GetPlayer().GetOrbitTargetId(); if (targetId != xf0_targetId) { if (targetId != kInvalidUniqueId) { - if (TCastToConstPtr point = mgr.GetObjectById(targetId)) + if (const TCastToConstPtr point = mgr.GetObjectById(targetId)) { CSfxManager::SfxStart(SFXui_lockon_grapple, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - else + } else { CSfxManager::SfxStart(SFXui_lockon_poi, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } } if (targetId == kInvalidUniqueId) { @@ -327,17 +364,20 @@ void CCompoundTargetReticle::UpdateCurrLockOnGroup(float dt, const CStateManager IsDamageOrbit(mgr.GetPlayer().GetOrbitRequest()) ? 0.65f : g_tweakTargeting->GetCurrLockOnEnterDuration(); } else { x12c_currGroupA = x10c_currGroupInterp; - if (xf0_targetId == kInvalidUniqueId) + if (xf0_targetId == kInvalidUniqueId) { x12c_currGroupA.SetTargetId(targetId); + } x14c_currGroupB = CTargetReticleRenderState( targetId, 1.f, zeus::skZero3f, 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); @@ -347,46 +387,54 @@ void CCompoundTargetReticle::UpdateCurrLockOnGroup(float dt, const CStateManager } else { UpdateTargetParameters(x10c_currGroupInterp, mgr); } + if (x1f8_missileBracketTimer != 0.f && x1f8_missileBracketTimer < g_tweakTargeting->GetMissileBracketDuration()) { - if (x1f8_missileBracketTimer < 0.f) + if (x1f8_missileBracketTimer < 0.f) { x1f8_missileBracketTimer = std::min(0.f, x1f8_missileBracketTimer + dt); - else + } 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; + for (auto& iconSquare : xe0_outerBeamIconSquares) { + iconSquare.x10_rotAng = iconSquare.x14_baseAngle; + } xc4_chargeGauge.x10_rotAng = xc4_chargeGauge.x14_baseAngle; x208_lockonTimer = FLT_EPSILON; } else { - float offshoot = + const 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). - asRel(); + for (auto& item : xe0_outerBeamIconSquares) { + item.x10_rotAng = zeus::CRelAngle(item.x18_offshootAngleDelta * offshoot + item.xc_offshootBaseAngle).asRel(); } xc4_chargeGauge.x10_rotAng = zeus::CRelAngle(xc4_chargeGauge.x18_offshootAngleDelta * offshoot + xc4_chargeGauge.xc_offshootBaseAngle). asRel(); } } - if (x208_lockonTimer > 0.f && x208_lockonTimer < g_tweakTargeting->GetLockonDuration()) + + 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) + } + if (x210_lockFireTimer > 0.f) { x210_lockFireTimer = std::max(0.f, x210_lockFireTimer - dt); - if (x1fc_missileBracketScaleTimer > 0.f) + } + if (x1fc_missileBracketScaleTimer > 0.f) { x1fc_missileBracketScaleTimer = std::max(0.f, x1fc_missileBracketScaleTimer - dt); + } } void CCompoundTargetReticle::UpdateNextLockOnGroup(float dt, const CStateManager& mgr) { TUniqueId nextTargetId = mgr.GetPlayer().GetOrbitNextTargetId(); if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan && - mgr.GetPlayer().GetOrbitTargetId() != kInvalidUniqueId) + mgr.GetPlayer().GetOrbitTargetId() != kInvalidUniqueId) { nextTargetId = mgr.GetPlayer().GetOrbitTargetId(); + } + if (nextTargetId != xf2_nextTargetId) { if (nextTargetId == kInvalidUniqueId) { x194_nextGroupA = x174_nextGroupInterp; @@ -408,6 +456,7 @@ void CCompoundTargetReticle::UpdateNextLockOnGroup(float dt, const CStateManager xf2_nextTargetId = nextTargetId; } } + if (x1d8_nextGroupTimer > 0.f) { UpdateTargetParameters(x194_nextGroupA, mgr); UpdateTargetParameters(x1b4_nextGroupB, mgr); @@ -420,22 +469,25 @@ void CCompoundTargetReticle::UpdateNextLockOnGroup(float dt, const CStateManager } void CCompoundTargetReticle::UpdateOrbitZoneGroup(float dt, const CStateManager& mgr) { - if (xf0_targetId == kInvalidUniqueId && xf2_nextTargetId != kInvalidUniqueId) + if (xf0_targetId == kInvalidUniqueId && xf2_nextTargetId != kInvalidUniqueId) { x20c_ = std::min(1.f, 2.f * dt + x20c_); - else + } else { x20c_ = std::max(0.f, x20c_ - 2.f * dt); + } + if (mgr.GetPlayer().IsShowingCrosshairs() && - mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) + mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) { x1e8_crosshairsScale = std::min(1.f, dt / g_tweakTargeting->GetCrosshairsScaleDuration() + x1e8_crosshairsScale); - else + } else { x1e8_crosshairsScale = std::max(0.f, x1e8_crosshairsScale - dt / g_tweakTargeting->GetCrosshairsScaleDuration()); + } } -void CCompoundTargetReticle::Draw(const CStateManager& mgr, bool hideLockon) const { +void CCompoundTargetReticle::Draw(const CStateManager& mgr, bool hideLockon) { if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && !mgr.GetCameraManager()->IsInCinematicCamera()) { SCOPED_GRAPHICS_DEBUG_GROUP("CCompoundTargetReticle::Draw", zeus::skCyan); - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + const zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); CGraphics::SetViewPointMatrix(camXf); if (!hideLockon) { DrawCurrLockOnGroup(camXf.basis, mgr); @@ -444,18 +496,23 @@ void CCompoundTargetReticle::Draw(const CStateManager& mgr, bool hideLockon) con } DrawGrappleGroup(camXf.basis, mgr, hideLockon); } - if (x28_noDrawTicks > 0) + + 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()) + + if (point.GetGrappleParameters().GetLockSwingTurn()) { color = g_tweakTargeting->GetLockedGrapplePointSelectColor(); - else + } else { color = g_tweakTargeting->GetGrapplePointSelectColor(); + } + color = zeus::CColor::lerp(g_tweakTargeting->GetGrapplePointColor(), color, t); zeus::CMatrix3f scale( CalculateClampedScale(orbitPos, 1.f, g_tweakTargeting->GetGrappleClampMin(), @@ -469,8 +526,9 @@ void CCompoundTargetReticle::DrawGrapplePoint(const CScriptGrapplePoint& point, void CCompoundTargetReticle::DrawGrappleGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr, bool hideLockon) const { - if (x28_noDrawTicks > 0) + if (x28_noDrawTicks > 0) { return; + } if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam) && x94_grapple.IsLoaded() && x20_prevState != EReticleState::Scan) { @@ -480,39 +538,45 @@ void CCompoundTargetReticle::DrawGrappleGroup(const zeus::CMatrix3f& rot, const if (point->GetActive()) { if (point->GetAreaIdAlways() != kInvalidAreaId) { const CGameArea* area = mgr.GetWorld()->GetAreaAlways(point->GetAreaIdAlways()); - CGameArea::EOcclusionState occState = + const auto occState = area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; - if (occState != CGameArea::EOcclusionState::Visible) + if (occState != CGameArea::EOcclusionState::Visible) { continue; + } } float t = 0.f; - if (point->GetUniqueId() == x1dc_grapplePoint0) + if (point->GetUniqueId() == x1dc_grapplePoint0) { t = x1e0_grapplePoint0T; - else if (point->GetUniqueId() == x1de_grapplePoint1) + } else if (point->GetUniqueId() == x1de_grapplePoint1) { t = x1e4_grapplePoint1T; - if (std::fabs(t) < 0.00001f) + } + 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); + const TCastToConstPtr point0 = mgr.GetObjectById(x1dc_grapplePoint0); + const 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) + const 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) + if (x28_noDrawTicks > 0) { return; - if (x1e0_grapplePoint0T + x1e4_grapplePoint1T > 0 || x10c_currGroupInterp.GetFactor() == 0.f) + } + if (x1e0_grapplePoint0T + x1e4_grapplePoint1T > 0 || x10c_currGroupInterp.GetFactor() == 0.f) { return; + } float lockBreakAlpha = x10c_currGroupInterp.GetFactor(); float visorFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); @@ -535,79 +599,83 @@ void CCompoundTargetReticle::DrawCurrLockOnGroup(const zeus::CMatrix3f& rot, con 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); + const int a = rand() % 9; + const 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) + 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()); + const 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()); + const zeus::CTransform modelXf(lockBreakXf * (rot * zeus::CMatrix3f::RotateY(x1ec_seekerAngle) * scale), + x10c_currGroupInterp.GetTargetPositionWorld()); CGraphics::SetModelMatrix(modelXf); zeus::CColor color = g_tweakTargeting->GetLockConfirmColor(); color.a() *= lockBreakAlpha; - CModelFlags flags(7, 0, 0, lockBreakColor + color); + const CModelFlags flags(7, 0, 0, lockBreakColor + color); x4c_lockConfirm->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()); + const zeus::CMatrix3f scale(CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), + x10c_currGroupInterp.GetRadiusWorld(), + x10c_currGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetTargetFlowerClampMin(), + g_tweakTargeting->GetTargetFlowerClampMax(), mgr) * + g_tweakTargeting->GetTargetFlowerScale() / lockBreakAlpha); + const 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); + const 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()); + const float t = + std::fabs((x1fc_missileBracketScaleTimer - 0.5f * g_tweakTargeting->GetMissileBracketScaleDuration()) / 0.5f * + g_tweakTargeting->GetMissileBracketScaleDuration()); + const float tscale = ((1.f - t) * g_tweakTargeting->GetMissileBracketScaleEnd() + + t * g_tweakTargeting->GetMissileBracketScaleStart()); + const 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( + const 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); + const 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()); + + const 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]; @@ -621,16 +689,18 @@ void CCompoundTargetReticle::DrawCurrLockOnGroup(const zeus::CMatrix3f& rot, con 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 = + const 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()); + const zeus::CMatrix3f chargeGaugeXf = rot * scale * zeus::CMatrix3f::RotateY(xc4_chargeGauge.x10_rotAng); + const float pulseT = + std::fabs(std::fmod(CGraphics::GetSecondsMod900(), g_tweakTargeting->GetChargeGaugePulsePeriod())); + const zeus::CColor gaugeColor = zeus::CColor::lerp(g_tweakTargeting->GetChargeGaugeNonFullColor(), zeus::CColor::lerp(g_tweakTargeting->GetChargeGaugePulseColorHigh(), g_tweakTargeting->GetChargeGaugePulseColorLow(), @@ -643,21 +713,22 @@ void CCompoundTargetReticle::DrawCurrLockOnGroup(const zeus::CMatrix3f& rot, con CGraphics::SetModelMatrix(modelXf); zeus::CColor color = gaugeColor; color.a() *= lockBreakAlpha * visorFactor; - CModelFlags flags(7, 0, 0, lockBreakColor + color); + const 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 = + const 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); + const CModelFlags tickFlags(7, 0, 0, lockBreakColor + color); + xa0_chargeTickFirst->Draw(tickFlags); modelXf.rotateLocalY(g_tweakTargeting->GetChargeTickAnglePitch()); CGraphics::SetModelMatrix(modelXf); } } } + if (x208_lockonTimer > 0.f && x70_innerBeamIcon.IsLoaded()) { const zeus::CColor* iconColor; switch (x200_beam) { @@ -674,41 +745,44 @@ void CCompoundTargetReticle::DrawCurrLockOnGroup(const zeus::CMatrix3f& rot, con iconColor = &g_tweakTargeting->GetInnerBeamColorPlasma(); break; } - zeus::CMatrix3f scale( + + const 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()); + const 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); + const 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()); + const 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()); + const 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); + const 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 = + const float t = std::fabs((x210_lockFireTimer - 0.5f * g_tweakTargeting->GetLockFireDuration()) / 0.5f * + g_tweakTargeting->GetLockFireDuration()); + const float tscale = ((1.f - t) * g_tweakTargeting->GetLockDaggerScaleEnd() + t * g_tweakTargeting->GetLockDaggerScaleStart()); - zeus::CMatrix3f scale( + const zeus::CMatrix3f scale( CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), x10c_currGroupInterp.GetRadiusWorld(), x10c_currGroupInterp.GetMinViewportClampScale() * g_tweakTargeting->GetLockDaggerClampMin(), @@ -728,21 +802,22 @@ void CCompoundTargetReticle::DrawCurrLockOnGroup(const zeus::CMatrix3f& rot, con ang = g_tweakTargeting->GetLockDaggerAngle2(); break; } - zeus::CTransform modelXf(lockBreakXf * lockDaggerXf * zeus::CMatrix3f::RotateY(ang), - x10c_currGroupInterp.GetTargetPositionWorld()); + const 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); + const CModelFlags flags(7, 0, 0, lockBreakColor + color); x88_lockDagger->Draw(flags); } } } } -void CCompoundTargetReticle::DrawNextLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr) const { - if (x28_noDrawTicks > 0) +void CCompoundTargetReticle::DrawNextLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr) { + if (x28_noDrawTicks > 0) { return; + } zeus::CVector3f position = x174_nextGroupInterp.GetTargetPositionWorld(); float visorFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); @@ -765,64 +840,64 @@ void CCompoundTargetReticle::DrawNextLockOnGroup(const zeus::CMatrix3f& rot, con } if (!xrayRet && x174_nextGroupInterp.GetFactor() > 0.f && x40_seeker.IsLoaded()) { - zeus::CMatrix3f scale( + const 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()); + const 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); + const CModelFlags flags(7, 0, 0, color); x40_seeker->Draw(flags); } if (xrayRet && xac_xrayRetRing.IsLoaded()) { - zeus::CMatrix3f scale( + const 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()); + const 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); + const CModelFlags flags(7, 0, 0, color); xac_xrayRetRing->Draw(flags); } if (thermalRet && xb8_thermalReticle.IsLoaded()) { - zeus::CMatrix3f scale( + const 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()); + const 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); + const 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()); + const zeus::CMatrix3f scale(CalculateClampedScale(position, x174_nextGroupInterp.GetRadiusWorld(), + x174_nextGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetScanTargetClampMin(), + g_tweakTargeting->GetScanTargetClampMax(), mgr) * + (1.f / factor)); + const 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; + for (size_t i = 0; i < m_scanRetRenderer.m_lineRenderers.size(); ++i) { + const float lineWidth = i != 0 ? 2.5f : 1.f; auto& rend = *m_scanRetRenderer.m_lineRenderers[i]; rend.Reset(); rend.AddVertex({-0.5f, 0.f, 0.f}, color, lineWidth); @@ -835,37 +910,38 @@ void CCompoundTargetReticle::DrawNextLockOnGroup(const zeus::CMatrix3f& rot, con 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; + for (size_t j = 0; j < m_scanRetRenderer.m_stripRenderers[i].size(); ++j) { + const float xSign = j < 2 ? -1.f : 1.f; + const float zSign = (j & 0x1) != 0 ? -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(); + auto& stripRend = *m_scanRetRenderer.m_stripRenderers[i][j]; + stripRend.Reset(); + stripRend.AddVertex({0.5f * xSign, 0.f, 0.1f * zSign}, color, lineWidth); + stripRend.AddVertex({0.5f * xSign, 0.f, 0.35f * zSign}, color, lineWidth); + stripRend.AddVertex({0.35f * xSign, 0.f, 0.5f * zSign}, color, lineWidth); + stripRend.AddVertex({0.1f * xSign, 0.f, 0.5f * zSign}, color, lineWidth); + stripRend.Render(); } } } } void CCompoundTargetReticle::DrawOrbitZoneGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr) const { - if (x28_noDrawTicks > 0) + 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); + const CModelFlags flags(7, 0, 0, color); x34_crosshairs->Draw(flags); } } void CCompoundTargetReticle::UpdateTargetParameters(CTargetReticleRenderState& state, const CStateManager& mgr) { - if (auto act = TCastToConstPtr(mgr.GetAllObjectList().GetObjectById(state.GetTargetId()))) { + if (const auto act = TCastToConstPtr(mgr.GetAllObjectList().GetObjectById(state.GetTargetId()))) { state.SetRadiusWorld(CalculateRadiusWorld(*act, mgr)); state.SetTargetPositionWorld(CalculatePositionWorld(*act, mgr)); } else if (state.GetIsOrbitZoneIdlePosition()) { @@ -877,11 +953,11 @@ void CCompoundTargetReticle::UpdateTargetParameters(CTargetReticleRenderState& s } 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)); + const auto tb = act.GetTouchBounds(); + const 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; + const 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; @@ -901,19 +977,21 @@ float CCompoundTargetReticle::CalculateRadiusWorld(const CActor& act, const CSta } zeus::CVector3f CCompoundTargetReticle::CalculatePositionWorld(const CActor& act, const CStateManager& mgr) const { - if (x20_prevState == EReticleState::Scan) + if (x20_prevState == EReticleState::Scan) { return act.GetOrbitPosition(mgr); + } return act.GetAimPosition(mgr, 0.f); } zeus::CVector3f CCompoundTargetReticle::CalculateOrbitZoneReticlePosition(const CStateManager& mgr, bool lag) const { const CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - float distMul = + const float distMul = 224.f / float(g_tweakPlayer->GetOrbitScreenBoxHalfExtentY(0)) / std::tan(zeus::degToRad(0.5f * curCam->GetFov())); - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + const zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); zeus::CVector3f lookDir = camXf.basis[1]; - if (lag) + if (lag) { lookDir = x10_laggingOrientation.transform(lookDir); + } return lookDir * distMul + camXf.origin; } @@ -927,42 +1005,70 @@ float CCompoundTargetReticle::CalculateClampedScale(const zeus::CVector3f& pos, 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; + const float realX = cam->GetPerspectiveMatrix().multiplyOneOverW(viewPos).x(); + const float offsetX = cam->GetPerspectiveMatrix().multiplyOneOverW(viewPos + zeus::CVector3f(scale, 0.f, 0.f)).x(); + const float unclampedX = (offsetX - realX) * 640; return zeus::clamp(clampMin, unclampedX, clampMax) / unclampedX * scale; } void CCompoundTargetReticle::Touch() { - if (x34_crosshairs.IsLoaded()) + if (x34_crosshairs.IsLoaded()) { x34_crosshairs->Touch(0); - if (x40_seeker.IsLoaded()) + } + + if (x40_seeker.IsLoaded()) { x40_seeker->Touch(0); - if (x4c_lockConfirm.IsLoaded()) + } + + if (x4c_lockConfirm.IsLoaded()) { x4c_lockConfirm->Touch(0); - if (x58_targetFlower.IsLoaded()) + } + + if (x58_targetFlower.IsLoaded()) { x58_targetFlower->Touch(0); - if (x64_missileBracket.IsLoaded()) + } + + if (x64_missileBracket.IsLoaded()) { x64_missileBracket->Touch(0); - if (x70_innerBeamIcon.IsLoaded()) + } + + if (x70_innerBeamIcon.IsLoaded()) { x70_innerBeamIcon->Touch(0); - if (x7c_lockFire.IsLoaded()) + } + + if (x7c_lockFire.IsLoaded()) { x7c_lockFire->Touch(0); - if (x88_lockDagger.IsLoaded()) + } + + if (x88_lockDagger.IsLoaded()) { x88_lockDagger->Touch(0); - if (x94_grapple.IsLoaded()) + } + + if (x94_grapple.IsLoaded()) { x94_grapple->Touch(0); - if (xa0_chargeTickFirst.IsLoaded()) + } + + if (xa0_chargeTickFirst.IsLoaded()) { xa0_chargeTickFirst->Touch(0); - if (xac_xrayRetRing.IsLoaded()) + } + + if (xac_xrayRetRing.IsLoaded()) { xac_xrayRetRing->Touch(0); - if (xb8_thermalReticle.IsLoaded()) + } + + if (xb8_thermalReticle.IsLoaded()) { xb8_thermalReticle->Touch(0); - if (xc4_chargeGauge.x0_model.IsLoaded()) + } + + if (xc4_chargeGauge.x0_model.IsLoaded()) { xc4_chargeGauge.x0_model->Touch(0); - for (SOuterItemInfo& info : xe0_outerBeamIconSquares) - if (info.x0_model.IsLoaded()) + } + + 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 e1df8b7e0..5049a1c45 100644 --- a/Runtime/GuiSys/CCompoundTargetReticle.hpp +++ b/Runtime/GuiSys/CCompoundTargetReticle.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include "Runtime/CPlayerState.hpp" @@ -27,26 +28,26 @@ class CTargetReticleRenderState { public: static const CTargetReticleRenderState skZeroRenderState; - CTargetReticleRenderState(TUniqueId target, float radiusWorld, const zeus::CVector3f& positionWorld, float factor, - float minVpClampScale, bool orbitZoneIdlePosition) + constexpr 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; } + constexpr void SetTargetId(TUniqueId id) { x0_target = id; } + constexpr void SetFactor(float factor) { x14_factor = factor; } + constexpr void SetIsOrbitZoneIdlePosition(bool orbit) { x1c_orbitZoneIdlePosition = orbit; } + constexpr float GetMinViewportClampScale() const { return x18_minVpClampScale; } + constexpr float GetFactor() const { return x14_factor; } + constexpr float GetRadiusWorld() const { return x4_radiusWorld; } + constexpr const zeus::CVector3f& GetTargetPositionWorld() const { return x8_positionWorld; } + constexpr bool GetIsOrbitZoneIdlePosition() const { return x1c_orbitZoneIdlePosition; } + constexpr void SetTargetPositionWorld(const zeus::CVector3f& position) { x8_positionWorld = position; } + constexpr void SetRadiusWorld(float radius) { x4_radiusWorld = radius; } + constexpr TUniqueId GetTargetId() const { return x0_target; } + constexpr void SetMinViewportClampScale(float scale) { x18_minVpClampScale = scale; } static void InterpolateWithClamp(const CTargetReticleRenderState& a, CTargetReticleRenderState& out, const CTargetReticleRenderState& b, float t); }; @@ -69,7 +70,7 @@ private: zeus::CQuaternion x10_laggingOrientation; EReticleState x20_prevState = EReticleState::Unspecified; EReticleState x24_nextState = EReticleState::Unspecified; - mutable u32 x28_noDrawTicks = 0; + u32 x28_noDrawTicks = 0; float x2c_overshootOffsetHalf; float x30_premultOvershootOffset; TCachedToken x34_crosshairs; @@ -120,16 +121,16 @@ private: bool x219_missileShot = false; bool x21a_fullyCharged = false; u8 x21b_ = 0; - u32 x21c_; - u32 x220_; - u32 x228_; + u32 x21c_ = 0; + u32 x220_ = 0; + u32 x228_ = 0; struct SScanReticuleRenderer { - std::optional m_lineRenderers[2]; - std::optional m_stripRenderers[2][4]; + std::array, 2> m_lineRenderers; + std::array, 4>, 2> m_stripRenderers; SScanReticuleRenderer(); }; - mutable SScanReticuleRenderer m_scanRetRenderer; + SScanReticuleRenderer m_scanRetRenderer; void DrawGrapplePoint(const CScriptGrapplePoint& point, float t, const CStateManager& mgr, const zeus::CMatrix3f& rot, bool zEqual) const; @@ -144,10 +145,10 @@ public: void UpdateCurrLockOnGroup(float, const CStateManager&); void UpdateNextLockOnGroup(float, const CStateManager&); void UpdateOrbitZoneGroup(float, const CStateManager&); - void Draw(const CStateManager&, bool hideLockon) const; + void Draw(const CStateManager&, bool hideLockon); 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 DrawNextLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager&); void DrawOrbitZoneGroup(const zeus::CMatrix3f& rot, const CStateManager&) const; void UpdateTargetParameters(CTargetReticleRenderState&, const CStateManager&); float CalculateRadiusWorld(const CActor&, const CStateManager&) const; diff --git a/Runtime/GuiSys/CErrorOutputWindow.cpp b/Runtime/GuiSys/CErrorOutputWindow.cpp index 04596dd20..aae8942d9 100644 --- a/Runtime/GuiSys/CErrorOutputWindow.cpp +++ b/Runtime/GuiSys/CErrorOutputWindow.cpp @@ -5,6 +5,7 @@ namespace urde { CErrorOutputWindow::CErrorOutputWindow(bool flag) : CIOWin("Error Output Window") { + x18_24_ = false; x18_25_ = true; x18_26_ = true; x18_27_ = true; diff --git a/Runtime/GuiSys/CErrorOutputWindow.hpp b/Runtime/GuiSys/CErrorOutputWindow.hpp index 85b2231d6..b6088a9ba 100644 --- a/Runtime/GuiSys/CErrorOutputWindow.hpp +++ b/Runtime/GuiSys/CErrorOutputWindow.hpp @@ -11,16 +11,11 @@ public: 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; - }; + bool x18_24_; + bool x18_25_; + bool x18_26_; + bool x18_27_; + bool x18_28_; const wchar_t* x1c_msg; public: diff --git a/Runtime/GuiSys/CGuiFrame.cpp b/Runtime/GuiSys/CGuiFrame.cpp index 1b1dd1329..9c721067e 100644 --- a/Runtime/GuiSys/CGuiFrame.cpp +++ b/Runtime/GuiSys/CGuiFrame.cpp @@ -133,7 +133,7 @@ void CGuiFrame::Reset() { void CGuiFrame::Update(float dt) { xc_headWidget->Update(dt); } void CGuiFrame::Draw(const CGuiWidgetDrawParms& parms) const { - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CGuiFrame::Draw FRME_{}"), x0_id).c_str(), zeus::skMagenta); + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CGuiFrame::Draw FRME_{}"), x0_id).c_str(), zeus::skMagenta); CGraphics::SetCullMode(ERglCullMode::None); CGraphics::SetAmbientColor(zeus::skWhite); DisableLights(); @@ -195,7 +195,7 @@ void CGuiFrame::ProcessUserInput(const CFinalInput& input) const { } } -bool CGuiFrame::ProcessMouseInput(const CFinalInput& input, const CGuiWidgetDrawParms& parms) const { +bool CGuiFrame::ProcessMouseInput(const CFinalInput& input, const CGuiWidgetDrawParms& parms) { if (const auto& kbm = input.GetKBM()) { zeus::CVector2f point(kbm->m_mouseCoord.norm[0] * 2.f - 1.f, kbm->m_mouseCoord.norm[1] * 2.f - 1.f); diff --git a/Runtime/GuiSys/CGuiFrame.hpp b/Runtime/GuiSys/CGuiFrame.hpp index a5c49d2b1..059316738 100644 --- a/Runtime/GuiSys/CGuiFrame.hpp +++ b/Runtime/GuiSys/CGuiFrame.hpp @@ -47,10 +47,10 @@ private: float m_aspectConstraint = -1.f; float m_maxAspect = -1.f; - mutable bool m_inMouseDown = false; - mutable bool m_inCancel = false; - mutable CGuiWidget* m_mouseDownWidget = nullptr; - mutable CGuiWidget* m_lastMouseOverWidget = nullptr; + bool m_inMouseDown = false; + bool m_inCancel = false; + CGuiWidget* m_mouseDownWidget = nullptr; + CGuiWidget* m_lastMouseOverWidget = nullptr; std::function m_mouseOverChangeCb; std::function m_mouseDownCb; std::function m_mouseUpCb; @@ -102,7 +102,7 @@ public: void Initialize(); void LoadWidgetsInGame(CInputStream& in, CSimplePool* sp); void ProcessUserInput(const CFinalInput& input) const; - bool ProcessMouseInput(const CFinalInput& input, const CGuiWidgetDrawParms& parms) const; + bool ProcessMouseInput(const CFinalInput& input, const CGuiWidgetDrawParms& parms); void ResetMouseState(); CGuiWidgetIdDB& GetWidgetIdDB() { return x18_idDB; } diff --git a/Runtime/GuiSys/CGuiModel.cpp b/Runtime/GuiSys/CGuiModel.cpp index 5a3846514..c8d1ef9c3 100644 --- a/Runtime/GuiSys/CGuiModel.cpp +++ b/Runtime/GuiSys/CGuiModel.cpp @@ -51,7 +51,7 @@ void CGuiModel::Draw(const CGuiWidgetDrawParms& parms) { } if (GetIsVisible()) { - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CGuiModel::Draw {}"), m_name).c_str(), zeus::skCyan); + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CGuiModel::Draw {}"), m_name).c_str(), zeus::skCyan); zeus::CColor moduCol = xa8_color2; moduCol.a() *= parms.x0_alphaMod; xb0_frame->EnableLights(xcc_lightMask, model->GetInstance()); diff --git a/Runtime/GuiSys/CGuiSliderGroup.cpp b/Runtime/GuiSys/CGuiSliderGroup.cpp index bdb3e49d7..74bbe0ff2 100644 --- a/Runtime/GuiSys/CGuiSliderGroup.cpp +++ b/Runtime/GuiSys/CGuiSliderGroup.cpp @@ -11,7 +11,10 @@ CGuiSliderGroup::CGuiSliderGroup(const CGuiWidgetParms& parms, float min, float , xbc_maxVal(max) , xc0_roundedCurVal(def) , xc4_curVal(def) -, xc8_increment(inc) {} +, xc8_increment(inc) +, xf4_24_inputPending(false) +, m_mouseInside(false) +, m_mouseDown(false) {} void CGuiSliderGroup::SetSelectionChangedCallback(std::function&& func) { xd8_changeCallback = std::move(func); diff --git a/Runtime/GuiSys/CGuiSliderGroup.hpp b/Runtime/GuiSys/CGuiSliderGroup.hpp index 3c13f783b..da3578d24 100644 --- a/Runtime/GuiSys/CGuiSliderGroup.hpp +++ b/Runtime/GuiSys/CGuiSliderGroup.hpp @@ -22,14 +22,9 @@ private: std::array xcc_sliderRangeWidgets{}; std::function xd8_changeCallback; EState xf0_state = EState::None; - union { - struct { - bool xf4_24_inputPending : 1; - mutable bool m_mouseInside : 1; - bool m_mouseDown : 1; - }; - u32 _dummy = 0; - }; + bool xf4_24_inputPending : 1; + mutable bool m_mouseInside : 1; + bool m_mouseDown : 1; mutable float m_mouseT = 0.f; diff --git a/Runtime/GuiSys/CGuiTextPane.cpp b/Runtime/GuiSys/CGuiTextPane.cpp index 681b89cf7..16c7a32c0 100644 --- a/Runtime/GuiSys/CGuiTextPane.cpp +++ b/Runtime/GuiSys/CGuiTextPane.cpp @@ -51,7 +51,7 @@ void CGuiTextPane::Draw(const CGuiWidgetDrawParms& parms) { if (!GetIsVisible()) { return; } - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CGuiTextPane::Draw {}"), m_name).c_str(), zeus::skCyan); + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CGuiTextPane::Draw {}"), m_name).c_str(), zeus::skCyan); zeus::CVector2f dims = GetDimensions(); diff --git a/Runtime/GuiSys/CGuiTextSupport.cpp b/Runtime/GuiSys/CGuiTextSupport.cpp index a2a6cb993..de1cc1da2 100644 --- a/Runtime/GuiSys/CGuiTextSupport.cpp +++ b/Runtime/GuiSys/CGuiTextSupport.cpp @@ -172,7 +172,7 @@ void CGuiTextSupport::CheckAndRebuildTextBuffer() { std::u16string initStr; if (x5c_fontId.IsValid()) - initStr = fmt::format(fmt(u"&font={};"), x5c_fontId); + initStr = fmt::format(FMT_STRING(u"&font={};"), x5c_fontId); initStr += x0_string; g_TextParser->ParseText(*g_TextExecuteBuf, initStr.c_str(), initStr.size(), x14_props.xc_txtrMap); @@ -219,7 +219,7 @@ void CGuiTextSupport::AutoSetExtent() { void CGuiTextSupport::Render() { CheckAndRebuildRenderBuffer(); if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { - SCOPED_GRAPHICS_DEBUG_GROUP("CGuiTextSupport::Draw", zeus::skBlue); + SCOPED_GRAPHICS_DEBUG_GROUP("CGuiTextSupport::Render", zeus::skBlue); zeus::CTransform oldModel = CGraphics::g_GXModelMatrix; CGraphics::SetModelMatrix(oldModel * zeus::CTransform::Scale(1.f, 1.f, -1.f)); buf->Render(x2c_geometryColor, x10_curTimeMod900); diff --git a/Runtime/GuiSys/CGuiWidget.cpp b/Runtime/GuiSys/CGuiWidget.cpp index 9d398a4f9..6996ad337 100644 --- a/Runtime/GuiSys/CGuiWidget.cpp +++ b/Runtime/GuiSys/CGuiWidget.cpp @@ -71,7 +71,7 @@ void CGuiWidget::ParseBaseInfo(CGuiFrame* frame, CInputStream& in, const CGuiWid in.readUint16Big(); if (isWorker) { if (!parent->AddWorkerWidget(this)) { - Log.report(logvisor::Warning, fmt("Warning: Discarding useless worker id. Parent is not a compound widget.")); + Log.report(logvisor::Warning, FMT_STRING("Warning: Discarding useless worker id. Parent is not a compound widget.")); xb4_workerId = -1; } } diff --git a/Runtime/GuiSys/CGuiWidgetIdDB.cpp b/Runtime/GuiSys/CGuiWidgetIdDB.cpp index 075534f9b..4455cc85a 100644 --- a/Runtime/GuiSys/CGuiWidgetIdDB.cpp +++ b/Runtime/GuiSys/CGuiWidgetIdDB.cpp @@ -10,6 +10,7 @@ CGuiWidgetIdDB::CGuiWidgetIdDB() { } s16 CGuiWidgetIdDB::FindWidgetID(std::string_view name) const { + // TODO: Heterogeneous lookup when C++20 available auto search = x0_dbMap.find(name.data()); if (search == x0_dbMap.cend()) return -1; diff --git a/Runtime/GuiSys/CGuiWidgetIdDB.hpp b/Runtime/GuiSys/CGuiWidgetIdDB.hpp index 799f6efe1..65197094c 100644 --- a/Runtime/GuiSys/CGuiWidgetIdDB.hpp +++ b/Runtime/GuiSys/CGuiWidgetIdDB.hpp @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include "Runtime/GCNTypes.hpp" diff --git a/Runtime/GuiSys/CHudBallInterface.cpp b/Runtime/GuiSys/CHudBallInterface.cpp index f2e0a79fd..74677b489 100644 --- a/Runtime/GuiSys/CHudBallInterface.cpp +++ b/Runtime/GuiSys/CHudBallInterface.cpp @@ -18,7 +18,7 @@ CHudBallInterface::CHudBallInterface(CGuiFrame& selHud, int pbAmount, int pbCapa 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(fmt::format(fmt("group_bombcount{}"), i))); + CGuiGroup* grp = static_cast(selHud.FindWidget(fmt::format(FMT_STRING("group_bombcount{}"), i))); CGuiWidget* filled = grp->GetWorkerWidget(1); CGuiWidget* empty = grp->GetWorkerWidget(0); x14_group_bombfilled.push_back(filled); @@ -65,7 +65,7 @@ void CHudBallInterface::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(fmt::format(fmt("{:02d}"), pbAmount)); + x10_textpane_bombdigits->TextSupport().SetText(fmt::format(FMT_STRING("{:02d}"), pbAmount)); x40_pbAmount = pbAmount; UpdatePowerBombReadoutColors(); } diff --git a/Runtime/GuiSys/CHudBossEnergyInterface.cpp b/Runtime/GuiSys/CHudBossEnergyInterface.cpp index b66374957..3532223d1 100644 --- a/Runtime/GuiSys/CHudBossEnergyInterface.cpp +++ b/Runtime/GuiSys/CHudBossEnergyInterface.cpp @@ -15,10 +15,11 @@ CHudBossEnergyInterface::CHudBossEnergyInterface(CGuiFrame& selHud) { 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); + + const auto& [filled, empty, shadow] = g_tweakGuiColors->GetVisorEnergyBarColors(0); + x18_energybart01_bossbar->SetFilledColor(filled); + x18_energybart01_bossbar->SetShadowColor(shadow); + x18_energybart01_bossbar->SetEmptyColor(empty); } void CHudBossEnergyInterface::Update(float dt) { diff --git a/Runtime/GuiSys/CHudBossEnergyInterface.hpp b/Runtime/GuiSys/CHudBossEnergyInterface.hpp index 71263c16f..c9e94f22d 100644 --- a/Runtime/GuiSys/CHudBossEnergyInterface.hpp +++ b/Runtime/GuiSys/CHudBossEnergyInterface.hpp @@ -10,7 +10,7 @@ class CGuiTextPane; class CGuiWidget; class CHudBossEnergyInterface { - float x0_alpha; + float x0_alpha = 0.f; float x4_fader = 0.f; float x8_curEnergy = 0.f; float xc_maxEnergy = 0.f; diff --git a/Runtime/GuiSys/CHudDecoInterface.cpp b/Runtime/GuiSys/CHudDecoInterface.cpp index d85df6618..60ad8e98c 100644 --- a/Runtime/GuiSys/CHudDecoInterface.cpp +++ b/Runtime/GuiSys/CHudDecoInterface.cpp @@ -34,7 +34,7 @@ CHudDecoInterfaceCombat::CHudDecoInterfaceCombat(CGuiFrame& selHud) { x78_basewidget_tickdeco0->SetColor(g_tweakGuiColors->GetTickDecoColor()); x38_basePosition = x7c_basewidget_frame->GetLocalPosition(); x44_baseRotation = x7c_basewidget_frame->GetLocalTransform().buildMatrix3f(); - UpdateHudAlpha(); + CHudDecoInterfaceCombat::UpdateHudAlpha(); } void CHudDecoInterfaceCombat::UpdateVisibility() { @@ -127,7 +127,7 @@ CHudDecoInterfaceScan::CHudDecoInterfaceScan(CGuiFrame& selHud) : x14_selHud(sel x250_basewidget_rightside->SetLocalPosition(x250_basewidget_rightside->RotateO2P(x224_rightsidePosition - sidesPos)); x234_sidesPositioner = FLT_MAX; - UpdateHudAlpha(); + CHudDecoInterfaceScan::UpdateHudAlpha(); } void CHudDecoInterfaceScan::UpdateVisibility() { @@ -377,7 +377,7 @@ CHudDecoInterfaceXRay::CHudDecoInterfaceXRay(CGuiFrame& selHud) { if (CGuiWidget* w = selHud.FindWidget("model_threatslider")) w->SetDepthWrite(true); - UpdateHudAlpha(); + CHudDecoInterfaceXRay::UpdateHudAlpha(); } void CHudDecoInterfaceXRay::UpdateVisibility() { @@ -482,7 +482,7 @@ CHudDecoInterfaceThermal::CHudDecoInterfaceThermal(CGuiFrame& selHud) { } x14_pivotPosition = x78_basewidget_pivot->GetIdlePosition(); - UpdateHudAlpha(); + CHudDecoInterfaceThermal::UpdateHudAlpha(); } void CHudDecoInterfaceThermal::UpdateVisibility() { diff --git a/Runtime/GuiSys/CHudEnergyInterface.cpp b/Runtime/GuiSys/CHudEnergyInterface.cpp index e664f2bed..f4275d312 100644 --- a/Runtime/GuiSys/CHudEnergyInterface.cpp +++ b/Runtime/GuiSys/CHudEnergyInterface.cpp @@ -27,12 +27,11 @@ CHudEnergyInterface::CHudEnergyInterface(CGuiFrame& selHud, float tankEnergy, in : 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; - +, 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")); @@ -100,7 +99,7 @@ void CHudEnergyInterface::Update(float dt, float energyLowPulse) { x1c_26_barDirty = false; x18_cachedBarEnergy = x2c_energybart01_energybar->GetFilledEnergy(); std::string string = - fmt::format(fmt("{:02d}"), int(std::fmod(x18_cachedBarEnergy, CPlayerState::GetEnergyTankCapacity()))); + fmt::format(FMT_STRING("{:02d}"), int(std::fmod(x18_cachedBarEnergy, CPlayerState::GetEnergyTankCapacity()))); x20_textpane_energydigits->TextSupport().SetText(string); } diff --git a/Runtime/GuiSys/CHudEnergyInterface.hpp b/Runtime/GuiSys/CHudEnergyInterface.hpp index 2c2fda089..7ad71557b 100644 --- a/Runtime/GuiSys/CHudEnergyInterface.hpp +++ b/Runtime/GuiSys/CHudEnergyInterface.hpp @@ -19,15 +19,10 @@ class CHudEnergyInterface { 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; - }; + 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; diff --git a/Runtime/GuiSys/CHudFreeLookInterface.cpp b/Runtime/GuiSys/CHudFreeLookInterface.cpp index 75d86e18b..94a6395f5 100644 --- a/Runtime/GuiSys/CHudFreeLookInterface.cpp +++ b/Runtime/GuiSys/CHudFreeLookInterface.cpp @@ -8,12 +8,12 @@ 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; +: 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"); diff --git a/Runtime/GuiSys/CHudFreeLookInterface.hpp b/Runtime/GuiSys/CHudFreeLookInterface.hpp index fedc6931b..d9d41bea1 100644 --- a/Runtime/GuiSys/CHudFreeLookInterface.hpp +++ b/Runtime/GuiSys/CHudFreeLookInterface.hpp @@ -24,16 +24,11 @@ class CHudFreeLookInterface : public IFreeLookInterface { 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; - }; + 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; diff --git a/Runtime/GuiSys/CHudHelmetInterface.cpp b/Runtime/GuiSys/CHudHelmetInterface.cpp index 963ab114d..a9a915e52 100644 --- a/Runtime/GuiSys/CHudHelmetInterface.cpp +++ b/Runtime/GuiSys/CHudHelmetInterface.cpp @@ -7,11 +7,12 @@ namespace urde { -CHudHelmetInterface::CHudHelmetInterface(CGuiFrame& helmetFrame) { - x3c_24_helmetVisibleDebug = true; - x3c_25_helmetVisibleGame = true; - x3c_26_glowVisibleDebug = true; - x3c_27_glowVisibleGame = true; +CHudHelmetInterface::CHudHelmetInterface(CGuiFrame& helmetFrame) +: x3c_24_helmetVisibleDebug(true) +, x3c_25_helmetVisibleGame(true) +, x3c_26_glowVisibleDebug(true) +, x3c_27_glowVisibleGame(true) +, x3c_28_hudLagDirty(false) { x40_camera = helmetFrame.GetFrameCamera(); x44_BaseWidget_Pivot = helmetFrame.FindWidget("BaseWidget_Pivot"); x48_BaseWidget_Helmet = helmetFrame.FindWidget("BaseWidget_Helmet"); diff --git a/Runtime/GuiSys/CHudHelmetInterface.hpp b/Runtime/GuiSys/CHudHelmetInterface.hpp index 534f02fce..0046f540c 100644 --- a/Runtime/GuiSys/CHudHelmetInterface.hpp +++ b/Runtime/GuiSys/CHudHelmetInterface.hpp @@ -12,16 +12,11 @@ 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; - }; + 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; diff --git a/Runtime/GuiSys/CHudMissileInterface.cpp b/Runtime/GuiSys/CHudMissileInterface.cpp index 36b900a22..1e3cadd73 100644 --- a/Runtime/GuiSys/CHudMissileInterface.cpp +++ b/Runtime/GuiSys/CHudMissileInterface.cpp @@ -26,11 +26,10 @@ CHudMissileInterface::CHudMissileInterface(CGuiFrame& selHud, int missileCapacit : x0_hudType(hudType) , x4_missileCapacity(missileCapacity) , x8_numMissles(numMissiles) -, x4c_chargeBeamFactor(chargeFactor) { - x58_24_missilesActive = missilesActive; - x58_25_visibleDebug = true; - x58_26_visibleGame = true; - +, 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")); @@ -217,7 +216,7 @@ void CHudMissileInterface::SetChargeBeamFactor(float t) { x4c_chargeBeamFactor = void CHudMissileInterface::SetNumMissiles(int numMissiles, const CStateManager& mgr) { numMissiles = zeus::clamp(0, numMissiles, 999); - x60_textpane_missiledigits->TextSupport().SetText(fmt::format(fmt("{:3d}"), numMissiles)); + x60_textpane_missiledigits->TextSupport().SetText(fmt::format(FMT_STRING("{:3d}"), numMissiles)); if (x8_numMissles < numMissiles) { xc_arrowTimer = g_tweakGui->GetMissileArrowVisTime(); diff --git a/Runtime/GuiSys/CHudMissileInterface.hpp b/Runtime/GuiSys/CHudMissileInterface.hpp index df21193ec..da8753dfa 100644 --- a/Runtime/GuiSys/CHudMissileInterface.hpp +++ b/Runtime/GuiSys/CHudMissileInterface.hpp @@ -26,16 +26,11 @@ class CHudMissileInterface { 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; - }; + 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; diff --git a/Runtime/GuiSys/CHudRadarInterface.cpp b/Runtime/GuiSys/CHudRadarInterface.cpp index aea967b02..51c190db2 100644 --- a/Runtime/GuiSys/CHudRadarInterface.cpp +++ b/Runtime/GuiSys/CHudRadarInterface.cpp @@ -28,8 +28,7 @@ CHudRadarInterface::CHudRadarInterface(CGuiFrame& baseHud, CStateManager& stateM x40_BaseWidget_RadarStuff->SetColor(g_tweakGuiColors->GetRadarStuffColor()); } -void CHudRadarInterface::DoDrawRadarPaint(const zeus::CVector3f& translate, float radius, - const zeus::CColor& color) const { +void CHudRadarInterface::DoDrawRadarPaint(const zeus::CVector3f& translate, float radius, const zeus::CColor& color) { radius *= 4.f; CRadarPaintShader::Instance& inst = m_paintInsts.emplace_back(); @@ -45,20 +44,23 @@ void CHudRadarInterface::DoDrawRadarPaint(const zeus::CVector3f& translate, floa } void CHudRadarInterface::DrawRadarPaint(const zeus::CVector3f& enemyPos, float radius, float alpha, - const SRadarPaintDrawParms& parms) const { - zeus::CVector2f playerToEnemy = enemyPos.toVec2f() - parms.x0_playerPos.toVec2f(); + const SRadarPaintDrawParms& parms) { + const zeus::CVector2f playerToEnemy = enemyPos.toVec2f() - parms.x0_playerPos.toVec2f(); + const 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::CColor color = g_tweakGuiColors->GetRadarEnemyPaintColor(); - color.a() *= alpha; - color.a() *= parms.x74_alpha; - DoDrawRadarPaint(parms.xc_preTranslate * zeus::CVector3f(scopeScaled.x(), 0.f, scopeScaled.y()), radius, color); + if (playerToEnemy.magnitude() > parms.x78_xyRadius || zDelta > parms.x7c_zRadius) { + return; } + + if (zDelta > parms.x80_ZCloseRadius) { + alpha *= 1.f - (zDelta - parms.x80_ZCloseRadius) / (parms.x7c_zRadius - parms.x80_ZCloseRadius); + } + + const zeus::CVector2f scopeScaled = playerToEnemy * parms.x70_scopeScalar; + zeus::CColor color = g_tweakGuiColors->GetRadarEnemyPaintColor(); + color.a() *= alpha; + color.a() *= parms.x74_alpha; + DoDrawRadarPaint(parms.xc_preTranslate * zeus::CVector3f(scopeScaled.x(), 0.f, scopeScaled.y()), radius, color); } void CHudRadarInterface::SetIsVisibleGame(bool v) { @@ -67,29 +69,33 @@ void CHudRadarInterface::SetIsVisibleGame(bool v) { } void CHudRadarInterface::Update(float dt, const CStateManager& mgr) { - CPlayerState& playerState = *mgr.GetPlayerState(); - float visorTransFactor = (playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat) - ? playerState.GetVisorTransitionFactor() - : 0.f; + const CPlayerState& playerState = *mgr.GetPlayerState(); + const 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); + const bool tweakVis = g_tweakGui->GetHudVisMode() >= ITweakGui::EHudVisMode::Three; + + if (tweakVis == x3c_25_visibleDebug) { + return; } + + 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 { +void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) { alpha *= g_GameState->GameOptions().GetHUDAlpha() / 255.f; if (g_tweakGui->GetHudVisMode() == ITweakGui::EHudVisMode::Zero || !x3c_24_visibleGame || !x0_txtrRadarPaint || - !x0_txtrRadarPaint.IsLoaded()) + !x0_txtrRadarPaint.IsLoaded()) { return; + } SRadarPaintDrawParms drawParms; - CPlayer& player = mgr.GetPlayer(); + const CPlayer& player = mgr.GetPlayer(); if (player.IsOverrideRadarRadius()) { drawParms.x78_xyRadius = player.GetRadarXYRadiusOverride(); drawParms.x7c_zRadius = player.GetRadarZRadiusOverride(); @@ -103,13 +109,13 @@ void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) const { drawParms.x6c_scopeRadius = g_tweakGui->GetRadarScopeCoordRadius(); drawParms.x70_scopeScalar = drawParms.x6c_scopeRadius / drawParms.x78_xyRadius; - float camZ = + const float camZ = zeus::CEulerAngles(zeus::CQuaternion(mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis)).z(); zeus::CRelAngle angleZ(camZ); angleZ.makeRel(); drawParms.xc_preTranslate = zeus::CTransform::RotateY(angleZ); drawParms.x3c_postTranslate = x40_BaseWidget_RadarStuff->GetWorldTransform(); - float enemyRadius = g_tweakGui->GetRadarEnemyPaintRadius(); + const float enemyRadius = g_tweakGui->GetRadarEnemyPaintRadius(); m_paintInsts.clear(); x44_camera->Draw(CGuiWidgetDrawParms{0.f, zeus::CVector3f{}}); @@ -119,7 +125,7 @@ void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) const { playerColor.a() *= alpha; DoDrawRadarPaint(zeus::skZero3f, g_tweakGui->GetRadarPlayerPaintRadius(), playerColor); - zeus::CAABox radarBounds( + const 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); @@ -133,15 +139,17 @@ void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) const { drawParms.x0_playerPos = mgr.GetPlayer().GetTranslation(); drawParms.x74_alpha = alpha; - for (TUniqueId id : nearList) { - if (TCastToConstPtr act = mgr.GetObjectById(id)) { - if (!act->GetActive()) + for (const TUniqueId id : nearList) { + if (const TCastToConstPtr act = mgr.GetObjectById(id)) { + if (!act->GetActive()) { continue; - if (TCastToConstPtr swarm = act.GetPtr()) { - float radius = enemyRadius * 0.5f; + } + if (const TCastToConstPtr swarm = act.GetPtr()) { + const float radius = enemyRadius * 0.5f; for (const CWallCrawlerSwarm::CBoid& boid : swarm->GetBoids()) { - if (!boid.GetActive()) + if (!boid.GetActive()) { continue; + } DrawRadarPaint(boid.GetTranslation(), radius, 0.5f, drawParms); } } else { diff --git a/Runtime/GuiSys/CHudRadarInterface.hpp b/Runtime/GuiSys/CHudRadarInterface.hpp index 8a601701b..080b496fe 100644 --- a/Runtime/GuiSys/CHudRadarInterface.hpp +++ b/Runtime/GuiSys/CHudRadarInterface.hpp @@ -33,17 +33,16 @@ class CHudRadarInterface { bool x3c_25_visibleDebug : 1; CGuiWidget* x40_BaseWidget_RadarStuff; CGuiCamera* x44_camera; - mutable CRadarPaintShader m_paintShader; - mutable std::vector m_paintInsts; - void DoDrawRadarPaint(const zeus::CVector3f& translate, float radius, const zeus::CColor& color) const; - void DrawRadarPaint(const zeus::CVector3f& enemyPos, float radius, float alpha, - const SRadarPaintDrawParms& parms) const; + CRadarPaintShader m_paintShader; + std::vector m_paintInsts; + void DoDrawRadarPaint(const zeus::CVector3f& translate, float radius, const zeus::CColor& color); + void DrawRadarPaint(const zeus::CVector3f& enemyPos, float radius, float alpha, const SRadarPaintDrawParms& parms); 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; + void Draw(const CStateManager& mgr, float alpha); }; } // namespace urde diff --git a/Runtime/GuiSys/CHudThreatInterface.cpp b/Runtime/GuiSys/CHudThreatInterface.cpp index 7a4235b19..e5cd207c7 100644 --- a/Runtime/GuiSys/CHudThreatInterface.cpp +++ b/Runtime/GuiSys/CHudThreatInterface.cpp @@ -88,7 +88,7 @@ void CHudThreatInterface::Update(float dt) { if (x70_textpane_threatdigits) { if (x10_threatDist < maxThreatEnergy) { x70_textpane_threatdigits->SetIsVisible(true); - x70_textpane_threatdigits->TextSupport().SetText(fmt::format(fmt("{:01.1f}"), std::max(0.f, x10_threatDist))); + x70_textpane_threatdigits->TextSupport().SetText(fmt::format(FMT_STRING("{:01.1f}"), std::max(0.f, x10_threatDist))); } else { x70_textpane_threatdigits->SetIsVisible(false); } diff --git a/Runtime/GuiSys/CHudVisorBeamMenu.cpp b/Runtime/GuiSys/CHudVisorBeamMenu.cpp index 3153cf848..58748fe84 100644 --- a/Runtime/GuiSys/CHudVisorBeamMenu.cpp +++ b/Runtime/GuiSys/CHudVisorBeamMenu.cpp @@ -68,7 +68,7 @@ CHudVisorBeamMenu::CHudVisorBeamMenu(CGuiFrame& baseHud, EHudVisorBeamMenu type, x18_basewidget_menu = x0_baseHud.FindWidget(BaseMenuNames[size_t(swappedType)]); x24_model_ghost = - static_cast(x0_baseHud.FindWidget(fmt::format(fmt("{}ghost"), ModelNames[size_t(x4_type)]))); + static_cast(x0_baseHud.FindWidget(fmt::format(FMT_STRING("{}ghost"), ModelNames[size_t(x4_type)]))); x28_menuItems.resize(4); for (size_t i = 0; i < x28_menuItems.size(); i++) { @@ -77,9 +77,9 @@ CHudVisorBeamMenu::CHudVisorBeamMenu(CGuiFrame& baseHud, EHudVisorBeamMenu type, SMenuItem& item = x28_menuItems[i]; item.x0_model_loz = - static_cast(x0_baseHud.FindWidget(fmt::format(fmt("{}loz{}"), modelName, menuItemOrder))); + static_cast(x0_baseHud.FindWidget(fmt::format(FMT_STRING("{}loz{}"), modelName, menuItemOrder))); item.x4_model_icon = - static_cast(x0_baseHud.FindWidget(fmt::format(fmt("{}icon{}"), modelName, menuItemOrder))); + static_cast(x0_baseHud.FindWidget(fmt::format(FMT_STRING("{}icon{}"), modelName, menuItemOrder))); item.xc_opacity = enables[i] ? 1.f : 0.f; } diff --git a/Runtime/GuiSys/CScanDisplay.cpp b/Runtime/GuiSys/CScanDisplay.cpp index 471f6ee18..8a78f3906 100644 --- a/Runtime/GuiSys/CScanDisplay.cpp +++ b/Runtime/GuiSys/CScanDisplay.cpp @@ -71,9 +71,10 @@ void CScanDisplay::CDataDot::SetDestPosition(const zeus::CVector2f& pos) { CScanDisplay::CScanDisplay(const CGuiFrame& selHud) : xa0_selHud(selHud) { x0_dataDot = g_SimplePool->GetObj("TXTR_DataDot"); - for (int i = 0; i < 4; ++i) + for (size_t i = 0; i < xbc_dataDots.capacity(); ++i) { xbc_dataDots.emplace_back(x0_dataDot); - x170_paneStates.resize(4); + } + x170_paneStates.resize(x170_paneStates.capacity()); } void CScanDisplay::ProcessInput(const CFinalInput& input) { @@ -139,26 +140,34 @@ void CScanDisplay::ProcessInput(const CFinalInput& input) { xb8_dash->SetColor(zeus::CColor(0.53f, 0.84f, 1.f, dashAlpha)); } -float CScanDisplay::GetDownloadStartTime(int idx) const { - if (!x14_scannableInfo) +float CScanDisplay::GetDownloadStartTime(size_t 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); } + + const float nTime = x14_scannableInfo->GetBucket(idx).x4_appearanceRange; + float maxTime = 0.f; + for (size_t i = 0; i < CScannableObjectInfo::NumBuckets; ++i) { + const 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) +float CScanDisplay::GetDownloadFraction(size_t 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) + } + + const float appearTime = GetDownloadStartTime(idx); + const 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); } @@ -182,26 +191,26 @@ void CScanDisplay::StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo, xa8_message->TextSupport().SetText(u""); xac_scrollMessage->TextSupport().SetText(u""); - for (int i = 0; i < 20; ++i) { - CAuiImagePane* pane = - static_cast(xa0_selHud.FindWidget(MP1::CPauseScreenBase::GetImagePaneName(i))); + for (size_t i = 0; i < 20; ++i) { + auto* 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({}, g_SimplePool); pane->SetAnimationParms(zeus::skZero2f, 0.f, 0.f); - int pos = -1; - for (int j = 0; j < 4; ++j) { + size_t pos = SIZE_MAX; + for (size_t j = 0; j < CScannableObjectInfo::NumBuckets; ++j) { if (x14_scannableInfo->GetBucket(j).x8_imagePos == i) { pos = j; break; } } - if (pos >= 0) + if (pos != SIZE_MAX) { x170_paneStates[pos].second = pane; + } } - for (int i = 0; i < x170_paneStates.size(); ++i) { + for (size_t i = 0; i < x170_paneStates.size(); ++i) { std::pair& state = x170_paneStates[i]; if (state.second) { const CScannableObjectInfo::SBucket& bucket = x14_scannableInfo->GetBucket(i); @@ -211,22 +220,25 @@ void CScanDisplay::StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo, } state.second->SetTextureID0(bucket.x0_texture, g_SimplePool); state.second->SetFlashFactor(0.f); - float startTime = GetDownloadStartTime(i); - if (scanTime >= startTime) + + const float startTime = GetDownloadStartTime(i); + if (scanTime >= startTime) { x170_paneStates[i].first = 0.f; - else + } else { x170_paneStates[i].first = -1.f; + } } } - CAssetId strId = x14_scannableInfo->GetStringTableId(); - if (strId.IsValid()) + const 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; + for (size_t i = 0; i < CScannableObjectInfo::NumBuckets; ++i) { + const u32 pos = x14_scannableInfo->GetBucket(i).x8_imagePos; CDataDot& dot = xbc_dataDots[i]; - if (pos != -1) { + if (pos != UINT32_MAX) { if (GetDownloadStartTime(i) - g_tweakGui->GetScanAppearanceDuration() < scanTime) { dot.SetAlpha(0.f); dot.SetDotState(CDataDot::EDotState::Done); @@ -243,12 +255,14 @@ void CScanDisplay::StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo, } void CScanDisplay::StopScan() { - if (xc_state == EScanState::Done || xc_state == EScanState::Inactive) + 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); + for (auto& dataDot : xbc_dataDots) { + dataDot.SetDesiredAlpha(0.f); + } } void CScanDisplay::SetScanMessageTypeEffect(CGuiTextPane* pane, bool type) { @@ -310,25 +324,30 @@ void CScanDisplay::Update(float dt, float scanningTime) { } } - for (int i = 0; i < 4; ++i) { - if (x170_paneStates[i].second == nullptr) + for (size_t i = 0; i < x170_paneStates.size(); ++i) { + if (x170_paneStates[i].second == nullptr) { 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()) + if (x170_paneStates[i].first > g_tweakGui->GetScanPaneFadeOutTime()) { tmp = 1.f - (x170_paneStates[i].first - g_tweakGui->GetScanPaneFadeOutTime()) / g_tweakGui->GetScanPaneFadeInTime(); - else + } else { tmp = x170_paneStates[i].first / g_tweakGui->GetScanPaneFadeOutTime(); + } x170_paneStates[i].second->SetFlashFactor(tmp * g_tweakGui->GetScanPaneFlashFactor() * x1a8_bodyAlpha); } - float alphaMul = + + const 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()) { @@ -338,7 +357,7 @@ void CScanDisplay::Update(float dt, float scanningTime) { dot.StartTransitionTo(zeus::skZero2f, g_tweakGui->GetScanAppearanceDuration()); break; case CDataDot::EDotState::RevealPane: { - float tmp = dot.GetTransitionFactor(); + const float tmp = dot.GetTransitionFactor(); if (tmp == 0.f) { dot.SetDotState(CDataDot::EDotState::Done); dot.SetDesiredAlpha(0.f); @@ -353,7 +372,7 @@ void CScanDisplay::Update(float dt, float scanningTime) { } } - for (int i = 0; i < 4; ++i) { + for (size_t i = 0; i < xbc_dataDots.size(); ++i) { CDataDot& dot = xbc_dataDots[i]; switch (dot.GetDotState()) { case CDataDot::EDotState::Hidden: diff --git a/Runtime/GuiSys/CScanDisplay.hpp b/Runtime/GuiSys/CScanDisplay.hpp index 7b9c60d83..45b205bcf 100644 --- a/Runtime/GuiSys/CScanDisplay.hpp +++ b/Runtime/GuiSys/CScanDisplay.hpp @@ -79,8 +79,8 @@ private: float x1b0_aPulse = 1.f; bool x1b4_scanComplete = false; - float GetDownloadStartTime(int idx) const; - float GetDownloadFraction(int idx, float scanningTime) const; + float GetDownloadStartTime(size_t idx) const; + float GetDownloadFraction(size_t idx, float scanningTime) const; static void SetScanMessageTypeEffect(CGuiTextPane* pane, bool type); public: diff --git a/Runtime/GuiSys/CSplashScreen.cpp b/Runtime/GuiSys/CSplashScreen.cpp index 9c36cd163..f4fd01a50 100644 --- a/Runtime/GuiSys/CSplashScreen.cpp +++ b/Runtime/GuiSys/CSplashScreen.cpp @@ -1,5 +1,7 @@ #include "Runtime/GuiSys/CSplashScreen.hpp" +#include + #include "Runtime/CArchitectureMessage.hpp" #include "Runtime/CArchitectureQueue.hpp" #include "Runtime/CSimplePool.hpp" @@ -8,12 +10,12 @@ namespace urde { -static const char* SplashTextures[]{"TXTR_NintendoLogo", "TXTR_RetroLogo", "TXTR_DolbyLogo"}; +constexpr std::array SplashTextures{"TXTR_NintendoLogo"sv, "TXTR_RetroLogo"sv, "TXTR_DolbyLogo"sv}; CSplashScreen::CSplashScreen(ESplashScreen which) : CIOWin("SplashScreen") , x14_which(which) -, m_quad(EFilterType::Blend, g_SimplePool->GetObj(SplashTextures[int(which)])) {} +, m_quad(EFilterType::Blend, g_SimplePool->GetObj(SplashTextures[size_t(which)])) {} CIOWin::EMessageReturn CSplashScreen::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { switch (msg.GetType()) { diff --git a/Runtime/GuiSys/CTargetingManager.cpp b/Runtime/GuiSys/CTargetingManager.cpp index 8221fdc15..ee5bf3f5a 100644 --- a/Runtime/GuiSys/CTargetingManager.cpp +++ b/Runtime/GuiSys/CTargetingManager.cpp @@ -18,7 +18,7 @@ void CTargetingManager::Update(float dt, const CStateManager& stateMgr) { x21c_orbitPointMarker.Update(dt, stateMgr); } -void CTargetingManager::Draw(const CStateManager& mgr, bool hideLockon) const { +void CTargetingManager::Draw(const CStateManager& mgr, bool hideLockon) { CGraphics::SetAmbientColor(zeus::skWhite); CGraphics::DisableAllLights(); x21c_orbitPointMarker.Draw(mgr); diff --git a/Runtime/GuiSys/CTargetingManager.hpp b/Runtime/GuiSys/CTargetingManager.hpp index 58d383930..7e6228c15 100644 --- a/Runtime/GuiSys/CTargetingManager.hpp +++ b/Runtime/GuiSys/CTargetingManager.hpp @@ -13,7 +13,7 @@ public: explicit CTargetingManager(const CStateManager& stateMgr); bool CheckLoadComplete(); void Update(float, const CStateManager& stateMgr); - void Draw(const CStateManager& stateMgr, bool hideLockon) const; + void Draw(const CStateManager& stateMgr, bool hideLockon); void Touch(); CCompoundTargetReticle& CompoundTargetReticle() { return x0_targetReticule; } }; diff --git a/Runtime/GuiSys/CTextExecuteBuffer.hpp b/Runtime/GuiSys/CTextExecuteBuffer.hpp index e84d1043d..e7dd10e75 100644 --- a/Runtime/GuiSys/CTextExecuteBuffer.hpp +++ b/Runtime/GuiSys/CTextExecuteBuffer.hpp @@ -27,8 +27,8 @@ class CTextExecuteBuffer { CBlockInstruction* xa0_curBlock = nullptr; CLineInstruction* xa4_curLine = nullptr; InstList::iterator xa8_curWordIt; - s32 xac_curY; - s32 xb0_curX; + s32 xac_curY = 0; + s32 xb0_curX = 0; s32 xb4_curWordX = 0; s32 xb8_curWordY = 0; s32 xbc_spaceDistance = 0; @@ -37,7 +37,7 @@ class CTextExecuteBuffer { 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, diff --git a/Runtime/IMain.hpp b/Runtime/IMain.hpp index b84364c51..16772b39f 100644 --- a/Runtime/IMain.hpp +++ b/Runtime/IMain.hpp @@ -6,6 +6,7 @@ #include #include #include +#include "DataSpec/DNACommon/URDEVersionInfo.hpp" namespace hecl { class Console; @@ -13,6 +14,9 @@ class CVarManager; } // namespace hecl namespace urde { +using ERegion = DataSpec::ERegion; +using EGame = DataSpec::EGame; + class CStopwatch; enum class EGameplayResult { None, Win, Lose, Playing }; @@ -40,5 +44,12 @@ public: virtual size_t GetExpectedIdSize() const = 0; virtual void WarmupShaders() = 0; virtual hecl::Console* Console() const = 0; + virtual EGame GetGame() const =0; + virtual ERegion GetRegion() const =0; + virtual bool IsPAL() const = 0; + virtual bool IsJapanese() const = 0; + virtual bool IsUSA() const = 0; + virtual bool IsTrilogy() const = 0; + virtual std::string_view GetVersionString() const=0; }; } // namespace urde diff --git a/Runtime/IOStreams.cpp b/Runtime/IOStreams.cpp index 39ba621a0..2b76b7e67 100644 --- a/Runtime/IOStreams.cpp +++ b/Runtime/IOStreams.cpp @@ -8,7 +8,7 @@ namespace urde { #if DUMP_BITS static void PrintBinary(u32 val, u32 count) { for (u32 i = 0; i < count; ++i) { - fmt::print(fmt("{}"), (val >> (count - i - 1)) & 0x1); + fmt::print(FMT_STRING("{}"), (val >> (count - i - 1)) & 0x1); } } #endif @@ -57,7 +57,7 @@ s32 CBitStreamReader::ReadEncoded(u32 bitCount) { #if DUMP_BITS std::fputs("READ ", stdout); PrintBinary(ret, bitCount); - fmt::print(fmt(" {} {}\n"), pos, boff); + fmt::print(FMT_STRING(" {} {}\n"), pos, boff); #endif return ret; @@ -67,7 +67,7 @@ void CBitStreamWriter::WriteEncoded(u32 val, u32 bitCount) { #if DUMP_BITS std::fputs("WRITE ", stdout); PrintBinary(val, bitCount); - fmt::print(fmt(" {} {}\n"), position(), x18_bitOffset); + fmt::print(FMT_STRING(" {} {}\n"), position(), x18_bitOffset); #endif const s32 shiftAmt = x18_bitOffset - s32(bitCount); diff --git a/Runtime/IOStreams.hpp b/Runtime/IOStreams.hpp index 8837e61fe..1fe75f4bd 100644 --- a/Runtime/IOStreams.hpp +++ b/Runtime/IOStreams.hpp @@ -43,7 +43,7 @@ class CBitStreamWriter : public athena::io::MemoryWriter { public: static constexpr u32 GetBitCount(u32 maxVal) { return CBitStreamReader::GetBitCount(maxVal); } - CBitStreamWriter(atUint8* data = nullptr, atUint64 length = 0x10) : MemoryWriter(data, length) {} + explicit CBitStreamWriter(atUint8* data = nullptr, atUint64 length = 0x10) : MemoryWriter(data, length) {} void WriteEncoded(u32 val, u32 bitCount); @@ -62,7 +62,7 @@ class CZipInputStream : public CInputStream { z_stream x30_zstrm = {}; public: - CZipInputStream(std::unique_ptr&& strm); + explicit CZipInputStream(std::unique_ptr&& strm); ~CZipInputStream() override; atUint64 readUBytesToBuf(void* buf, atUint64 len) override; void seek(atInt64, athena::SeekOrigin) override {} diff --git a/Runtime/Input/CRumbleGenerator.cpp b/Runtime/Input/CRumbleGenerator.cpp index 7887c405d..ce2ee350a 100644 --- a/Runtime/Input/CRumbleGenerator.cpp +++ b/Runtime/Input/CRumbleGenerator.cpp @@ -24,8 +24,9 @@ void CRumbleGenerator::Update(float dt) { if (!b_tp) { b_tp = true; s_tp = now; - } else + } else { ms = std::chrono::duration_cast(now - s_tp).count(); + } #endif if (!xf0_24_disabled) { @@ -38,7 +39,7 @@ void CRumbleGenerator::Update(float dt) { if (xe0_commandArray[i] != EMotorState::Stop) { #if PWM_MONITOR s_tp = now; - printf("%lldms ON\n", ms); + fmt::print(FMT_STRING("{}ms ON\n"), ms); #endif xe0_commandArray[i] = EMotorState::Stop; updated = true; @@ -50,7 +51,7 @@ void CRumbleGenerator::Update(float dt) { if (xe0_commandArray[i] != EMotorState::Rumble) { #if PWM_MONITOR s_tp = now; - printf("%lldms Off\n", ms); + fmt::print(FMT_STRING("{}ms Off\n"), ms); #endif xe0_commandArray[i] = EMotorState::Rumble; updated = true; @@ -62,7 +63,7 @@ void CRumbleGenerator::Update(float dt) { if (xe0_commandArray[i] != EMotorState::Stop) { #if PWM_MONITOR s_tp = now; - printf("%lldms ON\n", ms); + fmt::print(FMT_STRING("{}ms ON\n"), ms); #endif xe0_commandArray[i] = EMotorState::Stop; updated = true; diff --git a/Runtime/Input/CRumbleVoice.hpp b/Runtime/Input/CRumbleVoice.hpp index 719aab552..b0dd7978a 100644 --- a/Runtime/Input/CRumbleVoice.hpp +++ b/Runtime/Input/CRumbleVoice.hpp @@ -32,15 +32,10 @@ struct SAdsrData { 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; - }; - u32 dummy = 0; - }; + bool x18_24_hasSustain : 1; + bool x18_25_autoRelease : 1; - constexpr SAdsrData() noexcept { x18_24_hasSustain = false; x18_25_autoRelease = false; }; + constexpr SAdsrData() noexcept : x18_24_hasSustain(false), x18_25_autoRelease(false) {} constexpr SAdsrData(float attackGain, float autoReleaseDur, float attackDur, float decayDur, float sustainGain, float releaseDur, bool hasSustain, bool autoRelease) noexcept : x0_attackGain(attackGain) @@ -48,10 +43,9 @@ struct SAdsrData { , x8_attackDur(attackDur) , xc_decayDur(decayDur) , x10_sustainGain(sustainGain) - , x14_releaseDur(releaseDur) { - x18_24_hasSustain = hasSustain; - x18_25_autoRelease = autoRelease; - } + , x14_releaseDur(releaseDur) + , x18_24_hasSustain(hasSustain) + , x18_25_autoRelease(autoRelease) {} }; struct SAdsrDelta { diff --git a/Runtime/MP1/CFrontEndUI.cpp b/Runtime/MP1/CFrontEndUI.cpp index 6fedaf6f3..30065b8af 100644 --- a/Runtime/MP1/CFrontEndUI.cpp +++ b/Runtime/MP1/CFrontEndUI.cpp @@ -125,6 +125,16 @@ void CFrontEndUI::SNewFileSelectFrame::FinishedLoading() { 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(); + + // TODO: Implement language menu + auto langPair = FindTextPanePair(x1c_loadedFrame, "textpane_lang"); + if (langPair.x0_panes[0] != nullptr) { + langPair.x0_panes[0]->SetIsSelectable(false); + langPair.x0_panes[0]->SetIsVisible(false); + langPair.x0_panes[1]->SetIsSelectable(false); + langPair.x0_panes[1]->SetIsVisible(false); + } + x28_textpane_erase = FindTextPanePair(x1c_loadedFrame, "textpane_erase"); x38_textpane_gba = FindTextPanePair(x1c_loadedFrame, "textpane_gba"); x30_textpane_cheats = FindTextPanePair(x1c_loadedFrame, "textpane_cheats"); @@ -134,10 +144,11 @@ void CFrontEndUI::SNewFileSelectFrame::FinishedLoading() { 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)); + FindAndSetPairText(x1c_loadedFrame, "textpane_title", + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 97 : 92)); CGuiTextPane* proceed = static_cast(x1c_loadedFrame->FindWidget("textpane_proceed")); if (proceed) - proceed->TextSupport().SetText(g_MainStringTable->GetString(85)); + proceed->TextSupport().SetText(g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 85 : 79)); x40_tablegroup_popup->SetIsVisible(false); x40_tablegroup_popup->SetIsActive(false); x40_tablegroup_popup->SetVertical(false); @@ -307,7 +318,8 @@ void CFrontEndUI::SNewFileSelectFrame::HandleActiveChange(CGuiTableGroup* active tbDetails[i].percent = data->x18_itemPercent; } } - m_touchBar.SetFileSelectPhase(tbDetails.data(), x8_subMenu == ESubMenu::EraseGame, CSlideShow::SlideShowGalleryFlags()); + m_touchBar.SetFileSelectPhase(tbDetails.data(), x8_subMenu == ESubMenu::EraseGame, + CSlideShow::SlideShowGalleryFlags()); } else if (active == x40_tablegroup_popup) { if (x8_subMenu == ESubMenu::EraseGamePopup) m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::EraseBack); @@ -344,8 +356,10 @@ void CFrontEndUI::SNewFileSelectFrame::ActivateEraseGamePopup() { x8_subMenu = ESubMenu::EraseGamePopup; HandleActiveChange(x40_tablegroup_popup); - x48_textpane_popupadvance.SetPairText(g_MainStringTable->GetString(95)); - x50_textpane_popupcancel.SetPairText(g_MainStringTable->GetString(38)); + x48_textpane_popupadvance.SetPairText( + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 95 : 89)); + x50_textpane_popupcancel.SetPairText( + g_MainStringTable->GetString(38)); // This string is unmodified in PAL/NTSCJ/Trilogy 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); @@ -384,19 +398,25 @@ void CFrontEndUI::SNewFileSelectFrame::ActivateNewGamePopup() { 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)); + x48_textpane_popupadvance.SetPairText( + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 102 : 96)); + x50_textpane_popupcancel.SetPairText( + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 94 : 88)); + x58_textpane_popupextra.SetPairText( + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 101 : 95)); CGuiWidget* worker = x40_tablegroup_popup->GetWorkerWidget(2); 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)); + x48_textpane_popupadvance.SetPairText( + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 67 : 61)); + x50_textpane_popupcancel.SetPairText( + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 94 : 88)); x44_model_dash7->SetVisibility(false, ETraversalMode::Children); } - x60_textpane_cancel->TextSupport().SetText(g_MainStringTable->GetString(82)); + x60_textpane_cancel->TextSupport().SetText( + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 82 : 76)); } void CFrontEndUI::SNewFileSelectFrame::ResetFrame() { @@ -436,7 +456,8 @@ void CFrontEndUI::SNewFileSelectFrame::ActivateErase() { } } - x60_textpane_cancel->TextSupport().SetText(g_MainStringTable->GetString(82)); + x60_textpane_cancel->TextSupport().SetText( + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 82 : 76)); HandleActiveChange(x20_tablegroup_fileselect); } @@ -456,13 +477,19 @@ void CFrontEndUI::SNewFileSelectFrame::ClearFrameContents() { } } - 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); + StartTextAnimating(x28_textpane_erase.x0_panes[0], g_MainStringTable->GetString(38), + 60.f); // This string is unmodified in PAL/NTSCJ/Trilogy + StartTextAnimating(x38_textpane_gba.x0_panes[0], g_MainStringTable->GetString(37), + 60.f); // This string is unmodified in PAL/NTSCJ/Trilogy + StartTextAnimating(x30_textpane_cheats.x0_panes[0], + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 96 : 90), 60.f); - 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); + StartTextAnimating(x28_textpane_erase.x0_panes[1], g_MainStringTable->GetString(38), + 60.f); // This string is unmodified in PAL/NTSCJ/Trilogy + StartTextAnimating(x38_textpane_gba.x0_panes[1], g_MainStringTable->GetString(37), + 60.f); // This string is unmodified in PAL/NTSCJ/Trilogy + StartTextAnimating(x30_textpane_cheats.x0_panes[1], + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 96 : 90), 60.f); if (hasSave) { x28_textpane_erase.x0_panes[0]->SetIsSelectable(true); @@ -489,6 +516,27 @@ void CFrontEndUI::SNewFileSelectFrame::ClearFrameContents() { HandleActiveChange(x20_tablegroup_fileselect); } +std::u16string GetTimeString(const CGameState::GameFileStateInfo* data) { + if (data) { + auto pt = std::div(data->x0_playTime, 3600); +#if FE_USE_SECONDS_IN_ELAPSED + return fmt::format(FMT_STRING(u"{:02d}:{:02d}:{:02d}"), pt.quot, pt.rem / 60, pt.rem % 60); +#else + return fmt::format(FMT_STRING(u"{:02d}:{:02d}"), pt.quot, pt.rem / 60); +#endif + } + if (!g_Main->IsUSA() || g_Main->IsTrilogy()) + return g_MainStringTable->GetString(53); + return g_MainStringTable->GetString(52); +} + +std::u16string GetElapsedString(const CGameState::GameFileStateInfo* data) { + if (!g_Main->IsUSA() || g_Main->IsTrilogy()) + return g_MainStringTable->GetString(data ? 55 : 54); + + return std::u16string(g_MainStringTable->GetString(data ? 54 : 53)); +} + void CFrontEndUI::SNewFileSelectFrame::SetupFrameContents() { for (size_t i = 0; i < x64_fileSelections.size(); ++i) { SFileMenuOption& option = x64_fileSelections[i]; @@ -508,8 +556,12 @@ void CFrontEndUI::SNewFileSelectFrame::SetupFrameContents() { case 0: // Completion percent if (data) { - std::u16string fileStr = g_MainStringTable->GetString((data->x20_hardMode ? 106 : 39) + int(i)); - str = fileStr + fmt::format(fmt(u" {:02d}%"), data->x18_itemPercent); + int strIdx = (data->x20_hardMode ? 106 : 39); + if ((!g_Main->IsUSA() || g_Main->IsTrilogy())) + strIdx = (strIdx == 106 ? 100 : 40); + + std::u16string fileStr = g_MainStringTable->GetString(strIdx + int(i)); + str = fileStr + fmt::format(FMT_STRING(u" {:02d}%"), data->x18_itemPercent); break; } str = g_MainStringTable->GetString(36); @@ -524,38 +576,38 @@ void CFrontEndUI::SNewFileSelectFrame::SetupFrameContents() { } break; } - str = g_MainStringTable->GetString(51); + str = g_MainStringTable->GetString(51 + int(!g_Main->IsUSA() || g_Main->IsTrilogy())); break; -#if FE_USE_SECONDS_IN_ELAPSED - case 2: - // Formatted time - if (data) { - auto pt = std::div(data->x0_playTime, 3600); - str = fmt::format(fmt(u"{:02d}:{:02d}:{:02d}"), pt.quot, pt.rem / 60, pt.rem % 60); - break; - } - str = g_MainStringTable->GetString(52); - break; - case 3: - // "Elapsed" - str = std::u16string(u" ") + std::u16string(g_MainStringTable->GetString(data ? 54 : 53)); - break; -#else 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; +#if FE_USE_SECONDS_IN_ELAPSED + if (!g_Main->IsUSA() || g_Main->IsTrilogy()) { + str = GetElapsedString(data); + } else { + str = GetTimeString(data); + } +#else + if (!g_Main->IsUSA() || g_Main->IsTrilogy()) { + str = GetElapsedString(data); + } else { + str = GetTimeString(data); } - str = g_MainStringTable->GetString(52); - break; - - case 3: - // "Elapsed" - str = g_MainStringTable->GetString(data ? 54 : 53); - break; #endif + break; + case 3: +#if FE_USE_SECONDS_IN_ELAPSED + if (!g_Main->IsUSA() || g_Main->IsTrilogy()) { + str = GetTimeString(data); + } else { + str = std::u16string(u" ") + GetElapsedString(data); + } +#else + if (!g_Main->IsUSA() || g_Main->IsTrilogy()) { + str = GetTimeString(data); + } else { + str = std::u16string(u" ") + GetElapsedString(data); + } +#endif + break; default: break; @@ -647,11 +699,11 @@ void CFrontEndUI::SNewFileSelectFrame::DoFileMenuAdvance(CGuiTableGroup* caller) CFrontEndUI::SFileMenuOption CFrontEndUI::SNewFileSelectFrame::FindFileSelectOption(CGuiFrame* frame, int idx) { SFileMenuOption ret; - ret.x0_base = frame->FindWidget(fmt::format(fmt("basewidget_file{}"), idx)); - ret.x4_textpanes[0] = FindTextPanePair(frame, fmt::format(fmt("textpane_filename{}"), idx)); - ret.x4_textpanes[1] = FindTextPanePair(frame, fmt::format(fmt("textpane_world{}"), idx)); - ret.x4_textpanes[2] = FindTextPanePair(frame, fmt::format(fmt("textpane_playtime{}"), idx)); - ret.x4_textpanes[3] = FindTextPanePair(frame, fmt::format(fmt("textpane_date{}"), idx)); + ret.x0_base = frame->FindWidget(fmt::format(FMT_STRING("basewidget_file{}"), idx)); + ret.x4_textpanes[0] = FindTextPanePair(frame, fmt::format(FMT_STRING("textpane_filename{}"), idx)); + ret.x4_textpanes[1] = FindTextPanePair(frame, fmt::format(FMT_STRING("textpane_world{}"), idx)); + ret.x4_textpanes[2] = FindTextPanePair(frame, fmt::format(FMT_STRING("textpane_playtime{}"), idx)); + ret.x4_textpanes[3] = FindTextPanePair(frame, fmt::format(FMT_STRING("textpane_date{}"), idx)); return ret; } @@ -681,54 +733,54 @@ void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::SetUIText(EUIType tp) { switch (tp) { case EUIType::InsertPak: - instructions = 73; // Insert Game Pak - no = 82; - yes = 83; + instructions = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 73 : 67; // Insert Game Pak + no = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 82 : 76; + yes = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 83 : 77; pakoutVisible = true; circleGbaVisible = true; break; case EUIType::ConnectSocket: - instructions = 68; // Connect socket - no = 82; - yes = 83; + instructions = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 68 : 62; // Connect socket + no = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 82 : 76; + yes = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 83 : 77; cableVisible = true; circleGcVisible = true; circleGbaVisible = true; break; case EUIType::PressStartAndSelect: - instructions = 74; // Hold start and select - no = 82; - yes = 83; + instructions = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 74 : 68; // Hold start and select + no = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 82 : 76; + yes = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 83 : 77; cableVisible = true; circleStartVisible = true; gbaScreenVisible = true; break; case EUIType::BeginLink: - instructions = 75; // Begin link? - no = 82; - yes = 83; + instructions = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 75 : 69; // Begin link? + no = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 82 : 76; + yes = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 83 : 77; cableVisible = true; gbaScreenVisible = true; break; case EUIType::TurnOffGBA: - instructions = 76; // Turn off GBA - no = 82; - yes = 83; + instructions = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 76 : 70; // Turn off GBA + no = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 82 : 76; + yes = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 83 : 77; cableVisible = true; gbaScreenVisible = true; circleStartVisible = true; break; case EUIType::Linking: x4_gbaSupport->StartLink(); - instructions = 72; // Linking + instructions = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 72 : 66; // Linking cableVisible = true; gbaScreenVisible = true; connectVisible = true; break; case EUIType::LinkFailed: - instructions = 69; // Link failed - no = 82; - yes = 83; + instructions = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 69 : 63; // Link failed + no = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 82 : 76; + yes = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 83 : 77; cableVisible = true; circleGcVisible = true; circleGbaVisible = true; @@ -736,8 +788,8 @@ void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::SetUIText(EUIType tp) { gbaScreenVisible = true; break; case EUIType::LinkCompleteOrLinking: - yes = 83; - instructions = x40_linkInProgress + 71; // Complete or linking + yes = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 83 : 77; + instructions = x40_linkInProgress + (g_Main->IsUSA() && !g_Main->IsTrilogy() ? 71 : 65); // Complete or linking cableVisible = true; gbaScreenVisible = true; break; @@ -775,8 +827,9 @@ void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::SetUIText(EUIType tp) { x0_uiType = tp; } -CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EAction CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::ProcessUserInput( - const CFinalInput& input, bool linkInProgress, CFrontEndUITouchBar::EAction tbAction) { +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); @@ -790,9 +843,7 @@ CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EAction CFrontEndUI::SFusionBonus case EUIType::LinkFailed: case EUIType::LinkCompleteOrLinking: case EUIType::TurnOffGBA: - if (input.PA() || - input.PSpecialKey(boo::ESpecialKey::Enter) || - input.PMouseButton(boo::EMouseButton::Primary) || + if (input.PA() || input.PSpecialKey(boo::ESpecialKey::Enter) || input.PMouseButton(boo::EMouseButton::Primary) || tbAction == CFrontEndUITouchBar::EAction::Confirm) { PlayAdvanceSfx(); SetUIText(NextLinkUI[size_t(x0_uiType)]); @@ -874,18 +925,23 @@ void CFrontEndUI::SFusionBonusFrame::FinishedLoading() { 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((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 66 : 60)); + FindAndSetPairText(x24_loadedFrame, "textpane_fusionsuit", + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 63 : 57)); + FindAndSetPairText(x24_loadedFrame, "textpane_fusionsuitno", + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 65 : 59)); + FindAndSetPairText(x24_loadedFrame, "textpane_fusionsuityes", + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 64 : 58)); + FindAndSetPairText(x24_loadedFrame, "textpane_title", + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 100 : 94)); static_cast(x24_loadedFrame->FindWidget("textpane_proceed")) ->TextSupport() - .SetText(g_MainStringTable->GetString(85)); + .SetText(g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 85 : 79)); static_cast(x24_loadedFrame->FindWidget("textpane_cancel")) ->TextSupport() - .SetText(g_MainStringTable->GetString(82)); + .SetText(g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 82 : 76)); x2c_tablegroup_fusionsuit->SetIsActive(false); x2c_tablegroup_fusionsuit->SetIsVisible(false); @@ -949,22 +1005,27 @@ void CFrontEndUI::SFusionBonusFrame::Update(float dt, CSaveGameScreen* saveUI) { if (x28_tablegroup_options->GetUserSelection() == 1) { /* Fusion Suit */ if (x3a_mpNotComplete) - instructionStr = g_MainStringTable->GetString(80); // MP not complete + instructionStr = + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 80 : 74); // MP not complete else if (!showFusionSuit) - instructionStr = g_MainStringTable->GetString(78); // To enable fusion suit + instructionStr = + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 78 : 72); // To enable fusion suit } else { /* NES Metroid */ if (x39_fusionNotComplete) - instructionStr = g_MainStringTable->GetString(79); // You have not completed fusion + instructionStr = g_MainStringTable->GetString( + (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 79 : 73); // You have not completed fusion else if (!g_GameState->SystemOptions().GetPlayerBeatFusion()) - instructionStr = g_MainStringTable->GetString(77); // To play NES Metroid + instructionStr = + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 77 : 71); // To play NES Metroid } x30_textpane_instructions.SetPairText(instructionStr); } -CFrontEndUI::SFusionBonusFrame::EAction CFrontEndUI::SFusionBonusFrame::ProcessUserInput( - const CFinalInput& input, CSaveGameScreen* sui, CFrontEndUITouchBar::EAction tbAction) { +CFrontEndUI::SFusionBonusFrame::EAction +CFrontEndUI::SFusionBonusFrame::ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui, + CFrontEndUITouchBar::EAction tbAction) { x8_action = EAction::None; if (sui) @@ -1111,14 +1172,14 @@ void CFrontEndUI::SGuiTextPair::SetPairText(std::u16string_view str) { CFrontEndUI::SGuiTextPair CFrontEndUI::FindTextPanePair(CGuiFrame* frame, std::string_view name) { SGuiTextPair ret; ret.x0_panes[0] = static_cast(frame->FindWidget(name)); - ret.x0_panes[1] = static_cast(frame->FindWidget(fmt::format(fmt("{}b"), name))); + ret.x0_panes[1] = static_cast(frame->FindWidget(fmt::format(FMT_STRING("{}b"), name))); return ret; } void CFrontEndUI::FindAndSetPairText(CGuiFrame* frame, std::string_view name, std::u16string_view str) { CGuiTextPane* w1 = static_cast(frame->FindWidget(name)); w1->TextSupport().SetText(str); - CGuiTextPane* w2 = static_cast(frame->FindWidget(fmt::format(fmt("{}b"), name))); + CGuiTextPane* w2 = static_cast(frame->FindWidget(fmt::format(FMT_STRING("{}b"), name))); w2->TextSupport().SetText(str); } @@ -1126,18 +1187,32 @@ 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"); + //TODO: HACK: Implement language menu so this isn't necessary + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + x1c_gbaPair = FindTextPanePair(x14_loadedFrme, "textpane_gba"); + } else { + x1c_gbaPair = FindTextPanePair(x14_loadedFrme, "textpane_lang"); + } x1c_gbaPair.SetPairText(g_MainStringTable->GetString(37)); - x24_cheatPair = FindTextPanePair(x14_loadedFrme, "textpane_cheats"); - x24_cheatPair.SetPairText(g_MainStringTable->GetString(96)); + //TODO: HACK: Implement language menu so this isn't necessary + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + x24_cheatPair = FindTextPanePair(x14_loadedFrme, "textpane_cheats"); + } else { + x24_cheatPair = FindTextPanePair(x14_loadedFrme, "textpane_options"); + } + x24_cheatPair.SetPairText(g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 96 : 90)); - 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)); + FindAndSetPairText(x14_loadedFrme, "textpane_start", + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 67 : 61)); + //TODO: HACK: Implement language menu so this isn't necessary + FindAndSetPairText(x14_loadedFrme, (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? "textpane_options" : "textpane_gba", + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 94 : 88)); + FindAndSetPairText(x14_loadedFrme, "textpane_title", + g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 98 : 92)); CGuiTextPane* proceed = static_cast(x14_loadedFrme->FindWidget("textpane_proceed")); if (proceed) - proceed->TextSupport().SetText(g_MainStringTable->GetString(85)); + proceed->TextSupport().SetText(g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 85 : 79)); x18_tablegroup_mainmenu->SetMenuAdvanceCallback([this](CGuiTableGroup* caller) { DoAdvance(caller); }); x18_tablegroup_mainmenu->SetMenuSelectionChangeCallback( @@ -1220,7 +1295,8 @@ void CFrontEndUI::SFrontEndFrame::HandleActiveChange(CGuiTableGroup* active) { active->SetColors(zeus::skWhite, zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); } -void CFrontEndUI::SFrontEndFrame::DoCancel(CGuiTableGroup* caller) { /* Intentionally empty */ } +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); @@ -1260,10 +1336,9 @@ CFrontEndUI::SNesEmulatorFrame::SNesEmulatorFrame() { 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::skWhite, zeus::skBlack, - zeus::skWhite, 0, 0, g_SimplePool, - CGuiWidget::EGuiModelDrawFlags::Alpha); - xc_textSupport->SetText(g_MainStringTable->GetString(103)); + xc_textSupport = std::make_unique(deface->id, props, zeus::skWhite, zeus::skBlack, zeus::skWhite, 0, + 0, g_SimplePool, CGuiWidget::EGuiModelDrawFlags::Alpha); + xc_textSupport->SetText(g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 103 : 97)); xc_textSupport->AutoSetExtent(); xc_textSupport->ClearRenderBuffer(); } @@ -1412,10 +1487,9 @@ void CFrontEndUI::SNesEmulatorFrame::Draw(CSaveGameScreen* saveUi) const { } } -CFrontEndUI::SOptionsFrontEndFrame::SOptionsFrontEndFrame() { +CFrontEndUI::SOptionsFrontEndFrame::SOptionsFrontEndFrame() : x134_24_visible(true), x134_25_exitOptions(false) { x4_frme = g_SimplePool->GetObj("FRME_OptionsFrontEnd"); x10_pauseScreen = g_SimplePool->GetObj("STRG_PauseScreen"); - x134_24_visible = true; } void CFrontEndUI::SOptionsFrontEndFrame::DoSliderChange(CGuiSliderGroup* caller, float value) { @@ -1530,10 +1604,11 @@ void CFrontEndUI::SOptionsFrontEndFrame::HandleRightSelectionChange() { void CFrontEndUI::SOptionsFrontEndFrame::SetRightUIText() { const int userSel = x24_tablegroup_leftmenu->GetUserSelection(); - const auto& options = GameOptionsRegistry[userSel]; + const auto& options = + (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? GameOptionsRegistry[userSel] : GameOptionsRegistryNew[userSel]; for (int i = 0; i < 5; ++i) { - std::string name = fmt::format(fmt("textpane_right{}"), i); + std::string name = fmt::format(FMT_STRING("textpane_right{}"), i); if (i < static_cast(options.first)) { FindTextPanePair(x1c_loadedFrame, name).SetPairText(x20_loadedPauseStrg->GetString(options.second[i].stringId)); x28_tablegroup_rightmenu->GetWorkerWidget(i)->SetIsSelectable(true); @@ -1579,24 +1654,31 @@ void CFrontEndUI::SOptionsFrontEndFrame::FinishedLoading() { x34_slidergroup_slider->SetSelectionChangedCallback( [this](CGuiSliderGroup* caller, float value) { DoSliderChange(caller, value); }); - 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_double0") + .SetPairText(x20_loadedPauseStrg->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 95 : 98)); // Off + FindTextPanePair(x1c_loadedFrame, "textpane_double1") + .SetPairText(x20_loadedPauseStrg->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 94 : 97)); // On + FindTextPanePair(x1c_loadedFrame, "textpane_triple0") + .SetPairText(x20_loadedPauseStrg->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 96 : 99)); // Mono + FindTextPanePair(x1c_loadedFrame, "textpane_triple1") + .SetPairText(x20_loadedPauseStrg->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 97 : 100)); // Stereo + FindTextPanePair(x1c_loadedFrame, "textpane_triple2") + .SetPairText(x20_loadedPauseStrg->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 98 : 101)); // Dolby - FindTextPanePair(x1c_loadedFrame, "textpane_title").SetPairText(g_MainStringTable->GetString(99)); // OPTIONS + FindTextPanePair(x1c_loadedFrame, "textpane_title") + .SetPairText(g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 99 : 93)); // OPTIONS if (CGuiTextPane* proceed = static_cast(x1c_loadedFrame->FindWidget("textpane_proceed"))) - proceed->TextSupport().SetText(g_MainStringTable->GetString(85)); + proceed->TextSupport().SetText(g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 85 : 79)); if (CGuiTextPane* cancel = static_cast(x1c_loadedFrame->FindWidget("textpane_cancel"))) - cancel->TextSupport().SetText(g_MainStringTable->GetString(82)); + cancel->TextSupport().SetText(g_MainStringTable->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 82 : 76)); // Visor, Display, Sound, Controller for (int i = 0; i < 4; ++i) { - const std::string name = fmt::format(fmt("textpane_filename{}"), i); - FindTextPanePair(x1c_loadedFrame, name).SetPairText(x20_loadedPauseStrg->GetString(16 + i)); + const std::string name = fmt::format(FMT_STRING("textpane_filename{}"), i); + FindTextPanePair(x1c_loadedFrame, name) + .SetPairText(x20_loadedPauseStrg->GetString((g_Main->IsUSA() && !g_Main->IsTrilogy() ? 16 : 18) + i)); } x2c_tablegroup_double->SetVertical(false); @@ -1767,7 +1849,9 @@ void CFrontEndUI::StartSlideShow(CArchitectureQueue& queue) { queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, std::make_shared())); } -std::string CFrontEndUI::GetAttractMovieFileName(int idx) { return fmt::format(fmt("Video/attract{}.thp"), idx); } +std::string CFrontEndUI::GetAttractMovieFileName(int idx) { + return fmt::format(FMT_STRING("Video/attract{}.thp"), idx); +} std::string CFrontEndUI::GetNextAttractMovieFileName() { std::string ret = GetAttractMovieFileName(xbc_nextAttract); @@ -2092,10 +2176,8 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue& if (x50_curScreen != x54_nextScreen) { if (x54_nextScreen == EScreen::AttractMovie && - (input.PStart() || input.PA() || - input.PSpecialKey(boo::ESpecialKey::Esc) || - input.PSpecialKey(boo::ESpecialKey::Enter) || - input.PMouseButton(boo::EMouseButton::Primary) || + (input.PStart() || input.PA() || input.PSpecialKey(boo::ESpecialKey::Esc) || + input.PSpecialKey(boo::ESpecialKey::Enter) || input.PMouseButton(boo::EMouseButton::Primary) || touchBarAction == CFrontEndUITouchBar::EAction::Start)) { /* Player wants to return to opening credits from attract movie */ SetFadeBlackTimer(std::min(1.f, x58_fadeBlackTimer)); @@ -2103,10 +2185,8 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue& return; } - if (input.PA() || input.PStart() || - input.PSpecialKey(boo::ESpecialKey::Esc) || - input.PSpecialKey(boo::ESpecialKey::Enter) || - input.PMouseButton(boo::EMouseButton::Primary) || + if (input.PA() || input.PStart() || input.PSpecialKey(boo::ESpecialKey::Esc) || + input.PSpecialKey(boo::ESpecialKey::Enter) || input.PMouseButton(boo::EMouseButton::Primary) || 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 */ @@ -2117,10 +2197,8 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue& } } else { if (x50_curScreen == EScreen::Title) { - if (input.PStart() || input.PA() || - input.PSpecialKey(boo::ESpecialKey::Esc) || - input.PSpecialKey(boo::ESpecialKey::Enter) || - input.PMouseButton(boo::EMouseButton::Primary) || + if (input.PStart() || input.PA() || input.PSpecialKey(boo::ESpecialKey::Esc) || + input.PSpecialKey(boo::ESpecialKey::Enter) || input.PMouseButton(boo::EMouseButton::Primary) || touchBarAction == CFrontEndUITouchBar::EAction::Start) { if (x58_fadeBlackTimer < 30.f - g_tweakGame->GetPressStartDelay()) { /* Proceed to file select UI */ diff --git a/Runtime/MP1/CFrontEndUI.hpp b/Runtime/MP1/CFrontEndUI.hpp index b1c2aac75..046f0522a 100644 --- a/Runtime/MP1/CFrontEndUI.hpp +++ b/Runtime/MP1/CFrontEndUI.hpp @@ -279,13 +279,8 @@ public: 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; - }; - }; + bool x134_24_visible : 1; + bool x134_25_exitOptions : 1; std::unique_ptr m_touchBar; bool m_touchBarInValue = false; diff --git a/Runtime/MP1/CInGameGuiManager.cpp b/Runtime/MP1/CInGameGuiManager.cpp index effe4dd60..31a4dd461 100644 --- a/Runtime/MP1/CInGameGuiManager.cpp +++ b/Runtime/MP1/CInGameGuiManager.cpp @@ -178,7 +178,11 @@ CInGameGuiManager::CInGameGuiManager(CStateManager& stateMgr, CArchitectureQueue , x1c_rand(1234) , x20_faceplateDecor(stateMgr) , x50_deathDot(g_SimplePool->GetObj("TXTR_DeathDot")) -, x5c_pauseScreenDGRPs(LockPauseScreenDependencies()) { +, x5c_pauseScreenDGRPs(LockPauseScreenDependencies()) +, x1f8_24_(false) +, x1f8_25_playerAlive(true) +, x1f8_26_deferTransition(false) +, x1f8_27_exitSaveUI(true) { x1e0_helmetVisMode = g_tweakGui->GetHelmetVisMode(); x1e4_enableTargetingManager = g_tweakGui->GetEnableTargetingManager(); x1e8_enableAutoMapper = g_tweakGui->GetEnableAutoMapper(); @@ -187,9 +191,6 @@ CInGameGuiManager::CInGameGuiManager(CStateManager& stateMgr, CArchitectureQueue x1f4_visorStaticAlpha = stateMgr.GetPlayer().GetVisorStaticAlpha(); - x1f8_25_playerAlive = true; - x1f8_27_exitSaveUI = true; - xc8_inGameGuiDGRPs.reserve(InGameGuiDGRPs.size()); for (const char* const dgrp : InGameGuiDGRPs) { xc8_inGameGuiDGRPs.emplace_back(g_SimplePool->GetObj(dgrp)); diff --git a/Runtime/MP1/CInGameGuiManager.hpp b/Runtime/MP1/CInGameGuiManager.hpp index 76ba934f2..3009e4d34 100644 --- a/Runtime/MP1/CInGameGuiManager.hpp +++ b/Runtime/MP1/CInGameGuiManager.hpp @@ -95,6 +95,10 @@ private: EHudVisMode x1ec_hudVisMode; u32 x1f0_enablePlayerVisor; float x1f4_visorStaticAlpha; + bool x1f8_24_ : 1; + bool x1f8_25_playerAlive : 1; + bool x1f8_26_deferTransition : 1; + bool x1f8_27_exitSaveUI : 1; std::optional m_deathRenderTexQuad; std::optional m_deathDotQuad; @@ -102,16 +106,6 @@ private: 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); diff --git a/Runtime/MP1/CInventoryScreen.cpp b/Runtime/MP1/CInventoryScreen.cpp index cdc4d1a36..47082ad3c 100644 --- a/Runtime/MP1/CInventoryScreen.cpp +++ b/Runtime/MP1/CInventoryScreen.cpp @@ -1,61 +1,69 @@ #include "Runtime/MP1/CInventoryScreen.hpp" +#include + #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/GuiSys/CGuiModel.hpp" #include "Runtime/GuiSys/CGuiTableGroup.hpp" #include "Runtime/GuiSys/CGuiTextPane.hpp" #include "Runtime/Input/ControlMapper.hpp" +#include "Runtime/IMain.hpp" namespace urde::MP1 { - +namespace { struct SInventoryItem { u32 idx; u32 nameStrIdx; u32 entryStrIdx; }; -static const SInventoryItem ArmCannonItems[] = { +constexpr std::array ArmCannonItems{{ {0, 0x24, 0x46}, // Power Beam {1, 0x25, 0x48}, // Ice Beam {2, 0x26, 0x4a}, // Wave Beam {3, 0x27, 0x4c}, // Plasma Beam {4, 0x28, 0x4e}, // Phazon Beam -}; +}}; -static const SInventoryItem MorphballItems[] = { +constexpr std::array MorphballItems{{ {5, 0x2e, 0x57}, // Morph Ball {6, 0x2f, 0x58}, // Boost Ball {7, 0x30, 0x59}, // Spider Ball {8, 0x31, 0x5a}, // Morph Ball Bomb {9, 0x32, 0x5b}, // Power Bomb -}; +}}; -static const SInventoryItem SuitItems[] = { +constexpr std::array SuitItems{{ {10, 0x33, 0x52}, // Power Suit {11, 0x34, 0x53}, // Varia Suit {12, 0x35, 0x54}, // Gravity Suit {13, 0x36, 0x55}, // Phazon Suit {14, 0x37, 0x56}, // Energy Tank -}; +}}; -static const SInventoryItem VisorItems[] = { +constexpr std::array 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[] = { +constexpr std::array SecondaryItems{{ {19, 0x3c, 0x4f}, // Space Jump Boots {20, 0x3d, 0x50}, // Grapple Beam {21, 0x3e, 0x51}, // Missile Launcher {22, 0x3f, 0x5c}, // Charge Beam {23, 0x40, 0x5d}, // Beam Combo -}; +}}; -static const std::pair InventoryRegistry[] = { - {5, ArmCannonItems}, {5, MorphballItems}, {5, SuitItems}, {4, VisorItems}, {5, SecondaryItems}, -}; +constexpr std::array, 5> InventoryRegistry{{ + {ArmCannonItems.size(), ArmCannonItems.data()}, + {MorphballItems.size(), MorphballItems.data()}, + {SuitItems.size(), SuitItems.data()}, + {VisorItems.size(), VisorItems.data()}, + {SecondaryItems.size(), SecondaryItems.data()}, +}}; +} // Anonymous namespace CInventoryScreen::CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg, const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp) @@ -278,14 +286,22 @@ bool CInventoryScreen::HasLeftInventoryItem(int idx) const { void CInventoryScreen::VActivate() { for (int i = 0; i < 5; ++i) { if (HasLeftInventoryItem(i)) { - xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 10)); + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 10)); + } else { + xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 12)); + } } else { xa8_textpane_categories[i]->TextSupport().SetText(u"??????"); x70_tablegroup_leftlog->GetWorkerWidget(i)->SetIsSelectable(false); } } - x178_textpane_title->TextSupport().SetText(xc_pauseStrg.GetString(9)); + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + x178_textpane_title->TextSupport().SetText(xc_pauseStrg.GetString(9)); + } else { + x178_textpane_title->TextSupport().SetText(xc_pauseStrg.GetString(11)); + } x180_basewidget_yicon->SetVisibility(true, ETraversalMode::Children); } @@ -295,15 +311,22 @@ 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); + std::u16string entryText = xc_pauseStrg.GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? sel.entryStrIdx : sel.entryStrIdx + 3); 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); + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + 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); + } else { + entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::SuperMissile) ? 73 : 68); + entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::IceSpreader) ? 75 : 68); + entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::Wavebuster) ? 78 : 68); + entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::Flamethrower) ? 79 : 68); + } } x174_textpane_body->TextSupport().SetText(entryText, true); @@ -437,14 +460,14 @@ bool CInventoryScreen::IsRightInventoryItemEquipped(int idx) const { void CInventoryScreen::UpdateRightTable() { CPauseScreenBase::UpdateRightTable(); - const std::pair& category = InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()]; + const auto& [size, data] = 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)); + if (i < int(size)) { + if (HasRightInventoryItem(data[i].idx)) { + title->TextSupport().SetText(xc_pauseStrg.GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? data[i].nameStrIdx : data[i].nameStrIdx + 3)); x84_tablegroup_rightlog->GetWorkerWidget(i + 1)->SetIsSelectable(true); if (i < minSel) minSel = i; @@ -476,7 +499,7 @@ bool CInventoryScreen::ShouldRightTableAdvance() const { } u32 CInventoryScreen::GetRightTableCount() const { - return InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()].first; + return u32(InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()].first); } bool CInventoryScreen::IsRightLogDynamic() const { return true; } @@ -484,9 +507,9 @@ 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::skWhite : zeus::CColor(1.f, 0.71f)); - const std::pair& cat = InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()]; + const auto& [size, data] = InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()]; for (u32 i = 0; i < 5; ++i) { - if (i < cat.first && IsRightInventoryItemEquipped(cat.second[i].idx)) { + if (i < size && IsRightInventoryItemEquipped(data[i].idx)) { x15c_model_righttitledecos[i]->SetColor(g_tweakGuiColors->GetPauseItemBlueColor()); xd8_textpane_titles[i]->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemBlueColor()); } else { @@ -498,16 +521,17 @@ void CInventoryScreen::UpdateRightLogColors(bool active, const zeus::CColor& act 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 zeus::CColor actColor = g_tweakGuiColors->GetPauseItemAmberColor() * activeColor; + const 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) + const auto& [size, data] = InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()]; + for (s32 i = 0; i < 5; ++i) { + const bool act = i == idx && active; + if (i < int(size) && IsRightInventoryItemEquipped(data[i].idx) && act) { x8c_model_righthighlight->SetColor(g_tweakGuiColors->GetPauseItemBlueColor()); - else if (act) + } else if (act) { x8c_model_righthighlight->SetColor(actColor); + } x144_model_titles[i]->SetColor(act ? actColor : inactColor); } } diff --git a/Runtime/MP1/CLogBookScreen.cpp b/Runtime/MP1/CLogBookScreen.cpp index e665c0c16..f469b1722 100644 --- a/Runtime/MP1/CLogBookScreen.cpp +++ b/Runtime/MP1/CLogBookScreen.cpp @@ -14,7 +14,10 @@ namespace urde::MP1 { CLogBookScreen::CLogBookScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg) -: CPauseScreenBase(mgr, frame, pauseStrg, true) { +: CPauseScreenBase(mgr, frame, pauseStrg, true) +, x260_24_loaded(false) +, x260_25_inTextScroll(false) +, x260_26_exitTextScroll(false) { x19c_scanCompletes.resize(5); x200_viewScans.resize(5); x258_artifactDoll = std::make_unique(); @@ -177,7 +180,6 @@ bool CLogBookScreen::IsScanCategoryReady(CSaveWorld::EScanCategory category) con }); } - void CLogBookScreen::UpdateBodyText() { if (x10_mode != EMode::TextScroll) { x174_textpane_body->TextSupport().SetText(u""); @@ -198,7 +200,11 @@ void CLogBookScreen::UpdateBodyText() { if (IsArtifactCategorySelected()) { const int headIdx = GetSelectedArtifactHeadScanIndex(); if (headIdx >= 0 && g_GameState->GetPlayerState()->HasPowerUp(CPlayerState::EItemType(headIdx + 29))) { - accumStr = std::u16string(u"\n\n\n\n\n\n").append(g_MainStringTable->GetString(105)); + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + accumStr = std::u16string(u"\n\n\n\n\n\n").append(g_MainStringTable->GetString(105)); + } else { + accumStr = std::u16string(u"\n\n\n\n\n\n").append(g_MainStringTable->GetString(107)); + } } } @@ -212,10 +218,11 @@ void CLogBookScreen::UpdateBodyImagesAndText() { pane->SetAnimationParms(zeus::skZero2f, 0.f, 0.f); } - for (int i = 0; i < 4; ++i) { + for (size_t i = 0; i < CScannableObjectInfo::NumBuckets; ++i) { const CScannableObjectInfo::SBucket& bucket = scan->GetBucket(i); - if (bucket.x8_imagePos == UINT32_MAX) + if (bucket.x8_imagePos == UINT32_MAX) { 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, diff --git a/Runtime/MP1/CLogBookScreen.hpp b/Runtime/MP1/CLogBookScreen.hpp index 8b2892b7b..f782faf0f 100644 --- a/Runtime/MP1/CLogBookScreen.hpp +++ b/Runtime/MP1/CLogBookScreen.hpp @@ -13,7 +13,7 @@ namespace urde { class CPlayerState; class CScannableObjectInfo; class CStringTable; -} +} // namespace urde namespace urde::MP1 { class CArtifactDoll; @@ -25,18 +25,14 @@ class CLogBookScreen : public CPauseScreenBase { x200_viewScans; float x254_viewInterp = 0.f; std::unique_ptr x258_artifactDoll; - - 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; - }; + enum class ELeavePauseState { + InPause = 0, + LeavingPause = 1, + LeftPause = 2 + } x25c_leavePauseState = ELeavePauseState::InPause; + bool x260_24_loaded : 1; + bool x260_25_inTextScroll : 1; + bool x260_26_exitTextScroll : 1; void InitializeLogBook(); void UpdateRightTitles(); diff --git a/Runtime/MP1/CMFGame.cpp b/Runtime/MP1/CMFGame.cpp index affd3f57e..81d422198 100644 --- a/Runtime/MP1/CMFGame.cpp +++ b/Runtime/MP1/CMFGame.cpp @@ -1,5 +1,7 @@ #include "Runtime/MP1/CMFGame.hpp" +#include + #include "Runtime/CArchitectureQueue.hpp" #include "Runtime/MP1/CSamusHud.hpp" #include "Runtime/MP1/MP1.hpp" @@ -14,13 +16,16 @@ 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; +: CMFGameBase("CMFGame") +, x14_stateManager(stateMgr.lock()) +, x18_guiManager(guiMgr.lock()) +, x2a_24_initialized(false) +, x2a_25_samusAlive(true) { static_cast(*g_Main).SetMFGameBuilt(true); } CMFGame::~CMFGame() { - CMain& main = static_cast(*g_Main); + auto& main = static_cast(*g_Main); main.SetMFGameBuilt(false); main.SetScreenFading(false); CDecalManager::Reinitialize(); @@ -253,8 +258,9 @@ void CMFGame::EnterMapScreen() { x14_stateManager->SetInMapScreen(true); } -CMFGameLoader::CMFGameLoader() : CMFGameLoaderBase("CMFGameLoader") { - CMain* m = static_cast(g_Main); +CMFGameLoader::CMFGameLoader() +: CMFGameLoaderBase("CMFGameLoader"), x2c_24_initialized(false), x2c_25_transitionFinished(false) { + auto* m = static_cast(g_Main); switch (m->GetFlowState()) { case EFlowState::Default: case EFlowState::StateSetter: { @@ -282,16 +288,18 @@ CMFGameLoader::CMFGameLoader() : CMFGameLoaderBase("CMFGameLoader") { CMFGameLoader::~CMFGameLoader() = default; -static const char* LoadDepPAKs[] = {"TestAnim", "SamusGun", "SamGunFx", nullptr}; - void CMFGameLoader::MakeLoadDependencyList() { + static constexpr std::array loadDepPAKs{"TestAnim", "SamusGun", "SamGunFx"}; + std::vector tags; - for (int i = 0; LoadDepPAKs[i]; ++i) - g_ResFactory->GetTagListForFile(LoadDepPAKs[i], tags); + for (const auto pak : loadDepPAKs) { + g_ResFactory->GetTagListForFile(pak, tags); + } x1c_loadList.reserve(tags.size()); - for (const SObjectTag& tag : tags) + for (const SObjectTag& tag : tags) { x1c_loadList.push_back(g_SimplePool->GetObj(tag)); + } } CIOWin::EMessageReturn CMFGameLoader::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { diff --git a/Runtime/MP1/CMFGame.hpp b/Runtime/MP1/CMFGame.hpp index fe7d70ca3..d491089b1 100644 --- a/Runtime/MP1/CMFGame.hpp +++ b/Runtime/MP1/CMFGame.hpp @@ -23,13 +23,8 @@ class CMFGame : public CMFGameBase { 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; - }; + bool x2a_24_initialized : 1; + bool x2a_25_samusAlive : 1; CColoredQuadFilter m_fadeToBlack{EFilterType::Multiply}; @@ -57,14 +52,8 @@ 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; - }; + bool x2c_24_initialized : 1; + bool x2c_25_transitionFinished : 1; void MakeLoadDependencyList(); diff --git a/Runtime/MP1/CMemoryCardDriver.cpp b/Runtime/MP1/CMemoryCardDriver.cpp index 0cf7076e4..a8a1b2669 100644 --- a/Runtime/MP1/CMemoryCardDriver.cpp +++ b/Runtime/MP1/CMemoryCardDriver.cpp @@ -667,7 +667,7 @@ void CMemoryCardDriver::InitializeFileInfo() { ExportPersistentOptions(); OSCalendarTime time = CBasics::ToCalendarTime(std::chrono::system_clock::now()); - std::string timeString = fmt::format(fmt("{:02d}.{:02d}.{:02d} {:02d}:{:02d}"), + std::string timeString = fmt::format(FMT_STRING("{: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 "); diff --git a/Runtime/MP1/COptionsScreen.cpp b/Runtime/MP1/COptionsScreen.cpp index 0bb91fe3f..ae175de5f 100644 --- a/Runtime/MP1/COptionsScreen.cpp +++ b/Runtime/MP1/COptionsScreen.cpp @@ -1,5 +1,6 @@ #include "Runtime/MP1/COptionsScreen.hpp" +#include "Runtime/IMain.hpp" #include "Runtime/CArchitectureQueue.hpp" #include "Runtime/GuiSys/CGuiSliderGroup.hpp" #include "Runtime/GuiSys/CGuiTableGroup.hpp" @@ -154,8 +155,8 @@ void COptionsScreen::ProcessControllerInput(const CFinalInput& input) { CPauseScreenBase::ProcessControllerInput(input); CGameOptions::TryRestoreDefaults(input, x70_tablegroup_leftlog->GetUserSelection(), x1c_rightSel, false, rightClicked); - if (x70_tablegroup_leftlog->GetUserSelection() == 4 && (input.PA() || leftClicked || - input.PSpecialKey(boo::ESpecialKey::Enter))) + if (x70_tablegroup_leftlog->GetUserSelection() == 4 && + (input.PA() || leftClicked || input.PSpecialKey(boo::ESpecialKey::Enter))) x19c_quitGame = std::make_unique(EQuitType::QuitGame); } else { CPauseScreenBase::ResetMouseState(); @@ -177,10 +178,16 @@ void COptionsScreen::Draw(float transInterp, float totalAlpha, float yOff) { 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)); + for (int i = 0; i < 5; ++i) { + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 16)); + } else { + xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 18)); + } + } - x178_textpane_title->TextSupport().SetText(xc_pauseStrg.GetString(15)); + x178_textpane_title->TextSupport().SetText( + xc_pauseStrg.GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 15 : 17)); #if 0 for (int i=5 ; i<5 ; ++i) @@ -190,22 +197,23 @@ void COptionsScreen::VActivate() { x174_textpane_body->TextSupport().SetJustification(EJustification::Center); x174_textpane_body->TextSupport().SetVerticalJustification(EVerticalJustification::Bottom); + int stringOffset = (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 0 : 3; static_cast(x190_tablegroup_double->GetWorkerWidget(0)) ->TextSupport() - .SetText(xc_pauseStrg.GetString(95)); + .SetText(xc_pauseStrg.GetString(95 + stringOffset)); static_cast(x190_tablegroup_double->GetWorkerWidget(1)) ->TextSupport() - .SetText(xc_pauseStrg.GetString(94)); + .SetText(xc_pauseStrg.GetString(94 + stringOffset)); static_cast(x194_tablegroup_triple->GetWorkerWidget(0)) ->TextSupport() - .SetText(xc_pauseStrg.GetString(96)); + .SetText(xc_pauseStrg.GetString(96 + stringOffset)); static_cast(x194_tablegroup_triple->GetWorkerWidget(1)) ->TextSupport() - .SetText(xc_pauseStrg.GetString(97)); + .SetText(xc_pauseStrg.GetString(97 + stringOffset)); static_cast(x194_tablegroup_triple->GetWorkerWidget(2)) ->TextSupport() - .SetText(xc_pauseStrg.GetString(98)); + .SetText(xc_pauseStrg.GetString(98 + stringOffset)); x18c_slidergroup_slider->SetSelectionChangedCallback( [this](CGuiSliderGroup* caller, float value) { OnSliderChanged(caller, value); }); @@ -229,12 +237,15 @@ void COptionsScreen::ChangedMode(EMode oldMode) { void COptionsScreen::UpdateRightTable() { CPauseScreenBase::UpdateRightTable(); - const std::pair& category = GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()]; + const std::pair& category = + (g_Main->IsUSA() && !g_Main->IsTrilogy()) ? GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()] + : GameOptionsRegistryNew[x70_tablegroup_leftlog->GetUserSelection()]; for (int i = 0; i < 5; ++i) { - if (i < category.first) + if (i < category.first) { xd8_textpane_titles[i]->TextSupport().SetText(xc_pauseStrg.GetString(category.second[i].stringId)); - else + } else { xd8_textpane_titles[i]->TextSupport().SetText(u""); + } } } diff --git a/Runtime/MP1/CPauseScreen.cpp b/Runtime/MP1/CPauseScreen.cpp index 706156aa2..0d1af0369 100644 --- a/Runtime/MP1/CPauseScreen.cpp +++ b/Runtime/MP1/CPauseScreen.cpp @@ -224,17 +224,17 @@ void CPauseScreen::ProcessControllerInput(const CStateManager& mgr, const CFinal } x38_textpane_l1->TextSupport().SetText( - fmt::format(fmt("&image={};"), g_tweakPlayerRes->x74_lTrigger[ + fmt::format(FMT_STRING("&image={};"), g_tweakPlayerRes->x74_lTrigger[ ControlMapper::GetDigitalInput(ControlMapper::ECommands::PreviousPauseScreen, useInput) || m_lDown])); x3c_textpane_r->TextSupport().SetText( - fmt::format(fmt("&image={};"), g_tweakPlayerRes->x80_rTrigger[ + fmt::format(FMT_STRING("&image={};"), g_tweakPlayerRes->x80_rTrigger[ ControlMapper::GetDigitalInput(ControlMapper::ECommands::NextPauseScreen, useInput) || m_rDown])); x48_textpane_return->TextSupport().SetText( - fmt::format(fmt("&image={};"), g_tweakPlayerRes->x8c_startButton[useInput.DStart() || m_returnDown])); + fmt::format(FMT_STRING("&image={};"), g_tweakPlayerRes->x8c_startButton[useInput.DStart() || m_returnDown])); x50_textpane_back->TextSupport().SetText( - fmt::format(fmt("&image={};"), g_tweakPlayerRes->x98_aButton[useInput.DA() || m_backDown])); + fmt::format(FMT_STRING("&image={};"), g_tweakPlayerRes->x98_aButton[useInput.DA() || m_backDown])); x4c_textpane_next->TextSupport().SetText( - fmt::format(fmt("&image={};"), g_tweakPlayerRes->xa4_bButton[useInput.DB() || m_nextDown])); + fmt::format(FMT_STRING("&image={};"), g_tweakPlayerRes->xa4_bButton[useInput.DB() || m_nextDown])); } void CPauseScreen::TransitionComplete() { diff --git a/Runtime/MP1/CPauseScreenBase.cpp b/Runtime/MP1/CPauseScreenBase.cpp index 1f9e662c8..caf457b95 100644 --- a/Runtime/MP1/CPauseScreenBase.cpp +++ b/Runtime/MP1/CPauseScreenBase.cpp @@ -13,14 +13,28 @@ #include "Runtime/GuiSys/CGuiTextPane.hpp" #include "Runtime/GuiSys/CGuiWidgetDrawParms.hpp" #include "Runtime/GuiSys/CStringTable.hpp" +#include "Runtime/IMain.hpp" namespace urde::MP1 { CPauseScreenBase::CPauseScreenBase(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg, bool isLogBook) -: x4_mgr(mgr), x8_frame(frame), xc_pauseStrg(pauseStrg) { - m_isLogBook = isLogBook; - m_playRightTableSfx = true; +: x4_mgr(mgr) +, x8_frame(frame) +, xc_pauseStrg(pauseStrg) +, x198_24_ready(false) +, x198_25_handledInput(false) +, x198_26_exitPauseScreen(false) +, x198_27_canDraw(false) +, x198_28_pulseTextArrowTop(false) +, x198_29_pulseTextArrowBottom(false) +, m_isLogBook(isLogBook) +, m_bodyUpClicked(false) +, m_bodyDownClicked(false) +, m_bodyClicked(false) +, m_leftClicked(false) +, m_rightClicked(false) +, m_playRightTableSfx(true) { InitializeFrameGlue(); } @@ -66,8 +80,8 @@ void CPauseScreenBase::InitializeFrameGlue() { 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(fmt::format(fmt(u"&image={};"), g_tweakPlayerRes->xbc_yButton[0])); - x188_textpane_ytext->TextSupport().SetText(xc_pauseStrg.GetString(99)); + x184_textpane_yicon->TextSupport().SetText(fmt::format(FMT_STRING(u"&image={};"), g_tweakPlayerRes->xbc_yButton[0])); + x188_textpane_ytext->TextSupport().SetText(xc_pauseStrg.GetString((g_Main->IsUSA() && !g_Main->IsTrilogy()) ? 99 : 102)); x188_textpane_ytext->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); x18c_slidergroup_slider = static_cast(x8_frame.FindWidget("slidergroup_slider")); x18c_slidergroup_slider->SetMouseActive(true); @@ -92,18 +106,18 @@ void CPauseScreenBase::InitializeFrameGlue() { for (int i = 0; i < 5; ++i) { xd8_textpane_titles.push_back( - static_cast(x8_frame.FindWidget(fmt::format(fmt("textpane_title{}"), i + 1)))); + static_cast(x8_frame.FindWidget(fmt::format(FMT_STRING("textpane_title{}"), i + 1)))); xd8_textpane_titles.back()->TextSupport().SetText(u""); - x144_model_titles.push_back(static_cast(x8_frame.FindWidget(fmt::format(fmt("model_title{}"), i + 1)))); + x144_model_titles.push_back(static_cast(x8_frame.FindWidget(fmt::format(FMT_STRING("model_title{}"), i + 1)))); m_model_lefttitledecos.push_back( - static_cast(x8_frame.FindWidget(fmt::format(fmt("model_lefttitledeco{}"), i)))); + static_cast(x8_frame.FindWidget(fmt::format(FMT_STRING("model_lefttitledeco{}"), i)))); m_model_lefttitledecos.back()->SetMouseActive(true); x15c_model_righttitledecos.push_back( - static_cast(x8_frame.FindWidget(fmt::format(fmt("model_righttitledeco{}"), i + 1)))); + static_cast(x8_frame.FindWidget(fmt::format(FMT_STRING("model_righttitledeco{}"), i + 1)))); x15c_model_righttitledecos.back()->SetMouseActive(true); xa8_textpane_categories.push_back( - static_cast(x8_frame.FindWidget(fmt::format(fmt("textpane_category{}"), i)))); - xc0_model_categories.push_back(static_cast(x8_frame.FindWidget(fmt::format(fmt("model_category{}"), i)))); + static_cast(x8_frame.FindWidget(fmt::format(FMT_STRING("textpane_category{}"), i)))); + xc0_model_categories.push_back(static_cast(x8_frame.FindWidget(fmt::format(FMT_STRING("model_category{}"), i)))); } for (int i = 0; i < 20; ++i) @@ -523,13 +537,13 @@ void CPauseScreenBase::OnWidgetScroll(CGuiWidget* widget, const boo::SScrollDelt } } -std::string CPauseScreenBase::GetImagePaneName(u32 i) { +std::string CPauseScreenBase::GetImagePaneName(size_t i) { static constexpr std::array PaneSuffixes{ "0", "1", "2", "3", "01", "12", "23", "012", "123", "0123", "4", "5", "6", "7", "45", "56", "67", "456", "567", "4567", }; - return fmt::format(fmt("imagepane_pane{}"), PaneSuffixes[i]); + return fmt::format(FMT_STRING("imagepane_pane{}"), PaneSuffixes[i]); } } // namespace urde::MP1 diff --git a/Runtime/MP1/CPauseScreenBase.hpp b/Runtime/MP1/CPauseScreenBase.hpp index 7b9937143..6272087e9 100644 --- a/Runtime/MP1/CPauseScreenBase.hpp +++ b/Runtime/MP1/CPauseScreenBase.hpp @@ -74,24 +74,20 @@ protected: 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; - bool m_isLogBook : 1; - bool m_bodyUpClicked : 1; - bool m_bodyDownClicked : 1; - bool m_bodyClicked : 1; - bool m_leftClicked : 1; - bool m_rightClicked : 1; - bool m_playRightTableSfx : 1; - }; - u32 _dummy = 0; - }; + 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; + bool m_isLogBook : 1; + bool m_bodyUpClicked : 1; + bool m_bodyDownClicked : 1; + bool m_bodyClicked : 1; + bool m_leftClicked : 1; + bool m_rightClicked : 1; + bool m_playRightTableSfx : 1; + void InitializeFrameGlue(); void ChangeMode(EMode mode, bool playSfx = true); void UpdateSideTable(CGuiTableGroup* table); @@ -106,7 +102,7 @@ protected: void OnWidgetScroll(CGuiWidget* widget, const boo::SScrollDelta& delta, int accumX, int accumY); public: - static std::string GetImagePaneName(u32 i); + static std::string GetImagePaneName(size_t i); CPauseScreenBase(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg, bool isLogBook = false); diff --git a/Runtime/MP1/CPauseScreenBlur.cpp b/Runtime/MP1/CPauseScreenBlur.cpp index 37dbacbef..f750dba69 100644 --- a/Runtime/MP1/CPauseScreenBlur.cpp +++ b/Runtime/MP1/CPauseScreenBlur.cpp @@ -6,9 +6,8 @@ namespace urde::MP1 { -CPauseScreenBlur::CPauseScreenBlur() : x4_mapLightQuarter(g_SimplePool->GetObj("TXTR_MapLightQuarter")) { - x50_25_gameDraw = true; -} +CPauseScreenBlur::CPauseScreenBlur() +: x4_mapLightQuarter(g_SimplePool->GetObj("TXTR_MapLightQuarter")), x50_24_blurring(false), x50_25_gameDraw(true) {} void CPauseScreenBlur::OnNewInGameGuiState(EInGameGuiState state, CStateManager& stateMgr) { switch (state) { diff --git a/Runtime/MP1/CPauseScreenBlur.hpp b/Runtime/MP1/CPauseScreenBlur.hpp index e96b2eafc..69a7e4951 100644 --- a/Runtime/MP1/CPauseScreenBlur.hpp +++ b/Runtime/MP1/CPauseScreenBlur.hpp @@ -20,16 +20,12 @@ class CPauseScreenBlur { EState x14_nextState = EState::InGame; float x18_blurAmt = 0.f; CCameraBlurPass x1c_camBlur; + bool x50_24_blurring : 1; + bool x50_25_gameDraw : 1; + 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); diff --git a/Runtime/MP1/CPlayMovie.cpp b/Runtime/MP1/CPlayMovie.cpp index fcffdaf28..9d9494fc8 100644 --- a/Runtime/MP1/CPlayMovie.cpp +++ b/Runtime/MP1/CPlayMovie.cpp @@ -8,7 +8,13 @@ const char* kMovies[] = {"Video/wingame.thp", "Video/wingame_best.thp", " bool CPlayMovie::IsResultsScreen(EWhichMovie which) { return int(which) <= 2; } -CPlayMovie::CPlayMovie(EWhichMovie which) : CPlayMovieBase("CPlayMovie", kMovies[int(which)]), x18_which(which) { +CPlayMovie::CPlayMovie(EWhichMovie which) +: CPlayMovieBase("CPlayMovie", kMovies[int(which)]) +, x18_which(which) +, x78_24_(false) +, x78_25_(false) +, x78_26_resultsScreen(false) +, x78_27_(false) { (void)x18_which; } diff --git a/Runtime/MP1/CPlayMovie.hpp b/Runtime/MP1/CPlayMovie.hpp index f881461e1..8e40a9f85 100644 --- a/Runtime/MP1/CPlayMovie.hpp +++ b/Runtime/MP1/CPlayMovie.hpp @@ -20,15 +20,11 @@ public: 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; - }; + bool x78_24_ : 1; + bool x78_25_ : 1; + bool x78_26_resultsScreen : 1; + bool x78_27_ : 1; + static bool IsResultsScreen(EWhichMovie which); public: diff --git a/Runtime/MP1/CPlayerVisor.cpp b/Runtime/MP1/CPlayerVisor.cpp index bf499de71..2c6ba0d2e 100644 --- a/Runtime/MP1/CPlayerVisor.cpp +++ b/Runtime/MP1/CPlayerVisor.cpp @@ -321,7 +321,7 @@ void CPlayerVisor::LockUnlockAssets() { #endif } -void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, const CTargetingManager* tgtMgr) { +void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, CTargetingManager* tgtMgr) { SCOPED_GRAPHICS_DEBUG_GROUP("CPlayerVisor::DrawScanEffect", zeus::skMagenta); const bool indicatorsDrawn = DrawScanObjectIndicators(mgr); @@ -645,7 +645,7 @@ void CPlayerVisor::Update(float dt, const CStateManager& mgr) { x58_scanMagInterp = std::max(x58_scanMagInterp - 2.f * dt, scanMag); } -void CPlayerVisor::Draw(const CStateManager& mgr, const CTargetingManager* tgtManager) { +void CPlayerVisor::Draw(const CStateManager& mgr, CTargetingManager* tgtManager) { CGraphics::SetAmbientColor(zeus::skWhite); CGraphics::DisableAllLights(); switch (mgr.GetPlayerState()->GetActiveVisor(mgr)) { diff --git a/Runtime/MP1/CPlayerVisor.hpp b/Runtime/MP1/CPlayerVisor.hpp index d502ba090..a38135aca 100644 --- a/Runtime/MP1/CPlayerVisor.hpp +++ b/Runtime/MP1/CPlayerVisor.hpp @@ -72,7 +72,7 @@ class CPlayerVisor { void UpdateScanWindow(float dt, const CStateManager& mgr); EScanWindowState GetDesiredScanWindowState(const CStateManager& mgr) const; void LockUnlockAssets(); - void DrawScanEffect(const CStateManager& mgr, const CTargetingManager* tgtMgr); + void DrawScanEffect(const CStateManager& mgr, CTargetingManager* tgtMgr); void DrawXRayEffect(const CStateManager& mgr); void DrawThermalEffect(const CStateManager& mgr); void UpdateCurrentVisor(float transFactor); @@ -85,7 +85,7 @@ public: explicit CPlayerVisor(CStateManager& stateMgr); ~CPlayerVisor(); void Update(float dt, const CStateManager& stateMgr); - void Draw(const CStateManager& stateMgr, const CTargetingManager* tgtManager); + void Draw(const CStateManager& stateMgr, CTargetingManager* tgtManager); void Touch(); float GetDesiredViewportScaleX(const CStateManager& stateMgr) const; float GetDesiredViewportScaleY(const CStateManager& stateMgr) const; diff --git a/Runtime/MP1/CQuitGameScreen.cpp b/Runtime/MP1/CQuitGameScreen.cpp index 4a364c0f9..a51d63fe1 100644 --- a/Runtime/MP1/CQuitGameScreen.cpp +++ b/Runtime/MP1/CQuitGameScreen.cpp @@ -1,5 +1,7 @@ #include "Runtime/MP1/CQuitGameScreen.hpp" +#include + #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/CSimplePool.hpp" #include "Runtime/Audio/CSfxManager.hpp" @@ -14,11 +16,11 @@ namespace urde::MP1 { -static const int Titles[] = {24, 25, 26, 27, 28}; +constexpr std::array Titles{24, 25, 26, 27, 28}; -static const int DefaultSelections[] = {1, 0, 1, 1, 0}; +constexpr std::array DefaultSelections{1, 0, 1, 1, 0}; -static const float VerticalOffsets[] = {0.f, 1.6f, 1.f, 0.f, 1.f}; +constexpr std::array 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}, @@ -37,7 +39,7 @@ void CQuitGameScreen::FinishedLoading() { static_cast(x10_loadedFrame->FindWidget("textpane_title")) ->TextSupport() - .SetText(g_MainStringTable->GetString(Titles[int(x0_type)])); + .SetText(g_MainStringTable->GetString(Titles[size_t(x0_type)])); static_cast(x10_loadedFrame->FindWidget("textpane_yes")) ->TextSupport() @@ -46,7 +48,7 @@ void CQuitGameScreen::FinishedLoading() { ->TextSupport() .SetText(g_MainStringTable->GetString(23)); - x14_tablegroup_quitgame->SetUserSelection(DefaultSelections[int(x0_type)]); + x14_tablegroup_quitgame->SetUserSelection(DefaultSelections[size_t(x0_type)]); x14_tablegroup_quitgame->SetWorkersMouseActive(true); x10_loadedFrame->SetMouseUpCallback([this](CGuiWidget* widget, bool cancel) { OnWidgetMouseUp(widget, cancel); }); SetColors(); @@ -83,23 +85,30 @@ EQuitAction CQuitGameScreen::Update(float dt) { void CQuitGameScreen::Draw() { SCOPED_GRAPHICS_DEBUG_GROUP("CQuitGameScreen::Draw", zeus::skPurple); - if (x0_type == EQuitType::QuitGame) + 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[size_t(x0_type)]}}); + } } void CQuitGameScreen::ProcessUserInput(const CFinalInput& input) { - if (input.ControllerIdx() != 0) + if (input.ControllerIdx() != 0) { return; - if (!x10_loadedFrame) + } + + if (!x10_loadedFrame) { return; - x10_loadedFrame->ProcessMouseInput(input, - CGuiWidgetDrawParms{1.f, zeus::CVector3f{0.f, 0.f, VerticalOffsets[int(x0_type)]}}); + } + + x10_loadedFrame->ProcessMouseInput( + input, CGuiWidgetDrawParms{1.f, zeus::CVector3f{0.f, 0.f, VerticalOffsets[size_t(x0_type)]}}); x10_loadedFrame->ProcessUserInput(input); - if ((input.PB() || input.PSpecialKey(boo::ESpecialKey::Esc)) && x0_type != EQuitType::ContinueFromLastSave) + if ((input.PB() || input.PSpecialKey(boo::ESpecialKey::Esc)) && x0_type != EQuitType::ContinueFromLastSave) { x18_action = EQuitAction::No; + } } CQuitGameScreen::CQuitGameScreen(EQuitType tp) : x0_type(tp) { diff --git a/Runtime/MP1/CSamusDoll.cpp b/Runtime/MP1/CSamusDoll.cpp index a4ca9f2cb..01c6673d8 100644 --- a/Runtime/MP1/CSamusDoll.cpp +++ b/Runtime/MP1/CSamusDoll.cpp @@ -98,7 +98,15 @@ CSamusDoll::CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& bool hasGrappleBeam) : x10_ballXf(zeus::CTransform::Translate(0.f, 0.f, 0.625f * g_tweakPlayer->GetPlayerBallHalfExtent())) , x44_suit(suit) -, x48_beam(beam) { +, x48_beam(beam) +, x270_24_hasSpiderBall(hasSpiderBall) +, x270_25_hasGrappleBeam(hasGrappleBeam) +, x270_26_pulseSuit(false) +, x270_27_pulseBeam(false) +, x270_28_pulseGrapple(false) +, x270_29_pulseBoots(false) +, x270_30_pulseVisor(false) +, x270_31_loaded(false) { x70_fixedRot.rotateZ(M_PIF); x90_userInterpRot = xb0_userRot = x70_fixedRot; x1d4_spiderBallGlass = g_SimplePool->GetObj(SpiderBallGlassModels[size_t(suit)].first); @@ -115,8 +123,6 @@ CSamusDoll::CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& x230_ballTransitionFlash = g_SimplePool->GetObj("MorphBallTransitionFlash"); x23c_lights.push_back(CLight::BuildDirectional(zeus::skForward, zeus::skWhite)); x24c_actorLights = std::make_unique(8, zeus::skZero3f, 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()) { @@ -150,7 +156,7 @@ bool CSamusDoll::IsLoaded() const { CModelData CSamusDoll::BuildSuitModelData1(CPlayerState::EPlayerSuit suit) { CModelData ret(CAnimRes(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, Character1Idxs[size_t(suit)], zeus::skOne3f, 2, true)); - CAnimPlaybackParms parms(2, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(2, -1, 1.f, true); ret.GetAnimationData()->SetAnimation(parms, false); return ret; } @@ -158,7 +164,7 @@ CModelData CSamusDoll::BuildSuitModelData1(CPlayerState::EPlayerSuit suit) { CModelData CSamusDoll::BuildSuitModelDataBoots(CPlayerState::EPlayerSuit suit) { CModelData ret(CAnimRes(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, CharacterBootsIdxs[size_t(suit)], zeus::skOne3f, 2, true)); - CAnimPlaybackParms parms(2, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(2, -1, 1.f, true); ret.GetAnimationData()->SetAnimation(parms, false); return ret; } diff --git a/Runtime/MP1/CSamusDoll.hpp b/Runtime/MP1/CSamusDoll.hpp index ac0ddd645..6833a75e6 100644 --- a/Runtime/MP1/CSamusDoll.hpp +++ b/Runtime/MP1/CSamusDoll.hpp @@ -71,19 +71,14 @@ class CSamusDoll { 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; - }; + 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; static constexpr zeus::CVector3f skInitialOffset{0.0f, 0.0f, 0.8f}; static CModelData BuildSuitModelData1(CPlayerState::EPlayerSuit suit); diff --git a/Runtime/MP1/CSamusFaceReflection.cpp b/Runtime/MP1/CSamusFaceReflection.cpp index 84ca37816..8a8e2c5af 100644 --- a/Runtime/MP1/CSamusFaceReflection.cpp +++ b/Runtime/MP1/CSamusFaceReflection.cpp @@ -16,7 +16,7 @@ CSamusFaceReflection::CSamusFaceReflection(CStateManager& stateMgr) : x0_modelData(CAnimRes(g_ResFactory->GetResourceIdByName("ACS_SamusFace")->id, 0, zeus::skOne3f, 0, true)) , x4c_lights(std::make_unique(8, zeus::skZero3f, 4, 4, false, false, false, 0.1f)) { x60_lookDir = zeus::skForward; - CAnimPlaybackParms parms(0, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(0, -1, 1.f, true); x0_modelData.GetAnimationData()->SetAnimation(parms, false); } diff --git a/Runtime/MP1/CSamusHud.cpp b/Runtime/MP1/CSamusHud.cpp index 5681b8c86..8fe61b2b3 100644 --- a/Runtime/MP1/CSamusHud.cpp +++ b/Runtime/MP1/CSamusHud.cpp @@ -23,9 +23,11 @@ CSamusHud::CSamusHud(CStateManager& stateMgr) : x8_targetingMgr(stateMgr) , x258_frmeHelmet(g_SimplePool->GetObj("FRME_Helmet")) , x268_frmeBaseHud(g_SimplePool->GetObj("FRME_BaseHud")) +, x2e0_24_inFreeLook(false) +, x2e0_25_lookControlHeld(false) +, x2e0_26_latestFirstPerson(true) +, x2e0_27_energyLow(stateMgr.GetPlayer().IsEnergyLow(stateMgr)) , 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::skZero3f, 4, 1, true, 0, 0, 0.1f); x340_hudLights.resize(3, SCachedHudLight(zeus::skZero3f, zeus::skWhite, 0.f, 0.f, 0.f, 0.f)); x46c_.resize(3); @@ -114,7 +116,7 @@ void CSamusHud::InitializeFrameGluePermanent(const CStateManager& mgr) { for (size_t i = 0; i < x5a4_videoBands.size(); ++i) { SVideoBand& band = x5a4_videoBands[i]; band.x0_videoband = - static_cast(x274_loadedFrmeBaseHud->FindWidget(fmt::format(fmt("model_videoband{}"), i))); + static_cast(x274_loadedFrmeBaseHud->FindWidget(fmt::format(FMT_STRING("model_videoband{}"), i))); band.x4_randA = 6 + (std::rand() % ((66 - 6) + 1)); band.x8_randB = 16 + (std::rand() % ((256 - 16) + 1)); } @@ -1299,7 +1301,7 @@ void CSamusHud::Update(float dt, const CStateManager& mgr, CInGameGuiManager::EH 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 = fmt::format(fmt("{:02d}:{:02d}:{:02d}"), int(minutes), int(seconds), int(hundredths)); + std::string timeStr = fmt::format(FMT_STRING("{:02d}:{:02d}:{:02d}"), int(minutes), int(seconds), int(hundredths)); x594_base_textpane_counter->TextSupport().SetText(timeStr); x594_base_textpane_counter->SetIsVisible(true); diff --git a/Runtime/MP1/CSamusHud.hpp b/Runtime/MP1/CSamusHud.hpp index 47baf9248..c140ba43d 100644 --- a/Runtime/MP1/CSamusHud.hpp +++ b/Runtime/MP1/CSamusHud.hpp @@ -95,17 +95,10 @@ class CSamusHud { 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; - }; - + bool x2e0_24_inFreeLook : 1; + bool x2e0_25_lookControlHeld : 1; + bool x2e0_26_latestFirstPerson : 1; + bool x2e0_27_energyLow : 1; u32 x2e4_ = 0; u32 x2e8_ = 0; CPlayerGun::EMissleMode x2ec_missileMode = CPlayerGun::EMissleMode::Inactive; diff --git a/Runtime/MP1/CSaveGameScreen.cpp b/Runtime/MP1/CSaveGameScreen.cpp index 95fe4acda..390fd2705 100644 --- a/Runtime/MP1/CSaveGameScreen.cpp +++ b/Runtime/MP1/CSaveGameScreen.cpp @@ -190,11 +190,18 @@ void CSaveGameScreen::SetUIText() { 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"; + if (g_Main->IsUSA() && !g_Main->IsTrilogy()) { + msgB = 0; // No card found + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + opt2 = -2; + opt2Str = u"Create Dolphin Card"; + } else { + msgAStr = u"This version of Metroid Prime\nhas a currently unsupported save format.\n"; + msgBStr = u"&push;&main-color=$ff0000ff;Saving has been disabled.&pop;\n"; + opt0 = -2; + opt0Str = u"Press &image=SI,1.0,0.68,05AF9CAA; to proceed.\n"; + } break; case EUIType::NeedsFormatBroken: msgB = 1; // Needs format (card broken) diff --git a/Runtime/MP1/CSlideShow.cpp b/Runtime/MP1/CSlideShow.cpp index 40b0d9571..50338b7ab 100644 --- a/Runtime/MP1/CSlideShow.cpp +++ b/Runtime/MP1/CSlideShow.cpp @@ -6,12 +6,20 @@ 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_25_(false) +, x134_26_(false) +, x134_27_(false) +, x134_28_disableInput(false) +, x134_29_(false) +, x134_30_(true) +, x134_31_(false) +, x135_24_(true) { const SObjectTag* font = g_ResFactory->GetResourceIdByName(g_tweakSlideShow->GetFont()); if (font) { CGuiTextProperties propsA(false, true, EJustification::Center, EVerticalJustification::Bottom); @@ -93,7 +101,7 @@ CIOWin::EMessageReturn CSlideShow::OnMessage(const CArchitectureMessage& msg, CA if (x18_galleryTXTRDeps.empty()) { x18_galleryTXTRDeps.reserve(5); for (int i = 1; true; ++i) { - std::string depResName = fmt::format(fmt("Gallery{:02d}_DGRP"), i); + std::string depResName = fmt::format(FMT_STRING("Gallery{:02d}_DGRP"), i); if (!LoadTXTRDep(depResName)) break; } diff --git a/Runtime/MP1/CSlideShow.hpp b/Runtime/MP1/CSlideShow.hpp index 11087684f..20bed1176 100644 --- a/Runtime/MP1/CSlideShow.hpp +++ b/Runtime/MP1/CSlideShow.hpp @@ -87,21 +87,15 @@ private: 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; - }; + 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; bool LoadTXTRDep(std::string_view name); static bool AreAllDepsLoaded(const std::vector>& deps); diff --git a/Runtime/MP1/CTweaks.cpp b/Runtime/MP1/CTweaks.cpp index 431ab3dfc..790b632c1 100644 --- a/Runtime/MP1/CTweaks.cpp +++ b/Runtime/MP1/CTweaks.cpp @@ -63,8 +63,13 @@ void CTweaks::RegisterTweaks(hecl::CVarManager* 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); + if (g_Main->IsTrilogy() || g_Main->IsPAL() || g_Main->IsJapanese()) { + g_tweakTargeting = new DataSpec::DNAMP1::CTweakTargeting(*strm); + g_tweakTargeting->initCVars(cvarMgr); + } else { + g_tweakTargeting = new DataSpec::DNAMP1::CTweakTargeting(*strm); + g_tweakTargeting->initCVars(cvarMgr); + } /* Game */ tag = g_ResFactory->GetResourceIdByName("Game"); @@ -121,7 +126,12 @@ void CTweaks::RegisterResourceTweaks(hecl::CVarManager* 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); + if (g_Main->IsTrilogy() || g_Main->IsPAL() || g_Main->IsJapanese()) { + g_tweakPlayerRes = new DataSpec::DNAMP1::CTweakPlayerRes(*strm); + } else { + g_tweakPlayerRes = new DataSpec::DNAMP1::CTweakPlayerRes(*strm); + } + g_tweakPlayerRes->ResolveResources(*g_ResFactory); g_tweakPlayerRes->initCVars(cvarMgr); } diff --git a/Runtime/MP1/MP1.cpp b/Runtime/MP1/MP1.cpp index 3c1735d0d..8fe307f85 100644 --- a/Runtime/MP1/MP1.cpp +++ b/Runtime/MP1/MP1.cpp @@ -61,6 +61,7 @@ #include "Runtime/Particle/CWeaponDescription.hpp" #include "Runtime/World/CPlayer.hpp" #include "Runtime/World/CStateMachine.hpp" +#include "Runtime/World/CScriptMazeNode.hpp" #include #include @@ -70,12 +71,6 @@ #include -namespace hecl { -extern CVar* com_enableCheats; -extern CVar* com_developer; -extern CVar* com_cubemaps; -}; // namespace hecl - namespace urde::MP1 { namespace { struct AudioGroupInfo { @@ -98,7 +93,7 @@ CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, boo::IAudioVoi , 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); + auto* m = static_cast(g_Main); x30_inputGenerator.startScanning(); g_InputGenerator = &x30_inputGenerator; @@ -144,8 +139,9 @@ void CGameArchitectureSupport::Update(float dt) { } bool CGameArchitectureSupport::LoadAudio() { - if (x88_audioLoadStatus == EAudioLoadStatus::Loaded) + if (x88_audioLoadStatus == EAudioLoadStatus::Loaded) { return true; + } for (int i = 0; i < 5; ++i) { TToken& tok = x8c_pendingAudioGroups[i]; @@ -240,7 +236,17 @@ void CGameArchitectureSupport::specialKeyUp(boo::ESpecialKey key, boo::EModifier 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) { +: m_booSetter(gfxFactory, cmdQ, spareTex) +, x128_globalObjects(resFactory, resStore) +, x160_24_finished(false) +, x160_25_mfGameBuilt(false) +, x160_26_screenFading(false) +, x160_27_(false) +, x160_28_manageCard(false) +, x160_29_(false) +, x160_30_(false) +, x160_31_cardBusy(false) +, x161_24_gameFrameDrawn(false) { xe4_gameplayResult = EGameplayResult::Playing; g_Main = this; } @@ -333,17 +339,28 @@ CGameGlobalObjects::~CGameGlobalObjects() { g_GameState = nullptr; g_TweakManager = nullptr; } +void CGameGlobalObjects::PostInitialize() { + AddPaksAndFactories(); + LoadTextureCache(); + LoadStringTable(); + m_renderer.reset(AllocateRenderer(*xcc_simplePool, *x4_resFactory)); + CEnvFxManager::Initialize(); + CScriptMazeNode::LoadMazeSeeds(); +} void CMain::AddWorldPaks() { CResLoader* loader = g_ResFactory->GetResLoader(); - if (!loader) + if (loader == nullptr) { return; + } + auto pakPrefix = g_tweakGame->GetWorldPrefix(); for (int i = 0; i < 9; ++i) { std::string path(pakPrefix); - if (i != 0) - path += '0' + i; + if (i != 0) { + path += '0' + char(i); + } if (CDvdFile::FileExists(path + ".upak")) { loader->AddPakFileAsync(path, false, true); @@ -354,14 +371,15 @@ void CMain::AddWorldPaks() { void CMain::AddOverridePaks() { CResLoader* loader = g_ResFactory->GetResLoader(); - if (!loader) + if (loader == nullptr) { return; + } /* Inversely load each pak starting at 999, to ensure proper priority order * the higher the number the higer the priority, e.g: Override0 has less priority than Override1 etc. */ for (size_t i = 999; i > 0; --i) { - const std::string path = fmt::format(fmt("Override{}"), i); + const std::string path = fmt::format(FMT_STRING("Override{}"), i); if (CDvdFile::FileExists(path + ".upak")) { loader->AddPakFileAsync(path, false, false, true); } @@ -372,8 +390,9 @@ void CMain::AddOverridePaks() { /* Attempt to load URDE.upak * NOTE(phil): Should we fatal here if it's not found? */ - if (CDvdFile::FileExists("URDE.upak")) + if (CDvdFile::FileExists("URDE.upak")) { loader->AddPakFile("URDE", false, false, true); + } } void CMain::ResetGameState() { @@ -398,7 +417,7 @@ void CMain::InitializeSubsystems() { } void CMain::MemoryCardInitializePump() { - if (g_MemoryCardSys) { + if (g_MemoryCardSys != nullptr) { return; } @@ -419,8 +438,9 @@ void CMain::FillInAssetIDs() { } bool CMain::LoadAudio() { - if (x164_archSupport) + if (x164_archSupport) { return x164_archSupport->LoadAudio(); + } return true; } @@ -430,8 +450,9 @@ void CMain::EnsureWorldPakReady(CAssetId mlvl) { /* TODO: Schedule resource list } void CMain::Give(hecl::Console* console, const std::vector& args) { - if (args.size() < 1 || (!g_GameState || !g_GameState->GetPlayerState())) + if (args.empty() || (g_GameState == nullptr || !g_GameState->GetPlayerState())) { return; + } std::string type = args[0]; athena::utility::tolower(type); @@ -449,15 +470,16 @@ void CMain::Give(hecl::Console* console, const std::vector& args) { } else { CPlayerState::EItemType eType = CPlayerState::ItemNameToType(type); if (eType == CPlayerState::EItemType::Invalid) { - console->report(hecl::Console::Level::Info, fmt("Invalid item {}"), type); + console->report(hecl::Console::Level::Info, FMT_STRING("Invalid item {}"), type); return; } if (eType == CPlayerState::EItemType::HealthRefill) { pState->IncrPickup(eType, 9999); console->report(hecl::Console::Level::Info, - fmt("Cheater....., Greatly increasing Metroid encounters, have fun!")); - if (g_StateManager) + FMT_STRING("Cheater....., Greatly increasing Metroid encounters, have fun!")); + if (g_StateManager != nullptr) { g_StateManager->Player()->AsyncLoadSuit(*g_StateManager); + } return; } @@ -474,23 +496,28 @@ void CMain::Give(hecl::Console* console, const std::vector& args) { if (eType == CPlayerState::EItemType::Missiles) { u32 tmp = ((u32(itemAmt) / 5) + (itemAmt % 5)) * 5; pState->ReInitalizePowerUp(eType, tmp); - } else + } else { pState->ReInitalizePowerUp(eType, itemAmt); + } } - if (itemAmt > 0) + if (itemAmt > 0) { pState->IncrPickup(eType, u32(itemAmt)); - else + } else { pState->DecrPickup(eType, zeus::clamp(0u, u32(abs(itemAmt)), pState->GetItemAmount(eType))); + } } - if (g_StateManager) + if (g_StateManager != nullptr) { g_StateManager->Player()->AsyncLoadSuit(*g_StateManager); - console->report(hecl::Console::Level::Info, fmt("Cheater....., Greatly increasing Metroid encounters, have fun!")); + } + console->report(hecl::Console::Level::Info, + FMT_STRING("Cheater....., Greatly increasing Metroid encounters, have fun!")); } // namespace MP1 void CMain::Remove(hecl::Console*, const std::vector& args) { - if (args.size() < 1 || (!g_GameState || !g_GameState->GetPlayerState())) + if (args.empty() || (g_GameState == nullptr || !g_GameState->GetPlayerState())) { return; + } std::string type = args[0]; athena::utility::tolower(type); @@ -503,37 +530,42 @@ void CMain::Remove(hecl::Console*, const std::vector& args) { CPlayerState::EItemType eType = CPlayerState::ItemNameToType(type); if (eType != CPlayerState::EItemType::Invalid) { pState->ReInitalizePowerUp(eType, 0); - if (g_StateManager) + if (g_StateManager != nullptr) { g_StateManager->Player()->AsyncLoadSuit(*g_StateManager); + } } } } void CMain::God(hecl::Console* con, const std::vector&) { - if (g_GameState && g_GameState->GetPlayerState()) { + if (g_GameState != nullptr && g_GameState->GetPlayerState()) { g_GameState->GetPlayerState()->SetCanTakeDamage(!g_GameState->GetPlayerState()->CanTakeDamage()); - if (!g_GameState->GetPlayerState()->CanTakeDamage()) - con->report(hecl::Console::Level::Info, fmt("God Mode Enabled")); - else - con->report(hecl::Console::Level::Info, fmt("God Mode Disabled")); + if (!g_GameState->GetPlayerState()->CanTakeDamage()) { + con->report(hecl::Console::Level::Info, FMT_STRING("God Mode Enabled")); + } else { + con->report(hecl::Console::Level::Info, FMT_STRING("God Mode Disabled")); + } } } void CMain::Teleport(hecl::Console*, const std::vector& args) { - if (!g_StateManager || args.size() < 3) + if (g_StateManager == nullptr || args.size() < 3) { return; + } zeus::CVector3f loc; - for (u32 i = 0; i < 3; ++i) + 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) + 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); @@ -541,41 +573,47 @@ void CMain::Teleport(hecl::Console*, const std::vector& args) { void CMain::ListWorlds(hecl::Console* con, const std::vector&) { - if (g_ResFactory && g_ResFactory->GetResLoader()) { - for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) + if (g_ResFactory != nullptr && g_ResFactory->GetResLoader() != nullptr) { + for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) { if (pak->IsWorldPak()) { - for (const auto& named : pak->GetNameList()) + for (const auto& named : pak->GetNameList()) { if (named.second.type == SBIG('MLVL')) { - con->report(hecl::Console::Level::Info, fmt("{} '{}'"), named.first, named.second.id); + con->report(hecl::Console::Level::Info, FMT_STRING("{} '{}'"), named.first, named.second.id); } + } } + } } } void CMain::Warp(hecl::Console* con, const std::vector& args) { - if (!g_StateManager) + if (g_StateManager == nullptr) { return; + } - if (args.size() < 1) + if (args.empty()) { return; + } - TAreaId aId; + TAreaId aId = 0; std::string worldName; if (args.size() == 2) { worldName = args[0]; athena::utility::tolower(worldName); aId = strtol(args[1].c_str(), nullptr, 10); - } else + } else { aId = strtol(args[0].c_str(), nullptr, 10); + } - if (!worldName.empty() && g_ResFactory && g_ResFactory->GetResLoader()) { + if (!worldName.empty() && g_ResFactory != nullptr && g_ResFactory->GetResLoader() != nullptr) { bool found = false; for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) { - if (found) + if (found) { break; + } if (pak->IsWorldPak()) { - for (const auto& named : pak->GetNameList()) + for (const auto& named : pak->GetNameList()) { if (named.second.type == SBIG('MLVL')) { std::string name = named.first; athena::utility::tolower(name); @@ -585,14 +623,16 @@ void CMain::Warp(hecl::Console* con, const std::vector& args) { break; } } + } } } } g_GameState->GetWorldTransitionManager()->DisableTransition(); - if (aId >= g_GameState->CurrentWorldState().GetLayerState()->GetAreaCount()) + if (aId >= g_GameState->CurrentWorldState().GetLayerState()->GetAreaCount()) { aId = 0; + } g_GameState->CurrentWorldState().SetAreaId(aId); g_Main->SetFlowState(EFlowState::None); @@ -624,6 +664,7 @@ void CMain::RefreshGameState() { } static logvisor::Module DiscordLog("Discord"); +static logvisor::Module MainLog("MP1::CMain"); static const char* DISCORD_APPLICATION_ID = "402571593815031819"; static int64_t DiscordStartTime; static CAssetId DiscordWorldSTRG; @@ -659,12 +700,12 @@ void CMain::UpdateDiscordPresence(CAssetId worldSTRG) { updated = true; } - if (g_GameState) { + if (g_GameState != nullptr) { if (CPlayerState* pState = g_GameState->GetPlayerState().get()) { u32 itemPercent = pState->CalculateItemCollectionRate() * 100 / pState->GetPickupTotal(); if (DiscordItemPercent != itemPercent) { DiscordItemPercent = itemPercent; - DiscordState = fmt::format(fmt("{}%"), itemPercent); + DiscordState = fmt::format(FMT_STRING("{}%"), itemPercent); updated = true; } } @@ -680,14 +721,16 @@ void CMain::UpdateDiscordPresence(CAssetId worldSTRG) { } } -void CMain::HandleDiscordReady(const DiscordUser* request) { DiscordLog.report(logvisor::Info, fmt("Discord Ready")); } +void CMain::HandleDiscordReady(const DiscordUser* request) { + DiscordLog.report(logvisor::Info, FMT_STRING("Discord Ready")); +} void CMain::HandleDiscordDisconnected(int errorCode, const char* message) { - DiscordLog.report(logvisor::Warning, fmt("Discord Disconnected: {}"), message); + DiscordLog.report(logvisor::Warning, FMT_STRING("Discord Disconnected: {}"), message); } void CMain::HandleDiscordErrored(int errorCode, const char* message) { - DiscordLog.report(logvisor::Error, fmt("Discord Error: {}"), message); + DiscordLog.report(logvisor::Error, FMT_STRING("Discord Error: {}"), message); } void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarManager* cvarMgr, boo::IWindow* window, @@ -695,6 +738,7 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarMana InitializeDiscord(); m_mainWindow = window; m_cvarMgr = cvarMgr; + m_cvarCommons = std::make_unique(*m_cvarMgr); m_console = std::make_unique(m_cvarMgr); m_console->init(window); m_console->registerCommand( @@ -725,6 +769,21 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarMana [this](hecl::Console* console, const std::vector& args) { Warp(console, args); }, hecl::SConsoleCommand::ECommandFlags::Normal); + bool loadedVersion = false; + if (CDvdFile::FileExists("version.yaml")) { + CDvdFile file("version.yaml"); + if (file) { + std::unique_ptr buf = std::make_unique(file.Length()); + u32 readLen = file.SyncRead(buf.get(), file.Length()); + if (readLen == file.Length()) { + CMemoryInStream memoryInStream(buf.get(), file.Length()); + athena::io::FromYAMLStream(m_version, memoryInStream); + loadedVersion = true; + MainLog.report(logvisor::Level::Info, FMT_STRING("Loaded version info")); + } + } + } + InitializeSubsystems(); AddOverridePaks(); x128_globalObjects.PostInitialize(); @@ -732,19 +791,34 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarMana x70_tweaks.RegisterResourceTweaks(m_cvarMgr); AddWorldPaks(); + if (loadedVersion) { + if (GetGame() != EGame::MetroidPrime1) { + MainLog.report(logvisor::Level::Fatal, + FMT_STRING("Attempted to initialize URDE in MP1 mode with non-MP1 data!!!!")); + } + hecl::SystemStringConv conv(GetVersionString()); + boo::SystemStringView versionView(conv.sys_str()); + MainLog.report(logvisor::Level::Info, FMT_STRING(_SYS_STR("Loading data from Metroid Prime version {} from region {}{}")), + versionView, boo::SystemChar(GetRegion()), IsTrilogy() ? _SYS_STR(" from trilogy") : _SYS_STR("")); + } else { + MainLog.report(logvisor::Level::Fatal, FMT_STRING("Unable to load version info")); + } + 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; + hecl::SystemChar* endptr = nullptr; m_warpWorldIdx = TAreaId(hecl::StrToUl(worldIdxStr, &endptr, 0)); - if (endptr == worldIdxStr) + if (endptr == worldIdxStr) { m_warpWorldIdx = 0; + } m_warpAreaId = TAreaId(hecl::StrToUl(areaIdxStr, &endptr, 0)); - if (endptr == areaIdxStr) + if (endptr == areaIdxStr) { m_warpAreaId = 0; + } bool found = false; for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) { @@ -767,7 +841,7 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarMana if (*cur == _SYS_STR('1')) m_warpLayerBits |= u64(1) << (cur - layerStr); } else if (layerStr[0] == _SYS_STR('0') && layerStr[1] == _SYS_STR('x')) { - m_warpMemoryRelays.push_back(TAreaId(hecl::StrToUl(layerStr + 2, nullptr, 16))); + m_warpMemoryRelays.emplace_back(TAreaId(hecl::StrToUl(layerStr + 2, nullptr, 16))); } ++it; } @@ -781,21 +855,22 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarMana x164_archSupport = std::make_unique(*this, voiceEngine, backend); g_archSupport = x164_archSupport.get(); x164_archSupport->PreloadAudio(); - std::srand(static_cast(std::time(nullptr))); + std::srand(static_cast(std::time(nullptr))); // g_TweakManager->ReadFromMemoryCard("AudioTweaks"); } static logvisor::Module WarmupLog("ShaderWarmup"); void CMain::WarmupShaders() { - if (m_warmupTags.size()) + if (!m_warmupTags.empty()) return; m_needsWarmupClear = true; size_t modelCount = 0; g_ResFactory->EnumerateResources([&](const SObjectTag& tag) { - if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('MREA')) + if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('MREA')) { ++modelCount; + } return true; }); m_warmupTags.reserve(modelCount); @@ -805,8 +880,9 @@ void CMain::WarmupShaders() { g_ResFactory->EnumerateResources([&](const SObjectTag& tag) { if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('MREA')) { - if (addedTags.find(tag) != addedTags.end()) + if (addedTags.find(tag) != addedTags.end()) { return true; + } addedTags.insert(tag); m_warmupTags.push_back(tag); } @@ -815,7 +891,7 @@ void CMain::WarmupShaders() { m_warmupIt = m_warmupTags.begin(); - WarmupLog.report(logvisor::Info, fmt("Began warmup of {} objects"), m_warmupTags.size()); + WarmupLog.report(logvisor::Info, FMT_STRING("Began warmup of {} objects"), m_warmupTags.size()); } bool CMain::Proc() { @@ -828,16 +904,16 @@ bool CMain::Proc() { } float dt = 1 / 60.f; -#if MP1_VARIABLE_DELTA_TIME - auto now = delta_clock::now(); - if (m_firstFrame) { - m_firstFrame = false; - } else { - using delta_duration = std::chrono::duration>; - dt = std::min(std::chrono::duration_cast(now - m_prevFrameTime).count(), dt); + if (m_cvarCommons->m_variableDt->toBoolean()) { + auto now = delta_clock::now(); + if (m_firstFrame) { + m_firstFrame = false; + } else { + using delta_duration = std::chrono::duration>; + dt = std::min(std::chrono::duration_cast(now - m_prevFrameTime).count(), 1 / 30.f); + } + m_prevFrameTime = now; } - m_prevFrameTime = now; -#endif m_console->proc(); if (!m_console->isOpen()) { @@ -872,7 +948,7 @@ void CMain::Draw() { } auto startTime = std::chrono::steady_clock::now(); while (m_warmupIt != m_warmupTags.end()) { - WarmupLog.report(logvisor::Info, fmt("[{} / {}] Warming {}"), int(m_warmupIt - m_warmupTags.begin() + 1), + WarmupLog.report(logvisor::Info, FMT_STRING("[{} / {}] Warming {}"), int(m_warmupIt - m_warmupTags.begin() + 1), int(m_warmupTags.size()), *m_warmupIt); if (m_warmupIt->type == FOURCC('CMDL')) @@ -888,7 +964,7 @@ void CMain::Draw() { } if (m_warmupIt == m_warmupTags.end()) { m_warmupTags = std::vector(); - WarmupLog.report(logvisor::Info, fmt("Finished warmup")); + WarmupLog.report(logvisor::Info, FMT_STRING("Finished warmup")); } return; } diff --git a/Runtime/MP1/MP1.hpp b/Runtime/MP1/MP1.hpp index 397031000..f2ca5a0ac 100644 --- a/Runtime/MP1/MP1.hpp +++ b/Runtime/MP1/MP1.hpp @@ -3,45 +3,42 @@ #ifndef MP1_USE_BOO #define MP1_USE_BOO 0 #endif -#ifndef MP1_VARIABLE_DELTA_TIME -#define MP1_VARIABLE_DELTA_TIME 0 -#endif -#include "IMain.hpp" -#include "CTweaks.hpp" -#include "CPlayMovie.hpp" -#include "IOStreams.hpp" -#include "CBasics.hpp" -#include "CMemoryCardSys.hpp" -#include "CResFactory.hpp" -#include "CSimplePool.hpp" -#include "Character/CAssetFactory.hpp" -#include "World/CAi.hpp" -#include "CGameState.hpp" -#include "CInGameTweakManager.hpp" -#include "Particle/CElementGen.hpp" -#include "Character/CAnimData.hpp" -#include "Particle/CDecalManager.hpp" -#include "Particle/CGenDescription.hpp" -#include "Graphics/CBooRenderer.hpp" -#include "Audio/CAudioSys.hpp" -#include "Input/CInputGenerator.hpp" -#include "GuiSys/CGuiSys.hpp" -#include "CIOWinManager.hpp" -#include "GuiSys/CSplashScreen.hpp" -#include "CMainFlow.hpp" -#include "GuiSys/CConsoleOutputWindow.hpp" -#include "GuiSys/CErrorOutputWindow.hpp" -#include "GuiSys/CTextParser.hpp" -#include "CAudioStateWin.hpp" -#include "GameGlobalObjects.hpp" -#include "CArchitectureQueue.hpp" -#include "CTimeProvider.hpp" -#include "GuiSys/CTextExecuteBuffer.hpp" +#include "Runtime/IMain.hpp" +#include "Runtime/MP1/CTweaks.hpp" +#include "Runtime/MP1/CPlayMovie.hpp" +#include "Runtime/IOStreams.hpp" +#include "Runtime/CBasics.hpp" +#include "Runtime/CMemoryCardSys.hpp" +#include "Runtime/CResFactory.hpp" +#include "Runtime/CSimplePool.hpp" +#include "Runtime/Character/CAssetFactory.hpp" +#include "Runtime/World/CAi.hpp" +#include "Runtime/CGameState.hpp" +#include "Runtime/MP1/CInGameTweakManager.hpp" +#include "Runtime/Particle/CElementGen.hpp" +#include "Runtime/Character/CAnimData.hpp" +#include "Runtime/Particle/CDecalManager.hpp" +#include "Runtime/Particle/CGenDescription.hpp" +#include "Runtime/Graphics/CBooRenderer.hpp" +#include "Runtime/Audio/CAudioSys.hpp" +#include "Runtime/Input/CInputGenerator.hpp" +#include "Runtime/GuiSys/CGuiSys.hpp" +#include "Runtime/CIOWinManager.hpp" +#include "Runtime/GuiSys/CSplashScreen.hpp" +#include "Runtime/MP1/CMainFlow.hpp" +#include "Runtime/GuiSys/CConsoleOutputWindow.hpp" +#include "Runtime/GuiSys/CErrorOutputWindow.hpp" +#include "Runtime/GuiSys/CTextParser.hpp" +#include "Runtime/MP1/CAudioStateWin.hpp" +#include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/CArchitectureQueue.hpp" +#include "Runtime/CTimeProvider.hpp" +#include "Runtime/GuiSys/CTextExecuteBuffer.hpp" #include "DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp" #include "DataSpec/DNAMP1/Tweaks/CTweakGame.hpp" -#include "World/CScriptMazeNode.hpp" #include "hecl/Console.hpp" +#include "hecl/CVarCommons.hpp" struct DiscordUser; @@ -104,14 +101,7 @@ public: ~CGameGlobalObjects(); - void PostInitialize() { - AddPaksAndFactories(); - LoadTextureCache(); - LoadStringTable(); - m_renderer.reset(AllocateRenderer(*xcc_simplePool, *x4_resFactory)); - CEnvFxManager::Initialize(); - CScriptMazeNode::LoadMazeSeeds(); - } + void PostInitialize(); void ResetGameState() { x134_gameState = std::make_unique(); @@ -144,7 +134,7 @@ class CGameArchitectureSupport std::vector> x8c_pendingAudioGroups; boo::SWindowRect m_windowRect; - bool m_rectIsDirty; + bool m_rectIsDirty = false; void destroyed() { x4_archQueue.Push(MakeMsg::CreateRemoveAllIOWins(EArchMsgTarget::IOWinManager)); } @@ -204,7 +194,7 @@ class CMain : public IMain int appMain(boo::IApplication* app); void appQuitting(boo::IApplication*) { xe8_b24_finished = true; } void appFilesOpen(boo::IApplication*, const std::vector& paths) { - fmt::print(stderr, fmt("OPENING: ")); + fmt::print(stderr, FMT_STRING("OPENING: ")); for (const std::string& path : paths) fprintf(stderr, "%s ", path.c_str()); fprintf(stderr, "\n"); @@ -227,26 +217,22 @@ private: 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; - }; + 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; std::unique_ptr x164_archSupport; boo::IWindow* m_mainWindow = nullptr; hecl::CVarManager* m_cvarMgr = nullptr; + std::unique_ptr m_cvarCommons; std::unique_ptr m_console; // Warmup state std::vector m_warmupTags; @@ -255,11 +241,10 @@ private: bool m_loadedPersistentResources = false; bool m_doQuit = false; -#if MP1_VARIABLE_DELTA_TIME bool m_firstFrame = true; using delta_clock = std::chrono::high_resolution_clock; std::chrono::time_point m_prevFrameTime; -#endif + DataSpec::URDEVersionInfo m_version; void InitializeSubsystems(); static void InitializeDiscord(); @@ -327,6 +312,13 @@ public: void ListWorlds(hecl::Console*, const std::vector&); void Warp(hecl::Console*, const std::vector&); hecl::Console* Console() const override { return m_console.get(); } + bool IsPAL() const override { return m_version.region == ERegion::PAL; } + bool IsJapanese() const override { return m_version.region == ERegion::NTSC_J; } + bool IsUSA() const override { return m_version.region == ERegion::NTSC_U; } + bool IsTrilogy() const override { return m_version.isTrilogy; } + ERegion GetRegion() const override { return m_version.region; } + EGame GetGame() const override { return m_version.game; } + std::string_view GetVersionString() const override{ return m_version.version; } int m_warpWorldIdx = -1; TAreaId m_warpAreaId = 0; diff --git a/Runtime/MP1/World/CBabygoth.cpp b/Runtime/MP1/World/CBabygoth.cpp index 1a831d151..12c1d1aeb 100644 --- a/Runtime/MP1/World/CBabygoth.cpp +++ b/Runtime/MP1/World/CBabygoth.cpp @@ -1,5 +1,7 @@ #include "Runtime/MP1/World/CBabygoth.hpp" +#include + #include "Runtime/CSimplePool.hpp" #include "Runtime/CStateManager.hpp" #include "Runtime/GameGlobalObjects.hpp" @@ -21,7 +23,15 @@ #include "TCastTo.hpp" // Generated file, do not modify include path namespace urde::MP1 { -const std::string_view CBabygoth::skpMouthDamageJoint = "LCTR_SHEMOUTH"sv; +constexpr std::string_view skpMouthDamageJoint = "LCTR_SHEMOUTH"sv; + +constexpr std::array skSphereJointList{{ + {"L_knee", 1.2f}, + {"R_knee", 1.2f}, + {"LCTR_SHEMOUTH", 1.7f}, + {"Pelvis", 1.2f}, + {"butt_LCTR", 0.9f}, +}}; CBabygothData::CBabygothData(CInputStream& in) : x0_fireballAttackTime(in.readFloatBig()) @@ -69,7 +79,21 @@ CBabygoth::CBabygoth(TUniqueId uid, std::string_view name, const CEntityInfo& in g_SimplePool->GetObj({SBIG('WPSC'), babyData.x44_fireBreathWeapon}) : g_SimplePool->GetObj("FlameThrower"sv)) , x98c_dVuln(pInfo.GetDamageVulnerability()) -, xa00_shellHitPoints(babyData.GetShellHitPoints()) { +, xa00_shellHitPoints(babyData.GetShellHitPoints()) +, xa48_24_isAlert(false) +, xa48_25_(false) +, xa48_26_inProjectileAttack(false) +, xa48_27_(false) +, xa48_28_pendingAttackContactDamage(false) +, xa48_29_hasBeenEnraged(false) +, xa48_30_heardPlayerFire(false) +, xa48_31_approachNeedsPathSearch(true) +, xa49_24_gettingUp(false) +, xa49_25_shouldStepBackwards(false) +, xa49_26_readyForTeam(false) +, xa49_27_locomotionValid(false) +, xa49_28_onApproachPath(false) +, xa49_29_objectSpaceCollision(false) { TLockedToken model = g_SimplePool->GetObj({SBIG('CMDL'), babyData.x138_noShellModel}); TLockedToken skin = g_SimplePool->GetObj({SBIG('CSKR'), babyData.x13c_noShellSkin}); xa08_noShellModel = @@ -80,7 +104,6 @@ CBabygoth::CBabygoth(TUniqueId uid, std::string_view name, const CEntityInfo& in xa2c_destroyShellParticle = g_SimplePool->GetObj({SBIG('PART'), babyData.x154_destroyShellParticle}); if (x570_babyData.x148_intermediateCrackParticle.IsValid()) xa38_intermediateCrackParticle = g_SimplePool->GetObj({SBIG('PART'), babyData.x148_intermediateCrackParticle}); - xa48_31_approachNeedsPathSearch = true; x958_iceProjectile.Token().Lock(); UpdateTouchBounds(); x460_knockBackController.SetEnableFreeze(false); @@ -285,13 +308,10 @@ void CBabygoth::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, E CPatterned::DoUserAnimEvent(mgr, node, type, dt); } -const SSphereJointInfo CBabygoth::skSphereJointList[skSphereJointCount] = { - {"L_knee", 1.2f}, {"R_knee", 1.2f}, {"LCTR_SHEMOUTH", 1.7f}, {"Pelvis", 1.2f}, {"butt_LCTR", 0.9f}}; - -void CBabygoth::AddSphereCollisionList(const SSphereJointInfo* sphereJointInfo, s32 jointCount, +void CBabygoth::AddSphereCollisionList(const SSphereJointInfo* sphereJointInfo, size_t jointCount, std::vector& jointList) { - for (s32 i = 0; i < jointCount; ++i) { - CSegId seg = GetModelData()->GetAnimationData()->GetLocatorSegId(sphereJointInfo[i].name); + for (size_t i = 0; i < jointCount; ++i) { + const CSegId seg = GetModelData()->GetAnimationData()->GetLocatorSegId(sphereJointInfo[i].name); jointList.push_back( CJointCollisionDescription::SphereCollision(seg, sphereJointInfo[i].radius, sphereJointInfo[i].name, 1000.f)); } @@ -299,7 +319,7 @@ void CBabygoth::AddSphereCollisionList(const SSphereJointInfo* sphereJointInfo, void CBabygoth::SetupCollisionManager(CStateManager& mgr) { std::vector joints; - AddSphereCollisionList(skSphereJointList, skSphereJointCount, joints); + AddSphereCollisionList(skSphereJointList.data(), skSphereJointList.size(), joints); x928_colActMgr = std::make_unique(mgr, GetUniqueId(), GetAreaIdAlways(), joints, false); x928_colActMgr->SetActive(mgr, GetActive()); @@ -1083,12 +1103,13 @@ bool CBabygoth::Leash(CStateManager& mgr, float) { return false; } -bool CBabygoth::IsDestinationObstructed(CStateManager& mgr) { - for (CEntity* obj : mgr.GetListeningAiObjectList()) { - if (TCastToPtr ai = obj) { +bool CBabygoth::IsDestinationObstructed(const CStateManager& mgr) const { + for (const CEntity* obj : mgr.GetListeningAiObjectList()) { + if (const TCastToConstPtr ai = obj) { if (ai->GetAreaIdAlways() == GetAreaIdAlways()) { - if ((x8b8_backupDestPos - ai->GetTranslation()).magSquared() <= 10.f) + if ((x8b8_backupDestPos - ai->GetTranslation()).magSquared() <= 10.f) { return true; + } } } } diff --git a/Runtime/MP1/World/CBabygoth.hpp b/Runtime/MP1/World/CBabygoth.hpp index 706f0be2e..fec7ec593 100644 --- a/Runtime/MP1/World/CBabygoth.hpp +++ b/Runtime/MP1/World/CBabygoth.hpp @@ -63,9 +63,6 @@ public: enum class EShellState { Default, CrackOne, CrackTwo, Destroyed }; private: - static constexpr s32 skSphereJointCount = 5; - static const SSphereJointInfo skSphereJointList[skSphereJointCount]; - static const std::string_view skpMouthDamageJoint; s32 x568_stateProg = -1; EShellState x56c_shellState = EShellState::Default; CBabygothData x570_babyData; @@ -100,27 +97,22 @@ private: TToken xa20_crackTwoParticle; TToken xa2c_destroyShellParticle; TLockedToken xa38_intermediateCrackParticle; // Used to be an optional, not necessary in URDE - union { - struct { - bool xa48_24_isAlert : 1; - bool xa48_25_ : 1; - bool xa48_26_inProjectileAttack : 1; - bool xa48_27_ : 1; - bool xa48_28_pendingAttackContactDamage : 1; - bool xa48_29_hasBeenEnraged : 1; - bool xa48_30_heardPlayerFire : 1; - bool xa48_31_approachNeedsPathSearch : 1; - bool xa49_24_gettingUp : 1; - bool xa49_25_shouldStepBackwards : 1; - bool xa49_26_readyForTeam : 1; - bool xa49_27_locomotionValid : 1; - bool xa49_28_onApproachPath : 1; - bool xa49_29_objectSpaceCollision : 1; - }; - u32 _dummy = 0; - }; + bool xa48_24_isAlert : 1; + bool xa48_25_ : 1; + bool xa48_26_inProjectileAttack : 1; + bool xa48_27_ : 1; + bool xa48_28_pendingAttackContactDamage : 1; + bool xa48_29_hasBeenEnraged : 1; + bool xa48_30_heardPlayerFire : 1; + bool xa48_31_approachNeedsPathSearch : 1; + bool xa49_24_gettingUp : 1; + bool xa49_25_shouldStepBackwards : 1; + bool xa49_26_readyForTeam : 1; + bool xa49_27_locomotionValid : 1; + bool xa49_28_onApproachPath : 1; + bool xa49_29_objectSpaceCollision : 1; - void AddSphereCollisionList(const SSphereJointInfo*, s32, std::vector&); + void AddSphereCollisionList(const SSphereJointInfo*, size_t, std::vector&); void SetupCollisionManager(CStateManager&); @@ -168,7 +160,7 @@ private: void UpdateShellHealth(CStateManager&); - bool IsDestinationObstructed(CStateManager&); + bool IsDestinationObstructed(const CStateManager& mgr) const; void DestroyShell(CStateManager& mgr); diff --git a/Runtime/MP1/World/CBeetle.cpp b/Runtime/MP1/World/CBeetle.cpp index 85764d1e0..ed6b65e05 100644 --- a/Runtime/MP1/World/CBeetle.cpp +++ b/Runtime/MP1/World/CBeetle.cpp @@ -18,22 +18,23 @@ CBeetle::CBeetle(TUniqueId uid, std::string_view name, const CEntityInfo& info, CModelData&& mData, const CPatternedInfo& pInfo, CPatterned::EFlavorType flavor, CBeetle::EEntranceType entranceType, const CDamageInfo& touchDamage, const CDamageVulnerability& platingVuln, const zeus::CVector3f& tailAimReference, - float initialAttackDelay, float retreatTime, float f3, - const CDamageVulnerability& tailVuln, const CActorParameters& aParams, - const std::optional& tailModel) + float initialAttackDelay, float retreatTime, float f3, const CDamageVulnerability& tailVuln, + const CActorParameters& aParams, const std::optional& tailModel) : CPatterned(ECharacter::Beetle, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant(flavor)) , x56c_entranceType(entranceType) , x574_tailAimReference(tailAimReference) , x580_f3(f3) , x584_touchDamage(touchDamage) -, x5ac_tailModel(tailModel ? std::optional(CModelData(*tailModel)) : - std::optional()) +, x5ac_tailModel(tailModel ? std::optional(CModelData(*tailModel)) : std::nullopt) , x5fc_pathFindSearch(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f) , x744_platingVuln(platingVuln) , x7ac_tailVuln(tailVuln) , x814_attackDelayTimer(initialAttackDelay) -, x834_retreatTime(retreatTime) { +, x834_retreatTime(retreatTime) +, x838_24_hitSomething(false) +, x838_25_burrowing(false) +, x838_26_canSkid(false) { x5a0_headbuttDist = GetAnimationDistance(CPASAnimParmData(7, CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(1))); x5a4_jumpBackwardDist = x64_modelData->GetScale().y() * @@ -161,7 +162,7 @@ void CBeetle::Render(CStateManager& mgr) { x5ac_tailModel->Render(mgr, tailXf, x90_actorLights.get(), flags); } } else if (x5ac_tailModel) { - CModelFlags flags(0, 0, 3, zeus::skWhite); + constexpr CModelFlags flags(0, 0, 3, zeus::skWhite); x5ac_tailModel->Render(mgr, tailXf, x90_actorLights.get(), flags); } } diff --git a/Runtime/MP1/World/CBeetle.hpp b/Runtime/MP1/World/CBeetle.hpp index 3e396b02e..a810c5a6f 100644 --- a/Runtime/MP1/World/CBeetle.hpp +++ b/Runtime/MP1/World/CBeetle.hpp @@ -38,14 +38,9 @@ private: zeus::CVector3f x824_predictPos; float x830_intoGroundFactor = 1.f; float x834_retreatTime; - union { - struct { - bool x838_24_hitSomething : 1; - bool x838_25_burrowing : 1; - bool x838_26_canSkid : 1; - }; - u32 _dummy3 = 0; - }; + bool x838_24_hitSomething : 1; + bool x838_25_burrowing : 1; + bool x838_26_canSkid : 1; void SquadAdd(CStateManager& mgr); void SquadRemove(CStateManager& mgr); diff --git a/Runtime/MP1/World/CEyeball.cpp b/Runtime/MP1/World/CEyeball.cpp index 521c88b4b..7fd687e17 100644 --- a/Runtime/MP1/World/CEyeball.cpp +++ b/Runtime/MP1/World/CEyeball.cpp @@ -11,6 +11,8 @@ #include "TCastTo.hpp" // Generated file, do not modify include path namespace urde::MP1 { +constexpr std::string_view skEyeLocator = "Laser_LCTR"sv; + CEyeball::CEyeball(TUniqueId uid, std::string_view name, CPatterned::EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, float attackDelay, float attackStartTime, CAssetId wpscId, const CDamageInfo& dInfo, CAssetId beamContactFxId, diff --git a/Runtime/MP1/World/CEyeball.hpp b/Runtime/MP1/World/CEyeball.hpp index c0e698729..a7fa3699c 100644 --- a/Runtime/MP1/World/CEyeball.hpp +++ b/Runtime/MP1/World/CEyeball.hpp @@ -11,7 +11,6 @@ namespace urde::MP1 { class CEyeball : public CPatterned { - static constexpr std::string_view skEyeLocator = "Laser_LCTR"sv; float x568_attackDelay; float x56c_attackStartTime; CBoneTracking x570_boneTracking; diff --git a/Runtime/MP1/World/CFlaahgra.cpp b/Runtime/MP1/World/CFlaahgra.cpp index bc707b59c..8df1d39ac 100644 --- a/Runtime/MP1/World/CFlaahgra.cpp +++ b/Runtime/MP1/World/CFlaahgra.cpp @@ -22,14 +22,29 @@ #include "TCastTo.hpp" // Generated file, do not modify include path namespace urde::MP1 { +constexpr zeus::CColor skDamageColor{0.5f, 0.5f, 0.f, 1.f}; +constexpr zeus::CColor skUnkColor{0.5f, 0.f, 0.f, 1.f}; +constexpr zeus::CVector3f skUnkVec1{0.5f, 7.f, 0.f}; -const SJointInfo CFlaahgra::skLeftArmJointList[3]{ - {"L_elbow", "L_blade", 0.6f, 1.f}, {"L_blade", "L_claw", 0.6f, 1.f}, {"L_CLAW_LCTR", "L_CLAW_END_LCTR", 0.6f, 1.f}}; +constexpr std::array skLeftArmJointList{{ + {"L_elbow", "L_blade", 0.6f, 1.f}, + {"L_blade", "L_claw", 0.6f, 1.f}, + {"L_CLAW_LCTR", "L_CLAW_END_LCTR", 0.6f, 1.f}, +}}; -const SJointInfo CFlaahgra::skRightArmJointList[3]{ - {"R_elbow", "R_blade", 0.6f, 1.f}, {"R_blade", "R_claw", 0.6f, 1.f}, {"R_CLAW_LCTR", "R_CLAW_END_LCTR", 0.6f, 1.f}}; -const SSphereJointInfo CFlaahgra::skSphereJointList[5]{ - {"Head_1", 1.5f}, {"Spine_2", 1.5f}, {"Spine_4", 1.5f}, {"Spine_6", 1.5f}, {"Collar", 1.5f}}; +constexpr std::array skRightArmJointList{{ + {"R_elbow", "R_blade", 0.6f, 1.f}, + {"R_blade", "R_claw", 0.6f, 1.f}, + {"R_CLAW_LCTR", "R_CLAW_END_LCTR", 0.6f, 1.f}, +}}; + +constexpr std::array skSphereJointList{{ + {"Head_1", 1.5f}, + {"Spine_2", 1.5f}, + {"Spine_4", 1.5f}, + {"Spine_6", 1.5f}, + {"Collar", 1.5f}, +}}; CFlaahgraData::CFlaahgraData(CInputStream& in) : x0_(in.readFloatBig()) @@ -121,8 +136,7 @@ void CFlaahgra::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM switch (msg) { case EScriptObjectMessage::InitializedInArea: { if (!x8e4_25_loading && !x8e4_24_loaded) { - const_cast(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()) - ->x113c_playerActorsLoading++; + mgr.GetWorld()->GetArea(GetAreaIdAlways())->GetPostConstructed()->x113c_playerActorsLoading++; x8e4_25_loading = true; } @@ -283,7 +297,9 @@ void CFlaahgra::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, E return; } case EUserEventType::BeginAction: { +#ifndef NDEBUG printf("BeginAction\n"); +#endif x8e4_26_ = true; x7c4_ = GetEndActionTime(); break; @@ -401,8 +417,7 @@ void CFlaahgra::LoadTokens(CStateManager& mgr) { void CFlaahgra::FinalizeLoad(CStateManager& mgr) { x8e4_24_loaded = true; if (x8e4_25_loading) { - const_cast(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()) - ->x113c_playerActorsLoading--; + mgr.GetWorld()->GetArea(GetAreaIdAlways())->GetPostConstructed()->x113c_playerActorsLoading--; x8e4_25_loading = false; } @@ -444,11 +459,11 @@ void CFlaahgra::GetMirrorWaypoints(CStateManager& mgr) { } } -void CFlaahgra::AddCollisionList(const SJointInfo* joints, int count, +void CFlaahgra::AddCollisionList(const SJointInfo* joints, size_t count, std::vector& outJoints) { const CAnimData* animData = GetModelData()->GetAnimationData(); - for (s32 i = 0; i < count; ++i) { + for (size_t i = 0; i < count; ++i) { const auto& joint = joints[i]; const CSegId from = animData->GetLocatorSegId(joint.from); const CSegId to = animData->GetLocatorSegId(joint.to); @@ -462,11 +477,11 @@ void CFlaahgra::AddCollisionList(const SJointInfo* joints, int count, } } -void CFlaahgra::AddSphereCollisionList(const SSphereJointInfo* joints, int count, +void CFlaahgra::AddSphereCollisionList(const SSphereJointInfo* joints, size_t count, std::vector& outJoints) { const CAnimData* animData = GetModelData()->GetAnimationData(); - for (s32 i = 0; i < count; ++i) { + for (size_t i = 0; i < count; ++i) { const auto& joint = joints[i]; const CSegId seg = animData->GetLocatorSegId(joint.name); @@ -499,20 +514,20 @@ void CFlaahgra::SetupHealthInfo(CStateManager& mgr) { void CFlaahgra::SetupCollisionManagers(CStateManager& mgr) { std::vector leftArmjointList; zeus::CVector3f oldScale = GetModelData()->GetScale(); - leftArmjointList.reserve(3); - AddCollisionList(skLeftArmJointList, 3, leftArmjointList); + leftArmjointList.reserve(skLeftArmJointList.size()); + AddCollisionList(skLeftArmJointList.data(), skLeftArmJointList.size(), leftArmjointList); x79c_leftArmCollision = std::make_unique(mgr, GetUniqueId(), GetAreaIdAlways(), leftArmjointList, true); SetMaterialProperties(x79c_leftArmCollision, mgr); std::vector rightArmJointList; - rightArmJointList.reserve(3); - AddCollisionList(skRightArmJointList, 3, rightArmJointList); + rightArmJointList.reserve(skRightArmJointList.size()); + AddCollisionList(skRightArmJointList.data(), skRightArmJointList.size(), rightArmJointList); x7a0_rightArmCollision = std::make_unique(mgr, GetUniqueId(), GetAreaIdAlways(), rightArmJointList, true); SetMaterialProperties(x7a0_rightArmCollision, mgr); std::vector sphereJointList; - sphereJointList.reserve(5); - AddSphereCollisionList(skSphereJointList, 5, sphereJointList); + sphereJointList.reserve(skSphereJointList.size()); + AddSphereCollisionList(skSphereJointList.data(), skSphereJointList.size(), sphereJointList); x7a4_sphereCollision = std::make_unique(mgr, GetUniqueId(), GetAreaIdAlways(), sphereJointList, true); SetMaterialProperties(x7a4_sphereCollision, mgr); @@ -872,7 +887,8 @@ void CFlaahgra::RattlePlayer(CStateManager& mgr, const zeus::CVector3f& vec) { } void CFlaahgra::Faint(CStateManager& mgr, EStateMsg msg, float arg) { - static const pas::ESeverity kSeverities[2]{pas::ESeverity::Zero, pas::ESeverity::One}; + static constexpr std::array kSeverities{pas::ESeverity::Zero, pas::ESeverity::One}; + if (msg == EStateMsg::Activate) { x568_ = 0; x7d4_ = 0.f; @@ -881,7 +897,7 @@ void CFlaahgra::Faint(CStateManager& mgr, EStateMsg msg, float arg) { SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); SendScriptMsgs(EScriptObjectState::Retreat, mgr, EScriptObjectMessage::None); x450_bodyController->GetCommandMgr().DeliverCmd( - CBCKnockDownCmd(-GetTransform().frontVector(), kSeverities[u32(x7ac_)])); + CBCKnockDownCmd(-GetTransform().frontVector(), kSeverities[size_t(x7ac_)])); } else if (msg == EStateMsg::Update) { if (x568_ == 0) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Fall) { @@ -890,7 +906,7 @@ void CFlaahgra::Faint(CStateManager& mgr, EStateMsg msg, float arg) { UpdateHeadDamageVulnerability(mgr, true); } else { x450_bodyController->GetCommandMgr().DeliverCmd( - CBCKnockDownCmd(-GetTransform().frontVector(), kSeverities[u32(x7ac_)])); + CBCKnockDownCmd(-GetTransform().frontVector(), kSeverities[size_t(x7ac_)])); } } else if (x568_ == 2) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LieOnGround) { @@ -942,12 +958,14 @@ void CFlaahgra::Dead(CStateManager& mgr, EStateMsg msg, float) { } } -static const pas::ESeverity kStates1[5]{pas::ESeverity::Invalid, pas::ESeverity::Invalid, pas::ESeverity::Invalid, - pas::ESeverity::Two, pas::ESeverity::Invalid}; - void CFlaahgra::Attack(CStateManager& mgr, EStateMsg msg, float arg) { - static const pas::ESeverity kSeverity[5]{pas::ESeverity::Three, pas::ESeverity::Four, pas::ESeverity::One, - pas::ESeverity::Zero, pas::ESeverity::Invalid}; + static constexpr std::array kStates1{ + pas::ESeverity::Invalid, pas::ESeverity::Invalid, pas::ESeverity::Invalid, + pas::ESeverity::Two, pas::ESeverity::Invalid, + }; + static constexpr std::array kSeverity{ + pas::ESeverity::Three, pas::ESeverity::Four, pas::ESeverity::One, pas::ESeverity::Zero, pas::ESeverity::Invalid, + }; if (msg == EStateMsg::Activate) { x568_ = 0; diff --git a/Runtime/MP1/World/CFlaahgra.hpp b/Runtime/MP1/World/CFlaahgra.hpp index b8f0e32d0..24bbfcd20 100644 --- a/Runtime/MP1/World/CFlaahgra.hpp +++ b/Runtime/MP1/World/CFlaahgra.hpp @@ -86,13 +86,6 @@ public: }; class CFlaahgra : public CPatterned { - - static const SJointInfo skLeftArmJointList[3]; - static const SJointInfo skRightArmJointList[3]; - static const SSphereJointInfo skSphereJointList[5]; - static constexpr zeus::CColor skDamageColor = zeus::CColor(0.5f, 0.5f, 0.f, 1.f); - static constexpr zeus::CColor skUnkColor = zeus::CColor(0.5f, 0.f, 0.f, 1.f); - static constexpr zeus::CVector3f skUnkVec1 = zeus::CVector3f(0.5f, 7.f, 0.f); s32 x568_ = -1; CFlaahgraData x56c_; std::unique_ptr x6cc_boneTracking; // Used to be an rstl::pair @@ -163,8 +156,8 @@ class CFlaahgra : public CPatterned { void LoadTokens(CStateManager& mgr); void FinalizeLoad(CStateManager& mgr); void GetMirrorWaypoints(CStateManager& mgr); - void AddCollisionList(const SJointInfo*, int, std::vector&); - void AddSphereCollisionList(const SSphereJointInfo*, int, std::vector&); + void AddCollisionList(const SJointInfo*, size_t, std::vector&); + void AddSphereCollisionList(const SSphereJointInfo*, size_t, std::vector&); void SetupCollisionManagers(CStateManager&); void sub801ae980(CStateManager&); void UpdateCollisionManagers(float, CStateManager&); diff --git a/Runtime/MP1/World/CMetroid.cpp b/Runtime/MP1/World/CMetroid.cpp index 8adbdbff1..0361fa327 100644 --- a/Runtime/MP1/World/CMetroid.cpp +++ b/Runtime/MP1/World/CMetroid.cpp @@ -23,6 +23,7 @@ CMetroid::CMetroid(TUniqueId uid, std::string_view name, EFlavorType flavor, con const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, const CMetroidData& metroidData, TUniqueId) : CPatterned(ECharacter::Metroid, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, - EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Medium) {} + EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Medium) +, x9bf_29_(false) {} } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroid.hpp b/Runtime/MP1/World/CMetroid.hpp index 1a547f75c..14c4d5b25 100644 --- a/Runtime/MP1/World/CMetroid.hpp +++ b/Runtime/MP1/World/CMetroid.hpp @@ -30,12 +30,7 @@ public: }; class CMetroid : public CPatterned { - union { - struct { - bool x9bf_29_ : 1; - }; - u32 _dummy = 0; - }; + bool x9bf_29_ : 1; public: DEFINE_PATTERNED(Metroid) diff --git a/Runtime/MP1/World/CMetroidBeta.cpp b/Runtime/MP1/World/CMetroidBeta.cpp index fac634659..6750f6006 100644 --- a/Runtime/MP1/World/CMetroidBeta.cpp +++ b/Runtime/MP1/World/CMetroidBeta.cpp @@ -56,7 +56,15 @@ CMetroidBeta::CMetroidBeta(TUniqueId uid, std::string_view name, const CEntityIn , x824_(std::make_unique(x7f0_, 0)) , x828_(std::make_unique(x7fc_)) , x82c_(std::make_unique(x808_)) -, x830_(std::make_unique(x814_)) { +, x830_(std::make_unique(x814_)) +, x840_24_(false) +, x840_25_(false) +, x840_26_(false) +, x840_27_(false) +, x840_28_(false) +, x840_29_(false) +, x840_30_(false) +, x840_31_(false) { x820_->SetParticleEmission(false); x828_->SetParticleEmission(false); x82c_->SetParticleEmission(false); diff --git a/Runtime/MP1/World/CMetroidBeta.hpp b/Runtime/MP1/World/CMetroidBeta.hpp index 5c421dcf6..0c4400203 100644 --- a/Runtime/MP1/World/CMetroidBeta.hpp +++ b/Runtime/MP1/World/CMetroidBeta.hpp @@ -75,19 +75,14 @@ class CMetroidBeta : public CPatterned { float x834_ = 0.f; CRandom16 x838_ = CRandom16(1469); float x83c_; - union { - struct { - bool x840_24_ : 1; - bool x840_25_ : 1; - bool x840_26_ : 1; - bool x840_27_ : 1; - bool x840_28_ : 1; - bool x840_29_ : 1; - bool x840_30_ : 1; - bool x840_31_ : 1; - }; - u32 _dummy = 0; - }; + bool x840_24_ : 1; + bool x840_25_ : 1; + bool x840_26_ : 1; + bool x840_27_ : 1; + bool x840_28_ : 1; + bool x840_29_ : 1; + bool x840_30_ : 1; + bool x840_31_ : 1; void CreateCollisionActorManager(CStateManager& mgr); void AddSphereJoints(SSphereJointInfo* sphereJoints, s32 count, std::vector& joints); diff --git a/Runtime/MP1/World/CNewIntroBoss.cpp b/Runtime/MP1/World/CNewIntroBoss.cpp index 7678f004c..d875b6801 100644 --- a/Runtime/MP1/World/CNewIntroBoss.cpp +++ b/Runtime/MP1/World/CNewIntroBoss.cpp @@ -1,5 +1,7 @@ #include "Runtime/MP1/World/CNewIntroBoss.hpp" +#include + #include "Runtime/CStateManager.hpp" #include "Runtime/Character/CCharLayoutInfo.hpp" #include "Runtime/Collision/CCollisionActor.hpp" @@ -13,6 +15,27 @@ namespace urde::MP1 { +constexpr std::array skSphereJoints{{ + {"Head_1", 1.5f}, + {"Tail_1", 1.5f}, +}}; + +constexpr std::array 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}}, + {"R_shoulder_front", "R_elbow_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}}, +}}; + CNewIntroBoss::CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, float minTurnAngle, CAssetId projectile, const CDamageInfo& dInfo, @@ -35,24 +58,6 @@ CNewIntroBoss::CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntity void CNewIntroBoss::Accept(IVisitor& visitor) { visitor.Visit(this); } -static const SSphereJointInfo skSphereJoints[] = {{"Head_1", 1.5f}, {"Tail_1", 1.5f}}; - -static const SOBBJointInfo 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}}, - {"R_shoulder_front", "R_elbow_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}}, -}; - void CNewIntroBoss::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { if (msg == EScriptObjectMessage::Registered) { RemoveMaterial(EMaterialTypes::Solid, mgr); diff --git a/Runtime/MP1/World/CParasite.cpp b/Runtime/MP1/World/CParasite.cpp index 07fb97d61..e21fed1f5 100644 --- a/Runtime/MP1/World/CParasite.cpp +++ b/Runtime/MP1/World/CParasite.cpp @@ -58,10 +58,19 @@ 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_24_receivedTelegraph(false) +, x742_25_jumpVelDirty(false) +, x742_26_(false) +, x742_27_landed(false) +, x742_28_onGround(true) +, x742_29_(false) +, x742_30_attackOver(true) +, x742_31_(false) +, x743_24_halted(false) +, x743_25_vulnerable(false) +, x743_26_oculusShotAt(false) +, x743_27_inJump(false) { switch (x5d0_walkerType) { case EWalkerType::Geemer: x460_knockBackController.SetEnableFreeze(false); diff --git a/Runtime/MP1/World/CParasite.hpp b/Runtime/MP1/World/CParasite.hpp index 1e673d124..69b07dc15 100644 --- a/Runtime/MP1/World/CParasite.hpp +++ b/Runtime/MP1/World/CParasite.hpp @@ -70,23 +70,19 @@ class CParasite : public CWallWalker { 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 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; + bool CloseToWall(const CStateManager& mgr) const; void FaceTarget(const zeus::CVector3f& target); TUniqueId RecursiveFindClosestWayPoint(CStateManager& mgr, TUniqueId id, float& dist); diff --git a/Runtime/MP1/World/CRipper.cpp b/Runtime/MP1/World/CRipper.cpp index bf9e8ee8d..45344ca70 100644 --- a/Runtime/MP1/World/CRipper.cpp +++ b/Runtime/MP1/World/CRipper.cpp @@ -21,8 +21,8 @@ CRipper::CRipper(TUniqueId uid, std::string_view name, EFlavorType type, const C {EMaterialTypes::Solid}, {EMaterialTypes::NoStaticCollision, EMaterialTypes::NoPlatformCollision, EMaterialTypes::Platform})); x460_knockBackController.SetAutoResetImpulse(false); - x460_knockBackController.SetAnimationStateRange(EKnockBackAnimationState::KnockBack, - EKnockBackAnimationState::Hurled); + x460_knockBackController.SetAnimationStateRange(EKnockBackAnimationState::Flinch, + EKnockBackAnimationState::KnockBack); } void CRipper::Think(float dt, CStateManager& mgr) { @@ -33,25 +33,23 @@ void CRipper::Think(float dt, CStateManager& mgr) { ProcessGrapplePoint(mgr); const CPlayer& pl = mgr.GetPlayer(); CGrappleArm::EArmState armState = pl.GetPlayerGun()->GetGrappleArm().GetAnimState(); - if (x598_grapplePoint == kInvalidUniqueId || pl.GetOrbitTargetId() != x598_grapplePoint || - pl.GetGrappleState() == CPlayer::EGrappleState::None) { - CPatterned::Think(dt, mgr); - if (x59c_24_muted) { - SetMuted(false); - x59c_24_muted = false; - } - } else { - if (armState == CGrappleArm::EArmState::FireGrapple) { - CPatterned::Think(dt, mgr); - } else if (armState == CGrappleArm::EArmState::IntoGrappleIdle || armState == CGrappleArm::EArmState::Three) { + if (x598_grapplePoint != kInvalidUniqueId && pl.GetOrbitTargetId() == x598_grapplePoint && pl.GetGrappleState() != CPlayer::EGrappleState::None) { + if (pl.GetGrappleState() != CPlayer::EGrappleState::Firing && (armState > CGrappleArm::EArmState::Three)) { Stop(); if (!x59c_24_muted) { SetMuted(true); x59c_24_muted = true; } + } else { + CPatterned::Think(dt, mgr); + } + } else { + CPatterned::Think(dt, mgr); + if (x59c_24_muted) { + SetMuted(false); + x59c_24_muted = false; } } - CPatterned::Think(dt, mgr); } void CRipper::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { @@ -73,7 +71,7 @@ void CRipper::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMan x450_bodyController->Activate(mgr); AddMaterial(EMaterialTypes::Immovable, mgr); RemoveMaterial(EMaterialTypes::Solid, mgr); - if (x3fc_flavor != EFlavorType::One) { + if (x3fc_flavor == EFlavorType::One) { AddGrapplePoint(mgr); RemoveMaterial(EMaterialTypes::Orbit, mgr); } @@ -96,7 +94,7 @@ void CRipper::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { } void CRipper::ProcessGrapplePoint(CStateManager& mgr) { - if (x3fc_flavor == EFlavorType::One || x598_grapplePoint == kInvalidUniqueId) + if (x3fc_flavor != EFlavorType::One || x598_grapplePoint == kInvalidUniqueId) return; if (TCastToPtr gp = mgr.ObjectById(x598_grapplePoint)) { @@ -109,7 +107,7 @@ void CRipper::AddGrapplePoint(CStateManager& mgr) { return; x598_grapplePoint = mgr.AllocateUniqueId(); - mgr.AddObject(new CScriptGrapplePoint(x59a_platformId, "RipperGrapplePoint"sv, + mgr.AddObject(new CScriptGrapplePoint(x598_grapplePoint, "RipperGrapplePoint"sv, CEntityInfo(GetAreaIdAlways(), NullConnectionList), GetTransform(), true, x568_grappleParams)); } diff --git a/Runtime/MP1/World/CSpacePirate.cpp b/Runtime/MP1/World/CSpacePirate.cpp index 409a11e5b..5fe62cdf7 100644 --- a/Runtime/MP1/World/CSpacePirate.cpp +++ b/Runtime/MP1/World/CSpacePirate.cpp @@ -418,6 +418,7 @@ CSpacePirate::CSpacePirate(TUniqueId uid, std::string_view name, const CEntityIn x637_24_enablePatrol = false; x637_25_enableAim = false; x637_26_hearPlayerFire = false; + x637_27_inProjectilePath = false; x637_28_noPlayerLos = false; x637_29_inWallHang = false; x637_30_jumpVelSet = false; @@ -438,6 +439,7 @@ CSpacePirate::CSpacePirate(TUniqueId uid, std::string_view name, const CEntityIn x639_29_enableBreakDodge = false; x639_30_closeMelee = false; x639_31_sentAttackMsg = false; + x63a_24_normalDodge = false; x758_headSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("Head_1"sv); x7b6_gunSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("R_gun_LCTR"sv); @@ -2080,7 +2082,7 @@ void CSpacePirate::Cover(CStateManager& mgr, EStateMsg msg, float dt) { case EStateMsg::Activate: if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Cover) { if (CScriptCoverPoint* cp = GetCoverPoint(mgr, x640_coverPoint)) { - x79c_coverDir = (cp->GetAttackDirection() & 0x2) ? pas::ECoverDirection::Left : pas::ECoverDirection::Right; + x79c_coverDir = cp->GetAttackDirection(); x32c_animState = EAnimState::Ready; x2e0_destPos = cp->GetTranslation(); TryCommand(mgr, pas::EAnimationState::Cover, &CPatterned::TryCover, int(x79c_coverDir)); diff --git a/Runtime/MP1/World/CSpacePirate.hpp b/Runtime/MP1/World/CSpacePirate.hpp index 0663fd803..89e61b92d 100644 --- a/Runtime/MP1/World/CSpacePirate.hpp +++ b/Runtime/MP1/World/CSpacePirate.hpp @@ -97,61 +97,56 @@ private: }; CSpacePirateData x568_pirateData; - union { - struct { - bool x634_24_pendingAmbush : 1; - bool x634_25_ceilingAmbush : 1; - bool x634_26_nonAggressive : 1; - bool x634_27_melee : 1; - bool x634_28_noShuffleCloseCheck : 1; - bool x634_29_onlyAttackInRange : 1; - bool x634_30_ : 1; - bool x634_31_noKnockbackImpulseReset : 1; - bool x635_24_noMeleeAttack : 1; - bool x635_25_breakAttack : 1; - bool x635_26_seated : 1; - bool x635_27_shadowPirate : 1; - bool x635_28_alertBeforeCloak : 1; - bool x635_29_noBreakDodge : 1; - bool x635_30_floatingCorpse : 1; - bool x635_31_ragdollNoAiCollision : 1; - bool x636_24_trooper : 1; - bool x636_25_hearNoise : 1; - bool x636_26_enableMeleeAttack : 1; - bool x636_27_ : 1; - bool x636_28_ : 1; - bool x636_29_enableRetreat : 1; - bool x636_30_shuffleClose : 1; - bool x636_31_inAttackState : 1; - bool x637_24_enablePatrol : 1; - bool x637_25_enableAim : 1; - bool x637_26_hearPlayerFire : 1; - bool x637_27_inProjectilePath : 1; - bool x637_28_noPlayerLos : 1; - bool x637_29_inWallHang : 1; - bool x637_30_jumpVelSet : 1; - bool x637_31_prevInCineCam : 1; - bool x638_24_pendingFrenzyChance : 1; - bool x638_25_appliedBladeDamage : 1; - bool x638_26_alwaysAggressive : 1; - bool x638_27_coverCheck : 1; - bool x638_28_enableDodge : 1; - bool x638_29_noPlayerDodge : 1; - bool x638_30_ragdollOver : 1; - bool x638_31_mayStartAttack : 1; - bool x639_24_ : 1; - bool x639_25_useJumpBackJump : 1; - bool x639_26_started : 1; - bool x639_27_inRange : 1; - bool x639_28_satUp : 1; - bool x639_29_enableBreakDodge : 1; - bool x639_30_closeMelee : 1; - bool x639_31_sentAttackMsg : 1; - bool x63a_24_normalDodge : 1; - }; - u64 _dummy = 0; - }; + bool x634_24_pendingAmbush : 1; + bool x634_25_ceilingAmbush : 1; + bool x634_26_nonAggressive : 1; + bool x634_27_melee : 1; + bool x634_28_noShuffleCloseCheck : 1; + bool x634_29_onlyAttackInRange : 1; + bool x634_30_ : 1; + bool x634_31_noKnockbackImpulseReset : 1; + bool x635_24_noMeleeAttack : 1; + bool x635_25_breakAttack : 1; + bool x635_26_seated : 1; + bool x635_27_shadowPirate : 1; + bool x635_28_alertBeforeCloak : 1; + bool x635_29_noBreakDodge : 1; + bool x635_30_floatingCorpse : 1; + bool x635_31_ragdollNoAiCollision : 1; + bool x636_24_trooper : 1; + bool x636_25_hearNoise : 1; + bool x636_26_enableMeleeAttack : 1; + bool x636_27_ : 1; + bool x636_28_ : 1; + bool x636_29_enableRetreat : 1; + bool x636_30_shuffleClose : 1; + bool x636_31_inAttackState : 1; + bool x637_24_enablePatrol : 1; + bool x637_25_enableAim : 1; + bool x637_26_hearPlayerFire : 1; + bool x637_27_inProjectilePath : 1; + bool x637_28_noPlayerLos : 1; + bool x637_29_inWallHang : 1; + bool x637_30_jumpVelSet : 1; + bool x637_31_prevInCineCam : 1; + bool x638_24_pendingFrenzyChance : 1; + bool x638_25_appliedBladeDamage : 1; + bool x638_26_alwaysAggressive : 1; + bool x638_27_coverCheck : 1; + bool x638_28_enableDodge : 1; + bool x638_29_noPlayerDodge : 1; + bool x638_30_ragdollOver : 1; + bool x638_31_mayStartAttack : 1; + bool x639_24_ : 1; + bool x639_25_useJumpBackJump : 1; + bool x639_26_started : 1; + bool x639_27_inRange : 1; + bool x639_28_satUp : 1; + bool x639_29_enableBreakDodge : 1; + bool x639_30_closeMelee : 1; + bool x639_31_sentAttackMsg : 1; + bool x63a_24_normalDodge : 1; s32 x63c_frenzyFrames = 0; TUniqueId x640_coverPoint = kInvalidUniqueId; diff --git a/Runtime/MP1/World/CSpankWeed.cpp b/Runtime/MP1/World/CSpankWeed.cpp index 223d1dc20..ba062bb5f 100644 --- a/Runtime/MP1/World/CSpankWeed.cpp +++ b/Runtime/MP1/World/CSpankWeed.cpp @@ -1,5 +1,7 @@ #include "Runtime/MP1/World/CSpankWeed.hpp" +#include + #include "Runtime/CStateManager.hpp" #include "Runtime/Collision/CCollisionActor.hpp" #include "Runtime/World/CPatternedInfo.hpp" @@ -9,6 +11,17 @@ namespace urde::MP1 { logvisor::Module SpankLog("urde::MP1::SpankWeed"); + +constexpr std::array 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}, +}}; + 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) @@ -29,7 +42,7 @@ CSpankWeed::CSpankWeed(TUniqueId uid, std::string_view name, const CEntityInfo& GetModelData()->SetScale(zeus::CVector3f(scale)); SpankLog.report(logvisor::Level::Warning, - fmt("WARNING: Non-uniform scale {} applied to Spank Weed" + FMT_STRING("WARNING: Non-uniform scale {} applied to Spank Weed" "...changing scale to ({} {} {})\n"), modelScale, scale, scale, scale); } @@ -48,9 +61,6 @@ CSpankWeed::CSpankWeed(TUniqueId uid, std::string_view name, const CEntityInfo& x460_knockBackController.SetAutoResetImpulse(false); } -static const SSphereJointInfo 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) { diff --git a/Runtime/MP1/World/CThardus.cpp b/Runtime/MP1/World/CThardus.cpp index d0f8f6763..0961b8c14 100644 --- a/Runtime/MP1/World/CThardus.cpp +++ b/Runtime/MP1/World/CThardus.cpp @@ -920,7 +920,7 @@ void CThardus::sub801dae2c(CStateManager& mgr, u32 rockIndex) { void CThardus::sub801dc444(CStateManager& mgr, const zeus::CVector3f& pos, CAssetId particle) { u32 w = x6f4_; ++x6f4_; - std::string particleName = fmt::format(fmt("ROCK_EFFECT{}-{}"), particle.Value(), w); + std::string particleName = fmt::format(FMT_STRING("ROCK_EFFECT{}-{}"), particle.Value(), w); GetModelData()->GetAnimationData()->GetParticleDB().AddAuxiliaryParticleEffect( particleName, 0x40, CAuxiliaryParticleData(0, {FOURCC('PART'), particle}, pos, 1.f), 2.f * GetModelData()->GetScale(), mgr, GetAreaIdAlways(), 0); @@ -977,7 +977,7 @@ void CThardus::UpdateExcludeList(const std::unique_ptr& } } -void CThardus::RenderFlare(const CStateManager& mgr, float t) const { +void CThardus::RenderFlare(const CStateManager& mgr, float t) { if (!x91c_flareTexture) return; if (!m_flareFilter) diff --git a/Runtime/MP1/World/CThardus.hpp b/Runtime/MP1/World/CThardus.hpp index 1fdb108b3..85a16cb14 100644 --- a/Runtime/MP1/World/CThardus.hpp +++ b/Runtime/MP1/World/CThardus.hpp @@ -159,11 +159,11 @@ class CThardus : public CPatterned { void _SetupCollisionManagers(CStateManager& mgr); void _BuildSphereJointList(const SSphereJointInfo* arr, size_t count, std::vector& list); void _BuildAABoxJointList(const SAABoxJointInfo* arr, size_t count, std::vector& list); - void RenderFlare(const CStateManager& mgr, float t) const; + void RenderFlare(const CStateManager& mgr, float t); zeus::CVector3f sub801de550(const CStateManager& mgr) const; zeus::CVector3f sub801de434(const CStateManager& mgr) const { return {}; } - mutable std::optional m_flareFilter; + std::optional m_flareFilter; public: DEFINE_PATTERNED(Thardus) diff --git a/Runtime/MP1/World/CWarWasp.cpp b/Runtime/MP1/World/CWarWasp.cpp index 69da69330..eaddc3e1e 100644 --- a/Runtime/MP1/World/CWarWasp.cpp +++ b/Runtime/MP1/World/CWarWasp.cpp @@ -1,5 +1,7 @@ #include "Runtime/MP1/World/CWarWasp.hpp" +#include + #include "Runtime/CSimplePool.hpp" #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/Character/CCharLayoutInfo.hpp" @@ -24,9 +26,15 @@ CWarWasp::CWarWasp(TUniqueId uid, std::string_view name, const CEntityInfo& info , x590_pfSearch(nullptr, 0x3, pInfo.GetPathfindingIndex(), 1.f, 1.f) , x684_(dInfo1) , x6d4_projectileInfo(projectileWeapon, projectileDamage) -, x72c_projectileVisorSfx(CSfxManager::TranslateSFXID(projecileVisorSfx)) { - x72e_24_jumpBackRepeat = true; - x72e_26_initiallyInactive = !pInfo.GetActive(); +, x72c_projectileVisorSfx(CSfxManager::TranslateSFXID(projecileVisorSfx)) +, x72e_24_jumpBackRepeat(true) +, x72e_25_canApplyDamage(false) +, x72e_26_initiallyInactive(!pInfo.GetActive()) +, x72e_27_teamMatesMelee(false) +, x72e_28_inProjectileAttack(false) +, x72e_29_pathObstructed(false) +, x72e_30_isRetreating(false) +, x72e_31_heardNoise(false) { x6d4_projectileInfo.Token().Lock(); UpdateTouchBounds(); SetCoefficientOfRestitutionModifier(0.1f); @@ -877,9 +885,9 @@ float CWarWasp::GetTeamZStratum(s32 team) const { return 0.f; } -static const float Table[] = {0.4f, 0.6f, 1.f}; - float CWarWasp::CalcSeekMagnitude(const CStateManager& mgr) const { + static constexpr std::array Table{0.4f, 0.6f, 1.f}; + const float ret = ((x708_circleAttackTeam >= 0 && x708_circleAttackTeam < 3) ? Table[x708_circleAttackTeam] : 1.f) * 0.9f; if (TCastToConstPtr aimgr = mgr.GetObjectById(x674_aiMgr)) { if (aimgr->IsPartOfTeam(GetUniqueId())) { diff --git a/Runtime/MP1/World/CWarWasp.hpp b/Runtime/MP1/World/CWarWasp.hpp index 86cb01aaa..b5b5f84d8 100644 --- a/Runtime/MP1/World/CWarWasp.hpp +++ b/Runtime/MP1/World/CWarWasp.hpp @@ -33,19 +33,15 @@ class CWarWasp : public CPatterned { float x718_circleBurstOffTotemAngle = zeus::degToRad(90.f); TLockedToken x71c_projectileVisorParticle; // Used to be optional u16 x72c_projectileVisorSfx; - union { - struct { - bool x72e_24_jumpBackRepeat : 1; - bool x72e_25_canApplyDamage : 1; - bool x72e_26_initiallyInactive : 1; - bool x72e_27_teamMatesMelee : 1; - bool x72e_28_inProjectileAttack : 1; - bool x72e_29_pathObstructed : 1; - bool x72e_30_isRetreating : 1; - bool x72e_31_heardNoise : 1; - }; - u32 _dummy = 0; - }; + bool x72e_24_jumpBackRepeat : 1; + bool x72e_25_canApplyDamage : 1; + bool x72e_26_initiallyInactive : 1; + bool x72e_27_teamMatesMelee : 1; + bool x72e_28_inProjectileAttack : 1; + bool x72e_29_pathObstructed : 1; + bool x72e_30_isRetreating : 1; + bool x72e_31_heardNoise : 1; + void SwarmAdd(CStateManager& mgr); void SwarmRemove(CStateManager& mgr); void ApplyDamage(CStateManager& mgr); diff --git a/Runtime/Particle/CColorElement.cpp b/Runtime/Particle/CColorElement.cpp index 05489c698..0a8c7722d 100644 --- a/Runtime/Particle/CColorElement.cpp +++ b/Runtime/Particle/CColorElement.cpp @@ -123,17 +123,16 @@ 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); + int cv = a + b + 1; + if (cv < 0) { + cv = 1; + } - if (b >= 1) { - int cv2 = frame % cv; - if (cv2 >= a) - x10_bVal->GetValue(frame, valOut); - else - xc_aVal->GetValue(frame, valOut); - } else + if (b < 1 || frame % cv <= a) { xc_aVal->GetValue(frame, valOut); - + } else { + x10_bVal->GetValue(frame, valOut); + } return false; } diff --git a/Runtime/Particle/CDecal.cpp b/Runtime/Particle/CDecal.cpp index c18156852..77f357a31 100644 --- a/Runtime/Particle/CDecal.cpp +++ b/Runtime/Particle/CDecal.cpp @@ -9,7 +9,7 @@ CRandom16 CDecal::sDecalRandom; bool CDecal::sMoveRedToAlphaBuffer = false; CDecal::CDecal(const TToken& desc, const zeus::CTransform& xf) -: x0_description(desc), xc_transform(xf) { +: x0_description(desc), xc_transform(xf), x5c_29_modelInvalid(false) { CGlobalRandom gr(sDecalRandom); CDecalDescription& desco = *x0_description; @@ -219,14 +219,14 @@ void CDecal::RenderMdl() { CGraphics::SetModelMatrix(worldXf); if (desc.x5c_24_DMAB) { - CModelFlags flags(7, 0, 1, color); + const 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::skWhite); + constexpr CModelFlags flags(0, 0, 3, zeus::skWhite); desc.x38_DMDL.m_token->Draw(flags); } else { - CModelFlags flags(5, 0, 1, color); + const CModelFlags flags(5, 0, 1, color); desc.x38_DMDL.m_token->Draw(flags); } } diff --git a/Runtime/Particle/CDecal.hpp b/Runtime/Particle/CDecal.hpp index 224658da1..6417e052e 100644 --- a/Runtime/Particle/CDecal.hpp +++ b/Runtime/Particle/CDecal.hpp @@ -13,17 +13,12 @@ namespace urde { struct SQuadDescr; struct CQuadDecal { - union { - struct { - bool x0_24_invalid : 1; - }; - u32 _dummy = 0; - }; + 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; } + CQuadDecal() : x0_24_invalid(true) {} + CQuadDecal(s32 i, float f) : x0_24_invalid(true), x4_lifetime(i), x8_rotation(f) {} boo::ObjToken m_instBuf; boo::ObjToken m_uniformBuf; @@ -41,14 +36,9 @@ class CDecal { std::array x3c_decalQuads; 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; - }; + 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); diff --git a/Runtime/Particle/CDecalDataFactory.cpp b/Runtime/Particle/CDecalDataFactory.cpp index 48ea6300a..edb35b7f2 100644 --- a/Runtime/Particle/CDecalDataFactory.cpp +++ b/Runtime/Particle/CDecalDataFactory.cpp @@ -85,7 +85,7 @@ bool CDecalDataFactory::CreateDPSM(CDecalDescription* desc, CInputStream& in, CS desc->x5c_25_DMOO = CPF::GetBool(in); break; default: { - Log.report(logvisor::Fatal, fmt("Unknown DPSC class {} @{}"), clsId, in.position()); + Log.report(logvisor::Fatal, FMT_STRING("Unknown DPSC class {} @{}"), clsId, in.position()); return false; } } diff --git a/Runtime/Particle/CDecalDescription.hpp b/Runtime/Particle/CDecalDescription.hpp index ff1d74afa..7d0038a2e 100644 --- a/Runtime/Particle/CDecalDescription.hpp +++ b/Runtime/Particle/CDecalDescription.hpp @@ -23,6 +23,8 @@ struct SQuadDescr { class CDecalDescription { public: + CDecalDescription() : x5c_24_DMAB(false), x5c_25_DMOO(false) {} + SQuadDescr x0_Quads[2]; SParticleModel x38_DMDL; std::unique_ptr x48_DLFT; @@ -30,13 +32,8 @@ public: 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; - }; - u32 dummy = 0; - }; + bool x5c_24_DMAB : 1; + bool x5c_25_DMOO : 1; }; } // namespace urde diff --git a/Runtime/Particle/CDecalManager.cpp b/Runtime/Particle/CDecalManager.cpp index 831d5c6f7..19b94ec98 100644 --- a/Runtime/Particle/CDecalManager.cpp +++ b/Runtime/Particle/CDecalManager.cpp @@ -21,8 +21,9 @@ void CDecalManager::Initialize() { return; m_DecalPool.clear(); - for (int i = 0; i < 64; ++i) - m_DecalPool.emplace_back(std::optional{}, 0, i - 1, false); + for (int i = 0; i < 64; ++i) { + m_DecalPool.emplace_back(std::nullopt, 0, i - 1, false); + } m_FreeIndex = 63; m_PoolInitialized = true; @@ -39,8 +40,9 @@ void CDecalManager::Reinitialize() { Initialize(); m_DecalPool.clear(); - for (int i = 0; i < 64; ++i) - m_DecalPool.emplace_back(std::optional{}, 0, i - 1, false); + for (int i = 0; i < 64; ++i) { + m_DecalPool.emplace_back(std::nullopt, 0, i - 1, false); + } m_ActiveIndexList.clear(); diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index 1353886a9..88a3b754c 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -54,12 +54,25 @@ void CElementGen::Initialize() { void CElementGen::Shutdown() { CElementGenShaders::Shutdown(); } CElementGen::CElementGen(TToken gen, EModelOrientationType orientType, EOptionalSystemFlags flags) -: x1c_genDesc(std::move(gen)), x2c_orientType(orientType), x27c_randState(x94_randomSeed) { +: x1c_genDesc(std::move(gen)) +, x2c_orientType(orientType) +, x26c_24_translationDirty(false) +, x26c_25_LIT_(false) +, x26c_26_AAPH(false) +, x26c_27_ZBUF(false) +, x26c_28_zTest(false) +, x26c_29_ORNT(false) +, x26c_30_MBLR(false) +, x26c_31_LINE(false) +, x26d_24_FXLL(false) +, x26d_25_warmedUp(false) +, x26d_26_modelsUseLights(false) +, x26d_27_enableOPTS(True(flags & EOptionalSystemFlags::Two)) +, x26d_28_enableADV(false) +, x27c_randState(x94_randomSeed) { CGenDescription* desc = x1c_genDesc.GetObj(); x28_loadedGenDesc = desc; - x26d_27_enableOPTS = True(flags & EOptionalSystemFlags::Two); - if (desc->x54_x40_TEXR) desc->x54_x40_TEXR->GetValueTexture(0).GetObj(); if (desc->x58_x44_TIND) @@ -242,7 +255,7 @@ bool CElementGen::Update(double t) { if (pswtElem && !x26d_25_warmedUp) { int pswt = 0; pswtElem->GetValue(x74_curFrame, pswt); - //Log.report(logvisor::Info, fmt("Running warmup on particle system 0x%08x for %d ticks."), desc, pswt); + //Log.report(logvisor::Info, FMT_STRING("Running warmup on particle system 0x%08x for %d ticks."), desc, pswt); InternalUpdate((1.f / 60.f) * pswt); x26d_25_warmedUp = true; } @@ -800,7 +813,7 @@ u32 CElementGen::GetSystemCount() const { } void CElementGen::Render(const CActorLights* actorLights) { - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CElementGen::Render {}"), + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CElementGen::Render {}"), *x1c_genDesc.GetObjectTag()).c_str(), zeus::skYellow); CGenDescription* desc = x1c_genDesc.GetObj(); @@ -885,7 +898,7 @@ void CElementGen::RenderModels(const CActorLights* actorLights) { g_instNoTexData.reserve(x30_particles.size()); break; default: - Log.report(logvisor::Fatal, fmt("unexpected particle shader class")); + Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class")); break; } @@ -1123,8 +1136,7 @@ void CElementGen::RenderLines() { m_lineRenderer->Reset(); - for (size_t i = 0; i < x30_particles.size(); ++i) { - CParticle& particle = x30_particles[i]; + for (auto& particle : x30_particles) { g_currentParticle = &particle; int partFrame = x74_curFrame - particle.x28_startFrame; @@ -1297,7 +1309,7 @@ void CElementGen::RenderParticles() { g_instNoTexData.reserve(x30_particles.size()); break; default: - Log.report(logvisor::Fatal, fmt("unexpected particle shader class")); + Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class")); break; } @@ -1486,7 +1498,7 @@ void CElementGen::RenderParticles() { g_instNoTexData.reserve(x30_particles.size() * mbspVal); break; default: - Log.report(logvisor::Fatal, fmt("unexpected particle shader class")); + Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class")); break; } const float mbspFac = 1.f / float(mbspVal); diff --git a/Runtime/Particle/CElementGen.hpp b/Runtime/Particle/CElementGen.hpp index 26ec47598..4441e45db 100644 --- a/Runtime/Particle/CElementGen.hpp +++ b/Runtime/Particle/CElementGen.hpp @@ -60,7 +60,7 @@ private: int x70_internalStartFrame = 0; int x74_curFrame = 0; double x78_curSeconds = 0.f; - float x80_timeDeltaScale; + float x80_timeDeltaScale = 0.f; int x84_prevFrame = -1; bool x88_particleEmission = true; float x8c_generatorRemainder = 0.f; @@ -87,26 +87,19 @@ private: 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; - }; - + 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; int x270_MBSP = 0; int m_maxMBSP = 0; ERglLightBits x274_backupLightActive = ERglLightBits::None; diff --git a/Runtime/Particle/CFlameWarp.cpp b/Runtime/Particle/CFlameWarp.cpp index 23ea08edf..2cc4e6e68 100644 --- a/Runtime/Particle/CFlameWarp.cpp +++ b/Runtime/Particle/CFlameWarp.cpp @@ -19,9 +19,9 @@ void CFlameWarp::ModifyParticles(std::vector& particles) { float maxTransp = 0.f; u8 idx = 0; for (CParticle& particle : particles) { - float transp = 1.f - particle.x34_color.a(); + const float transp = 1.f - particle.x34_color.a(); if (transp > maxTransp) { - float distSq = (particle.x4_pos - x74_warpPoint).magSquared(); + const float distSq = (particle.x4_pos - x74_warpPoint).magSquared(); if (distSq > x8c_maxDistSq && distSq < x98_maxInfluenceDistSq) { x8c_maxDistSq = distSq; maxTransp = transp; @@ -29,28 +29,30 @@ void CFlameWarp::ModifyParticles(std::vector& particles) { } } - if (particle.x2c_lineLengthOrSize < x90_minSize) + if (particle.x2c_lineLengthOrSize < x90_minSize) { x90_minSize = particle.x2c_lineLengthOrSize; - if (particle.x2c_lineLengthOrSize > x94_maxSize) + } + 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; + const 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( + const zeus::CVector3f deltaNorm = delta.normalized(); + const zeus::CVector3f behindPos = particle.x10_prevPos - deltaNorm * 5.f; + const zeus::CVector3f fullDelta = particle.x4_pos - behindPos; + const 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); + const 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; + const 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) * @@ -91,8 +93,9 @@ void CFlameWarp::ResetPosition(const zeus::CVector3f& pos) { zeus::CAABox CFlameWarp::CalculateBounds() const { zeus::CAABox ret; - for (const auto& v : x4_collisionPoints) + for (const auto& v : x4_collisionPoints) { ret.accumulateBounds(v); + } return ret; } diff --git a/Runtime/Particle/CGenDescription.hpp b/Runtime/Particle/CGenDescription.hpp index bde4b376d..5661d62c4 100644 --- a/Runtime/Particle/CGenDescription.hpp +++ b/Runtime/Particle/CGenDescription.hpp @@ -39,30 +39,25 @@ public: // 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; - }; - u32 dummy1 = 0; - }; + 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; @@ -112,7 +107,25 @@ public: /* Custom additions */ std::unique_ptr m_bevelGradient; /* FourCC BGCL */ - CGenDescription() { x45_25_x31_27_PMOO = true; } + CGenDescription() + : x44_28_x30_28_SORT(false) + , x44_30_x31_24_MBLR(false) + , x44_24_x30_24_LINE(false) + , x44_29_x30_29_LIT_(false) + , x44_26_x30_26_AAPH(false) + , x44_27_x30_27_ZBUF(false) + , x44_25_x30_25_FXLL(false) + , x44_31_x31_25_PMAB(false) + , x45_29_x31_31_VMD4(false) + , x45_28_x31_30_VMD3(false) + , x45_27_x31_29_VMD2(false) + , x45_26_x31_28_VMD1(false) + , x45_31_x32_25_OPTS(false) + , x45_24_x31_26_PMUS(false) + , x45_25_x31_27_PMOO(true) + , x45_30_x32_24_CIND(false) + , x30_30_ORNT(false) + , x30_31_RSOP(false) {} }; } // namespace urde diff --git a/Runtime/Particle/CIntElement.cpp b/Runtime/Particle/CIntElement.cpp index 591bf4d93..44b69b65d 100644 --- a/Runtime/Particle/CIntElement.cpp +++ b/Runtime/Particle/CIntElement.cpp @@ -158,17 +158,16 @@ 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 cv = a + b + 1; + if (cv < 0) { + cv = 1; + } - if (b >= 1) { - int cv2 = frame % cv; - if (cv2 >= a) - x10_bVal->GetValue(frame, valOut); - else - xc_aVal->GetValue(frame, valOut); - } else + if (b < 1 || frame % cv <= a) { xc_aVal->GetValue(frame, valOut); - + } else { + x10_bVal->GetValue(frame, valOut); + } return false; } diff --git a/Runtime/Particle/CIntElement.hpp b/Runtime/Particle/CIntElement.hpp index f2a8a4267..f9d490b86 100644 --- a/Runtime/Particle/CIntElement.hpp +++ b/Runtime/Particle/CIntElement.hpp @@ -137,7 +137,7 @@ class CIESampleAndHold : public CIntElement { mutable int x8_nextSampleFrame = 0; std::unique_ptr xc_waitFramesMin; std::unique_ptr x10_waitFramesMax; - mutable int x14_holdVal; + mutable int x14_holdVal = 0; public: CIESampleAndHold(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) diff --git a/Runtime/Particle/CModVectorElement.cpp b/Runtime/Particle/CModVectorElement.cpp index 95cf05124..6b5ec2d29 100644 --- a/Runtime/Particle/CModVectorElement.cpp +++ b/Runtime/Particle/CModVectorElement.cpp @@ -202,17 +202,16 @@ bool CMVEPulse::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos int a, b; x4_aDuration->GetValue(frame, a); x8_bDuration->GetValue(frame, b); - int cv = std::max(1, a + b + 1); + int cv = a + b + 1; + if (cv < 0) { + cv = 1; + } - if (b >= 1) { - int cv2 = frame % cv; - if (cv2 >= a) - x10_bVal->GetValue(frame, pVel, pPos); - else - xc_aVal->GetValue(frame, pVel, pPos); - } else + if (b < 1 || frame % cv <= a) { xc_aVal->GetValue(frame, pVel, pPos); - + } else { + x10_bVal->GetValue(frame, pVel, pPos); + } return false; } diff --git a/Runtime/Particle/CParticleDataFactory.cpp b/Runtime/Particle/CParticleDataFactory.cpp index cf0b89f2b..ae6c5eedf 100644 --- a/Runtime/Particle/CParticleDataFactory.cpp +++ b/Runtime/Particle/CParticleDataFactory.cpp @@ -18,7 +18,7 @@ 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, fmt("bool element does not begin with CNST")); + Log.report(logvisor::Fatal, FMT_STRING("bool element does not begin with CNST")); return in.readBool(); } @@ -984,7 +984,7 @@ bool CParticleDataFactory::CreateGPSM(CGenDescription* fillDesc, CInputStream& i fillDesc->xec_xd8_SELC = GetElectricGeneratorDesc(in, resPool); break; default: { - Log.report(logvisor::Fatal, fmt("Unknown GPSM class {} @{}"), clsId, in.position()); + Log.report(logvisor::Fatal, FMT_STRING("Unknown GPSM class {} @{}"), clsId, in.position()); return false; } } diff --git a/Runtime/Particle/CParticleDataFactory.hpp b/Runtime/Particle/CParticleDataFactory.hpp index 6b37cc4b2..7cf3527aa 100644 --- a/Runtime/Particle/CParticleDataFactory.hpp +++ b/Runtime/Particle/CParticleDataFactory.hpp @@ -30,7 +30,7 @@ struct SParticleModel { 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; } + explicit operator bool() const { return m_found; } }; struct SChildGeneratorDesc { @@ -39,7 +39,7 @@ struct SChildGeneratorDesc { 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; } + explicit operator bool() const { return m_found; } }; struct SSwooshGeneratorDesc { @@ -48,7 +48,7 @@ struct SSwooshGeneratorDesc { 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; } + explicit operator bool() const { return m_found; } }; struct SElectricGeneratorDesc { @@ -57,7 +57,7 @@ struct SElectricGeneratorDesc { 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; } + explicit operator bool() const { return m_found; } }; class CParticleDataFactory { diff --git a/Runtime/Particle/CParticleElectric.cpp b/Runtime/Particle/CParticleElectric.cpp index 355b8aaaa..b7584b936 100644 --- a/Runtime/Particle/CParticleElectric.cpp +++ b/Runtime/Particle/CParticleElectric.cpp @@ -1,5 +1,7 @@ #include "Runtime/Particle/CParticleElectric.hpp" +#include + #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/Graphics/CBooRenderer.hpp" #include "Runtime/Graphics/CGraphics.hpp" @@ -19,25 +21,33 @@ namespace urde { u16 CParticleElectric::g_GlobalSeed = 99; CParticleElectric::CParticleElectric(const TToken& token) -: x1c_elecDesc(token), x14c_randState(g_GlobalSeed++) { +: x1c_elecDesc(token) +, x14c_randState(g_GlobalSeed++) +, x450_24_emitting(true) +, x450_25_haveGPSM(false) +, x450_26_haveEPSM(false) +, x450_27_haveSSWH(false) +, x450_28_haveLWD(false) +, x450_29_transformDirty(true) { x1bc_allocated.resize(32); - x450_24_emitting = true; - x450_29_transformDirty = true; CElectricDescription* desc = x1c_elecDesc.GetObj(); - if (CIntElement* sseg = desc->x10_SSEG.get()) + if (CIntElement* sseg = desc->x10_SSEG.get()) { sseg->GetValue(x28_currentFrame, x150_SSEG); + } - if (CIntElement* scnt = desc->xc_SCNT.get()) + if (CIntElement* scnt = desc->xc_SCNT.get()) { scnt->GetValue(x28_currentFrame, x154_SCNT); + } x154_SCNT = std::min(x154_SCNT, 32); - if (CIntElement* life = desc->x0_LIFE.get()) + if (CIntElement* life = desc->x0_LIFE.get()) { life->GetValue(0, x2c_LIFE); - else + } else { x2c_LIFE = INT_MAX; + } if (desc->x40_SSWH) { x450_27_haveSSWH = true; @@ -79,8 +89,9 @@ CParticleElectric::CParticleElectric(const TToken& token) } void CParticleElectric::RenderSwooshes() { - for (CParticleElectricManager& elec : x3e8_electricManagers) + for (const CParticleElectricManager& elec : x3e8_electricManagers) { x1e0_swooshGenerators[elec.x0_idx]->Render(); + } } void CParticleElectric::SetupLineGXMaterial() { @@ -89,18 +100,21 @@ void CParticleElectric::SetupLineGXMaterial() { void CParticleElectric::DrawLineStrip(const std::vector& verts, float width, const zeus::CColor& color) { - size_t useIdx = m_nextLineRenderer; - if (++m_nextLineRenderer > m_lineRenderers.size()) + const size_t useIdx = m_nextLineRenderer; + if (++m_nextLineRenderer > m_lineRenderers.size()) { m_lineRenderers.resize(m_nextLineRenderer); - if (!m_lineRenderers[useIdx]) + } + 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 useColor = x1b8_moduColor * color; renderer.Reset(); - for (const zeus::CVector3f& vert : verts) + for (const zeus::CVector3f& vert : verts) { renderer.AddVertex(vert, useColor, width); + } renderer.Render(g_Renderer->IsThermalVisorHotPass()); } @@ -117,12 +131,15 @@ void CParticleElectric::RenderLines() { SetupLineGXMaterial(); for (CParticleElectricManager& elec : x3e8_electricManagers) { CLineManager& line = *x2e4_lineManagers[elec.x0_idx]; - if (x1c_elecDesc->x28_LWD1) + if (x1c_elecDesc->x28_LWD1) { DrawLineStrip(line.x0_verts, line.x10_widths[0], line.x1c_colors[0]); - if (x1c_elecDesc->x2c_LWD2) + } + if (x1c_elecDesc->x2c_LWD2) { DrawLineStrip(line.x0_verts, line.x10_widths[1], line.x1c_colors[1]); - if (x1c_elecDesc->x30_LWD3) + } + if (x1c_elecDesc->x30_LWD3) { DrawLineStrip(line.x0_verts, line.x10_widths[2], line.x1c_colors[2]); + } } // Enable culling @@ -135,22 +152,28 @@ void CParticleElectric::UpdateCachedTransform() { x450_29_transformDirty = false; } -void CParticleElectric::UpdateLine(int idx, int frame) { +void CParticleElectric::UpdateLine(size_t idx, int frame) { CLineManager& line = *x2e4_lineManagers[idx]; - if (CColorElement* lcl1 = x1c_elecDesc->x34_LCL1.get()) + if (CColorElement* lcl1 = x1c_elecDesc->x34_LCL1.get()) { lcl1->GetValue(frame, line.x1c_colors[0]); - if (CColorElement* lcl2 = x1c_elecDesc->x38_LCL2.get()) + } + if (CColorElement* lcl2 = x1c_elecDesc->x38_LCL2.get()) { lcl2->GetValue(frame, line.x1c_colors[1]); - if (CColorElement* lcl3 = x1c_elecDesc->x3c_LCL3.get()) + } + if (CColorElement* lcl3 = x1c_elecDesc->x3c_LCL3.get()) { lcl3->GetValue(frame, line.x1c_colors[2]); + } - if (CRealElement* lwd1 = x1c_elecDesc->x28_LWD1.get()) + if (CRealElement* lwd1 = x1c_elecDesc->x28_LWD1.get()) { lwd1->GetValue(frame, line.x10_widths[0]); - if (CRealElement* lwd2 = x1c_elecDesc->x2c_LWD2.get()) + } + if (CRealElement* lwd2 = x1c_elecDesc->x2c_LWD2.get()) { lwd2->GetValue(frame, line.x10_widths[1]); - if (CRealElement* lwd3 = x1c_elecDesc->x30_LWD3.get()) + } + if (CRealElement* lwd3 = x1c_elecDesc->x30_LWD3.get()) { lwd3->GetValue(frame, line.x10_widths[2]); + } } void CParticleElectric::UpdateElectricalEffects() { @@ -158,28 +181,32 @@ void CParticleElectric::UpdateElectricalEffects() { CParticleElectricManager& elec = *it; if (elec.x4_slif <= 1) { x1bc_allocated[elec.x0_idx] = false; - if (elec.x10_gpsmIdx != -1) + if (elec.x10_gpsmIdx != -1) { x400_gpsmGenerators[elec.x10_gpsmIdx]->SetParticleEmission(false); - if (elec.x14_epsmIdx != -1) + } + if (elec.x14_epsmIdx != -1) { x410_epsmGenerators[elec.x14_epsmIdx]->SetParticleEmission(false); + } it = x3e8_electricManagers.erase(it); continue; } - CParticleGlobals::instance()->SetParticleLifetime(elec.xc_endFrame - elec.x8_startFrame); - int frame = x28_currentFrame - elec.x8_startFrame; + CParticleGlobals::instance()->SetParticleLifetime(int(elec.xc_endFrame - elec.x8_startFrame)); + const int frame = x28_currentFrame - int(elec.x8_startFrame); CParticleGlobals::instance()->UpdateParticleLifetimeTweenValues(frame); if (x450_27_haveSSWH) { CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; zeus::CColor color = zeus::skWhite; - if (CColorElement* colr = x1c_elecDesc->x14_COLR.get()) + if (CColorElement* colr = x1c_elecDesc->x14_COLR.get()) { colr->GetValue(frame, color); + } swoosh.SetModulationColor(color * x1b8_moduColor); } - if (x450_28_haveLWD) + if (x450_28_haveLWD) { UpdateLine(elec.x0_idx, frame); + } elec.x4_slif -= 1; ++it; @@ -187,28 +214,34 @@ void CParticleElectric::UpdateElectricalEffects() { } 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; + const float tmp = float(end - start) / float(x430_fractalMags.size()) * ampl; + const 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) + if (((start + end) & 1) != 0) { x430_fractalMags[end - 1] = x430_fractalMags[end]; + } - if (storeIdx - start > 1) + if (storeIdx - start > 1) { CalculateFractal(start, storeIdx, ampl, ampd); - if (end - storeIdx > 1) + } + if (end - storeIdx > 1) { CalculateFractal(storeIdx, end, ampl, ampd); + } } void CParticleElectric::CalculatePoints() { zeus::CVector3f pos, vel; - if (CEmitterElement* iemt = x1c_elecDesc->x18_IEMT.get()) + if (CEmitterElement* iemt = x1c_elecDesc->x18_IEMT.get()) { iemt->GetValue(x28_currentFrame, pos, vel); + } - if (x178_overrideIPos) + if (x178_overrideIPos) { pos = *x178_overrideIPos; - if (x188_overrideIVel) + } + if (x188_overrideIVel) { vel = *x188_overrideIVel; + } rstl::reserved_vector points; @@ -222,13 +255,16 @@ void CParticleElectric::CalculatePoints() { zeus::CVector3f fpos = zeus::skForward; zeus::CVector3f fvel; - if (CEmitterElement* femt = x1c_elecDesc->x1c_FEMT.get()) + if (CEmitterElement* femt = x1c_elecDesc->x1c_FEMT.get()) { femt->GetValue(x28_currentFrame, fpos, fvel); + } - if (x198_overrideFPos) + if (x198_overrideFPos) { fpos = *x198_overrideFPos; - if (x1a8_overrideFVel) + } + if (x1a8_overrideFVel) { fvel = *x1a8_overrideFVel; + } if (!fvel.isZero()) { if (points.size() == 3) { @@ -244,21 +280,21 @@ void CParticleElectric::CalculatePoints() { } if (points.size() == 4) { - int segs = x150_SSEG - 1; - float segDiv = 1.f / float(segs); + const int segs = x150_SSEG - 1; + const 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; + const 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); + const int segs = x150_SSEG - 1; + const float segDiv = 1.f / float(segs); zeus::CVector3f accum = x420_calculatedVerts[0]; - zeus::CVector3f segDelta = (fpos - pos) * segDiv; + const 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; @@ -267,8 +303,9 @@ void CParticleElectric::CalculatePoints() { x420_calculatedVerts[segs] = fpos; } - for (int i = 0; i < x150_SSEG; ++i) + 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()) { @@ -277,8 +314,9 @@ void CParticleElectric::CalculatePoints() { } float ampdVal = 0.f; - if (CRealElement* ampd = x1c_elecDesc->x24_AMPD.get()) + if (CRealElement* ampd = x1c_elecDesc->x24_AMPD.get()) { ampd->GetValue(x28_currentFrame, ampdVal); + } CalculateFractal(0, x420_calculatedVerts.size() - 1, amplVal, ampdVal); @@ -289,55 +327,63 @@ void CParticleElectric::CalculatePoints() { v0.normalize(); v1.normalize(); float dot = v0.dot(v1); - if (dot < 0) + if (dot < 0) { dot = -dot; - if (std::fabs(dot - 1.f) < 0.00001f) + } + if (std::fabs(dot - 1.f) < 0.00001f) { upVec = zeus::lookAt(x420_calculatedVerts[0], x420_calculatedVerts[1]).basis[2]; - else + } 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); + const 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]; + for (size_t i = 1; i < x420_calculatedVerts.size() - 1; ++i) { + const zeus::CVector3f delta = x420_calculatedVerts[i] - x420_calculatedVerts[i - 1]; if (!delta.isZero()) { - zeus::CRelAngle angle = + const 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) + for (size_t 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; + if (x1c_elecDesc->x70_ZERY) { + for (auto& calculatedVert : x420_calculatedVerts) { + calculatedVert.y() = 0.f; + } + } } 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(); + size_t allocIdx = 0; - int toAdd = x1bc_allocated.size() - allocIdx; - for (int j = 0; j < toAdd; ++j, ++allocIdx) { - if (x1bc_allocated[allocIdx]) + for (int i = 0; i < count; ++i) { + if (x3e8_electricManagers.size() < size_t(x154_SCNT)) { + const zeus::CTransform cachedRot = xf8_cachedXf.getRotation(); + + const size_t toAdd = x1bc_allocated.size() - allocIdx; + for (size_t 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()) + if (CIntElement* slif = x1c_elecDesc->x4_SLIF.get()) { slif->GetValue(x28_currentFrame, lifetime); + } x3e8_electricManagers.emplace_back(allocIdx, lifetime, x28_currentFrame); CParticleElectricManager& elec = x3e8_electricManagers.back(); CParticleGlobals::instance()->SetParticleLifetime(elec.xc_endFrame - elec.x8_startFrame); - int frame = x28_currentFrame - elec.x8_startFrame; + const int frame = x28_currentFrame - int(elec.x8_startFrame); CParticleGlobals::instance()->UpdateParticleLifetimeTweenValues(frame); CalculatePoints(); @@ -349,8 +395,9 @@ void CParticleElectric::CreateNewParticles(int count) { swoosh.SetGlobalScale(xe0_globalScale); swoosh.SetLocalScale(xec_localScale); zeus::CColor color = zeus::skWhite; - if (CColorElement* colr = x1c_elecDesc->x14_COLR.get()) + if (CColorElement* colr = x1c_elecDesc->x14_COLR.get()) { colr->GetValue(frame, color); + } swoosh.SetModulationColor(color * x1b8_moduColor); swoosh.DoElectricCreate(x420_calculatedVerts); } @@ -361,8 +408,9 @@ void CParticleElectric::CreateNewParticles(int count) { UpdateLine(allocIdx, 0); if (x450_27_haveSSWH) { x130_buildBounds = zeus::CAABox(); - for (const zeus::CVector3f& vec : x420_calculatedVerts) + for (const zeus::CVector3f& vec : x420_calculatedVerts) { x130_buildBounds.accumulateBounds(vec); + } line.x28_aabb = x130_buildBounds; } } @@ -371,7 +419,7 @@ void CParticleElectric::CreateNewParticles(int count) { for (int k = 0; k < x154_SCNT; ++k) { CElementGen& gen = *x400_gpsmGenerators[k]; if (!gen.GetParticleEmission()) { - zeus::CTransform scale = + const zeus::CTransform scale = zeus::CTransform::Scale(xe0_globalScale) * zeus::CTransform::Scale(xec_localScale); gen.SetTranslation(scale * x420_calculatedVerts.front()); gen.SetParticleEmission(true); @@ -385,7 +433,7 @@ void CParticleElectric::CreateNewParticles(int count) { for (int k = 0; k < x154_SCNT; ++k) { CElementGen& gen = *x410_epsmGenerators[k]; if (!gen.GetParticleEmission()) { - zeus::CTransform scale = + const zeus::CTransform scale = zeus::CTransform::Scale(xe0_globalScale) * zeus::CTransform::Scale(xec_localScale); gen.SetTranslation(scale * x420_calculatedVerts.back()); gen.SetParticleEmission(true); @@ -406,8 +454,7 @@ void CParticleElectric::AddElectricalEffects() { if (CRealElement* grat = x1c_elecDesc->x8_GRAT.get()) { if (grat->GetValue(x28_currentFrame, genRate)) { x3e8_electricManagers.clear(); - for (int i = 0; i < x1bc_allocated.size(); ++i) - x1bc_allocated[i] = false; + std::fill(x1bc_allocated.begin(), x1bc_allocated.end(), false); return; } else { genRate = std::max(0.f, genRate); @@ -415,9 +462,9 @@ void CParticleElectric::AddElectricalEffects() { } x15c_genRem += genRate; - int partCount = std::floor(x15c_genRem); + const float partCount = std::floor(x15c_genRem); x15c_genRem -= partCount; - CreateNewParticles(partCount); + CreateNewParticles(int(partCount)); } void CParticleElectric::BuildBounds() { @@ -429,14 +476,15 @@ void CParticleElectric::BuildBounds() { x160_systemBounds = zeus::CAABox(); if (x450_27_haveSSWH) { - for (CParticleElectricManager& elec : x3e8_electricManagers) { - CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; - if (auto bounds = swoosh.GetBounds()) + for (const CParticleElectricManager& elec : x3e8_electricManagers) { + const CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; + if (const auto bounds = swoosh.GetBounds()) { x160_systemBounds.accumulateBounds(*bounds); + } } } else if (x450_28_haveLWD) { zeus::CAABox tmp = zeus::CAABox(); - for (CParticleElectricManager& elec : x3e8_electricManagers) { + for (const CParticleElectricManager& elec : x3e8_electricManagers) { CLineManager& line = *x2e4_lineManagers[elec.x0_idx]; tmp.accumulateBounds(line.x28_aabb); } @@ -448,44 +496,52 @@ void CParticleElectric::BuildBounds() { } if (x450_25_haveGPSM) { - for (int i = 0; i < x154_SCNT; ++i) - if (auto bounds = x400_gpsmGenerators[i]->GetBounds()) + 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()) + 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); + [[maybe_unused]] CGlobalRandom gr(x14c_randState); bool ret = false; if (x450_25_haveGPSM) { - for (int i = 0; i < x154_SCNT; ++i) - if (!x400_gpsmGenerators[i]->IsSystemDeletable()) + 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()) + for (int i = 0; i < x154_SCNT; ++i) { + if (!x410_epsmGenerators[i]->IsSystemDeletable()) { break; + } + } } - bool emitting = x450_24_emitting && x28_currentFrame < x2c_LIFE; + const 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(); + const zeus::CTransform globalOrient = xf8_cachedXf.getRotation(); if (x450_27_haveSSWH) { - for (CParticleElectricManager& elec : x3e8_electricManagers) { + for (const CParticleElectricManager& elec : x3e8_electricManagers) { CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; swoosh.SetGlobalTranslation(xf8_cachedXf.origin); swoosh.SetGlobalOrientation(globalOrient); @@ -495,7 +551,7 @@ bool CParticleElectric::Update(double dt) { } if (x450_25_haveGPSM) { - for (CParticleElectricManager& elec : x3e8_electricManagers) { + for (const CParticleElectricManager& elec : x3e8_electricManagers) { CElementGen& gen = *x400_gpsmGenerators[elec.x0_idx]; gen.SetGlobalTranslation(xf8_cachedXf.origin); gen.SetGlobalOrientation(globalOrient); @@ -505,7 +561,7 @@ bool CParticleElectric::Update(double dt) { } if (x450_26_haveEPSM) { - for (CParticleElectricManager& elec : x3e8_electricManagers) { + for (const CParticleElectricManager& elec : x3e8_electricManagers) { CElementGen& gen = *x410_epsmGenerators[elec.x0_idx]; gen.SetGlobalTranslation(xf8_cachedXf.origin); gen.SetGlobalOrientation(globalOrient); @@ -524,19 +580,25 @@ bool CParticleElectric::Update(double dt) { AddElectricalEffects(); if (x450_25_haveGPSM) { - if (x28_currentFrame >= x2c_LIFE) - for (int i = 0; i < x154_SCNT; ++i) + 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) + } + } + 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) + 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) + } + } + for (int i = 0; i < x154_SCNT; ++i) { x410_epsmGenerators[i]->Update(1.0 / 60.0); + } } ret = true; @@ -544,33 +606,39 @@ bool CParticleElectric::Update(double dt) { x28_currentFrame += 1; } - if (ret) + if (ret) { BuildBounds(); + } return ret; } void CParticleElectric::Render(const CActorLights* lights) { - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CParticleElectric::Render {}"), + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CParticleElectric::Render {}"), *x1c_elecDesc.GetObjectTag()).c_str(), zeus::skYellow); - if (x3e8_electricManagers.size()) { - if (x450_29_transformDirty) + if (!x3e8_electricManagers.empty()) { + if (x450_29_transformDirty) { UpdateCachedTransform(); - if (x450_27_haveSSWH) + } + if (x450_27_haveSSWH) { RenderSwooshes(); - if (x450_28_haveLWD) + } + if (x450_28_haveLWD) { RenderLines(); + } } if (x450_25_haveGPSM) { - for (int i = 0; i < x154_SCNT; ++i) + 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) + for (int i = 0; i < x154_SCNT; ++i) { x410_epsmGenerators[i]->Render(lights); + } } } @@ -590,20 +658,22 @@ void CParticleElectric::SetGlobalOrientation(const zeus::CTransform& orientation x450_29_transformDirty = true; if (x450_27_haveSSWH) { - for (CParticleElectricManager& elec : x3e8_electricManagers) { + for (const CParticleElectricManager& elec : x3e8_electricManagers) { CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; swoosh.SetGlobalOrientation(xb0_globalOrientation); } } if (x450_25_haveGPSM) { - for (int i = 0; i < x154_SCNT; ++i) + 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) + for (int i = 0; i < x154_SCNT; ++i) { x410_epsmGenerators[i]->SetGlobalOrientation(xb0_globalOrientation); + } } } @@ -612,20 +682,22 @@ void CParticleElectric::SetGlobalTranslation(const zeus::CVector3f& translation) x450_29_transformDirty = true; if (x450_27_haveSSWH) { - for (CParticleElectricManager& elec : x3e8_electricManagers) { + for (const CParticleElectricManager& elec : x3e8_electricManagers) { CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; swoosh.SetGlobalTranslation(xa4_globalTranslation); } } if (x450_25_haveGPSM) { - for (int i = 0; i < x154_SCNT; ++i) + 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) + for (int i = 0; i < x154_SCNT; ++i) { x410_epsmGenerators[i]->SetGlobalTranslation(xa4_globalTranslation); + } } } @@ -639,20 +711,22 @@ void CParticleElectric::SetLocalScale(const zeus::CVector3f& scale) { x450_29_transformDirty = true; if (x450_27_haveSSWH) { - for (CParticleElectricManager& elec : x3e8_electricManagers) { + for (const 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) + 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) + for (int i = 0; i < x154_SCNT; ++i) { x410_epsmGenerators[i]->SetLocalScale(xec_localScale); + } } } @@ -673,22 +747,28 @@ const zeus::CVector3f& CParticleElectric::GetGlobalScale() const { return xe0_gl const zeus::CColor& CParticleElectric::GetModulationColor() const { return x1b8_moduColor; } bool CParticleElectric::IsSystemDeletable() const { - if (x450_24_emitting && x28_currentFrame < x2c_LIFE) + if (x450_24_emitting && x28_currentFrame < x2c_LIFE) { return false; + } - if (x3e8_electricManagers.size()) + if (!x3e8_electricManagers.empty()) { return false; + } if (x450_25_haveGPSM) { - for (int i = 0; i < x154_SCNT; ++i) - if (!x400_gpsmGenerators[i]->IsSystemDeletable()) + 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()) + for (int i = 0; i < x154_SCNT; ++i) { + if (!x410_epsmGenerators[i]->IsSystemDeletable()) { return false; + } + } } return true; @@ -706,38 +786,46 @@ u32 CParticleElectric::GetParticleCount() const { u32 ret = 0; for (const CParticleElectricManager& elec : x3e8_electricManagers) { - if (x450_27_haveSSWH) + if (x450_27_haveSSWH) { ret += x1e0_swooshGenerators[elec.x0_idx]->GetParticleCount(); - if (x450_28_haveLWD) + } + if (x450_28_haveLWD) { ret += x150_SSEG; + } } if (x450_25_haveGPSM) { - for (int i = 0; i < x154_SCNT; ++i) + 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) + for (int i = 0; i < x154_SCNT; ++i) { ret += x410_epsmGenerators[i]->GetParticleCount(); + } } return ret; } bool CParticleElectric::SystemHasLight() const { - if (x450_25_haveGPSM) + if (x450_25_haveGPSM) { return x400_gpsmGenerators.front()->SystemHasLight(); - else if (x450_26_haveEPSM) + } + if (x450_26_haveEPSM) { return x410_epsmGenerators.front()->SystemHasLight(); + } return false; } CLight CParticleElectric::GetLight() const { - if (x450_25_haveGPSM) + if (x450_25_haveGPSM) { return x400_gpsmGenerators.front()->GetLight(); - else if (x450_26_haveEPSM) + } + if (x450_26_haveEPSM) { return x410_epsmGenerators.front()->GetLight(); + } return CLight::BuildLocalAmbient(GetGlobalTranslation(), zeus::skOrange); } diff --git a/Runtime/Particle/CParticleElectric.hpp b/Runtime/Particle/CParticleElectric.hpp index 9da641f06..2760922de 100644 --- a/Runtime/Particle/CParticleElectric.hpp +++ b/Runtime/Particle/CParticleElectric.hpp @@ -85,28 +85,22 @@ private: std::vector x420_calculatedVerts; std::vector x430_fractalMags; std::vector x440_fractalOffsets; + 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; 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; - }; - 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 UpdateLine(size_t idx, int frame); void UpdateElectricalEffects(); void CalculateFractal(int start, int end, float ampl, float ampd); void CalculatePoints(); diff --git a/Runtime/Particle/CParticleElectricDataFactory.cpp b/Runtime/Particle/CParticleElectricDataFactory.cpp index fe366b70a..dc88cb621 100644 --- a/Runtime/Particle/CParticleElectricDataFactory.cpp +++ b/Runtime/Particle/CParticleElectricDataFactory.cpp @@ -107,7 +107,7 @@ bool CParticleElectricDataFactory::CreateELSM(CElectricDescription* desc, CInput desc->x70_ZERY = CPF::GetBool(in); break; default: { - Log.report(logvisor::Fatal, fmt("Unknown ELSM class {} @{}"), clsId, in.position()); + Log.report(logvisor::Fatal, FMT_STRING("Unknown ELSM class {} @{}"), clsId, in.position()); return false; } } diff --git a/Runtime/Particle/CParticleGlobals.hpp b/Runtime/Particle/CParticleGlobals.hpp index ac55d5996..cea7df8f4 100644 --- a/Runtime/Particle/CParticleGlobals.hpp +++ b/Runtime/Particle/CParticleGlobals.hpp @@ -13,31 +13,32 @@ namespace urde { class CElementGen; class CParticleGlobals { - CParticleGlobals()=default; + CParticleGlobals() = default; static std::unique_ptr g_ParticleGlobals; + public: int m_EmitterTime = 0; float m_EmitterTimeReal = 0.f; void SetEmitterTime(int frame) { m_EmitterTime = frame; - m_EmitterTimeReal = frame; + m_EmitterTimeReal = float(frame); } int m_ParticleLifetime = 0; float m_ParticleLifetimeReal = 0.f; void SetParticleLifetime(int frame) { m_ParticleLifetime = frame; - m_ParticleLifetimeReal = frame; + m_ParticleLifetimeReal = float(frame); } int m_ParticleLifetimePercentage = 0; float m_ParticleLifetimePercentageReal = 0.f; float m_ParticleLifetimePercentageRemainder = 0.f; void UpdateParticleLifetimeTweenValues(int frame) { - float lt = m_ParticleLifetime != 0.0f ? m_ParticleLifetime : 1.0f; - m_ParticleLifetimePercentageReal = 100.0f * frame / lt; + const float lt = m_ParticleLifetime != 0 ? float(m_ParticleLifetime) : 1.0f; + m_ParticleLifetimePercentageReal = 100.0f * float(frame) / lt; m_ParticleLifetimePercentage = int(m_ParticleLifetimePercentageReal); - m_ParticleLifetimePercentageRemainder = m_ParticleLifetimePercentageReal - m_ParticleLifetimePercentage; + m_ParticleLifetimePercentageRemainder = m_ParticleLifetimePercentageReal - float(m_ParticleLifetimePercentage); m_ParticleLifetimePercentage = zeus::clamp(0, m_ParticleLifetimePercentage, 100); } @@ -48,7 +49,7 @@ public: CElementGen* x4_system; }; - SParticleSystem* m_currentParticleSystem; + SParticleSystem* m_currentParticleSystem = nullptr; static CParticleGlobals* instance() { if (!g_ParticleGlobals) @@ -59,22 +60,22 @@ public: }; struct SParticleInstanceTex { - zeus::CVector4f pos[4]; + std::array pos; zeus::CColor color; - zeus::CVector2f uvs[4]; + std::array uvs; }; extern std::vector g_instTexData; struct SParticleInstanceIndTex { - zeus::CVector4f pos[4]; + std::array pos; zeus::CColor color; - zeus::CVector4f texrTindUVs[4]; + std::array texrTindUVs; zeus::CVector4f sceneUVs; }; extern std::vector g_instIndTexData; struct SParticleInstanceNoTex { - zeus::CVector4f pos[4]; + std::array pos; zeus::CColor color; }; extern std::vector g_instNoTexData; diff --git a/Runtime/Particle/CParticleSwoosh.cpp b/Runtime/Particle/CParticleSwoosh.cpp index 6ab26b711..78512b2b8 100644 --- a/Runtime/Particle/CParticleSwoosh.cpp +++ b/Runtime/Particle/CParticleSwoosh.cpp @@ -16,42 +16,55 @@ CParticleSwoosh::CParticleSwoosh(const TToken& desc, int len , 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; + : 99) +, x1d0_24_emitting(true) +, x1d0_25_AALP(false) +, x1d0_26_forceOneUpdate(false) +, x1d0_27_renderGaps(false) +, x1d0_28_LLRD(false) +, x1d0_29_VLS1(false) +, x1d0_30_VLS2(false) +, x1d0_31_constantTex(false) +, x1d1_24_constantUv(false) { ++g_ParticleSystemAliveCount; - if (leng > 0) + if (leng > 0) { x1b4_LENG = leng; - else if (CIntElement* leng = x1c_desc->x10_LENG.get()) - leng->GetValue(0, x1b4_LENG); + } else if (CIntElement* lengElement = x1c_desc->x10_LENG.get()) { + lengElement->GetValue(0, x1b4_LENG); + } x1b4_LENG += 1; - if (CIntElement* side = x1c_desc->x18_SIDE.get()) + 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; if (IsValid()) { - if (CIntElement* pslt = x1c_desc->x0_PSLT.get()) + if (CIntElement* pslt = x1c_desc->x0_PSLT.get()) { pslt->GetValue(0, x2c_PSLT); - else + } else { x2c_PSLT = INT_MAX; + } x1d0_25_AALP = x1c_desc->x44_31_AALP; - if (CIntElement* spln = x1c_desc->x38_SPLN.get()) + if (CIntElement* spln = x1c_desc->x38_SPLN.get()) { spln->GetValue(0, x1b0_SPLN); - if (x1b0_SPLN < 0) + } + if (x1b0_SPLN < 0) { x1b0_SPLN = 0; + } x15c_swooshes.clear(); x15c_swooshes.reserve(x1b4_LENG); - for (int i = 0; i < x1b4_LENG; ++i) - x15c_swooshes.emplace_back(zeus::skZero3f, zeus::skZero3f, 0.f, 0.f, 0, false, - zeus::CTransform(), zeus::skZero3f, 0.f, 0.f, - zeus::skClear); + for (int i = 0; i < x1b4_LENG; ++i) { + x15c_swooshes.emplace_back(zeus::skZero3f, zeus::skZero3f, 0.f, 0.f, 0, false, zeus::CTransform(), zeus::skZero3f, + 0.f, 0.f, zeus::skClear); + } SetOrientation(zeus::CTransform()); @@ -61,11 +74,11 @@ CParticleSwoosh::CParticleSwoosh(const TToken& desc, int len x19c_p3.resize(x1b8_SIDE); if (x1c_desc->x44_29_WIRE) { - int maxVerts = x1b4_LENG * (x1b0_SPLN + 1) * x1b8_SIDE * 12; + const 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; + const auto maxVerts = size_t(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); @@ -125,14 +138,16 @@ void CParticleSwoosh::UpdateTranslationAndOrientation() { swoosh.x68_frame = x28_curFrame - swoosh.x70_startFrame; CParticleGlobals::instance()->UpdateParticleLifetimeTweenValues(swoosh.x68_frame); if (x1c_desc->x44_28_SROT) { - if (CRealElement* irot = x1c_desc->x1c_IROT.get()) + 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()) + if (CRealElement* rotm = x1c_desc->x20_ROTM.get()) { rotm->GetValue(x28_curFrame, swoosh.x34_rotm); - else + } else { swoosh.x34_rotm = 0.f; + } } if (CModVectorElement* velm = x1c_desc->x30_VELM.get()) { @@ -188,8 +203,9 @@ void CParticleSwoosh::UpdateTranslationAndOrientation() { } bool CParticleSwoosh::Update(double dt) { - if (!IsValid()) + if (!IsValid()) { return false; + } CParticleGlobals::instance()->SetParticleLifetime(x1b4_LENG); CParticleGlobals::instance()->SetEmitterTime(x28_curFrame); @@ -198,24 +214,27 @@ bool CParticleSwoosh::Update(double dt) { double evalTime = x28_curFrame / 60.0; float time = 1.f; - if (CRealElement* timeElem = x1c_desc->x4_TIME.get()) + 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()) + 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()) + if (CRealElement* irot = x1c_desc->x1c_IROT.get()) { irot->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x30_irot); - else + } 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; @@ -232,20 +251,23 @@ bool CParticleSwoosh::Update(double dt) { x15c_swooshes[x158_curParticle].x74_velocity = x44_orientation * x15c_swooshes[x158_curParticle].x74_velocity; } - if (CVectorElement* pofs = x1c_desc->x24_POFS.get()) + 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()) + if (CColorElement* colr = x1c_desc->x14_COLR.get()) { colr->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x6c_color); - else + } else { x15c_swooshes[x158_curParticle].x6c_color = zeus::skWhite; + } int tspn = 0; - if (CIntElement* tspnElem = x1c_desc->x40_TSPN.get()) + if (CIntElement* tspnElem = x1c_desc->x40_TSPN.get()) { tspnElem->GetValue(x28_curFrame, tspn); - x1cc_TSPN = tspn; + } + x1cc_TSPN = float(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; @@ -262,28 +284,32 @@ bool CParticleSwoosh::Update(double dt) { 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) + if (t > 0.f) { return p1; - if (t >= 1.f) + } + if (t >= 1.f) { return p2; + } // Tricubic spline interpolation - float t2 = t * t; - float t3 = t2 * t; + const float t2 = t * t; + const 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; + const float p0Coef = -0.5f * t3 + t2 - 0.5f * t; + const float p1Coef = 1.5f * t3 - 2.5f * t2 + 1.f; + const float p2Coef = -1.5f * t3 + 2.f * t2 + 0.5f * t; + const float p3Coef = 0.5f * t3 + 0.5f * t2; return p0 * p0Coef + p1 * p1Coef + p2 * p2Coef + p3 * p3Coef; } int CParticleSwoosh::WrapIndex(int i) const { - while (i < 0) + while (i < 0) { i += x1b4_LENG; - while (i >= x1b4_LENG) + } + while (i >= x1b4_LENG) { i -= x1b4_LENG; + } return i; } @@ -296,112 +322,125 @@ void CParticleSwoosh::RenderNSidedSpline() { } bool cros = x1c_desc->x44_25_CROS; - if (x1b8_SIDE >= 4 || x1b8_SIDE & 0x1) + if (x1b8_SIDE >= 4 || (x1b8_SIDE & 0x1) != 0) { cros = false; + } int curIdx = x158_curParticle; for (size_t i = 0; i < x15c_swooshes.size(); ++i) { - bool a0 = x15c_swooshes[WrapIndex(curIdx - 1)].x0_active; - bool a1 = x15c_swooshes[WrapIndex(curIdx)].x0_active; + const bool a0 = x15c_swooshes[WrapIndex(curIdx - 1)].x0_active; + const bool a1 = x15c_swooshes[WrapIndex(curIdx)].x0_active; if (!a1 || (a1 && !a0)) { curIdx -= 1; - if (curIdx < 0) + if (curIdx < 0) { curIdx = x15c_swooshes.size() - 1; + } continue; } - SSwooshData& refSwoosh = x15c_swooshes[curIdx]; + const SSwooshData& refSwoosh = x15c_swooshes[curIdx]; - float sideDiv = 360.f / float(x1b8_SIDE); + const 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) + 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) + if (!x15c_swooshes[crossRefIdx].x0_active) { crossRefIdx = WrapIndex(curIdx - 1); + } } if (x1b4_LENG == 2) { - if (j == 0) + if (j == 0) { crossRefIdx = WrapIndex(curIdx); - if (j == 3) + } + 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) + if (WrapIndex(x158_curParticle + 2) == curIdx && j == 3) { crossRefIdx = WrapIndex(x158_curParticle + 1); - else if (x1ac_particleCount - 2 == i && j == 3) + } else if (x1ac_particleCount - 2 == i && j == 3) { crossRefIdx = 0; + } } - SSwooshData& crossSwoosh = x15c_swooshes[crossRefIdx]; + const SSwooshData& crossSwoosh = x15c_swooshes[crossRefIdx]; for (int k = 0; k < x1b8_SIDE; ++k) { - float n = sideDiv * k; + const float n = sideDiv * k; float ang = zeus::degToRad(n + crossSwoosh.x30_irot + crossSwoosh.x34_rotm); if (std::fabs(ang) > M_PIF) { ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF; - if (ang > M_PIF) + if (ang > M_PIF) { ang -= 2.f * M_PIF; - else if (ang < -M_PIF) + } else if (ang < -M_PIF) { ang += 2.f * M_PIF; + } } - float z = std::sin(ang); - float x = std::cos(ang); + const float z = std::sin(ang); + const 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; + const float rad = (n > 0.f && n <= 180.f) ? crossSwoosh.x4_leftRad : crossSwoosh.x8_rightRad; + const zeus::CVector3f offset = crossSwoosh.xc_translation + crossSwoosh.x24_useOffset; - if (j == 0) + if (j == 0) { x16c_p0[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; - else if (j == 1) + } else if (j == 1) { x17c_p1[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; - else if (j == 2) + } else if (j == 2) { x18c_p2[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; - else if (j == 3) + } 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) + if (x1ec_TSPN > 0) { x1d4_uvs.xMin = float((i % x1ec_TSPN) * x1e8_uvSpan); - else + } else { x1d4_uvs.xMin = float(i * x1e8_uvSpan); + } } - float segUvSpan = x1e8_uvSpan / float(x1b0_SPLN + 1); + const 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); + const float t0 = j / float(x1b0_SPLN + 1); + const float t1 = (j + 1) / float(x1b0_SPLN + 1); int faces = x1b8_SIDE; - if (x1b8_SIDE <= 2) + if (x1b8_SIDE <= 2) { faces = 1; - else if (cros) + } 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) + if (k + 1 >= x1b8_SIDE) { otherK = 0; - zeus::CColor color = refSwoosh.x6c_color * x20c_moduColor; + } + + const zeus::CColor color = refSwoosh.x6c_color * x20c_moduColor; if (cros) { 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); + const auto v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0); + const auto v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0); + const auto v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1); + const auto 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}); @@ -409,10 +448,10 @@ void CParticleSwoosh::RenderNSidedSpline() { 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); + const auto v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0); + const auto v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0); + const auto v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1); + const auto 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); @@ -437,57 +476,65 @@ void CParticleSwoosh::RenderNSidedSpline() { } } - if (x1c_desc->x3c_TEXR && x1b0_SPLN > 0) + if (x1c_desc->x3c_TEXR && x1b0_SPLN > 0) { x1d4_uvs.xMin += segUvSpan; + } } curIdx -= 1; - if (curIdx < 0) + if (curIdx < 0) { curIdx = x15c_swooshes.size() - 1; + } } - if (x1bc_prim == GX::LINES) + if (x1bc_prim == GX::LINES) { m_lineRenderer->Render(g_Renderer->IsThermalVisorHotPass()); + } } void CParticleSwoosh::RenderNSidedNoSpline() { RenderNSidedSpline(); } void CParticleSwoosh::Render3SidedSolidSpline() { - if (x15c_swooshes.size() < 2) + if (x15c_swooshes.size() < 2) { return; + } int curIdx = x158_curParticle; float curUvSpan = -x1e8_uvSpan; zeus::CColor prevColor0 = zeus::skClear; for (size_t i = 0; i < x15c_swooshes.size(); ++i) { - SSwooshData& swoosh = x15c_swooshes[curIdx]; + const SSwooshData& swoosh = x15c_swooshes[curIdx]; curIdx -= 1; - if (curIdx < 0) + 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) + if (ang1 > M_PIF) { ang1 -= 2.f * M_PIF; - else if (ang1 < -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); + const 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) + 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); + const 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) + 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); + const 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]; @@ -507,15 +554,15 @@ void CParticleSwoosh::Render3SidedSolidSpline() { x17c_p1[1] = x16c_p0[1]; x17c_p1[2] = x16c_p0[2]; - zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; + const 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; + const zeus::CColor useColor0 = prevColor0; if (swoosh.x0_active) { - zeus::CColor prevColor1 = prevColor0; + const zeus::CColor prevColor1 = prevColor0; prevColor0 = swoosh.x6c_color * x20c_moduColor; float prevUvSpan = curUvSpan; curUvSpan += x1e8_uvSpan; @@ -575,48 +622,53 @@ void CParticleSwoosh::Render3SidedSolidSpline() { } void CParticleSwoosh::Render3SidedSolidNoSplineNoGaps() { - if (x15c_swooshes.size() < 2) + if (x15c_swooshes.size() < 2) { return; + } - zeus::CVector3f p0[2]; - zeus::CVector3f p1[2]; - zeus::CVector3f p2[2]; + std::array p0; + std::array p1; + std::array p2; int curIdx = x158_curParticle; bool lastActive = false; zeus::CColor c0 = zeus::skClear; float uv0 = -x1e8_uvSpan; for (size_t i = 0; i < x15c_swooshes.size(); ++i) { - SSwooshData& swoosh = x15c_swooshes[curIdx]; + const SSwooshData& swoosh = x15c_swooshes[curIdx]; curIdx -= 1; - if (curIdx < 0) + 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) + if (ang1 > M_PIF) { ang1 -= 2.f * M_PIF; - else if (ang1 < -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); + const 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) + 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); + const 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) + 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); + const 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; + const 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; @@ -632,10 +684,10 @@ void CParticleSwoosh::Render3SidedSolidNoSplineNoGaps() { } lastActive = true; - zeus::CColor c1 = c0; + const zeus::CColor c1 = c0; c0 = swoosh.x6c_color * x20c_moduColor; - float uv1 = uv0; + const float uv1 = uv0; uv0 += x1e8_uvSpan; m_cachedVerts.push_back({p0[i & 1], {uv0, x1d4_uvs.yMin}, c0}); @@ -665,12 +717,13 @@ void CParticleSwoosh::Render2SidedNoSplineGaps() { bool streaming = false; int curIdx = x158_curParticle; for (size_t i = 0; i < x15c_swooshes.size(); ++i) { - SSwooshData& swoosh = x15c_swooshes[curIdx]; - bool otherActive = x15c_swooshes[WrapIndex(curIdx - 1)].x0_active; + const SSwooshData& swoosh = x15c_swooshes[curIdx]; + const bool otherActive = x15c_swooshes[WrapIndex(curIdx - 1)].x0_active; curIdx -= 1; - if (curIdx < 0) + if (curIdx < 0) { curIdx = x15c_swooshes.size() - 2; + } if (!swoosh.x0_active) { if (streaming) { @@ -681,10 +734,12 @@ void CParticleSwoosh::Render2SidedNoSplineGaps() { } if (!streaming) { - if (!otherActive) + if (!otherActive) { continue; - if (i >= x15c_swooshes.size() - 2) + } + if (i >= x15c_swooshes.size() - 2) { continue; + } streaming = true; drawStart = m_cachedVerts.size(); } @@ -692,24 +747,25 @@ void CParticleSwoosh::Render2SidedNoSplineGaps() { 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) + if (ang > M_PIF) { ang -= 2.f * M_PIF; - else if (ang < -M_PIF) + } else if (ang < -M_PIF) { ang += 2.f * M_PIF; + } } - float sinAng = std::sin(ang); - float cosAng = std::cos(ang); + const float sinAng = std::sin(ang); + const float cosAng = std::cos(ang); - zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; - zeus::CVector3f v0 = + const zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; + const zeus::CVector3f v0 = swoosh.x38_orientation * zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) + useOffset; - zeus::CVector3f v1 = + const 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; + const 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}); @@ -726,43 +782,47 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() { 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 = + const zeus::CVector3f camToParticle = ((zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * xec_scaleXf).inverse() * CGraphics::g_ViewMatrix) .origin; zeus::CVector3f dotVec = zeus::skZero3f; for (size_t i = 0; i < x15c_swooshes.size(); ++i) { - SSwooshData& swoosh = x15c_swooshes[curIdx]; + const SSwooshData& swoosh = x15c_swooshes[curIdx]; curIdx -= 1; - if (curIdx < 0) + if (curIdx < 0) { curIdx = x15c_swooshes.size() - 1; + } if (swoosh.x0_active) { particleCount -= 1; int otherIdx = curIdx - 1; - if (otherIdx < 0) + if (otherIdx < 0) { otherIdx = x15c_swooshes.size() - 1; + } - SSwooshData& otherSwoosh = x15c_swooshes[otherIdx]; + const SSwooshData& otherSwoosh = x15c_swooshes[otherIdx]; zeus::CVector3f delta = otherSwoosh.xc_translation - swoosh.xc_translation; - if (otherIdx == x158_curParticle) + if (otherIdx == x158_curParticle) { delta = swoosh.xc_translation - x15c_swooshes[(curIdx + 1) % x15c_swooshes.size()].xc_translation; + } 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; + const zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; + const zeus::CVector3f v0 = dotVec * swoosh.x4_leftRad + useOffset; + const zeus::CVector3f v1 = dotVec * -swoosh.x8_rightRad + useOffset; - zeus::CColor color = swoosh.x6c_color * x20c_moduColor; + const 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}); @@ -774,21 +834,23 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() { m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); } - if (x1ec_TSPN > 0) + if (x1ec_TSPN > 0) { uvOffset += x1e8_uvSpan; - else + } else { uvOffset = float(i * x1e8_uvSpan); + } } } } } } else { for (size_t i = 0; i < x15c_swooshes.size(); ++i) { - SSwooshData& swoosh = x15c_swooshes[curIdx]; + const SSwooshData& swoosh = x15c_swooshes[curIdx]; curIdx -= 1; - if (curIdx < 0) + if (curIdx < 0) { curIdx = x15c_swooshes.size() - 1; + } if (swoosh.x0_active) { particleCount -= 1; @@ -796,24 +858,25 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() { 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) + if (ang > M_PIF) { ang -= 2.f * M_PIF; - else if (ang < -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 = + const zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; + const 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; + const 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; + const 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}); @@ -825,43 +888,46 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() { m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); } - if (x1ec_TSPN > 0) + if (x1ec_TSPN > 0) { uvOffset += x1e8_uvSpan; - else - uvOffset = float(i* x1e8_uvSpan); + } else { + uvOffset = float(i * x1e8_uvSpan); + } } } } } else { for (size_t i = 0; i < x15c_swooshes.size(); ++i) { - SSwooshData& swoosh = x15c_swooshes[curIdx]; + const SSwooshData& swoosh = x15c_swooshes[curIdx]; curIdx -= 1; - if (curIdx < 0) + 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) + if (ang > M_PIF) { ang -= 2.f * M_PIF; - else if (ang < -M_PIF) + } else if (ang < -M_PIF) { ang += 2.f * M_PIF; + } } - float sinAng = std::sin(ang); - float cosAng = std::cos(ang); + const float sinAng = std::sin(ang); + const float cosAng = std::cos(ang); - zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; - zeus::CVector3f v0 = + const zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; + const zeus::CVector3f v0 = swoosh.x38_orientation * zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) + useOffset; - zeus::CVector3f v1 = + const 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; + const zeus::CColor color = swoosh.x6c_color * x20c_moduColor; m_cachedVerts.push_back({v0, {}, color}); m_cachedVerts.push_back({v1, {}, color}); } @@ -872,14 +938,17 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() { } void CParticleSwoosh::Render(const CActorLights*) { - if (x1b4_LENG < 2 || x1ac_particleCount <= 1) + if (x1b4_LENG < 2 || x1ac_particleCount <= 1) { return; - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CParticleSwoosh::Render {}"), + } + + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CParticleSwoosh::Render {}"), *x1c_desc.GetObjectTag()).c_str(), zeus::skYellow); m_cachedVerts.clear(); - if (m_dataBind[0]) + if (m_dataBind[0]) { CGraphics::SetShaderDataBinding(m_dataBind[g_Renderer->IsThermalVisorHotPass()]); + } CParticleGlobals::instance()->SetParticleLifetime(x1b4_LENG); CGlobalRandom gr(x1c0_rand); @@ -902,15 +971,18 @@ void CParticleSwoosh::Render(const CActorLights*) { x1d0_31_constantTex = texr->HasConstantTexture(); x1d1_24_constantUv = texr->HasConstantUV(); - if (CIntElement* tspn = x1c_desc->x40_TSPN.get()) + if (CIntElement* tspn = x1c_desc->x40_TSPN.get()) { tspn->GetValue(x28_curFrame, x1ec_TSPN); + } - if (x1ec_TSPN <= 0) + if (x1ec_TSPN <= 0) { x1ec_TSPN = x15c_swooshes.size() - 1; + } x1e8_uvSpan = 1.f; - if (x1ec_TSPN > 0) + if (x1ec_TSPN > 0) { x1e8_uvSpan = 1.f / float(x1ec_TSPN); + } // TEV0 modulate } else { @@ -921,29 +993,33 @@ void CParticleSwoosh::Render(const CActorLights*) { if (x1b8_SIDE == 2) { if (x1b0_SPLN <= 0) { - if (x1d0_27_renderGaps) + if (x1d0_27_renderGaps) { Render2SidedNoSplineGaps(); - else + } else { Render2SidedNoSplineNoGaps(); + } } else { Render2SidedSpline(); } } else if (x1b8_SIDE == 3) { - if (x1b0_SPLN > 0) + if (x1b0_SPLN > 0) { Render3SidedSolidSpline(); - else + } else { Render3SidedSolidNoSplineNoGaps(); + } } else { - if (x1b0_SPLN > 0) + if (x1b0_SPLN > 0) { RenderNSidedSpline(); - else + } else { RenderNSidedNoSpline(); + } } zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); m_uniformBuf->load(&mvp, sizeof(zeus::CMatrix4f)); - if (m_cachedVerts.size()) + if (m_cachedVerts.size()) { m_vertBuf->load(m_cachedVerts.data(), m_cachedVerts.size() * sizeof(CParticleSwooshShaders::Vert)); + } } void CParticleSwoosh::SetOrientation(const zeus::CTransform& xf) { @@ -986,18 +1062,19 @@ const zeus::CVector3f& CParticleSwoosh::GetGlobalScale() const { return xe0_glob const zeus::CColor& CParticleSwoosh::GetModulationColor() const { return x20c_moduColor; } bool CParticleSwoosh::IsSystemDeletable() const { - if (x1d0_24_emitting && x28_curFrame < x2c_PSLT) + if (x1d0_24_emitting && x28_curFrame < x2c_PSLT) { return false; + } return GetParticleCount() < 2; } std::optional CParticleSwoosh::GetBounds() const { if (GetParticleCount() <= 1) { - zeus::CVector3f trans = x38_translation + xa4_globalTranslation; + const 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; + const 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); } } diff --git a/Runtime/Particle/CParticleSwoosh.hpp b/Runtime/Particle/CParticleSwoosh.hpp index ed421eeca..7eef5119c 100644 --- a/Runtime/Particle/CParticleSwoosh.hpp +++ b/Runtime/Particle/CParticleSwoosh.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -33,7 +34,7 @@ class CParticleSwoosh : public CParticleGen { 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 + int x68_frame = 0; // Frame index of evaluated data zeus::CColor x6c_color; // Updated by COLR int x70_startFrame; zeus::CVector3f x74_velocity; @@ -78,26 +79,20 @@ class CParticleSwoosh : public CParticleGen { int x1b0_SPLN = 0; int x1b4_LENG = 0; int x1b8_SIDE = 0; - GX::Primitive x1bc_prim; + 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; - }; + float x1cc_TSPN = 0.f; + 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; SUVElementSet x1d4_uvs = {}; CTexture* x1e4_tex = nullptr; @@ -108,7 +103,7 @@ class CParticleSwoosh : public CParticleGen { float x208_maxRadius = 0.f; zeus::CColor x20c_moduColor = zeus::skWhite; - boo::ObjToken m_dataBind[2]; + std::array, 2> m_dataBind; boo::ObjToken m_vertBuf; boo::ObjToken m_uniformBuf; std::unique_ptr m_lineRenderer; diff --git a/Runtime/Particle/CParticleSwooshDataFactory.cpp b/Runtime/Particle/CParticleSwooshDataFactory.cpp index 122d93b02..76ef71e19 100644 --- a/Runtime/Particle/CParticleSwooshDataFactory.cpp +++ b/Runtime/Particle/CParticleSwooshDataFactory.cpp @@ -122,7 +122,7 @@ bool CParticleSwooshDataFactory::CreateWPSM(CSwooshDescription* desc, CInputStre desc->x45_26_CRND = CPF::GetBool(in); break; default: { - Log.report(logvisor::Fatal, fmt("Unknown SWSH class {} @{}"), clsId, in.position()); + Log.report(logvisor::Fatal, FMT_STRING("Unknown SWSH class {} @{}"), clsId, in.position()); return false; } } diff --git a/Runtime/Particle/CProjectileWeaponDataFactory.cpp b/Runtime/Particle/CProjectileWeaponDataFactory.cpp index 6727f4295..c234a8907 100644 --- a/Runtime/Particle/CProjectileWeaponDataFactory.cpp +++ b/Runtime/Particle/CProjectileWeaponDataFactory.cpp @@ -149,8 +149,17 @@ bool CProjectileWeaponDataFactory::CreateWPSM(CWeaponDescription* desc, CInputSt case SBIG('FOFF'): desc->xb0_FOFF = CPF::GetRealElement(in); break; + case SBIG('SPS1'): + desc->x28_SPS1 = CPF::GetBool(in); + break; + case SBIG('SPS2'): + desc->x29_SPS2 = CPF::GetBool(in); + break; + case SBIG('FC60'): + desc->x29_FC60 = CPF::GetBool(in); + break; default: { - Log.report(logvisor::Fatal, fmt("Unknown WPSM class {} @{}"), clsId, in.position()); + Log.report(logvisor::Fatal, FMT_STRING("Unknown WPSM class {} @{}"), clsId, in.position()); return false; } } diff --git a/Runtime/Particle/CRealElement.cpp b/Runtime/Particle/CRealElement.cpp index 313aace09..707a372f4 100644 --- a/Runtime/Particle/CRealElement.cpp +++ b/Runtime/Particle/CRealElement.cpp @@ -137,17 +137,18 @@ 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); + int cv = a + b + 1; + if (cv < 0) { + cv = 1; + } - if (b >= 1) { - int cv2 = frame % cv; - if (cv2 >= a) - x10_valB->GetValue(frame, valOut); - else - xc_valA->GetValue(frame, valOut); - } else + // CREPulse is an outlier here, the other + // IElement classes use <= instead of <. + if (b < 1 || frame % cv < a) { xc_valA->GetValue(frame, valOut); - + } else { + x10_valB->GetValue(frame, valOut); + } return false; } diff --git a/Runtime/Particle/CSwooshDescription.hpp b/Runtime/Particle/CSwooshDescription.hpp index 084ac1971..67217d80f 100644 --- a/Runtime/Particle/CSwooshDescription.hpp +++ b/Runtime/Particle/CSwooshDescription.hpp @@ -31,23 +31,29 @@ public: 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; - }; - u32 dummy = 0; - }; + 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; - CSwooshDescription() { x44_25_CROS = true; } + CSwooshDescription() + : x44_24_LLRD(false) + , x44_25_CROS(true) + , x44_26_VLS1(false) + , x44_27_VLS2(false) + , x44_28_SROT(false) + , x44_29_WIRE(false) + , x44_30_TEXW(false) + , x44_31_AALP(false) + , x45_24_ZBUF(false) + , x45_25_ORNT(false) + , x45_26_CRND(false) {} }; } // namespace urde diff --git a/Runtime/Particle/CVectorElement.cpp b/Runtime/Particle/CVectorElement.cpp index 27fd0531d..0b395b68b 100644 --- a/Runtime/Particle/CVectorElement.cpp +++ b/Runtime/Particle/CVectorElement.cpp @@ -227,17 +227,16 @@ 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); + int cv = a + b + 1; + if (cv < 0) { + cv = 1; + } - if (b >= 1) { - int cv2 = frame % cv; - if (cv2 >= a) - x10_bVal->GetValue(frame, valOut); - else - xc_aVal->GetValue(frame, valOut); - } else + if (b < 1 || frame % cv <= a) { xc_aVal->GetValue(frame, valOut); - + } else { + x10_bVal->GetValue(frame, valOut); + } return false; } diff --git a/Runtime/Particle/CWeaponDescription.hpp b/Runtime/Particle/CWeaponDescription.hpp index b6a1c2852..0144fe111 100644 --- a/Runtime/Particle/CWeaponDescription.hpp +++ b/Runtime/Particle/CWeaponDescription.hpp @@ -18,7 +18,7 @@ struct SCollisionResponseData { 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; } + explicit operator bool() const { return m_found; } }; class CWeaponDescription { @@ -54,5 +54,9 @@ public: s32 xa8_PJFX = -1; std::unique_ptr xac_RNGE; std::unique_ptr xb0_FOFF; + // PAL/RS5 + bool x28_SPS1 = false; + bool x29_SPS2 = false; + bool x29_FC60 = false; }; } // namespace urde diff --git a/Runtime/RetroTypes.cpp b/Runtime/RetroTypes.cpp index d9fc73d5d..3a94df7d5 100644 --- a/Runtime/RetroTypes.cpp +++ b/Runtime/RetroTypes.cpp @@ -15,9 +15,9 @@ CAssetId::CAssetId(CInputStream& in) { else if (g_Main->GetExpectedIdSize() == sizeof(u64)) Assign(in.readUint64Big()); else - Log.report(logvisor::Fatal, fmt("Unsupported id length {}"), g_Main->GetExpectedIdSize()); + Log.report(logvisor::Fatal, FMT_STRING("Unsupported id length {}"), g_Main->GetExpectedIdSize()); } else - Log.report(logvisor::Fatal, fmt("Input constructor called before runtime Main entered!")); + Log.report(logvisor::Fatal, FMT_STRING("Input constructor called before runtime Main entered!")); } void CAssetId::PutTo(COutputStream& out) { @@ -27,9 +27,9 @@ void CAssetId::PutTo(COutputStream& out) { else if (g_Main->GetExpectedIdSize() == sizeof(u64)) out.writeUint64Big(id); else - Log.report(logvisor::Fatal, fmt("Unsupported id length {}"), g_Main->GetExpectedIdSize()); + Log.report(logvisor::Fatal, FMT_STRING("Unsupported id length {}"), g_Main->GetExpectedIdSize()); } else - Log.report(logvisor::Fatal, fmt("PutTo called before runtime Main entered!")); + Log.report(logvisor::Fatal, FMT_STRING("PutTo called before runtime Main entered!")); } } // namespace urde \ No newline at end of file diff --git a/Runtime/Weapon/CAuxWeapon.cpp b/Runtime/Weapon/CAuxWeapon.cpp index 64722caf8..e0e377821 100644 --- a/Runtime/Weapon/CAuxWeapon.cpp +++ b/Runtime/Weapon/CAuxWeapon.cpp @@ -28,7 +28,7 @@ constexpr std::array skComboNames{ }; constexpr std::array skSoundId{ - 1810, 1837, 1847, 1842, 1810, + SFXsfx0712, SFXsfx072D, SFXwpn_combo_wavebuster, SFXwpn_combo_flamethrower, SFXsfx0712, }; CAuxWeapon::CAuxWeapon(TUniqueId playerId) @@ -210,19 +210,21 @@ void CAuxWeapon::CreateFlameThrower(const zeus::CTransform& xf, CStateManager& m 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"), - {}}; + const std::array 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); + auto* 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); diff --git a/Runtime/Weapon/CBurstFire.cpp b/Runtime/Weapon/CBurstFire.cpp index fe5af34e8..4d0cc7334 100644 --- a/Runtime/Weapon/CBurstFire.cpp +++ b/Runtime/Weapon/CBurstFire.cpp @@ -9,7 +9,8 @@ #include namespace urde { -CBurstFire::CBurstFire(const SBurst* const* burstDefs, s32 firstBurstCount) : x10_firstBurstCounter(firstBurstCount) { +CBurstFire::CBurstFire(const SBurst* const* burstDefs, s32 firstBurstCount) +: x10_firstBurstCounter(firstBurstCount), x14_24_shouldFire(false), x14_25_avoidAccuracy(false) { while (*burstDefs) { x1c_burstDefs.push_back(*burstDefs); ++burstDefs; diff --git a/Runtime/Weapon/CBurstFire.hpp b/Runtime/Weapon/CBurstFire.hpp index a46bed4fd..3ed99890a 100644 --- a/Runtime/Weapon/CBurstFire.hpp +++ b/Runtime/Weapon/CBurstFire.hpp @@ -23,13 +23,8 @@ class CBurstFire { 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; - }; + bool x14_24_shouldFire : 1; + bool x14_25_avoidAccuracy : 1; const SBurst* x18_curBursts = nullptr; rstl::reserved_vector x1c_burstDefs; diff --git a/Runtime/Weapon/CEnergyProjectile.cpp b/Runtime/Weapon/CEnergyProjectile.cpp index cfc6e12d0..23b6e2cee 100644 --- a/Runtime/Weapon/CEnergyProjectile.cpp +++ b/Runtime/Weapon/CEnergyProjectile.cpp @@ -20,71 +20,89 @@ CEnergyProjectile::CEnergyProjectile(bool active, const TToken>& visorParticle, - u16 visorSfx, bool sendCollideMsg) + const std::optional>& 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]) +, x2ec_dir(xf.frontVector()) , x2f8_mag(x2ec_dir.magnitude()) -, x2fc_camShake(CCameraShakeData::BuildProjectileCameraShake(0.5f, 0.75f)) { +, x2fc_camShake(CCameraShakeData::BuildProjectileCameraShake(0.5f, 0.75f)) +, x3d0_24_dead(false) +, x3d0_25_(false) +, x3d0_26_(false) +, x3d0_27_camShakeDirty(false) { 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); + const s32 sfxId = x170_projectile.GetSoundIdForCollision(type); + if (sfxId < 0) { + return; } + + 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; + + const CSfxHandle hnd = CSfxManager::AddEmitter(parmData, true, 0x7f, false, kInvalidAreaId); + if (!x2e4_26_waterUpdate) { + return; + } + + 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()); + const TCastToConstPtr act = mgr.GetObjectById(owner); + if (!act) { + return; } + + const 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) + 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()) + 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; + } + } + const TLockedToken desc = x170_projectile.GetWeaponDescription(); + const s32 sfx = desc->xa8_PJFX; if (sfx != -1) { float range = 50.f; float falloff = 0.2f; - if (CRealElement* rnge = desc->xac_RNGE.get()) + if (CRealElement* rnge = desc->xac_RNGE.get()) { rnge->GetValue(0, range); - if (CRealElement* foff = desc->xb0_FOFF.get()) + } + if (CRealElement* foff = desc->xb0_FOFF.get()) { foff->GetValue(0, falloff); + } CAudioSys::C3DEmitterParmData parmData = {}; parmData.x0_pos = x170_projectile.GetTranslation(); @@ -113,22 +131,27 @@ void CEnergyProjectile::Accept(IVisitor& visitor) { visitor.Visit(this); } static constexpr u64 kCheckMaterial = 0xE3FFFE; void CEnergyProjectile::ResolveCollisionWithWorld(const CRayCastResult& res, CStateManager& mgr) { - EWeaponCollisionResponseTypes crType = CCollisionResponseData::GetWorldCollisionResponseType( + const auto crType = CCollisionResponseData::GetWorldCollisionResponseType( CMaterialList::BitPosition((res.GetMaterial().GetValue() & 0xffffffff) & kCheckMaterial)); - if ((xe8_projectileAttribs & (EProjectileAttrib::Wave | EProjectileAttrib::ComboShot)) != + + 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; + return; } + + // 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); + const auto 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())) { @@ -138,7 +161,7 @@ void CEnergyProjectile::ResolveCollisionWithActor(const CRayCastResult& res, CAc CGameProjectile::ResolveCollisionWithActor(res, act, mgr); ApplyDamageToActors(mgr, x12c_curDamageInfo); } - if (TCastToPtr proj = act) { + if (const TCastToPtr proj = act) { proj->Explode(GetTranslation(), x34_transform.basis[1], EWeaponCollisionResponseTypes::OtherProjectile, mgr, *GetDamageVulnerability(), GetUniqueId()); } @@ -147,31 +170,36 @@ void CEnergyProjectile::ResolveCollisionWithActor(const CRayCastResult& res, CAc void CEnergyProjectile::Think(float dt, CStateManager& mgr) { CWeapon::Think(dt, mgr); if (mgr.GetWorld()->GetCurrentAreaId() != GetAreaIdAlways() && - (xe8_projectileAttribs & EProjectileAttrib::ArmCannon) == EProjectileAttrib::ArmCannon) + (xe8_projectileAttribs & EProjectileAttrib::ArmCannon) == EProjectileAttrib::ArmCannon) { mgr.SetActorAreaId(*this, mgr.GetWorld()->GetCurrentAreaId()); + } UpdateProjectileMovement(dt, mgr); TUniqueId id = kInvalidUniqueId; - CRayCastResult res = DoCollisionCheck(id, mgr); + const CRayCastResult res = DoCollisionCheck(id, mgr); if (res.IsValid()) { - if (TCastToPtr act = mgr.ObjectById(id)) + if (const TCastToPtr act = mgr.ObjectById(id)) { ResolveCollisionWithActor(res, *act, mgr); - else + } else { ResolveCollisionWithWorld(res, mgr); + } } x170_projectile.UpdateParticleFX(); - if (x2e4_24_active && x3d0_26_) + if (x2e4_24_active && x3d0_26_) { Explode(GetTranslation(), zeus::skUp, EWeaponCollisionResponseTypes::Default, mgr, CDamageVulnerability::NormalVulnerabilty(), kInvalidUniqueId); + } if (x2c8_projectileLight != kInvalidUniqueId) { - if (TCastToPtr light = mgr.ObjectById(x2c8_projectileLight)) { + if (const TCastToPtr light = mgr.ObjectById(x2c8_projectileLight)) { light->SetTransform(GetTransform()); light->SetTranslation(GetTranslation()); - if (CElementGen* ps1 = x170_projectile.GetAttachedPS1()) - if (ps1->SystemHasLight()) + if (CElementGen* ps1 = x170_projectile.GetAttachedPS1()) { + if (ps1->SystemHasLight()) { light->SetLight(ps1->GetLight()); + } + } } } @@ -181,20 +209,22 @@ void CEnergyProjectile::Think(float dt, CStateManager& mgr) { } x3d4_curTime += dt; - if (x3d4_curTime > 45.f || x170_projectile.IsSystemDeletable() || x3d0_24_dead) + if (x3d4_curTime > 45.f || x170_projectile.IsSystemDeletable() || x3d0_24_dead) { mgr.FreeScriptObject(GetUniqueId()); + } } void CEnergyProjectile::Render(CStateManager& mgr) { - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CEnergyProjectile::Render WPSC_{}"), x2cc_wpscId).c_str(), zeus::skOrange); + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CEnergyProjectile::Render WPSC_{}"), x2cc_wpscId).c_str(), zeus::skOrange); - CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); + const auto 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) + const float warpTime = 1.f - float(x170_projectile.GameTime()); + if (warpTime > 0.f) { mgr.DrawSpaceWarp(GetTranslation(), warpTime * 0.75f); + } } } @@ -218,11 +248,12 @@ void CEnergyProjectile::Render(CStateManager& mgr) { } void CEnergyProjectile::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) { - auto bounds = x170_projectile.GetBounds(); - if (bounds && !frustum.aabbFrustumTest(*bounds)) + const auto bounds = x170_projectile.GetBounds(); + if (bounds && !frustum.aabbFrustumTest(*bounds)) { return; + } - CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); + const auto visor = mgr.GetPlayerState()->GetActiveVisor(mgr); if (visor != CPlayerState::EPlayerVisor::XRay && ((xe8_projectileAttribs & EProjectileAttrib::Ice) != EProjectileAttrib::Ice || mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot)) { @@ -243,7 +274,8 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3 bool retargetPlayer = false; bool deflect = false; zeus::CVector3f targetPos; - EVulnerability vulnType = dVuln.GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false); + const EVulnerability vulnType = dVuln.GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false); + if (vulnType == EVulnerability::Deflect) { deflect = true; EDeflectType deflectType = dVuln.GetDeflectionType(x12c_curDamageInfo.GetWeaponMode()); @@ -255,17 +287,19 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3 case EDeflectType::Three: if (deflectType != EDeflectType::Two || (xf0_weaponType != EWeaponType::Missile && - (xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::ComboShot)) - if (xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player)) + (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); + const float ang = mgr.GetActiveRandom()->Range(0.f, 2.f * M_PIF); + const float y = std::sin(ang); + const float x = std::cos(ang); targetPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f) + zeus::CVector3f(x, 0.f, y); ChangeProjectileOwner(hitActor, mgr); } @@ -274,7 +308,8 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3 if (vulnType != EVulnerability::Immune && !deflect) { deflect = (type == EWeaponCollisionResponseTypes::Unknown15 || type == EWeaponCollisionResponseTypes::EnemyShielded || - (type >= EWeaponCollisionResponseTypes::Unknown69 && type <= EWeaponCollisionResponseTypes::AtomicAlphaReflect)); + (type >= EWeaponCollisionResponseTypes::Unknown69 && + type <= EWeaponCollisionResponseTypes::AtomicAlphaReflect)); } SetTranslation(offsetPos); @@ -305,29 +340,30 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3 zeus::CVector3f scale = zeus::skOne3f; bool camClose = false; if (mgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) { - float mag = (offsetPos - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation()).magnitude(); + const 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) + if ((xe8_projectileAttribs & EProjectileAttrib::Ice) == EProjectileAttrib::Ice) { explodeFlags |= 0x4; - if (camClose) + } + 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::skWhite); + } + const CEntityInfo explosionInfo(GetAreaIdAlways(), CEntity::NullConnectionList); + auto* explosion = new CExplosion(*particle, mgr.AllocateUniqueId(), true, explosionInfo, + "Projectile collision response", particleXf, explodeFlags, scale, zeus::skWhite); mgr.AddObject(explosion); - if (TCastToPtr hActor = mgr.ObjectById(hitActor)) { + if (const 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 (const TCastToPtr otherPlat = ent) { if (otherPlat->IsSlave(hitActor)) { plat = otherPlat.GetPtr(); validPlat = true; @@ -336,8 +372,9 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3 } } } - if (validPlat) + if (validPlat) { plat->AddSlave(explosion->GetUniqueId(), mgr); + } } } else { x3d0_24_dead = true; @@ -345,13 +382,14 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3 if ((xe8_projectileAttribs & (EProjectileAttrib::ComboShot | EProjectileAttrib::Ice)) == (EProjectileAttrib::ComboShot | EProjectileAttrib::Ice)) { - /* Ice Spreader */ - TLockedToken iceSpreadParticle = g_SimplePool->GetObj("IceSpread1"); + // Ice Spreader + const 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::skOne3f, zeus::skWhite); + + auto* iceImpact = new CIceImpact(iceSpreadParticle, mgr.AllocateUniqueId(), GetAreaIdAlways(), true, + "Ice spread explosion", particleXf, flags, zeus::skOne3f, zeus::skWhite); mgr.AddObject(iceImpact); } } diff --git a/Runtime/Weapon/CEnergyProjectile.hpp b/Runtime/Weapon/CEnergyProjectile.hpp index 6156e0e0f..0413f086a 100644 --- a/Runtime/Weapon/CEnergyProjectile.hpp +++ b/Runtime/Weapon/CEnergyProjectile.hpp @@ -10,15 +10,10 @@ class CEnergyProjectile : public CGameProjectile { 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; - }; + 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); diff --git a/Runtime/Weapon/CFlameThrower.cpp b/Runtime/Weapon/CFlameThrower.cpp index 154c80e31..14d8b799a 100644 --- a/Runtime/Weapon/CFlameThrower.cpp +++ b/Runtime/Weapon/CFlameThrower.cpp @@ -33,10 +33,8 @@ CFlameThrower::CFlameThrower(const TToken& wDesc, std::strin , x3fc_playerIceTxtr(playerIceTxtr) , x400_24_active(false) , x400_25_particlesActive(false) -, x400_26_(!(flameInfo.GetAttributes() & 1)) -, x400_27_coneCollision((flameInfo.GetAttributes() & 0x2) != 0) { - -} +, x400_26_((flameInfo.GetAttributes() & 1) == 0) +, x400_27_coneCollision((flameInfo.GetAttributes() & 0x2) != 0) {} void CFlameThrower::Accept(IVisitor& visitor) { visitor.Visit(this); } diff --git a/Runtime/Weapon/CFlameThrower.hpp b/Runtime/Weapon/CFlameThrower.hpp index 423f8e7d4..2b824cc40 100644 --- a/Runtime/Weapon/CFlameThrower.hpp +++ b/Runtime/Weapon/CFlameThrower.hpp @@ -31,16 +31,10 @@ private: CAssetId x3f4_playerSteamTxtr; s16 x3f8_playerHitSfx; CAssetId x3fc_playerIceTxtr; - - union { - struct { - bool x400_24_active : 1; - bool x400_25_particlesActive : 1; - bool x400_26_ : 1; - bool x400_27_coneCollision : 1; /* Z-sort and finer collision detection */ - }; - u32 _dummy = 0; - }; + bool x400_24_active : 1; + bool x400_25_particlesActive : 1; + bool x400_26_ : 1; + bool x400_27_coneCollision : 1; /* Z-sort and finer collision detection */ void CreateFlameParticles(CStateManager&); void SetFlameLightActive(CStateManager&, bool); diff --git a/Runtime/Weapon/CGSComboFire.hpp b/Runtime/Weapon/CGSComboFire.hpp index bdac15732..2c789475d 100644 --- a/Runtime/Weapon/CGSComboFire.hpp +++ b/Runtime/Weapon/CGSComboFire.hpp @@ -11,16 +11,12 @@ class CGSComboFire { 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; - }; + bool x10_24_over : 1; + bool x10_25_idle : 1; public: + CGSComboFire() : x10_24_over(false), x10_25_idle(false) {} + bool IsComboOver() const { return x10_24_over; } s32 GetLoopState() const { return x4_loopState; } void SetLoopState(s32 l) { x4_loopState = l; } diff --git a/Runtime/Weapon/CGameProjectile.cpp b/Runtime/Weapon/CGameProjectile.cpp index 312c3cb32..83dc6a2ac 100644 --- a/Runtime/Weapon/CGameProjectile.cpp +++ b/Runtime/Weapon/CGameProjectile.cpp @@ -1,5 +1,7 @@ #include "Runtime/Weapon/CGameProjectile.hpp" +#include + #include "Runtime/CStateManager.hpp" #include "Runtime/Collision/CCollisionActor.hpp" #include "Runtime/Collision/CInternalRayCastStructure.hpp" @@ -19,15 +21,15 @@ CGameProjectile::CGameProjectile(bool active, const TToken& const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, TUniqueId homingTarget, EProjectileAttrib attribs, bool underwater, const zeus::CVector3f& scale, - const std::optional>& visorParticle, - u16 visorSfx, bool sendCollideMsg) + std::optional> visorParticle, u16 visorSfx, + bool sendCollideMsg) : CWeapon(uid, aid, active, owner, wType, name, xf, CMaterialFilter::MakeIncludeExclude( {EMaterialTypes::Solid, EMaterialTypes::NonSolidDamageable}, {EMaterialTypes::Projectile, EMaterialTypes::ProjectilePassthrough, excludeMat}), CMaterialList(EMaterialTypes::Projectile), dInfo, attribs | GetBeamAttribType(wType), CModelData::CModelDataNull()) -, x158_visorParticle(visorParticle) +, x158_visorParticle(std::move(visorParticle)) , x168_visorSfx(visorSfx) , x170_projectile(wDesc, xf.origin, xf.basis, scale, (attribs & EProjectileAttrib::ParticleOPTS) == EProjectileAttrib::ParticleOPTS) @@ -35,13 +37,12 @@ CGameProjectile::CGameProjectile(bool active, const TToken& , 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; -} +, 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); } diff --git a/Runtime/Weapon/CGameProjectile.hpp b/Runtime/Weapon/CGameProjectile.hpp index c3ea5e75d..06748ee5a 100644 --- a/Runtime/Weapon/CGameProjectile.hpp +++ b/Runtime/Weapon/CGameProjectile.hpp @@ -49,23 +49,18 @@ protected: 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; - }; - }; + 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::optional>& visorParticle, u16 visorSfx, - bool sendCollideMsg); + const zeus::CVector3f& scale, std::optional> visorParticle, + u16 visorSfx, bool sendCollideMsg); void Accept(IVisitor& visitor) override; virtual void ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr); diff --git a/Runtime/Weapon/CGrappleArm.cpp b/Runtime/Weapon/CGrappleArm.cpp index fc80cd45a..e6aca556e 100644 --- a/Runtime/Weapon/CGrappleArm.cpp +++ b/Runtime/Weapon/CGrappleArm.cpp @@ -37,7 +37,13 @@ CGrappleArm::CGrappleArm(const zeus::CVector3f& scale) , 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)) { +, x3a4_rainSplashGenerator(std::make_unique(scale, 20, 2, 0.f, 0.125f)) +, x3b2_24_active(false) +, x3b2_25_beamActive(false) +, x3b2_26_grappleHit(false) +, x3b2_27_armMoving(false) +, x3b2_28_isGrappling(false) +, x3b2_29_suitLoading(false) { x0_grappleArmModel->SetSortThermal(true); xa0_grappleGearModel.SetSortThermal(true); xec_grapNoz1Model.SetSortThermal(true); @@ -125,35 +131,35 @@ void CGrappleArm::SetAnimState(EArmState state) { switch (state) { case EArmState::IntoGrapple: { ResetAuxParams(true); - CAnimPlaybackParms parms(0, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(0, -1, 1.f, true); x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false); x3b2_25_beamActive = false; x3b2_24_active = true; break; } case EArmState::IntoGrappleIdle: { - CAnimPlaybackParms parms(1, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(1, -1, 1.f, true); x0_grappleArmModel->GetAnimationData()->EnableLooping(true); x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false); break; } case EArmState::FireGrapple: { - CAnimPlaybackParms parms(2, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(2, -1, 1.f, true); x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false); break; } case EArmState::ConnectGrapple: { - CAnimPlaybackParms parms(3, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(3, -1, 1.f, true); x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false); break; } case EArmState::Connected: { - CAnimPlaybackParms parms(3, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(3, -1, 1.f, true); x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false); break; } case EArmState::OutOfGrapple: { - CAnimPlaybackParms parms(4, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(4, -1, 1.f, true); x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false); DisconnectGrappleBeam(); break; @@ -478,7 +484,7 @@ void CGrappleArm::RenderXRayModel(const CStateManager& mgr, const zeus::CTransfo CGraphics::SetModelMatrix(modelXf * zeus::CTransform::Scale(x0_grappleArmModel->GetScale())); // CGraphics::DisableAllLights(); // g_Renderer->SetAmbientColor(zeus::skWhite); - CSkinnedModel& model = const_cast(*x50_grappleArmSkeletonModel->GetAnimationData()->GetModelData()); + CSkinnedModel& model = *x50_grappleArmSkeletonModel->GetAnimationData()->GetModelData(); model.GetModelInst()->ActivateLights({CLight::BuildLocalAmbient({}, zeus::skWhite)}); x0_grappleArmModel->GetAnimationData()->Render(model, flags, std::nullopt, nullptr); // g_Renderer->SetAmbientColor(zeus::skWhite); diff --git a/Runtime/Weapon/CGrappleArm.hpp b/Runtime/Weapon/CGrappleArm.hpp index 87873faf5..f3192ee14 100644 --- a/Runtime/Weapon/CGrappleArm.hpp +++ b/Runtime/Weapon/CGrappleArm.hpp @@ -75,17 +75,12 @@ private: 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; - }; + 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; static float g_GrappleBeamAnglePhaseDelta; static float g_GrappleBeamXWaveAmplitude; diff --git a/Runtime/Weapon/CGunMotion.cpp b/Runtime/Weapon/CGunMotion.cpp index 966886eef..85db42741 100644 --- a/Runtime/Weapon/CGunMotion.cpp +++ b/Runtime/Weapon/CGunMotion.cpp @@ -83,7 +83,7 @@ void CGunMotion::Update(float dt, CStateManager& mgr) { } void CGunMotion::Draw(const CStateManager& mgr, const zeus::CTransform& xf) const { - CModelFlags flags(0, 0, 3, zeus::skWhite); + constexpr CModelFlags flags(0, 0, 3, zeus::skWhite); x0_modelData.Render(mgr, xf, nullptr, flags); } diff --git a/Runtime/Weapon/CGunWeapon.cpp b/Runtime/Weapon/CGunWeapon.cpp index 5ff1215c1..3baa52db1 100644 --- a/Runtime/Weapon/CGunWeapon.cpp +++ b/Runtime/Weapon/CGunWeapon.cpp @@ -70,7 +70,13 @@ CGunWeapon::CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, EM , x1c8_playerMaterial(playerMaterial) , x200_beamId(GetWeaponIndex(type)) , x20c_shaderIdx(u32(x200_beamId)) -, x214_ancsId(ancsId) { +, x214_ancsId(ancsId) +, x218_24(false) +, x218_25_enableCharge(false) +, x218_26_loaded(false) +, x218_27_subtypeBasePose(false) +, x218_28_suitArmLocked(false) +, x218_29_drawHologram(false) { AllocResPools(x200_beamId); BuildDependencyList(x200_beamId); } @@ -172,7 +178,7 @@ void CGunWeapon::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, } } -const std::array CGunWeapon::skShootAnim{4, 3}; +constexpr std::array CGunWeapon::skShootAnim{4, 3}; void CGunWeapon::Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) { @@ -250,7 +256,7 @@ void CGunWeapon::TouchHolo(const CStateManager& mgr) { } void CGunWeapon::PointGenerator(void* ctx, const std::vector>& vn) { - reinterpret_cast(ctx)->GeneratePoints(vn); + static_cast(ctx)->GeneratePoints(vn); } void CGunWeapon::Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags, @@ -265,17 +271,17 @@ void CGunWeapon::Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CT 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); + const zeus::CColor mulColor(flags.x4_color.a(), flags.x4_color.a()); + constexpr zeus::CColor addColor(0.25f, 0.25f); if (x218_29_drawHologram) { DrawHologram(mgr, xf, flags); } else { - CModelFlags useFlags(0, 0, 3, zeus::skWhite); + constexpr CModelFlags useFlags(0, 0, 3, zeus::skWhite); x10_solidModelData->RenderThermal(xf, mulColor, addColor, useFlags); } if (drawSuitArm && xb0_suitArmModelData) { - CModelFlags useFlags(0, 0, 3, zeus::skWhite); + constexpr CModelFlags useFlags(0, 0, 3, zeus::skWhite); xb0_suitArmModelData->RenderThermal(xf, mulColor, addColor, useFlags); } } else { diff --git a/Runtime/Weapon/CGunWeapon.hpp b/Runtime/Weapon/CGunWeapon.hpp index 30328d686..a4d099cde 100644 --- a/Runtime/Weapon/CGunWeapon.hpp +++ b/Runtime/Weapon/CGunWeapon.hpp @@ -84,18 +84,13 @@ protected: // 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; - }; + 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; void AllocResPools(CPlayerState::EBeamId beam); void FreeResPools(); diff --git a/Runtime/Weapon/CIceBeam.cpp b/Runtime/Weapon/CIceBeam.cpp index 298a9dc88..4db41a2dc 100644 --- a/Runtime/Weapon/CIceBeam.cpp +++ b/Runtime/Weapon/CIceBeam.cpp @@ -1,5 +1,7 @@ #include "Runtime/Weapon/CIceBeam.hpp" +#include + #include "Runtime/CSimplePool.hpp" #include "Runtime/GameGlobalObjects.hpp" @@ -59,12 +61,12 @@ void CIceBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, c CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); } -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) { + static constexpr std::array soundId{SFXwpn_fire_ice_normal, SFXwpn_fire_ice_charged}; + CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); - NWeaponTypes::play_sfx(kSoundId[int(chargeState)], underwater, false, 0.165f); + NWeaponTypes::play_sfx(soundId[size_t(chargeState)], underwater, false, 0.165f); } void CIceBeam::EnableFx(bool enable) { diff --git a/Runtime/Weapon/CNewFlameThrower.cpp b/Runtime/Weapon/CNewFlameThrower.cpp index f2c86609f..2e8bdaac0 100644 --- a/Runtime/Weapon/CNewFlameThrower.cpp +++ b/Runtime/Weapon/CNewFlameThrower.cpp @@ -8,9 +8,9 @@ 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) + const std::array& resInfo, 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::skOne3f, {}, -1, false) , x304_mainFire(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[0]})) diff --git a/Runtime/Weapon/CNewFlameThrower.hpp b/Runtime/Weapon/CNewFlameThrower.hpp index 29f8af7a9..4c2353f58 100644 --- a/Runtime/Weapon/CNewFlameThrower.hpp +++ b/Runtime/Weapon/CNewFlameThrower.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -10,7 +11,7 @@ namespace urde { class CNewFlameThrower : public CGameProjectile { - CRandom16 x2e8_rand = {99}; + CRandom16 x2e8_rand{99}; float x2ec_ = 0.f; float x2f0_ = 0.f; bool x300_ = false; @@ -53,7 +54,7 @@ public: // NFTSecondarySparks // CNewFlameThrower(const TToken& desc, std::string_view name, EWeaponType wType, - const CAssetId resInfo[8], const zeus::CTransform& xf, EMaterialTypes matType, + const std::array& resInfo, 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; } diff --git a/Runtime/Weapon/CPhazonBeam.cpp b/Runtime/Weapon/CPhazonBeam.cpp index 3017a7fa1..5a20894a8 100644 --- a/Runtime/Weapon/CPhazonBeam.cpp +++ b/Runtime/Weapon/CPhazonBeam.cpp @@ -1,5 +1,7 @@ #include "Runtime/Weapon/CPhazonBeam.hpp" +#include + #include "Runtime/CSimplePool.hpp" #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/Graphics/CBooRenderer.hpp" @@ -77,8 +79,6 @@ void CPhazonBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); } -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) { @@ -95,7 +95,8 @@ void CPhazonBeam::Fire(bool underwater, float dt, EChargeState chargeState, cons CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); } - NWeaponTypes::play_sfx(kSoundId[int(chargeState)], underwater, false, 0.165f); + static constexpr std::array soundId{SFXwpn_fire_phazon_normal, SFXwpn_fire_power_charged}; + NWeaponTypes::play_sfx(soundId[size_t(chargeState)], underwater, false, 0.165f); } void CPhazonBeam::Update(float dt, CStateManager& mgr) { diff --git a/Runtime/Weapon/CPlasmaProjectile.cpp b/Runtime/Weapon/CPlasmaProjectile.cpp index 7d25610d7..b6475aad3 100644 --- a/Runtime/Weapon/CPlasmaProjectile.cpp +++ b/Runtime/Weapon/CPlasmaProjectile.cpp @@ -29,8 +29,8 @@ CPlasmaProjectile::CPlasmaProjectile(const TToken& wDesc, st const CBeamInfo& bInfo, const zeus::CTransform& xf, EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, const PlayerEffectResoures& res, bool growingBeam, EProjectileAttrib attribs) -: CBeamProjectile(wDesc, name, wType, xf, bInfo.GetLength(), bInfo.GetRadius(), bInfo.GetTravelSpeed(), matType, - dInfo, uid, aid, owner, attribs, growingBeam) +: CBeamProjectile(wDesc, name, wType, xf, bInfo.GetLength(), bInfo.GetRadius(), bInfo.GetTravelSpeed(), matType, dInfo, + uid, aid, owner, attribs, growingBeam) , x478_beamAttributes(bInfo.GetBeamAttributes()) , x47c_lifeTime(bInfo.GetLifeTime()) , x480_pulseSpeed(bInfo.GetPulseSpeed()) @@ -38,7 +38,13 @@ CPlasmaProjectile::CPlasmaProjectile(const TToken& wDesc, st , x488_expansionSpeed(bInfo.GetExpansionSpeed()) , x48c_(bInfo.GetLength() / 32.f) , x490_innerColor(bInfo.GetInnerColor()) -, x494_outerColor(bInfo.GetOuterColor()) { +, x494_outerColor(bInfo.GetOuterColor()) +, x548_24_(false) +, x548_25_enableEnergyPulse(true) +, x548_26_firing(false) +, x548_27_texturesLoaded(false) +, x548_28_drawOwnerFirst(growingBeam) +, x548_29_activePlayerPhazon(false) { x4e8_texture = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), bInfo.GetTextureId()}); x4f4_glowTexture = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), bInfo.GetGlowTextureId()}); x500_contactFxDesc = g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), bInfo.GetContactFxId()}); @@ -47,14 +53,14 @@ CPlasmaProjectile::CPlasmaProjectile(const TToken& wDesc, st x51c_pulseGen = std::make_unique(x50c_pulseFxDesc, CElementGen::EModelOrientationType::Normal); x524_freezeSteamTxtr = res[0]; x528_freezeIceTxtr = res[1]; - if (res[2] != UINT64_MAX) + if (res[2].IsValid()) { x52c_visorElectric = g_SimplePool->GetObj(SObjectTag{FOURCC('ELSC'), res[2]}); - if (res[3] != UINT64_MAX) + } + if (res[3].IsValid()) { x538_visorParticle = g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), res[3]}); - x544_freezeSfx = CSfxManager::TranslateSFXID(res[4]); - x546_electricSfx = CSfxManager::TranslateSFXID(res[5]); - x548_25_enableEnergyPulse = true; - x548_28_drawOwnerFirst = growingBeam; + } + x544_freezeSfx = CSfxManager::TranslateSFXID(u16(res[4].Value())); + x546_electricSfx = CSfxManager::TranslateSFXID(u16(res[5].Value())); x518_contactGen->SetGlobalScale(zeus::CVector3f(bInfo.GetContactFxScale())); x51c_pulseGen->SetGlobalScale(zeus::CVector3f(bInfo.GetPulseFxScale())); x518_contactGen->SetParticleEmission(false); @@ -134,7 +140,7 @@ void CPlasmaProjectile::UpdateEnergyPulse(float dt) { x51c_pulseGen->Update(dt); } -void CPlasmaProjectile::RenderMotionBlur() const { +void CPlasmaProjectile::RenderMotionBlur() { CGraphics::SetModelMatrix({}); zeus::CColor color1 = x494_outerColor; zeus::CColor color2 = x494_outerColor; diff --git a/Runtime/Weapon/CPlasmaProjectile.hpp b/Runtime/Weapon/CPlasmaProjectile.hpp index d9c249c5b..048b78fc0 100644 --- a/Runtime/Weapon/CPlasmaProjectile.hpp +++ b/Runtime/Weapon/CPlasmaProjectile.hpp @@ -18,10 +18,10 @@ namespace urde { class CPlasmaProjectile : public CBeamProjectile { public: - struct PlayerEffectResoures : rstl::reserved_vector { - PlayerEffectResoures(u64 a = UINT64_MAX, u64 b = UINT64_MAX, u64 c = UINT64_MAX, u64 d = UINT64_MAX, - u64 e = UINT64_MAX, u64 f = UINT64_MAX, u64 g = UINT64_MAX, u64 h = UINT64_MAX) - : rstl::reserved_vector({a, b, c, d, e, f, g, h}) {} + struct PlayerEffectResoures : rstl::reserved_vector { + PlayerEffectResoures(CAssetId a = {}, CAssetId b = {}, CAssetId c = {}, CAssetId d = {}, + CAssetId e = {}, CAssetId f = {}, CAssetId g = {}, CAssetId h = {}) + : rstl::reserved_vector({a, b, c, d, e, f, g, h}) {} }; private: std::vector x468_lights; @@ -67,17 +67,12 @@ private: TToken x538_visorParticle; // Used to be optional u16 x544_freezeSfx; u16 x546_electricSfx; - union { - struct { - bool x548_24_ : 1; - bool x548_25_enableEnergyPulse : 1; - bool x548_26_firing : 1; - bool x548_27_texturesLoaded : 1; - bool x548_28_drawOwnerFirst : 1; - bool x548_29_activePlayerPhazon : 1; - }; - u32 _dummy3 = 0; - }; + bool x548_24_ : 1; + bool x548_25_enableEnergyPulse : 1; + bool x548_26_firing : 1; + bool x548_27_texturesLoaded : 1; + bool x548_28_drawOwnerFirst : 1; + bool x548_29_activePlayerPhazon : 1; struct RenderObjects { CColoredStripShader m_beamStrip1; @@ -93,14 +88,14 @@ private: boo::ObjToken tex, boo::ObjToken glowTex); }; - mutable std::optional m_renderObjs; + std::optional m_renderObjs; void SetLightsActive(bool active, CStateManager& mgr); void CreatePlasmaLights(u32 sourceId, const CLight& l, CStateManager& mgr); void DeletePlasmaLights(CStateManager& mgr); void UpdateLights(float expansion, float dt, CStateManager& mgr); void UpdateEnergyPulse(float dt); - void RenderMotionBlur() const; + void RenderMotionBlur(); void RenderBeam(s32 subdivs, float width, const zeus::CColor& color, s32 flags, CColoredStripShader& shader) const; float UpdateBeamState(float dt, CStateManager& mgr); diff --git a/Runtime/Weapon/CPlayerGun.cpp b/Runtime/Weapon/CPlayerGun.cpp index 8a279abc3..b74da08de 100644 --- a/Runtime/Weapon/CPlayerGun.cpp +++ b/Runtime/Weapon/CPlayerGun.cpp @@ -109,29 +109,61 @@ constexpr std::array chargeShakeTbl{ constexpr CMaterialFilter sAimFilter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough}); -const std::array kThermalFlags{{ +constexpr std::array kThermalFlags{{ {0, 0, 3, zeus::skWhite}, {5, 0, 3, zeus::CColor(0.f, 0.5f)}, {0, 0, 3, zeus::skWhite}, {0, 0, 3, zeus::skWhite}, }}; -const CModelFlags kHandThermalFlag = {7, 0, 3, zeus::skWhite}; -const CModelFlags kHandHoloFlag = {1, 0, 3, zeus::CColor(0.75f, 0.5f, 0.f, 1.f)}; +constexpr CModelFlags kHandThermalFlag{7, 0, 3, zeus::skWhite}; +constexpr CModelFlags kHandHoloFlag{1, 0, 3, zeus::CColor(0.75f, 0.5f, 0.f, 1.f)}; } // Anonymous namespace 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) +: x0_lights(8, zeus::CVector3f{-30.f, 0.f, 30.f}, 4, 4, false, 0, 0, 0.1f) , x538_playerId(playerId) , x550_camBob(CPlayerCameraBob::ECameraBobType::One, CPlayerCameraBob::GetCameraBobExtent(), CPlayerCameraBob::GetCameraBobPeriod()) , 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)) { +, x6e0_rightHandModel(CAnimRes(g_tweakGunRes->xc_rightHand, 0, zeus::CVector3f(3.f), 0, true)) +, x832_24_coolingCharge(false) +, x832_25_chargeEffectVisible(false) +, x832_26_comboFiring(false) +, x832_27_chargeAnimStarted(false) +, x832_28_readyForShot(false) +, x832_29_lockedOn(false) +, x832_30_requestReturnToDefault(false) +, x832_31_inRestPose(true) +, x833_24_notFidgeting(true) +, x833_25_(false) +, x833_26_(false) +, x833_27_(false) +, x833_28_phazonBeamActive(false) +, x833_29_pointBlankWorldSurface(false) +, x833_30_canShowAuxMuzzleEffect(true) +, x833_31_inFreeLook(false) +, x834_24_charging(false) +, x834_25_gunMotionFidgeting(false) +, x834_26_animPlaying(false) +, x834_27_underwater(false) +, x834_28_requestImmediateRecharge(false) +, x834_29_frozen(false) +, x834_30_inBigStrike(false) +, x834_31_gunMotionInFidgetBasePosition(false) +, x835_24_canFirePhazon(false) +, x835_25_inPhazonBeam(false) +, x835_26_phazonBeamMorphing(false) +, x835_27_intoPhazonBeam(false) +, x835_28_bombReady(false) +, x835_29_powerBombReady(false) +, x835_30_inPhazonPool(false) +, x835_31_actorAttached(false) { x354_bombFuseTime = g_tweakPlayerGun->GetBombFuseTime(); x358_bombDropDelayTime = g_tweakPlayerGun->GetBombDropDelayTime(); x668_aimVerticalSpeed = g_tweakPlayerGun->GetAimVerticalSpeed(); @@ -155,9 +187,6 @@ CPlayerGun::CPlayerGun(TUniqueId playerId) 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); kVerticalAngleTable[2] = g_tweakPlayerGun->GetUpLookAngle(); diff --git a/Runtime/Weapon/CPlayerGun.hpp b/Runtime/Weapon/CPlayerGun.hpp index 1a0dda246..579e5e825 100644 --- a/Runtime/Weapon/CPlayerGun.hpp +++ b/Runtime/Weapon/CPlayerGun.hpp @@ -82,18 +82,15 @@ private: float x18_transitionFactor = 1.f; EDir x1c_dir = EDir::Done; EGunState x20_gunState = EGunState::OutWipeDone; - - union { - struct { - bool x24_24_morphing : 1; - bool x24_25_weaponChanged : 1; - }; - u32 _dummy = 0; - }; + bool x24_24_morphing : 1; + bool x24_25_weaponChanged : 1; public: CGunMorph(float gunTransformTime, float holoHoldTime) - : x4_gunTransformTime(gunTransformTime), x10_holoHoldTime(std::fabs(holoHoldTime)) {} + : x4_gunTransformTime(gunTransformTime) + , x10_holoHoldTime(std::fabs(holoHoldTime)) + , x24_24_morphing(false) + , x24_25_weaponChanged(false) {} float GetYLerp() const { return x0_yLerp; } float GetTransitionFactor() const { return x18_transitionFactor; } EGunState GetGunState() const { return x20_gunState; } @@ -225,46 +222,41 @@ private: std::unique_ptr x82c_shadow; s16 x830_chargeRumbleHandle = -1; - union { - struct { - bool x832_24_coolingCharge : 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 x832_24_coolingCharge : 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 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 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; - }; + 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; CTexturedQuadFilter m_screenQuad{EFilterType::Blend, CGraphics::g_SpareTexture.get(), CTexturedQuadFilter::ZTest::GEqualZWrite}; diff --git a/Runtime/Weapon/CProjectileWeapon.cpp b/Runtime/Weapon/CProjectileWeapon.cpp index 31316e3b9..55dddc6f3 100644 --- a/Runtime/Weapon/CProjectileWeapon.cpp +++ b/Runtime/Weapon/CProjectileWeapon.cpp @@ -15,8 +15,15 @@ CProjectileWeapon::CProjectileWeapon(const TToken& wDesc, co , x10_random(g_GlobalSeed) , x14_localToWorldXf(localToWorld) , x74_worldOffset(worldOffset) -, xe4_flags(flags) { - x124_24_active = true; +, xe4_flags(flags) +, x124_24_active(true) +, x124_25_APSO(false) +, x124_26_AP11(false) +, x124_27_AP21(false) +, x124_28_AS11(false) +, x124_29_AS12(false) +, x124_30_AS13(false) +, x124_31_VMD2(false) { CGlobalRandom gr(x10_random); x124_31_VMD2 = x4_weaponDesc->x10_VMD2; x124_25_APSO = x4_weaponDesc->x28_APSO; @@ -201,7 +208,7 @@ void CProjectileWeapon::RenderParticles() const { x104_->Render(); } -void CProjectileWeapon::AddToRenderer() const { +void CProjectileWeapon::AddToRenderer() { if (xfc_APSMGen) g_Renderer->AddParticleGen(*xfc_APSMGen); if (x100_APS2Gen) @@ -216,7 +223,7 @@ void CProjectileWeapon::AddToRenderer() const { g_Renderer->AddParticleGen(*x104_); } -void CProjectileWeapon::Render() const { +void CProjectileWeapon::Render() { if (xf4_curFrame > xe8_lifetime || !x124_24_active || !x108_model) return; @@ -227,8 +234,8 @@ void CProjectileWeapon::Render() const { std::vector useLights; useLights.push_back(CLight::BuildLocalAmbient({}, xc8_ambientLightColor)); - const_cast(**x108_model).GetInstance().ActivateLights(useLights); - CModelFlags flags(0, 0, 3, zeus::skWhite); + (**x108_model).GetInstance().ActivateLights(useLights); + constexpr CModelFlags flags(0, 0, 3, zeus::skWhite); (*x108_model)->Draw(flags); } diff --git a/Runtime/Weapon/CProjectileWeapon.hpp b/Runtime/Weapon/CProjectileWeapon.hpp index b24b68433..6ff083fde 100644 --- a/Runtime/Weapon/CProjectileWeapon.hpp +++ b/Runtime/Weapon/CProjectileWeapon.hpp @@ -53,19 +53,14 @@ class CProjectileWeapon { 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; - }; + 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; public: CProjectileWeapon(const TToken& wDesc, const zeus::CVector3f& worldOffset, @@ -88,8 +83,8 @@ public: const zeus::CVector3f& target); TLockedToken GetWeaponDescription() const { return x4_weaponDesc; } void RenderParticles() const; - virtual void AddToRenderer() const; - virtual void Render() const; + virtual void AddToRenderer(); + virtual void Render(); bool IsSystemDeletable() const; void UpdateChildParticleSystems(float); void UpdatePSTranslationAndOrientation(); diff --git a/Runtime/Weapon/CWaveBuster.hpp b/Runtime/Weapon/CWaveBuster.hpp index d15269cca..c46c471d0 100644 --- a/Runtime/Weapon/CWaveBuster.hpp +++ b/Runtime/Weapon/CWaveBuster.hpp @@ -26,7 +26,7 @@ class CWaveBuster : public CGameProjectile { std::unique_ptr x388_busterSwoosh2Gen; std::unique_ptr x38c_busterSparksGen; std::unique_ptr x390_busterLightGen; - CRandom16 x394_rand = {99}; + CRandom16 x394_rand{99}; float x39c_ = 0.5f; float x3a0_ = 0.5f; float x3a4_ = 0.f; diff --git a/Runtime/Weapon/WeaponCommon.cpp b/Runtime/Weapon/WeaponCommon.cpp index 7c448a2e4..ef6ade659 100644 --- a/Runtime/Weapon/WeaponCommon.cpp +++ b/Runtime/Weapon/WeaponCommon.cpp @@ -134,10 +134,11 @@ void do_sound_event(std::pair& sfxHandle, float& pitch, bool do } } -CAssetId get_asset_id_from_name(const char* name) { +CAssetId get_asset_id_from_name(std::string_view name) { const SObjectTag* tag = g_ResFactory->GetResourceIdByName(name); - if (!tag) + if (!tag) { return {}; + } return tag->id; } diff --git a/Runtime/Weapon/WeaponCommon.hpp b/Runtime/Weapon/WeaponCommon.hpp index 599911708..74c183927 100644 --- a/Runtime/Weapon/WeaponCommon.hpp +++ b/Runtime/Weapon/WeaponCommon.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp" @@ -83,7 +84,7 @@ void get_token_vector(const CAnimData& animData, int animIdx, std::vector& 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); +CAssetId get_asset_id_from_name(std::string_view name); CPlayerState::EPlayerSuit get_current_suit(const CStateManager& mgr); CSfxHandle play_sfx(u16 sfx, bool underwater, bool looped, float pan); diff --git a/Runtime/World/CActor.cpp b/Runtime/World/CActor.cpp index 37fa2b6d4..ee78f3806 100644 --- a/Runtime/World/CActor.cpp +++ b/Runtime/World/CActor.cpp @@ -34,27 +34,37 @@ 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) { +, xc6_nextDrawNode(otherUid) +, xe4_24_nextNonLoopingSfxHandle(0) +, xe4_27_notInSortedLists(true) +, xe4_28_transformDirty(true) +, xe4_29_actorLightsDirty(true) +, xe4_30_outOfFrustum(false) +, xe4_31_calculateLighting(true) +, xe5_24_shadowEnabled(false) +, xe5_25_shadowDirty(false) +, xe5_26_muted(false) +, xe5_27_useInSortedLists(true) +, xe5_28_callTouch(true) +, xe5_29_globalTimeProvider(params.x58_24_globalTimeProvider) +, xe5_30_renderUnsorted(params.x58_26_renderUnsorted) +, xe5_31_pointGeneratorParticles(false) +, xe6_24_fluidCounter(0) +, xe6_27_thermalVisorFlags(u8(params.x58_25_thermalHeat ? 2 : 1)) +, xe6_29_renderParticleDBInside(true) +, xe6_30_enablePitchBend(false) +, xe6_31_targetableVisorFlags(params.GetVisorParameters().GetMask()) +, xe7_27_enableRender(true) +, xe7_28_worldLightingDirty(false) +, xe7_29_drawEnabled(active) +, xe7_30_doTargetDistanceTest(true) +, xe7_31_targetable(true) { x90_actorLights = mData.IsNull() ? nullptr : 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); @@ -94,7 +104,7 @@ void CActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMana else RemoveMaterial(EMaterialTypes::Scannable, mgr); - if (HasModelData() && x64_modelData->GetAnimationData()) { + if (HasModelData() && x64_modelData->HasAnimData()) { TAreaId aid = GetAreaId(); x64_modelData->GetAnimationData()->InitializeEffects(mgr, aid, x64_modelData->GetScale()); } @@ -212,7 +222,7 @@ void CActor::DrawTouchBounds() const { void CActor::RenderInternal(const CStateManager& mgr) const { SCOPED_GRAPHICS_DEBUG_GROUP( - fmt::format(fmt("CActor::RenderInternal {} {} {}"), x8_uid, xc_editorId, x10_name).c_str(), zeus::skOrange); + fmt::format(FMT_STRING("CActor::RenderInternal {} {} {}"), x8_uid, xc_editorId, x10_name).c_str(), zeus::skOrange); CModelData::EWhichModel which = CModelData::GetRenderingModel(mgr); if (which == CModelData::EWhichModel::ThermalHot) { diff --git a/Runtime/World/CActor.hpp b/Runtime/World/CActor.hpp index 3dc0d863d..4ddc866ca 100644 --- a/Runtime/World/CActor.hpp +++ b/Runtime/World/CActor.hpp @@ -48,35 +48,30 @@ protected: 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; - }; + 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; boo::ObjToken m_reflectionCube; diff --git a/Runtime/World/CActorModelParticles.cpp b/Runtime/World/CActorModelParticles.cpp index ceb99f7d5..d531b7670 100644 --- a/Runtime/World/CActorModelParticles.cpp +++ b/Runtime/World/CActorModelParticles.cpp @@ -25,7 +25,12 @@ static bool IsMediumOrLarge(CActor& act) { } CActorModelParticles::CItem::CItem(const CEntity& ent, CActorModelParticles& parent) -: x0_id(ent.GetUniqueId()), x4_areaId(ent.GetAreaIdAlways()), xdc_ashy(parent.x48_ashy), x128_parent(parent) { +: x0_id(ent.GetUniqueId()) +, x4_areaId(ent.GetAreaIdAlways()) +, xdc_ashy(parent.x48_ashy) +, x128_parent(parent) +, x12c_24_thermalCold(false) +, x12c_25_thermalHot(false) { x8_onFireGens.resize(8); } diff --git a/Runtime/World/CActorModelParticles.hpp b/Runtime/World/CActorModelParticles.hpp index df191ab5d..bb27fa909 100644 --- a/Runtime/World/CActorModelParticles.hpp +++ b/Runtime/World/CActorModelParticles.hpp @@ -56,13 +56,8 @@ public: zeus::CVector3f xec_particleOffsetScale = zeus::skOne3f; zeus::CTransform xf8_iceXf; CActorModelParticles& x128_parent; - union { - struct { - bool x12c_24_thermalCold : 1; - bool x12c_25_thermalHot : 1; - }; - u16 _dummy = 0; - }; + bool x12c_24_thermalCold : 1; + bool x12c_25_thermalHot : 1; float x130_remTime = 10.f; mutable u8 x134_lockDeps = 0; bool UpdateOnFire(float dt, CActor* actor, CStateManager& mgr); diff --git a/Runtime/World/CActorParameters.hpp b/Runtime/World/CActorParameters.hpp index b7b395b43..8ab6be70f 100644 --- a/Runtime/World/CActorParameters.hpp +++ b/Runtime/World/CActorParameters.hpp @@ -18,15 +18,10 @@ class CActorParameters { 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; - }; + 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; diff --git a/Runtime/World/CAmbientAI.cpp b/Runtime/World/CAmbientAI.cpp index 4fc4ae2e9..462854a0b 100644 --- a/Runtime/World/CAmbientAI.cpp +++ b/Runtime/World/CAmbientAI.cpp @@ -19,7 +19,9 @@ CAmbientAI::CAmbientAI(TUniqueId uid, std::string_view name, const CEntityInfo& , x2d8_impactRange(impactRange) , x2dc_defaultAnim(GetModelData()->GetAnimationData()->GetDefaultAnimation()) , x2e0_alertAnim(alertAnim) -, x2e4_impactAnim(impactAnim) { +, x2e4_impactAnim(impactAnim) +, x2e8_24_dead(false) +, x2e8_25_animating(false) { GetModelData()->GetAnimationData()->EnableLooping(true); } diff --git a/Runtime/World/CAmbientAI.hpp b/Runtime/World/CAmbientAI.hpp index 8ba3dbb03..37c979955 100644 --- a/Runtime/World/CAmbientAI.hpp +++ b/Runtime/World/CAmbientAI.hpp @@ -26,14 +26,8 @@ class CAmbientAI : public CPhysicsActor { s32 x2dc_defaultAnim; s32 x2e0_alertAnim; s32 x2e4_impactAnim; - - union { - struct { - bool x2e8_24_dead : 1; - bool x2e8_25_animating : 1; - }; - u32 _dummy = 0; - }; + bool x2e8_24_dead : 1; + bool x2e8_25_animating : 1; public: CAmbientAI(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, diff --git a/Runtime/World/CDamageInfo.cpp b/Runtime/World/CDamageInfo.cpp index 9911afbc4..c657afa67 100644 --- a/Runtime/World/CDamageInfo.cpp +++ b/Runtime/World/CDamageInfo.cpp @@ -36,10 +36,12 @@ float CDamageInfo::GetDamage(const CDamageVulnerability& dVuln) const { float CDamageInfo::GetRadiusDamage(const CDamageVulnerability& dVuln) const { EVulnerability vuln = dVuln.GetVulnerability(x0_weaponMode, false); - if (vuln == EVulnerability::Deflect) + if (vuln == EVulnerability::Deflect) { return 0.f; - else if (vuln == EVulnerability::Weak) + } + if (vuln == EVulnerability::Weak) { return 2.f * xc_radiusDamage; + } return xc_radiusDamage; } diff --git a/Runtime/World/CDamageVulnerability.cpp b/Runtime/World/CDamageVulnerability.cpp index cb48efc37..44bc12a25 100644 --- a/Runtime/World/CDamageVulnerability.cpp +++ b/Runtime/World/CDamageVulnerability.cpp @@ -240,36 +240,44 @@ bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect) } EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const { - if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) + if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) { return EVulnerability::Deflect; + } - if (mode.IsInstantKill()) + if (mode.IsInstantKill()) { return EVulnerability::Normal; + } EVulnerability vuln = (&x0_power)[u32(mode.GetType())]; if (mode.IsCharged()) { - if (mode.GetType() < EWeaponType::Bomb) + if (mode.GetType() < EWeaponType::Bomb) { vuln = (&x3c_chargedPower)[u32(mode.GetType())]; - else + } else { vuln = EVulnerability::Normal; + } } if (mode.IsComboed()) { - if (mode.GetType() < EWeaponType::Bomb) + if (mode.GetType() < EWeaponType::Bomb) { vuln = (&x3c_chargedPower)[u32(mode.GetType())]; - else + } else { vuln = EVulnerability::Normal; + } } - if (ignoreDirect) + if (ignoreDirect) { return vuln; + } - if (vuln == EVulnerability::DirectWeak) + if (vuln == EVulnerability::DirectWeak) { return EVulnerability::Weak; - else if (vuln == EVulnerability::DirectNormal) + } + if (vuln == EVulnerability::DirectNormal) { return EVulnerability::Normal; - else if (vuln == EVulnerability::DirectImmune) + } + if (vuln == EVulnerability::DirectImmune) { return EVulnerability::Immune; + } return vuln; } diff --git a/Runtime/World/CEntity.cpp b/Runtime/World/CEntity.cpp index 850b3ec5e..432dcc19c 100644 --- a/Runtime/World/CEntity.cpp +++ b/Runtime/World/CEntity.cpp @@ -10,10 +10,11 @@ CEntity::CEntity(TUniqueId uniqueId, const CEntityInfo& info, bool active, std:: , x8_uid(uniqueId) , xc_editorId(info.GetEditorId()) , x10_name(name) -, x20_conns(info.GetConnectionList()) { - x30_24_active = active; - x30_27_inUse = x4_areaId != kInvalidAreaId; -} +, x20_conns(info.GetConnectionList()) +, x30_24_active(active) +, x30_25_inGraveyard(false) +, x30_26_scriptingBlocked(false) +, x30_27_inUse(x4_areaId != kInvalidAreaId) {} void CEntity::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { switch (msg) { @@ -44,8 +45,10 @@ void CEntity::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateM } void CEntity::SendScriptMsgs(EScriptObjectState state, CStateManager& stateMgr, EScriptObjectMessage skipMsg) { - for (const SConnection& conn : x20_conns) - if (conn.x0_state == state && conn.x4_msg != 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 fd8dd406a..debd13f68 100644 --- a/Runtime/World/CEntity.hpp +++ b/Runtime/World/CEntity.hpp @@ -21,16 +21,10 @@ protected: 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; - }; + bool x30_24_active : 1; + bool x30_25_inGraveyard : 1; + bool x30_26_scriptingBlocked : 1; + bool x30_27_inUse : 1; public: static const std::vector NullConnectionList; diff --git a/Runtime/World/CEnvFxManager.cpp b/Runtime/World/CEnvFxManager.cpp index 0ec4437a2..a9bd5bc62 100644 --- a/Runtime/World/CEnvFxManager.cpp +++ b/Runtime/World/CEnvFxManager.cpp @@ -375,10 +375,10 @@ static zeus::CColor GetFlakeColor(const zeus::CMatrix4f& mvp, const CEnvFxShader 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(); +void CEnvFxManagerGrid::RenderSnowParticles(const zeus::CTransform& camXf) { + const zeus::CVector3f xVec = 0.2f * camXf.basis[0]; + const zeus::CVector3f zVec = 0.2f * camXf.basis[2]; + const 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(); @@ -396,26 +396,26 @@ void CEnvFxManagerGrid::RenderSnowParticles(const zeus::CTransform& camXf) const CGraphics::DrawInstances(0, 4, x1c_particles.size()); } -void CEnvFxManagerGrid::RenderRainParticles(const zeus::CTransform& camXf) const { +void CEnvFxManagerGrid::RenderRainParticles(const zeus::CTransform& camXf) { m_lineRenderer.Reset(); - float zOffset = 2.f * (1.f - std::fabs(camXf.basis[2].dot(zeus::skUp))) + 1.f; - zeus::CColor color0(1.f, 10.f / 15.f); + const float zOffset = 2.f * (1.f - std::fabs(camXf.basis[2].dot(zeus::skUp))) + 1.f; + const zeus::CColor color0(1.f, 10.f / 15.f); for (const auto& particle : x1c_particles) { - zeus::CVector3f pos0 = particle.toVec3f(); + const 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; + const float uvy0 = pos0.z() * 10.f + m_uvyOffset; + const float uvy1 = pos1.z() * 10.f + m_uvyOffset; m_lineRenderer.AddVertex(pos0, zeus::skWhite, 1.f, {0.f, uvy0}); m_lineRenderer.AddVertex(pos1, zeus::skClear, 1.f, {0.f, uvy1}); } m_lineRenderer.Render(g_Renderer->IsThermalVisorHotPass(), 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(); +void CEnvFxManagerGrid::RenderUnderwaterParticles(const zeus::CTransform& camXf) { + const zeus::CVector3f xVec = 0.5f * camXf.basis[0]; + const zeus::CVector3f zVec = 0.5f * camXf.basis[2]; + const 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(); @@ -434,7 +434,7 @@ void CEnvFxManagerGrid::RenderUnderwaterParticles(const zeus::CTransform& camXf) } void CEnvFxManagerGrid::Render(const zeus::CTransform& xf, const zeus::CTransform& invXf, const zeus::CTransform& camXf, - float fxDensity, EEnvFxType fxType, const CEnvFxManager& parent) const { + float fxDensity, EEnvFxType fxType, CEnvFxManager& parent) { 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(); @@ -469,7 +469,7 @@ void CEnvFxManagerGrid::Render(const zeus::CTransform& xf, const zeus::CTransfor } } -void CEnvFxManager::SetupSnowTevs(const CStateManager& mgr) const { +void CEnvFxManager::SetupSnowTevs(const CStateManager& mgr) { mgr.GetCameraManager()->GetCurrentCamera(mgr); if (mgr.GetCameraManager()->GetFluidCounter() != 0) { g_Renderer->SetWorldFog(ERglFogMode::PerspExp, 0.f, 35.f, zeus::skBlack); @@ -535,7 +535,7 @@ void CEnvFxManager::SetupUnderwaterTevs(const zeus::CTransform& invXf, const CSt // Swap: RGBR } -void CEnvFxManager::Render(const CStateManager& mgr) const { +void CEnvFxManager::Render(const CStateManager& mgr) { EEnvFxType fxType = mgr.GetWorld()->GetNeededEnvFx(); if (fxType != EEnvFxType::None) { if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed || @@ -562,7 +562,7 @@ void CEnvFxManager::Render(const CStateManager& mgr) const { break; } m_fogUniformBuf->load(&CGraphics::g_Fog, sizeof(CGraphics::g_Fog)); - for (const auto& grid : x50_grids) + for (auto& grid : x50_grids) grid.Render(xf, invXf, camXf, x30_fxDensity, fxType, *this); // Backface cull diff --git a/Runtime/World/CEnvFxManager.hpp b/Runtime/World/CEnvFxManager.hpp index 02bc1f4e3..d0bc82dfc 100644 --- a/Runtime/World/CEnvFxManager.hpp +++ b/Runtime/World/CEnvFxManager.hpp @@ -64,34 +64,34 @@ class CEnvFxManagerGrid { 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; + hecl::VertexBufferPool::Token m_instBuf; + hecl::UniformBufferPool::Token m_uniformBuf; + CLineRenderer m_lineRenderer; boo::ObjToken m_snowBinding; boo::ObjToken m_underwaterBinding; - mutable float m_uvyOffset = 0.f; + 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); + void RenderRainParticles(const zeus::CTransform& camXf); + void RenderUnderwaterParticles(const zeus::CTransform& camXf); public: CEnvFxManagerGrid(const zeus::CVector2i& position, const zeus::CVector2i& extent, 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; + EEnvFxType fxType, CEnvFxManager& parent); }; class CEnvFxManager { friend class CEnvFxManagerGrid; friend class CEnvFxShaders; - mutable hecl::VertexBufferPool m_instPool; - mutable hecl::UniformBufferPool m_uniformPool; - mutable CEnvFxShaders::Uniform m_uniformData; + hecl::VertexBufferPool m_instPool; + hecl::UniformBufferPool m_uniformPool; + CEnvFxShaders::Uniform m_uniformData; boo::ObjToken m_fogUniformBuf; zeus::CAABox x0_particleBounds = zeus::CAABox(-63.5f, 63.5f); @@ -133,7 +133,7 @@ class CEnvFxManager { 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 SetupSnowTevs(const CStateManager& mgr); void SetupRainTevs() const; void SetupUnderwaterTevs(const zeus::CTransform& invXf, const CStateManager& mgr) const; @@ -142,7 +142,7 @@ public: void AsyncLoadResources(CStateManager& mgr); void Update(float, CStateManager& mgr); - void Render(const CStateManager& mgr) const; + void Render(const CStateManager& mgr); void SetFxDensity(s32, float); void AreaLoaded(); void SetSplashRate(float f) { xb54_baseSplashRate = f; } diff --git a/Runtime/World/CFire.hpp b/Runtime/World/CFire.hpp index f2471d3b2..357b2b89e 100644 --- a/Runtime/World/CFire.hpp +++ b/Runtime/World/CFire.hpp @@ -35,10 +35,11 @@ public: void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&) override; void Think(float, CStateManager&) override; std::optional GetTouchBounds() const override { - if (GetActive()) + if (GetActive()) { return x128_; + } - return {}; + return std::nullopt; } void Touch(CActor&, CStateManager&) override; diff --git a/Runtime/World/CFishCloud.cpp b/Runtime/World/CFishCloud.cpp index 16f86f27d..81399b7bd 100644 --- a/Runtime/World/CFishCloud.cpp +++ b/Runtime/World/CFishCloud.cpp @@ -46,11 +46,16 @@ CFishCloud::CFishCloud(TUniqueId uid, bool active, std::string_view name, const , x16c_color(color) , x170_weaponKillRadius(weaponKillRadius) , x174_containmentRadius(containmentRadius) -, x234_deathSfx(deathSfx != 0xffffffff ? CSfxManager::TranslateSFXID(u16(deathSfx & 0xffff)) : u16(0xffff)) { - x250_28_killable = killable; - x250_29_repelFromThreats = repelFromThreats; +, x234_deathSfx(deathSfx != 0xffffffff ? CSfxManager::TranslateSFXID(u16(deathSfx & 0xffff)) : u16(0xffff)) +, x250_24_randomMovement(false) +, x250_25_worldSpace(true) // The result of a close_enough paradox (weird inlined test?) +, x250_26_enableWeaponRepelDamping(false) +, x250_27_validModel(false) +, x250_28_killable(killable) +, x250_29_repelFromThreats(repelFromThreats) +, x250_30_enablePlayerRepelDamping(false) +, x250_31_updateWithoutPartitions(false) { x108_modifierSources.reserve(10); - x250_25_worldSpace = true; // The result of a close_enough paradox (weird inlined test?) if (aRes.GetId().IsValid()) { x1b0_models.emplace_back(std::make_unique(aRes)); x1b0_models.emplace_back(std::make_unique(aRes)); @@ -58,14 +63,18 @@ CFishCloud::CFishCloud(TUniqueId uid, bool active, std::string_view name, const x1b0_models.emplace_back(std::make_unique(aRes)); x250_27_validModel = true; } - if (part1.IsValid()) + if (part1.IsValid()) { x1c4_particleDescs.push_back(g_SimplePool->GetObj({FOURCC('PART'), part1})); - if (part2.IsValid()) + } + if (part2.IsValid()) { x1c4_particleDescs.push_back(g_SimplePool->GetObj({FOURCC('PART'), part2})); - if (part3.IsValid()) + } + if (part3.IsValid()) { x1c4_particleDescs.push_back(g_SimplePool->GetObj({FOURCC('PART'), part3})); - if (part4.IsValid()) + } + if (part4.IsValid()) { x1c4_particleDescs.push_back(g_SimplePool->GetObj({FOURCC('PART'), part4})); + } for (const auto& p : x1c4_particleDescs) { x1f8_particleGens.emplace_back(std::make_unique(p)); x1f8_particleGens.back()->SetParticleEmission(false); @@ -74,7 +83,7 @@ CFishCloud::CFishCloud(TUniqueId uid, bool active, std::string_view name, const x21c_deathParticleCounts.push_back(partCount2); x21c_deathParticleCounts.push_back(partCount3); x21c_deathParticleCounts.push_back(partCount4); - zeus::CAABox aabb = GetBoundingBox(); + const zeus::CAABox aabb = GetBoundingBox(); x238_partitionPitch = (aabb.max - aabb.min) / 7.f; x244_ooPartitionPitch = 1.f / x238_partitionPitch; } @@ -82,17 +91,18 @@ CFishCloud::CFishCloud(TUniqueId uid, bool active, std::string_view name, const void CFishCloud::Accept(IVisitor& visitor) { visitor.Visit(this); } void CFishCloud::UpdateParticles(float dt) { - for (auto& p : x1f8_particleGens) + for (auto& p : x1f8_particleGens) { p->Update(dt); + } } void CFishCloud::UpdatePartitionList() { xf8_boidPartitionLists.clear(); xf8_boidPartitionLists.resize(xf8_boidPartitionLists.capacity()); - auto aabb = GetBoundingBox(); + const auto aabb = GetBoundingBox(); for (auto& b : xe8_boids) { - zeus::CVector3f idxs = (b.x0_pos - aabb.min) * x244_ooPartitionPitch; - int idx = int(idxs.x()) + int(idxs.y()) * 7 + int(idxs.z()) * 49; + const zeus::CVector3f idxs = (b.x0_pos - aabb.min) * x244_ooPartitionPitch; + const int idx = int(idxs.x()) + int(idxs.y()) * 7 + int(idxs.z()) * 49; if (idx >= 0 && idx < 343) { b.x1c_next = xf8_boidPartitionLists[idx]; xf8_boidPartitionLists[idx] = &b; @@ -101,39 +111,41 @@ void CFishCloud::UpdatePartitionList() { } bool CFishCloud::PointInBox(const zeus::CAABox& aabb, const zeus::CVector3f& point) const { - if (!x250_25_worldSpace) + if (!x250_25_worldSpace) { return aabb.pointInside(point); + } return GetUntransformedBoundingBox().pointInside(GetTransform().transposeRotate(point - GetTranslation())); } zeus::CPlane CFishCloud::FindClosestPlane(const zeus::CAABox& aabb, const zeus::CVector3f& point) const { if (!x250_25_worldSpace) { float minDist = FLT_MAX; - zeus::CAABox::EBoxFaceId minFace = zeus::CAABox::EBoxFaceId::YMin; + auto minFace = zeus::CAABox::EBoxFaceId::YMin; for (int i = 0; i < 6; ++i) { - auto tri = aabb.getTri(zeus::CAABox::EBoxFaceId(i), 0); - float dist = zeus::CPlane(tri.x10_verts[0], tri.x10_verts[2], tri.x10_verts[1]).pointToPlaneDist(point); + const auto tri = aabb.getTri(zeus::CAABox::EBoxFaceId(i), 0); + const float dist = zeus::CPlane(tri.x10_verts[0], tri.x10_verts[2], tri.x10_verts[1]).pointToPlaneDist(point); if (dist >= 0.f && dist < minDist) { minDist = dist; minFace = zeus::CAABox::EBoxFaceId(i); } } - auto tri = aabb.getTri(minFace, 0); + const auto tri = aabb.getTri(minFace, 0); return zeus::CPlane(tri.x10_verts[0], tri.x10_verts[2], tri.x10_verts[1]); } else { - auto unPoint = GetTransform().transposeRotate(point - GetTranslation()); - auto unAabb = GetUntransformedBoundingBox(); + const auto unPoint = GetTransform().transposeRotate(point - GetTranslation()); + const auto unAabb = GetUntransformedBoundingBox(); float minDist = FLT_MAX; - zeus::CAABox::EBoxFaceId minFace = zeus::CAABox::EBoxFaceId::YMin; + auto minFace = zeus::CAABox::EBoxFaceId::YMin; for (int i = 0; i < 6; ++i) { - auto tri = unAabb.getTri(zeus::CAABox::EBoxFaceId(i), 0); - float dist = zeus::CPlane(tri.x10_verts[0], tri.x10_verts[2], tri.x10_verts[1]).pointToPlaneDist(unPoint); + const auto tri = unAabb.getTri(zeus::CAABox::EBoxFaceId(i), 0); + const float dist = zeus::CPlane(tri.x10_verts[0], tri.x10_verts[2], tri.x10_verts[1]).pointToPlaneDist(unPoint); if (dist >= 0.f && dist < minDist) { minDist = dist; minFace = zeus::CAABox::EBoxFaceId(i); } } - auto tri = unAabb.getTri(minFace, 0); + + const auto tri = unAabb.getTri(minFace, 0); return zeus::CPlane(GetTransform() * tri.x10_verts[0], GetTransform() * tri.x10_verts[2], GetTransform() * tri.x10_verts[1]); @@ -141,23 +153,28 @@ zeus::CPlane CFishCloud::FindClosestPlane(const zeus::CAABox& aabb, const zeus:: } CFishCloud::CBoid* CFishCloud::GetListAt(const zeus::CVector3f& pos) { - zeus::CAABox aabb = GetBoundingBox(); - zeus::CVector3f ints = (pos - aabb.min) * x244_ooPartitionPitch; - int idx = int(ints.x()) + int(ints.y()) * 7 + int(ints.z()) * 49; - if (idx < 0 || idx >= 343) + const zeus::CAABox aabb = GetBoundingBox(); + const zeus::CVector3f ints = (pos - aabb.min) * x244_ooPartitionPitch; + const int idx = int(ints.x()) + int(ints.y()) * 7 + int(ints.z()) * 49; + + if (idx < 0 || idx >= 343) { return nullptr; + } + return xf8_boidPartitionLists[idx]; } void CFishCloud::BuildBoidNearList(const zeus::CVector3f& pos, float radius, rstl::reserved_vector& nearList) { - float radiusSq = radius * radius; + const float radiusSq = radius * radius; CBoid* b = GetListAt(pos); - while (b && nearList.size() < 25) { + + while (b != nullptr && nearList.size() < 25) { if (b->x20_active) { - float distSq = (b->GetTranslation() - pos).magSquared(); - if (distSq != 0.f && distSq < radiusSq) + const float distSq = (b->GetTranslation() - pos).magSquared(); + if (distSq != 0.f && distSq < radiusSq) { nearList.push_back(b); + } } b = b->x1c_next; } @@ -165,45 +182,54 @@ void CFishCloud::BuildBoidNearList(const zeus::CVector3f& pos, float radius, void CFishCloud::BuildBoidNearPartitionList(const zeus::CVector3f& pos, float radius, rstl::reserved_vector& nearList) { - float radiusSq = radius * radius; - zeus::CAABox aabb = GetBoundingBox(); - float x = std::max(radius * x244_ooPartitionPitch.x(), float(x238_partitionPitch.x())); - float y = std::max(radius * x244_ooPartitionPitch.y(), float(x238_partitionPitch.y())); - float z = std::max(radius * x244_ooPartitionPitch.z(), float(x238_partitionPitch.z())); - float nx = 0.01f - x; - float ny = 0.01f - y; - float nz = 0.01f - z; + const float radiusSq = radius * radius; + const zeus::CAABox aabb = GetBoundingBox(); + const float x = std::max(radius * x244_ooPartitionPitch.x(), float(x238_partitionPitch.x())); + const float y = std::max(radius * x244_ooPartitionPitch.y(), float(x238_partitionPitch.y())); + const float z = std::max(radius * x244_ooPartitionPitch.z(), float(x238_partitionPitch.z())); + const float nx = 0.01f - x; + const float ny = 0.01f - y; + const float nz = 0.01f - z; + for (float lnx = nx; lnx < x; lnx += x238_partitionPitch.x()) { - float cx = lnx + pos.x(); - if (cx < aabb.min.x()) + const float cx = lnx + pos.x(); + if (cx < aabb.min.x()) { continue; - if (cx >= aabb.max.x()) + } + if (cx >= aabb.max.x()) { break; + } for (float lny = ny; lny < y; lny += x238_partitionPitch.y()) { - float cy = lny + pos.y(); - if (cy < aabb.min.y()) + const float cy = lny + pos.y(); + if (cy < aabb.min.y()) { continue; - if (cy >= aabb.max.y()) + } + if (cy >= aabb.max.y()) { break; + } for (float lnz = nz; lnz < z; lnz += x238_partitionPitch.z()) { - float cz = lnz + pos.z(); - if (cz < aabb.min.z()) + const float cz = lnz + pos.z(); + if (cz < aabb.min.z()) { continue; - if (cz >= aabb.max.z()) + } + if (cz >= aabb.max.z()) { break; - zeus::CVector3f ints = (zeus::CVector3f(cx, cy, cz) - aabb.min) * x244_ooPartitionPitch; - int idx = int(ints.x()) + int(ints.y()) * 7 + int(ints.z()) * 49; - if (idx < 0) + } + const zeus::CVector3f ints = (zeus::CVector3f(cx, cy, cz) - aabb.min) * x244_ooPartitionPitch; + const int idx = int(ints.x()) + int(ints.y()) * 7 + int(ints.z()) * 49; + if (idx < 0) { continue; + } if (idx < 343) { CBoid* boid = xf8_boidPartitionLists[idx]; - while (boid) { + while (boid != nullptr) { if (boid->x20_active) { - float distSq = (boid->x0_pos - pos).magSquared(); + const float distSq = (boid->x0_pos - pos).magSquared(); if (distSq != 0.f && distSq < radiusSq) { nearList.push_back(boid); - if (nearList.size() == 25) + if (nearList.size() == 25) { return; + } } } boid = boid->x1c_next; @@ -215,7 +241,7 @@ void CFishCloud::BuildBoidNearPartitionList(const zeus::CVector3f& pos, float ra } void CFishCloud::PlaceBoid(CStateManager& mgr, CBoid& boid, const zeus::CAABox& aabb) const { - auto plane = FindClosestPlane(aabb, boid.x0_pos); + const auto plane = FindClosestPlane(aabb, boid.x0_pos); boid.x0_pos -= plane.pointToPlaneDist(boid.x0_pos) * plane.normal() + 0.0001f * plane.normal(); boid.xc_vel.y() = mgr.GetActiveRandom()->Float() - 0.5f; boid.xc_vel.x() = mgr.GetActiveRandom()->Float() - 0.5f; @@ -228,7 +254,7 @@ void CFishCloud::PlaceBoid(CStateManager& mgr, CBoid& boid, const zeus::CAABox& } } else { if (!PointInBox(aabb, boid.x0_pos)) { - auto unAabb = GetUntransformedBoundingBox(); + const auto unAabb = GetUntransformedBoundingBox(); boid.x0_pos.z() = mgr.GetActiveRandom()->Float() * (unAabb.max.z() - unAabb.min.z()) + unAabb.min.z(); boid.x0_pos.y() = mgr.GetActiveRandom()->Float() * (unAabb.max.y() - unAabb.min.y()) + unAabb.min.y(); boid.x0_pos.x() = mgr.GetActiveRandom()->Float() * (unAabb.max.x() - unAabb.min.x()) + unAabb.min.x(); @@ -238,57 +264,75 @@ void CFishCloud::PlaceBoid(CStateManager& mgr, CBoid& boid, const zeus::CAABox& } void CFishCloud::ApplySeparation(CBoid& boid, const rstl::reserved_vector& nearList) const { - if (nearList.empty()) + if (nearList.empty()) { return; + } + float minDist = FLT_MAX; zeus::CVector3f pos; - for (CBoid* b : nearList) { - float dist = (boid.GetTranslation() - b->GetTranslation()).magSquared(); + for (const CBoid* b : nearList) { + const float dist = (boid.GetTranslation() - b->GetTranslation()).magSquared(); if (dist < minDist) { minDist = dist; pos = b->GetTranslation(); } } + ApplySeparation(boid, pos, x138_separationRadius, x144_separationMagnitude); } void CFishCloud::ApplySeparation(CBoid& boid, const zeus::CVector3f& separateFrom, float separationRadius, float separationMagnitude) const { - zeus::CVector3f delta = boid.GetTranslation() - separateFrom; - if (delta.canBeNormalized()) { - float deltaDistSq = delta.magSquared(); - float capDeltaDistSq = separationRadius * separationRadius; - if (deltaDistSq < capDeltaDistSq) - boid.xc_vel += (1.f - deltaDistSq / capDeltaDistSq) * delta.normalized() * separationMagnitude; + const zeus::CVector3f delta = boid.GetTranslation() - separateFrom; + if (!delta.canBeNormalized()) { + return; } + + const float deltaDistSq = delta.magSquared(); + const float capDeltaDistSq = separationRadius * separationRadius; + if (deltaDistSq >= capDeltaDistSq) { + return; + } + + boid.xc_vel += (1.f - deltaDistSq / capDeltaDistSq) * delta.normalized() * separationMagnitude; } void CFishCloud::ApplyCohesion(CBoid& boid, const rstl::reserved_vector& nearList) const { - if (nearList.empty()) + if (nearList.empty()) { return; + } + zeus::CVector3f avg; - for (CBoid* b : nearList) + for (const CBoid* b : nearList) { avg += b->GetTranslation(); + } + avg = avg / float(nearList.size()); ApplyCohesion(boid, avg, x138_separationRadius, x13c_cohesionMagnitude); } void CFishCloud::ApplyCohesion(CBoid& boid, const zeus::CVector3f& cohesionFrom, float cohesionRadius, float cohesionMagnitude) const { - zeus::CVector3f delta = cohesionFrom - boid.GetTranslation(); - if (delta.canBeNormalized()) { - float distSq = delta.magSquared(); - float capDistSq = cohesionRadius * cohesionRadius; - boid.xc_vel += ((distSq > capDistSq) ? 1.f : distSq / capDistSq) * delta.normalized() * cohesionMagnitude; + const zeus::CVector3f delta = cohesionFrom - boid.GetTranslation(); + if (!delta.canBeNormalized()) { + return; } + + const float distSq = delta.magSquared(); + const float capDistSq = cohesionRadius * cohesionRadius; + boid.xc_vel += ((distSq > capDistSq) ? 1.f : distSq / capDistSq) * delta.normalized() * cohesionMagnitude; } void CFishCloud::ApplyAlignment(CBoid& boid, const rstl::reserved_vector& nearList) const { - if (nearList.empty()) + if (nearList.empty()) { return; + } + zeus::CVector3f avg; - for (CBoid* b : nearList) + for (const CBoid* b : nearList) { avg += b->xc_vel; + } + avg = avg / float(nearList.size()); boid.xc_vel += zeus::CVector3f::getAngleDiff(boid.xc_vel, avg) / M_PIF * (avg * x140_alignmentWeight); @@ -296,12 +340,14 @@ void CFishCloud::ApplyAlignment(CBoid& boid, const rstl::reserved_vector capDistSq) ? 0.f : (1.f - distSq / capDistSq)) * delta.normalized() * attractionMagnitude; + const zeus::CVector3f delta = attractTo - boid.GetTranslation(); + if (!delta.canBeNormalized()) { + return; } + + const float distSq = delta.magSquared(); + const float capDistSq = attractionRadius * attractionRadius; + boid.xc_vel += ((distSq > capDistSq) ? 0.f : (1.f - distSq / capDistSq)) * delta.normalized() * attractionMagnitude; } void CFishCloud::ApplyRepulsion(CBoid& boid, const zeus::CVector3f& attractTo, @@ -311,74 +357,93 @@ void CFishCloud::ApplyRepulsion(CBoid& boid, const zeus::CVector3f& attractTo, void CFishCloud::ApplySwirl(CBoid& boid, const zeus::CVector3f& swirlPoint, bool clockwise, float magnitude, float radius) const { - zeus::CVector3f delta = boid.x0_pos - swirlPoint; - float deltaMag = delta.magnitude(); + const zeus::CVector3f delta = boid.x0_pos - swirlPoint; + const float deltaMag = delta.magnitude(); + zeus::CVector3f alignVec; - if (clockwise) + if (clockwise) { alignVec = delta.normalized().cross(zeus::skUp); - else + } else { alignVec = zeus::skUp.cross(delta / deltaMag); - float weight = deltaMag > radius ? 0.f : 1.f - deltaMag / radius; + } + + const float weight = deltaMag > radius ? 0.f : 1.f - deltaMag / radius; boid.xc_vel += zeus::CVector3f::getAngleDiff(boid.xc_vel, alignVec) / M_PIF * weight * (magnitude * alignVec); } void CFishCloud::ApplyContainment(CBoid& boid, const zeus::CAABox& aabb) const { - if (boid.xc_vel.canBeNormalized()) { - if (!PointInBox(aabb, boid.xc_vel.normalized() * x130_speed * x174_containmentRadius + boid.x0_pos)) { - ApplyAttraction(boid, aabb.center(), 100000.f, x158_containmentMagnitude); - } + if (!boid.xc_vel.canBeNormalized()) { + return; } + + if (PointInBox(aabb, boid.xc_vel.normalized() * x130_speed * x174_containmentRadius + boid.x0_pos)) { + return; + } + + ApplyAttraction(boid, aabb.center(), 100000.f, x158_containmentMagnitude); } void CFishCloud::ScatterBoid(CStateManager& mgr, CBoid& b) const { - float angle = (mgr.GetActiveRandom()->Float() - 0.5f) * M_PIF * x154_maxScatterAngle; - float cosAngle = std::cos(angle); - float sinAngle = std::sin(angle); + const float angle = (mgr.GetActiveRandom()->Float() - 0.5f) * M_PIF * x154_maxScatterAngle; + const float cosAngle = std::cos(angle); + const float sinAngle = std::sin(angle); b.xc_vel.x() += x150_scatterVel * (b.xc_vel.y() * sinAngle + b.xc_vel.x() * cosAngle); b.xc_vel.y() += x150_scatterVel * (b.xc_vel.y() * cosAngle + b.xc_vel.x() * sinAngle); } void CFishCloud::Think(float dt, CStateManager& mgr) { - if (!GetActive()) + if (!GetActive()) { return; + } + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); - auto occState = area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; + const auto occState = area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; if (occState == CGameArea::EOcclusionState::Visible) { x168_weaponRepelDamping = std::max(0.f, x168_weaponRepelDamping - x160_weaponRepelDampingSpeed * dt * 0.1f); - if (x250_26_enableWeaponRepelDamping) - x168_weaponRepelDamping = std::min(x160_weaponRepelDampingSpeed * dt + x168_weaponRepelDamping, - x148_weaponRepelMagnitude); + if (x250_26_enableWeaponRepelDamping) { + x168_weaponRepelDamping = + std::min(x160_weaponRepelDampingSpeed * dt + x168_weaponRepelDamping, x148_weaponRepelMagnitude); + } + x164_playerRepelDamping = std::max(0.f, x164_playerRepelDamping - x15c_playerRepelDampingSpeed * dt * 0.1f); - if (x250_30_enablePlayerRepelDamping) - x164_playerRepelDamping = std::min(x15c_playerRepelDampingSpeed * dt + x164_playerRepelDamping, - x14c_playerRepelMagnitude); + if (x250_30_enablePlayerRepelDamping) { + x164_playerRepelDamping = + std::min(x15c_playerRepelDampingSpeed * dt + x164_playerRepelDamping, x14c_playerRepelMagnitude); + } + x250_26_enableWeaponRepelDamping = false; x250_30_enablePlayerRepelDamping = false; ++x118_thinkCounter; + UpdateParticles(dt); UpdatePartitionList(); - zeus::CAABox aabb = GetBoundingBox(); + + const zeus::CAABox aabb = GetBoundingBox(); int idx = 0; for (auto& b : xe8_boids) { if (b.x20_active && (idx & x11c_updateMask) == (x118_thinkCounter & x11c_updateMask)) { rstl::reserved_vector nearList; - if (x250_31_updateWithoutPartitions) + if (x250_31_updateWithoutPartitions) { BuildBoidNearList(b.x0_pos, x138_separationRadius, nearList); - else + } else { BuildBoidNearPartitionList(b.x0_pos, x138_separationRadius, nearList); + } + for (int i = 0; i < 5; ++i) { switch (i) { case 1: ApplySeparation(b, nearList); break; case 2: - if (!x250_24_randomMovement || mgr.GetActiveRandom()->Float() > x12c_randomMovementTimer) + if (!x250_24_randomMovement || mgr.GetActiveRandom()->Float() > x12c_randomMovementTimer) { ApplyCohesion(b, nearList); + } break; case 3: - if (!x250_24_randomMovement || mgr.GetActiveRandom()->Float() > x12c_randomMovementTimer) + if (!x250_24_randomMovement || mgr.GetActiveRandom()->Float() > x12c_randomMovementTimer) { ApplyAlignment(b, nearList); + } break; case 4: ScatterBoid(mgr, b); @@ -386,12 +451,14 @@ void CFishCloud::Think(float dt, CStateManager& mgr) { default: break; } - if (b.xc_vel.magSquared() > 3.2f) + if (b.xc_vel.magSquared() > 3.2f) { break; + } } + if (!x250_24_randomMovement && b.xc_vel.magSquared() < 3.2f) { - for (auto& m : x108_modifierSources) { - if (TCastToPtr act = mgr.ObjectById(m.x0_source)) { + for (const auto& m : x108_modifierSources) { + if (const TCastToConstPtr act = mgr.ObjectById(m.x0_source)) { if (m.xd_isSwirl) { ApplySwirl(b, act->GetTranslation(), m.xc_isRepulsor, m.x8_priority, m.x4_radius); } else if (m.xc_isRepulsor) { @@ -411,28 +478,34 @@ void CFishCloud::Think(float dt, CStateManager& mgr) { } ++idx; } + for (auto& b : xe8_boids) { if (b.x20_active) { ApplyContainment(b, aabb); - float velMag = b.xc_vel.magnitude(); - if (!zeus::close_enough(velMag, 0.f)) + const float velMag = b.xc_vel.magnitude(); + if (!zeus::close_enough(velMag, 0.f)) { b.xc_vel = b.xc_vel / velMag; + } b.xc_vel.z() *= 0.99f; } } + if (x12c_randomMovementTimer > 0.f) { x12c_randomMovementTimer -= dt; } else { x12c_randomMovementTimer = 0.f; x250_24_randomMovement = false; } + for (auto& b : xe8_boids) { if (b.x20_active) { b.x0_pos += b.xc_vel * dt * x130_speed; - if (!PointInBox(aabb, b.x0_pos)) + if (!PointInBox(aabb, b.x0_pos)) { PlaceBoid(mgr, b, aabb); + } } } + if (x250_27_validModel) { for (auto& m : x1b0_models) { m->GetAnimationData()->SetPlaybackRate(1.f); @@ -450,8 +523,8 @@ void CFishCloud::AllocateSkinnedModels(CStateManager& mgr, CModelData::EWhichMod int idx = 0; for (auto& m : x1b0_models) { m->EnableLooping(true); - m->AdvanceAnimation( - m->GetAnimationData()->GetAnimTimeRemaining("Whole Body"sv) * 0.25f * idx, mgr, x4_areaId, true); + m->AdvanceAnimation(m->GetAnimationData()->GetAnimTimeRemaining("Whole Body"sv) * 0.25f * float(idx), mgr, + x4_areaId, true); ++idx; } x230_whichModel = which; @@ -462,10 +535,10 @@ void CFishCloud::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CSt switch (msg) { case EScriptObjectMessage::Registered: { xe8_boids.reserve(x134_numBoids); - zeus::CAABox aabb = GetUntransformedBoundingBox(); - zeus::CVector3f extent = aabb.max - aabb.min; + const zeus::CAABox aabb = GetUntransformedBoundingBox(); + const zeus::CVector3f extent = aabb.max - aabb.min; zeus::CVector3f randPoint; - for (int i = 0; i < x134_numBoids; ++i) { + for (u32 i = 0; i < x134_numBoids; ++i) { randPoint.z() = mgr.GetActiveRandom()->Float() * extent.z() + aabb.min.z(); randPoint.y() = mgr.GetActiveRandom()->Float() * extent.y() + aabb.min.y(); randPoint.x() = mgr.GetActiveRandom()->Float() * extent.x() + aabb.min.x(); @@ -476,8 +549,9 @@ void CFishCloud::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CSt 0.2f * std::pow(mgr.GetActiveRandom()->Float(), 7.f) + 0.9f); } CreatePartitionList(); - if (x250_27_validModel) + if (x250_27_validModel) { AllocateSkinnedModels(mgr, CModelData::EWhichModel::Normal); + } break; } default: @@ -496,26 +570,30 @@ void CFishCloud::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { } void CFishCloud::AddParticlesToRenderer() const { - for (const auto& p : x1f8_particleGens) + for (const auto& p : x1f8_particleGens) { g_Renderer->AddParticleGen(*p); + } } void CFishCloud::RenderBoid(int idx, const CBoid& boid, u32& drawMask, bool thermalHot, const CModelFlags& flags) const { - u32 modelIndex = idx & 0x3; + const u32 modelIndex = idx & 0x3; CModelData& mData = *x1b0_models[modelIndex]; CSkinnedModel& model = mData.PickAnimatedModel(CModelData::EWhichModel::Normal); - if (!model.GetModelInst()->TryLockTextures()) + if (!model.GetModelInst()->TryLockTextures()) { return; - u32 thisDrawMask = 1u << modelIndex; - if (drawMask & thisDrawMask) { + } + + const u32 thisDrawMask = 1u << modelIndex; + if ((drawMask & thisDrawMask) != 0) { drawMask &= ~thisDrawMask; mData.GetAnimationData()->BuildPose(); } + model.GetModelInst()->SetAmbientColor(zeus::skWhite); CGraphics::SetModelMatrix(zeus::lookAt(boid.x0_pos, boid.x0_pos + boid.xc_vel)); if (thermalHot) { - CModelFlags thermFlags(0, 0, 3, zeus::skWhite); + constexpr CModelFlags thermFlags(0, 0, 3, zeus::skWhite); mData.RenderThermal(zeus::skWhite, zeus::CColor(0.f, 0.25f), thermFlags); } else { mData.GetAnimationData()->Render(model, flags, std::nullopt, nullptr); @@ -523,24 +601,31 @@ void CFishCloud::RenderBoid(int idx, const CBoid& boid, u32& drawMask, } void CFishCloud::Render(CStateManager& mgr) { - if (!GetActive()) + if (!GetActive()) { return; - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CFishCloud::Render {} {} {}"), + } + + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CFishCloud::Render {} {} {}"), x8_uid, xc_editorId, x10_name).c_str(), zeus::skOrange); - bool thermalHot = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot; + + const bool thermalHot = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot; CModelFlags flags(0, 0, 3, zeus::skWhite); - if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) { flags = CModelFlags(5, 0, 3, x16c_color); - else + } else { flags = CModelFlags(1, 0, 3, x16c_color); + } + AddParticlesToRenderer(); + if (x250_27_validModel) { // Ambient white int idx = 0; u32 drawMask = 0xffffffff; for (const auto& b : xe8_boids) { - if (b.x20_active) + if (b.x20_active) { RenderBoid(idx, b, drawMask, thermalHot, flags); + } ++idx; } } else { @@ -590,35 +675,41 @@ void CFishCloud::KillBoid(CBoid& b) const { void CFishCloud::Touch(CActor& other, CStateManager& mgr) { CActor::Touch(other, mgr); - if (TCastToPtr weap = other) { + + if (const TCastToConstPtr weap = other) { if (!x250_26_enableWeaponRepelDamping && x250_29_repelFromThreats) { int idx = 0; for (auto& b : xe8_boids) { - if ((idx & 0x3) == (x118_thinkCounter & 0x3)) + if ((idx & 0x3) == (x118_thinkCounter & 0x3)) { ApplyRepulsion(b, weap->GetTranslation(), 8.f, x148_weaponRepelMagnitude - x168_weaponRepelDamping); + } ++idx; } } + x250_26_enableWeaponRepelDamping = true; + if (x250_28_killable) { - if (auto tb = weap->GetTouchBounds()) { + if (const auto tb = weap->GetTouchBounds()) { for (auto& b : xe8_boids) { - if (b.x20_active && - tb->intersects(zeus::CAABox(weap->GetTranslation() - x170_weaponKillRadius, - weap->GetTranslation() + x170_weaponKillRadius))) + if (b.x20_active && tb->intersects(zeus::CAABox(weap->GetTranslation() - x170_weaponKillRadius, + weap->GetTranslation() + x170_weaponKillRadius))) { KillBoid(b); + } } } } } + if (x250_29_repelFromThreats) { - if (TCastToPtr player = other) { - zeus::CVector3f playerPos = player->GetTranslation(); + if (const TCastToConstPtr player = other) { + const zeus::CVector3f playerPos = player->GetTranslation(); for (auto& b : xe8_boids) { zeus::CVector3f adjPlayerPos = playerPos; - float zDelta = b.x0_pos.z() - adjPlayerPos.z(); - if (zDelta > 0.f && zDelta < 2.3f) + const float zDelta = b.x0_pos.z() - adjPlayerPos.z(); + if (zDelta > 0.f && zDelta < 2.3f) { adjPlayerPos.z() = float(b.x0_pos.z()); + } adjPlayerPos.x() += mgr.GetActiveRandom()->Float() * 0.2f - 0.1f; adjPlayerPos.y() += mgr.GetActiveRandom()->Float() * 0.2f - 0.1f; ApplyRepulsion(b, adjPlayerPos, 8.f, x14c_playerRepelMagnitude - x164_playerRepelDamping); @@ -629,7 +720,7 @@ void CFishCloud::Touch(CActor& other, CStateManager& mgr) { } zeus::CAABox CFishCloud::GetUntransformedBoundingBox() const { - zeus::CVector3f extent = x120_scale * 0.75f; + const zeus::CVector3f extent = x120_scale * 0.75f; return zeus::CAABox(-extent, extent); } @@ -638,46 +729,62 @@ zeus::CAABox CFishCloud::GetBoundingBox() const { } void CFishCloud::RemoveRepulsor(TUniqueId sourceId) { - CModifierSource source(sourceId, true, false, 0.f, 0.f); - auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); - if (it != x108_modifierSources.end()) - x108_modifierSources.erase(it); + const CModifierSource source(sourceId, true, false, 0.f, 0.f); + const auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + + if (it == x108_modifierSources.end()) { + return; + } + + x108_modifierSources.erase(it); } void CFishCloud::RemoveAttractor(TUniqueId sourceId) { - CModifierSource source(sourceId, false, false, 0.f, 0.f); - auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); - if (it != x108_modifierSources.end()) - x108_modifierSources.erase(it); + const CModifierSource source(sourceId, false, false, 0.f, 0.f); + const auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + + if (it == x108_modifierSources.end()) { + return; + } + + x108_modifierSources.erase(it); } bool CFishCloud::AddRepulsor(TUniqueId sourceId, bool swirl, float radius, float priority) { - CModifierSource source(sourceId, true, swirl, radius, priority); - auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + const CModifierSource source(sourceId, true, swirl, radius, priority); + const auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + if (it != x108_modifierSources.end()) { it->x4_radius = radius; it->x8_priority = priority; return true; - } else if (x108_modifierSources.size() < x108_modifierSources.capacity()) { - x108_modifierSources.insert(std::lower_bound( - x108_modifierSources.begin(), x108_modifierSources.end(), source), source); + } + + if (x108_modifierSources.size() < x108_modifierSources.capacity()) { + x108_modifierSources.insert(std::lower_bound(x108_modifierSources.begin(), x108_modifierSources.end(), source), + source); return true; } + return false; } bool CFishCloud::AddAttractor(TUniqueId sourceId, bool swirl, float radius, float priority) { - CModifierSource source(sourceId, false, swirl, radius, priority); - auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + const CModifierSource source(sourceId, false, swirl, radius, priority); + const auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + if (it != x108_modifierSources.end()) { it->x4_radius = radius; it->x8_priority = priority; return true; - } else if (x108_modifierSources.size() < x108_modifierSources.capacity()) { - x108_modifierSources.insert(std::lower_bound( - x108_modifierSources.begin(), x108_modifierSources.end(), source), source); + } + + if (x108_modifierSources.size() < x108_modifierSources.capacity()) { + x108_modifierSources.insert(std::lower_bound(x108_modifierSources.begin(), x108_modifierSources.end(), source), + source); return true; } + return false; } diff --git a/Runtime/World/CFishCloud.hpp b/Runtime/World/CFishCloud.hpp index f6c13f3bf..5d8dcc42f 100644 --- a/Runtime/World/CFishCloud.hpp +++ b/Runtime/World/CFishCloud.hpp @@ -80,23 +80,18 @@ class CFishCloud : public CActor { rstl::reserved_vector, 4> x1c4_particleDescs; rstl::reserved_vector, 4> x1f8_particleGens; rstl::reserved_vector x21c_deathParticleCounts; - CModelData::EWhichModel x230_whichModel; + CModelData::EWhichModel x230_whichModel{}; u16 x234_deathSfx; zeus::CVector3f x238_partitionPitch; zeus::CVector3f x244_ooPartitionPitch; - union { - struct { - bool x250_24_randomMovement : 1; - bool x250_25_worldSpace : 1; - bool x250_26_enableWeaponRepelDamping : 1; - bool x250_27_validModel : 1; - bool x250_28_killable : 1; - bool x250_29_repelFromThreats : 1; - bool x250_30_enablePlayerRepelDamping : 1; - bool x250_31_updateWithoutPartitions : 1; - }; - u32 _dummy = 0; - }; + bool x250_24_randomMovement : 1; + bool x250_25_worldSpace : 1; + bool x250_26_enableWeaponRepelDamping : 1; + bool x250_27_validModel : 1; + bool x250_28_killable : 1; + bool x250_29_repelFromThreats : 1; + bool x250_30_enablePlayerRepelDamping : 1; + bool x250_31_updateWithoutPartitions : 1; void UpdateParticles(float dt); void UpdatePartitionList(); diff --git a/Runtime/World/CFluidPlane.cpp b/Runtime/World/CFluidPlane.cpp index aaf96d8ff..e9744ac43 100644 --- a/Runtime/World/CFluidPlane.cpp +++ b/Runtime/World/CFluidPlane.cpp @@ -83,8 +83,7 @@ void CFluidPlane::AddRipple(const CRipple& ripple, const CScriptWater& water, CS mgr.GetFluidPlaneManager()->RippleManager().AddRipple(ripple); } -void CFluidPlane::RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46], - const u8 (&flags)[9][9], int startYDiv, +void CFluidPlane::RenderStripWithRipples(float curY, const Heights& heights, const Flags& flags, int startYDiv, const CFluidPlaneRender::SPatchInfo& info, std::vector& vOut, std::vector& pvOut) { @@ -310,8 +309,7 @@ void CFluidPlane::RenderStripWithRipples(float curY, const CFluidPlaneRender::SH } } -void CFluidPlane::RenderPatch(const CFluidPlaneRender::SPatchInfo& info, - const CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9], +void CFluidPlane::RenderPatch(const CFluidPlaneRender::SPatchInfo& info, const Heights& heights, const Flags& flags, bool noRipples, bool flagIs1, std::vector& vOut, std::vector& pvOut) { if (noRipples) { diff --git a/Runtime/World/CFluidPlane.hpp b/Runtime/World/CFluidPlane.hpp index c5c70128e..73eb051d4 100644 --- a/Runtime/World/CFluidPlane.hpp +++ b/Runtime/World/CFluidPlane.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -84,10 +85,10 @@ public: struct SRippleInfo { const CRipple& x0_ripple; - int x4_fromX; - int x8_toX; - int xc_fromY; - int x10_toY; + int x4_fromX = 0; + int x8_toX = 0; + int xc_fromY = 0; + int x10_toY = 0; int x14_gfromX; int x18_gtoX; int x1c_gfromY; @@ -116,6 +117,10 @@ public: }; class CFluidPlane { +public: + using Flags = std::array, 9>; + using Heights = std::array, 46>; + protected: CAssetId x4_texPattern1Id; CAssetId x8_texPattern2Id; @@ -135,12 +140,12 @@ protected: 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, + virtual void RenderStripWithRipples(float curY, const Heights& heights, const Flags& flags, int startYDiv, + const CFluidPlaneRender::SPatchInfo& info, std::vector& vOut, std::vector& pvOut); - void RenderPatch(const CFluidPlaneRender::SPatchInfo& info, const CFluidPlaneRender::SHFieldSample (&heights)[46][46], - const u8 (&flags)[9][9], bool noRipples, bool flagIs1, std::vector& vOut, + void RenderPatch(const CFluidPlaneRender::SPatchInfo& info, const Heights& heights, const Flags& flags, + bool noRipples, bool flagIs1, std::vector& vOut, std::vector& pvOut); public: @@ -168,10 +173,10 @@ public: 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(); } + bool HasColorTexture() const { return x30_texColor.HasReference(); } const CTexture& GetTexturePattern1() const { return *x10_texPattern1; } - bool HasTexturePattern1() const { return x10_texPattern1.operator bool(); } + bool HasTexturePattern1() const { return x10_texPattern1.HasReference(); } const CTexture& GetTexturePattern2() const { return *x20_texPattern2; } - bool HasTexturePattern2() const { return x20_texPattern2.operator bool(); } + bool HasTexturePattern2() const { return x20_texPattern2.HasReference(); } }; } // namespace urde diff --git a/Runtime/World/CFluidPlaneCPU.cpp b/Runtime/World/CFluidPlaneCPU.cpp index f30ad5efc..c412bf1ea 100644 --- a/Runtime/World/CFluidPlaneCPU.cpp +++ b/Runtime/World/CFluidPlaneCPU.cpp @@ -110,14 +110,15 @@ void CFluidPlaneCPU::CalculateLightmapMatrix(const zeus::CTransform& areaXf, con } 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)); +static CFluidPlaneCPU::SineTable sGlobalSineWave{}; +static void InitializeSineWave() { + if (sSineWaveInitialized) { + return; + } + for (size_t i = 0; i < sGlobalSineWave.size(); ++i) { + sGlobalSineWave[i] = std::sin(2.f * M_PIF * (float(i) / 256.f)); + } sSineWaveInitialized = true; - return sGlobalSineWave; } #define kEnableWaterBumpMaps true @@ -128,11 +129,11 @@ CFluidPlaneShader::RenderSetupInfo CFluidPlaneCPU::RenderSetup(const CStateManag const CScriptWater* water) { CFluidPlaneShader::RenderSetupInfo out; - float uvT = mgr.GetFluidPlaneManager()->GetUVT(); - bool hasBumpMap = HasBumpMap() && kEnableWaterBumpMaps; + const float uvT = mgr.GetFluidPlaneManager()->GetUVT(); + const bool hasBumpMap = HasBumpMap() && kEnableWaterBumpMaps; bool doubleLightmapBlend = false; - bool hasEnvMap = mgr.GetCameraManager()->GetFluidCounter() == 0 && HasEnvMap(); - bool hasEnvBumpMap = HasEnvBumpMap(); + const bool hasEnvMap = mgr.GetCameraManager()->GetFluidCounter() == 0 && HasEnvMap(); + const bool hasEnvBumpMap = HasEnvBumpMap(); InitializeSineWave(); CGraphics::SetModelMatrix(xf); @@ -165,8 +166,7 @@ CFluidPlaneShader::RenderSetupInfo CFluidPlaneCPU::RenderSetup(const CStateManag curTex++; } - float fluidUVs[3][2]; - x4c_uvMotion.CalculateFluidTextureOffset(uvT, fluidUVs); + const auto fluidUVs = x4c_uvMotion.CalculateFluidTextureOffset(uvT); out.texMtxs[0][0][0] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); out.texMtxs[0][1][1] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); @@ -304,8 +304,7 @@ bool CFluidPlaneCPU::PrepareRipple(const CRipple& ripple, const CFluidPlaneRende 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], +void CFluidPlaneCPU::ApplyTurbulence(float t, Heights& heights, const Flags& flags, const SineTable& sineWave, const CFluidPlaneRender::SPatchInfo& info, const zeus::CVector3f& areaCenter) const { if (!HasTurbulence()) { @@ -335,9 +334,8 @@ void CFluidPlaneCPU::ApplyTurbulence(float t, CFluidPlaneRender::SHFieldSample ( } } -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 { +void CFluidPlaneCPU::ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo, Heights& heights, Flags& flags, + const SineTable& sineWave, const CFluidPlaneRender::SPatchInfo& info) const { float lookupT = 256.f * (1.f - rippleInfo.x0_ripple.GetTime() * rippleInfo.x0_ripple.GetOOTimeFalloff() * rippleInfo.x0_ripple.GetOOTimeFalloff()) * @@ -410,8 +408,9 @@ void CFluidPlaneCPU::ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInf 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]; + heights[k][l].height += + rippleV * rippleInfo.x0_ripple.GetLookupAmplitude() * + sineWave[size_t(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff]; } else { heights[k][l].height += 0.f; } @@ -461,8 +460,9 @@ void CFluidPlaneCPU::ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInf 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]; + heights[k][l].height += + rippleV * rippleInfo.x0_ripple.GetLookupAmplitude() * + sineWave[size_t(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff]; } else { heights[k][l].height += 0.f; } @@ -486,8 +486,8 @@ void CFluidPlaneCPU::ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInf } 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 { + Heights& heights, Flags& flags, const SineTable& sineWave, + const CFluidPlaneRender::SPatchInfo& info) const { for (const CFluidPlaneRender::SRippleInfo& rippleInfo : rippleInfos) ApplyRipple(rippleInfo, heights, flags, sineWave, info); for (int i = 0; i < CFluidPlaneRender::numTilesInHField; ++i) @@ -500,7 +500,7 @@ void CFluidPlaneCPU::ApplyRipples(const rstl::reserved_vector& rippleManager, int fromX, int toX, - int fromY, int toY) const { +bool CFluidPlaneCPU::UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info, Heights& heights, Flags& flags, + const zeus::CVector3f& areaCenter, const std::optional& rippleManager, + int fromX, int toX, int fromY, int toY) const { rstl::reserved_vector rippleInfos; if (rippleManager) { for (const CRipple& ripple : rippleManager->GetRipples()) { @@ -731,10 +729,10 @@ bool CFluidPlaneCPU::UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo return false; } -/* Used to be part of locked cache - * These are too big for stack allocation */ -static CFluidPlaneRender::SHFieldSample lc_heights[46][46] = {}; -static u8 lc_flags[9][9] = {}; +// Used to be part of locked cache +// These are too big for stack allocation +static CFluidPlane::Heights lc_heights{}; +static CFluidPlane::Flags lc_flags{}; 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, diff --git a/Runtime/World/CFluidPlaneCPU.hpp b/Runtime/World/CFluidPlaneCPU.hpp index 6572ad38e..b3e53a76c 100644 --- a/Runtime/World/CFluidPlaneCPU.hpp +++ b/Runtime/World/CFluidPlaneCPU.hpp @@ -12,6 +12,9 @@ namespace urde { class CFluidUVMotion; class CFluidPlaneCPU : public CFluidPlane { +public: + using SineTable = std::array; + protected: class CTurbulence { float x0_speed; @@ -60,28 +63,22 @@ protected: u32 m_maxVertCount; bool m_tessellation = false; - bool m_cachedDoubleLightmapBlend; - bool m_cachedAdditive; + bool m_cachedDoubleLightmapBlend = false; + bool m_cachedAdditive = false; 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); - bool UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info, - CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], - const zeus::CVector3f& areaCenter, const std::optional& rippleManager, - int fromX, int toX, int fromY, int toY) const; + void ApplyTurbulence(float t, Heights& heights, const Flags& flags, const SineTable& sineWave, + const CFluidPlaneRender::SPatchInfo& info, const zeus::CVector3f& areaCenter) const; + void ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo, Heights& heights, Flags& flags, + const SineTable& sineWave, const CFluidPlaneRender::SPatchInfo& info) const; + void ApplyRipples(const rstl::reserved_vector& rippleInfos, Heights& heights, + Flags& flags, const SineTable& sineWave, const CFluidPlaneRender::SPatchInfo& info) const; + static void UpdatePatchNoNormals(Heights& heights, const Flags& flags, const CFluidPlaneRender::SPatchInfo& info); + static void UpdatePatchWithNormals(Heights& heights, const Flags& flags, const CFluidPlaneRender::SPatchInfo& info); + bool UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info, Heights& heights, Flags& flags, + const zeus::CVector3f& areaCenter, const std::optional& rippleManager, int fromX, + int toX, int fromY, int toY) const; public: CFluidPlaneCPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap, @@ -106,13 +103,13 @@ public: 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(); } + bool HasBumpMap() const { return xb0_bumpMap.HasReference(); } const CTexture& GetBumpMap() const { return *xb0_bumpMap; } - bool HasEnvMap() const { return xc0_envMap.operator bool(); } + bool HasEnvMap() const { return xc0_envMap.HasReference(); } const CTexture& GetEnvMap() const { return *xc0_envMap; } - bool HasEnvBumpMap() const { return xd0_envBumpMap.operator bool(); } + bool HasEnvBumpMap() const { return xd0_envBumpMap.HasReference(); } const CTexture& GetEnvBumpMap() const { return *xd0_envBumpMap; } - bool HasLightMap() const { return xe0_lightmap.operator bool(); } + bool HasLightMap() const { return xe0_lightmap.HasReference(); } const CTexture& GetLightMap() const { return *xe0_lightmap; } const zeus::CVector3f& GetBumpLightDir() const { return xf0_bumpLightDir; } float GetTileSize() const { return x100_tileSize; } diff --git a/Runtime/World/CFluidPlaneDoor.cpp b/Runtime/World/CFluidPlaneDoor.cpp index 339d321bd..5cc804d00 100644 --- a/Runtime/World/CFluidPlaneDoor.cpp +++ b/Runtime/World/CFluidPlaneDoor.cpp @@ -18,11 +18,10 @@ CFluidPlaneShader::RenderSetupInfo CFluidPlaneDoor::RenderSetup(const CStateMana bool noNormals) { CFluidPlaneShader::RenderSetupInfo out; - float uvT = mgr.GetFluidPlaneManager()->GetUVT(); + const float uvT = mgr.GetFluidPlaneManager()->GetUVT(); CGraphics::SetModelMatrix(xf); - float fluidUVs[3][2]; - x4c_uvMotion.CalculateFluidTextureOffset(uvT, fluidUVs); + const auto fluidUVs = x4c_uvMotion.CalculateFluidTextureOffset(uvT); out.texMtxs[0][0][0] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); out.texMtxs[0][1][1] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); @@ -52,10 +51,10 @@ CFluidPlaneShader::RenderSetupInfo CFluidPlaneDoor::RenderSetup(const CStateMana return out; } -/* Used to be part of locked cache - * These are too big for stack allocation */ -static CFluidPlaneRender::SHFieldSample lc_heights[46][46] = {}; -static u8 lc_flags[9][9] = {}; +// Used to be part of locked cache +// These are too big for stack allocation +static CFluidPlane::Heights lc_heights{}; +static CFluidPlane::Flags lc_flags{}; void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, const zeus::CTransform& areaXf, bool noNormals, diff --git a/Runtime/World/CFluidPlaneGPU.cpp b/Runtime/World/CFluidPlaneGPU.cpp index e83d494a3..6495ab4d7 100644 --- a/Runtime/World/CFluidPlaneGPU.cpp +++ b/Runtime/World/CFluidPlaneGPU.cpp @@ -17,8 +17,7 @@ CFluidPlaneGPU::CFluidPlaneGPU(CAssetId texPattern1, CAssetId texPattern2, CAsse m_tessellation = true; } -void CFluidPlaneGPU::RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46], - const u8 (&flags)[9][9], int startYDiv, +void CFluidPlaneGPU::RenderStripWithRipples(float curY, const Heights& heights, const Flags& flags, int startYDiv, const CFluidPlaneRender::SPatchInfo& info, std::vector& vOut, std::vector& pvOut) { diff --git a/Runtime/World/CFluidPlaneGPU.hpp b/Runtime/World/CFluidPlaneGPU.hpp index 00dc59121..b735a1e09 100644 --- a/Runtime/World/CFluidPlaneGPU.hpp +++ b/Runtime/World/CFluidPlaneGPU.hpp @@ -17,9 +17,8 @@ public: float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend, float reflectionSize, float rippleIntensity, u32 maxVertCount); - void RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46], - const u8 (&flags)[9][9], int startYDiv, const CFluidPlaneRender::SPatchInfo& info, - std::vector& vOut, + void RenderStripWithRipples(float curY, const Heights& heights, const Flags& flags, int startYDiv, + const CFluidPlaneRender::SPatchInfo& info, std::vector& vOut, std::vector& pvOut) override; }; diff --git a/Runtime/World/CFluidPlaneManager.cpp b/Runtime/World/CFluidPlaneManager.cpp index 78f24bba0..48917c26f 100644 --- a/Runtime/World/CFluidPlaneManager.cpp +++ b/Runtime/World/CFluidPlaneManager.cpp @@ -79,53 +79,58 @@ void CFluidPlaneManager::CreateSplash(TUniqueId splasher, CStateManager& mgr, co } static bool g_RippleMapSetup = false; -u8 CFluidPlaneManager::RippleValues[64][64] = {}; -u8 CFluidPlaneManager::RippleMins[64] = {}; -u8 CFluidPlaneManager::RippleMaxs[64] = {}; +std::array, 64> CFluidPlaneManager::RippleValues{}; +std::array CFluidPlaneManager::RippleMins{}; +std::array CFluidPlaneManager::RippleMaxs{}; boo::ObjToken CFluidPlaneManager::RippleMapTex; void CFluidPlaneManager::SetupRippleMap() { - if (g_RippleMapSetup) + if (g_RippleMapSetup) { return; + } g_RippleMapSetup = true; float curX = 0.f; - for (int i = 0; i < 64; ++i) { + for (size_t 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; + for (size_t j = 0; j < 64; ++j) { + const float rVal = 1.f - curY; float minX = curY; float maxX = 1.25f * (0.25f * rVal + 0.1f) + curY; - if (curY < 0.f) + if (curY < 0.f) { minX = 0.f; - else if (maxX > 1.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) + const float t = (curX - minX) / (maxX - minX); + if (t < 0.4f) { val = 2.5f * t; - else if (t > 0.75f) + } else if (t > 0.75f) { val = 4.f * (1.f - t); - else + } else { val = 1.f; + } } - auto valA = u8(std::max(int(255.f * val * rVal * rVal) - 1, 0)); + const auto valA = u8(std::max(int(255.f * val * rVal * rVal) - 1, 0)); RippleValues[i][j] = valA; - if (valA != 0 && curY < minY) + if (valA != 0 && curY < minY) { minY = curY; - if (valA != 0 && curY > maxY) + } + 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)); + const auto valB = u8(std::max(int(255.f * minY) - 1, 0)); + const auto valC = u8(std::min(int(255.f * maxY) + 1, 255)); RippleMins[i] = valB; RippleMaxs[i] = valC; curX += (1.f / 63.f); @@ -133,7 +138,7 @@ void CFluidPlaneManager::SetupRippleMap() { CGraphics::CommitResources([](boo::IGraphicsDataFactory::Context& ctx) { RippleMapTex = ctx.newStaticTexture(64, 64, 1, boo::TextureFormat::I8, boo::TextureClampMode::ClampToBlack, - RippleValues, 64 * 64); + RippleValues.data(), 64 * 64); return true; } BooTrace); } diff --git a/Runtime/World/CFluidPlaneManager.hpp b/Runtime/World/CFluidPlaneManager.hpp index 62bb95d9c..e492a9480 100644 --- a/Runtime/World/CFluidPlaneManager.hpp +++ b/Runtime/World/CFluidPlaneManager.hpp @@ -44,9 +44,9 @@ class CFluidPlaneManager { static void SetupRippleMap(); public: - static u8 RippleValues[64][64]; - static u8 RippleMins[64]; - static u8 RippleMaxs[64]; + static std::array, 64> RippleValues; + static std::array RippleMins; + static std::array RippleMaxs; static boo::ObjToken RippleMapTex; CFluidPlaneManager(); diff --git a/Runtime/World/CFluidUVMotion.cpp b/Runtime/World/CFluidUVMotion.cpp index 81c2cdb0a..2018038ec 100644 --- a/Runtime/World/CFluidUVMotion.cpp +++ b/Runtime/World/CFluidUVMotion.cpp @@ -6,15 +6,11 @@ namespace urde { -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; -} +CFluidUVMotion::CFluidUVMotion(float timeToWrap, float orientation, const SFluidLayerMotion& colorLayer, + const SFluidLayerMotion& pattern1Layer, const SFluidLayerMotion& pattern2Layer) +: x0_fluidLayers{{colorLayer, pattern1Layer, pattern2Layer}} +, x4c_ooTimeToWrap(1.f / timeToWrap) +, x50_orientation(orientation) {} CFluidUVMotion::CFluidUVMotion(float timeToWrap, float orientation) : x4c_ooTimeToWrap(1.f / timeToWrap), x50_orientation(orientation) { @@ -25,15 +21,16 @@ CFluidUVMotion::CFluidUVMotion(float timeToWrap, float orientation) 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); +CFluidUVMotion::FluidOffsets CFluidUVMotion::CalculateFluidTextureOffset(float t) const { + FluidOffsets offsets; + const float totalYOffset = t * x4c_ooTimeToWrap * std::cos(x50_orientation); + const float totalXOffset = t * x4c_ooTimeToWrap * std::sin(x50_orientation); - for (u32 i = 0; i < x0_fluidLayers.size(); ++i) { + for (size_t i = 0; i < x0_fluidLayers.size(); ++i) { const SFluidLayerMotion& layer = x0_fluidLayers[i]; - float speedT = t * layer.x4_ooTimeToWrap; - float cycleT = speedT - std::floor(speedT); + const float speedT = t * layer.x4_ooTimeToWrap; + const float cycleT = speedT - std::floor(speedT); float localY; float localX; switch (layer.x0_motion) { @@ -42,7 +39,7 @@ void CFluidUVMotion::CalculateFluidTextureOffset(float t, float offsets[3][2]) c localY = 0.f; } break; case EFluidUVMotion::Circular: { - float angle = (M_PIF * 2) * cycleT; + const float angle = (M_PIF * 2) * cycleT; localY = layer.xc_magnitude * std::sin(angle); localX = layer.xc_magnitude * std::cos(angle); } break; @@ -55,11 +52,13 @@ void CFluidUVMotion::CalculateFluidTextureOffset(float t, float offsets[3][2]) c break; } - float x = localX * std::sin(layer.x8_orientation) + localY * std::cos(layer.x8_orientation) + totalXOffset; - float y = localY * std::sin(layer.x8_orientation) + localX * std::cos(layer.x8_orientation) + totalYOffset; + const float x = localX * std::sin(layer.x8_orientation) + localY * std::cos(layer.x8_orientation) + totalXOffset; + const float y = localY * std::sin(layer.x8_orientation) + localX * std::cos(layer.x8_orientation) + totalYOffset; offsets[i][0] = x - std::floor(x); offsets[i][1] = y - std::floor(y); } + + return offsets; } } // namespace urde diff --git a/Runtime/World/CFluidUVMotion.hpp b/Runtime/World/CFluidUVMotion.hpp index fd506bcfc..e8d1eb8dd 100644 --- a/Runtime/World/CFluidUVMotion.hpp +++ b/Runtime/World/CFluidUVMotion.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "Runtime/RetroTypes.hpp" #include "Runtime/rstl.hpp" @@ -38,6 +40,8 @@ private: float x50_orientation; public: + using FluidOffsets = std::array, 3>; + CFluidUVMotion(float timeToWrap, float orientation, const SFluidLayerMotion& colorLayer, const SFluidLayerMotion& pattern1Layer, const SFluidLayerMotion& pattern2Layer); CFluidUVMotion(float timeToWrap, float orientation); @@ -45,6 +49,8 @@ public: 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; + + // In game binaries this uses an out pointer instead of return by value. + FluidOffsets CalculateFluidTextureOffset(float t) const; }; } // namespace urde diff --git a/Runtime/World/CGameArea.cpp b/Runtime/World/CGameArea.cpp index 050adf9f7..4c8bbe12e 100644 --- a/Runtime/World/CGameArea.cpp +++ b/Runtime/World/CGameArea.cpp @@ -1,5 +1,7 @@ #include "Runtime/World/CGameArea.hpp" +#include + #include "Runtime/CGameState.hpp" #include "Runtime/CSimplePool.hpp" #include "Runtime/CStateManager.hpp" @@ -43,8 +45,10 @@ CAreaRenderOctTree::CAreaRenderOctTree(const u8* buf) : x0_buf(buf) { } } -static const u32 ChildCounts[] = {0, 2, 2, 4, 2, 4, 4, 8}; -u32 CAreaRenderOctTree::Node::GetChildCount() const { return ChildCounts[x2_flags]; } +u32 CAreaRenderOctTree::Node::GetChildCount() const { + static constexpr std::array ChildCounts{0, 2, 2, 4, 2, 4, 4, 8}; + return ChildCounts[x2_flags]; +} zeus::CAABox CAreaRenderOctTree::Node::GetNodeBounds(const zeus::CAABox& curAABB, int idx) const { zeus::CVector3f center = curAABB.center(); @@ -253,7 +257,7 @@ std::pair, s32> GetScriptingMemoryAlways(const IGameArea& CMemoryInStream r(data.get() + 4, 96 - 4); u32 version = r.readUint32Big(); if (!(version & 0x10000)) - Log.report(logvisor::Fatal, fmt("Attempted to load non-URDE MREA")); + Log.report(logvisor::Fatal, FMT_STRING("Attempted to load non-URDE MREA")); version &= ~0x10000; header.version = (version >= 12 && version <= 15) ? version : 0; @@ -1148,7 +1152,7 @@ SMREAHeader CGameArea::VerifyHeader() const { CMemoryInStream r(x110_mreaSecBufs[0].first.get() + 4, x110_mreaSecBufs[0].second - 4); u32 version = r.readUint32Big(); if (!(version & 0x10000)) - Log.report(logvisor::Fatal, fmt("Attempted to load non-URDE MREA")); + Log.report(logvisor::Fatal, FMT_STRING("Attempted to load non-URDE MREA")); version &= ~0x10000; header.version = (version >= 12 && version <= 15) ? version : 0; if (!header.version) diff --git a/Runtime/World/CGameArea.hpp b/Runtime/World/CGameArea.hpp index 31623d90b..b8571699c 100644 --- a/Runtime/World/CGameArea.hpp +++ b/Runtime/World/CGameArea.hpp @@ -229,18 +229,13 @@ public: // 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; - }; + 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; std::vector> x110c_layerPtrs; float x111c_thermalCurrent = 0.f; float x1120_thermalSpeed = 0.f; @@ -251,6 +246,15 @@ public: float x1134_weaponWorldLightingSpeed = 0.f; float x1138_weaponWorldLightingTarget = 1.f; u32 x113c_playerActorsLoading = 0; + + CPostConstructed() + : x1108_24_(false) + , x1108_25_modelsConstructed(false) + , x1108_26_(false) + , x1108_27_(false) + , x1108_28_occlusionPinged(false) + , x1108_29_pvsHasActors(false) + , x1108_30_(false) {} }; private: @@ -347,11 +351,8 @@ public: s32 GetDockCount() const { return xcc_docks.size(); } bool IsPostConstructed() const { return xf0_24_postConstructed; } - const CPostConstructed* GetPostConstructed() const { - if (!x12c_postConstructed) - return nullptr; - return x12c_postConstructed.get(); - } + CPostConstructed* GetPostConstructed() { return x12c_postConstructed.get(); } + const CPostConstructed* GetPostConstructed() const { return x12c_postConstructed.get(); } bool IsValidated() const { return xf0_28_validated; } diff --git a/Runtime/World/CKnockBackController.cpp b/Runtime/World/CKnockBackController.cpp index 9c56b6042..2ffa1ebc8 100644 --- a/Runtime/World/CKnockBackController.cpp +++ b/Runtime/World/CKnockBackController.cpp @@ -6,409 +6,418 @@ namespace urde { -static const CKnockBackController::KnockBackParms KnockBackParmsTable[3][19][4] = { - { - { +constexpr std::array, 19>, 3> KnockBackParmsTable{{ + {{ + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 1.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 2.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 2.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Shock, 4.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 4.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 0.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 4.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 2.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 2.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 5.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 5.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 8.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 4.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::ExplodeDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - }, - { - { + }}, + }}, + {{ + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 2.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 1.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::Shock, 2.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 2.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 2.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Shock, 4.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 4.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 0.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 4.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 4.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 2.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 2.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 5.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 5.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 8.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 8.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 4.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 4.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::Burn, 6.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::BurnDeath, 6.000000f, -1.000000f}, {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::Burn, 6.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::BurnDeath, 6.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::BurnDeath, 6.000000f, -1.000000f}, {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::Burn, 6.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Burn, 6.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::BurnDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::Burn, 6.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::LaggedBurnDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::LaggedBurnDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::PhazeOut, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - }, - { - { + }}, + }}, + {{ + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 2.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 1.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::Shock, 2.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 2.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 2.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Shock, 4.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 4.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Shock, 4.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 4.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 4.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::Shock, 4.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 2.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 2.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 2.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 2.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 4.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 4.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 2.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Freeze, 2.500000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::Burn, 6.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Burn, 6.000000f, -1.000000f}, {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::Burn, 6.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::Burn, 6.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::Burn, 6.000000f, -1.000000f}, {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::Burn, 6.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::Burn, 6.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::BurnDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::Burn, 6.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::None, EKnockBackAnimationFollowUp::None, 0.000000f, 0.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::LaggedBurnDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::LaggedBurnDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - { + }}, + {{ {EKnockBackAnimationState::Flinch, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::PhazeOut, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Hurled, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, {EKnockBackAnimationState::Fall, EKnockBackAnimationFollowUp::IceDeath, 0.000000f, -1.000000f}, - }, - }, -}; + }}, + }}, +}}; -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 < 5; ++i) { - x24_.push_back(std::make_pair(0.f, FLT_MAX)); - x80_availableStates.set(i); - } +constexpr std::array ImpulseDurationTable{0.1f, 0.3f}; + +CKnockBackController::CKnockBackController(EKnockBackVariant variant) +: x0_variant(variant) +, x81_24_autoResetImpulse(true) +, x81_25_enableFreeze(true) +, x81_26_enableShock(false) +, x81_27_enableBurn(true) +, x81_28_enableBurnDeath(true) +, x81_29_enableExplodeDeath(true) +, x81_30_enableLaggedBurnDeath(true) +, x81_31_(true) +, x82_24_(true) +, x82_25_inDeferredKnockBack(false) +, x82_26_locomotionDuringElectrocution(false) { + x24_.resize(x24_.capacity(), std::make_pair(0.0f, FLT_MAX)); } -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()); + + if (parent.GetMaterialList().HasMaterial(EMaterialTypes::Immovable) || x60_impulseRemTime <= 0.f) { + return; } + + 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()); } bool CKnockBackController::TickDeferredTimer(float dt) { x68_deferRemTime -= dt; - if (x14_deferWeaponType != EWeaponType::None) + if (x14_deferWeaponType != EWeaponType::None) { return x68_deferRemTime <= 0.f; + } return false; } -EKnockBackCharacterState CKnockBackController::GetKnockBackCharacterState(CPatterned& parent) { - if (parent.GetBodyController()->IsFrozen()) +EKnockBackCharacterState CKnockBackController::GetKnockBackCharacterState(const CPatterned& parent) const { + if (parent.GetBodyController()->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) +void CKnockBackController::ValidateState(const CPatterned& parent) { + if (x4_activeParms.x0_animState < x18_minAnimState) { x4_activeParms.x0_animState = x18_minAnimState; - else if (x4_activeParms.x0_animState > x1c_maxAnimState) + } else if (x4_activeParms.x0_animState > x1c_maxAnimState) { x4_activeParms.x0_animState = x1c_maxAnimState; + } - EKnockBackAnimationState useState = EKnockBackAnimationState::Invalid; + auto useState = EKnockBackAnimationState::Invalid; if (parent.IsAlive()) { if (parent.GetBodyController()->HasBodyState(pas::EAnimationState::Hurled) && x80_availableStates.test(3) && x4_activeParms.x0_animState >= EKnockBackAnimationState::Hurled) { @@ -468,10 +477,12 @@ void CKnockBackController::ValidateState(CPatterned& parent) { } } -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; +float CKnockBackController::CalculateExtraHurlVelocity(CStateManager& mgr, float magnitude, float kbResistance) const { + if (magnitude <= kbResistance) { + return 0.f; + } + + return (1.1f - 0.2f * mgr.GetActiveRandom()->Float()) * 2.f * (magnitude - kbResistance); } void CKnockBackController::DoKnockBackAnimation(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, @@ -479,10 +490,11 @@ void CKnockBackController::DoKnockBackAnimation(const zeus::CVector3f& backVec, switch (x4_activeParms.x0_animState) { case EKnockBackAnimationState::Hurled: { float hurlVel = 5.f; - if (CHealthInfo* hInfo = parent.HealthInfo(mgr)) + 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::skUp; + const zeus::CVector3f backUpVec = backVec + backVec.magnitude() * zeus::skUp; if (backUpVec.canBeNormalized()) { parent.GetBodyController()->GetCommandMgr().DeliverCmd(CBCHurledCmd(-backVec, backUpVec.normalized() * hurlVel)); parent.SetMomentumWR({0.f, 0.f, parent.GetGravityConstant() * -parent.GetMass()}); @@ -498,7 +510,7 @@ void CKnockBackController::DoKnockBackAnimation(const zeus::CVector3f& backVec, break; } case EKnockBackAnimationState::Flinch: { - std::pair bestAnim = + const std::pair bestAnim = parent.GetBodyController()->GetPASDatabase().FindBestAnimation(CPASAnimParmData(23), *mgr.GetActiveRandom(), -1); if (bestAnim.first > 0.f) { parent.GetModelData()->GetAnimationData()->AddAdditiveAnimation(bestAnim.second, 1.f, false, true); @@ -512,25 +524,27 @@ void CKnockBackController::DoKnockBackAnimation(const zeus::CVector3f& backVec, } } -void CKnockBackController::ResetKnockBackImpulse(CPatterned& parent, const zeus::CVector3f& backVec, float magnitude) { +void CKnockBackController::ResetKnockBackImpulse(const 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) + if (x60_impulseRemTime <= 0.f) { x5c_impulseMag = magnitude; - else + } else { x5c_impulseMag += magnitude * (1.f - x60_impulseRemTime / ImpulseDurationTable[x20_impulseDurationIdx]); + } x60_impulseRemTime = ImpulseDurationTable[x20_impulseDurationIdx]; } } void CKnockBackController::DoDeferredKnockBack(CStateManager& mgr, CPatterned& parent) { if (x14_deferWeaponType == EWeaponType::Wave) { - x4_activeParms = KnockBackParmsTable[int(x0_variant)][int(EKnockBackWeaponType::WaveComboedDirect)] - [int(GetKnockBackCharacterState(parent))]; + x4_activeParms = KnockBackParmsTable[size_t(x0_variant)][size_t(EKnockBackWeaponType::WaveComboedDirect)] + [size_t(GetKnockBackCharacterState(parent))]; ValidateState(parent); - if (CHealthInfo* hInfo = parent.HealthInfo(mgr)) { - zeus::CVector3f backVec = -parent.GetTransform().basis[1]; + if (parent.HealthInfo(mgr) != nullptr) { + const zeus::CVector3f backVec = -parent.GetTransform().basis[1]; DoKnockBackAnimation(backVec, mgr, parent, 10.f); ResetKnockBackImpulse(parent, backVec, 2.f); x82_25_inDeferredKnockBack = true; @@ -545,37 +559,47 @@ void CKnockBackController::DoDeferredKnockBack(CStateManager& mgr, CPatterned& p } void CKnockBackController::sub80233d40(int i, float f1, float f2) { - if (i < 0 || i > 4) + 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; + + if (b) { + return; } + + 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)) + if (TickDeferredTimer(dt)) { DoDeferredKnockBack(mgr, parent); - if (x82_26_locomotionDuringElectrocution && parent.GetBodyController()->IsElectrocuting()) + } + if (x82_26_locomotionDuringElectrocution && parent.GetBodyController()->IsElectrocuting()) { parent.GetBodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Locomotion)); + } } EKnockBackWeaponType CKnockBackController::GetKnockBackWeaponType(const CDamageInfo& info, EWeaponType wType, EKnockBackType type) { int stacking = 0; - if (info.GetWeaponMode().IsCharged()) + if (info.GetWeaponMode().IsCharged()) { stacking = 1; - else if (info.GetWeaponMode().IsComboed()) + } else if (info.GetWeaponMode().IsComboed()) { stacking = 2; - if (wType > EWeaponType::Phazon) + } + + if (wType > EWeaponType::Phazon) { return EKnockBackWeaponType::Invalid; + } + switch (wType) { case EWeaponType::Power: return EKnockBackWeaponType(type != EKnockBackType::Direct ? stacking : stacking + 1); @@ -598,25 +622,34 @@ EKnockBackWeaponType CKnockBackController::GetKnockBackWeaponType(const CDamageI } } -void CKnockBackController::SelectDamageState(CPatterned& parent, const CDamageInfo& info, EWeaponType wType, +void CKnockBackController::SelectDamageState(const 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); + x4_activeParms = KnockBackParms(); + + const EKnockBackWeaponType weaponType = GetKnockBackWeaponType(info, wType, type); + if (weaponType == EKnockBackWeaponType::Invalid) { + return; } + + x4_activeParms = + KnockBackParmsTable[size_t(x0_variant)][size_t(weaponType)][size_t(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); + if (x82_25_inDeferredKnockBack) { + return; } + + 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 e3f4339ac..ec3b831e3 100644 --- a/Runtime/World/CKnockBackController.hpp +++ b/Runtime/World/CKnockBackController.hpp @@ -61,16 +61,16 @@ enum class EKnockBackAnimationFollowUp { class CKnockBackController { public: struct KnockBackParms { - EKnockBackAnimationState x0_animState; - EKnockBackAnimationFollowUp x4_animFollowup; - float x8_followupDuration; - float xc_intoFreezeDur; + EKnockBackAnimationState x0_animState = EKnockBackAnimationState::None; + EKnockBackAnimationFollowUp x4_animFollowup = EKnockBackAnimationFollowUp::None; + float x8_followupDuration = 0.f; + float xc_intoFreezeDur = 0.f; }; private: friend class CPatterned; EKnockBackVariant x0_variant; - KnockBackParms x4_activeParms; + KnockBackParms x4_activeParms{}; EWeaponType x14_deferWeaponType = EWeaponType::None; EKnockBackAnimationState x18_minAnimState = EKnockBackAnimationState::None; EKnockBackAnimationState x1c_maxAnimState = EKnockBackAnimationState::Fall; @@ -85,33 +85,28 @@ private: 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; - }; + std::bitset<5> x80_availableStates{0b11111}; + 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); + EKnockBackCharacterState GetKnockBackCharacterState(const CPatterned& parent) const; + void ValidateState(const CPatterned& parent); + float CalculateExtraHurlVelocity(CStateManager& mgr, float magnitude, float kbResistance) const; void DoKnockBackAnimation(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, float magnitude); - void ResetKnockBackImpulse(CPatterned& parent, const zeus::CVector3f& backVec, float magnitude); + void ResetKnockBackImpulse(const 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); + void SelectDamageState(const CPatterned& parent, const CDamageInfo& info, EWeaponType wType, EKnockBackType type); public: explicit CKnockBackController(EKnockBackVariant variant); diff --git a/Runtime/World/CMorphBall.cpp b/Runtime/World/CMorphBall.cpp index d00d29429..f693d900f 100644 --- a/Runtime/World/CMorphBall.cpp +++ b/Runtime/World/CMorphBall.cpp @@ -204,7 +204,7 @@ constexpr std::array BallSwooshColorsJaggy{{ }}; } // Anonymous namespace -const std::array CMorphBall::BallGlowColors{{ +constexpr std::array CMorphBall::BallGlowColors{{ {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, @@ -216,7 +216,7 @@ const std::array CMorphBall::BallGlowColors{{ {0xff, 0xff, 0xff}, }}; -const std::array CMorphBall::BallTransFlashColors{{ +constexpr std::array CMorphBall::BallTransFlashColors{{ {0xc2, 0x7e, 0x10}, {0x66, 0xc4, 0xff}, {0x60, 0xff, 0x90}, @@ -228,7 +228,7 @@ const std::array CMorphBall::BallTransFlashColors{{ {0xfb, 0x98, 0x21}, }}; -const std::array CMorphBall::BallAuxGlowColors{{ +constexpr std::array CMorphBall::BallAuxGlowColors{{ {0xc2, 0x7e, 0x10}, {0x66, 0xc4, 0xff}, {0x6c, 0xff, 0x61}, @@ -283,8 +283,9 @@ CMorphBall::CMorphBall(CPlayer& player, float radius) kSpiderBallCollisionRadius = GetBallRadius() + 0.2f; - for (int i = 0; i < 32; ++i) + for (size_t i = 0; i < x19e4_spiderElectricGens.capacity(); ++i) { x19e4_spiderElectricGens.emplace_back(std::make_unique(x19a0_spiderElectric, 0), false); + } LoadAnimationTokens("SamusBallANCS"); InitializeWakeEffects(); @@ -303,10 +304,9 @@ void CMorphBall::LoadAnimationTokens(std::string_view ancsName) { } void CMorphBall::InitializeWakeEffects() { - TToken nullParticle = + const TToken nullParticle = CToken(TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::make_unique())); - for (int i = 0; i < 8; ++i) - x1b84_wakeEffects.push_back(nullParticle); + x1b84_wakeEffects.resize(x1b84_wakeEffects.capacity(), nullParticle); x1b84_wakeEffects[2] = g_SimplePool->GetObj("DirtWake"); x1b84_wakeEffects[0] = g_SimplePool->GetObj("PhazonWake"); @@ -317,7 +317,7 @@ void CMorphBall::InitializeWakeEffects() { x1b84_wakeEffects[6] = g_SimplePool->GetObj("SandWake"); x1b84_wakeEffects[7] = g_SimplePool->GetObj("RainWake"); - x1bc8_wakeEffectGens.resize(8); + x1bc8_wakeEffectGens.resize(x1b84_wakeEffects.capacity()); 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]); @@ -1129,7 +1129,7 @@ void CMorphBall::EnterMorphBallState(CStateManager& mgr) { x1c20_tireFactor = 0.f; UpdateEffects(0.f, mgr); x187c_spiderBallState = ESpiderBallState::Inactive; - CAnimPlaybackParms parms(0, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(0, -1, 1.f, true); x58_ballModel->GetAnimationData()->SetAnimation(parms, false); x1e20_ballAnimIdx = 0; StopEffects(); @@ -1288,7 +1288,7 @@ void CMorphBall::ComputeBoostBallMovement(const CFinalInput& input, CStateManage if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) && x187c_spiderBallState != ESpiderBallState::Active) { if (x1e20_ballAnimIdx == 0) { - CAnimPlaybackParms parms(1, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(1, -1, 1.f, true); x58_ballModel->GetAnimationData()->SetAnimation(parms, false); x1e20_ballAnimIdx = 1; x1e24_boostSfxHandle = CSfxManager::SfxStart(SFXsam_ball_charge_lp, 1.f, 0.f, true, 0x7f, true, kInvalidAreaId); @@ -1298,7 +1298,7 @@ void CMorphBall::ComputeBoostBallMovement(const CFinalInput& input, CStateManage x1de8_boostChargeTime = g_tweakBall->GetBoostBallMaxChargeTime(); } else { if (x1e20_ballAnimIdx == 1) { - CAnimPlaybackParms parms(0, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(0, -1, 1.f, true); x58_ballModel->GetAnimationData()->SetAnimation(parms, false); x1e20_ballAnimIdx = 0; CSfxManager::RemoveEmitter(x1e24_boostSfxHandle); @@ -1399,7 +1399,7 @@ void CMorphBall::CancelBoosting() { x1de8_boostChargeTime = 0.f; x1df4_boostDrainTime = 0.f; if (x1e20_ballAnimIdx == 1) { - CAnimPlaybackParms parms(0, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(0, -1, 1.f, true); x58_ballModel->GetAnimationData()->SetAnimation(parms, false); x1e20_ballAnimIdx = 0; CSfxManager::SfxStop(x1e24_boostSfxHandle); @@ -1539,7 +1539,7 @@ void CMorphBall::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { } void CMorphBall::PointGenerator(void* ctx, const std::vector>& vn) { - reinterpret_cast(ctx)->GeneratePoints(vn); + static_cast(ctx)->GeneratePoints(vn); } void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) const { @@ -1674,8 +1674,8 @@ void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) co RenderMorphBallTransitionFlash(mgr); if (x0_player.GetFrozenState()) { - CModelFlags fflags(0, 0, 3, zeus::skWhite); - x70_frozenBallModel->Render(mgr, zeus::CTransform::Translate(ballToWorld.origin), lights, fflags); + constexpr CModelFlags modelFlags(0, 0, 3, zeus::skWhite); + x70_frozenBallModel->Render(mgr, zeus::CTransform::Translate(ballToWorld.origin), lights, modelFlags); } RenderIceBreakEffect(mgr); diff --git a/Runtime/World/CMorphBall.hpp b/Runtime/World/CMorphBall.hpp index bc52fcc17..4fceccab6 100644 --- a/Runtime/World/CMorphBall.hpp +++ b/Runtime/World/CMorphBall.hpp @@ -111,7 +111,7 @@ private: std::unique_ptr x19e0_effect_morphBallIceBreakGen; rstl::reserved_vector, bool>, 32> x19e4_spiderElectricGens; std::list x1b6c_activeSpiderElectricList; - CRandom16 x1b80_rand = {99}; + CRandom16 x1b80_rand{99}; rstl::reserved_vector, 8> x1b84_wakeEffects; rstl::reserved_vector, 8> x1bc8_wakeEffectGens; s32 x1c0c_wakeEffectIdx = -1; diff --git a/Runtime/World/CPathFindArea.cpp b/Runtime/World/CPathFindArea.cpp index 568dcbd85..ec3aae84b 100644 --- a/Runtime/World/CPathFindArea.cpp +++ b/Runtime/World/CPathFindArea.cpp @@ -123,7 +123,7 @@ CPFArea::CPFArea(std::unique_ptr&& buf, u32 len) { u32 version = r.readUint32Big(); if (version != 4) - Log.report(logvisor::Fatal, fmt("Unexpected PATH version {}, should be 4"), version); + Log.report(logvisor::Fatal, FMT_STRING("Unexpected PATH version {}, should be 4"), version); u32 numNodes = r.readUint32Big(); x140_nodes.reserve(numNodes); diff --git a/Runtime/World/CPathFindSearch.cpp b/Runtime/World/CPathFindSearch.cpp index a8de88774..3cdb5dab2 100644 --- a/Runtime/World/CPathFindSearch.cpp +++ b/Runtime/World/CPathFindSearch.cpp @@ -357,9 +357,10 @@ void CPathFindVisualizer::Draw(const CPathFindSearch& path) { m_spline.Render(); } -void CPathFindSearch::DebugDraw() const { - if (!m_viz) +void CPathFindSearch::DebugDraw() { + if (!m_viz) { m_viz.emplace(); + } m_viz->Draw(*this); } diff --git a/Runtime/World/CPathFindSearch.hpp b/Runtime/World/CPathFindSearch.hpp index ce5a37d6e..26eeef532 100644 --- a/Runtime/World/CPathFindSearch.hpp +++ b/Runtime/World/CPathFindSearch.hpp @@ -27,13 +27,13 @@ private: CPFArea* x0_area; rstl::reserved_vector x4_waypoints; u32 xc8_curWaypoint = 0; - EResult xcc_result; + 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; - mutable std::optional m_viz; + std::optional m_viz; 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; @@ -61,7 +61,7 @@ public: void SetCharacterRadius(float r) { xd4_chRadius = r; } void SetPadding(float padding) { xd8_padding = padding; } float RemainingPathDistance(const zeus::CVector3f& pos) const; - void DebugDraw() const; + void DebugDraw(); }; } // namespace urde diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index 1360075e3..3d68c7058 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -25,11 +25,12 @@ 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); +constexpr zeus::CColor CPatterned::skDamageColor(0.5f, 0.f, 0.f); +constexpr CMaterialList skPatternedGroundMaterialList(EMaterialTypes::Character, EMaterialTypes::Solid, + EMaterialTypes::Orbit, EMaterialTypes::GroundCollider, + EMaterialTypes::Target); +constexpr CMaterialList skPatternedFlyerMaterialList(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, @@ -41,12 +42,21 @@ CPatterned::CPatterned(ECharacter character, TUniqueId uid, std::string_view nam pInfo.xcc_bodyOrigin + 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, + moveType == EMovementType::Flyer ? skPatternedFlyerMaterialList : skPatternedGroundMaterialList, 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) +, x328_24_inPosition(false) +, x328_25_verticalMovement(moveType == EMovementType::Flyer) +, x328_26_solidCollision(false) +, x328_27_onGround(moveType != EMovementType::Flyer) +, x328_28_prevOnGround(true) +, x328_29_noPatternShagging(false) +, x328_30_lookAtDeathDir(true) +, x328_31_energyAttractor(false) +, x329_24_(true) , x34c_character(character) , x388_anim(pInfo.GetAnimationParameters().GetInitialAnimation()) , x3b4_speed(pInfo.x4_speed) @@ -61,18 +71,33 @@ CPatterned::CPatterned(ECharacter character, TUniqueId uid, std::string_view nam , x3dc_frozenXDamageThreshold(pInfo.xe0_frozenXDamage) , x3e0_xDamageDelay(pInfo.xe4_xDamageDelay) , x3fc_flavor(flavor) +, x400_24_hitByPlayerProjectile(false) +, x400_25_alive(true) +, x400_26_(false) +, x400_27_fadeToDeath(false) +, x400_28_pendingMassiveDeath(false) +, x400_29_pendingMassiveFrozenDeath(false) +, x400_30_patternShagged(false) +, x400_31_isFlyer(moveType == CPatterned::EMovementType::Flyer) +, x401_24_pathOverCount(0) +, x401_26_disableMove(false) +, x401_27_phazingOut(false) +, x401_28_burning(false) +, x401_29_laggedBurnDeath(false) +, x401_30_pendingDeath(false) +, x401_31_nextPendingShock(false) +, x402_24_pendingShock(false) +, x402_25_lostMassiveFrozenHP(false) +, x402_26_dieIf80PercFrozen(false) +, x402_27_noXrayModel(false) +, x402_28_isMakingBigStrike(false) +, x402_29_drawParticles(true) +, x402_30_updateThermalFrozenState(x402_31_thawed = actorParms.HasThermalHeat()) +, x402_31_thawed(false) +, x403_24_keepThermalVisorState(false) +, x403_25_enableStateMachine(true) // t +, x403_26_stateControlledMassiveDeath(true) , 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; @@ -472,10 +497,11 @@ void CPatterned::Death(CStateManager& mgr, const zeus::CVector3f& dir, EScriptOb 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) { + if (!x401_27_phazingOut && !x401_28_burning && hInfo != nullptr) { x460_knockBackController.KnockBack(backVec, mgr, *this, info, type, magnitude); - if (x450_bodyController->IsFrozen() && x460_knockBackController.GetActiveParms().xc_intoFreezeDur >= 0.f) + 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::skZero3f, zeus::CUnitVector3f(x34_transform.transposeRotate(backVec)), @@ -520,10 +546,11 @@ void CPatterned::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, c break; case EKnockBackAnimationFollowUp::IceDeath: Death(mgr, zeus::skZero3f, EScriptObjectState::DeathRattle); - if (x54c_iceDeathExplosionParticle) + if (x54c_iceDeathExplosionParticle) { MassiveFrozenDeath(mgr); - else if (x450_bodyController->IsFrozen()) + } else if (x450_bodyController->IsFrozen()) { x450_bodyController->FrozenBreakout(); + } break; default: break; @@ -583,7 +610,7 @@ bool CPatterned::NoPathNodes(CStateManager&, float arg) { return true; } -static const float skActorApproachDistance = 3.f; +constexpr float skActorApproachDistance = 3.f; bool CPatterned::PathShagged(CStateManager&, float arg) { if (CPathFindSearch* search = GetSearchPath()) { diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index 6cacca57b..16dcbbdd2 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -125,21 +125,15 @@ protected: 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_solidCollision : 1; - bool x328_27_onGround : 1; - bool x328_28_prevOnGround : 1; - bool x328_29_noPatternShagging : 1; - bool x328_30_lookAtDeathDir : 1; - bool x328_31_energyAttractor : 1; - bool x329_24_ : 1; - }; - u32 _dummy = 0; - }; - + bool x328_24_inPosition : 1; + bool x328_25_verticalMovement : 1; + bool x328_26_solidCollision : 1; + bool x328_27_onGround : 1; + bool x328_28_prevOnGround : 1; + bool x328_29_noPatternShagging : 1; + bool x328_30_lookAtDeathDir : 1; + bool x328_31_energyAttractor : 1; + bool x329_24_ : 1; EAnimState x32c_animState = EAnimState::NotReady; CStateMachineState x330_stateMachineState; ECharacter x34c_character; @@ -176,39 +170,32 @@ protected: 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; - uint32_t 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; - }; - + 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; + uint32_t 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 CDamageInfo x404_contactDamage; float x420_curDamageRemTime = 0.f; float x424_damageWaitTime; diff --git a/Runtime/World/CPlayer.cpp b/Runtime/World/CPlayer.cpp index 812085fe1..a8a374f64 100644 --- a/Runtime/World/CPlayer.cpp +++ b/Runtime/World/CPlayer.cpp @@ -221,17 +221,39 @@ CPlayer::CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox& stepDown) , x2d8_fpBounds(aabb) , x7d0_animRes(resId, 0, playerScale, 0, true) -, x7d8_beamScale(playerScale) { +, x7d8_beamScale(playerScale) +, x9c4_24_visorChangeRequested(false) +, x9c4_25_showCrosshairs(false) +, x9c4_26_(true) +, x9c4_27_canEnterMorphBall(true) +, x9c4_28_canLeaveMorphBall(true) +, x9c4_29_spiderBallControlXY(false) +, x9c4_30_controlDirOverride(false) +, x9c4_31_inWaterMovement(false) +, x9c5_24_(false) +, x9c5_25_splashUpdated(false) +, x9c5_26_(false) +, x9c5_27_camSubmerged(false) +, x9c5_28_slidingOnWall(false) +, x9c5_29_hitWall(false) +, x9c5_30_selectFluidBallSound(false) +, x9c5_31_stepCameraZBiasDirty(true) +, x9c6_24_extendTargetDistance(false) +, x9c6_25_interpolatingControlDir(false) +, x9c6_26_outOfBallLookAtHint(false) +, x9c6_27_aimingAtProjectile(false) +, x9c6_28_aligningGrappleSwingTurn(false) +, x9c6_29_disableInput(false) +, x9c6_30_newScanScanning(false) +, x9c6_31_overrideRadarRadius(false) +, x9c7_24_noDamageLoopSfx(false) +, x9c7_25_outOfBallLookAtHintActor(false) { x490_gun = std::make_unique(uid); x49c_gunHolsterRemTime = g_tweakPlayerGun->GetGunNotFiringTime(); x4a0_failsafeTest = std::make_unique(); x76c_cameraBob = std::make_unique(CPlayerCameraBob::ECameraBobType::One, CPlayerCameraBob::GetCameraBobExtent(), CPlayerCameraBob::GetCameraBobPeriod()); - x9c4_26_ = true; - x9c4_27_canEnterMorphBall = true; - x9c4_28_canLeaveMorphBall = true; - x9c5_31_stepCameraZBiasDirty = true; const CAssetId beamId = g_tweakPlayerRes->GetBeamBallTransitionModel(x7ec_beam); x7f0_ballTransitionBeamModel = std::make_unique(CStaticRes(beamId, playerScale)); x730_transitionModels.reserve(3); @@ -1550,7 +1572,7 @@ void CPlayer::RenderReflectedPlayer(CStateManager& mgr) { } CPhysicsActor::Render(mgr); if (HasTransitionBeamModel()) { - const CModelFlags flags(0, 0, 3, zeus::skWhite); + constexpr CModelFlags flags(0, 0, 3, zeus::skWhite); x7f0_ballTransitionBeamModel->Render(mgr, x7f4_gunWorldXf, nullptr, flags); } break; @@ -3926,7 +3948,7 @@ void CPlayer::SetOrbitState(EPlayerOrbitState state, CStateManager& mgr) { #ifndef NDEBUG if (x310_orbitTargetId != kInvalidUniqueId) { if (const CEntity* ent = mgr.GetObjectById(x310_orbitTargetId)) { - Log.report(logvisor::Info, fmt("Orbiting {} {}"), ent->GetEditorId(), ent->GetName()); + Log.report(logvisor::Info, FMT_STRING("Orbiting {} {}"), ent->GetEditorId(), ent->GetName()); } } #endif @@ -5837,7 +5859,7 @@ void CPlayer::SetHudDisable(float staticTimer, float outSpeed, float inSpeed) { } void CPlayer::SetIntoBallReadyAnimation(CStateManager& mgr) { - const CAnimPlaybackParms parms(2, -1, 1.f, true); + constexpr CAnimPlaybackParms parms(2, -1, 1.f, true); x64_modelData->GetAnimationData()->SetAnimation(parms, false); x64_modelData->GetAnimationData()->EnableLooping(false); x64_modelData->AdvanceAnimation(0.f, mgr, kInvalidAreaId, true); diff --git a/Runtime/World/CPlayer.hpp b/Runtime/World/CPlayer.hpp index bbe098bd5..b36616ea7 100644 --- a/Runtime/World/CPlayer.hpp +++ b/Runtime/World/CPlayer.hpp @@ -285,39 +285,32 @@ private: 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_inWaterMovement : 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; - }; - + 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_inWaterMovement : 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; float x9c8_eyeZBias = 0.f; float x9cc_stepCameraZBias = 0.f; u32 x9d0_bombJumpCount = 0; diff --git a/Runtime/World/CScriptActorKeyframe.cpp b/Runtime/World/CScriptActorKeyframe.cpp index ef5237923..4da536cfd 100644 --- a/Runtime/World/CScriptActorKeyframe.cpp +++ b/Runtime/World/CScriptActorKeyframe.cpp @@ -15,14 +15,13 @@ 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 != 0u) +, x44_27_timedLoop(fadeOut != 0u) +, x44_28_playing(false) +, x44_29_(false) {} void CScriptActorKeyframe::Accept(IVisitor& visitor) { visitor.Visit(this); } diff --git a/Runtime/World/CScriptActorKeyframe.hpp b/Runtime/World/CScriptActorKeyframe.hpp index 659ff4f36..ac6b78aed 100644 --- a/Runtime/World/CScriptActorKeyframe.hpp +++ b/Runtime/World/CScriptActorKeyframe.hpp @@ -12,17 +12,12 @@ private: 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; - }; + 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; public: CScriptActorKeyframe(TUniqueId uid, std::string_view name, const CEntityInfo& info, s32 animId, bool looping, diff --git a/Runtime/World/CScriptActorRotate.hpp b/Runtime/World/CScriptActorRotate.hpp index 8f1893679..89c03d50d 100644 --- a/Runtime/World/CScriptActorRotate.hpp +++ b/Runtime/World/CScriptActorRotate.hpp @@ -18,16 +18,10 @@ class CScriptActorRotate : public CEntity { 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; - }; + bool x58_24_updateRotation : 1; + bool x58_25_skipSpiderBallWaypoints : 1; + bool x58_26_updateActors : 1; + bool x58_27_updateOnCreation : 1; void UpdateActors(bool, CStateManager&); void UpdateSpiderBallWaypoints(CStateManager&); diff --git a/Runtime/World/CScriptAiJumpPoint.cpp b/Runtime/World/CScriptAiJumpPoint.cpp index 934e7371c..f49f08566 100644 --- a/Runtime/World/CScriptAiJumpPoint.cpp +++ b/Runtime/World/CScriptAiJumpPoint.cpp @@ -12,7 +12,8 @@ CScriptAiJumpPoint::CScriptAiJumpPoint(TUniqueId uid, std::string_view name, con : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic), CActorParameters::None(), kInvalidUniqueId) , xe8_apex(apex) -, xec_touchBounds(xf.origin, xf.origin) {} +, xec_touchBounds(xf.origin, xf.origin) +, x108_24(false) {} void CScriptAiJumpPoint::Accept(IVisitor& visitor) { visitor.Visit(this); } diff --git a/Runtime/World/CScriptAiJumpPoint.hpp b/Runtime/World/CScriptAiJumpPoint.hpp index 1f62259a8..74a8224fd 100644 --- a/Runtime/World/CScriptAiJumpPoint.hpp +++ b/Runtime/World/CScriptAiJumpPoint.hpp @@ -12,12 +12,7 @@ class CScriptAiJumpPoint : public CActor { private: float xe8_apex; zeus::CAABox xec_touchBounds; - union { - struct { - bool x108_24 : 1; - }; - u8 dummy = 0; - }; + bool x108_24 : 1; TUniqueId x10a_occupant = kInvalidUniqueId; TUniqueId x10c_currentWaypoint = kInvalidUniqueId; TUniqueId x10e_nextWaypoint = kInvalidUniqueId; diff --git a/Runtime/World/CScriptCameraHintTrigger.cpp b/Runtime/World/CScriptCameraHintTrigger.cpp index 0498fb39d..d52ed6b0f 100644 --- a/Runtime/World/CScriptCameraHintTrigger.cpp +++ b/Runtime/World/CScriptCameraHintTrigger.cpp @@ -14,10 +14,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_deactivateOnEnter = deactivateOnEnter; - x130_25_deactivateOnExit = deactivateOnExit; -} +, x124_scale(scale) +, x130_24_deactivateOnEnter(deactivateOnEnter) +, x130_25_deactivateOnExit(deactivateOnExit) +, x130_26_playerInside(false) +, x130_27_playerWasInside(false) {} void CScriptCameraHintTrigger::Accept(IVisitor& visitor) { visitor.Visit(this); } diff --git a/Runtime/World/CScriptCameraHintTrigger.hpp b/Runtime/World/CScriptCameraHintTrigger.hpp index 68497d278..b1a0067f2 100644 --- a/Runtime/World/CScriptCameraHintTrigger.hpp +++ b/Runtime/World/CScriptCameraHintTrigger.hpp @@ -12,15 +12,10 @@ namespace urde { class CScriptCameraHintTrigger : public CActor { zeus::COBBox xe8_obb; zeus::CVector3f x124_scale; - union { - struct { - bool x130_24_deactivateOnEnter : 1; - bool x130_25_deactivateOnExit : 1; - bool x130_26_playerInside : 1; - bool x130_27_playerWasInside : 1; - }; - u32 _dummy = 0; - }; + bool x130_24_deactivateOnEnter : 1; + bool x130_25_deactivateOnExit : 1; + bool x130_26_playerInside : 1; + bool x130_27_playerWasInside : 1; public: CScriptCameraHintTrigger(TUniqueId uid, bool active, std::string_view name, diff --git a/Runtime/World/CScriptCameraPitchVolume.cpp b/Runtime/World/CScriptCameraPitchVolume.cpp index 7bbbc76a9..ac19a0e77 100644 --- a/Runtime/World/CScriptCameraPitchVolume.cpp +++ b/Runtime/World/CScriptCameraPitchVolume.cpp @@ -22,7 +22,9 @@ CScriptCameraPitchVolume::CScriptCameraPitchVolume(TUniqueId uid, bool active, s , x124_upPitch(upPitch) , x128_downPitch(downPitch) , x12c_scale(scale * skScaleFactor) -, x138_maxInterpDistance(maxInterpDistance) {} +, x138_maxInterpDistance(maxInterpDistance) +, x13c_24_entered(false) +, x13c_25_occupied(false) {} void CScriptCameraPitchVolume::Accept(IVisitor& visitor) { visitor.Visit(this); } diff --git a/Runtime/World/CScriptCameraPitchVolume.hpp b/Runtime/World/CScriptCameraPitchVolume.hpp index 2b84d2816..b50dfa3ad 100644 --- a/Runtime/World/CScriptCameraPitchVolume.hpp +++ b/Runtime/World/CScriptCameraPitchVolume.hpp @@ -17,14 +17,8 @@ class CScriptCameraPitchVolume : public CActor { 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; - }; + bool x13c_24_entered : 1; + bool x13c_25_occupied : 1; public: CScriptCameraPitchVolume(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, diff --git a/Runtime/World/CScriptColorModulate.cpp b/Runtime/World/CScriptColorModulate.cpp index b194417ba..7c9226dd6 100644 --- a/Runtime/World/CScriptColorModulate.cpp +++ b/Runtime/World/CScriptColorModulate.cpp @@ -15,17 +15,16 @@ CScriptColorModulate::CScriptColorModulate(TUniqueId uid, std::string_view name, , 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; -} +, 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); } diff --git a/Runtime/World/CScriptColorModulate.hpp b/Runtime/World/CScriptColorModulate.hpp index bd60316f9..750fbb46a 100644 --- a/Runtime/World/CScriptColorModulate.hpp +++ b/Runtime/World/CScriptColorModulate.hpp @@ -30,20 +30,15 @@ private: 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; - }; + 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; public: CScriptColorModulate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CColor& colorA, diff --git a/Runtime/World/CScriptControllerAction.cpp b/Runtime/World/CScriptControllerAction.cpp index c1f5b4fa0..57c89676b 100644 --- a/Runtime/World/CScriptControllerAction.cpp +++ b/Runtime/World/CScriptControllerAction.cpp @@ -10,10 +10,12 @@ 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; -} +: CEntity(uid, info, active, name) +, x34_command(command) +, x38_mapScreenSubaction(w1) +, x3c_24_mapScreenResponse(mapScreenResponse) +, x3c_25_deactivateOnClose(deactivateOnClose) +, x3c_26_pressed(false) {} void CScriptControllerAction::Accept(IVisitor& visitor) { visitor.Visit(this); } diff --git a/Runtime/World/CScriptControllerAction.hpp b/Runtime/World/CScriptControllerAction.hpp index a18dd5838..e7e0c2486 100644 --- a/Runtime/World/CScriptControllerAction.hpp +++ b/Runtime/World/CScriptControllerAction.hpp @@ -11,14 +11,9 @@ 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; - }; + bool x3c_24_mapScreenResponse : 1; + bool x3c_25_deactivateOnClose : 1; + bool x3c_26_pressed : 1; public: CScriptControllerAction(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, diff --git a/Runtime/World/CScriptCoverPoint.cpp b/Runtime/World/CScriptCoverPoint.cpp index 44af6ac16..479a1318f 100644 --- a/Runtime/World/CScriptCoverPoint.cpp +++ b/Runtime/World/CScriptCoverPoint.cpp @@ -11,9 +11,14 @@ CScriptCoverPoint::CScriptCoverPoint(TUniqueId uid, std::string_view name, const 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; +, xe8_26_landHere((flags & 0x20) != 0u) +, xe8_27_wallHang((flags & 0x10) != 0u) +, xe8_28_stay((flags & 0x8) != 0u) +, xe8_29_((flags & 0x4) != 0u) +, xe8_30_attackDirection((flags & 0x2) != 0u) +, xf4_coverTime(coverTime) +, xf8_24_crouch(crouch) +, xf8_25_inUse(false) { 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); diff --git a/Runtime/World/CScriptCoverPoint.hpp b/Runtime/World/CScriptCoverPoint.hpp index 176636db9..2a62a12ca 100644 --- a/Runtime/World/CScriptCoverPoint.hpp +++ b/Runtime/World/CScriptCoverPoint.hpp @@ -4,31 +4,23 @@ #include #include "Runtime/GCNTypes.hpp" +#include "Runtime/Character/CharacterCommon.hpp" #include "Runtime/World/CActor.hpp" #include 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; - }; - + bool xe8_26_landHere : 1; + bool xe8_27_wallHang : 1; + bool xe8_28_stay : 1; + bool xe8_29_ : 1; + bool xe8_30_attackDirection : 1; 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; - }; + bool xf8_24_crouch : 1; + bool xf8_25_inUse : 1; TUniqueId xfa_occupant = kInvalidUniqueId; TUniqueId xfc_retreating = kInvalidUniqueId; std::optional x100_touchBounds; @@ -53,7 +45,9 @@ public: bool Blown(const zeus::CVector3f& pos) const; float GetSinSqVerticalAngle() const; float GetCosHorizontalAngle() const { return xec_cosHorizontalAngle; } - u32 GetAttackDirection() const { return xe8_flags; } + pas::ECoverDirection GetAttackDirection() const { + return xe8_30_attackDirection ? pas::ECoverDirection::Right : pas::ECoverDirection::Left; + } void Reserve(TUniqueId id) { xfa_occupant = id; } }; } // namespace urde diff --git a/Runtime/World/CScriptDamageableTrigger.cpp b/Runtime/World/CScriptDamageableTrigger.cpp index 3b0a6040b..71fd94ef8 100644 --- a/Runtime/World/CScriptDamageableTrigger.cpp +++ b/Runtime/World/CScriptDamageableTrigger.cpp @@ -36,8 +36,12 @@ CScriptDamageableTrigger::CScriptDamageableTrigger(TUniqueId uid, std::string_vi , 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; +, x254_fluidPlane(patternTex1, patternTex2, colorTex, 1.f, 2, EFluidType::NormalWater, 1.f, CFluidUVMotion(6.f, 0.f)) +, x300_24_notOccluded(false) +, x300_25_alphaOut(false) +, x300_26_outOfFrustum(false) +, x300_27_invulnerable(false) +, 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); diff --git a/Runtime/World/CScriptDamageableTrigger.hpp b/Runtime/World/CScriptDamageableTrigger.hpp index 590cff53b..378385231 100644 --- a/Runtime/World/CScriptDamageableTrigger.hpp +++ b/Runtime/World/CScriptDamageableTrigger.hpp @@ -29,17 +29,13 @@ private: zeus::CTransform x214_faceDirInv; zeus::CVector3f x244_faceTranslate; float x250_alphaTimer = 0.f; - mutable 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; - }; + CFluidPlaneDoor x254_fluidPlane; + 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; diff --git a/Runtime/World/CScriptDebris.cpp b/Runtime/World/CScriptDebris.cpp index 740c2bda1..7cdc46d56 100644 --- a/Runtime/World/CScriptDebris.cpp +++ b/Runtime/World/CScriptDebris.cpp @@ -27,9 +27,17 @@ CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntity , x278_ooDuration(1.f / x274_duration) , x27c_restitution(restitution) , x280_scaleType(scaleType) +, x281_24_randomAngImpulse(randomAngImpulse) +, x281_25_particle1GlobalTranslation(false) +, x281_26_deferDeleteTillParticle1Done(false) +, x281_27_particle2GlobalTranslation(false) +, x281_28_deferDeleteTillParticle2Done(false) +, x281_29_particle3Active(false) +, x281_30_debrisExtended(false) +, x281_31_dieOnProjectile(false) +, x282_24_noBounce(false) , 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) @@ -80,6 +88,15 @@ CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntity , x264_color(color) , x268_endsColor(endsColor) , x27c_restitution(restitution) +, x281_24_randomAngImpulse(false) +, x281_25_particle1GlobalTranslation(particle1GlobalTranslation) +, x281_26_deferDeleteTillParticle1Done(deferDeleteTillParticle1Done) +, x281_27_particle2GlobalTranslation(particle2GlobalTranslation) +, x281_28_deferDeleteTillParticle2Done(deferDeleteTillParticle2Done) +, x281_29_particle3Active(false) +, x281_30_debrisExtended(true) +, x281_31_dieOnProjectile(false) +, x282_24_noBounce(noBounce) , x288_linConeAngle(linConeAngle) , x28c_linMinMag(linMinMag) , x290_linMaxMag(linMaxMag) @@ -93,13 +110,6 @@ CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntity , 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; diff --git a/Runtime/World/CScriptDebris.hpp b/Runtime/World/CScriptDebris.hpp index bf7ca8cfa..da4824e1f 100644 --- a/Runtime/World/CScriptDebris.hpp +++ b/Runtime/World/CScriptDebris.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -27,20 +28,15 @@ private: 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; - }; + 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; @@ -55,7 +51,7 @@ private: zeus::CVector3f x2b0_scale; zeus::CVector3f x2bc_endScale; zeus::CVector3f x2c8_collisionNormal; - std::unique_ptr x2d4_particleGens[3]; /* x2d4, x2d8, x2dc */ + std::array, 3> x2d4_particleGens; /* x2d4, x2d8, x2dc */ TReservedAverage x2e0_speedAvg; public: diff --git a/Runtime/World/CScriptDock.cpp b/Runtime/World/CScriptDock.cpp index 9440242a9..28100ff44 100644 --- a/Runtime/World/CScriptDock.cpp +++ b/Runtime/World/CScriptDock.cpp @@ -12,25 +12,22 @@ #include "TCastTo.hpp" // Generated file, do not modify include path namespace urde { -CMaterialList MakeDockMaterialList() { - CMaterialList list; - list.Add(EMaterialTypes::Trigger); - list.Add(EMaterialTypes::Immovable); - list.Add(EMaterialTypes::AIBlock); - return list; -} + +constexpr auto skDockMaterialList = + CMaterialList{EMaterialTypes::Trigger, EMaterialTypes::Immovable, EMaterialTypes::AIBlock}; CScriptDock::CScriptDock(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& position, const zeus::CVector3f& extents, s32 dock, TAreaId area, bool active, s32 dockReferenceCount, bool loadConnected) -: CPhysicsActor(uid, active, name, info, zeus::CTransform(zeus::CMatrix3f(), position), - CModelData::CModelDataNull(), MakeDockMaterialList(), zeus::CAABox(-extents * 0.5f, extents * 0.5f), - SMoverData(1.f), CActorParameters::None(), 0.3f, 0.1f) +: CPhysicsActor(uid, active, name, info, zeus::CTransform(zeus::CMatrix3f(), position), CModelData::CModelDataNull(), + skDockMaterialList, zeus::CAABox(-extents * 0.5f, extents * 0.5f), 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_24_dockReferenced(false) +, x268_25_loadConnected(loadConnected) +, x268_26_areaPostConstructed(false) {} void CScriptDock::Accept(IVisitor& visitor) { visitor.Visit(this); } @@ -70,9 +67,10 @@ void CScriptDock::Think(float dt, CStateManager& mgr) { if (CObjectList* objs = mgr.GetWorld()->GetArea(aid)->GetAreaObjects()) { for (CEntity* ent : *objs) { - TCastToPtr dock(ent); - if (dock && dock->GetDockId() == otherDock) - dock->SetLoadConnected(mgr, true); + const TCastToPtr dock2(ent); + if (dock2 && dock2->GetDockId() == otherDock) { + dock2->SetLoadConnected(mgr, true); + } } } } diff --git a/Runtime/World/CScriptDock.hpp b/Runtime/World/CScriptDock.hpp index 42d7605e8..f34d71a73 100644 --- a/Runtime/World/CScriptDock.hpp +++ b/Runtime/World/CScriptDock.hpp @@ -15,14 +15,9 @@ class CScriptDock : public CPhysicsActor { 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; - }; + bool x268_24_dockReferenced : 1; + bool x268_25_loadConnected : 1; + bool x268_26_areaPostConstructed : 1; public: CScriptDock(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& position, diff --git a/Runtime/World/CScriptEffect.cpp b/Runtime/World/CScriptEffect.cpp index f62b93e18..85f568ee5 100644 --- a/Runtime/World/CScriptEffect.cpp +++ b/Runtime/World/CScriptEffect.cpp @@ -32,6 +32,17 @@ CScriptEffect::CScriptEffect(TUniqueId uid, std::string_view name, const CEntity : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(), CActorParameters::None().HotInThermal(hotInThermal), kInvalidUniqueId) , x10c_partId(partId) +, 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) , x114_rateInverseCamDist(rateInverseCamDist) , x118_rateInverseCamDistSq(rateInverseCamDist * rateInverseCamDist) , x11c_rateInverseCamDistRate(rateInverseCamDistRate) @@ -42,18 +53,6 @@ CScriptEffect::CScriptEffect(TUniqueId uid, std::string_view name, const CEntity , 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; - if (partId.IsValid()) { xf8_particleSystemToken = g_SimplePool->GetObj({FOURCC('PART'), partId}); x104_particleSystem = std::make_unique(xf8_particleSystemToken); @@ -154,12 +153,14 @@ void CScriptEffect::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt if (GetActive()) { std::vector playIds; for (const SConnection& conn : x20_conns) { - if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) { continue; + } - TUniqueId connId = mgr.GetIdForScript(conn.x8_objId); - if (connId != kInvalidUniqueId) - playIds.push_back(connId); + const TUniqueId scriptId = mgr.GetIdForScript(conn.x8_objId); + if (scriptId != kInvalidUniqueId) { + playIds.push_back(scriptId); + } } if (!playIds.empty()) { diff --git a/Runtime/World/CScriptEffect.hpp b/Runtime/World/CScriptEffect.hpp index 384b62130..261486754 100644 --- a/Runtime/World/CScriptEffect.hpp +++ b/Runtime/World/CScriptEffect.hpp @@ -19,22 +19,17 @@ class CScriptEffect : public CActor { 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; - }; + 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; diff --git a/Runtime/World/CScriptGenerator.hpp b/Runtime/World/CScriptGenerator.hpp index 3b98b7101..76b154b20 100644 --- a/Runtime/World/CScriptGenerator.hpp +++ b/Runtime/World/CScriptGenerator.hpp @@ -11,13 +11,8 @@ namespace urde { class CScriptGenerator : public CEntity { u32 x34_spawnCount; - union { - struct { - bool x38_24_noReuseFollowers : 1; - bool x38_25_noInheritTransform : 1; - }; - u8 dummy1 = 0; - }; + bool x38_24_noReuseFollowers : 1; + bool x38_25_noInheritTransform : 1; zeus::CVector3f x3c_offset; float x48_minScale; float x4c_maxScale; diff --git a/Runtime/World/CScriptGunTurret.cpp b/Runtime/World/CScriptGunTurret.cpp index 774a4319e..134ce33f8 100644 --- a/Runtime/World/CScriptGunTurret.cpp +++ b/Runtime/World/CScriptGunTurret.cpp @@ -158,7 +158,15 @@ CScriptGunTurret::CScriptGunTurret(TUniqueId uid, std::string_view name, ETurret , x428_targettingLightDesc(g_SimplePool->GetObj({SBIG('PART'), turretData.GetTargettingLightRes()})) , x434_frozenEffectDesc(g_SimplePool->GetObj({SBIG('PART'), turretData.GetFrozenEffectRes()})) , x440_chargingEffectDesc(g_SimplePool->GetObj({SBIG('PART'), turretData.GetChargingEffectRes()})) -, x44c_panningEffectDesc(g_SimplePool->GetObj({SBIG('PART'), turretData.GetPanningEffectRes()})) { +, x44c_panningEffectDesc(g_SimplePool->GetObj({SBIG('PART'), turretData.GetPanningEffectRes()})) +, x560_24_dead(false) +, x560_25_frozen(false) +, x560_26_firedWithSetBurst(false) +, x560_27_burstSet(false) +, x560_28_hasBeenActivated(false) +, x560_29_scriptedStart(false) +, x560_30_needsStopClankSound(true) +, x560_31_frenzyReverse(false) { if (turretData.GetVisorEffectRes().IsValid()) x458_visorEffectDesc = g_SimplePool->GetObj({SBIG('PART'), turretData.GetVisorEffectRes()}); x468_idleLight = std::make_unique(x410_idleLightDesc); @@ -171,14 +179,6 @@ CScriptGunTurret::CScriptGunTurret(TUniqueId uid, std::string_view name, ETurret x514_lastFrontVector = xf.frontVector(); x544_originalFrontVec = xf.frontVector(); x550_originalRightVec = xf.rightVector(); - x560_24_dead = false; - x560_25_frozen = false; - x560_26_firedWithSetBurst = false; - x560_27_burstSet = false; - x560_28_hasBeenActivated = false; - x560_29_scriptedStart = false; - x560_30_needsStopClankSound = true; - x560_31_frenzyReverse = false; if (comp == ETurretComponent::Base && HasModelData() && GetModelData()->HasAnimData()) GetModelData()->EnableLooping(true); @@ -394,7 +394,9 @@ void CScriptGunTurret::SetTurretState(ETurretState state, CStateManager& mgr) { } if (state != ETurretState::Invalid && x520_state != state) { - fmt::print(fmt("{} {} {} - {}\n"), GetUniqueId(), GetEditorId(), GetName(), StateNames[size_t(state)]); +#ifndef NDEBUG + fmt::print(FMT_STRING("{} {} {} - {}\n"), GetUniqueId(), GetEditorId(), GetName(), StateNames[size_t(state)]); +#endif } x520_state = state; diff --git a/Runtime/World/CScriptGunTurret.hpp b/Runtime/World/CScriptGunTurret.hpp index 779005a86..47935993a 100644 --- a/Runtime/World/CScriptGunTurret.hpp +++ b/Runtime/World/CScriptGunTurret.hpp @@ -170,19 +170,14 @@ private: zeus::CVector3f x544_originalFrontVec; zeus::CVector3f x550_originalRightVec; s32 x55c_additiveChargeAnim = -1; - union { - struct { - bool x560_24_dead : 1; - bool x560_25_frozen : 1; - bool x560_26_firedWithSetBurst : 1; - bool x560_27_burstSet : 1; - bool x560_28_hasBeenActivated : 1; - bool x560_29_scriptedStart : 1; - bool x560_30_needsStopClankSound : 1; - bool x560_31_frenzyReverse : 1; - }; - u32 _dummy = 0; - }; + bool x560_24_dead : 1; + bool x560_25_frozen : 1; + bool x560_26_firedWithSetBurst : 1; + bool x560_27_burstSet : 1; + bool x560_28_hasBeenActivated : 1; + bool x560_29_scriptedStart : 1; + bool x560_30_needsStopClankSound : 1; + bool x560_31_frenzyReverse : 1; private: void SetupCollisionManager(CStateManager&); diff --git a/Runtime/World/CScriptMazeNode.cpp b/Runtime/World/CScriptMazeNode.cpp index 2ed75e9b7..2fa0d173e 100644 --- a/Runtime/World/CScriptMazeNode.cpp +++ b/Runtime/World/CScriptMazeNode.cpp @@ -8,7 +8,7 @@ namespace urde { -atUint32 CScriptMazeNode::sMazeSeeds[300] = {0}; +std::array CScriptMazeNode::sMazeSeeds{}; CScriptMazeNode::CScriptMazeNode(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, s32 w1, s32 w2, s32 w3, @@ -20,18 +20,20 @@ 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) +, x13c_25_(false) +, x13c_26_(false) {} 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); + const u32 resSize = g_ResFactory->ResourceSize(*tag); + const std::unique_ptr buf = g_ResFactory->LoadResourceSync(*tag); CMemoryInStream in(buf.get(), resSize); - for (u32 i = 0; i < 300; ++i) - sMazeSeeds[i] = in.readUint32Big(); + for (auto& seed : sMazeSeeds) { + seed = in.readUint32Big(); + } } } // namespace urde diff --git a/Runtime/World/CScriptMazeNode.hpp b/Runtime/World/CScriptMazeNode.hpp index f9e147d5a..7ad096af6 100644 --- a/Runtime/World/CScriptMazeNode.hpp +++ b/Runtime/World/CScriptMazeNode.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include "Runtime/RetroTypes.hpp" @@ -9,7 +10,7 @@ namespace urde { class CScriptMazeNode : public CActor { - static u32 sMazeSeeds[300]; + static std::array sMazeSeeds; s32 xe8_; s32 xec_; s32 xf0_; @@ -24,14 +25,9 @@ class CScriptMazeNode : public CActor { 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; - }; + bool x13c_24_ : 1; + bool x13c_25_ : 1; + bool x13c_26_ : 1; public: CScriptMazeNode(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, s32, s32, s32, diff --git a/Runtime/World/CScriptMemoryRelay.hpp b/Runtime/World/CScriptMemoryRelay.hpp index 594b6da71..2f0b31c64 100644 --- a/Runtime/World/CScriptMemoryRelay.hpp +++ b/Runtime/World/CScriptMemoryRelay.hpp @@ -7,14 +7,9 @@ namespace urde { class CScriptMemoryRelay : public CEntity { - union { - struct { - bool x34_24_defaultActive; - bool x34_25_skipSendActive; - bool x34_26_ignoreMessages; - }; - u8 dummy = 0; - }; + bool x34_24_defaultActive; + bool x34_25_skipSendActive; + bool x34_26_ignoreMessages; public: CScriptMemoryRelay(TUniqueId, std::string_view name, const CEntityInfo&, bool, bool, bool); diff --git a/Runtime/World/CScriptPickup.hpp b/Runtime/World/CScriptPickup.hpp index 234d9fde2..ec4e5b0ba 100644 --- a/Runtime/World/CScriptPickup.hpp +++ b/Runtime/World/CScriptPickup.hpp @@ -15,7 +15,7 @@ class CScriptPickup : public CPhysicsActor { float x268_fadeInTime; float x26c_lifeTime; float x270_curTime = 0.f; - float x274_tractorTime; + float x274_tractorTime = 0.f; float x278_delayTimer; TLockedToken x27c_pickupParticleDesc; diff --git a/Runtime/World/CScriptPlatform.cpp b/Runtime/World/CScriptPlatform.cpp index 38c8eff84..4bab7cffa 100644 --- a/Runtime/World/CScriptPlatform.cpp +++ b/Runtime/World/CScriptPlatform.cpp @@ -1,5 +1,7 @@ #include "Runtime/World/CScriptPlatform.hpp" +#include + #include "Runtime/CStateManager.hpp" #include "Runtime/Collision/CCollidableOBBTreeGroup.hpp" #include "Runtime/Collision/CGameCollision.hpp" @@ -15,14 +17,8 @@ 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; -} +constexpr auto skPlatformMaterialList = + CMaterialList{EMaterialTypes::Solid, EMaterialTypes::Immovable, EMaterialTypes::Platform, EMaterialTypes::Occluder}; CScriptPlatform::CScriptPlatform(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, @@ -30,7 +26,7 @@ CScriptPlatform::CScriptPlatform(TUniqueId uid, std::string_view name, const CEn bool active, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, std::optional> dcln, bool rainSplashes, u32 maxRainSplashes, u32 rainGenRate) -: CPhysicsActor(uid, active, name, info, xf, std::move(mData), MakePlatformMaterialList(), aabb, SMoverData(15000.f), +: CPhysicsActor(uid, active, name, info, xf, std::move(mData), skPlatformMaterialList, aabb, SMoverData(15000.f), actParms, 0.3f, 0.1f) , x25c_currentSpeed(speed) , x28c_initialHealth(hInfo) @@ -52,37 +48,45 @@ CScriptPlatform::CScriptPlatform(TUniqueId uid, std::string_view name, const CEn CMaterialList(EMaterialTypes::Solid), CMaterialList(EMaterialTypes::NoStaticCollision, EMaterialTypes::NoPlatformCollision, EMaterialTypes::Platform))); xf8_24_movable = false; - if (HasModelData() && GetModelData()->HasAnimData()) + if (HasModelData() && GetModelData()->HasAnimData()) { GetModelData()->GetAnimationData()->EnableLooping(true); - if (x304_treeGroupContainer) + } + 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); + if (std::find(draggedSet.begin(), draggedSet.end(), actor->GetUniqueId().Value()) != draggedSet.end()) { + return; + } + + draggedSet.push_back(actor->GetUniqueId().Value()); + zeus::CTransform newXf = actor->GetTransform(); + newXf.origin += delta; + actor->SetTransform(newXf); + if (const 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)) + for (SRiders& rider : x328_slavesStatic) { + if (const 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)) { + if (const TCastToPtr act = mgr.ObjectById(it->x0_uid)) { DragSlave(mgr, draggedSet, act.GetPtr(), delta); ++it; - } else + } else { it = x338_slavesDynamic.erase(it); + } } } @@ -101,9 +105,9 @@ void CScriptPlatform::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, C } case EScriptObjectMessage::Next: { x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr); - if (x25a_targetWaypoint == kInvalidUniqueId) + if (x25a_targetWaypoint == kInvalidUniqueId) { mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop); - else if (TCastToPtr wp = mgr.ObjectById(x25a_targetWaypoint)) { + } else if (const TCastToPtr wp = mgr.ObjectById(x25a_targetWaypoint)) { x25c_currentSpeed = 0.f; Stop(); x270_dragDelta = wp->GetTranslation() - GetTranslation(); @@ -122,10 +126,11 @@ void CScriptPlatform::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, C } case EScriptObjectMessage::Start: { x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr); - if (x25a_targetWaypoint == kInvalidUniqueId) + if (x25a_targetWaypoint == kInvalidUniqueId) { mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop); - else if (TCastToPtr wp = mgr.ObjectById(x25a_targetWaypoint)) + } else if (const TCastToConstPtr wp = mgr.ObjectById(x25a_targetWaypoint)) { x25c_currentSpeed = wp->GetSpeed(); + } break; } case EScriptObjectMessage::Reset: { @@ -134,10 +139,11 @@ void CScriptPlatform::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, C break; } case EScriptObjectMessage::Increment: { - if (GetActive()) + if (GetActive()) { CScriptColorModulate::FadeInHelper(mgr, GetUniqueId(), x268_fadeInTime); - else + } else { mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Activate); + } break; } case EScriptObjectMessage::Decrement: @@ -186,7 +192,7 @@ void CScriptPlatform::MoveRiders(CStateManager& mgr, float dt, bool active, std: continue; } act->SetTranslation(newPos); - if (TCastToPtr player = act.GetPtr()) { + if (const TCastToConstPtr player = act.GetPtr()) { if (player->GetOrbitState() != CPlayer::EPlayerOrbitState::NoOrbit) { ++it; continue; @@ -205,9 +211,11 @@ void CScriptPlatform::MoveRiders(CStateManager& mgr, float dt, bool active, std: 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)) + for (const SRiders& rider : movedRiders) { + if (const TCastToConstPtr act = mgr.ObjectById(rider.x0_uid)) { ret.push_back(act->GetUniqueId()); + } + } return ret; } @@ -220,9 +228,11 @@ void CScriptPlatform::PreThink(float dt, CStateManager& mgr) { zeus::CTransform oldXf = x34_transform; CMotionState mState = GetMotionState(); if (GetActive()) { - for (SRiders& rider : x318_riders) - if (TCastToPtr act = mgr.ObjectById(rider.x0_uid)) + for (SRiders& rider : x318_riders) { + if (const TCastToConstPtr act = mgr.ObjectById(rider.x0_uid)) { rider.x8_transform.origin = x34_transform.transposeRotate(act->GetTranslation() - GetTranslation()); + } + } x27c_rotDelta = Move(dt, mgr); } @@ -249,16 +259,20 @@ void CScriptPlatform::PreThink(float dt, CStateManager& mgr) { } void CScriptPlatform::Think(float dt, CStateManager& mgr) { - if (!GetActive()) + if (!GetActive()) { return; + } if (HasModelData() && GetModelData()->HasAnimData()) { - if (!x356_25_controlledAnimation) + if (!x356_25_controlledAnimation) { UpdateAnimation(dt, mgr, true); + } + if (x356_28_rainSplashes && mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain) { if (HasModelData() && !GetModelData()->IsNull() && mgr.GetEnvFxManager()->IsSplashActive() && - mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f) + mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f) { mgr.GetActorModelParticles()->AddRainSplashGenerator(*this, mgr, x34c_maxRainSplashes, x350_rainGenRate, 0.f); + } } } @@ -267,8 +281,9 @@ void CScriptPlatform::Think(float dt, CStateManager& mgr) { DragSlaves(mgr, draggedSet, x270_dragDelta); } - if (x356_24_dead) + if (x356_24_dead) { return; + } if (HealthInfo(mgr)->GetHP() <= 0.f) { x356_24_dead = true; @@ -278,33 +293,42 @@ void CScriptPlatform::Think(float dt, CStateManager& mgr) { 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}); + const 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) + if (xb4_drawFlags == flags && !x356_30_disableXrayAlpha) { xb4_drawFlags = CModelFlags(0, 0, 3, zeus::skWhite); + } } } - if (!mgr.GetObjectById(x354_boundsTrigger)) + + if (!mgr.GetObjectById(x354_boundsTrigger)) { x354_boundsTrigger = kInvalidUniqueId; + } } void CScriptPlatform::Render(CStateManager& mgr) { - bool xray = mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay; - if (xray && !x356_31_xrayFog) + 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::skBlack); + } + CPhysicsActor::Render(mgr); - if (xray && !x356_31_xrayFog) + + if (xray && !x356_31_xrayFog) { mgr.SetupFogForArea(x4_areaId); + } } std::optional CScriptPlatform::GetTouchBounds() const { - if (x314_treeGroup) + if (x314_treeGroup) { return {x314_treeGroup->CalculateAABox(GetTransform())}; + } return {CPhysicsActor::GetBoundingBox()}; } @@ -316,38 +340,40 @@ zeus::CTransform CScriptPlatform::GetPrimitiveTransform() const { } const CCollisionPrimitive* CScriptPlatform::GetCollisionPrimitive() const { - if (!x314_treeGroup) + 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()) + 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)) + if (x354_boundsTrigger != kInvalidUniqueId) { + if (const 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; + return std::any_of(x318_riders.cbegin(), x318_riders.cend(), [id](const auto& rider) { return rider.x0_uid == id; }); } 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()) + 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(); @@ -357,7 +383,7 @@ 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))) { + if (const TCastToPtr act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) { act->AddMaterial(EMaterialTypes::PlatformSlave, mgr); zeus::CTransform xf = act->GetTransform(); xf.origin = act->GetTranslation() - GetTranslation(); @@ -365,9 +391,11 @@ void CScriptPlatform::BuildSlaveList(CStateManager& mgr) { } } 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))) + for (auto it = list.first; it != list.second; ++it) { + if (TCastToConstPtr(mgr.GetObjectById(it->second))) { x354_boundsTrigger = it->second; + } + } } } } @@ -378,7 +406,7 @@ void CScriptPlatform::AddRider(std::vector& riders, TUniqueId riderId, 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)) { + if (const TCastToPtr act = mgr.ObjectById(riderId)) { xf.origin = ridee->GetTransform().transposeRotate(act->GetTranslation() - ridee->GetTranslation()); mgr.SendScriptMsg(act.GetPtr(), ridee->GetUniqueId(), EScriptObjectMessage::AddPlatformRider); } @@ -390,32 +418,37 @@ void CScriptPlatform::AddRider(std::vector& riders, TUniqueId riderId, void CScriptPlatform::AddSlave(TUniqueId id, CStateManager& mgr) { const 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); - } + [id](const SRiders& r) { return r.x0_uid == id; }); + if (search != x338_slavesDynamic.end()) { + return; + } + + if (const TCastToPtr act = mgr.ObjectById(id)) { + act->AddMaterial(EMaterialTypes::PlatformSlave, mgr); + const zeus::CTransform localXf = x34_transform.inverse() * act->GetTransform(); + x338_slavesDynamic.emplace_back(id, 0.166667f, localXf); } } TUniqueId CScriptPlatform::GetNext(TUniqueId uid, CStateManager& mgr) { - TCastToConstPtr nextWp = mgr.GetObjectById(uid); - if (!nextWp) + const TCastToConstPtr nextWp = mgr.GetObjectById(uid); + if (!nextWp) { return GetWaypoint(mgr); + } - TUniqueId next = nextWp->NextWaypoint(mgr); - if (TCastToConstPtr wp = mgr.GetObjectById(next)) + const TUniqueId next = nextWp->NextWaypoint(mgr); + if (const TCastToConstPtr wp = mgr.GetObjectById(next)) { x25c_currentSpeed = wp->GetSpeed(); + } return next; } TUniqueId CScriptPlatform::GetWaypoint(CStateManager& mgr) { for (const SConnection& conn : x20_conns) { - if (conn.x4_msg == EScriptObjectMessage::Follow) + if (conn.x4_msg == EScriptObjectMessage::Follow) { return mgr.GetIdForScript(conn.x8_objId); + } } return kInvalidUniqueId; @@ -427,27 +460,32 @@ void CScriptPlatform::SplashThink(const zeus::CAABox&, const CFluidPlane&, float zeus::CQuaternion CScriptPlatform::Move(float dt, CStateManager& mgr) { TUniqueId nextWaypoint = x25a_targetWaypoint; - if (x25a_targetWaypoint == kInvalidUniqueId) + 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; } - if (nextWaypoint == kInvalidUniqueId) + const TCastToConstPtr wp = mgr.ObjectById(nextWaypoint); + if (x258_currentWaypoint != kInvalidUniqueId && wp && !wp->GetActive()) { + nextWaypoint = GetNext(x258_currentWaypoint, mgr); + if (nextWaypoint == kInvalidUniqueId) { + if (const TCastToConstPtr wp2 = mgr.ObjectById(x258_currentWaypoint)) { + if (wp2->GetActive()) { + nextWaypoint = x258_currentWaypoint; + } + } + } + } + + if (nextWaypoint == kInvalidUniqueId) { return zeus::CQuaternion(); + } while (nextWaypoint != kInvalidUniqueId) { - if (TCastToPtr wp = mgr.ObjectById(nextWaypoint)) { - zeus::CVector3f platToWp = wp->GetTranslation() - GetTranslation(); + if (const TCastToPtr wp2 = mgr.ObjectById(nextWaypoint)) { + const zeus::CVector3f platToWp = wp2->GetTranslation() - GetTranslation(); if (zeus::close_enough(platToWp, zeus::skZero3f)) { x258_currentWaypoint = nextWaypoint; - mgr.SendScriptMsg(wp.GetPtr(), GetUniqueId(), EScriptObjectMessage::Arrived); + mgr.SendScriptMsg(wp2.GetPtr(), GetUniqueId(), EScriptObjectMessage::Arrived); if (zeus::close_enough(x25c_currentSpeed, 0.f, 0.02)) { nextWaypoint = GetNext(x258_currentWaypoint, mgr); x25c_currentSpeed = 0.f; @@ -456,19 +494,19 @@ zeus::CQuaternion CScriptPlatform::Move(float dt, CStateManager& mgr) { nextWaypoint = GetNext(x258_currentWaypoint, mgr); } - if (nextWaypoint != kInvalidUniqueId) + if (nextWaypoint != kInvalidUniqueId) { continue; + } mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop); } if (zeus::close_enough(platToWp, zeus::skZero3f)) { - x270_dragDelta = wp->GetTranslation() - GetTranslation(); + x270_dragDelta = wp2->GetTranslation() - GetTranslation(); MoveToWR(GetTranslation(), dt); - } else if ((platToWp.normalized() * x25c_currentSpeed * dt).magSquared() > platToWp.magSquared()) { - x270_dragDelta = wp->GetTranslation() - GetTranslation(); - MoveToWR(wp->GetTranslation(), dt); + x270_dragDelta = wp2->GetTranslation() - GetTranslation(); + MoveToWR(wp2->GetTranslation(), dt); } else { x270_dragDelta = platToWp.normalized() * x25c_currentSpeed * dt; MoveToWR(GetTranslation() + x270_dragDelta, dt); @@ -477,15 +515,17 @@ zeus::CQuaternion CScriptPlatform::Move(float dt, CStateManager& mgr) { rstl::reserved_vector nearList; mgr.BuildColliderList(nearList, *this, GetMotionVolume(dt)); rstl::reserved_vector nonRiders; - for (TUniqueId id : nearList) - if (!IsRider(id) && !IsSlave(id)) + for (TUniqueId id : nearList) { + if (!IsRider(id) && !IsSlave(id)) { nonRiders.push_back(id); + } + } if (x356_26_detectCollision) { - CMotionState mState = PredictMotion(dt); + const CMotionState mState = PredictMotion(dt); MoveCollisionPrimitive(mState.x0_translation); - bool collision = CGameCollision::DetectDynamicCollisionBoolean(*GetCollisionPrimitive(), - GetPrimitiveTransform(), nonRiders, mgr); + const bool collision = CGameCollision::DetectDynamicCollisionBoolean(*GetCollisionPrimitive(), + GetPrimitiveTransform(), nonRiders, mgr); MoveCollisionPrimitive(zeus::skZero3f); if (collision || x356_27_squishedRider) { if (x356_26_detectCollision) { @@ -494,7 +534,7 @@ zeus::CQuaternion CScriptPlatform::Move(float dt, CStateManager& mgr) { break; } else { x356_27_squishedRider = false; - TUniqueId prevWaypoint = nextWaypoint; + const TUniqueId prevWaypoint = nextWaypoint; nextWaypoint = GetNext(nextWaypoint, mgr); if (x25a_targetWaypoint == nextWaypoint || x25a_targetWaypoint == prevWaypoint) { x260_moveDelay = 0.035f; diff --git a/Runtime/World/CScriptPlayerActor.cpp b/Runtime/World/CScriptPlayerActor.cpp index 206d1f3d4..d99824f1e 100644 --- a/Runtime/World/CScriptPlayerActor.cpp +++ b/Runtime/World/CScriptPlayerActor.cpp @@ -25,10 +25,16 @@ CScriptPlayerActor::CScriptPlayerActor(TUniqueId uid, std::string_view name, con 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; +, x350_flags(flags) +, x354_24_setBoundingBox(setBoundingBox) +, x354_25_deferOnlineModelData(false) +, x354_26_deferOfflineModelData(false) +, x354_27_beamModelLoading(false) +, x354_28_suitModelLoading(false) +, x354_29_loading(true) +, x354_30_enableLoading(true) +, x354_31_deferOnlineLoad(false) +, x355_24_areaTrackingLoad(false) { CMaterialList exclude = GetMaterialFilter().GetExcludeList(); CMaterialList include = GetMaterialFilter().GetIncludeList(); include.Add(EMaterialTypes::Player); @@ -211,8 +217,8 @@ void CScriptPlayerActor::Think(float dt, CStateManager& mgr) { 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; + CGameArea* area = mgr.GetWorld()->GetArea(x4_areaId); + --area->GetPostConstructed()->x113c_playerActorsLoading; x355_24_areaTrackingLoad = false; } x354_29_loading = false; @@ -285,8 +291,8 @@ void CScriptPlayerActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid 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; + CGameArea* area = mgr.GetWorld()->GetArea(x4_areaId); + ++area->GetPostConstructed()->x113c_playerActorsLoading; x355_24_areaTrackingLoad = true; } if (GetActive()) { diff --git a/Runtime/World/CScriptPlayerActor.hpp b/Runtime/World/CScriptPlayerActor.hpp index 041f1a05a..bdbd13890 100644 --- a/Runtime/World/CScriptPlayerActor.hpp +++ b/Runtime/World/CScriptPlayerActor.hpp @@ -25,20 +25,15 @@ class CScriptPlayerActor : public CScriptActor { 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; - }; + 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 GetSuitCharIdx(const CStateManager& mgr, CPlayerState::EPlayerSuit suit) const; diff --git a/Runtime/World/CScriptPlayerHint.cpp b/Runtime/World/CScriptPlayerHint.cpp index f369b0a12..a8733e28f 100644 --- a/Runtime/World/CScriptPlayerHint.cpp +++ b/Runtime/World/CScriptPlayerHint.cpp @@ -1,5 +1,7 @@ #include "Runtime/World/CScriptPlayerHint.hpp" +#include + #include "Runtime/CStateManager.hpp" #include "Runtime/MP1/World/CMetroidPrimeRelay.hpp" #include "Runtime/World/CActorParameters.hpp" @@ -19,20 +21,28 @@ CScriptPlayerHint::CScriptPlayerHint(TUniqueId uid, std::string_view name, const 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); + const bool inList = + std::any_of(xe8_objectList.cbegin(), xe8_objectList.cend(), [uid](const auto id) { return id == uid; }); + if (inList) { + return; + } + + if (xe8_objectList.size() == xe8_objectList.capacity()) { + return; + } + + 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; - } + const auto iter = + std::find_if(xe8_objectList.cbegin(), xe8_objectList.cend(), [uid](const auto id) { return id == uid; }); + + if (iter == xe8_objectList.cend()) { + return; } + + xe8_objectList.erase(iter); } void CScriptPlayerHint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { diff --git a/Runtime/World/CScriptShadowProjector.cpp b/Runtime/World/CScriptShadowProjector.cpp index 63831af1c..652d47e76 100644 --- a/Runtime/World/CScriptShadowProjector.cpp +++ b/Runtime/World/CScriptShadowProjector.cpp @@ -10,7 +10,7 @@ namespace urde { CScriptShadowProjector::CScriptShadowProjector(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, const zeus::CVector3f& offset, - bool b2, float scale, float f2, float opacity, float opacityQ, + bool persistent, float scale, float f2, float opacity, float opacityQ, s32 textureSize) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(), CActorParameters::None(), kInvalidUniqueId) @@ -19,9 +19,9 @@ 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(persistent) +, x110_25_shadowInvalidated(false) {} void CScriptShadowProjector::Accept(IVisitor& visitor) { visitor.Visit(this); } diff --git a/Runtime/World/CScriptShadowProjector.hpp b/Runtime/World/CScriptShadowProjector.hpp index 54a521def..2480ca17e 100644 --- a/Runtime/World/CScriptShadowProjector.hpp +++ b/Runtime/World/CScriptShadowProjector.hpp @@ -20,14 +20,8 @@ class CScriptShadowProjector : public CActor { 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; - }; + bool x110_24_persistent : 1; + bool x110_25_shadowInvalidated : 1; public: CScriptShadowProjector(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, diff --git a/Runtime/World/CScriptSound.cpp b/Runtime/World/CScriptSound.cpp index 8fcc6504f..16ad3c504 100644 --- a/Runtime/World/CScriptSound.cpp +++ b/Runtime/World/CScriptSound.cpp @@ -27,14 +27,17 @@ 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; +, x118_pitch(pitch / 8192.f) +, x11c_24_playRequested(false) +, x11c_25_looped(looped) +, x11c_26_nonEmitter(nonEmitter) +, x11c_27_autoStart(autoStart) +, x11c_28_occlusionTest(occlusionTest) +, x11c_29_acoustics(acoustics) +, x11c_30_worldSfx(worldSfx) +, x11c_31_selfFree(false) +, x11d_24_allowDuplicates(allowDuplicates) +, x11d_25_processedThisFrame(false) { if (x11c_30_worldSfx && (!x11c_26_nonEmitter || !x11c_25_looped)) x11c_30_worldSfx = false; } @@ -47,7 +50,7 @@ void CScriptSound::PreThink(float dt, CStateManager& mgr) { x11d_25_processedThisFrame = false; } -static const CMaterialFilter kSolidFilter = +constexpr CMaterialFilter kSolidFilter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough}); float CScriptSound::GetOccludedVolumeAmount(const zeus::CVector3f& pos, const CStateManager& mgr) { diff --git a/Runtime/World/CScriptSound.hpp b/Runtime/World/CScriptSound.hpp index 63e33e989..70addc700 100644 --- a/Runtime/World/CScriptSound.hpp +++ b/Runtime/World/CScriptSound.hpp @@ -28,21 +28,16 @@ class CScriptSound : public CActor { 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; - }; + 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; static float GetOccludedVolumeAmount(const zeus::CVector3f& pos, const CStateManager& mgr); diff --git a/Runtime/World/CScriptSpawnPoint.hpp b/Runtime/World/CScriptSpawnPoint.hpp index ab867ec6c..20a488de5 100644 --- a/Runtime/World/CScriptSpawnPoint.hpp +++ b/Runtime/World/CScriptSpawnPoint.hpp @@ -14,13 +14,8 @@ 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; - }; + bool x10c_24_firstSpawn : 1; + bool x10c_25_morphed : 1; public: CScriptSpawnPoint(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, diff --git a/Runtime/World/CScriptSpecialFunction.cpp b/Runtime/World/CScriptSpecialFunction.cpp index 460612f5a..207e2a5cb 100644 --- a/Runtime/World/CScriptSpecialFunction.cpp +++ b/Runtime/World/CScriptSpecialFunction.cpp @@ -1,5 +1,7 @@ #include "Runtime/World/CScriptSpecialFunction.hpp" +#include + #include "Runtime/CGameState.hpp" #include "Runtime/CMemoryCardSys.hpp" #include "Runtime/CSimplePool.hpp" @@ -45,8 +47,18 @@ CScriptSpecialFunction::CScriptSpecialFunction(TUniqueId uid, std::string_view n , x184_(0.f) , x1bc_areaSaveId(aId1) , x1c0_layerIdx(aId2) -, x1c4_item(itemType) { - x1e4_26_sfx2Played = true; +, x1c4_item(itemType) +, x1e4_24_(false) +, x1e4_25_spinnerCanMove(false) +, x1e4_26_sfx2Played(true) +, x1e4_27_sfx3Played(false) +, x1e4_28_frustumEntered(false) +, x1e4_29_frustumExited(false) +, x1e4_30_(false) +, x1e4_31_inAreaDamage(false) +, x1e5_24_doSave(false) +, x1e5_25_playerInArea(false) +, x1e5_26_displayBillboard(false) { if (xe8_function == ESpecialFunction::HUDTarget) x1c8_touchBounds = {-1.f, 1.f}; } @@ -115,8 +127,11 @@ void CScriptSpecialFunction::Think(float dt, CStateManager& mgr) { break; } } -static const ERumbleFxId fxTranslation[6] = {ERumbleFxId::Twenty, ERumbleFxId::One, ERumbleFxId::TwentyOne, - ERumbleFxId::TwentyTwo, ERumbleFxId::TwentyThree, ERumbleFxId::Zero}; + +constexpr std::array fxTranslation{ + 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) { diff --git a/Runtime/World/CScriptSpecialFunction.hpp b/Runtime/World/CScriptSpecialFunction.hpp index 0d5dc7935..f001d8abe 100644 --- a/Runtime/World/CScriptSpecialFunction.hpp +++ b/Runtime/World/CScriptSpecialFunction.hpp @@ -99,22 +99,17 @@ private: s32 x1c0_layerIdx; CPlayerState::EItemType x1c4_item; std::optional x1c8_touchBounds; - union { - struct { - bool x1e4_24_ : 1; - bool x1e4_25_spinnerCanMove : 1; - bool x1e4_26_sfx2Played : 1; - bool x1e4_27_sfx3Played : 1; - bool x1e4_28_frustumEntered : 1; - bool x1e4_29_frustumExited : 1; - bool x1e4_30_ : 1; - bool x1e4_31_inAreaDamage : 1; - bool x1e5_24_doSave : 1; - bool x1e5_25_playerInArea : 1; - bool x1e5_26_displayBillboard : 1; - }; - u32 x1e4_dummy = 0; - }; + bool x1e4_24_ : 1; + bool x1e4_25_spinnerCanMove : 1; + bool x1e4_26_sfx2Played : 1; + bool x1e4_27_sfx3Played : 1; + bool x1e4_28_frustumEntered : 1; + bool x1e4_29_frustumExited : 1; + bool x1e4_30_ : 1; + bool x1e4_31_inAreaDamage : 1; + bool x1e5_24_doSave : 1; + bool x1e5_25_playerInArea : 1; + bool x1e5_26_displayBillboard : 1; TLockedToken x1e8_; // Used to be optional public: CScriptSpecialFunction(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, ESpecialFunction, diff --git a/Runtime/World/CScriptSpindleCamera.hpp b/Runtime/World/CScriptSpindleCamera.hpp index 5f6fe7983..4e9d15d8f 100644 --- a/Runtime/World/CScriptSpindleCamera.hpp +++ b/Runtime/World/CScriptSpindleCamera.hpp @@ -78,7 +78,7 @@ class CScriptSpindleCamera : public CGameCamera { float x328_maxAzimuthInterpTimer = 0.f; bool x32c_outsideClampedAzimuth = false; zeus::CVector3f x330_lookDir; - bool x33c_24_inResetThink; + bool x33c_24_inResetThink = false; float GetInVar(const SSpindleProperty& seg) const { return x18c_inVars[int(seg.x4_input)]; } diff --git a/Runtime/World/CScriptStreamedMusic.cpp b/Runtime/World/CScriptStreamedMusic.cpp index 841861bf4..0cf0e9e2e 100644 --- a/Runtime/World/CScriptStreamedMusic.cpp +++ b/Runtime/World/CScriptStreamedMusic.cpp @@ -27,7 +27,7 @@ void CScriptStreamedMusic::StartStream(CStateManager& mgr) { void CScriptStreamedMusic::TweakOverride(CStateManager& mgr) { const CWorld* wld = mgr.GetWorld(); const CGameArea* area = wld->GetAreaAlways(x4_areaId); - std::string twkName = fmt::format(fmt("Area {} MusicObject: {}"), area->GetAreaAssetId(), x10_name); + std::string twkName = fmt::format(FMT_STRING("Area {} MusicObject: {}"), area->GetAreaAssetId(), x10_name); if (g_TweakManager->HasTweakValue(twkName)) { const CTweakValue::Audio& audio = g_TweakManager->GetTweakValue(twkName)->GetAudio(); x34_fileName = audio.GetFileName(); diff --git a/Runtime/World/CScriptTargetingPoint.cpp b/Runtime/World/CScriptTargetingPoint.cpp index bc7e59b6f..3924b0cc3 100644 --- a/Runtime/World/CScriptTargetingPoint.cpp +++ b/Runtime/World/CScriptTargetingPoint.cpp @@ -9,7 +9,8 @@ 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) +, xe8_e4_(false) {} void CScriptTargetingPoint::Accept(IVisitor& visitor) { visitor.Visit(this); } diff --git a/Runtime/World/CScriptTargetingPoint.hpp b/Runtime/World/CScriptTargetingPoint.hpp index 672f7366e..0cbf6132e 100644 --- a/Runtime/World/CScriptTargetingPoint.hpp +++ b/Runtime/World/CScriptTargetingPoint.hpp @@ -8,12 +8,7 @@ namespace urde { class CScriptTargetingPoint : public CActor { private: - union { - struct { - bool xe8_e4_ : 1; - }; - u8 xe8_dummy = 0; - }; + bool xe8_e4_ : 1; TUniqueId xea_; float xec_time = 0.f; diff --git a/Runtime/World/CScriptTrigger.cpp b/Runtime/World/CScriptTrigger.cpp index 666c990ec..9dcbc39ec 100644 --- a/Runtime/World/CScriptTrigger.cpp +++ b/Runtime/World/CScriptTrigger.cpp @@ -20,13 +20,13 @@ 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; +, 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); } @@ -255,7 +255,7 @@ void CScriptTrigger::Touch(CActor& act, CStateManager& mgr) { x148_29_didPhazonDamage = false; } else if (x100_damageInfo.GetDamage() > 0.f) { const CDamageVulnerability* dVuln = mgr.Player()->GetDamageVulnerability(); - if (dVuln->WeaponHurts(x100_damageInfo.GetWeaponMode(), 0) && + if (dVuln->WeaponHurts(x100_damageInfo.GetWeaponMode(), false) && x100_damageInfo.GetWeaponMode().GetType() == EWeaponType::Phazon && !mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit)) { pl->IncrementEnvironmentDamage(); diff --git a/Runtime/World/CScriptTrigger.hpp b/Runtime/World/CScriptTrigger.hpp index 038ab41f0..f399d6b28 100644 --- a/Runtime/World/CScriptTrigger.hpp +++ b/Runtime/World/CScriptTrigger.hpp @@ -54,18 +54,12 @@ protected: 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; - }; + 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; public: CScriptTrigger(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, diff --git a/Runtime/World/CScriptWater.cpp b/Runtime/World/CScriptWater.cpp index 92e1ba2d0..bab5f78c8 100644 --- a/Runtime/World/CScriptWater.cpp +++ b/Runtime/World/CScriptWater.cpp @@ -61,14 +61,18 @@ CScriptWater::CScriptWater( , 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) { +, x2c0_tileSize(tileSize) +, x2e8_24_b4(b4) +, x2e8_25_morphIn(false) +, x2e8_26_morphing(false) +, x2e8_27_allowRender(allowRender) +, x2e8_28_recomputeClipping(true) +, x2e8_29_alphaIn(false) +, x2e8_30_alphaOut(false) { 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)) @@ -140,7 +144,7 @@ void CScriptWater::SetupGrid(bool recomputeClipping) { x2e8_28_recomputeClipping = recomputeClipping; } -static const CMaterialFilter SolidFilter = CMaterialFilter::MakeInclude({EMaterialTypes::Solid}); +constexpr CMaterialFilter SolidFilter = CMaterialFilter::MakeInclude({EMaterialTypes::Solid}); void CScriptWater::SetupGridClipping(CStateManager& mgr, int computeVerts) { if (x2e8_28_recomputeClipping) { diff --git a/Runtime/World/CScriptWater.hpp b/Runtime/World/CScriptWater.hpp index 3751aef0a..0bbe7785e 100644 --- a/Runtime/World/CScriptWater.hpp +++ b/Runtime/World/CScriptWater.hpp @@ -66,18 +66,14 @@ class CScriptWater : public CScriptTrigger { 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; - }; + 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); diff --git a/Runtime/World/CScriptWorldTeleporter.hpp b/Runtime/World/CScriptWorldTeleporter.hpp index f76a21763..dc66d9f63 100644 --- a/Runtime/World/CScriptWorldTeleporter.hpp +++ b/Runtime/World/CScriptWorldTeleporter.hpp @@ -16,15 +16,9 @@ class CScriptWorldTeleporter : public CEntity { 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; - }; - + bool x40_24_upElevator : 1; + bool x40_25_inTransition : 1; + bool x40_27_fadeWhite : 1; float x44_charFadeIn = 0.1f; float x48_charsPerSecond = 8.0f; float x4c_showDelay = 0.0f; diff --git a/Runtime/World/CSnakeWeedSwarm.cpp b/Runtime/World/CSnakeWeedSwarm.cpp index 76609926a..85bf1fe2d 100644 --- a/Runtime/World/CSnakeWeedSwarm.cpp +++ b/Runtime/World/CSnakeWeedSwarm.cpp @@ -416,7 +416,7 @@ void CSnakeWeedSwarm::RenderBoid(u32 idx, const CBoid& boid, u32& posesToBuild) auto& modelData = *x1b0_modelData[modelIdx]; auto& model = modelData.PickAnimatedModel(x1c4_which); auto& animData = *modelData.GetAnimationData(); - const CModelFlags useFlags(0, 0, 3, zeus::skWhite); + constexpr CModelFlags useFlags(0, 0, 3, zeus::skWhite); if (posesToBuild & 1 << modelIdx) { posesToBuild &= ~(1 << modelIdx); animData.BuildPose(); diff --git a/Runtime/World/CStateMachine.cpp b/Runtime/World/CStateMachine.cpp index f8979a42d..16b0d5652 100644 --- a/Runtime/World/CStateMachine.cpp +++ b/Runtime/World/CStateMachine.cpp @@ -79,8 +79,8 @@ void CStateMachineState::Update(CStateManager& mgr, CAi& ai, float delta) { x4_state->CallFunc(mgr, ai, EStateMsg::Deactivate, 0.f); x4_state = state; //#ifndef NDEBUG - fmt::print(fmt("{} {} {} - {} {}\n"), ai.GetUniqueId(), ai.GetEditorId(), ai.GetName(), - state->xc_name, int(state - x0_machine->GetStateVector().data())); +// fmt::print(FMT_STRING("{} {} {} - {} {}\n"), ai.GetUniqueId(), ai.GetEditorId(), ai.GetName(), +// state->xc_name, int(state - x0_machine->GetStateVector().data())); //#endif x8_time = 0.f; x18_24_codeTrigger = false; diff --git a/Runtime/World/CStateMachine.hpp b/Runtime/World/CStateMachine.hpp index 0ddecca84..7964294f6 100644 --- a/Runtime/World/CStateMachine.hpp +++ b/Runtime/World/CStateMachine.hpp @@ -50,8 +50,8 @@ class CAiState { friend class CStateMachineState; CAiStateFunc x0_func; char xc_name[32] = {}; - u32 x2c_numTriggers; - CAiTrigger* x30_firstTrigger; + u32 x2c_numTriggers = 0; + CAiTrigger* x30_firstTrigger = nullptr; public: CAiState(CAiStateFunc func, const char* name) { @@ -88,16 +88,11 @@ class CStateMachineState { 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; - }; + float x14_ = 0.f; + bool x18_24_codeTrigger : 1; public: - CStateMachineState() = default; + CStateMachineState() : x18_24_codeTrigger(false) {} CAiState* GetActorState() const { return x4_state; } diff --git a/Runtime/World/CVisorFlare.cpp b/Runtime/World/CVisorFlare.cpp index 1be3c4a63..0e46e3e8f 100644 --- a/Runtime/World/CVisorFlare.cpp +++ b/Runtime/World/CVisorFlare.cpp @@ -69,7 +69,9 @@ void CVisorFlare::Update(float dt, const zeus::CVector3f& pos, const CActor* act mgr.SetThermalColdScale2(mgr.GetThermalColdScale2() + x24_); } - printf("%08X %f %f\n", act->GetEditorId().id, x24_, x28_); +//#ifndef NDEBUG +// printf("%08X %f %f\n", act->GetEditorId().id, x24_, x28_); +//#endif } } diff --git a/Runtime/World/CWallCrawlerSwarm.cpp b/Runtime/World/CWallCrawlerSwarm.cpp index 57f9658bb..4bcecc687 100644 --- a/Runtime/World/CWallCrawlerSwarm.cpp +++ b/Runtime/World/CWallCrawlerSwarm.cpp @@ -69,13 +69,13 @@ CWallCrawlerSwarm::CWallCrawlerSwarm(TUniqueId uid, bool active, std::string_vie , x548_numBoids(numBoids) , x54c_maxCreatedBoids(maxCreatedBoids) , x554_maxLaunches(maxLaunches) -, x558_flavor(flavor) { +, x558_flavor(flavor) +, x560_24_enableLighting(true) +, x560_25_useSoftwareLight(true) +, x560_26_modelAssetDirty(false) { x168_partitionedBoidLists.resize(125); x55c_launchSfx = CSfxManager::TranslateSFXID(launchSfx != -1 ? u16(launchSfx) : u16(0xffff)); x55e_scatterSfx = CSfxManager::TranslateSFXID(scatterSfx != -1 ? u16(scatterSfx) : u16(0xffff)); - x560_24_enableLighting = true; - x560_25_useSoftwareLight = true; - x560_26_modelAssetDirty = false; CAnimRes attractAnimRes(animRes); attractAnimRes.SetCanLoop(true); attractAnimRes.SetDefaultAnim(attractAnim != -1 ? attractAnim : 0); @@ -835,7 +835,7 @@ void CWallCrawlerSwarm::Think(float dt, CStateManager& mgr) { const zeus::CAABox aabb = BoxForPosition(r26, r27, r20, x374_boidRadius + 0.5f); CAreaCollisionCache ccache(aabb); CGameCollision::BuildAreaCollisionCache(mgr, ccache); - while (boid) { + while (boid != nullptr) { r21 += 1; if (boid->GetActive()) { if (x558_flavor == EFlavor::Scarab) { @@ -1062,7 +1062,7 @@ void CWallCrawlerSwarm::RenderBoid(const CBoid* boid, u32& drawMask, bool therma model.GetModelInst()->SetAmbientColor(boid->x40_ambientLighting); CGraphics::SetModelMatrix(boid->GetTransform()); if (boid->x48_timeToDie > 0.f && !thermalHot) { - const CModelFlags useFlags(0, 0, 3, zeus::skWhite); + constexpr CModelFlags useFlags(0, 0, 3, zeus::skWhite); mData.GetAnimationData()->Render(model, useFlags, std::nullopt, nullptr); if (auto iceModel = mData.GetAnimationData()->GetIceModel()) { if (!iceModel->GetModelInst()->TryLockTextures()) { @@ -1075,7 +1075,7 @@ void CWallCrawlerSwarm::RenderBoid(const CBoid* boid, u32& drawMask, bool therma mData.GetAnimationData()->Render(*iceModel, iceFlags, std::nullopt, nullptr); } } else if (thermalHot) { - const CModelFlags thermFlags(5, 0, 3, zeus::skWhite); + constexpr CModelFlags thermFlags(5, 0, 3, zeus::skWhite); mData.RenderThermal(zeus::skWhite, zeus::CColor(0.f, 0.25f), thermFlags); } else { mData.GetAnimationData()->Render(model, flags, std::nullopt, nullptr); @@ -1083,7 +1083,7 @@ void CWallCrawlerSwarm::RenderBoid(const CBoid* boid, u32& drawMask, bool therma } void CWallCrawlerSwarm::Render(CStateManager& mgr) { - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CWallCrawlerSwarm::Render {} {} {}"), + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CWallCrawlerSwarm::Render {} {} {}"), x8_uid, xc_editorId, x10_name).c_str(), zeus::skOrange); u32 drawMask = 0xffffffff; const bool r24 = x560_24_enableLighting; @@ -1235,5 +1235,15 @@ zeus::CVector3f CWallCrawlerSwarm::GetAimPosition(const CStateManager&, float dt return x108_boids[x42c_lockOnIdx].x30_velocity * dt + x124_lastOrbitPosition; } +void CWallCrawlerSwarm::ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& stateMgr) { + for (CBoid& boid : x108_boids) { + if (boid.GetActive() && (boid.GetTranslation() - pos).magSquared() < info.GetRadius() * info.GetRadius()) { + boid.x78_health -= info.GetRadiusDamage(); + if (boid.x78_health <= 0.f) { + KillBoid(boid, stateMgr, 1.f, 0.1f); + } + } + } +} } // namespace urde diff --git a/Runtime/World/CWallCrawlerSwarm.hpp b/Runtime/World/CWallCrawlerSwarm.hpp index a7c934f2a..a990538c7 100644 --- a/Runtime/World/CWallCrawlerSwarm.hpp +++ b/Runtime/World/CWallCrawlerSwarm.hpp @@ -38,27 +38,28 @@ public: CCollisionSurface x50_surface = 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), 0xffffffff); - float x78_health; + float x78_health = 0.f; int x7c_framesNotOnSurface : 8; int x7c_idx : 10; int x7c_remainingLaunchNotOnSurfaceFrames : 8; - - union { - struct { - bool x80_24_active : 1; - bool x80_25_inFrustum : 1; - bool x80_26_launched : 1; - bool x80_27_scarabExplodeTimerEnabled : 1; - bool x80_28_nearPlayer : 1; - }; - u32 x80_ = 0; - }; + bool x80_24_active : 1; + bool x80_25_inFrustum : 1; + bool x80_26_launched : 1; + bool x80_27_scarabExplodeTimerEnabled : 1; + bool x80_28_nearPlayer : 1; public: - CBoid(const zeus::CTransform& xf, int idx) : x0_xf(xf) { - x7c_framesNotOnSurface = 0; - x7c_idx = idx; - } + CBoid(const zeus::CTransform& xf, int idx) + : x0_xf(xf) + , x7c_framesNotOnSurface(0) + , x7c_idx(idx) + , x7c_remainingLaunchNotOnSurfaceFrames(0) + , x80_24_active(false) + , x80_25_inFrustum(false) + , x80_26_launched(false) + , x80_27_scarabExplodeTimerEnabled(false) + , x80_28_nearPlayer(false) {} + zeus::CTransform& Transform() { return x0_xf; } zeus::CVector3f& Translation() { return x0_xf.origin; } const zeus::CTransform& GetTransform() const { return x0_xf; } @@ -204,7 +205,7 @@ public: zeus::CVector3f GetOrbitPosition(const CStateManager&) const override; zeus::CVector3f GetAimPosition(const CStateManager&, float) const override; const zeus::CVector3f& GetLastKilledOffset() const { return x130_lastKilledOffset; } - void ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& stateMgr) {} + void ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& stateMgr); const std::vector& GetBoids() const { return x108_boids; } int GetCurrentLockOnId() const { return x42c_lockOnIdx; } bool GetLockOnLocationValid(int id) const { return id >= 0 && id < x108_boids.size() && x108_boids[id].GetActive(); } diff --git a/Runtime/World/CWorld.cpp b/Runtime/World/CWorld.cpp index f2499f3ca..5527c7fdb 100644 --- a/Runtime/World/CWorld.cpp +++ b/Runtime/World/CWorld.cpp @@ -1,5 +1,8 @@ #include "Runtime/World/CWorld.hpp" +#include +#include + #include "Runtime/CGameState.hpp" #include "Runtime/CInGameTweakManagerBase.hpp" #include "Runtime/CSimplePool.hpp" @@ -44,15 +47,17 @@ 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()) + if (!id.IsValid()) { return kInvalidAreaId; - for (const CDummyGameArea& area : x18_areas) { - if (area.xc_mrea == id) - return ret; - ++ret; } - return kInvalidAreaId; + + const auto iter = + std::find_if(x18_areas.cbegin(), x18_areas.cend(), [id](const auto& area) { return area.xc_mrea == id; }); + if (iter == x18_areas.cend()) { + return kInvalidAreaId; + } + + return TAreaId(std::distance(x18_areas.cbegin(), iter)); } CWorld::CRelay::CRelay(CInputStream& in) { @@ -184,8 +189,13 @@ 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; +: x8_mlvlId(mlvlId) +, x60_objectStore(objStore) +, x64_resFactory(resFactory) +, x70_24_currentAreaNeedsAllocation(true) +, x70_25_loadPaused(false) +, x70_26_skyboxActive(false) +, x70_27_skyboxVisible(false) { SObjectTag tag{FOURCC('MLVL'), mlvlId}; x44_bufSz = resFactory.ResourceSize(tag); x40_loadBuf.reset(new u8[x44_bufSz]); @@ -221,15 +231,17 @@ 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()) + if (!id.IsValid()) { return kInvalidAreaId; - for (const std::unique_ptr& area : x18_areas) { - if (area->x84_mrea == id) - return ret; - ++ret; } - return kInvalidAreaId; + + const auto iter = + std::find_if(x18_areas.cbegin(), x18_areas.cend(), [id](const auto& area) { return area->x84_mrea == id; }); + if (iter == x18_areas.cend()) { + return kInvalidAreaId; + } + + return TAreaId(std::distance(x18_areas.cbegin(), iter)); } void CWorld::MoveToChain(CGameArea* area, EChain chain) { @@ -345,7 +357,7 @@ bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, CAssetId mreaId) if (version > 12) { x84_defAudioTrack = r.readString(); - std::string trackKey = fmt::format(fmt("WorldDefault: {}"), x8_mlvlId); + std::string trackKey = fmt::format(FMT_STRING("WorldDefault: {}"), x8_mlvlId); if (g_TweakManager->HasTweakValue(trackKey)) x84_defAudioTrack = g_TweakManager->GetTweakValue(trackKey)->GetAudio().GetFileName(); } @@ -700,19 +712,20 @@ bool CWorld::AreSkyNeedsMet() const { } TAreaId CWorld::GetAreaIdForSaveId(s32 saveId) const { - if (saveId == -1) + 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; + if (x18_areas.empty()) { + return kInvalidAreaId; + } + + const auto iter = std::find_if(x18_areas.cbegin(), x18_areas.cend(), + [saveId](const auto& area) { return area->x88_areaId == saveId; }); + if (iter == x18_areas.cend()) { + return kInvalidAreaId; + } + + return TAreaId(std::distance(x18_areas.cbegin(), iter)); } } // namespace urde diff --git a/Runtime/World/CWorld.hpp b/Runtime/World/CWorld.hpp index 2b662179d..57edfb455 100644 --- a/Runtime/World/CWorld.hpp +++ b/Runtime/World/CWorld.hpp @@ -38,13 +38,15 @@ public: }; class CDummyWorld : public IWorld { - bool x4_loadMap; enum class Phase { Loading, LoadingMap, LoadingMapAreas, Done, - } x8_phase = Phase::Loading; + }; + + bool x4_loadMap; + Phase x8_phase = Phase::Loading; CAssetId xc_mlvlId; CAssetId x10_strgId; CAssetId x14_savwId; @@ -112,7 +114,9 @@ private: LoadingSkyBox, LoadingSoundGroups, Done, - } x4_phase = Phase::Loading; + }; + + Phase x4_phase = Phase::Loading; CAssetId x8_mlvlId; CAssetId xc_strgId; CAssetId x10_savwId; @@ -130,16 +134,10 @@ private: 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; - }; + 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; std::optional> x94_skyboxWorld; @@ -173,7 +171,7 @@ public: void CycleLoadPauseState(); CWorld(IObjectStore& objStore, IFactory& resFactory, CAssetId mlvlId); - ~CWorld(); + ~CWorld() override; bool DoesAreaExist(TAreaId area) const; const std::vector>& GetGameAreas() const { return x18_areas; } diff --git a/Runtime/World/CWorldTransManager.hpp b/Runtime/World/CWorldTransManager.hpp index 978d0f447..105d23ce8 100644 --- a/Runtime/World/CWorldTransManager.hpp +++ b/Runtime/World/CWorldTransManager.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -31,7 +32,7 @@ public: CModelData x1c_samusModelData; CModelData x68_beamModelData; CModelData xb4_platformModelData; - CModelData x100_bgModelData[3]; + std::array x100_bgModelData; TLockedToken x14c_beamModel; TLockedToken x158_suitModel; TLockedToken x164_suitSkin; @@ -57,35 +58,30 @@ private: std::unique_ptr x8_textData; TLockedToken xc_strTable; u8 x14_ = 0; - float x18_bgOffset; - float x1c_bgHeight; + float x18_bgOffset = 0.0f; + float x1c_bgHeight = 0.0f; 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 x34_stopTime = 0.0f; 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 x3c_sfxInterval = 0.0f; + bool x40_strIdx = false; + 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; CColoredQuadFilter m_fadeToBlack{EFilterType::Blend}; CTexturedQuadFilter m_dissolve{EFilterType::Blend, CGraphics::g_SpareTexture.get()}; CWideScreenFilter m_widescreen{EFilterType::Blend}; CCameraBlurFilter m_camblur; - boo::ObjToken m_reflectionCube[2]; + std::array, 2> m_reflectionCube; static int GetSuitCharIdx(); void DrawFirstPass(CActorLights* lights); @@ -101,7 +97,12 @@ private: void DrawText(); public: - CWorldTransManager() { x44_24_transFinished = true; } + CWorldTransManager() + : x44_24_transFinished(true) + , x44_25_stopSoon(false) + , x44_26_goingUp(false) + , x44_27_fadeWhite(false) + , x44_28_textDirty(false) {} void Update(float); void Draw(); diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index 41ff3a2d3..e7985007b 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -134,7 +134,7 @@ constexpr int skElitePiratePropCount = 41; static bool EnsurePropertyCount(int count, int expected, const char* structName) { if (count < expected) { - Log.report(logvisor::Warning, fmt("Insufficient number of props ({}/{}) for {} entity"), count, expected, + Log.report(logvisor::Warning, FMT_STRING("Insufficient number of props ({}/{}) for {} entity"), count, expected, structName); return false; } @@ -700,7 +700,7 @@ CEntity* ScriptLoader::LoadSound(CStateManager& mgr, CInputStream& in, int propC s32 pitch = in.readInt32Big(); if (soundId < 0) { - Log.report(logvisor::Warning, fmt("Invalid sound ID specified in Sound {} ({}), dropping..."), head.x0_name, + Log.report(logvisor::Warning, FMT_STRING("Invalid sound ID specified in Sound {} ({}), dropping..."), head.x0_name, info.GetEditorId()); return nullptr; } @@ -856,7 +856,7 @@ CEntity* ScriptLoader::LoadSpawnPoint(CStateManager& mgr, CInputStream& in, int CEntity* ScriptLoader::LoadCameraHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { if (propCount > 25) { - Log.report(logvisor::Warning, fmt("Too many props ({} > 25) for CameraHint entity"), propCount); + Log.report(logvisor::Warning, FMT_STRING("Too many props ({} > 25) for CameraHint entity"), propCount); return nullptr; } @@ -1054,7 +1054,7 @@ CEntity* ScriptLoader::LoadCameraFilterKeyframe(CStateManager& mgr, CInputStream color.readRGBABig(in); float timeIn = in.readFloatBig(); float timeOut = in.readFloatBig(); - CAssetId txtr = in.readUint32Big(); + CAssetId txtr(in); return new CScriptCameraFilterKeyframe(mgr.AllocateUniqueId(), name, info, ftype, shape, filterIdx, unk, color, timeIn, timeOut, txtr, active); @@ -1364,7 +1364,7 @@ CEntity* ScriptLoader::LoadSpacePirate(CStateManager& mgr, CInputStream& in, int if (animParms.GetCharacter() == 0) { Log.report(logvisor::Warning, - fmt("SpacePirate <{}> has AnimationInformation property with invalid character selected"), head.x0_name); + FMT_STRING("SpacePirate <{}> has AnimationInformation property with invalid character selected"), head.x0_name); animParms.SetCharacter(2); } @@ -1593,7 +1593,7 @@ CEntity* ScriptLoader::LoadFlickerBat(CStateManager& mgr, CInputStream& in, int CEntity* ScriptLoader::LoadPathCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { if (propCount > 15) { - Log.report(logvisor::Warning, fmt("Too many props ({} > 15) for PathCamera entity"), propCount); + Log.report(logvisor::Warning, FMT_STRING("Too many props ({} > 15) for PathCamera entity"), propCount); return nullptr; } @@ -2384,7 +2384,7 @@ CEntity* ScriptLoader::LoadVisorFlare(CStateManager& mgr, CInputStream& in, int CEntity* ScriptLoader::LoadWorldTeleporter(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { if (propCount < 4 || propCount > 26) { - Log.report(logvisor::Warning, fmt("Incorrect number of props for WorldTeleporter")); + Log.report(logvisor::Warning, FMT_STRING("Incorrect number of props for WorldTeleporter")); return nullptr; } diff --git a/Runtime/rstl.hpp b/Runtime/rstl.hpp index eaf42903e..d1ceb77b3 100644 --- a/Runtime/rstl.hpp +++ b/Runtime/rstl.hpp @@ -363,7 +363,7 @@ public: void push_back(const T& d) { #ifndef NDEBUG if (x0_size == N) { - Log.report(logvisor::Fatal, fmt("push_back() called on full rstl::reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("push_back() called on full rstl::reserved_vector.")); } #endif @@ -374,7 +374,7 @@ public: void push_back(T&& d) { #ifndef NDEBUG if (x0_size == N) { - Log.report(logvisor::Fatal, fmt("push_back() called on full rstl::reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("push_back() called on full rstl::reserved_vector.")); } #endif @@ -386,7 +386,7 @@ public: T& emplace_back(_Args&&... args) { #ifndef NDEBUG if (x0_size == N) { - Log.report(logvisor::Fatal, fmt("emplace_back() called on full rstl::reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("emplace_back() called on full rstl::reserved_vector.")); } #endif @@ -400,7 +400,7 @@ public: void pop_back() { #ifndef NDEBUG if (x0_size == 0) { - Log.report(logvisor::Fatal, fmt("pop_back() called on empty rstl::reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("pop_back() called on empty rstl::reserved_vector.")); } #endif @@ -411,7 +411,7 @@ public: iterator insert(const_iterator pos, const T& value) { #ifndef NDEBUG if (x0_size == N) { - Log.report(logvisor::Fatal, fmt("insert() called on full rstl::reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("insert() called on full rstl::reserved_vector.")); } #endif @@ -432,7 +432,7 @@ public: iterator insert(const_iterator pos, T&& value) { #ifndef NDEBUG if (x0_size == N) - Log.report(logvisor::Fatal, fmt("insert() called on full rstl::reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("insert() called on full rstl::reserved_vector.")); #endif auto target_it = base::_const_cast_iterator(pos); if (pos == cend()) { @@ -451,7 +451,7 @@ public: void resize(size_t size) { #ifndef NDEBUG if (size > N) { - Log.report(logvisor::Fatal, fmt("resize() call overflows rstl::reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("resize() call overflows rstl::reserved_vector.")); } #endif @@ -473,7 +473,7 @@ public: void resize(size_t size, const T& value) { #ifndef NDEBUG if (size > N) { - Log.report(logvisor::Fatal, fmt("resize() call overflows rstl::reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("resize() call overflows rstl::reserved_vector.")); } #endif @@ -495,7 +495,7 @@ public: iterator erase(const_iterator pos) { #ifndef NDEBUG if (x0_size == 0) { - Log.report(logvisor::Fatal, fmt("erase() called on empty rstl::reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("erase() called on empty rstl::reserved_vector.")); } #endif @@ -554,7 +554,7 @@ public: [[nodiscard]] T& operator[](size_t idx) { #ifndef NDEBUG if (idx >= x0_size) { - Log.report(logvisor::Fatal, fmt("out of bounds access on reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("out of bounds access on reserved_vector.")); } #endif return _value(idx); @@ -562,7 +562,7 @@ public: [[nodiscard]] const T& operator[](size_t idx) const { #ifndef NDEBUG if (idx >= x0_size) { - Log.report(logvisor::Fatal, fmt("out of bounds access on reserved_vector.")); + Log.report(logvisor::Fatal, FMT_STRING("out of bounds access on reserved_vector.")); } #endif return _value(idx); diff --git a/Shaders/shader_CFluidPlaneShaderGLSL.cpp b/Shaders/shader_CFluidPlaneShaderGLSL.cpp index 9a2646d0c..7e7e218f4 100644 --- a/Shaders/shader_CFluidPlaneShaderGLSL.cpp +++ b/Shaders/shader_CFluidPlaneShaderGLSL.cpp @@ -332,19 +332,19 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { out << "#define TEXTURE_DECLS "; if (info.m_hasPatternTex1) - fmt::print(out, fmt("TBINDING{} uniform sampler2D patternTex1;"), nextTex++); + fmt::print(out, FMT_STRING("TBINDING{} uniform sampler2D patternTex1;"), nextTex++); if (info.m_hasPatternTex2) - fmt::print(out, fmt("TBINDING{} uniform sampler2D patternTex2;"), nextTex++); + fmt::print(out, FMT_STRING("TBINDING{} uniform sampler2D patternTex2;"), nextTex++); if (info.m_hasColorTex) - fmt::print(out, fmt("TBINDING{} uniform sampler2D colorTex;"), nextTex++); + fmt::print(out, FMT_STRING("TBINDING{} uniform sampler2D colorTex;"), nextTex++); if (info.m_hasBumpMap) - fmt::print(out, fmt("TBINDING{} uniform sampler2D bumpMap;"), nextTex++); + fmt::print(out, FMT_STRING("TBINDING{} uniform sampler2D bumpMap;"), nextTex++); if (info.m_hasEnvMap) - fmt::print(out, fmt("TBINDING{} uniform sampler2D envMap;"), nextTex++); + fmt::print(out, FMT_STRING("TBINDING{} uniform sampler2D envMap;"), nextTex++); if (info.m_hasEnvBumpMap) - fmt::print(out, fmt("TBINDING{} uniform sampler2D envBumpMap;"), nextTex++); + fmt::print(out, FMT_STRING("TBINDING{} uniform sampler2D envBumpMap;"), nextTex++); if (info.m_hasLightmap) - fmt::print(out, fmt("TBINDING{} uniform sampler2D lightMap;"), nextTex++); + fmt::print(out, FMT_STRING("TBINDING{} uniform sampler2D lightMap;"), nextTex++); out << '\n'; if (info.m_hasBumpMap) @@ -362,7 +362,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { case EFluidType::PhazonFluid: case EFluidType::Four: if (info.m_hasLightmap) { - fmt::print(out, fmt("vec4 lightMapTexel = texture(lightMap, vtf.uvs[{}]);"), lightmapUv); + fmt::print(out, FMT_STRING("vec4 lightMapTexel = texture(lightMap, vtf.uvs[{}]);"), lightmapUv); // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS // Output reg 2 @@ -407,7 +407,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) { // Make previous stage indirect, mtx0 - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "vec2 indUvs = (texture(envBumpMap, vtf.uvs[{}]).ra - vec2(0.5, 0.5)) * " "vec2(fog.indScale, -fog.indScale);"), envBumpMapUv); @@ -421,11 +421,11 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { // Make previous stage indirect, mtx0 if (info.m_hasColorTex) out << "colorOut += texture(colorTex, vtf.uvs[2]) * lighting;"; - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "vec2 indUvs = (texture(envBumpMap, vtf.uvs[{}]).ra - vec2(0.5, 0.5)) * " "vec2(fog.indScale, -fog.indScale);"), envBumpMapUv); - fmt::print(out, fmt("colorOut = mix(colorOut, texture(envMap, indUvs + vtf.uvs[{}]), kColor1);"), envMapUv); + fmt::print(out, FMT_STRING("colorOut = mix(colorOut, texture(envMap, indUvs + vtf.uvs[{}]), kColor1);"), envMapUv); } else if (info.m_hasColorTex) { out << "colorOut += texture(colorTex, vtf.uvs[2]) * lighting;"; } @@ -434,7 +434,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { case EFluidType::PoisonWater: if (info.m_hasLightmap) { - fmt::print(out, fmt("vec4 lightMapTexel = texture(lightMap, vtf.uvs[{}]);"), lightmapUv); + fmt::print(out, FMT_STRING("vec4 lightMapTexel = texture(lightMap, vtf.uvs[{}]);"), lightmapUv); // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS // Output reg 2 @@ -480,7 +480,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { if (info.m_hasColorTex) { if (info.m_hasEnvBumpMap) { // Make previous stage indirect, mtx0 - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "vec2 indUvs = (texture(envBumpMap, vtf.uvs[{}]).ra - vec2(0.5, 0.5)) * " "vec2(fog.indScale, -fog.indScale);"), envBumpMapUv); @@ -534,7 +534,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { "vec3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;" "float lx = dot(vtf.mvTangent.xyz, lightVec);" "float ly = dot(vtf.mvBinorm.xyz, lightVec);"; - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "vec4 emboss1 = texture(bumpMap, vtf.uvs[{}]) + vec4(0.5);" "vec4 emboss2 = texture(bumpMap, vtf.uvs[{}] + vec2(lx, ly));"), bumpMapUv, bumpMapUv); @@ -582,7 +582,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { // 3: bumpMapTCG, bumpMap, NULL // ZERO, TEX, PREV, ZERO // Output reg prev, scale 2 - fmt::print(out, fmt("vec4 emboss1 = texture(bumpMap, vtf.uvs[{}]) + vec4(0.5);"), bumpMapUv); + fmt::print(out, FMT_STRING("vec4 emboss1 = texture(bumpMap, vtf.uvs[{}]) + vec4(0.5);"), bumpMapUv); out << "colorOut *= emboss1 * vec4(2.0);"; } @@ -602,13 +602,13 @@ static void _BuildAdditionalTCGs(std::stringstream& out, const SFluidPlaneShader out << "#define ADDITIONAL_TCGS "; if (info.m_hasBumpMap) - fmt::print(out, fmt("vtf.uvs[{}] = (texMtxs[0] * pos).xy;"), nextTCG++); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = (texMtxs[0] * pos).xy;"), nextTCG++); if (info.m_hasEnvBumpMap) - fmt::print(out, fmt("vtf.uvs[{}] = (texMtxs[3] * vec4(normalIn.xyz, 1.0)).xy;"), nextTCG++); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = (texMtxs[3] * vec4(normalIn.xyz, 1.0)).xy;"), nextTCG++); if (info.m_hasEnvMap) - fmt::print(out, fmt("vtf.uvs[{}] = (texMtxs[{}] * pos).xy;"), nextTCG++, nextMtx++); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = (texMtxs[{}] * pos).xy;"), nextTCG++, nextMtx++); if (info.m_hasLightmap) - fmt::print(out, fmt("vtf.uvs[{}] = (texMtxs[{}] * pos).xy;"), nextTCG, nextMtx); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = (texMtxs[{}] * pos).xy;"), nextTCG, nextMtx); out << '\n'; } @@ -721,11 +721,11 @@ static std::string _BuildFS(const SFluidPlaneDoorShaderInfo& info) { out << "#define TEXTURE_DECLS "; if (info.m_hasPatternTex1) - fmt::print(out, fmt("TBINDING{} uniform sampler2D patternTex1;"), nextTex++); + fmt::print(out, FMT_STRING("TBINDING{} uniform sampler2D patternTex1;"), nextTex++); if (info.m_hasPatternTex2) - fmt::print(out, fmt("TBINDING{} uniform sampler2D patternTex2;"), nextTex++); + fmt::print(out, FMT_STRING("TBINDING{} uniform sampler2D patternTex2;"), nextTex++); if (info.m_hasColorTex) - fmt::print(out, fmt("TBINDING{} uniform sampler2D colorTex;"), nextTex++); + fmt::print(out, FMT_STRING("TBINDING{} uniform sampler2D colorTex;"), nextTex++); out << '\n'; // Tex0 * kColor0 * Tex1 + Tex2 diff --git a/Shaders/shader_CFluidPlaneShaderHLSL.cpp b/Shaders/shader_CFluidPlaneShaderHLSL.cpp index 32eff6cae..ebf81e869 100644 --- a/Shaders/shader_CFluidPlaneShaderHLSL.cpp +++ b/Shaders/shader_CFluidPlaneShaderHLSL.cpp @@ -368,37 +368,37 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { out << "#define TEXTURE_DECLS "; if (info.m_hasPatternTex1) - fmt::print(out, fmt("Texture2D patternTex1 : register(t{});"), nextTex++); + fmt::print(out, FMT_STRING("Texture2D patternTex1 : register(t{});"), nextTex++); if (info.m_hasPatternTex2) - fmt::print(out, fmt("Texture2D patternTex2 : register(t{});"), nextTex++); + fmt::print(out, FMT_STRING("Texture2D patternTex2 : register(t{});"), nextTex++); if (info.m_hasColorTex) - fmt::print(out, fmt("Texture2D colorTex : register(t{});"), nextTex++); + fmt::print(out, FMT_STRING("Texture2D colorTex : register(t{});"), nextTex++); if (info.m_hasBumpMap) - fmt::print(out, fmt("Texture2D bumpMap : register(t{});"), nextTex++); + fmt::print(out, FMT_STRING("Texture2D bumpMap : register(t{});"), nextTex++); if (info.m_hasEnvMap) - fmt::print(out, fmt("Texture2D envMap : register(t{});"), nextTex++); + fmt::print(out, FMT_STRING("Texture2D envMap : register(t{});"), nextTex++); if (info.m_hasEnvBumpMap) - fmt::print(out, fmt("Texture2D envBumpMap : register(t{});"), nextTex++); + fmt::print(out, FMT_STRING("Texture2D envBumpMap : register(t{});"), nextTex++); if (info.m_hasLightmap) - fmt::print(out, fmt("Texture2D lightMap : register(t{});"), nextTex++); + fmt::print(out, FMT_STRING("Texture2D lightMap : register(t{});"), nextTex++); out << '\n'; out << "#define ADDITIONAL_TCGS "; if (info.m_hasBumpMap) { bumpMapUv = nextTCG; - fmt::print(out, fmt("vtf.uvs[{}] = mul(texMtxs[0], pos).xy;"), nextTCG++); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = mul(texMtxs[0], pos).xy;"), nextTCG++); } if (info.m_hasEnvBumpMap) { envBumpMapUv = nextTCG; - fmt::print(out, fmt("vtf.uvs[{}] = mul(texMtxs[3], float4(normalIn.xyz, 1.0)).xy;"), nextTCG++); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = mul(texMtxs[3], float4(normalIn.xyz, 1.0)).xy;"), nextTCG++); } if (info.m_hasEnvMap) { envMapUv = nextTCG; - fmt::print(out, fmt("vtf.uvs[{}] = mul(texMtxs[{}], pos).xy;"), nextTCG++, nextMtx++); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = mul(texMtxs[{}], pos).xy;"), nextTCG++, nextMtx++); } if (info.m_hasLightmap) { lightmapUv = nextTCG; - fmt::print(out, fmt("vtf.uvs[{}] = mul(texMtxs[{}], pos).xy;"), nextTCG++, nextMtx++); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = mul(texMtxs[{}], pos).xy;"), nextTCG++, nextMtx++); } out << '\n'; @@ -408,7 +408,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { case EFluidType::PhazonFluid: case EFluidType::Four: if (info.m_hasLightmap) { - fmt::print(out, fmt("float4 lightMapTexel = lightMap.Sample(samp, vtf.uvs[{}]);"), lightmapUv); + fmt::print(out, FMT_STRING("float4 lightMapTexel = lightMap.Sample(samp, vtf.uvs[{}]);"), lightmapUv); // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS // Output reg 2 @@ -453,7 +453,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) { // Make previous stage indirect, mtx0 - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[{}]).ra - float2(0.5, 0.5)) * " "float2(fog.indScale, -fog.indScale);"), envBumpMapUv); @@ -467,11 +467,11 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { // Make previous stage indirect, mtx0 if (info.m_hasColorTex) out << "colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;"; - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[{}]).ra - float2(0.5, 0.5)) * " "float2(fog.indScale, -fog.indScale);"), envBumpMapUv); - fmt::print(out, fmt("colorOut = lerp(colorOut, envMap.Sample(samp, indUvs + vtf.uvs[{}]), kColor1);"), envMapUv); + fmt::print(out, FMT_STRING("colorOut = lerp(colorOut, envMap.Sample(samp, indUvs + vtf.uvs[{}]), kColor1);"), envMapUv); } else if (info.m_hasColorTex) { out << "colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;"; } @@ -480,7 +480,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { case EFluidType::PoisonWater: if (info.m_hasLightmap) { - fmt::print(out, fmt("float4 lightMapTexel = lightMap.Sample(samp, vtf.uvs[{}]);"), lightmapUv); + fmt::print(out, FMT_STRING("float4 lightMapTexel = lightMap.Sample(samp, vtf.uvs[{}]);"), lightmapUv); // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS // Output reg 2 @@ -526,7 +526,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { if (info.m_hasColorTex) { if (info.m_hasEnvBumpMap) { // Make previous stage indirect, mtx0 - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[{}]).ra - float2(0.5, 0.5)) * " "float2(fog.indScale, -fog.indScale);"), envBumpMapUv); @@ -580,7 +580,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { "float3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;" "float lx = dot(vtf.mvTangent.xyz, lightVec);" "float ly = dot(vtf.mvBinorm.xyz, lightVec);"; - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "float4 emboss1 = bumpMap.Sample(samp, vtf.uvs[{}]) + float4(0.5);" "float4 emboss2 = bumpMap.Sample(samp, vtf.uvs[{}] + float2(lx, ly));"), bumpMapUv, bumpMapUv); @@ -628,7 +628,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { // 3: bumpMapTCG, bumpMap, NULL // ZERO, TEX, PREV, ZERO // Output reg prev, scale 2 - fmt::print(out, fmt("float4 emboss1 = bumpMap.Sample(samp, vtf.uvs[{}]) + float4(0.5);"), bumpMapUv); + fmt::print(out, FMT_STRING("float4 emboss1 = bumpMap.Sample(samp, vtf.uvs[{}]) + float4(0.5);"), bumpMapUv); out << "colorOut *= emboss1 * float4(2.0);"; } @@ -648,13 +648,13 @@ static void _BuildAdditionalTCGs(std::stringstream& out, const SFluidPlaneShader out << "#define ADDITIONAL_TCGS "; if (info.m_hasBumpMap) - fmt::print(out, fmt("vtf.uvs[{}] = mul(texMtxs[0], pos).xy;"), nextTCG++); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = mul(texMtxs[0], pos).xy;"), nextTCG++); if (info.m_hasEnvBumpMap) - fmt::print(out, fmt("vtf.uvs[{}] = mul(texMtxs[3], float4(normalIn.xyz, 1.0)).xy;"), nextTCG++); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = mul(texMtxs[3], float4(normalIn.xyz, 1.0)).xy;"), nextTCG++); if (info.m_hasEnvMap) - fmt::print(out, fmt("vtf.uvs[{}] = mul(texMtxs[{}], pos).xy;"), nextTCG++, nextMtx++); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = mul(texMtxs[{}], pos).xy;"), nextTCG++, nextMtx++); if (info.m_hasLightmap) - fmt::print(out, fmt("vtf.uvs[{}] = mul(texMtxs[{}], pos).xy;"), nextTCG, nextMtx); + fmt::print(out, FMT_STRING("vtf.uvs[{}] = mul(texMtxs[{}], pos).xy;"), nextTCG, nextMtx); out << '\n'; } @@ -727,11 +727,11 @@ static std::string _BuildFS(const SFluidPlaneDoorShaderInfo& info) { out << "#define TEXTURE_DECLS "; if (info.m_hasPatternTex1) - fmt::print(out, fmt("Texture2D patternTex1 : register(t{});"), nextTex++); + fmt::print(out, FMT_STRING("Texture2D patternTex1 : register(t{});"), nextTex++); if (info.m_hasPatternTex2) - fmt::print(out, fmt("Texture2D patternTex2 : register(t{});"), nextTex++); + fmt::print(out, FMT_STRING("Texture2D patternTex2 : register(t{});"), nextTex++); if (info.m_hasColorTex) - fmt::print(out, fmt("Texture2D colorTex : register(t{});"), nextTex++); + fmt::print(out, FMT_STRING("Texture2D colorTex : register(t{});"), nextTex++); out << '\n'; // Tex0 * kColor0 * Tex1 + Tex2 diff --git a/Shaders/shader_CFluidPlaneShaderMetal.cpp b/Shaders/shader_CFluidPlaneShaderMetal.cpp index cc988a511..f8bda5069 100644 --- a/Shaders/shader_CFluidPlaneShaderMetal.cpp +++ b/Shaders/shader_CFluidPlaneShaderMetal.cpp @@ -366,19 +366,19 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { out << "#define TEXTURE_PARAMS "; if (info.m_hasPatternTex1) - fmt::print(out, fmt(",texture2d patternTex1 [[ texture({}) ]]"), nextTex++); + fmt::print(out, FMT_STRING(",texture2d patternTex1 [[ texture({}) ]]"), nextTex++); if (info.m_hasPatternTex2) - fmt::print(out, fmt(",texture2d patternTex2 [[ texture({}) ]]"), nextTex++); + fmt::print(out, FMT_STRING(",texture2d patternTex2 [[ texture({}) ]]"), nextTex++); if (info.m_hasColorTex) - fmt::print(out, fmt(",texture2d colorTex [[ texture({}) ]]"), nextTex++); + fmt::print(out, FMT_STRING(",texture2d colorTex [[ texture({}) ]]"), nextTex++); if (info.m_hasBumpMap) - fmt::print(out, fmt(",texture2d bumpMap [[ texture({}) ]]"), nextTex++); + fmt::print(out, FMT_STRING(",texture2d bumpMap [[ texture({}) ]]"), nextTex++); if (info.m_hasEnvMap) - fmt::print(out, fmt(",texture2d envMap [[ texture({}) ]]"), nextTex++); + fmt::print(out, FMT_STRING(",texture2d envMap [[ texture({}) ]]"), nextTex++); if (info.m_hasEnvBumpMap) - fmt::print(out, fmt(",exture2d envBumpMap [[ texture({}) ]]"), nextTex++); + fmt::print(out, FMT_STRING(",exture2d envBumpMap [[ texture({}) ]]"), nextTex++); if (info.m_hasLightmap) - fmt::print(out, fmt(",texture2d lightMap [[ texture({}) ]]"), nextTex++); + fmt::print(out, FMT_STRING(",texture2d lightMap [[ texture({}) ]]"), nextTex++); out << '\n'; if (info.m_hasBumpMap) { @@ -400,7 +400,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { case EFluidType::PhazonFluid: case EFluidType::Four: if (info.m_hasLightmap) { - fmt::print(out, fmt("float4 lightMapTexel = lightMap.sample(samp, vtf.uv{});"), lightmapUv); + fmt::print(out, FMT_STRING("float4 lightMapTexel = lightMap.sample(samp, vtf.uv{});"), lightmapUv); // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS // Output reg 2 @@ -445,7 +445,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) { // Make previous stage indirect, mtx0 - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "float2 indUvs = (envBumpMap.sample(samp, vtf.uv{}).ra - float2(0.5, 0.5)) * " "float2(lu.fog.indScale, -lu.fog.indScale);"), envBumpMapUv); @@ -459,11 +459,11 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { // Make previous stage indirect, mtx0 if (info.m_hasColorTex) out << "colorOut += colorTex.sample(samp, vtf.uv2) * lighting;"; - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "float2 indUvs = (envBumpMap.sample(samp, vtf.uv{}).ra - float2(0.5, 0.5)) * " "float2(lu.fog.indScale, -lu.fog.indScale);"), envBumpMapUv); - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "colorOut = mix(colorOut, envMap.sample(samp, indUvs + vtf.uv{}), lu.kColor1);"), envMapUv); } else if (info.m_hasColorTex) { out << "colorOut += colorTex.sample(samp, vtf.uv2) * lighting;"; @@ -473,7 +473,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { case EFluidType::PoisonWater: if (info.m_hasLightmap) { - fmt::print(out, fmt("float4 lightMapTexel = lightMap.sample(samp, vtf.uv{});"), lightmapUv); + fmt::print(out, FMT_STRING("float4 lightMapTexel = lightMap.sample(samp, vtf.uv{});"), lightmapUv); // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS // Output reg 2 @@ -519,7 +519,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { if (info.m_hasColorTex) { if (info.m_hasEnvBumpMap) { // Make previous stage indirect, mtx0 - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "float2 indUvs = (envBumpMap.sample(samp, vtf.uv{}).ra - float2(0.5, 0.5)) * " "float2(lu.fog.indScale, -lu.fog.indScale);"), envBumpMapUv); @@ -573,7 +573,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { "float3 lightVec = lu.lights[3].pos.xyz - vtf.mvPos.xyz;" "float lx = dot(vtf.mvTangent.xyz, lightVec);" "float ly = dot(vtf.mvBinorm.xyz, lightVec);"; - fmt::print(out, fmt( + fmt::print(out, FMT_STRING( "float4 emboss1 = bumpMap.sample(samp, vtf.uv{}) + float4(0.5);" "float4 emboss2 = bumpMap.sample(samp, vtf.uv{} + float2(lx, ly));"), bumpMapUv, bumpMapUv); @@ -621,7 +621,7 @@ static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { // 3: bumpMapTCG, bumpMap, NULL // ZERO, TEX, PREV, ZERO // Output reg prev, scale 2 - fmt::print(out, fmt("float4 emboss1 = bumpMap.sample(samp, vtf.uv{}) + float4(0.5);"), bumpMapUv); + fmt::print(out, FMT_STRING("float4 emboss1 = bumpMap.sample(samp, vtf.uv{}) + float4(0.5);"), bumpMapUv); out << "colorOut *= emboss1 * float4(2.0);"; } @@ -641,13 +641,13 @@ static void _BuildAdditionalTCGs(std::stringstream& out, const SFluidPlaneShader out << "#define ADDITIONAL_TCGS "; if (info.m_hasBumpMap) - fmt::print(out, fmt("vtf.uv{} = (fu.texMtxs[0] * pos).xy;"), nextTCG++); + fmt::print(out, FMT_STRING("vtf.uv{} = (fu.texMtxs[0] * pos).xy;"), nextTCG++); if (info.m_hasEnvBumpMap) - fmt::print(out, fmt("vtf.uv{} = (fu.texMtxs[3] * float4(normalIn.xyz, 1.0)).xy;"), nextTCG++); + fmt::print(out, FMT_STRING("vtf.uv{} = (fu.texMtxs[3] * float4(normalIn.xyz, 1.0)).xy;"), nextTCG++); if (info.m_hasEnvMap) - fmt::print(out, fmt("vtf.uv{} = (fu.texMtxs[{}] * pos).xy;"), nextTCG++, nextMtx++); + fmt::print(out, FMT_STRING("vtf.uv{} = (fu.texMtxs[{}] * pos).xy;"), nextTCG++, nextMtx++); if (info.m_hasLightmap) - fmt::print(out, fmt("vtf.uv{} = (fu.texMtxs[{}] * pos).xy;"), nextTCG++, nextMtx++); + fmt::print(out, FMT_STRING("vtf.uv{} = (fu.texMtxs[{}] * pos).xy;"), nextTCG++, nextMtx++); out << '\n'; } @@ -718,11 +718,11 @@ static std::string _BuildFS(const SFluidPlaneDoorShaderInfo& info) { out << "#define TEXTURE_PARAMS "; if (info.m_hasPatternTex1) - fmt::print(out, fmt(",texture2d patternTex1 [[ texture({}) ]]"), nextTex++); + fmt::print(out, FMT_STRING(",texture2d patternTex1 [[ texture({}) ]]"), nextTex++); if (info.m_hasPatternTex2) - fmt::print(out, fmt(",texture2d patternTex2 [[ texture({}) ]]"), nextTex++); + fmt::print(out, FMT_STRING(",texture2d patternTex2 [[ texture({}) ]]"), nextTex++); if (info.m_hasColorTex) - fmt::print(out, fmt(",texture2d colorTex [[ texture({}) ]]"), nextTex++); + fmt::print(out, FMT_STRING(",texture2d colorTex [[ texture({}) ]]"), nextTex++); out << '\n'; // Tex0 * kColor0 * Tex1 + Tex2 diff --git a/amuse b/amuse index 9c75aeccb..5112228ab 160000 --- a/amuse +++ b/amuse @@ -1 +1 @@ -Subproject commit 9c75aeccbec4d344b9481bc3c312a50241f5ecb1 +Subproject commit 5112228abd4d2a468f36ee4289a789fb2c2a921c diff --git a/assetnameparser/main.cpp b/assetnameparser/main.cpp index 7f4eaa0c1..839488da3 100644 --- a/assetnameparser/main.cpp +++ b/assetnameparser/main.cpp @@ -180,7 +180,7 @@ int main(int argc, const char* argv[]) logvisor::RegisterStandardExceptions(); logvisor::RegisterConsoleLogger(); if (argc < 3) { - Log.report(logvisor::Error, fmt(_SYS_STR("Usage: {} ")), argv[0]); + Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Usage: {} ")), argv[0]); return 1; } @@ -193,13 +193,13 @@ int main(int argc, const char* argv[]) if (!doc.LoadFile(docF)) { const tinyxml2::XMLElement* elm = doc.RootElement(); if (strcmp(elm->Name(), "AssetNameMap")) { - Log.report(logvisor::Fatal, fmt(_SYS_STR("Invalid database supplied"))); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Invalid database supplied"))); return 1; } elm = elm->FirstChildElement("AssetNameMap"); if (elm == nullptr) { - Log.report(logvisor::Fatal, fmt(_SYS_STR("Malformed AssetName database"))); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Malformed AssetName database"))); return 1; } @@ -210,7 +210,7 @@ int main(int argc, const char* argv[]) const tinyxml2::XMLElement* valueElm = elm->FirstChildElement("Value"); if (!keyElm || !valueElm) { - Log.report(logvisor::Fatal, fmt(_SYS_STR("Malformed Asset entry, [Key,Value] required"))); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Malformed Asset entry, [Key,Value] required"))); return 0; } @@ -219,7 +219,7 @@ int main(int argc, const char* argv[]) const tinyxml2::XMLElement* typeElm = valueElm->FirstChildElement("Type"); if (!nameElm || !dirElm || !typeElm) { - Log.report(logvisor::Fatal, fmt(_SYS_STR("Malformed Value entry, [Name,Directory,Type] required"))); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Malformed Value entry, [Name,Directory,Type] required"))); return 0; } assets.emplace_back(); @@ -233,7 +233,7 @@ int main(int argc, const char* argv[]) FILE* f = Fopen(outPath.c_str(), _SYS_STR("wb")); if (!f) { - Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to open destination"))); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to open destination"))); return 0; } @@ -261,6 +261,6 @@ int main(int argc, const char* argv[]) if (docF) fclose(docF); - Log.report(logvisor::Fatal, fmt(_SYS_STR("failed to load"))); + Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("failed to load"))); return 1; } diff --git a/assets/urde-screen1.png b/assets/urde-screen1.png new file mode 100644 index 000000000..92de9dcea Binary files /dev/null and b/assets/urde-screen1.png differ diff --git a/hecl b/hecl index 0b42de34d..95ac3ef77 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 0b42de34d0439ed46e393e0bb6de1b02641399a1 +Subproject commit 95ac3ef77c8a5dfe70f498fdffea5fe92091bd73 diff --git a/hecl-gui b/hecl-gui index db38d19ac..c66d33b0b 160000 --- a/hecl-gui +++ b/hecl-gui @@ -1 +1 @@ -Subproject commit db38d19ac3ed624f4e55fb071c177db4feed3ce0 +Subproject commit c66d33b0b2fca695c39d1c0c829489ba67a52f47 diff --git a/jbus b/jbus index d72163ad2..b8e1e4673 160000 --- a/jbus +++ b/jbus @@ -1 +1 @@ -Subproject commit d72163ad27c4a8b4d993e1a29d758a3548d92bed +Subproject commit b8e1e4673e66d45876d87439faf463a7301ee05c diff --git a/kabufuda b/kabufuda index 35e5c7c90..4891a9568 160000 --- a/kabufuda +++ b/kabufuda @@ -1 +1 @@ -Subproject commit 35e5c7c90f9d368f29ab191a005d30f91774e50e +Subproject commit 4891a9568856bb775d0889b47c3808880803423b diff --git a/nod b/nod index f147e1235..2783337c3 160000 --- a/nod +++ b/nod @@ -1 +1 @@ -Subproject commit f147e1235646b849f78a8574a6d554214b70792d +Subproject commit 2783337c36bacdf832f78182340e4aa6063dece9 diff --git a/specter b/specter index 27eb476b0..fc0d79ace 160000 --- a/specter +++ b/specter @@ -1 +1 @@ -Subproject commit 27eb476b05efeb1b94329eb85f36a1fd83858870 +Subproject commit fc0d79ace7063f24efaeaf8153753855eb3e2b95 diff --git a/visigen/CMakeLists.txt b/visigen/CMakeLists.txt index da13fffd9..f38393310 100644 --- a/visigen/CMakeLists.txt +++ b/visigen/CMakeLists.txt @@ -2,8 +2,10 @@ if(NOT WINDOWS_STORE) cmake_minimum_required(VERSION 3.10 FATAL_ERROR) # because of c++17 project(visigen) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) +if (NOT MSVC) + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() add_executable(visigen diff --git a/visigen/MainMac.mm b/visigen/MainMac.mm index ddd0cb276..aba699c1a 100644 --- a/visigen/MainMac.mm +++ b/visigen/MainMac.mm @@ -113,7 +113,7 @@ int main(int argc, const char** argv) { if (argc > 1 && !strcmp(argv[1], "--dlpackage")) { - fmt::print(fmt("{}\n"), URDE_DLPACKAGE); + fmt::print(FMT_STRING("{}\n"), URDE_DLPACKAGE); return 100; } diff --git a/visigen/MainWin.cpp b/visigen/MainWin.cpp index fe347a85c..34ce7cd5a 100644 --- a/visigen/MainWin.cpp +++ b/visigen/MainWin.cpp @@ -41,7 +41,7 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l int wmain(int argc, const hecl::SystemChar** argv) { if (argc > 1 && !wcscmp(argv[1], L"--dlpackage")) { - fmt::print(fmt("{}\n"), URDE_DLPACKAGE); + fmt::print(FMT_STRING("{}\n"), URDE_DLPACKAGE); return 100; } @@ -125,7 +125,7 @@ int wmain(int argc, const hecl::SystemChar** argv) { continue; case WM_USER + 1: { /* Update window title from client thread */ - std::wstring title = fmt::format(fmt(L"VISIGen [{:g}%]"), s_Percent * 100.f); + std::wstring title = fmt::format(FMT_STRING(L"VISIGen [{:g}%]"), s_Percent * 100.f); SetWindowTextW(window, title.c_str()); continue; } diff --git a/visigen/MainXlib.cpp b/visigen/MainXlib.cpp index 333d3920d..90a3a04f4 100644 --- a/visigen/MainXlib.cpp +++ b/visigen/MainXlib.cpp @@ -64,7 +64,7 @@ static Window windowId; static void UpdatePercent(float percent) { XLockDisplay(xDisp); - std::string title = fmt::format(fmt("VISIGen [{:g}%]"), double(percent * 100.f)); + std::string title = fmt::format(FMT_STRING("VISIGen [{:g}%]"), double(percent * 100.f)); XChangeProperty(xDisp, windowId, XA_WM_NAME, XA_STRING, 8, PropModeReplace, reinterpret_cast(title.c_str()), int(title.size())); XUnlockDisplay(xDisp); @@ -75,7 +75,7 @@ static void _sigint(int) {} int main(int argc, const char** argv) { if (argc > 1 && !strcmp(argv[1], "--dlpackage")) { - fmt::print(fmt("{}\n"), URDE_DLPACKAGE); + fmt::print(FMT_STRING("{}\n"), URDE_DLPACKAGE); return 100; } @@ -88,14 +88,14 @@ int main(int argc, const char** argv) { VISIRenderer renderer(argc, argv); if (!XInitThreads()) { - Log.report(logvisor::Error, fmt("X doesn't support multithreading")); + Log.report(logvisor::Error, FMT_STRING("X doesn't support multithreading")); return 1; } /* Open Xlib Display */ xDisp = XOpenDisplay(nullptr); if (!xDisp) { - Log.report(logvisor::Error, fmt("Can't open X display")); + Log.report(logvisor::Error, FMT_STRING("Can't open X display")); return 1; } @@ -108,7 +108,7 @@ int main(int argc, const char** argv) { int numFBConfigs = 0; fbConfigs = glXGetFBConfigs(xDisp, xDefaultScreen, &numFBConfigs); if (!fbConfigs || numFBConfigs == 0) { - Log.report(logvisor::Error, fmt("glXGetFBConfigs failed")); + Log.report(logvisor::Error, FMT_STRING("glXGetFBConfigs failed")); return 1; } @@ -135,7 +135,7 @@ int main(int argc, const char** argv) { XFree(fbConfigs); if (!selFBConfig) { - Log.report(logvisor::Error, fmt("unable to find suitable pixel format")); + Log.report(logvisor::Error, FMT_STRING("unable to find suitable pixel format")); return 1; } @@ -179,7 +179,7 @@ int main(int argc, const char** argv) { glXCreateContextAttribsARB = reinterpret_cast( glXGetProcAddressARB(reinterpret_cast("glXCreateContextAttribsARB"))); if (!glXCreateContextAttribsARB) { - Log.report(logvisor::Error, fmt("unable to resolve glXCreateContextAttribsARB")); + Log.report(logvisor::Error, FMT_STRING("unable to resolve glXCreateContextAttribsARB")); return 1; } } @@ -194,12 +194,12 @@ int main(int argc, const char** argv) { } XSetErrorHandler(oldHandler); if (!glxCtx) { - Log.report(logvisor::Fatal, fmt("unable to make new GLX context")); + Log.report(logvisor::Fatal, FMT_STRING("unable to make new GLX context")); return 1; } GLXWindow glxWindow = glXCreateWindow(xDisp, selFBConfig, windowId, nullptr); if (!glxWindow) { - Log.report(logvisor::Fatal, fmt("unable to make new GLX window")); + Log.report(logvisor::Fatal, FMT_STRING("unable to make new GLX window")); return 1; } @@ -251,7 +251,7 @@ int main(int argc, const char** argv) { XLockDisplay(xDisp); if (!glXMakeContextCurrent(xDisp, glxWindow, glxWindow, glxCtx)) - Log.report(logvisor::Fatal, fmt("unable to make GLX context current")); + Log.report(logvisor::Fatal, FMT_STRING("unable to make GLX context current")); XUnlockDisplay(xDisp); UpdatePercent(0); diff --git a/visigen/VISIBuilder.cpp b/visigen/VISIBuilder.cpp index 3aa472f87..b9a90effe 100644 --- a/visigen/VISIBuilder.cpp +++ b/visigen/VISIBuilder.cpp @@ -18,11 +18,11 @@ static std::unique_ptr RGBABuf(new VISIRenderer::RGBA8[25 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, fmt("Cache hit")); + // Log.report(logvisor::Info, FMT_STRING("Cache hit")); return *search->second; } - // Log.report(logvisor::Info, fmt("Rendering")); + // Log.report(logvisor::Info, FMT_STRING("Rendering")); bool needsTransparent = false; m_renderer.RenderPVSOpaque(RGBABuf.get(), vec, needsTransparent); std::unique_ptr leafOut = std::make_unique(); @@ -107,19 +107,19 @@ void VISIBuilder::Node::buildChildren(int level, int divisions, const zeus::CAAB 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, fmt("Unsub Z")); + // Log.report(logvisor::Info, FMT_STRING("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, fmt("Unsub Y")); + // Log.report(logvisor::Info, FMT_STRING("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, fmt("Unsub X")); + // Log.report(logvisor::Info, FMT_STRING("Unsub X")); continue; } break; @@ -129,7 +129,7 @@ void VISIBuilder::Node::buildChildren(int level, int divisions, const zeus::CAAB // This is now a leaf node for (int i = 0; i < 8; ++i) leaf |= childNodes[i].leaf; - // Log.report(logvisor::Info, fmt("Leaf Promote")); + // Log.report(logvisor::Info, FMT_STRING("Leaf Promote")); return; } } @@ -258,7 +258,7 @@ std::vector VISIBuilder::build(const zeus::CAABox& fullAabb, size_t mod const std::vector& entities, const std::vector& lights, size_t layer2LightCount, FPercent updatePercent, ProcessType parentPid) { - // Log.report(logvisor::Info, fmt("Started!")); + // Log.report(logvisor::Info, FMT_STRING("Started!")); size_t featureCount = modelCount + entities.size(); renderCache.m_lightMetaBit = featureCount; @@ -322,6 +322,6 @@ std::vector VISIBuilder::build(const zeus::CAABox& fullAabb, size_t mod w.seekAlign32(); - // Log.report(logvisor::Info, fmt("Finished!")); + // Log.report(logvisor::Info, FMT_STRING("Finished!")); return dataOut; } diff --git a/visigen/VISIRenderer.cpp b/visigen/VISIRenderer.cpp index 95cb38262..a95463e27 100644 --- a/visigen/VISIRenderer.cpp +++ b/visigen/VISIRenderer.cpp @@ -59,7 +59,7 @@ bool VISIRenderer::SetupShaders() { glGetShaderiv(m_vtxShader, GL_INFO_LOG_LENGTH, &logLen); char* log = (char*)malloc(logLen); glGetShaderInfoLog(m_vtxShader, logLen, nullptr, log); - Log.report(logvisor::Error, fmt("unable to compile vert source\n{}\n{}\n"), log, VS); + Log.report(logvisor::Error, FMT_STRING("unable to compile vert source\n{}\n{}\n"), log, VS); free(log); return false; } @@ -72,7 +72,7 @@ bool VISIRenderer::SetupShaders() { glGetShaderiv(m_fragShader, GL_INFO_LOG_LENGTH, &logLen); char* log = (char*)malloc(logLen); glGetShaderInfoLog(m_fragShader, logLen, nullptr, log); - Log.report(logvisor::Error, fmt("unable to compile frag source\n{}\n{}\n"), log, FS); + Log.report(logvisor::Error, FMT_STRING("unable to compile frag source\n{}\n{}\n"), log, FS); free(log); return false; } @@ -87,7 +87,7 @@ bool VISIRenderer::SetupShaders() { glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &logLen); char* log = (char*)malloc(logLen); glGetProgramInfoLog(m_program, logLen, nullptr, log); - Log.report(logvisor::Error, fmt("unable to link shader program\n{}\n"), log); + Log.report(logvisor::Error, FMT_STRING("unable to link shader program\n{}\n"), log); free(log); return false; } @@ -414,13 +414,13 @@ void VISIRenderer::Run(FPercent updatePercent) { CalculateProjMatrix(); if (glewInit() != GLEW_OK) { - Log.report(logvisor::Error, fmt("unable to init glew")); + Log.report(logvisor::Error, FMT_STRING("unable to init glew")); m_return = 1; return; } if (!GLEW_ARB_occlusion_query2) { - Log.report(logvisor::Error, fmt("GL_ARB_occlusion_query2 extension not present")); + Log.report(logvisor::Error, FMT_STRING("GL_ARB_occlusion_query2 extension not present")); m_return = 1; return; } @@ -431,7 +431,7 @@ void VISIRenderer::Run(FPercent updatePercent) { } if (m_argc < 3) { - Log.report(logvisor::Error, fmt("Missing input/output file args")); + Log.report(logvisor::Error, FMT_STRING("Missing input/output file args")); m_return = 1; return; }