diff --git a/DataSpec/DNACommon/Tweaks/ITweakGunRes.hpp b/DataSpec/DNACommon/Tweaks/ITweakGunRes.hpp index def186cb7..912bfd56c 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakGunRes.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakGunRes.hpp @@ -3,6 +3,7 @@ #include "ITweak.hpp" #include "Runtime/IFactory.hpp" +#include "Runtime/CPlayerState.hpp" namespace DataSpec { @@ -10,14 +11,7 @@ namespace DataSpec struct ITweakGunRes : ITweak { using ResId = urde::CAssetId; - enum class EBeamId - { - Power, - Ice, - Wave, - Plasma, - Phazon - }; + using EBeamId = urde::CPlayerState::EBeamId; ResId x4_gunMotion; ResId x8_grappleArm; @@ -54,6 +48,7 @@ struct ITweakGunRes : ITweak b = 0; switch (EBeamId(b)) { + default: case EBeamId::Power: return x10_powerBeam; case EBeamId::Ice: diff --git a/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp b/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp index 4207baccd..a41d471dc 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp @@ -6,29 +6,32 @@ namespace DataSpec { +/* Same as CDamageInfo */ struct SShotParam : BigYAML { DECL_YAML - Value weaponType = -1; + Value weaponType = -1; + bool charged : 1; + bool combo : 1; + bool instaKill : 1; Value damage = 0.f; Value radiusDamage = 0.f; Value radius = 0.f; Value knockback = 0.f; - virtual bool Charged() const { return false; } - virtual bool Comboed() const { return false; } - virtual bool InstaKill() const { return false; } + bool noImmunity : 1; + SShotParam() { charged = false; combo = false; instaKill = false; noImmunity = false; } }; struct SComboShotParam : SShotParam { DECL_YAML - bool Comboed() const { return true; } + SComboShotParam() { combo = true; } }; struct SChargedShotParam : SShotParam { DECL_YAML - bool Charged() const { return true; } + SChargedShotParam() { charged = true; } }; struct SWeaponInfo : BigYAML diff --git a/Runtime/CPlayerState.hpp b/Runtime/CPlayerState.hpp index 15e21b7b5..67b1a6cdf 100644 --- a/Runtime/CPlayerState.hpp +++ b/Runtime/CPlayerState.hpp @@ -95,7 +95,8 @@ public: Ice, Wave, Plasma, - Phazon = 27 + Phazon, + Phazon2 = 27 }; private: diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index 2abeeee0e..5ec86e128 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -2314,7 +2314,7 @@ void CStateManager::UpdateRoomAcoustics(TAreaId aid) return; } - int idx = updateCount * x900_activeRandom->Float() * 0.99f; + auto idx = int(updateCount * x900_activeRandom->Float() * 0.99f); updates[idx]->EnableAuxCallbacks(); } diff --git a/Runtime/CStateManager.hpp b/Runtime/CStateManager.hpp index 567c9bba1..92b99a0ad 100644 --- a/Runtime/CStateManager.hpp +++ b/Runtime/CStateManager.hpp @@ -440,6 +440,7 @@ public: float GetThermalColdScale2() const { return xf28_thermColdScale2; } void SetThermalColdScale2(float s) { xf28_thermColdScale2 = s; } float IntegrateVisorFog(float f) const; + u32 GetUpdateFrameIndex() const { return x8d8_updateFrameIdx; } static float g_EscapeShakeCountdown; static bool g_EscapeShakeCountdownInit; diff --git a/Runtime/Camera/CCameraShakeData.cpp b/Runtime/Camera/CCameraShakeData.cpp index 1b7b406bd..92bfeacde 100644 --- a/Runtime/Camera/CCameraShakeData.cpp +++ b/Runtime/Camera/CCameraShakeData.cpp @@ -147,4 +147,9 @@ CCameraShakeData CCameraShakeData::LoadCameraShakeData(CInputStream& in) return {duration, 100.f, 0, zeus::CVector3f::skZero, shaker1, shaker2, shaker3}; } +const CCameraShakeData CCameraShakeData::skChargedCameraShakeData = + {0.3f, 100.f, 0, zeus::CVector3f::skZero, CCameraShakerComponent(), + CCameraShakerComponent(1, {0, 0.f, 0.f, 0.3f, -1.f}, {1, 0.f, 0.f, 0.05f, 0.3f}), + CCameraShakerComponent()}; + } diff --git a/Runtime/Camera/CCameraShakeData.hpp b/Runtime/Camera/CCameraShakeData.hpp index 99f953388..68ecd43d7 100644 --- a/Runtime/Camera/CCameraShakeData.hpp +++ b/Runtime/Camera/CCameraShakeData.hpp @@ -51,6 +51,7 @@ class CCameraShakeData float xd0_f2; public: + static const CCameraShakeData skChargedCameraShakeData; CCameraShakeData(float duration, float f2, u32 w1, const zeus::CVector3f& sfxPos, const CCameraShakerComponent& shaker1, const CCameraShakerComponent& shaker2, const CCameraShakerComponent& shaker3); diff --git a/Runtime/Character/CModelData.cpp b/Runtime/Character/CModelData.cpp index e6810a4ae..4ef71b5f3 100644 --- a/Runtime/Character/CModelData.cpp +++ b/Runtime/Character/CModelData.cpp @@ -54,6 +54,33 @@ void CModelData::Render(const CStateManager& stateMgr, const zeus::CTransform& x Render(GetRenderingModel(stateMgr), xf, lights, drawFlags); } +bool CModelData::IsLoaded(int shaderIdx) const +{ + if (x10_animData) + { + if (!x10_animData->xd8_modelData->GetModel()->IsLoaded(shaderIdx)) + return false; + if (const CSkinnedModel* model = x10_animData->xf4_xrayModel.get()) + if (!model->GetModel()->IsLoaded(shaderIdx)) + return false; + if (const CSkinnedModel* model = x10_animData->xf8_infraModel.get()) + if (!model->GetModel()->IsLoaded(shaderIdx)) + return false; + } + + if (const CModel* model = x1c_normalModel.GetObj()) + if (!model->IsLoaded(shaderIdx)) + return false; + if (const CModel* model = x2c_xrayModel.GetObj()) + if (!model->IsLoaded(shaderIdx)) + return false; + if (const CModel* model = x3c_infraModel.GetObj()) + if (!model->IsLoaded(shaderIdx)) + return false; + + return true; +} + CModelData::EWhichModel CModelData::GetRenderingModel(const CStateManager& stateMgr) { switch (stateMgr.GetPlayerState()->GetActiveVisor(stateMgr)) diff --git a/Runtime/Character/CModelData.hpp b/Runtime/Character/CModelData.hpp index a999c8d17..8dd84bb6b 100644 --- a/Runtime/Character/CModelData.hpp +++ b/Runtime/Character/CModelData.hpp @@ -111,6 +111,7 @@ public: SAdvancementDeltas GetAdvancementDeltas(const CCharAnimTime& a, const CCharAnimTime& b) const; void Render(const CStateManager& stateMgr, const zeus::CTransform& xf, const CActorLights* lights, const CModelFlags& drawFlags) const; + bool IsLoaded(int shaderIdx) const; static EWhichModel GetRenderingModel(const CStateManager& stateMgr); CSkinnedModel& PickAnimatedModel(EWhichModel which) const; const std::unique_ptr& PickStaticModel(EWhichModel which) const; diff --git a/Runtime/Graphics/Shaders/CElementGenShaders.cpp b/Runtime/Graphics/Shaders/CElementGenShaders.cpp index 772f76beb..23e28b718 100644 --- a/Runtime/Graphics/Shaders/CElementGenShaders.cpp +++ b/Runtime/Graphics/Shaders/CElementGenShaders.cpp @@ -12,6 +12,10 @@ boo::IShaderPipeline* CElementGenShaders::m_texAdditiveZTest = nullptr; boo::IShaderPipeline* CElementGenShaders::m_texAdditiveNoZTest = nullptr; boo::IShaderPipeline* CElementGenShaders::m_texRedToAlphaZTest = nullptr; boo::IShaderPipeline* CElementGenShaders::m_texRedToAlphaNoZTest = nullptr; +boo::IShaderPipeline* CElementGenShaders::m_texZTestNoZWriteSub = nullptr; +boo::IShaderPipeline* CElementGenShaders::m_texNoZTestNoZWriteSub = nullptr; +boo::IShaderPipeline* CElementGenShaders::m_texRedToAlphaZTestSub = nullptr; +boo::IShaderPipeline* CElementGenShaders::m_texRedToAlphaNoZTestSub = nullptr; boo::IShaderPipeline* CElementGenShaders::m_indTexZWrite = nullptr; boo::IShaderPipeline* CElementGenShaders::m_indTexNoZWrite = nullptr; @@ -51,7 +55,9 @@ void CElementGenShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Conte { CGenDescription* desc = gen.x1c_genDesc.GetObj(); boo::IShaderPipeline* regPipeline = nullptr; + boo::IShaderPipeline* regPipelineSub = nullptr; boo::IShaderPipeline* redToAlphaPipeline = nullptr; + boo::IShaderPipeline* redToAlphaPipelineSub = nullptr; boo::IShaderPipeline* regPipelinePmus = nullptr; boo::IShaderPipeline* redToAlphaPipelinePmus = nullptr; @@ -87,9 +93,17 @@ void CElementGenShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Conte else { if (gen.x26c_28_zTest) + { redToAlphaPipeline = m_texRedToAlphaZTest; + regPipelineSub = m_texZTestNoZWriteSub; + redToAlphaPipelineSub = m_texRedToAlphaZTestSub; + } else + { redToAlphaPipeline = m_texRedToAlphaNoZTest; + regPipelineSub = m_texNoZTestNoZWriteSub; + redToAlphaPipelineSub = m_texRedToAlphaNoZTestSub; + } if (gen.x26c_26_AAPH) { @@ -164,7 +178,7 @@ void CElementGenShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Conte } } - CElementGenShaders shad(gen, regPipeline, redToAlphaPipeline, + CElementGenShaders shad(gen, regPipeline, regPipelineSub, redToAlphaPipeline, redToAlphaPipelineSub, regPipelinePmus, redToAlphaPipelinePmus); TShader::BuildShaderDataBinding(ctx, shad); } diff --git a/Runtime/Graphics/Shaders/CElementGenShaders.hpp b/Runtime/Graphics/Shaders/CElementGenShaders.hpp index 813a76d2e..584389825 100644 --- a/Runtime/Graphics/Shaders/CElementGenShaders.hpp +++ b/Runtime/Graphics/Shaders/CElementGenShaders.hpp @@ -35,6 +35,10 @@ private: static boo::IShaderPipeline* m_texAdditiveNoZTest; static boo::IShaderPipeline* m_texRedToAlphaZTest; static boo::IShaderPipeline* m_texRedToAlphaNoZTest; + static boo::IShaderPipeline* m_texZTestNoZWriteSub; + static boo::IShaderPipeline* m_texNoZTestNoZWriteSub; + static boo::IShaderPipeline* m_texRedToAlphaZTestSub; + static boo::IShaderPipeline* m_texRedToAlphaNoZTestSub; static boo::IShaderPipeline* m_indTexZWrite; static boo::IShaderPipeline* m_indTexNoZWrite; @@ -57,15 +61,20 @@ private: CElementGen& m_gen; boo::IShaderPipeline* m_regPipeline; + boo::IShaderPipeline* m_regPipelineSub; boo::IShaderPipeline* m_redToAlphaPipeline; + boo::IShaderPipeline* m_redToAlphaPipelineSub; boo::IShaderPipeline* m_regPipelinePmus; boo::IShaderPipeline* m_redToAlphaPipelinePmus; CElementGenShaders(CElementGen& gen, boo::IShaderPipeline* regPipeline, + boo::IShaderPipeline* regPipelineSub, boo::IShaderPipeline* redToAlphaPipeline, + boo::IShaderPipeline* redToAlphaPipelineSub, boo::IShaderPipeline* regPipelinePmus, boo::IShaderPipeline* redToAlphaPipelinePmus) - : m_gen(gen), m_regPipeline(regPipeline), m_redToAlphaPipeline(redToAlphaPipeline), + : m_gen(gen), m_regPipeline(regPipeline), m_regPipelineSub(regPipelineSub), + m_redToAlphaPipeline(redToAlphaPipeline), m_redToAlphaPipelineSub(redToAlphaPipelineSub), m_regPipelinePmus(regPipelinePmus), m_redToAlphaPipelinePmus(redToAlphaPipelinePmus) {} public: diff --git a/Runtime/Graphics/Shaders/CElementGenShadersGLSL.cpp b/Runtime/Graphics/Shaders/CElementGenShadersGLSL.cpp index b34f0fe62..843d4b593 100644 --- a/Runtime/Graphics/Shaders/CElementGenShadersGLSL.cpp +++ b/Runtime/Graphics/Shaders/CElementGenShadersGLSL.cpp @@ -66,8 +66,8 @@ BOO_GLSL_BINDING_HEAD "TBINDING0 uniform sampler2D tex;\n" "void main()\n" "{\n" -" colorOut = vtf.color * texture(tex, vtf.uv);\n" -" colorOut.a = colorOut.r;\n" +" colorOut = vtf.color;\n" +" colorOut.a = texture(tex, vtf.uv).r;\n" "}\n"; static const char* VS_GLSL_INDTEX = @@ -302,10 +302,18 @@ struct OGLElementDataBindingFactory : TShader::IDataBindingF gen.m_normalDataBind = ctx.newShaderDataBinding(shaders.m_regPipeline, vtxFmt, nullptr, gen.m_instBuf, nullptr, 1, uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_regPipelineSub) + gen.m_normalSubDataBind = ctx.newShaderDataBinding(shaders.m_regPipelineSub, vtxFmt, nullptr, + gen.m_instBuf, nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); if (shaders.m_redToAlphaPipeline) gen.m_redToAlphaDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipeline, vtxFmt, nullptr, gen.m_instBuf, nullptr, 1, uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_redToAlphaPipelineSub) + gen.m_redToAlphaSubDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipelineSub, vtxFmt, nullptr, + gen.m_instBuf, nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); } if (gen.m_instBufPmus) @@ -368,6 +376,24 @@ TShader::IDataBindingFactory* CElementGenShaders::Initialize boo::Primitive::TriStrips, boo::ZTest::None, false, true, false, boo::CullMode::None); + m_texZTestNoZWriteSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, TexNames, 1, UniNames, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texNoZTestNoZWriteSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, TexNames, 1, UniNames, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texRedToAlphaZTestSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, 1, TexNames, 1, UniNames, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texRedToAlphaNoZTestSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, 1, TexNames, 1, UniNames, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + m_indTexZWrite = ctx.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, 3, TindTexNames, 1, UniNames, boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips, boo::ZTest::None, true, @@ -457,10 +483,19 @@ struct VulkanElementDataBindingFactory : TShader::IDataBindi gen.m_normalDataBind = ctx.newShaderDataBinding(shaders.m_regPipeline, nullptr, nullptr, gen.m_instBuf, nullptr, 1, uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_regPipelineSub) + gen.m_normalSubDataBind = ctx.newShaderDataBinding(shaders.m_regPipelineSub, nullptr, nullptr, + gen.m_instBuf, nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); if (shaders.m_redToAlphaPipeline) gen.m_redToAlphaDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipeline, nullptr, nullptr, gen.m_instBuf, nullptr, 1, uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_redToAlphaPipelineSub) + gen.m_redToAlphaSubDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipelineSub, nullptr, nullptr, + gen.m_instBuf, nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + } if (gen.m_instBufPmus) @@ -561,6 +596,24 @@ TShader::IDataBindingFactory* CElementGenShaders::Initialize boo::Primitive::TriStrips, boo::ZTest::None, false, true, false, boo::CullMode::None); + m_texZTestNoZWriteSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texNoZTestNoZWriteSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texRedToAlphaZTestSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texRedToAlphaNoZTestSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + m_indTexZWrite = ctx.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, m_vtxFormatIndTex, boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips, boo::ZTest::LEqual, true, diff --git a/Runtime/Graphics/Shaders/CElementGenShadersHLSL.cpp b/Runtime/Graphics/Shaders/CElementGenShadersHLSL.cpp index 80e1e0fa7..e56cc3bbf 100644 --- a/Runtime/Graphics/Shaders/CElementGenShadersHLSL.cpp +++ b/Runtime/Graphics/Shaders/CElementGenShadersHLSL.cpp @@ -65,8 +65,7 @@ static const char* FS_HLSL_TEX_REDTOALPHA = "\n" "float4 main(in VertToFrag vtf) : SV_Target0\n" "{\n" -" float4 colr = vtf.color * tex0.Sample(samp, vtf.uv);\n" -" return float4(colr.rgb, colr.r);" +" return float4(vtf.color.rgb, tex0.Sample(samp, vtf.uv).r);\n" "}\n"; static const char* VS_HLSL_INDTEX = @@ -222,11 +221,21 @@ struct D3DElementDataBindingFactory : TShader::IDataBindingF gen.m_instBuf, nullptr, 1, uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_regPipelineSub) + gen.m_normalSubDataBind = ctx.newShaderDataBinding(shaders.m_regPipelineSub, nullptr, nullptr, + gen.m_instBuf, nullptr, 1, uniforms, + nullptr, texCount, textures, + nullptr, nullptr); if (shaders.m_redToAlphaPipeline) gen.m_redToAlphaDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipeline, nullptr, nullptr, gen.m_instBuf, nullptr, 1, uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_redToAlphaPipelineSub) + gen.m_redToAlphaSubDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipelineSub, nullptr, nullptr, + gen.m_instBuf, nullptr, 1, uniforms, + nullptr, texCount, textures, + nullptr, nullptr); } if (gen.m_instBufPmus) @@ -334,6 +343,28 @@ TShader::IDataBindingFactory* CElementGenShaders::Initialize boo::Primitive::TriStrips, boo::ZTest::None, false, true, false, boo::CullMode::None); + m_texZTestNoZWriteSub = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texNoZTestNoZWriteSub = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texRedToAlphaZTestSub = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX_REDTOALPHA, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texRedToAlphaNoZTestSub = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX_REDTOALPHA, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + m_indTexZWrite = ctx.newShaderPipeline(VS_HLSL_INDTEX, FS_HLSL_INDTEX, nullptr, nullptr, nullptr, m_vtxFormatIndTex, boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, diff --git a/Runtime/Graphics/Shaders/CElementGenShadersMetal.cpp b/Runtime/Graphics/Shaders/CElementGenShadersMetal.cpp index 9d1e28f36..24dbb86a1 100644 --- a/Runtime/Graphics/Shaders/CElementGenShadersMetal.cpp +++ b/Runtime/Graphics/Shaders/CElementGenShadersMetal.cpp @@ -71,8 +71,7 @@ static const char* FS_METAL_TEX_REDTOALPHA = "fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n" " texture2d tex0 [[ texture(0) ]])\n" "{\n" -" float4 colr = vtf.color * tex0.sample(samp, vtf.uv);\n" -" return float4(colr.rgb, colr.r);" +" return float4(vtf.color.rgb, tex0.sample(samp, vtf.uv).r);\n" "}\n"; static const char* VS_METAL_INDTEX = @@ -242,10 +241,18 @@ struct MetalElementDataBindingFactory : TShader::IDataBindin gen.m_normalDataBind = ctx.newShaderDataBinding(shader.m_regPipeline, nullptr, nullptr, gen.m_instBuf, nullptr, 1, uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (shader.m_regPipelineSub) + gen.m_normalSubDataBind = ctx.newShaderDataBinding(shader.m_regPipelineSub, nullptr, nullptr, + gen.m_instBuf, nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); if (shader.m_redToAlphaPipeline) gen.m_redToAlphaDataBind = ctx.newShaderDataBinding(shader.m_redToAlphaPipeline, nullptr, nullptr, gen.m_instBuf, nullptr, 1, uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (shader.m_redToAlphaPipelineSub) + gen.m_redToAlphaSubDataBind = ctx.newShaderDataBinding(shader.m_redToAlphaPipelineSub, nullptr, nullptr, + gen.m_instBuf, nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); } if (gen.m_instBufPmus) @@ -254,13 +261,13 @@ struct MetalElementDataBindingFactory : TShader::IDataBindin texCount = std::min(texCount, 1); if (shader.m_regPipelinePmus) - gen.m_normalDataBind = ctx.newShaderDataBinding(shader.m_regPipelinePmus, nullptr, nullptr, - gen.m_instBufPmus, nullptr, 1, uniforms, - nullptr, texCount, textures, nullptr, nullptr); - if (shader.m_redToAlphaPipelinePmus) - gen.m_redToAlphaDataBind = ctx.newShaderDataBinding(shader.m_redToAlphaPipelinePmus, nullptr, nullptr, + gen.m_normalDataBindPmus = ctx.newShaderDataBinding(shader.m_regPipelinePmus, nullptr, nullptr, gen.m_instBufPmus, nullptr, 1, uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (shader.m_redToAlphaPipelinePmus) + gen.m_redToAlphaDataBindPmus = ctx.newShaderDataBinding(shader.m_redToAlphaPipelinePmus, nullptr, nullptr, + gen.m_instBufPmus, nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); } return nullptr; @@ -343,6 +350,28 @@ TShader::IDataBindingFactory* CElementGenShaders::Initialize boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips, boo::ZTest::None, false, true, true, boo::CullMode::None); + m_texZTestNoZWriteSub = ctx.newShaderPipeline(VS_METAL_TEX, FS_METAL_TEX, m_vtxFormatTex, + CGraphics::g_ViewportSamples, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texNoZTestNoZWriteSub = ctx.newShaderPipeline(VS_METAL_TEX, FS_METAL_TEX, m_vtxFormatTex, + CGraphics::g_ViewportSamples, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texRedToAlphaZTestSub = ctx.newShaderPipeline(VS_METAL_TEX, FS_METAL_TEX_REDTOALPHA, m_vtxFormatTex, + CGraphics::g_ViewportSamples, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texRedToAlphaNoZTestSub = ctx.newShaderPipeline(VS_METAL_TEX, FS_METAL_TEX_REDTOALPHA, m_vtxFormatTex, + CGraphics::g_ViewportSamples, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + m_indTexZWrite = ctx.newShaderPipeline(VS_METAL_INDTEX, FS_METAL_INDTEX, m_vtxFormatIndTex, CGraphics::g_ViewportSamples, boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, diff --git a/Runtime/MP1/CInventoryScreen.cpp b/Runtime/MP1/CInventoryScreen.cpp index 2f63cd24f..702e325ba 100644 --- a/Runtime/MP1/CInventoryScreen.cpp +++ b/Runtime/MP1/CInventoryScreen.cpp @@ -374,7 +374,7 @@ bool CInventoryScreen::IsRightInventoryItemEquipped(int idx) const case 3: // Plasma Beam return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Plasma; case 4: // Phazon Beam - return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Phazon; + return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Phazon2; case 5: // Morph Ball return playerState.HasPowerUp(CPlayerState::EItemType::MorphBall); case 6: // Boost Ball diff --git a/Runtime/MP1/World/CActorContraption.cpp b/Runtime/MP1/World/CActorContraption.cpp index 53cfe1577..9aa2cbcef 100644 --- a/Runtime/MP1/World/CActorContraption.cpp +++ b/Runtime/MP1/World/CActorContraption.cpp @@ -90,7 +90,8 @@ CFlameThrower* MP1::CActorContraption::CreateFlameThrower(const std::string& nam CFlameInfo flameInfo(6, 6, x308_flameFxId, 20, 0.5f, 1.f, 1.f); CFlameThrower* ret = new CFlameThrower(x300_flameThrowerGen, name, EWeaponType::Missile, flameInfo, zeus::CTransform::Identity(), EMaterialTypes::CollisionActor, x30c_dInfo, - id, GetAreaId(), GetUniqueId(), 0, -1, -1, -1); + id, GetAreaId(), GetUniqueId(), CWeapon::EProjectileAttrib::None, + -1, -1, -1); x2e8_children.emplace_back(id, name); diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index c8bf3543f..c6e1f1bd1 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -18,6 +18,7 @@ static logvisor::Module Log("urde::CElementGen"); URDE_DECL_SPECIALIZE_SHADER(CElementGenShaders) u16 CElementGen::g_GlobalSeed = 99; +bool CElementGen::g_subtractBlend = false; int CElementGen::g_ParticleAliveCount; int CElementGen::g_ParticleSystemAliveCount; @@ -1152,16 +1153,20 @@ void CElementGen::RenderModels() else { CModel* model = desc->x5c_x48_PMDL.m_token.GetObj(); - if (desc->x44_31_x31_25_PMAB) + if (g_subtractBlend) { - model->Draw({3, 0, 1, col}); + model->Draw({5, 0, 1, zeus::CColor(1.f, 0.5f)}); + } + else if (desc->x44_31_x31_25_PMAB) + { + model->Draw({7, 0, 1, col}); } else { if (1.f == col.a) model->Draw({0, 0, 3, zeus::CColor::skWhite}); else - model->Draw({4, 0, 1, col}); + model->Draw({5, 0, 1, col}); } } @@ -1389,10 +1394,20 @@ void CElementGen::RenderParticles() if (sMoveRedToAlphaBuffer && x26c_26_AAPH) moveRedToAlphaBuffer = true; - if (moveRedToAlphaBuffer) - CGraphics::SetShaderDataBinding(m_redToAlphaDataBind); + if (g_subtractBlend) + { + if (moveRedToAlphaBuffer) + CGraphics::SetShaderDataBinding(m_redToAlphaSubDataBind); + else + CGraphics::SetShaderDataBinding(m_normalSubDataBind); + } else - CGraphics::SetShaderDataBinding(m_normalDataBind); + { + if (moveRedToAlphaBuffer) + CGraphics::SetShaderDataBinding(m_redToAlphaDataBind); + else + CGraphics::SetShaderDataBinding(m_normalDataBind); + } int mbspVal = std::max(1, x270_MBSP); diff --git a/Runtime/Particle/CElementGen.hpp b/Runtime/Particle/CElementGen.hpp index 1fc52f9b8..80a4f7546 100644 --- a/Runtime/Particle/CElementGen.hpp +++ b/Runtime/Particle/CElementGen.hpp @@ -27,8 +27,10 @@ class CParticleElectric; class CElementGen : public CParticleGen { static u16 g_GlobalSeed; + static bool g_subtractBlend; public: static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; } + static void SetSubtractBlend(bool s) { g_subtractBlend = s; } enum class EModelOrientationType { Normal, @@ -172,7 +174,9 @@ public: boo::GraphicsDataToken m_gfxToken; boo::IShaderDataBinding* m_normalDataBind = nullptr; + boo::IShaderDataBinding* m_normalSubDataBind = nullptr; boo::IShaderDataBinding* m_redToAlphaDataBind = nullptr; + boo::IShaderDataBinding* m_redToAlphaSubDataBind = nullptr; boo::IGraphicsBufferD* m_instBuf = nullptr; boo::IGraphicsBufferD* m_uniformBuf = nullptr; diff --git a/Runtime/Weapon/CBeamProjectile.cpp b/Runtime/Weapon/CBeamProjectile.cpp index 9c96408c4..b9ae1f79e 100644 --- a/Runtime/Weapon/CBeamProjectile.cpp +++ b/Runtime/Weapon/CBeamProjectile.cpp @@ -5,9 +5,10 @@ namespace urde { CBeamProjectile::CBeamProjectile(const TToken& wDesc, const std::string& name, EWeaponType wType, - const zeus::CTransform& xf, int attribs, float f1, float f2, EMaterialTypes matType, - const CDamageInfo& dInfo, TUniqueId owner, TAreaId aid, TUniqueId uid, u32 w1, bool b1) -: CGameProjectile(false, wDesc, name, wType, xf, matType, dInfo, owner, aid, uid, kInvalidUniqueId, w1, false, + const zeus::CTransform& xf, int flags, float f1, float f2, EMaterialTypes matType, + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, + EProjectileAttrib attribs, bool b1) +: CGameProjectile(false, wDesc, name, wType, xf, matType, dInfo, uid, aid, owner, kInvalidUniqueId, attribs, false, zeus::CVector3f::skOne, {}, -1, false) { } diff --git a/Runtime/Weapon/CBeamProjectile.hpp b/Runtime/Weapon/CBeamProjectile.hpp index 5ba39138e..f111fa1be 100644 --- a/Runtime/Weapon/CBeamProjectile.hpp +++ b/Runtime/Weapon/CBeamProjectile.hpp @@ -7,8 +7,10 @@ namespace urde class CBeamProjectile : public CGameProjectile { public: - CBeamProjectile(const TToken&, const std::string&, EWeaponType, const zeus::CTransform&, int, - float, float, EMaterialTypes, const CDamageInfo&, TUniqueId, TAreaId, TUniqueId, u32, bool); + CBeamProjectile(const TToken& wDesc, const std::string& name, EWeaponType wType, + const zeus::CTransform& xf, int flags, float f1, float f2, EMaterialTypes matType, + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, + EProjectileAttrib attribs, bool b1); void Accept(IVisitor &visitor); float GetMaxRadius() const; diff --git a/Runtime/Weapon/CEnergyProjectile.cpp b/Runtime/Weapon/CEnergyProjectile.cpp index 1ee8d0d0d..3e8a017f3 100644 --- a/Runtime/Weapon/CEnergyProjectile.cpp +++ b/Runtime/Weapon/CEnergyProjectile.cpp @@ -5,12 +5,12 @@ namespace urde CEnergyProjectile::CEnergyProjectile(bool active, const TToken& desc, EWeaponType type, const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage, - TUniqueId id0, TAreaId aid, TUniqueId id1, TUniqueId id2, u32 w1, bool b1, - const zeus::CVector3f& scale, + TUniqueId uid, TAreaId aid, TUniqueId owner, TUniqueId homingTarget, + EProjectileAttrib attribs, bool underwater, const zeus::CVector3f& scale, const rstl::optional_object>& particle, s16 w2, bool b2) -: CGameProjectile(active, desc, "GameProjectile", type, xf, materials, damage, id0, aid, - id1, id2, w1, b1, scale, particle, w2, b2), +: CGameProjectile(active, desc, "GameProjectile", type, xf, materials, damage, uid, aid, + owner, homingTarget, attribs, underwater, scale, particle, w2, b2), x2ec_dir(xf.basis[1]), x2f8_mag(x2ec_dir.magnitude()), x2fc_camShake(CCameraShakeData::BuildProjectileCameraShake(0.5f, 0.75f)) { diff --git a/Runtime/Weapon/CEnergyProjectile.hpp b/Runtime/Weapon/CEnergyProjectile.hpp index e2c89b97a..382e4a8e0 100644 --- a/Runtime/Weapon/CEnergyProjectile.hpp +++ b/Runtime/Weapon/CEnergyProjectile.hpp @@ -28,8 +28,8 @@ class CEnergyProjectile : public CGameProjectile public: CEnergyProjectile(bool active, const TToken& desc, EWeaponType type, const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage, - TUniqueId id0, TAreaId aid, TUniqueId id1, TUniqueId id2, u32 w1, bool b1, - const zeus::CVector3f& scale, + TUniqueId uid, TAreaId aid, TUniqueId owner, TUniqueId homingTarget, + EProjectileAttrib attribs, bool underwater, const zeus::CVector3f& scale, const rstl::optional_object>& particle, s16 w2, bool b2); }; diff --git a/Runtime/Weapon/CFlameThrower.cpp b/Runtime/Weapon/CFlameThrower.cpp index 37b0bcfe5..3c17b6c42 100644 --- a/Runtime/Weapon/CFlameThrower.cpp +++ b/Runtime/Weapon/CFlameThrower.cpp @@ -10,9 +10,9 @@ const zeus::CVector3f CFlameThrower::kLightOffset(0, 3.f, 2.f); CFlameThrower::CFlameThrower(const TToken& wDesc, const std::string& name, EWeaponType wType, const CFlameInfo& flameInfo, const zeus::CTransform& xf, EMaterialTypes matType, - const CDamageInfo& dInfo, TUniqueId owner, TAreaId aId, TUniqueId uid, u32 w1, u32 w2, - s16 sId, u32 w3) -: CGameProjectile(false, wDesc, name, wType, xf, matType, dInfo, owner, aId, uid, kInvalidUniqueId, w1, false, + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aId, TUniqueId owner, + EProjectileAttrib attribs, u32 w2, s16 sId, u32 w3) +: CGameProjectile(false, wDesc, name, wType, xf, matType, dInfo, uid, aId, owner, kInvalidUniqueId, attribs, false, zeus::CVector3f(1.f), {}, -1, false) , x2e8_(xf) , x33c_flameDesc(g_SimplePool->GetObj({FOURCC('PART'), flameInfo.GetFlameFxId()})) diff --git a/Runtime/Weapon/CFlameThrower.hpp b/Runtime/Weapon/CFlameThrower.hpp index 8251cfeca..107a954ee 100644 --- a/Runtime/Weapon/CFlameThrower.hpp +++ b/Runtime/Weapon/CFlameThrower.hpp @@ -27,8 +27,8 @@ class CFlameThrower : public CGameProjectile public: CFlameThrower(const TToken& wDesc, const std::string& name, EWeaponType wType, const CFlameInfo& flameInfo, const zeus::CTransform& xf, EMaterialTypes matType, - const CDamageInfo& dInfo, TUniqueId owner, TAreaId aId, TUniqueId uid, u32 w1, u32 w2, s16 sId, - u32 w3); + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aId, TUniqueId owner, EProjectileAttrib attribs, + u32 w2, s16 sId, u32 w3); void Accept(IVisitor& visitor); void SetTransform(const zeus::CTransform& xf); diff --git a/Runtime/Weapon/CGameProjectile.cpp b/Runtime/Weapon/CGameProjectile.cpp index 38de5704f..4402144fd 100644 --- a/Runtime/Weapon/CGameProjectile.cpp +++ b/Runtime/Weapon/CGameProjectile.cpp @@ -8,14 +8,15 @@ namespace urde { CGameProjectile::CGameProjectile(bool active, const TToken&, const std::string& name, EWeaponType wType, const zeus::CTransform& xf, EMaterialTypes matType, - const CDamageInfo& dInfo, TUniqueId owner, TAreaId aid, TUniqueId uid, TUniqueId, - u32 w1, bool b2, const zeus::CVector3f&, - const rstl::optional_object>&, s16, bool b3) -: CWeapon(owner, aid, active, uid, wType, name, xf, + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, + TUniqueId homingTarget, EProjectileAttrib attribs, bool underwater, + const zeus::CVector3f& scale, + const rstl::optional_object>& particle, s16 s1, bool b3) +: CWeapon(uid, aid, active, owner, wType, name, xf, CMaterialFilter::MakeIncludeExclude( {EMaterialTypes::NonSolidDamageable, matType}, {EMaterialTypes::Projectile, EMaterialTypes::ProjectilePassthrough, matType, EMaterialTypes::Solid}), - CMaterialList(), dInfo, EProjectileAttrib(w1) | GetBeamAttribType(wType), CModelData::CModelDataNull()) + CMaterialList(), dInfo, attribs | GetBeamAttribType(wType), CModelData::CModelDataNull()) { } @@ -23,25 +24,25 @@ void CGameProjectile::Accept(urde::IVisitor& visitor) { visitor.Visit(this); } void CGameProjectile::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId /*uid*/, CStateManager& mgr) { - if (msg == EScriptObjectMessage::UpdateSplashInhabitant) + if (msg == EScriptObjectMessage::AddSplashInhabitant) { - if (!x2e4_27_) + if (!x2e4_27_inWater) { - x2e4_27_ = true; - x2e4_26_ = true; + x2e4_27_inWater = true; + x2e4_26_waterUpdate = true; } } else if (msg == EScriptObjectMessage::UpdateSplashInhabitant) { - if (!x2e4_26_) - x2e4_26_ = true; + if (!x2e4_26_waterUpdate) + x2e4_26_waterUpdate = true; } else if (msg == EScriptObjectMessage::RemoveSplashInhabitant) { - if (x2e4_26_) + if (x2e4_26_waterUpdate) { - x2e4_26_ = false; - x2e4_27_ = false; + x2e4_26_waterUpdate = false; + x2e4_27_inWater = false; } } else if (msg == EScriptObjectMessage::Deleted) diff --git a/Runtime/Weapon/CGameProjectile.hpp b/Runtime/Weapon/CGameProjectile.hpp index 0f0e2d60f..dd1c4a621 100644 --- a/Runtime/Weapon/CGameProjectile.hpp +++ b/Runtime/Weapon/CGameProjectile.hpp @@ -24,15 +24,17 @@ class CGameProjectile : public CWeapon { bool x2e4_24_ : 1; bool x2e4_25_ : 1; - bool x2e4_26_ : 1; - bool x2e4_27_ : 1; + bool x2e4_26_waterUpdate : 1; + bool x2e4_27_inWater : 1; bool x2e4_28_ : 1; }; }; public: - CGameProjectile(bool, const TToken&, const std::string&, EWeaponType, const zeus::CTransform&, - EMaterialTypes, const CDamageInfo&, TUniqueId, TAreaId, TUniqueId, TUniqueId, u32, bool, - const zeus::CVector3f&, const rstl::optional_object>&, s16, bool); + CGameProjectile(bool active, const TToken&, const std::string& name, + EWeaponType wType, const zeus::CTransform& xf, EMaterialTypes matType, + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, + TUniqueId homingTarget, EProjectileAttrib attribs, bool underwater, const zeus::CVector3f& scale, + const rstl::optional_object>& particle, s16 s1, bool b3); virtual void Accept(IVisitor &visitor); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); diff --git a/Runtime/Weapon/CGunWeapon.cpp b/Runtime/Weapon/CGunWeapon.cpp index 2c89cb795..9809acf76 100644 --- a/Runtime/Weapon/CGunWeapon.cpp +++ b/Runtime/Weapon/CGunWeapon.cpp @@ -1,11 +1,16 @@ #include "CGunWeapon.hpp" #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" -#include "Character/CModelData.hpp" +#include "CDependencyGroup.hpp" +#include "CGameState.hpp" +#include "CWeapon.hpp" +#include "CEnergyProjectile.hpp" +#include "Graphics/CSkinnedModel.hpp" +#include "Graphics/CVertexMorphEffect.hpp" namespace urde { -const char* CGunWeapon::skBeamXferNames[5] = +static const char* skBeamXferNames[] = { "PowerXfer", "IceXfer", @@ -14,7 +19,7 @@ const char* CGunWeapon::skBeamXferNames[5] = "PhazonXfer" }; -const char* CGunWeapon::skSuitArmNames[8] = +static const char* skSuitArmNames[] = { "PowerArm", "GravityArm", @@ -26,19 +31,65 @@ const char* CGunWeapon::skSuitArmNames[8] = "FusionArmP", }; -s32 GetWeaponIndex(EWeaponType type) +static const char* skMuzzleNames[] = +{ + "PowerMuzzle", + "PowerCharge", + "IceMuzzle", + "IceCharge", + "PowerMuzzle", + "WaveCharge", + "PlasmaMuzzle", + "PlasmaCharge", + "PhazonMuzzle", + "EmptyMuzzle" +}; + +static const char* skFrozenNames[] = +{ + "powerFrozen", + "Ice2nd_2", + "iceFrozen", + "Ice2nd_2", + "waveFrozen", + "Ice2nd_2", + "plasmaFrozen", + "Ice2nd_2", + "iceFrozen", + "Ice2nd_2" +}; + +static const char* skDependencyNames[] = +{ + "Power_DGRP", + "Ice_DGRP", + "Wave_DGRP", + "Plasma_DGRP", + "Phazon_DGRP" +}; + +static const char* skAnimDependencyNames[] = +{ + "Power_Anim_DGRP", + "Ice_Anim_DGRP", + "Wave_Anim_DGRP", + "Plasma_Anim_DGRP", + "Phazon_Anim_DGRP" +}; + +CPlayerState::EBeamId GetWeaponIndex(EWeaponType type) { if (type == EWeaponType::Power) - return 0; + return CPlayerState::EBeamId::Power; else if (type == EWeaponType::Ice) - return 1; + return CPlayerState::EBeamId::Ice; else if (type == EWeaponType::Wave) - return 2; + return CPlayerState::EBeamId::Wave; else if (type == EWeaponType::Plasma) - return 3; + return CPlayerState::EBeamId::Plasma; else if (type == EWeaponType::Phazon) - return 4; - return 0; + return CPlayerState::EBeamId::Phazon; + return CPlayerState::EBeamId::Power; } CGunWeapon::CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, @@ -46,26 +97,86 @@ CGunWeapon::CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, : x4_scale(scale), x104_gunCharacter(g_SimplePool->GetObj(SObjectTag{FOURCC('ANCS'), ancsId})), x13c_armCharacter(g_SimplePool->GetObj(skSuitArmNames[0])), + x160_xferEffect(g_SimplePool->GetObj(skBeamXferNames[int(GetWeaponIndex(type))])), x1c0_weaponType(type), x1c4_playerId(playerId), - x1c8_playerMaterial(playerMaterial) + x1c8_playerMaterial(playerMaterial), + x200_beamId(GetWeaponIndex(type)), + x20c_shaderIdx(u32(x200_beamId)), + x214_ancsId(ancsId) { + AllocResPools(x200_beamId); + BuildDependencyList(x200_beamId); +} + +void CGunWeapon::AllocResPools(CPlayerState::EBeamId beam) +{ + const CAssetId* wPair = g_tweakGunRes->GetWeaponPair(beam); + const char** muzzleNames = &skMuzzleNames[int(beam) * 2]; + const char** frozenNames = &skFrozenNames[int(beam) * 2]; + for (int i=0 ; i<2 ; ++i) + { + x16c_muzzleEffects.push_back(g_SimplePool->GetObj(muzzleNames[i])); + x144_weapons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('WPSC'), wPair[1]})); + x188_frozenEffects.push_back(g_SimplePool->GetObj(frozenNames[i])); + } +} + +void CGunWeapon::FreeResPools() +{ + x160_xferEffect.Unlock(); + for (int i=0 ; i<2 ; ++i) + { + x16c_muzzleEffects[i].Unlock(); + x144_weapons[i].Unlock(); + x188_frozenEffects[i].Unlock(); + } + x10c_anims.clear(); + x1a4_muzzleGenerators.clear(); + x1d0_velInfo.Clear(); +} + +void CGunWeapon::FillTokenVector(const std::vector& tags, std::vector& objects) +{ + for (const SObjectTag& tag : tags) + objects.push_back(g_SimplePool->GetObj(tag)); +} + +void CGunWeapon::BuildDependencyList(CPlayerState::EBeamId beam) +{ + TLockedToken deps = g_SimplePool->GetObj(skDependencyNames[int(beam)]); + TLockedToken animDeps = g_SimplePool->GetObj(skAnimDependencyNames[int(beam)]); + x12c_deps.reserve(deps->GetObjectTagVector().size() + animDeps->GetObjectTagVector().size()); + FillTokenVector(deps->GetObjectTagVector(), x12c_deps); + FillTokenVector(animDeps->GetObjectTagVector(), x12c_deps); } void CGunWeapon::AsyncLoadSuitArm(CStateManager& mgr) { + + xb0_suitArmModelData = std::experimental::nullopt; + x13c_armCharacter = g_SimplePool->GetObj(skSuitArmNames[int(NWeaponTypes::get_current_suit(mgr))]); + x13c_armCharacter.Lock(); + x218_28_suitArmLocked = true; } -void CGunWeapon::AllocResPools(CPlayerState::EBeamId) +void CGunWeapon::Reset(CStateManager& mgr) { + if (!x218_26_loaded) + return; + x10_solidModelData->AnimationData()->EnableLooping(false); + if (x218_25_enableCharge) + x218_25_enableCharge = false; + else + x100_gunController->Reset(); } static const s32 skAnimTypeList[] = { 0, 4, 1, 2, 3, 5, 6, 7, 8, 9, 10 }; void CGunWeapon::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) { - if (x218_26 && type >= NWeaponTypes::EGunAnimType::BasePosition && + if (x218_26_loaded && type >= NWeaponTypes::EGunAnimType::BasePosition && type <= NWeaponTypes::EGunAnimType::ToBeam) { x10_solidModelData->AnimationData()->EnableLooping(loop); @@ -74,54 +185,520 @@ void CGunWeapon::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) } } -void CGunWeapon::BuildSecondaryEffect(ESecondaryFxType type) +void CGunWeapon::PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) +{ + // Empty +} + +void CGunWeapon::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) +{ + if (x218_26_loaded && x1b8_frozenGenerator && x204_frozenEffect != EFrozenFxType::None) + x1b8_frozenGenerator->Render(); +} + +void CGunWeapon::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) +{ + if (x218_26_loaded && x204_frozenEffect != EFrozenFxType::None) + { + if (x204_frozenEffect == EFrozenFxType::Thawed) + { + if (x1b8_frozenGenerator->IsSystemDeletable()) + { + x1b8_frozenGenerator.reset(); + } + else + { + x1b8_frozenGenerator->SetTranslation(xf.origin); + x1b8_frozenGenerator->SetOrientation(xf.getRotation()); + } + } + else + { + x1b8_frozenGenerator->SetGlobalOrientAndTrans(xf); + } + if (x1b8_frozenGenerator) + x1b8_frozenGenerator->Update(dt); + } +} + +const s32 CGunWeapon::skShootAnim[2] = { 4, 3 }; + +void CGunWeapon::Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, + CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) +{ + CDamageInfo dInfo = GetDamageInfo(mgr, chargeState, chargeFactor1); + zeus::CVector3f scale(chargeState == EChargeState::Normal ? 1.f : chargeFactor2); + bool partialCharge = chargeState == EChargeState::Normal ? false : std::fabs(chargeFactor1 - 1.f) >= 0.00001f; + CWeapon::EProjectileAttrib attribs = CWeapon::EProjectileAttrib::ArmCannon; + if (partialCharge) + attribs |= CWeapon::EProjectileAttrib::PartialCharge; + if (chargeState == EChargeState::Charged) + attribs |= CWeapon::EProjectileAttrib::Charged; + + CEnergyProjectile* proj = new CEnergyProjectile(true, x144_weapons[int(chargeState)], x1c0_weaponType, + xf, x1c8_playerMaterial, dInfo, mgr.AllocateUniqueId(), + kInvalidAreaId, x1c4_playerId, homingTarget, attribs, + underwater, scale, {}, -1, false); + mgr.AddObject(proj); + proj->Think(dt, mgr); + + if (chargeState == EChargeState::Charged) + { + x218_25_enableCharge = true; + mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::skChargedCameraShakeData, false); + } + + x10_solidModelData->AnimationData()->EnableLooping(false); + CAnimPlaybackParms parms(skShootAnim[int(chargeState)], -1, 1.f, true); + x10_solidModelData->AnimationData()->SetAnimation(parms, false); +} + +void CGunWeapon::EnableFx(bool enable) +{ + // Empty +} + +void CGunWeapon::EnableSecondaryFx(ESecondaryFxType type) +{ + x1cc_enabledSecondaryEffect = type; +} + +void CGunWeapon::EnableFrozenEffect(EFrozenFxType type) { switch (type) { - case ESecondaryFxType::Two: - if (x204_secondaryEffectType == ESecondaryFxType::Two) + case EFrozenFxType::Thawed: + if (x204_frozenEffect == EFrozenFxType::Thawed) break; - x1b8_secondaryEffect = std::make_unique(x188_secondaryEffects[1], + x1b8_frozenGenerator = std::make_unique(x188_frozenEffects[1], CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One); - x1b8_secondaryEffect->SetGlobalScale(x4_scale); + x1b8_frozenGenerator->SetGlobalScale(x4_scale); break; - case ESecondaryFxType::One: - if (x204_secondaryEffectType == ESecondaryFxType::One) + case EFrozenFxType::Frozen: + if (x204_frozenEffect == EFrozenFxType::Frozen) break; - x1b8_secondaryEffect = std::make_unique(x188_secondaryEffects[0], + x1b8_frozenGenerator = std::make_unique(x188_frozenEffects[0], CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One); - x1b8_secondaryEffect->SetGlobalScale(x4_scale); + x1b8_frozenGenerator->SetGlobalScale(x4_scale); break; default: break; } - x204_secondaryEffectType = type; + x204_frozenEffect = type; } -void CGunWeapon::ActivateCharge(bool b1, bool b2) +void CGunWeapon::ActivateCharge(bool enable, bool resetEffect) { + x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetParticleEmission(false); + x208_muzzleEffectIdx = u32(enable); + if (enable || resetEffect) + { + x1a4_muzzleGenerators[x208_muzzleEffectIdx] = + std::make_unique(x16c_muzzleEffects[x208_muzzleEffectIdx], + CElementGen::EModelOrientationType::Normal, + CElementGen::EOptionalSystemFlags::One); + } } void CGunWeapon::Touch(const CStateManager& mgr) { - + if (x10_solidModelData) + { + x10_solidModelData->Touch(mgr, x20c_shaderIdx); + if (xb0_suitArmModelData) + xb0_suitArmModelData->Touch(mgr, 0); + } } void CGunWeapon::TouchHolo(const CStateManager& mgr) { + if (x60_holoModelData) + x60_holoModelData->Touch(mgr, 0); +} +void CGunWeapon::PointGenerator(void* ctx, const std::vector>& vn) +{ + reinterpret_cast(ctx)->GeneratePoints(vn); +} + +void CGunWeapon::Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, + const CModelFlags& flags, const CActorLights* lights) const +{ + if (!x218_26_loaded) + return; + + zeus::CTransform armXf = xf * x10_solidModelData->GetScaledLocatorTransform("elbow"); + + if (x1bc_rainSplashGenerator && x1bc_rainSplashGenerator->IsRaining()) + CSkinnedModel::SetPointGeneratorFunc(x1bc_rainSplashGenerator, PointGenerator); + + if (mgr.GetParticleFlags() == 0 && x200_beamId != CPlayerState::EBeamId::Ice) + { + zeus::CColor color1(flags.x4_color.a, flags.x4_color.a); + zeus::CColor color2(0.25f, 0.25f); + if (x218_29_drawHologram) + DrawHologram(mgr, xf, flags); + else + x10_solidModelData->RenderThermal(xf, color1, color2); + + if (drawSuitArm && xb0_suitArmModelData) + { + xb0_suitArmModelData->RenderThermal(xf, color1, color2); + } + } + else + { + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay && !x218_29_drawHologram) + { + CModelFlags useFlags = flags; + useFlags.x1_matSetIdx = u8(x20c_shaderIdx); + x10_solidModelData->Render(mgr, xf, lights, useFlags); + } + else + { + DrawHologram(mgr, xf, flags); + } + + if (drawSuitArm && xb0_suitArmModelData) + { + xb0_suitArmModelData->Render(mgr, armXf, lights, flags); + } + } + + if (x1bc_rainSplashGenerator && x1bc_rainSplashGenerator->IsRaining()) + { + CSkinnedModel::ClearPointGeneratorFunc(); + x1bc_rainSplashGenerator->Draw(xf); + } +} + +void CGunWeapon::DrawMuzzleFx(const CStateManager& mgr) const +{ + if (const CElementGen* effect = x1a4_muzzleGenerators[x208_muzzleEffectIdx].get()) + { + if (x200_beamId != CPlayerState::EBeamId::Ice && + mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) + { + CElementGen::SetSubtractBlend(true); + const_cast(effect)->Render(); + CElementGen::SetSubtractBlend(false); + } + else + { + const_cast(effect)->Render(); + } + } +} + +void CGunWeapon::LoadSuitArm(CStateManager& mgr) +{ + if (x13c_armCharacter.IsLoaded()) + { + CAssetId armId = NWeaponTypes::get_asset_id_from_name(skSuitArmNames[int(NWeaponTypes::get_current_suit(mgr))]); + xb0_suitArmModelData.emplace(CStaticRes(armId, x4_scale)); + xb0_suitArmModelData->SetSortThermal(true); + x218_28_suitArmLocked = false; + x13c_armCharacter.Unlock(); + } +} + +void CGunWeapon::LoadGunModels(CStateManager& mgr) +{ + s32 defaultAnim = x218_27_subtypeBasePose ? 0 : 9; + x10_solidModelData.emplace(CAnimRes(x214_ancsId, 0, x4_scale, defaultAnim, false)); + x60_holoModelData.emplace(CAnimRes(x214_ancsId, 1, x4_scale, defaultAnim, false)); + CAnimPlaybackParms parms(defaultAnim, -1, 1.f, true); + x10_solidModelData->AnimationData()->SetAnimation(parms, true); + LoadSuitArm(mgr); + x10_solidModelData->SetSortThermal(true); + x60_holoModelData->SetSortThermal(true); + x100_gunController = std::make_unique(*x10_solidModelData); +} + +void CGunWeapon::LoadAnimations() +{ + NWeaponTypes::get_token_vector(*x10_solidModelData->GetAnimationData(), 0, 15, x10c_anims, true); +} + +bool CGunWeapon::IsAnimsLoaded() const +{ + for (const CToken& tok : x10c_anims) + if (!tok.IsLoaded()) + return false; + return true; +} + +void CGunWeapon::LoadMuzzleFx(float dt) +{ + for (int i=0 ; i<2 ; ++i) + { + x1a4_muzzleGenerators.push_back(std::make_unique(x16c_muzzleEffects[i], + CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One)); + x1a4_muzzleGenerators.back()->SetParticleEmission(false); + x1a4_muzzleGenerators.back()->Update(dt); + } +} + +void CGunWeapon::LoadProjectileData(CStateManager& mgr) +{ + CRandom16 random(mgr.GetUpdateFrameIndex()); + CGlobalRandom grand(random); + for (int i=0 ; i<2 ; ++i) + { + zeus::CVector3f weaponVel; + if (const CVectorElement* ivec = x144_weapons[i]->x4_IVEC.get()) + ivec->GetValue(0, weaponVel); + x1d0_velInfo.x0_vel.push_back(weaponVel); + float tratVal = 0.f; + if (const CRealElement* trat = x144_weapons[i]->x30_TRAT.get()) + trat->GetValue(0, tratVal); + x1d0_velInfo.x24_trat.push_back(tratVal); + x1d0_velInfo.x1c_targetHoming.push_back(x144_weapons[i]->x29_HOMG); + if (weaponVel.y > 0.f) + x1d0_velInfo.x0_vel.back() *= zeus::CVector3f(60.f); + else + x1d0_velInfo.x0_vel.back() = zeus::CVector3f::skForward; + } +} + +void CGunWeapon::LoadFxIdle(float dt, CStateManager& mgr) +{ + if (NWeaponTypes::are_tokens_ready(x12c_deps)) + { + if ((x210_ & 0x2) != 0 && (x210_ & 0x4) != 0 && (x210_ & 0x10) != 0) + return; + bool loaded = true; + for (int i=0 ; i<2 ; ++i) + { + if (!x16c_muzzleEffects[i].IsLoaded()) + { + loaded = false; + break; + } + if (!x144_weapons[i].IsLoaded()) + { + loaded = false; + break; + } + } + + for (int i=0 ; i<2 ; ++i) + { + if (!x188_frozenEffects[i].IsLoaded()) + { + loaded = false; + break; + } + } + + if (!x160_xferEffect.IsLoaded()) + loaded = false; + + if (loaded) + { + if ((x210_ & 0x2) != 0x2) + { + LoadMuzzleFx(dt); + x210_ |= 0x2; + } + x210_ |= 0x10; + if ((x210_ & 0x4) != 0x4) + { + LoadProjectileData(mgr); + x210_ |= 0x4; + } + } + } +} + +void CGunWeapon::Update(float dt, CStateManager& mgr) +{ + if (x218_26_loaded) + { + x10_solidModelData->AdvanceAnimation(dt, mgr, kInvalidAreaId, true); + x100_gunController->Update(dt, mgr); + if (x218_28_suitArmLocked) + LoadSuitArm(mgr); + } + else + { + if (x104_gunCharacter) + { + if (x104_gunCharacter.IsLoaded()) + { + if ((x210_ & 0x1) != 0x1) + { + LoadGunModels(mgr); + LoadAnimations(); + x210_ |= 0x1; + } + if ((x210_ & 0x8) != 0x8) + { + if (IsAnimsLoaded()) + x210_ |= 0x8; + } + } + + LoadFxIdle(dt, mgr); + if ((x210_ & 0x1f) == 0x1f) + { + if (x10_solidModelData->PickAnimatedModel(CModelData::EWhichModel::Normal).GetModel()-> + IsLoaded(x20c_shaderIdx) && xb0_suitArmModelData->IsLoaded(0)) + x218_26_loaded = true; + } + } + } +} + +void CGunWeapon::LockTokens(CStateManager& mgr) +{ + AsyncLoadSuitArm(mgr); + NWeaponTypes::lock_tokens(x12c_deps); +} + +void CGunWeapon::UnlockTokens() +{ + x13c_armCharacter.Unlock(); + NWeaponTypes::unlock_tokens(x12c_deps); +} + +void CGunWeapon::Load(CStateManager& mgr, bool subtypeBasePose) +{ + LockTokens(mgr); + x218_27_subtypeBasePose = subtypeBasePose; + x204_frozenEffect = EFrozenFxType::None; + x1b8_frozenGenerator.reset(); + x104_gunCharacter.Lock(); + x160_xferEffect.Lock(); + for (int i=0 ; i<2 ; ++i) + { + x16c_muzzleEffects[i].Lock(); + x144_weapons[i].Lock(); + } + for (int i=0 ; i<2 ; ++i) + x188_frozenEffects[i].Lock(); +} + +void CGunWeapon::Unload(CStateManager& mgr) +{ + UnlockTokens(); + x210_ = 0; + x204_frozenEffect = EFrozenFxType::None; + x10_solidModelData = std::experimental::nullopt; + x60_holoModelData = std::experimental::nullopt; + xb0_suitArmModelData = std::experimental::nullopt; + x100_gunController.reset(); + x1bc_rainSplashGenerator = nullptr; + x1b8_frozenGenerator.reset(); + FreeResPools(); + x104_gunCharacter.Unlock(); + x218_26_loaded = false; +} + +bool CGunWeapon::IsLoaded() const +{ + return x218_26_loaded; } void CGunWeapon::DrawHologram(const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags) const { + if (!x218_26_loaded) + return; + if (x218_29_drawHologram) + { + CModelFlags useFlags = flags; + useFlags.m_extendedShader = EExtendedShader::Flat; + x60_holoModelData->Render(CModelData::EWhichModel::Normal, xf, nullptr, useFlags); + } + else + { + CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x10_solidModelData->GetScale())); + //CGraphics::DisableAllLights(); + //g_Renderer->SetAmbientColor(zeus::CColor::skWhite); + CSkinnedModel& model = + const_cast(*x60_holoModelData->GetAnimationData()->GetModelData()); + model.GetModelInst()->ActivateLights({CLight::BuildLocalAmbient({}, zeus::CColor::skWhite)}); + const_cast(this)->x10_solidModelData->AnimationData()->Render(model, flags, {}, nullptr); + //g_Renderer->SetAmbientColor(zeus::CColor::skWhite); + //CGraphics::DisableAllLights(); + } } void CGunWeapon::UpdateMuzzleFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, bool emitting) { + x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetGlobalTranslation(pos); + x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetGlobalScale(scale); + x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetParticleEmission(emitting); + x1a4_muzzleGenerators[x208_muzzleEffectIdx]->Update(dt); +} +void CGunWeapon::ReturnToDefault(CStateManager& mgr) +{ + x100_gunController->ReturnToDefault(mgr, 0.f, false); +} + +bool CGunWeapon::PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle) +{ + switch (state) + { + case SamusGun::EAnimationState::ComboFire: + x100_gunController->EnterComboFire(mgr, s32(x200_beamId)); + return true; + default: + return false; + case SamusGun::EAnimationState::Wander: + return true; + } +} + +void CGunWeapon::UnLoadFidget() +{ + x100_gunController->UnLoadFidget(); +} + +bool CGunWeapon::IsFidgetLoaded() const +{ + return x100_gunController->IsFidgetLoaded(); +} + +void CGunWeapon::AsyncLoadFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 animSet) +{ + x100_gunController->LoadFidgetAnimAsync(mgr, s32(type), s32(x200_beamId), animSet); +} + +void CGunWeapon::EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2) +{ + x100_gunController->EnterFidget(mgr, s32(type), s32(x200_beamId), parm2); +} + +CDamageInfo CGunWeapon::GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr) const +{ + CDamageInfo ret(shotParam); + if (g_GameState->GetHardMode()) + ret.MultiplyDamage(g_GameState->GetHardModeWeaponMultiplier()); + return ret; +} + +CDamageInfo CGunWeapon::GetDamageInfo(CStateManager& mgr, EChargeState chargeState, float chargeFactor) const +{ + const SWeaponInfo& wInfo = GetWeaponInfo(); + if (chargeState == EChargeState::Normal) + { + return GetShotDamageInfo(wInfo.x4_normal, mgr); + } + else + { + SShotParam param = wInfo.x20_charged; + param.damage *= chargeFactor; + param.radiusDamage *= chargeFactor; + param.radius *= chargeFactor; + param.knockback *= chargeFactor; + param.noImmunity = false; + return GetShotDamageInfo(param, mgr); + } } const SWeaponInfo& CGunWeapon::GetWeaponInfo() const @@ -145,7 +722,7 @@ zeus::CAABox CGunWeapon::GetBounds(const zeus::CTransform& xf) const bool CGunWeapon::IsChargeAnimOver() const { - return false; + return !(x218_25_enableCharge && x10_solidModelData->GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body")); } } diff --git a/Runtime/Weapon/CGunWeapon.hpp b/Runtime/Weapon/CGunWeapon.hpp index 2ebfd9627..501d5ee10 100644 --- a/Runtime/Weapon/CGunWeapon.hpp +++ b/Runtime/Weapon/CGunWeapon.hpp @@ -13,6 +13,7 @@ #include "CGunController.hpp" #include "WeaponCommon.hpp" #include "CGunMotion.hpp" +#include "World/CDamageInfo.hpp" namespace urde { @@ -28,16 +29,24 @@ enum class EChargeState }; using SWeaponInfo = DataSpec::SWeaponInfo; +using SShotParam = DataSpec::SShotParam; +using SChargedShotParam = DataSpec::SChargedShotParam; class CVelocityInfo { friend class CGunWeapon; rstl::reserved_vector x0_vel; rstl::reserved_vector x1c_targetHoming; - rstl::reserved_vector x24_; + rstl::reserved_vector x24_trat; public: const zeus::CVector3f& GetVelocity(int i) const { return x0_vel[i]; } bool GetTargetHoming(int i) const { return x1c_targetHoming[i]; } + void Clear() + { + x0_vel.clear(); + x1c_targetHoming.clear(); + x24_trat.clear(); + } }; class CGunWeapon @@ -50,33 +59,39 @@ public: Two, Three }; + enum class EFrozenFxType + { + None, + Frozen, + Thawed + }; protected: - static const char* skBeamXferNames[5]; - static const char* skAnimDependencyNames[5]; - static const char* skDependencyNames[5]; - static const char* skSuitArmNames[8]; + static const s32 skShootAnim[2]; zeus::CVector3f x4_scale; std::experimental::optional x10_solidModelData; - std::experimental::optional x60_; - std::experimental::optional xb0_; + std::experimental::optional x60_holoModelData; + std::experimental::optional xb0_suitArmModelData; std::unique_ptr x100_gunController; TToken x104_gunCharacter; + std::vector x10c_anims; + std::vector x12c_deps; TToken x13c_armCharacter; rstl::reserved_vector, 2> x144_weapons; TCachedToken x160_xferEffect; rstl::reserved_vector, 2> x16c_muzzleEffects; - rstl::reserved_vector, 2> x188_secondaryEffects; + rstl::reserved_vector, 2> x188_frozenEffects; rstl::reserved_vector, 2> x1a4_muzzleGenerators; - std::unique_ptr x1b8_secondaryEffect; + std::unique_ptr x1b8_frozenGenerator; CRainSplashGenerator* x1bc_rainSplashGenerator = nullptr; EWeaponType x1c0_weaponType; TUniqueId x1c4_playerId; EMaterialTypes x1c8_playerMaterial; + ESecondaryFxType x1cc_enabledSecondaryEffect = ESecondaryFxType::Zero; CVelocityInfo x1d0_velInfo; CPlayerState::EBeamId x200_beamId; - ESecondaryFxType x204_secondaryEffectType = ESecondaryFxType::Zero; - u32 x208_ = 0; - CPlayerState::EBeamId x20c_; + EFrozenFxType x204_frozenEffect = EFrozenFxType::None; + u32 x208_muzzleEffectIdx = 0; + u32 x20c_shaderIdx; u32 x210_ = 0; CAssetId x214_ancsId; union @@ -85,61 +100,78 @@ protected: { bool x218_24 : 1; bool x218_25_enableCharge : 1; - bool x218_26 : 1; - bool x218_27 : 1; - bool x218_28 : 1; - bool x218_29_leavingBeam : 1; + bool x218_26_loaded : 1; + // Initialize in selected beam's pose, rather than power beam's pose + bool x218_27_subtypeBasePose : 1; + bool x218_28_suitArmLocked : 1; + bool x218_29_drawHologram : 1; }; u32 _dummy = 0; }; + void AllocResPools(CPlayerState::EBeamId beam); + void FreeResPools(); + void FillTokenVector(const std::vector& tags, std::vector& objects); + void BuildDependencyList(CPlayerState::EBeamId beam); + CDamageInfo GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr) const; + void LoadSuitArm(CStateManager& mgr); + void LoadGunModels(CStateManager& mgr); + void LoadAnimations(); + bool IsAnimsLoaded() const; + void LoadMuzzleFx(float dt); + void LoadProjectileData(CStateManager& mgr); + void LoadFxIdle(float dt, CStateManager& mgr); + void LockTokens(CStateManager& mgr); + void UnlockTokens(); + + static void PointGenerator(void* ctx, const std::vector>& vn); + public: - CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, EMaterialTypes, const zeus::CVector3f& scale); + CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale); void AsyncLoadSuitArm(CStateManager& mgr); - void AllocResPools(CPlayerState::EBeamId); - virtual void Reset(CStateManager&) {} + virtual void Reset(CStateManager& mgr); virtual void PlayAnim(NWeaponTypes::EGunAnimType type, bool loop); - virtual void PreRenderGunFx(const CStateManager&, const zeus::CTransform&) {} - virtual void PostRenderGunFx(const CStateManager&, const zeus::CTransform&) {} - virtual void UpdateGunFx(bool shotSmoke, float, const CStateManager&, const zeus::CTransform&) {} + virtual void PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + virtual void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + virtual void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); virtual void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget) {} - virtual void EnableFx(bool) {} - virtual void EnableSecondaryFx(ESecondaryFxType) {} - void BuildSecondaryEffect(ESecondaryFxType type); - void ActivateCharge(bool b1, bool b2); + CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); + virtual void EnableFx(bool enable); + virtual void EnableSecondaryFx(ESecondaryFxType type); + void EnableFrozenEffect(EFrozenFxType type); + void ActivateCharge(bool enable, bool resetEffect); void Touch(const CStateManager& mgr); void TouchHolo(const CStateManager& mgr); - virtual void Draw(bool, const CStateManager&, const zeus::CTransform&, const CModelFlags&, - const CActorLights*) const {} - virtual void DrawMuzzleFx(const CStateManager&) const {} - virtual void Update(float, CStateManager&) {} - virtual void Load(CStateManager& mgr, bool) {} - virtual void Unload(CStateManager&) {} - virtual bool IsLoaded() const {return false;} + virtual void Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, + const CModelFlags& flags, const CActorLights* lights) const; + virtual void DrawMuzzleFx(const CStateManager& mgr) const; + virtual void Update(float dt, CStateManager& mgr); + virtual void Load(CStateManager& mgr, bool subtypeBasePose); + virtual void Unload(CStateManager& mgr); + virtual bool IsLoaded() const; void DrawHologram(const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags) const; void UpdateMuzzleFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, bool emitting); const CVelocityInfo& GetVelocityInfo() const { return x1d0_velInfo; } void SetRainSplashGenerator(CRainSplashGenerator* g) { x1bc_rainSplashGenerator = g; } CElementGen* GetChargeMuzzleFx() const { return x1a4_muzzleGenerators[1].get(); } const TToken& GetComboXferDescr() const { return x160_xferEffect; } - void ReturnToDefault(CStateManager& mgr) {} - bool PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle) { return false; } - void UnLoadFidget() {} - bool IsFidgetLoaded() const { return x100_gunController->IsFidgetLoaded(); } - void AsyncLoadFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 animSet) - { x100_gunController->LoadFidgetAnimAsync(mgr, s32(type), s32(x200_beamId), animSet); } - void EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2) - { x100_gunController->EnterFidget(mgr, s32(type), s32(x200_beamId), parm2); } + void ReturnToDefault(CStateManager& mgr); + bool PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle); + void UnLoadFidget(); + bool IsFidgetLoaded() const; + void AsyncLoadFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 animSet); + void EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2); bool HasSolidModelData() const { return x10_solidModelData.operator bool(); } CModelData& GetSolidModelData() { return *x10_solidModelData; } const SWeaponInfo& GetWeaponInfo() const; + CDamageInfo GetDamageInfo(CStateManager& mgr, EChargeState chargeState, float chargeFactor) const; EWeaponType GetWeaponType() const { return x1c0_weaponType; } zeus::CAABox GetBounds() const; zeus::CAABox GetBounds(const zeus::CTransform& xf) const; bool ComboFireOver() const { return x100_gunController->IsComboOver(); } bool IsChargeAnimOver() const; - void SetLeavingBeam(bool leaving) { x218_29_leavingBeam = leaving; } + void SetDrawHologram(bool d) { x218_29_drawHologram = d; } void EnableCharge(bool c) { x218_25_enableCharge = c; } }; } diff --git a/Runtime/Weapon/CPlasmaProjectile.cpp b/Runtime/Weapon/CPlasmaProjectile.cpp index 264f56cc1..2a4841618 100644 --- a/Runtime/Weapon/CPlasmaProjectile.cpp +++ b/Runtime/Weapon/CPlasmaProjectile.cpp @@ -6,9 +6,10 @@ namespace urde CPlasmaProjectile::CPlasmaProjectile(const TToken& wDesc, const std::string& name, EWeaponType wType, const CBeamInfo& bInfo, const zeus::CTransform& xf, - EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId owner, TAreaId aid, - TUniqueId uid, u32 w1, bool b1, u32 w2) -: CBeamProjectile(wDesc, name, wType, xf, bInfo.x18_, bInfo.x1c_, bInfo.x38_, matType, dInfo, owner, aid, uid, w2, b1) + EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, + TUniqueId owner, u32 w1, bool b1, EProjectileAttrib attribs) +: CBeamProjectile(wDesc, name, wType, xf, bInfo.x18_, bInfo.x1c_, bInfo.x38_, matType, + dInfo, uid, aid, owner, attribs, b1) { } diff --git a/Runtime/Weapon/CPlasmaProjectile.hpp b/Runtime/Weapon/CPlasmaProjectile.hpp index c7b691e3a..b81af922a 100644 --- a/Runtime/Weapon/CPlasmaProjectile.hpp +++ b/Runtime/Weapon/CPlasmaProjectile.hpp @@ -10,9 +10,10 @@ namespace urde class CPlasmaProjectile : public CBeamProjectile { public: - CPlasmaProjectile(const TToken&, const std::string&, EWeaponType, const CBeamInfo&, - const zeus::CTransform&, EMaterialTypes, const CDamageInfo&, TUniqueId, TAreaId, TUniqueId, u32, - bool, u32); + CPlasmaProjectile(const TToken& wDesc, const std::string& name, + EWeaponType wType, const CBeamInfo& bInfo, const zeus::CTransform& xf, + EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, + TUniqueId owner, u32 w1, bool b1, EProjectileAttrib attribs); void Accept(IVisitor& visitor); diff --git a/Runtime/Weapon/CPlayerGun.cpp b/Runtime/Weapon/CPlayerGun.cpp index 4cf66265d..518745551 100644 --- a/Runtime/Weapon/CPlayerGun.cpp +++ b/Runtime/Weapon/CPlayerGun.cpp @@ -1155,7 +1155,7 @@ void CPlayerGun::StartPhazonBeamTransition(bool active, CStateManager& mgr, CPla SetPhazonBeamFeedback(active); x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); x72c_currentBeam->EnableFx(true); - x72c_currentBeam->SetLeavingBeam(false); + x72c_currentBeam->SetDrawHologram(false); PlayAnim(NWeaponTypes::EGunAnimType::ToBeam, false); if (x833_31_inFreeLook) EnterFreeLook(mgr); @@ -1656,7 +1656,8 @@ void CPlayerGun::UpdateNormalShotCycle(float dt, CStateManager& mgr) homingTarget = GetTargetId(mgr); else homingTarget = kInvalidUniqueId; - x72c_currentBeam->Fire(x834_27_underwater, dt, x330_chargeState, xf, mgr, homingTarget); + x72c_currentBeam->Fire(x834_27_underwater, dt, x330_chargeState, xf, mgr, homingTarget, + x340_chargeBeamFactor, x340_chargeBeamFactor); mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::Zero); } @@ -2076,11 +2077,11 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM if (becameFrozen) { x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Zero); - x72c_currentBeam->BuildSecondaryEffect(CGunWeapon::ESecondaryFxType::One); + x72c_currentBeam->EnableFrozenEffect(CGunWeapon::EFrozenFxType::Frozen); } else if (becameThawed) { - x72c_currentBeam->BuildSecondaryEffect(CGunWeapon::ESecondaryFxType::Two); + x72c_currentBeam->EnableFrozenEffect(CGunWeapon::EFrozenFxType::Thawed); } if (becameFrozen || becameThawed) @@ -2151,14 +2152,14 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM case ENextState::EnterPhazonBeam: if (x75c_phazonBeam->IsLoaded()) break; - x72c_currentBeam->SetLeavingBeam(true); + x72c_currentBeam->SetDrawHologram(true); x75c_phazonBeam->Load(mgr, false); x33c_phazonBeamState = EPhazonBeamState::Entering; break; case ENextState::ExitPhazonBeam: if (x738_nextBeam->IsLoaded()) break; - x72c_currentBeam->SetLeavingBeam(true); + x72c_currentBeam->SetDrawHologram(true); x738_nextBeam->Load(mgr, false); x33c_phazonBeamState = EPhazonBeamState::Exiting; break; @@ -2515,7 +2516,7 @@ void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, co x744_auxWeapon->RenderMuzzleFx(); x72c_currentBeam->PreRenderGunFx(mgr, offsetWorldXf); - bool r26 = !x740_grappleArm->IsGrappling() && + bool drawSuitArm = !x740_grappleArm->IsGrappling() && mgr.GetPlayer().GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn; x73c_gunMotion->Draw(mgr, offsetWorldXf); @@ -2531,7 +2532,7 @@ void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, co kHandThermalFlag : kHandHoloFlag); } DrawArm(mgr, pos, flags); - x72c_currentBeam->Draw(r26, mgr, offsetWorldXf, useFlags, &x0_lights); + x72c_currentBeam->Draw(drawSuitArm, mgr, offsetWorldXf, useFlags, &x0_lights); x82c_shadow->DisableModelProjectedShadow(); break; case CGunMorph::EGunState::InWipeDone: @@ -2550,7 +2551,7 @@ void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, co x82c_shadow->EnableModelProjectedShadow(offsetWorldXf, x0_lights.GetShadowLightArrIndex(), 2.15f); CGraphics::SetModelMatrix(morphXf); DrawClipCube(x6c8_hologramClipCube); - x72c_currentBeam->Draw(r26, mgr, offsetWorldXf, useFlags, &x0_lights); + x72c_currentBeam->Draw(drawSuitArm, mgr, offsetWorldXf, useFlags, &x0_lights); x82c_shadow->DisableModelProjectedShadow(); } else diff --git a/Runtime/Weapon/CWeapon.cpp b/Runtime/Weapon/CWeapon.cpp index d44f4890d..29b289adb 100644 --- a/Runtime/Weapon/CWeapon.cpp +++ b/Runtime/Weapon/CWeapon.cpp @@ -5,9 +5,9 @@ namespace urde { -CWeapon::CWeapon(TUniqueId uid, TAreaId aid, bool active, TUniqueId, EWeaponType, const std::string& name, - const zeus::CTransform& xf, const CMaterialFilter& filter, const CMaterialList& mList, const CDamageInfo&, - EProjectileAttrib, CModelData&& mData) +CWeapon::CWeapon(TUniqueId uid, TAreaId aid, bool active, TUniqueId owner, EWeaponType type, + const std::string& name, const zeus::CTransform& xf, const CMaterialFilter& filter, + const CMaterialList& mList, const CDamageInfo&, EProjectileAttrib attribs, CModelData&& mData) : CActor(uid, active, name, CEntityInfo(aid, CEntity::NullConnectionList), xf, std::move(mData), mList, CActorParameters::None(), kInvalidUniqueId) , xf8_(filter) diff --git a/Runtime/Weapon/CWeapon.hpp b/Runtime/Weapon/CWeapon.hpp index c8efd9caf..691bc5c23 100644 --- a/Runtime/Weapon/CWeapon.hpp +++ b/Runtime/Weapon/CWeapon.hpp @@ -14,6 +14,9 @@ public: enum class EProjectileAttrib { None = 0, + PartialCharge = (1 << 0), + PlasmaProjectile = (1 << 1), + Charged = (1 << 2), Ice = (1 << 3), Wave = (1 << 4), Plasma = (1 << 5), @@ -21,6 +24,7 @@ public: Unknown1 = (1 << 7), Bombs = (1 << 8), PowerBombs = (1 << 9), + ArmCannon = (1 << 11), BigStrike = (1 << 12), StaticInterference = (1 << 14), }; @@ -39,8 +43,9 @@ private: float x150_damageDuration; float x154_interferenceDuration; public: - CWeapon(TUniqueId, TAreaId, bool, TUniqueId, EWeaponType, const std::string&, const zeus::CTransform&, - const CMaterialFilter&, const CMaterialList&, const CDamageInfo&, EProjectileAttrib, CModelData&&); + CWeapon(TUniqueId uid, TAreaId aid, bool active, TUniqueId owner, EWeaponType type, + const std::string& name, const zeus::CTransform& xf, const CMaterialFilter& filter, + const CMaterialList& mList, const CDamageInfo&, EProjectileAttrib attribs, CModelData&& mData); virtual void Accept(IVisitor &visitor); bool HasAttrib(EProjectileAttrib) const; diff --git a/Runtime/World/CDamageInfo.cpp b/Runtime/World/CDamageInfo.cpp index d9f790fd8..292b1b631 100644 --- a/Runtime/World/CDamageInfo.cpp +++ b/Runtime/World/CDamageInfo.cpp @@ -6,22 +6,23 @@ namespace urde { CDamageInfo::CDamageInfo(const DataSpec::SShotParam& other) -: x0_weaponMode(CWeaponMode(EWeaponType(other.weaponType), other.Charged(), other.Comboed(), other.InstaKill())) +: x0_weaponMode(CWeaponMode(EWeaponType(other.weaponType), other.charged, other.combo, other.instaKill)) , x8_damage(other.damage) , xc_radiusDamage(other.radiusDamage) , x10_radius(other.radius) , x14_knockback(other.knockback) +, x18_noImmunity(other.noImmunity) { } CDamageInfo& CDamageInfo::operator=(const DataSpec::SShotParam& other) { - x0_weaponMode = CWeaponMode(EWeaponType(other.weaponType), other.Charged(), other.Comboed(), other.InstaKill()); + x0_weaponMode = CWeaponMode(EWeaponType(other.weaponType), other.charged, other.combo, other.instaKill); x8_damage = other.damage; - xc_radiusDamage = x8_damage; + xc_radiusDamage = other.radiusDamage; x10_radius = other.radius; x14_knockback = other.knockback; - x18_noImmunity = false; + x18_noImmunity = other.noImmunity; return *this; } diff --git a/Runtime/World/CDamageInfo.hpp b/Runtime/World/CDamageInfo.hpp index afd7f21fa..412ea7af8 100644 --- a/Runtime/World/CDamageInfo.hpp +++ b/Runtime/World/CDamageInfo.hpp @@ -51,6 +51,12 @@ public: float GetRadiusDamage() const { return xc_radiusDamage; } float GetRadiusDamage(const CDamageVulnerability& dVuln) const; bool NoImmunity() const { return x18_noImmunity; } + void MultiplyDamage(float m) + { + x8_damage *= m; + xc_radiusDamage *= m; + x14_knockback *= m; + } }; } diff --git a/Runtime/World/CPlayer.hpp b/Runtime/World/CPlayer.hpp index 28e8adb1a..9e666cba0 100644 --- a/Runtime/World/CPlayer.hpp +++ b/Runtime/World/CPlayer.hpp @@ -425,8 +425,9 @@ private: float CalculateOrbitMinDistance(EPlayerOrbitType type) const; public: - CPlayer(TUniqueId, const zeus::CTransform&, const zeus::CAABox&, CAssetId w1, const zeus::CVector3f&, float, float, - float, float, const CMaterialList&); + CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox& aabb, CAssetId resId, + const zeus::CVector3f& playerScale, float mass, float stepUp, float stepDown, float ballRadius, + const CMaterialList& ml); bool IsTransparent() const; bool GetControlsFrozen() const { return x760_controlsFrozen; } diff --git a/Runtime/World/CScriptBeam.cpp b/Runtime/World/CScriptBeam.cpp index ad6e58ad1..f606d50fd 100644 --- a/Runtime/World/CScriptBeam.cpp +++ b/Runtime/World/CScriptBeam.cpp @@ -50,7 +50,7 @@ void CScriptBeam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CSt mgr.AddObject(new CPlasmaProjectile(xe8_weaponDescription, x10_name + "-Projectile", x138_damageInfo.GetWeaponMode().GetType(), xf4_beamInfo, x34_transform, EMaterialTypes::Projectile, x138_damageInfo, x8_uid, x4_areaId, - x154_projectileId, 8, false, 2)); + x154_projectileId, 8, false, CWeapon::EProjectileAttrib::PlasmaProjectile)); } else if (msg == EScriptObjectMessage::Deleted) { diff --git a/hecl b/hecl index af4857cfa..806a802cf 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit af4857cfae81cb2ca03526bdbb76335d913a6e24 +Subproject commit 806a802cff2bf5dc72afcc8145852e595cfdc654