Finish CGunWeapon

This commit is contained in:
Jack Andersen 2017-09-04 17:00:19 -10:00
parent 640623f3ef
commit 361aa1512b
38 changed files with 990 additions and 169 deletions

View File

@ -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:

View File

@ -6,29 +6,32 @@
namespace DataSpec
{
/* Same as CDamageInfo */
struct SShotParam : BigYAML
{
DECL_YAML
Value<atUint32> weaponType = -1;
Value<atInt32> weaponType = -1;
bool charged : 1;
bool combo : 1;
bool instaKill : 1;
Value<float> damage = 0.f;
Value<float> radiusDamage = 0.f;
Value<float> radius = 0.f;
Value<float> 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

View File

@ -95,7 +95,8 @@ public:
Ice,
Wave,
Plasma,
Phazon = 27
Phazon,
Phazon2 = 27
};
private:

View File

@ -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();
}

View File

@ -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;

View File

@ -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()};
}

View File

@ -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);

View File

@ -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))

View File

@ -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<CBooModel>& PickStaticModel(EWhichModel which) const;

View File

@ -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<CElementGenShaders>::BuildShaderDataBinding(ctx, shad);
}

View File

@ -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:

View File

@ -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<CElementGenShaders>::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<CElementGenShaders>::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<CElementGenShaders>::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<CElementGenShaders>::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,

View File

@ -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<CElementGenShaders>::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<CElementGenShaders>::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,

View File

@ -71,8 +71,7 @@ static const char* FS_METAL_TEX_REDTOALPHA =
"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n"
" texture2d<float> 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<CElementGenShaders>::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<CElementGenShaders>::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<CElementGenShaders>::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,

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -5,9 +5,10 @@ namespace urde
{
CBeamProjectile::CBeamProjectile(const TToken<CWeaponDescription>& 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)
{
}

View File

@ -7,8 +7,10 @@ namespace urde
class CBeamProjectile : public CGameProjectile
{
public:
CBeamProjectile(const TToken<CWeaponDescription>&, const std::string&, EWeaponType, const zeus::CTransform&, int,
float, float, EMaterialTypes, const CDamageInfo&, TUniqueId, TAreaId, TUniqueId, u32, bool);
CBeamProjectile(const TToken<CWeaponDescription>& 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;

View File

@ -5,12 +5,12 @@ namespace urde
CEnergyProjectile::CEnergyProjectile(bool active, const TToken<CWeaponDescription>& 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<TLockedToken<CGenDescription>>& 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))
{

View File

@ -28,8 +28,8 @@ class CEnergyProjectile : public CGameProjectile
public:
CEnergyProjectile(bool active, const TToken<CWeaponDescription>& 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<TLockedToken<CGenDescription>>& particle,
s16 w2, bool b2);
};

View File

@ -10,9 +10,9 @@ const zeus::CVector3f CFlameThrower::kLightOffset(0, 3.f, 2.f);
CFlameThrower::CFlameThrower(const TToken<CWeaponDescription>& 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()}))

View File

@ -27,8 +27,8 @@ class CFlameThrower : public CGameProjectile
public:
CFlameThrower(const TToken<CWeaponDescription>& 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);

View File

@ -8,14 +8,15 @@ namespace urde
{
CGameProjectile::CGameProjectile(bool active, const TToken<CWeaponDescription>&, 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<TLockedToken<CGenDescription>>&, 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<TLockedToken<CGenDescription>>& 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)

View File

@ -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<CWeaponDescription>&, const std::string&, EWeaponType, const zeus::CTransform&,
EMaterialTypes, const CDamageInfo&, TUniqueId, TAreaId, TUniqueId, TUniqueId, u32, bool,
const zeus::CVector3f&, const rstl::optional_object<TLockedToken<CGenDescription>>&, s16, bool);
CGameProjectile(bool active, const TToken<CWeaponDescription>&, 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<TLockedToken<CGenDescription>>& particle, s16 s1, bool b3);
virtual void Accept(IVisitor &visitor);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &);

View File

@ -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<SObjectTag>& tags, std::vector<CToken>& objects)
{
for (const SObjectTag& tag : tags)
objects.push_back(g_SimplePool->GetObj(tag));
}
void CGunWeapon::BuildDependencyList(CPlayerState::EBeamId beam)
{
TLockedToken<CDependencyGroup> deps = g_SimplePool->GetObj(skDependencyNames[int(beam)]);
TLockedToken<CDependencyGroup> 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<CElementGen>(x188_secondaryEffects[1],
x1b8_frozenGenerator = std::make_unique<CElementGen>(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<CElementGen>(x188_secondaryEffects[0],
x1b8_frozenGenerator = std::make_unique<CElementGen>(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<CElementGen>(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<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn)
{
reinterpret_cast<CRainSplashGenerator*>(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<CElementGen*>(effect)->Render();
CElementGen::SetSubtractBlend(false);
}
else
{
const_cast<CElementGen*>(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<CGunController>(*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<CElementGen>(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<CSkinnedModel&>(*x60_holoModelData->GetAnimationData()->GetModelData());
model.GetModelInst()->ActivateLights({CLight::BuildLocalAmbient({}, zeus::CColor::skWhite)});
const_cast<CGunWeapon*>(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"));
}
}

View File

@ -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<zeus::CVector3f, 2> x0_vel;
rstl::reserved_vector<bool, 2> x1c_targetHoming;
rstl::reserved_vector<float, 2> x24_;
rstl::reserved_vector<float, 2> 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<CModelData> x10_solidModelData;
std::experimental::optional<CModelData> x60_;
std::experimental::optional<CModelData> xb0_;
std::experimental::optional<CModelData> x60_holoModelData;
std::experimental::optional<CModelData> xb0_suitArmModelData;
std::unique_ptr<CGunController> x100_gunController;
TToken<CAnimCharacterSet> x104_gunCharacter;
std::vector<CToken> x10c_anims;
std::vector<CToken> x12c_deps;
TToken<CAnimCharacterSet> x13c_armCharacter;
rstl::reserved_vector<TCachedToken<CWeaponDescription>, 2> x144_weapons;
TCachedToken<CGenDescription> x160_xferEffect;
rstl::reserved_vector<TCachedToken<CGenDescription>, 2> x16c_muzzleEffects;
rstl::reserved_vector<TCachedToken<CGenDescription>, 2> x188_secondaryEffects;
rstl::reserved_vector<TCachedToken<CGenDescription>, 2> x188_frozenEffects;
rstl::reserved_vector<std::unique_ptr<CElementGen>, 2> x1a4_muzzleGenerators;
std::unique_ptr<CElementGen> x1b8_secondaryEffect;
std::unique_ptr<CElementGen> 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<SObjectTag>& tags, std::vector<CToken>& 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<std::pair<zeus::CVector3f, zeus::CVector3f>>& 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<CGenDescription>& 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; }
};
}

View File

@ -6,9 +6,10 @@ namespace urde
CPlasmaProjectile::CPlasmaProjectile(const TToken<CWeaponDescription>& 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)
{
}

View File

@ -10,9 +10,10 @@ namespace urde
class CPlasmaProjectile : public CBeamProjectile
{
public:
CPlasmaProjectile(const TToken<CWeaponDescription>&, const std::string&, EWeaponType, const CBeamInfo&,
const zeus::CTransform&, EMaterialTypes, const CDamageInfo&, TUniqueId, TAreaId, TUniqueId, u32,
bool, u32);
CPlasmaProjectile(const TToken<CWeaponDescription>& 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);

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
};
}

View File

@ -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; }

View File

@ -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)
{

2
hecl

@ -1 +1 @@
Subproject commit af4857cfae81cb2ca03526bdbb76335d913a6e24
Subproject commit 806a802cff2bf5dc72afcc8145852e595cfdc654