2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-05-13 23:11:20 +00:00

Implement CPlasmaProjectile

This commit is contained in:
Jack Andersen 2019-01-02 17:47:28 -10:00
parent 4f3c8daf27
commit 5b55320e9b
30 changed files with 1203 additions and 238 deletions

View File

@ -12,6 +12,25 @@
<option name="SPACE_AFTER_REFERENCE_IN_DECLARATION" value="true" /> <option name="SPACE_AFTER_REFERENCE_IN_DECLARATION" value="true" />
</Objective-C> </Objective-C>
<Objective-C-extensions> <Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions> <extensions>
<pair source="cpp" header="hpp" fileNamingConvention="NONE" /> <pair source="cpp" header="hpp" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" /> <pair source="c" header="h" fileNamingConvention="NONE" />

View File

@ -17,31 +17,31 @@ struct NewIntroBoss : IScriptObject {
Value<float> unknown1; Value<float> unknown1;
UniqueID32 weaponDesc; UniqueID32 weaponDesc;
DamageInfo damageInfo; DamageInfo damageInfo;
UniqueID32 particle1; UniqueID32 beamContactFxId;
UniqueID32 particle2; UniqueID32 beamPulseFxId;
UniqueID32 texture1; UniqueID32 beamTextureId;
UniqueID32 texture2; UniqueID32 beamGlowTextureId;
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const { void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const {
actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters);
} }
void nameIDs(PAKRouter<PAKBridge>& pakRouter) const { void nameIDs(PAKRouter<PAKBridge>& pakRouter) const {
if (particle1) { if (beamContactFxId) {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(beamContactFxId);
ent->name = name + "_part1"; ent->name = name + "_beamContactFxId";
} }
if (particle2) { if (beamPulseFxId) {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(beamPulseFxId);
ent->name = name + "_part2"; ent->name = name + "_beamPulseFxId";
} }
if (texture1) { if (beamTextureId) {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(beamTextureId);
ent->name = name + "_tex1"; ent->name = name + "_beamTextureId";
} }
if (texture2) { if (beamGlowTextureId) {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(beamGlowTextureId);
ent->name = name + "_tex2"; ent->name = name + "_beamGlowTextureId";
} }
patternedInfo.nameIDs(pakRouter, name + "_patterned"); patternedInfo.nameIDs(pakRouter, name + "_patterned");
actorParameters.nameIDs(pakRouter, name + "_actp"); actorParameters.nameIDs(pakRouter, name + "_actp");
@ -49,10 +49,10 @@ struct NewIntroBoss : IScriptObject {
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut, std::vector<hecl::ProjectPath>& lazyOut) const { void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut, std::vector<hecl::ProjectPath>& lazyOut) const {
g_curSpec->flattenDependencies(weaponDesc, pathsOut); g_curSpec->flattenDependencies(weaponDesc, pathsOut);
g_curSpec->flattenDependencies(particle1, pathsOut); g_curSpec->flattenDependencies(beamContactFxId, pathsOut);
g_curSpec->flattenDependencies(particle2, pathsOut); g_curSpec->flattenDependencies(beamPulseFxId, pathsOut);
g_curSpec->flattenDependencies(texture1, pathsOut); g_curSpec->flattenDependencies(beamTextureId, pathsOut);
g_curSpec->flattenDependencies(texture2, pathsOut); g_curSpec->flattenDependencies(beamGlowTextureId, pathsOut);
patternedInfo.depIDs(pathsOut); patternedInfo.depIDs(pathsOut);
actorParameters.depIDs(pathsOut, lazyOut); actorParameters.depIDs(pathsOut, lazyOut);
} }

View File

@ -424,47 +424,47 @@ struct ActorParameters : BigDNA {
struct BeamInfo : BigDNA { struct BeamInfo : BigDNA {
AT_DECL_DNA_YAML AT_DECL_DNA_YAML
Value<atUint32> propertyCount; Value<atUint32> propertyCount;
Value<atUint32> unknown1; Value<atUint32> beamAttributes;
UniqueID32 particle1; UniqueID32 contactFxId;
UniqueID32 particle2; UniqueID32 pulseFxId;
UniqueID32 texture1; UniqueID32 textureId;
UniqueID32 texture2; UniqueID32 glowTextureId;
Value<float> unknown2; Value<float> length;
Value<float> unknown3; Value<float> radius;
Value<float> unknown4; Value<float> expansionSpeed;
Value<float> unknown5; Value<float> lifeTime;
Value<float> unknown6; Value<float> pulseSpeed;
Value<float> unknown7; Value<float> shutdownTime;
Value<float> unknown8; Value<float> contactFxScale;
Value<float> unknown9; Value<float> pulseFxScale;
Value<float> unknown10; Value<float> travelSpeed;
DNAColor unknown11; DNAColor innerColor;
DNAColor unknown12; DNAColor outerColor;
void nameIDs(PAKRouter<PAKBridge>& pakRouter, const std::string& name) const { void nameIDs(PAKRouter<PAKBridge>& pakRouter, const std::string& name) const {
if (particle1) { if (contactFxId) {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(contactFxId);
ent->name = name + "_part1"; ent->name = name + "_part1";
} }
if (particle2) { if (pulseFxId) {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(pulseFxId);
ent->name = name + "_part2"; ent->name = name + "_part2";
} }
if (texture1) { if (textureId) {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(textureId);
ent->name = name + "_tex1"; ent->name = name + "_tex1";
} }
if (texture2) { if (glowTextureId) {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(glowTextureId);
ent->name = name + "_tex2"; ent->name = name + "_tex2";
} }
} }
void depIDs(std::vector<hecl::ProjectPath>& pathsOut) const { void depIDs(std::vector<hecl::ProjectPath>& pathsOut) const {
g_curSpec->flattenDependencies(particle1, pathsOut); g_curSpec->flattenDependencies(contactFxId, pathsOut);
g_curSpec->flattenDependencies(particle2, pathsOut); g_curSpec->flattenDependencies(pulseFxId, pathsOut);
g_curSpec->flattenDependencies(texture1, pathsOut); g_curSpec->flattenDependencies(textureId, pathsOut);
g_curSpec->flattenDependencies(texture2, pathsOut); g_curSpec->flattenDependencies(glowTextureId, pathsOut);
} }
}; };

View File

@ -837,7 +837,7 @@ bool CBSJump::CheckForWallJump(CBodyController& bc, CStateManager& mgr) {
float distToWall = (xc_waypoint1 - act->GetTranslation()).magnitude(); float distToWall = (xc_waypoint1 - act->GetTranslation()).magnitude();
zeus::CAABox aabb = act->GetBoundingBox(); zeus::CAABox aabb = act->GetBoundingBox();
float xExtent = (aabb.max.x() - aabb.min.x()) * 0.5f; float xExtent = (aabb.max.x() - aabb.min.x()) * 0.5f;
if (distToWall < 1.414f * xExtent || (act->CanLongJump() && distToWall < 3.f * xExtent)) { if (distToWall < 1.414f * xExtent || (act->MadeSolidCollision() && distToWall < 3.f * xExtent)) {
x4_state = x30_26_wallBounceRight ? pas::EJumpState::WallBounceRight : pas::EJumpState::WallBounceLeft; x4_state = x30_26_wallBounceRight ? pas::EJumpState::WallBounceRight : pas::EJumpState::WallBounceLeft;
CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_jumpType))); CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_jumpType)));
bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); bc.PlayBestAnimation(parms, *mgr.GetActiveRandom());
@ -851,7 +851,7 @@ bool CBSJump::CheckForWallJump(CBodyController& bc, CStateManager& mgr) {
void CBSJump::CheckForLand(CBodyController& bc, CStateManager& mgr) { void CBSJump::CheckForLand(CBodyController& bc, CStateManager& mgr) {
if (TCastToPtr<CPatterned> act = bc.GetOwner()) { if (TCastToPtr<CPatterned> act = bc.GetOwner()) {
if (act->CanLongJump() || act->IsOnGround()) { if (act->MadeSolidCollision() || act->IsOnGround()) {
x4_state = pas::EJumpState::OutOfJump; x4_state = pas::EJumpState::OutOfJump;
CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_jumpType))); CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_jumpType)));
bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); bc.PlayBestAnimation(parms, *mgr.GetActiveRandom());
@ -1044,7 +1044,7 @@ void CBSHurled::PlayLandAnimation(CBodyController& bc, CStateManager& mgr) {
bool CBSHurled::ShouldStartStrikeWall(CBodyController& bc) const { bool CBSHurled::ShouldStartStrikeWall(CBodyController& bc) const {
if (TCastToPtr<CPatterned> ai = bc.GetOwner()) { if (TCastToPtr<CPatterned> ai = bc.GetOwner()) {
if (ai->CanLongJump()) if (ai->MadeSolidCollision())
if (!ai->IsOnGround()) if (!ai->IsOnGround())
return true; return true;
} }
@ -1361,7 +1361,7 @@ void CBSWallHang::FixInPlace(CBodyController& bc) {
bool CBSWallHang::CheckForLand(CBodyController& bc, CStateManager& mgr) { bool CBSWallHang::CheckForLand(CBodyController& bc, CStateManager& mgr) {
if (TCastToPtr<CPatterned> ai = bc.GetOwner()) { if (TCastToPtr<CPatterned> ai = bc.GetOwner()) {
if (ai->CanLongJump() || ai->IsOnGround()) { if (ai->MadeSolidCollision() || ai->IsOnGround()) {
x4_state = pas::EWallHangState::DetachOutOfJump; x4_state = pas::EWallHangState::DetachOutOfJump;
CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state)));
bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); bc.PlayBestAnimation(parms, *mgr.GetActiveRandom());
@ -1379,7 +1379,7 @@ bool CBSWallHang::CheckForWall(CBodyController& bc, CStateManager& mgr) {
if (wp) if (wp)
magSq = (wp->GetTranslation() - ai->GetTranslation()).magSquared(); magSq = (wp->GetTranslation() - ai->GetTranslation()).magSquared();
if (magSq < 1.f || ai->CanLongJump()) { if (magSq < 1.f || ai->MadeSolidCollision()) {
x4_state = pas::EWallHangState::IntoWallHang; x4_state = pas::EWallHangState::IntoWallHang;
CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state)));
std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1);

View File

@ -615,6 +615,16 @@ CBooRenderer::CBooRenderer(IObjectStore& store, IFactory& resFac)
m_staticEntropy = store.GetObj("RandomStaticEntropy"); m_staticEntropy = store.GetObj("RandomStaticEntropy");
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
u8 clearPixel[] = {0, 0, 0, 0};
m_clearTexture = ctx.newStaticTexture(1, 1, 1, boo::TextureFormat::RGBA8,
boo::TextureClampMode::Repeat, clearPixel, 4).get();
u8 blackPixel[] = {0, 0, 0, 255};
m_blackTexture = ctx.newStaticTexture(1, 1, 1, boo::TextureFormat::RGBA8,
boo::TextureClampMode::Repeat, blackPixel, 4).get();
u8 whitePixel[] = {255, 255, 255, 255};
m_whiteTexture = ctx.newStaticTexture(1, 1, 1, boo::TextureFormat::RGBA8,
boo::TextureClampMode::Repeat, whitePixel, 4).get();
GenerateFogVolumeRampTex(ctx); GenerateFogVolumeRampTex(ctx);
GenerateSphereRampTex(ctx); GenerateSphereRampTex(ctx);
m_ballShadowId = ctx.newRenderTexture(m_ballShadowIdW, m_ballShadowIdH, boo::TextureClampMode::Repeat, 1, 0); m_ballShadowId = ctx.newRenderTexture(m_ballShadowIdW, m_ballShadowIdH, boo::TextureClampMode::Repeat, 1, 0);

View File

@ -106,6 +106,10 @@ class CBooRenderer final : public IRenderer {
// boo::ITextureS* xe4_blackTex = nullptr; // boo::ITextureS* xe4_blackTex = nullptr;
bool xee_24_ : 1; bool xee_24_ : 1;
boo::ObjToken<boo::ITexture> m_clearTexture;
boo::ObjToken<boo::ITexture> m_blackTexture;
boo::ObjToken<boo::ITexture> m_whiteTexture;
boo::ObjToken<boo::ITextureR> x14c_reflectionTex; boo::ObjToken<boo::ITextureR> x14c_reflectionTex;
// boo::ITextureS* x150_mirrorRamp = nullptr; // boo::ITextureS* x150_mirrorRamp = nullptr;
boo::ObjToken<boo::ITextureS> x1b8_fogVolumeRamp; boo::ObjToken<boo::ITextureS> x1b8_fogVolumeRamp;
@ -269,6 +273,10 @@ public:
const boo::ObjToken<boo::IGraphicsBufferS>& GetScanLinesEvenVBO() const { return m_scanLinesEvenVBO; } const boo::ObjToken<boo::IGraphicsBufferS>& GetScanLinesEvenVBO() const { return m_scanLinesEvenVBO; }
const boo::ObjToken<boo::IGraphicsBufferS>& GetScanLinesOddVBO() const { return m_scanLinesOddVBO; } const boo::ObjToken<boo::IGraphicsBufferS>& GetScanLinesOddVBO() const { return m_scanLinesOddVBO; }
const boo::ObjToken<boo::ITexture>& GetClearTexture() { return m_clearTexture; }
const boo::ObjToken<boo::ITexture>& GetBlackTexture() { return m_blackTexture; }
const boo::ObjToken<boo::ITexture>& GetWhiteTexture() { return m_whiteTexture; }
static void BindMainDrawTarget() { CGraphics::g_BooMainCommandQueue->setRenderTarget(CGraphics::g_SpareTexture); } static void BindMainDrawTarget() { CGraphics::g_BooMainCommandQueue->setRenderTarget(CGraphics::g_SpareTexture); }
void BindReflectionDrawTarget() { CGraphics::g_BooMainCommandQueue->setRenderTarget(x14c_reflectionTex); } void BindReflectionDrawTarget() { CGraphics::g_BooMainCommandQueue->setRenderTarget(x14c_reflectionTex); }
void BindBallShadowIdTarget() { void BindBallShadowIdTarget() {

View File

@ -22,6 +22,7 @@ set(GRAPHICS_SOURCES
Shaders/CLineRendererShaders.hpp Shaders/CLineRendererShaders.cpp Shaders/CLineRendererShaders.hpp Shaders/CLineRendererShaders.cpp
Shaders/CTexturedQuadFilter.hpp Shaders/CTexturedQuadFilter.cpp Shaders/CTexturedQuadFilter.hpp Shaders/CTexturedQuadFilter.cpp
Shaders/CColoredQuadFilter.hpp Shaders/CColoredQuadFilter.cpp Shaders/CColoredQuadFilter.hpp Shaders/CColoredQuadFilter.cpp
Shaders/CColoredStripShader.hpp Shaders/CColoredStripShader.cpp
Shaders/CModelShaders.hpp Shaders/CModelShaders.cpp Shaders/CModelShaders.hpp Shaders/CModelShaders.cpp
Shaders/CModelShadersGLSL.cpp Shaders/CModelShadersHLSL.cpp Shaders/CModelShadersMetal.cpp Shaders/CModelShadersGLSL.cpp Shaders/CModelShadersHLSL.cpp Shaders/CModelShadersMetal.cpp
Shaders/CThermalColdFilter.hpp Shaders/CThermalColdFilter.cpp Shaders/CThermalColdFilter.hpp Shaders/CThermalColdFilter.cpp

View File

@ -0,0 +1,75 @@
#include "CColoredStripShader.hpp"
#include "Graphics/CGraphics.hpp"
#include "hecl/Pipeline.hpp"
#include "GameGlobalObjects.hpp"
#include "Graphics/CBooRenderer.hpp"
namespace urde {
static boo::ObjToken<boo::IShaderPipeline> s_Pipeline;
static boo::ObjToken<boo::IShaderPipeline> s_AdditivePipeline;
static boo::ObjToken<boo::IShaderPipeline> s_FullAdditivePipeline;
void CColoredStripShader::Initialize() {
s_Pipeline = hecl::conv->convert(Shader_CColoredStripShader{});
s_AdditivePipeline = hecl::conv->convert(Shader_CColoredStripShaderAdditive{});
s_FullAdditivePipeline = hecl::conv->convert(Shader_CColoredStripShaderFullAdditive{});
}
void CColoredStripShader::Shutdown() {
s_Pipeline.reset();
s_AdditivePipeline.reset();
s_FullAdditivePipeline.reset();
}
static const boo::ObjToken<boo::IShaderPipeline>& SelectPipeline(CColoredStripShader::Mode mode) {
switch (mode) {
case CColoredStripShader::Mode::Alpha:
default:
return s_Pipeline;
case CColoredStripShader::Mode::Additive:
return s_AdditivePipeline;
case CColoredStripShader::Mode::FullAdditive:
return s_FullAdditivePipeline;
}
}
void CColoredStripShader::BuildResources(boo::IGraphicsDataFactory::Context& ctx, size_t maxVerts, Mode mode,
boo::ObjToken<boo::ITexture> tex) {
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vert), maxVerts);
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
boo::ObjToken<boo::IGraphicsBuffer> bufs[] = {m_uniBuf.get()};
boo::PipelineStage stages[] = {boo::PipelineStage::Vertex};
boo::ObjToken<boo::ITexture> texs[1];
if (tex)
texs[0] = tex;
else
texs[0] = g_Renderer->GetWhiteTexture();
m_dataBind = ctx.newShaderDataBinding(SelectPipeline(mode), m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr,
nullptr, 1, texs, nullptr, nullptr);
}
CColoredStripShader::CColoredStripShader(size_t maxVerts, Mode mode, boo::ObjToken<boo::ITexture> tex) {
CGraphics::CommitResources([this, maxVerts, mode, tex](boo::IGraphicsDataFactory::Context& ctx) {
BuildResources(ctx, maxVerts, mode, tex);
return true;
} BooTrace);
}
CColoredStripShader::CColoredStripShader(boo::IGraphicsDataFactory::Context& ctx, size_t maxVerts, Mode mode,
boo::ObjToken<boo::ITexture> tex) {
BuildResources(ctx, maxVerts, mode, tex);
}
void CColoredStripShader::draw(const zeus::CColor& color, size_t numVerts, const Vert* verts) {
m_vbo->load(verts, sizeof(Vert) * numVerts);
m_uniform.m_matrix = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f();
m_uniform.m_color = color;
m_uniBuf->load(&m_uniform, sizeof(m_uniform));
CGraphics::SetShaderDataBinding(m_dataBind);
CGraphics::DrawArray(0, numVerts);
}
}

View File

@ -0,0 +1,43 @@
#pragma once
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "zeus/CMatrix4f.hpp"
#include "zeus/CColor.hpp"
namespace urde
{
class CColoredStripShader {
public:
enum class Mode {
Alpha,
Additive,
FullAdditive
};
private:
struct Uniform {
zeus::CMatrix4f m_matrix;
zeus::CColor m_color;
};
boo::ObjToken<boo::IGraphicsBufferD> m_vbo;
boo::ObjToken<boo::IGraphicsBufferD> m_uniBuf;
boo::ObjToken<boo::IShaderDataBinding> m_dataBind;
Uniform m_uniform;
void BuildResources(boo::IGraphicsDataFactory::Context& ctx, size_t maxVerts, Mode mode,
boo::ObjToken<boo::ITexture> tex);
public:
struct Vert {
zeus::CVector3f m_pos;
zeus::CColor m_color;
zeus::CVector2f m_uv;
};
static void Initialize();
static void Shutdown();
CColoredStripShader(size_t maxVerts, Mode mode, boo::ObjToken<boo::ITexture> tex);
CColoredStripShader(boo::IGraphicsDataFactory::Context& ctx, size_t maxVerts, Mode mode,
boo::ObjToken<boo::ITexture> tex);
void draw(const zeus::CColor& color, size_t numVerts, const Vert* verts);
};
}

View File

@ -4,6 +4,7 @@
#include "Graphics/Shaders/CThermalHotFilter.hpp" #include "Graphics/Shaders/CThermalHotFilter.hpp"
#include "Graphics/Shaders/CSpaceWarpFilter.hpp" #include "Graphics/Shaders/CSpaceWarpFilter.hpp"
#include "Graphics/Shaders/CColoredQuadFilter.hpp" #include "Graphics/Shaders/CColoredQuadFilter.hpp"
#include "Graphics/Shaders/CColoredStripShader.hpp"
#include "Graphics/Shaders/CTexturedQuadFilter.hpp" #include "Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Graphics/Shaders/CCameraBlurFilter.hpp" #include "Graphics/Shaders/CCameraBlurFilter.hpp"
#include "Graphics/Shaders/CXRayBlurFilter.hpp" #include "Graphics/Shaders/CXRayBlurFilter.hpp"
@ -244,6 +245,7 @@ CMain::BooSetter::BooSetter(boo::IGraphicsDataFactory* factory, boo::IGraphicsCo
CAABoxShader::Initialize(); CAABoxShader::Initialize();
CWorldShadowShader::Initialize(); CWorldShadowShader::Initialize();
CColoredQuadFilter::Initialize(); CColoredQuadFilter::Initialize();
CColoredStripShader::Initialize();
CTexturedQuadFilter::Initialize(); CTexturedQuadFilter::Initialize();
CTexturedQuadFilterAlpha::Initialize(); CTexturedQuadFilterAlpha::Initialize();
CTextSupportShader::Initialize(); CTextSupportShader::Initialize();
@ -823,6 +825,7 @@ void CMain::Shutdown() {
CAABoxShader::Shutdown(); CAABoxShader::Shutdown();
CWorldShadowShader::Shutdown(); CWorldShadowShader::Shutdown();
CColoredQuadFilter::Shutdown(); CColoredQuadFilter::Shutdown();
CColoredStripShader::Shutdown();
CTexturedQuadFilter::Shutdown(); CTexturedQuadFilter::Shutdown();
CTexturedQuadFilterAlpha::Shutdown(); CTexturedQuadFilterAlpha::Shutdown();
CTextSupportShader::Shutdown(); CTextSupportShader::Shutdown();

View File

@ -477,7 +477,7 @@ void CBeetle::Generate(CStateManager& mgr, EStateMsg msg, float dt) {
AddMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, EMaterialTypes::GroundCollider, mgr); AddMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, EMaterialTypes::GroundCollider, mgr);
x328_25_verticalMovement = false; x328_25_verticalMovement = false;
x838_25_burrowing = false; x838_25_burrowing = false;
if (x328_26_longJump) if (x328_26_solidCollision)
DeathDelete(mgr); DeathDelete(mgr);
break; break;
default: default:
@ -581,7 +581,7 @@ void CBeetle::Attack(CStateManager& mgr, EStateMsg msg, float dt) {
default: default:
break; break;
} }
if (x328_26_longJump) if (x328_26_solidCollision)
x838_24_hitSomething = true; x838_24_hitSomething = true;
break; break;
case EStateMsg::Deactivate: case EStateMsg::Deactivate:

View File

@ -104,7 +104,7 @@ void CEyeball::Think(float dt, CStateManager& mgr) {
if (GetActive()) { if (GetActive()) {
CPlasmaProjectile* projectile = static_cast<CPlasmaProjectile*>(mgr.ObjectById(x5ec_projectileId)); CPlasmaProjectile* projectile = static_cast<CPlasmaProjectile*>(mgr.ObjectById(x5ec_projectileId));
if (projectile && projectile->GetActive()) if (projectile && projectile->GetActive())
projectile->UpdateFX(GetLctrTransform(skEyeLocator), dt, mgr); projectile->UpdateFx(GetLctrTransform(skEyeLocator), dt, mgr);
} }
if (x60c_28_firingBeam) { if (x60c_28_firingBeam) {
@ -125,7 +125,7 @@ void CEyeball::CreateBeam(CStateManager& mgr) {
mgr.AddObject(new CPlasmaProjectile(x5b4_projectileInfo.Token(), "EyeBall_Beam"sv, EWeaponType::AI, beamInfo, mgr.AddObject(new CPlasmaProjectile(x5b4_projectileInfo.Token(), "EyeBall_Beam"sv, EWeaponType::AI, beamInfo,
zeus::CTransform::Identity(), EMaterialTypes::Immovable, zeus::CTransform::Identity(), EMaterialTypes::Immovable,
x5b4_projectileInfo.GetDamage(), x5ec_projectileId, GetAreaIdAlways(), x5b4_projectileInfo.GetDamage(), x5ec_projectileId, GetAreaIdAlways(),
GetUniqueId(), 8, false, EProjectileAttrib::KeepInCinematic)); GetUniqueId(), {}, false, EProjectileAttrib::KeepInCinematic));
} }
void CEyeball::InActive(CStateManager&, EStateMsg msg, float) { void CEyeball::InActive(CStateManager&, EStateMsg msg, float) {

View File

@ -14,17 +14,17 @@ namespace urde::MP1 {
CNewIntroBoss::CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CNewIntroBoss::CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms,
float f1, CAssetId projectile, const CDamageInfo& dInfo, CAssetId part1, CAssetId part2, float f1, CAssetId projectile, const CDamageInfo& dInfo, CAssetId beamContactFxId,
CAssetId tex1, CAssetId tex2) CAssetId beamPulseFxId, CAssetId beamTextureId, CAssetId beamGlowTextureId)
: CPatterned(ECharacter::NewIntroBoss, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, : CPatterned(ECharacter::NewIntroBoss, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Medium) EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Medium)
, x570_(f1) , x570_(f1)
, x574_boneTracking(*GetModelData()->GetAnimationData(), "Head_1"sv, zeus::degToRad(80.f), zeus::degToRad(180.f), false) , x574_boneTracking(*GetModelData()->GetAnimationData(), "Head_1"sv, zeus::degToRad(80.f), zeus::degToRad(180.f), false)
, x5ac_projectileInfo(projectile, dInfo) , x5ac_projectileInfo(projectile, dInfo)
, x5f0_(part1) , x5f0_beamContactFxId(beamContactFxId)
, x5f4_(part2) , x5f4_beamPulseFxId(beamPulseFxId)
, x5f8_(tex1) , x5f8_beamTextureId(beamTextureId)
, x5fc_(tex2) { , x5fc_beamGlowTextureId(beamGlowTextureId) {
const_cast<TToken<CWeaponDescription>*>(&x5ac_projectileInfo.Token())->Lock(); const_cast<TToken<CWeaponDescription>*>(&x5ac_projectileInfo.Token())->Lock();
x574_boneTracking.SetActive(true); x574_boneTracking.SetActive(true);
} }
@ -58,10 +58,12 @@ void CNewIntroBoss::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt
x450_bodyController->Activate(mgr); x450_bodyController->Activate(mgr);
if (x5d4_stage1Projectile == kInvalidUniqueId) { if (x5d4_stage1Projectile == kInvalidUniqueId) {
CBeamInfo stage1BeamInfo = CBeamInfo(3, x5f0_, x5f4_, x5f8_, x5fc_, 50, 1.f, 1.f, 1.5f, 20.f, 1.f, 4.f, 8.f, CBeamInfo stage1BeamInfo(3, x5f0_beamContactFxId, x5f4_beamPulseFxId, x5f8_beamTextureId, x5fc_beamGlowTextureId,
zeus::CColor::skYellow, zeus::CColor(0.1098f, 0.5764f, 0.1592f), 150.f); 50, 1.f, 1.f, 1.5f, 20.f, 1.f, 4.f, 8.f, zeus::CColor::skYellow,
CBeamInfo stage2BeamInfo(3, x5f0_, x5f4_, x5f8_, x5fc_, 50, 1.f, 1.f, 2.f, 20.f, 1.f, 4.f, 8.f, zeus::CColor(0.1098f, 0.5764f, 0.1592f), 150.f);
zeus::CColor::skYellow, zeus::CColor(0.1098f, 0.5764f, 0.1592f), 150.f); CBeamInfo stage2BeamInfo(3, x5f0_beamContactFxId, x5f4_beamPulseFxId, x5f8_beamTextureId, x5fc_beamGlowTextureId,
50, 1.f, 1.f, 2.f, 20.f, 1.f, 4.f, 8.f, zeus::CColor::skYellow,
zeus::CColor(0.1098f, 0.5764f, 0.1592f), 150.f);
x5d4_stage1Projectile = mgr.AllocateUniqueId(); x5d4_stage1Projectile = mgr.AllocateUniqueId();
x5d6_stage2Projectile = mgr.AllocateUniqueId(); x5d6_stage2Projectile = mgr.AllocateUniqueId();
@ -69,15 +71,15 @@ void CNewIntroBoss::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt
CPlasmaProjectile* stage1Projectile = CPlasmaProjectile* stage1Projectile =
new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam"sv, EWeaponType::AI, stage1BeamInfo, {}, new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam"sv, EWeaponType::AI, stage1BeamInfo, {},
EMaterialTypes::Character, x5ac_projectileInfo.GetDamage(), x5d4_stage1Projectile, EMaterialTypes::Character, x5ac_projectileInfo.GetDamage(), x5d4_stage1Projectile,
GetAreaIdAlways(), GetUniqueId(), 8, true, EProjectileAttrib::KeepInCinematic); GetAreaIdAlways(), GetUniqueId(), {}, true, EProjectileAttrib::KeepInCinematic);
CPlasmaProjectile* stage2Projectile = CPlasmaProjectile* stage2Projectile =
new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam_Stage2"sv, EWeaponType::AI, stage2BeamInfo, new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam_Stage2"sv, EWeaponType::AI, stage2BeamInfo,
{}, EMaterialTypes::Character, x5ac_projectileInfo.GetDamage(), x5d6_stage2Projectile, {}, EMaterialTypes::Character, x5ac_projectileInfo.GetDamage(), x5d6_stage2Projectile,
GetAreaIdAlways(), GetUniqueId(), 8, true, EProjectileAttrib::KeepInCinematic); GetAreaIdAlways(), GetUniqueId(), {}, true, EProjectileAttrib::KeepInCinematic);
CPlasmaProjectile* stage3Projectile = CPlasmaProjectile* stage3Projectile =
new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam_Stage2"sv, EWeaponType::AI, stage2BeamInfo, new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam_Stage2"sv, EWeaponType::AI, stage2BeamInfo,
{}, EMaterialTypes::Character, x5ac_projectileInfo.GetDamage(), x5d8_stage3Projectile, {}, EMaterialTypes::Character, x5ac_projectileInfo.GetDamage(), x5d8_stage3Projectile,
GetAreaIdAlways(), GetUniqueId(), 8, true, EProjectileAttrib::KeepInCinematic); GetAreaIdAlways(), GetUniqueId(), {}, true, EProjectileAttrib::KeepInCinematic);
mgr.AddObject(stage1Projectile); mgr.AddObject(stage1Projectile);
mgr.AddObject(stage2Projectile); mgr.AddObject(stage2Projectile);
mgr.AddObject(stage3Projectile); mgr.AddObject(stage3Projectile);
@ -219,16 +221,18 @@ void CNewIntroBoss::Think(float dt, CStateManager& mgr) {
CPlasmaProjectile* curProjectile = static_cast<CPlasmaProjectile*>(mgr.ObjectById(x676_curProjectile)); CPlasmaProjectile* curProjectile = static_cast<CPlasmaProjectile*>(mgr.ObjectById(x676_curProjectile));
if (curProjectile && curProjectile->GetActive()) { if (curProjectile && curProjectile->GetActive()) {
x628_ += dt; x628_firingTime += dt;
zeus::CTransform xf = GetLctrTransform(x5dc_damageLocator); zeus::CTransform xf = GetLctrTransform(x5dc_damageLocator);
if (x400_25_alive) { if (x400_25_alive) {
zeus::CQuaternion clampedQuat = zeus::CQuaternion::clampedRotateTo( zeus::CQuaternion clampedQuat = zeus::CQuaternion::clampedRotateTo(xf.frontVector(),
(x610_lookPos + (zeus::min(x628_ / 1.5f, 1.f) * (x61c_ - x610_lookPos))) - xf.origin, xf.frontVector(), (x610_lookPos + (zeus::min(x628_firingTime / 1.5f, 1.f) * (x61c_startPlayerPos - x610_lookPos))) - xf.origin,
zeus::CRelAngle::FromDegrees(30.f)); zeus::CRelAngle::FromDegrees(30.f));
curProjectile->UpdateFX(clampedQuat.toTransform() * xf.getRotation(), dt, mgr); zeus::CTransform newXf = clampedQuat.toTransform() * xf.getRotation();
newXf.origin = xf.origin;
curProjectile->UpdateFx(newXf, dt, mgr);
} else } else
curProjectile->UpdateFX(xf, dt, mgr); curProjectile->UpdateFx(xf, dt, mgr);
} }
TCastToPtr<CCollisionActor> headAct = mgr.ObjectById(x600_headActor); TCastToPtr<CCollisionActor> headAct = mgr.ObjectById(x600_headActor);
@ -263,7 +267,8 @@ void CNewIntroBoss::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& nod
zeus::CTransform xf = GetLctrTransform(x5dc_damageLocator); zeus::CTransform xf = GetLctrTransform(x5dc_damageLocator);
zeus::CVector3f playerPos = PlayerPos(mgr); zeus::CVector3f playerPos = PlayerPos(mgr);
x604_predictedPlayerPos = x610_lookPos = x62c_targetPos = playerPos; x604_predictedPlayerPos = x610_lookPos = x62c_targetPos = playerPos;
x628_ = 0.f; x61c_startPlayerPos = playerPos;
x628_firingTime = 0.f;
if (GetLocoForHealth(mgr) == pas::ELocomotionType::Combat) if (GetLocoForHealth(mgr) == pas::ELocomotionType::Combat)
x676_curProjectile = x5d8_stage3Projectile; x676_curProjectile = x5d8_stage3Projectile;
else if (GetLocoForHealth(mgr) == pas::ELocomotionType::Lurk) else if (GetLocoForHealth(mgr) == pas::ELocomotionType::Lurk)
@ -337,24 +342,24 @@ bool CNewIntroBoss::ShouldAttack(CStateManager& mgr, float dt) {
bool CNewIntroBoss::AIStage(CStateManager& mgr, float) { return x568_locomotion != GetLocoForHealth(mgr); } bool CNewIntroBoss::AIStage(CStateManager& mgr, float) { return x568_locomotion != GetLocoForHealth(mgr); }
bool CNewIntroBoss::AnimOver(urde::CStateManager&, float) { return x56c_ == 3; } bool CNewIntroBoss::AnimOver(urde::CStateManager&, float) { return x56c_stateProg == 3; }
void CNewIntroBoss::Generate(CStateManager& mgr, EStateMsg msg, float dt) { void CNewIntroBoss::Generate(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) { if (msg == EStateMsg::Activate) {
x56c_ = 0; x56c_stateProg = 0;
x568_locomotion = GetLocoForHealth(mgr); x568_locomotion = GetLocoForHealth(mgr);
SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None);
} else if (msg == EStateMsg::Update) { } else if (msg == EStateMsg::Update) {
if (x56c_ == 0) { if (x56c_stateProg == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) {
x56c_ = 2; x56c_stateProg = 2;
return; return;
} }
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(GetGenerateForHealth(mgr))); x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(GetGenerateForHealth(mgr)));
} else if (x56c_ == 2) { } else if (x56c_stateProg == 2) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) {
x56c_ = 3; x56c_stateProg = 3;
SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None);
} }
} }
@ -373,18 +378,18 @@ bool CNewIntroBoss::InAttackPosition(CStateManager& mgr, float dt) {
void CNewIntroBoss::Attack(CStateManager& mgr, EStateMsg msg, float dt) { void CNewIntroBoss::Attack(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) if (msg == EStateMsg::Activate)
x56c_ = 0; x56c_stateProg = 0;
else if (msg == EStateMsg::Update) { else if (msg == EStateMsg::Update) {
if (x56c_ == 0) { if (x56c_stateProg == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::ProjectileAttack)
x56c_ = 2; x56c_stateProg = 2;
else { else {
x450_bodyController->GetCommandMgr().DeliverCmd( x450_bodyController->GetCommandMgr().DeliverCmd(
CBCProjectileAttackCmd(pas::ESeverity::One, mgr.GetPlayer().GetTranslation(), false)); CBCProjectileAttackCmd(pas::ESeverity::One, mgr.GetPlayer().GetTranslation(), false));
} }
} else if (x56c_ == 2) { } else if (x56c_stateProg == 2) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) {
x56c_ = 3; x56c_stateProg = 3;
x638_ = 0.f; x638_ = 0.f;
} }

View File

@ -11,7 +11,7 @@ class CCollisionActorManager;
namespace MP1 { namespace MP1 {
class CNewIntroBoss : public CPatterned { class CNewIntroBoss : public CPatterned {
pas::ELocomotionType x568_locomotion = pas::ELocomotionType::Relaxed; pas::ELocomotionType x568_locomotion = pas::ELocomotionType::Relaxed;
u32 x56c_ = 0; u32 x56c_stateProg = 0;
float x570_; float x570_;
CBoneTracking x574_boneTracking; CBoneTracking x574_boneTracking;
CProjectileInfo x5ac_projectileInfo; CProjectileInfo x5ac_projectileInfo;
@ -20,16 +20,16 @@ class CNewIntroBoss : public CPatterned {
TUniqueId x5d8_stage3Projectile = kInvalidUniqueId; TUniqueId x5d8_stage3Projectile = kInvalidUniqueId;
std::string x5dc_damageLocator; // ??? std::string x5dc_damageLocator; // ???
std::unique_ptr<CCollisionActorManager> x5ec_collisionManager; std::unique_ptr<CCollisionActorManager> x5ec_collisionManager;
CAssetId x5f0_; CAssetId x5f0_beamContactFxId;
CAssetId x5f4_; CAssetId x5f4_beamPulseFxId;
CAssetId x5f8_; CAssetId x5f8_beamTextureId;
CAssetId x5fc_; CAssetId x5fc_beamGlowTextureId;
TUniqueId x600_headActor = kInvalidUniqueId; TUniqueId x600_headActor = kInvalidUniqueId;
TUniqueId x602_pelvisActor = kInvalidUniqueId; TUniqueId x602_pelvisActor = kInvalidUniqueId;
zeus::CVector3f x604_predictedPlayerPos; zeus::CVector3f x604_predictedPlayerPos;
zeus::CVector3f x610_lookPos; zeus::CVector3f x610_lookPos;
zeus::CVector3f x61c_; zeus::CVector3f x61c_startPlayerPos;
float x628_ = 0.f; float x628_firingTime = 0.f;
zeus::CVector3f x62c_targetPos; zeus::CVector3f x62c_targetPos;
float x638_ = 0.2f; float x638_ = 0.2f;
float x63c_attackTime = 8.f; float x63c_attackTime = 8.f;
@ -48,8 +48,9 @@ class CNewIntroBoss : public CPatterned {
public: public:
DEFINE_PATTERNED(NewIntroBoss) DEFINE_PATTERNED(NewIntroBoss)
CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, float, CAssetId, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms,
const CDamageInfo& dInfo, CAssetId, CAssetId, CAssetId, CAssetId); float f1, CAssetId projectile, const CDamageInfo& dInfo, CAssetId beamContactFxId,
CAssetId beamPulseFxId, CAssetId beamTextureId, CAssetId beamGlowTextureId);
void Accept(IVisitor& visitor); void Accept(IVisitor& visitor);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager&); void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager&);

View File

@ -5,62 +5,87 @@
#include "zeus/CColor.hpp" #include "zeus/CColor.hpp"
namespace urde { namespace urde {
struct CBeamInfo { class CBeamInfo {
u32 x0_; u32 x0_;
s32 x4_; /*
CAssetId x8_; * 0x1: motion blur
CAssetId xc_; * 0x2: pulse effect
CAssetId x10_; * 0x4: one shot
CAssetId x14_; * 0x8: phazon damage
s32 x18_; */
float x1c_; s32 x4_beamAttributes;
float x20_; CAssetId x8_contactFxId;
float x24_; CAssetId xc_pulseFxId;
float x28_; CAssetId x10_textureId;
float x2c_; CAssetId x14_glowTextureId;
float x30_; s32 x18_length;
float x34_; float x1c_radius;
float x38_; float x20_expansionSpeed;
zeus::CColor x3c_; float x24_lifeTime;
zeus::CColor x40_; float x28_pulseSpeed;
float x2c_shutdownTime;
float x30_contactFxScale;
float x34_pulseFxScale;
float x38_travelSpeed;
zeus::CColor x3c_innerColor;
zeus::CColor x40_outerColor;
public:
CBeamInfo(CInputStream& in) CBeamInfo(CInputStream& in)
: x0_(in.readUint32Big()) : x0_(in.readUint32Big())
, x4_(in.readUint32Big()) , x4_beamAttributes(in.readUint32Big())
, x8_(in.readUint32Big()) , x8_contactFxId(in.readUint32Big())
, xc_(in.readUint32Big()) , xc_pulseFxId(in.readUint32Big())
, x10_(in.readUint32Big()) , x10_textureId(in.readUint32Big())
, x14_(in.readUint32Big()) , x14_glowTextureId(in.readUint32Big())
, x18_(in.readFloatBig()) , x18_length(in.readFloatBig())
, x1c_(in.readFloatBig()) , x1c_radius(in.readFloatBig())
, x20_(in.readFloatBig()) , x20_expansionSpeed(in.readFloatBig())
, x24_(in.readFloatBig()) , x24_lifeTime(in.readFloatBig())
, x28_(in.readFloatBig()) , x28_pulseSpeed(in.readFloatBig())
, x2c_(in.readFloatBig()) , x2c_shutdownTime(in.readFloatBig())
, x30_(in.readFloatBig()) , x30_contactFxScale(in.readFloatBig())
, x34_(in.readFloatBig()) , x34_pulseFxScale(in.readFloatBig())
, x38_(in.readFloatBig()) , x38_travelSpeed(in.readFloatBig())
, x3c_(zeus::CColor::ReadRGBABig(in)) , x3c_innerColor(zeus::CColor::ReadRGBABig(in))
, x40_(zeus::CColor::ReadRGBABig(in)) {} , x40_outerColor(zeus::CColor::ReadRGBABig(in)) {}
CBeamInfo(s32 w1, CAssetId w2, CAssetId w3, CAssetId w4, CAssetId w5, s32 w6, float f1, float f2, float f3, float f4, CBeamInfo(s32 beamAttributes, CAssetId contactFxId, CAssetId pulseFxId, CAssetId textureId, CAssetId glowTextureId,
float f5, float f6, float f7, const zeus::CColor& col1, const zeus::CColor& col2, float f8) s32 length, float radius, float f2, float f3, float f4, float f5, float contactFxScale, float pulseFxScale,
: x4_(w1) const zeus::CColor& innerColor, const zeus::CColor& outerColor, float travelSpeed)
, x8_(w2) : x4_beamAttributes(beamAttributes)
, xc_(w3) , x8_contactFxId(contactFxId)
, x10_(w4) , xc_pulseFxId(pulseFxId)
, x14_(w5) , x10_textureId(textureId)
, x18_(w6) , x14_glowTextureId(glowTextureId)
, x1c_(f1) , x18_length(length)
, x20_(f2) , x1c_radius(radius)
, x24_(f3) , x20_expansionSpeed(f2)
, x28_(f4) , x24_lifeTime(f3)
, x2c_(f5) , x28_pulseSpeed(f4)
, x30_(f6) , x2c_shutdownTime(f5)
, x34_(f7) , x30_contactFxScale(contactFxScale)
, x38_(f8) , x34_pulseFxScale(pulseFxScale)
, x3c_(col1) , x38_travelSpeed(travelSpeed)
, x40_(col2) {} , x3c_innerColor(innerColor)
, x40_outerColor(outerColor) {}
s32 GetBeamAttributes() const { return x4_beamAttributes; }
CAssetId GetContactFxId() const { return x8_contactFxId; }
CAssetId GetPulseFxId() const { return xc_pulseFxId; }
CAssetId GetTextureId() const { return x10_textureId; }
CAssetId GetGlowTextureId() const { return x14_glowTextureId; }
s32 GetLength() const { return x18_length; }
float GetRadius() const { return x1c_radius; }
float GetExpansionSpeed() const { return x20_expansionSpeed; }
float GetLifeTime() const { return x24_lifeTime; }
float GetPulseSpeed() const { return x28_pulseSpeed; }
float GetShutdownTime() const { return x2c_shutdownTime; }
float GetContactFxScale() const { return x30_contactFxScale; }
float GetPulseFxScale() const { return x34_pulseFxScale; }
float GetTravelSpeed() const { return x38_travelSpeed; }
const zeus::CColor& GetInnerColor() const { return x3c_innerColor; }
const zeus::CColor& GetOuterColor() const { return x40_outerColor; }
}; };
} // namespace urde } // namespace urde

View File

@ -1,41 +1,91 @@
#include "Weapon/CBeamProjectile.hpp" #include "Weapon/CBeamProjectile.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "CStateManager.hpp"
namespace urde { namespace urde {
CBeamProjectile::CBeamProjectile(const TToken<CWeaponDescription>& wDesc, std::string_view name, EWeaponType wType, CBeamProjectile::CBeamProjectile(const TToken<CWeaponDescription>& wDesc, std::string_view name, EWeaponType wType,
const zeus::CTransform& xf, s32 flags, float f1, float f2, EMaterialTypes matType, const zeus::CTransform& xf, s32 maxLength, float beamRadius, float travelSpeed,
const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid,
EProjectileAttrib attribs, bool b1) TUniqueId owner, EProjectileAttrib attribs, bool growingBeam)
: CGameProjectile(false, wDesc, name, wType, xf, matType, dInfo, uid, aid, owner, kInvalidUniqueId, attribs, false, : CGameProjectile(false, wDesc, name, wType, xf, matType, dInfo, uid, aid, owner, kInvalidUniqueId, attribs, false,
zeus::CVector3f::skOne, {}, -1, false) zeus::CVector3f::skOne, {}, 0xffff, false)
, x2e8_(std::abs(flags)) , x2e8_intMaxLength(std::abs(maxLength))
, x2ec_(x2e8_) , x2ec_maxLength(x2e8_intMaxLength)
, x2f0_(1.f / x2ec_) , x2f0_invMaxLength(1.f / x2ec_maxLength)
, x2f4_(f1) , x2f4_beamRadius(beamRadius)
, x300_(b1 == false ? x2ec_ : 0.f) , x300_intBeamLength(growingBeam ? 0.f : x2ec_maxLength)
, x308_(f2) , x304_beamLength(x2ec_maxLength)
, x464_24_(b1) , x308_travelSpeed(travelSpeed)
, x464_25_(false) {} , x464_24_growingBeam(growingBeam)
, x464_25_enableTouchDamage(false) {
x384_.resize(10);
x400_pointCache.resize(8);
}
std::experimental::optional<zeus::CAABox> CBeamProjectile::GetTouchBounds() const { std::experimental::optional<zeus::CAABox> CBeamProjectile::GetTouchBounds() const {
if (!GetActive()) if (!GetActive())
return {}; return {};
if (!x464_25_) { if (x464_25_enableTouchDamage) {
zeus::CVector3f pos = GetTranslation(); zeus::CVector3f pos = GetTranslation();
return {{pos - 1.f, pos + 1.f}}; return {{pos - 0.1f, pos + 0.1f}};
} }
return {}; return {};
} }
void CBeamProjectile::CalculateRenderBounds() { x9c_renderBounds = x354_.getTransformedAABox(x324_); } void CBeamProjectile::CalculateRenderBounds() { x9c_renderBounds = x354_.getTransformedAABox(x324_xf); }
void CBeamProjectile::ResetBeam(CStateManager&, bool) { void CBeamProjectile::ResetBeam(CStateManager&, bool) {
if (x464_24_) if (x464_24_growingBeam)
x300_ = 0.f; x300_intBeamLength = 0.f;
} }
void CBeamProjectile::UpdateFX(const zeus::CTransform&, float, CStateManager&) {} void CBeamProjectile::SetCollisionResultData(EDamageType dType, CRayCastResult& res, TUniqueId id) {
x2f8_damageType = dType;
x304_beamLength = res.GetT();
x318_collisionPoint = res.GetPoint();
x30c_collisionNormal = res.GetPlane().normal();
x2fe_collisionActorId = dType == EDamageType::Actor ? id : kInvalidUniqueId;
SetTranslation(res.GetPoint());
}
void CBeamProjectile::UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr) {
if (!GetActive())
return;
SetTransform(xf.getRotation());
if (x464_24_growingBeam) {
x300_intBeamLength += x308_travelSpeed * dt;
if (x300_intBeamLength > x2ec_maxLength)
x300_intBeamLength = x2ec_maxLength;
}
x304_beamLength = x300_intBeamLength;
x2f8_damageType = EDamageType::None;
x298_previousPos = xf.origin;
zeus::CVector3f beamEnd = xf.basis[1].normalized() * x300_intBeamLength + xf.origin;
SetTranslation(beamEnd);
x354_ = zeus::CAABox(zeus::CVector3f{-x2f4_beamRadius, 0.f, -x2f4_beamRadius},
zeus::CVector3f{x2f4_beamRadius, x304_beamLength, x2f4_beamRadius});
x36c_ = zeus::CAABox(zeus::CVector3f{-x2f4_beamRadius, 0.f, -x2f4_beamRadius},
zeus::CVector3f{x2f4_beamRadius, x300_intBeamLength, x2f4_beamRadius}).getTransformedAABox(xf);
rstl::reserved_vector<TUniqueId, 1024> nearList;
mgr.BuildNearList(nearList, x36c_, CMaterialFilter::MakeExclude({EMaterialTypes::ProjectilePassthrough}), nullptr);
TUniqueId collideId = kInvalidUniqueId;
CRayCastResult res = RayCollisionCheckWithWorld(collideId, x298_previousPos, beamEnd, x300_intBeamLength, nearList, mgr);
if (TCastToPtr<CActor> act = mgr.ObjectById(collideId)) {
SetCollisionResultData(EDamageType::Actor, res, collideId);
if (x464_25_enableTouchDamage)
ApplyDamageToActors(mgr, CDamageInfo(x12c_curDamageInfo, dt));
} else if (res.IsValid()) {
SetCollisionResultData(EDamageType::World, res, kInvalidUniqueId);
if (x464_25_enableTouchDamage)
mgr.ApplyDamageToWorld(xec_ownerId, *this, res.GetPoint(), CDamageInfo(x12c_curDamageInfo, dt), xf8_filter);
} else {
x318_collisionPoint = xf * zeus::CVector3f(x2f4_beamRadius, x304_beamLength, x2f4_beamRadius);
SetTranslation(x318_collisionPoint);
}
x324_xf = xf;
}
void CBeamProjectile::Accept(urde::IVisitor& visitor) { visitor.Visit(this); } void CBeamProjectile::Accept(urde::IVisitor& visitor) { visitor.Visit(this); }

View File

@ -3,48 +3,61 @@
#include "Weapon/CGameProjectile.hpp" #include "Weapon/CGameProjectile.hpp"
namespace urde { namespace urde {
class CBeamProjectile : public CGameProjectile { class CBeamProjectile : public CGameProjectile {
u32 x2e8_; public:
float x2ec_; enum class EDamageType {
float x2f0_; None,
float x2f4_; Actor,
u32 x2f8_ = 0; World
};
private:
s32 x2e8_intMaxLength;
float x2ec_maxLength;
float x2f0_invMaxLength;
float x2f4_beamRadius;
EDamageType x2f8_damageType = EDamageType::None;
TUniqueId x2fc_ = kInvalidUniqueId; TUniqueId x2fc_ = kInvalidUniqueId;
TUniqueId x2fe_ = kInvalidUniqueId; TUniqueId x2fe_collisionActorId = kInvalidUniqueId;
float x300_; float x300_intBeamLength;
float x304_; float x304_beamLength;
float x308_; float x308_travelSpeed;
zeus::CVector3f x30c_ = zeus::CVector3f::skUp; zeus::CVector3f x30c_collisionNormal = zeus::CVector3f::skUp;
zeus::CTransform x324_; zeus::CVector3f x318_collisionPoint = zeus::CVector3f::skZero;
zeus::CTransform x324_xf;
zeus::CAABox x354_ = zeus::CAABox::skNullBox; zeus::CAABox x354_ = zeus::CAABox::skNullBox;
zeus::CAABox x36c_ = zeus::CAABox::skNullBox;
rstl::reserved_vector<zeus::CVector3f, 10> x384_; rstl::reserved_vector<zeus::CVector3f, 10> x384_;
rstl::reserved_vector<zeus::CVector3f, 8> x400_; rstl::reserved_vector<zeus::CVector3f, 8> x400_pointCache;
bool x464_24_ : 1; bool x464_24_growingBeam : 1;
bool x464_25_ : 1; bool x464_25_enableTouchDamage : 1;
void SetCollisionResultData(EDamageType dType, CRayCastResult& res, TUniqueId id);
public: public:
CBeamProjectile(const TToken<CWeaponDescription>& wDesc, std::string_view name, EWeaponType wType, CBeamProjectile(const TToken<CWeaponDescription>& wDesc, std::string_view name, EWeaponType wType,
const zeus::CTransform& xf, s32 flags, float f1, float f2, EMaterialTypes matType, const zeus::CTransform& xf, s32 maxLength, float beamRadius, float travelSpeed,
const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, EProjectileAttrib attribs, EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner,
bool b1); EProjectileAttrib attribs, bool growingBeam);
void Accept(IVisitor& visitor); void Accept(IVisitor& visitor);
float GetMaxRadius() const; float GetMaxRadius() const { return x2f4_beamRadius; }
zeus::CVector3f GetSurfaceNormal() const; const zeus::CVector3f& GetSurfaceNormal() const { return x30c_collisionNormal; }
void GetDamageType() const; EDamageType GetDamageType() const { return x2f8_damageType; }
void GetCurrentPos() const; const zeus::CVector3f& GetCurrentPos() const { return x318_collisionPoint; }
void PointCache(); rstl::reserved_vector<zeus::CVector3f, 8>& PointCache() { return x400_pointCache; }
void GetPointCache() const; const rstl::reserved_vector<zeus::CVector3f, 8>& GetPointCache() const { return x400_pointCache; }
void CauseDamage(bool); void CauseDamage(bool b) { x464_25_enableTouchDamage = b; }
zeus::CVector3f GetBeamOrigin() const; const zeus::CTransform& GetBeamTransform() const { return x324_xf; }
void GetInvMaxLength() const; float GetInvMaxLength() const { return x2f0_invMaxLength; }
void GetCurrentLength(); float GetCurrentLength() const { return x304_beamLength; }
void GetMaxLength(); float GetMaxLength() const { return x2ec_maxLength; }
s32 GetIntMaxLength(); s32 GetIntMaxLength() const { return x2e8_intMaxLength; }
TUniqueId GetCollisionActorId() const { return x2fe_collisionActorId; }
std::experimental::optional<zeus::CAABox> GetTouchBounds() const; std::experimental::optional<zeus::CAABox> GetTouchBounds() const;
void CalculateRenderBounds(); void CalculateRenderBounds();
virtual void ResetBeam(CStateManager&, bool); virtual void ResetBeam(CStateManager&, bool);
virtual void UpdateFX(const zeus::CTransform&, float, CStateManager&); virtual void UpdateFx(const zeus::CTransform&, float, CStateManager&);
virtual void Fire(const zeus::CTransform&, CStateManager&, bool) = 0; virtual void Fire(const zeus::CTransform&, CStateManager&, bool) = 0;
}; };
} // namespace urde } // namespace urde

View File

@ -28,7 +28,7 @@ CGameProjectile::CGameProjectile(bool active, const TToken<CWeaponDescription>&
, x168_visorSfx(visorSfx) , x168_visorSfx(visorSfx)
, x170_projectile(wDesc, xf.origin, xf.basis, scale, , x170_projectile(wDesc, xf.origin, xf.basis, scale,
(attribs & EProjectileAttrib::ParticleOPTS) == EProjectileAttrib::ParticleOPTS) (attribs & EProjectileAttrib::ParticleOPTS) == EProjectileAttrib::ParticleOPTS)
, x298_lastOrigin(xf.origin) , x298_previousPos(xf.origin)
, x2a4_projExtent((xe8_projectileAttribs & EProjectileAttrib::BigProjectile) == EProjectileAttrib::BigProjectile ? 0.25f , x2a4_projExtent((xe8_projectileAttribs & EProjectileAttrib::BigProjectile) == EProjectileAttrib::BigProjectile ? 0.25f
: 0.1f) : 0.1f)
, x2c0_homingTargetId(homingTarget) , x2c0_homingTargetId(homingTarget)
@ -186,7 +186,7 @@ void CGameProjectile::UpdateProjectileMovement(float dt, CStateManager& mgr) {
if (x2e4_26_waterUpdate) if (x2e4_26_waterUpdate)
useDt = 37.5f * dt * dt; useDt = 37.5f * dt * dt;
x298_lastOrigin = x34_transform.origin; x298_previousPos = x34_transform.origin;
x170_projectile.Update(useDt); x170_projectile.Update(useDt);
SetTransform(x170_projectile.GetTransform()); SetTransform(x170_projectile.GetTransform());
SetTranslation(x170_projectile.GetTranslation()); SetTranslation(x170_projectile.GetTranslation());
@ -196,12 +196,12 @@ void CGameProjectile::UpdateProjectileMovement(float dt, CStateManager& mgr) {
CRayCastResult CGameProjectile::DoCollisionCheck(TUniqueId& idOut, CStateManager& mgr) { CRayCastResult CGameProjectile::DoCollisionCheck(TUniqueId& idOut, CStateManager& mgr) {
CRayCastResult res; CRayCastResult res;
if (x2e4_24_active) { if (x2e4_24_active) {
zeus::CVector3f posDelta = x34_transform.origin - x298_lastOrigin; zeus::CVector3f posDelta = x34_transform.origin - x298_previousPos;
rstl::reserved_vector<TUniqueId, 1024> nearList; rstl::reserved_vector<TUniqueId, 1024> nearList;
mgr.BuildNearList(nearList, GetProjectileBounds(), mgr.BuildNearList(nearList, GetProjectileBounds(),
CMaterialFilter::MakeExclude(EMaterialTypes::ProjectilePassthrough), this); CMaterialFilter::MakeExclude(EMaterialTypes::ProjectilePassthrough), this);
res = RayCollisionCheckWithWorld(idOut, x298_lastOrigin, x34_transform.origin, posDelta.magnitude(), nearList, mgr); res = RayCollisionCheckWithWorld(idOut, x298_previousPos, x34_transform.origin, posDelta.magnitude(), nearList, mgr);
} }
return res; return res;
} }
@ -335,25 +335,25 @@ CProjectileTouchResult CGameProjectile::CanCollideWithComplexCollision(CActor& a
if (useAct) { if (useAct) {
const CCollisionPrimitive* prim = useAct->GetCollisionPrimitive(); const CCollisionPrimitive* prim = useAct->GetCollisionPrimitive();
zeus::CTransform xf = useAct->GetPrimitiveTransform(); zeus::CTransform xf = useAct->GetPrimitiveTransform();
zeus::CVector3f deltaPos = GetTranslation() - x298_lastOrigin; zeus::CVector3f deltaPos = GetTranslation() - x298_previousPos;
if (deltaPos.canBeNormalized()) { if (deltaPos.canBeNormalized()) {
zeus::CVector3f dir = deltaPos.normalized(); zeus::CVector3f dir = deltaPos.normalized();
float mag = deltaPos.magnitude(); float mag = deltaPos.magnitude();
CRayCastResult res = prim->CastRayInternal( CRayCastResult res = prim->CastRayInternal(
{x298_lastOrigin, dir, mag, xf, {x298_previousPos, dir, mag, xf,
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough})}); CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough})});
if (!res.IsValid()) { if (!res.IsValid()) {
if (prim->GetPrimType() == FOURCC('SPHR')) { if (prim->GetPrimType() == FOURCC('SPHR')) {
mag *= 2.f; mag *= 2.f;
CRayCastResult res2 = prim->CastRayInternal( CRayCastResult res2 = prim->CastRayInternal(
{x298_lastOrigin - dir * mag, dir, deltaPos.magnitude(), xf, {x298_previousPos - dir * mag, dir, deltaPos.magnitude(), xf,
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough})}); CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough})});
if (res2.IsValid()) if (res2.IsValid())
return {act.GetUniqueId(), {res2}}; return {act.GetUniqueId(), {res2}};
} else if (TCastToPtr<CCollisionActor> cAct = act) { } else if (TCastToPtr<CCollisionActor> cAct = act) {
float rad = cAct->GetSphereRadius(); float rad = cAct->GetSphereRadius();
if ((x298_lastOrigin - GetTranslation()).magSquared() < rad * rad) { if ((x298_previousPos - GetTranslation()).magSquared() < rad * rad) {
zeus::CVector3f point = x298_lastOrigin - dir * rad * 1.125f; zeus::CVector3f point = x298_previousPos - dir * rad * 1.125f;
zeus::CUnitVector3f revDir(-dir); zeus::CUnitVector3f revDir(-dir);
return {act.GetUniqueId(), {{0.f, point, {revDir, point.dot(revDir)}, act.GetMaterialList()}}}; return {act.GetUniqueId(), {{0.f, point, {revDir, point.dot(revDir)}, act.GetMaterialList()}}};
} }
@ -415,12 +415,12 @@ CProjectileTouchResult CGameProjectile::CanCollideWithTrigger(CActor& act, CStat
} }
zeus::CAABox CGameProjectile::GetProjectileBounds() const { zeus::CAABox CGameProjectile::GetProjectileBounds() const {
return {{std::min(x298_lastOrigin.x(), GetTranslation().x()) - x2a4_projExtent, return {{std::min(x298_previousPos.x(), GetTranslation().x()) - x2a4_projExtent,
std::min(x298_lastOrigin.y(), GetTranslation().y()) - x2a4_projExtent, std::min(x298_previousPos.y(), GetTranslation().y()) - x2a4_projExtent,
std::min(x298_lastOrigin.z(), GetTranslation().z()) - x2a4_projExtent}, std::min(x298_previousPos.z(), GetTranslation().z()) - x2a4_projExtent},
{std::max(x298_lastOrigin.x(), GetTranslation().x()) + x2a4_projExtent, {std::max(x298_previousPos.x(), GetTranslation().x()) + x2a4_projExtent,
std::max(x298_lastOrigin.y(), GetTranslation().y()) + x2a4_projExtent, std::max(x298_previousPos.y(), GetTranslation().y()) + x2a4_projExtent,
std::max(x298_lastOrigin.z(), GetTranslation().z()) + x2a4_projExtent}}; std::max(x298_previousPos.z(), GetTranslation().z()) + x2a4_projExtent}};
} }
std::experimental::optional<zeus::CAABox> CGameProjectile::GetTouchBounds() const { std::experimental::optional<zeus::CAABox> CGameProjectile::GetTouchBounds() const {

View File

@ -30,7 +30,7 @@ protected:
std::experimental::optional<TLockedToken<CGenDescription>> x158_visorParticle; std::experimental::optional<TLockedToken<CGenDescription>> x158_visorParticle;
u16 x168_visorSfx; u16 x168_visorSfx;
CProjectileWeapon x170_projectile; CProjectileWeapon x170_projectile;
zeus::CVector3f x298_lastOrigin; zeus::CVector3f x298_previousPos;
float x2a4_projExtent; float x2a4_projExtent;
float x2a8_homingDt = 0.03f; float x2a8_homingDt = 0.03f;
double x2b0_targetHomingTime = 0.0; double x2b0_targetHomingTime = 0.0;
@ -83,6 +83,6 @@ public:
zeus::CAABox GetProjectileBounds() const; zeus::CAABox GetProjectileBounds() const;
std::experimental::optional<zeus::CAABox> GetTouchBounds() const; std::experimental::optional<zeus::CAABox> GetTouchBounds() const;
TUniqueId GetHomingTargetId() const { return x2c0_homingTargetId; } TUniqueId GetHomingTargetId() const { return x2c0_homingTargetId; }
zeus::CVector3f GetPreviousPos() const { return x298_lastOrigin; } zeus::CVector3f GetPreviousPos() const { return x298_previousPos; }
}; };
} // namespace urde } // namespace urde

View File

@ -1,17 +1,436 @@
#include "CPlasmaProjectile.hpp" #include "CPlasmaProjectile.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "World/CGameLight.hpp"
#include "CStateManager.hpp"
#include "Graphics/CBooRenderer.hpp"
#include "World/CPlayer.hpp"
#include "World/CHUDBillboardEffect.hpp"
namespace urde { namespace urde {
CPlasmaProjectile::RenderObjects::RenderObjects(boo::IGraphicsDataFactory::Context& ctx,
boo::ObjToken<boo::ITexture> tex,
boo::ObjToken<boo::ITexture> glowTex)
: m_beamStrip1(ctx, 8, CColoredStripShader::Mode::Additive, {})
, m_beamStrip2(ctx, 10, CColoredStripShader::Mode::FullAdditive, tex)
, m_beamStrip3(ctx, 18, CColoredStripShader::Mode::FullAdditive, tex)
, m_beamStrip4(ctx, 14, CColoredStripShader::Mode::Additive, glowTex)
, m_motionBlurStrip(ctx, 16, CColoredStripShader::Mode::Alpha, {}) {}
CPlasmaProjectile::CPlasmaProjectile(const TToken<CWeaponDescription>& wDesc, std::string_view name, EWeaponType wType, CPlasmaProjectile::CPlasmaProjectile(const TToken<CWeaponDescription>& wDesc, std::string_view name, EWeaponType wType,
const CBeamInfo& bInfo, const zeus::CTransform& xf, EMaterialTypes matType, const CBeamInfo& bInfo, const zeus::CTransform& xf, EMaterialTypes matType,
const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, u32 w1, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner,
bool b1, EProjectileAttrib attribs) const PlayerEffectResoures& res, bool growingBeam, EProjectileAttrib attribs)
: CBeamProjectile(wDesc, name, wType, xf, bInfo.x18_, bInfo.x1c_, bInfo.x38_, matType, dInfo, uid, aid, owner, attribs, : CBeamProjectile(wDesc, name, wType, xf, bInfo.GetLength(), bInfo.GetRadius(), bInfo.GetTravelSpeed(), matType,
b1) {} dInfo, uid, aid, owner, attribs, growingBeam)
, x478_beamAttributes(bInfo.GetBeamAttributes())
, x47c_lifeTime(bInfo.GetLifeTime())
, x480_pulseSpeed(bInfo.GetPulseSpeed())
, x484_shutdownTime(bInfo.GetShutdownTime())
, x488_expansionSpeed(bInfo.GetExpansionSpeed())
, x48c_(bInfo.GetLength() / 32.f)
, x490_innerColor(bInfo.GetInnerColor())
, x494_outerColor(bInfo.GetOuterColor()) {
x4e8_texture = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), bInfo.GetTextureId()});
x4f4_glowTexture = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), bInfo.GetGlowTextureId()});
x500_contactFxDesc = g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), bInfo.GetContactFxId()});
x50c_pulseFxDesc = g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), bInfo.GetPulseFxId()});
x518_contactGen = std::make_unique<CElementGen>(x500_contactFxDesc, CElementGen::EModelOrientationType::One);
x51c_pulseGen = std::make_unique<CElementGen>(x50c_pulseFxDesc, CElementGen::EModelOrientationType::Normal);
x524_freezeSteamTxtr = res[0];
x528_freezeIceTxtr = res[1];
if (res[2] != UINT64_MAX)
x52c_visorElectric = g_SimplePool->GetObj(SObjectTag{FOURCC('ELSC'), res[2]});
if (res[3] != UINT64_MAX)
x538_visorParticle = g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), res[3]});
x544_freezeSfx = CSfxManager::TranslateSFXID(res[4]);
x546_electricSfx = CSfxManager::TranslateSFXID(res[5]);
x548_25_enableEnergyPulse = true;
x548_28_drawOwnerFirst = growingBeam;
x518_contactGen->SetGlobalScale(zeus::CVector3f(bInfo.GetContactFxScale()));
x51c_pulseGen->SetGlobalScale(zeus::CVector3f(bInfo.GetPulseFxScale()));
x518_contactGen->SetParticleEmission(false);
x51c_pulseGen->SetParticleEmission(false);
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) {
m_renderObjs.emplace(ctx, x4e8_texture->GetBooTexture(), x4f4_glowTexture->GetBooTexture());
return true;
} BooTrace);
}
void CPlasmaProjectile::Accept(IVisitor& visitor) { visitor.Visit(this); } void CPlasmaProjectile::Accept(IVisitor& visitor) { visitor.Visit(this); }
void CPlasmaProjectile::Fire(const zeus::CTransform&, CStateManager&, bool) { SetActive(true); } void CPlasmaProjectile::SetLightsActive(bool active, CStateManager& mgr) {
for (TUniqueId lid : x468_lights) {
if (lid != kInvalidUniqueId) {
if (TCastToPtr<CGameLight> light = mgr.ObjectById(lid)) {
light->SetActive(active);
}
}
}
}
void CPlasmaProjectile::CreatePlasmaLights(u32 sourceId, const CLight& l, CStateManager& mgr) {
DeletePlasmaLights(mgr);
x468_lights.reserve(3);
for (int i = 0; i < 3; ++i) {
TUniqueId lid = mgr.AllocateUniqueId();
auto* light =
new CGameLight(lid, GetAreaId(), GetActive(), ""sv, GetTransform(), GetUniqueId(), l, sourceId, 0, 0.f);
mgr.AddObject(light);
x468_lights.push_back(lid);
}
}
void CPlasmaProjectile::DeletePlasmaLights(CStateManager& mgr) {
for (TUniqueId lid : x468_lights)
mgr.FreeScriptObject(lid);
x468_lights.clear();
}
void CPlasmaProjectile::UpdateLights(float expansion, float dt, CStateManager& mgr) {
if (x520_weaponGen) {
x520_weaponGen->Update(dt);
CLight l = x520_weaponGen->GetLight();
l.SetColor(zeus::CColor::lerp(zeus::CColor::skClear, l.GetColor(), expansion));
float halfLen = 0.5f * GetCurrentLength();
float y = 0.f;
for (TUniqueId lid : x468_lights) {
if (TCastToPtr<CGameLight> light = mgr.ObjectById(lid)) {
light->SetTransform({});
light->SetTranslation(GetBeamTransform() * zeus::CVector3f(0.f, y, 0.f));
light->SetLight(l);
}
y += halfLen;
}
}
}
void CPlasmaProjectile::UpdateEnergyPulse(float dt) {
if (GetDamageType() != EDamageType::None && x548_25_enableEnergyPulse) {
x4d8_energyPulseTimer -= dt;
if (x4d8_energyPulseTimer <= 0.f) {
x4d8_energyPulseTimer = 2.f * dt;
x51c_pulseGen->SetParticleEmission(true);
float t = GetCurrentLength() / GetMaxLength();
for (float i = 0.f; i <= t; i += 0.1f) {
float y = i * GetMaxLength() + x4cc_energyPulseStartY;
if (y > GetCurrentLength())
continue;
x51c_pulseGen->SetTranslation({0.f, y, 0.f});
x51c_pulseGen->ForceParticleCreation(1);
}
x51c_pulseGen->SetGlobalOrientAndTrans(GetBeamTransform());
x51c_pulseGen->SetParticleEmission(false);
}
}
x51c_pulseGen->Update(dt);
}
void CPlasmaProjectile::RenderMotionBlur() const {
CGraphics::SetModelMatrix({});
zeus::CColor color1 = x494_outerColor;
zeus::CColor color2 = x494_outerColor;
color1.a() = 63.f / 255.f;
color2.a() = 0.f;
CColoredStripShader::Vert verts[16];
for (int i = 0; i < 8; ++i) {
auto& v1 = verts[i * 2];
auto& v2 = verts[i * 2 + 1];
v1.m_pos = GetBeamTransform().origin;
v1.m_color = zeus::CColor::lerp(color1, color2, i / 8.f);
v2.m_pos = GetPointCache()[i];
v2.m_color = v1.m_color;
}
m_renderObjs->m_motionBlurStrip.draw(zeus::CColor::skWhite, 16, verts);
}
void CPlasmaProjectile::RenderBeam(s32 subdivs, float width, const zeus::CColor& color, s32 flags,
CColoredStripShader& shader) const {
// Flags: 0x1: textured, 0x2: length controlled UVY 0x4: alpha controlled additive blend,
// 0x8: glow texture, 0x10: subtractive blend
if ((flags & 0x1) == 0 || (flags & 0x8) ? x4f4_glowTexture.IsLoaded() : x4e8_texture.IsLoaded()) {
float angIncrement = 2.f * M_PIF / float(subdivs);
float uvY1 = -(x4cc_energyPulseStartY / 16.f);
float uvY2 = (uvY1 + float((flags & 0x3) == 0x3) != 0.f) ? 2.f : 0.5f * GetCurrentLength();
CColoredStripShader::Vert verts[18];
s32 numNodes = subdivs + 1;
float angle = 0.f;
bool flip = false;
for (s32 i = 0; i < numNodes; ++i) {
CColoredStripShader::Vert& v0 = verts[i * 2];
CColoredStripShader::Vert& v1 = verts[i * 2 + 1];
float x = std::cos(angle);
float y = std::sin(angle);
float uvX;
if (flags & 0x8)
uvX = 0.5f * y;
else if (flip)
uvX = width;
else
uvX = 0.f;
flip ^= true;
v0.m_pos = zeus::CVector3f(width * x, 0.f, width * y);
v0.m_color = color;
v0.m_uv = zeus::CVector2f(uvX, uvY1);
v1.m_pos = zeus::CVector3f(width * x, GetCurrentLength(), width * y);
v1.m_color = color;
v1.m_uv = zeus::CVector2f(uvX, uvY2);
angle += angIncrement;
}
shader.draw(zeus::CColor::skWhite, numNodes * 2, verts);
}
}
void CPlasmaProjectile::ResetBeam(CStateManager& mgr, bool fullReset) {
if (fullReset) {
SetActive(false);
SetLightsActive(false, mgr);
x4bc_lifeTimer = 0.f;
x4c0_expansionT = 0.f;
x4c8_beamAngle = 0.f;
x4d0_shutdownTimer = 0.f;
x4d4_contactPulseTimer = 0.f;
x4d8_energyPulseTimer = 0.f;
x4dc_playerEffectPulseTimer = 0.f;
x4b4_expansionState = EExpansionState::Inactive;
x548_26_firing = false;
x518_contactGen->SetParticleEmission(false);
x51c_pulseGen->SetParticleEmission(false);
} else {
x548_26_firing = false;
x4b4_expansionState = EExpansionState::Release;
x518_contactGen->SetParticleEmission(false);
x51c_pulseGen->SetParticleEmission(false);
}
}
float CPlasmaProjectile::UpdateBeamState(float dt, CStateManager& mgr) {
switch (x4b4_expansionState) {
case EExpansionState::Attack:
if (x4c0_expansionT > 0.5f)
x4b4_expansionState = EExpansionState::Sustain;
else
x4c0_expansionT += dt * x488_expansionSpeed;
break;
case EExpansionState::Sustain:
if (x478_beamAttributes & 0x4) {
if (x4bc_lifeTimer > x47c_lifeTime)
x4b4_expansionState = EExpansionState::Release;
else
x4bc_lifeTimer += dt;
}
break;
case EExpansionState::Release:
x4c0_expansionT += dt * x488_expansionSpeed;
if (x4c0_expansionT > 1.f) {
x4c0_expansionT = 1.f;
x4b4_expansionState = EExpansionState::Done;
x548_25_enableEnergyPulse = false;
}
break;
case EExpansionState::Done:
x4d0_shutdownTimer += dt;
if (x4d0_shutdownTimer > x484_shutdownTime &&
(!x518_contactGen || x518_contactGen->GetParticleCountAll() == 0)) {
x4b4_expansionState = EExpansionState::Inactive;
ResetBeam(mgr, true);
}
break;
default:
break;
}
return -4.f * x4c0_expansionT * (x4c0_expansionT - 1.f);
}
void CPlasmaProjectile::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
switch (msg) {
case EScriptObjectMessage::Registered: {
xe6_27_thermalVisorFlags = 2;
const SChildGeneratorDesc& apsm = x170_projectile.GetWeaponDescription()->x34_APSM;
if (apsm)
x520_weaponGen = std::make_unique<CElementGen>(apsm.m_token);
if (x520_weaponGen && x520_weaponGen->SystemHasLight())
CreatePlasmaLights(x170_projectile.GetWeaponDescription().GetObjectTag()->id.Value(),
x520_weaponGen->GetLight(), mgr);
else
x520_weaponGen.reset();
if (x548_28_drawOwnerFirst)
xc6_nextDrawNode = xec_ownerId;
mgr.AddWeaponId(xec_ownerId, xf0_weaponType);
break;
}
case EScriptObjectMessage::Deleted:
mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType);
DeletePlasmaLights(mgr);
if (x548_29_activePlayerPhazon) {
mgr.GetPlayer().DecrementPhazon();
x548_29_activePlayerPhazon = false;
}
break;
default:
break;
}
CGameProjectile::AcceptScriptMsg(msg, sender, mgr);
}
void CPlasmaProjectile::MakeBillboardEffect(const std::experimental::optional<TToken<CGenDescription>>& particle,
const std::experimental::optional<TToken<CElectricDescription>>& electric,
std::string_view name, CStateManager& mgr) {
auto* effect = new CHUDBillboardEffect(particle, electric, mgr.AllocateUniqueId(), true, name,
CHUDBillboardEffect::GetNearClipDistance(mgr),
CHUDBillboardEffect::GetScaleForPOV(mgr),
zeus::CColor::skWhite, zeus::CVector3f::skOne, zeus::CVector3f::skZero);
mgr.AddObject(effect);
}
void CPlasmaProjectile::UpdatePlayerEffects(float dt, CStateManager& mgr) {
x4dc_playerEffectPulseTimer -= dt;
if ((x4b4_expansionState == EExpansionState::Attack || x4b4_expansionState == EExpansionState::Sustain) &&
x4dc_playerEffectPulseTimer <= 0.f && GetDamageType() == EDamageType::Actor &&
GetCollisionActorId() == mgr.GetPlayer().GetUniqueId()) {
if ((x478_beamAttributes & 0x8) && !x548_29_activePlayerPhazon) {
x548_29_activePlayerPhazon = true;
x4e4_playerDamageTimer = 0.f;
mgr.GetPlayer().IncrementPhazon();
}
switch (xf0_weaponType) {
case EWeaponType::Ice:
mgr.GetPlayer().Freeze(mgr, x524_freezeSteamTxtr, x544_freezeSfx, x528_freezeIceTxtr);
break;
case EWeaponType::Wave:
if (x52c_visorElectric) {
MakeBillboardEffect({}, {x52c_visorElectric}, "PlasmaElectricFx"sv, mgr);
CSfxManager::SfxStart(x546_electricSfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
mgr.GetPlayer().SetHudDisable(3.f, 0.5f, 2.5f);
mgr.GetPlayer().SetOrbitRequestForTarget(mgr.GetPlayer().GetOrbitTargetId(),
CPlayer::EPlayerOrbitRequest::ActivateOrbitSource, mgr);
mgr.GetPlayerState()->GetStaticInterference().AddSource(GetUniqueId(), 0.2f, 3.f);
}
break;
case EWeaponType::Plasma:
if (x538_visorParticle)
MakeBillboardEffect({x538_visorParticle}, {}, "PlasmaVisorFx"sv, mgr);
break;
default:
break;
}
x4dc_playerEffectPulseTimer = 0.75f;
}
if (x548_29_activePlayerPhazon) {
CDamageInfo scaledDamage(x498_phazonDamage, dt);
mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), xec_ownerId, scaledDamage, xf8_filter,
zeus::CVector3f::skZero);
x4e4_playerDamageTimer += dt;
if (x4e4_playerDamageTimer >= x4e0_playerDamageDuration) {
mgr.GetPlayer().DecrementPhazon();
x4e4_playerDamageTimer = 0.f;
x548_29_activePlayerPhazon = false;
}
}
}
void CPlasmaProjectile::UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr) {
if (!GetActive())
return;
x548_27_texturesLoaded = x4e8_texture.IsLoaded() && x4f4_glowTexture.IsLoaded();
CauseDamage(x4b4_expansionState == EExpansionState::Attack || x4b4_expansionState == EExpansionState::Sustain);
CBeamProjectile::UpdateFx(xf, dt, mgr);
UpdatePlayerEffects(dt, mgr);
if (x478_beamAttributes & 0x1) {
for (int i = 7; i > 0; --i)
PointCache()[i] = PointCache()[i - 1];
PointCache()[0] = GetCurrentPos();
}
if (x518_contactGen) {
x4d4_contactPulseTimer -= dt;
if ((GetDamageType() != EDamageType::None ? x548_25_enableEnergyPulse : false) && x4d4_contactPulseTimer <= 0.f) {
x518_contactGen->SetOrientation(zeus::lookAt(zeus::CVector3f::skZero, GetSurfaceNormal()));
x518_contactGen->SetTranslation(GetSurfaceNormal() * 0.001f + GetCurrentPos());
x518_contactGen->SetParticleEmission(true);
x4d4_contactPulseTimer = 1.f / 16.f;
} else {
x518_contactGen->SetParticleEmission(false);
}
x518_contactGen->Update(dt);
}
float modulation = UpdateBeamState(dt, mgr);
UpdateEnergyPulse(dt);
x4c8_beamAngle += 720.f * dt;
if (x4c8_beamAngle > 360.f)
x4c8_beamAngle = 0.f;
x4b8_beamWidth = modulation * GetMaxRadius();
x4c4_expansion = modulation;
x4cc_energyPulseStartY += dt * x480_pulseSpeed;
if (x4cc_energyPulseStartY > 5.f)
x4cc_energyPulseStartY = 0.f;
UpdateLights(modulation, dt, mgr);
}
void CPlasmaProjectile::Fire(const zeus::CTransform& xf, CStateManager& mgr, bool b) {
SetActive(true);
SetLightsActive(true, mgr);
x548_25_enableEnergyPulse = true;
x548_26_firing = true;
x548_24_ = b;
x4b4_expansionState = EExpansionState::Attack;
if (x478_beamAttributes & 0x1)
std::fill(PointCache().begin(), PointCache().end(), xf.origin);
}
void CPlasmaProjectile::Touch(CActor& other, CStateManager& mgr) {
// Empty
}
bool CPlasmaProjectile::CanRenderUnsorted(const CStateManager& mgr) const {
return false;
}
void CPlasmaProjectile::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const {
if (GetActive()) {
g_Renderer->AddParticleGen(*x518_contactGen);
if (x478_beamAttributes & 0x2) {
g_Renderer->AddParticleGen(*x51c_pulseGen);
}
}
EnsureRendered(mgr, GetBeamTransform().origin, GetSortingBounds(mgr));
}
void CPlasmaProjectile::Render(const CStateManager& mgr) const {
if (!GetActive())
return;
zeus::CTransform xf = GetBeamTransform();
// Subtractive blending for xray
s32 flags = mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay ? 0x10 : 0x0;
if ((x478_beamAttributes & 0x1) == 0)
xf.origin += mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr);
// Z test, no write
if ((x478_beamAttributes & 0x1) && x548_25_enableEnergyPulse && x4b4_expansionState != EExpansionState::Attack)
RenderMotionBlur();
// Pass1: alpha-controlled additive
CGraphics::SetModelMatrix(xf);
RenderBeam(3, 0.25f * x4b8_beamWidth, zeus::CColor(1.f, 0.3f), flags | 0x4, m_renderObjs->m_beamStrip1);
// Pass2: textured
CGraphics::SetModelMatrix(xf * zeus::CTransform::RotateY(zeus::degToRad(x4c8_beamAngle)));
RenderBeam(4, 0.5f * x4b8_beamWidth, x490_innerColor, flags | 0x1, m_renderObjs->m_beamStrip2);
// Pass3: textured | length-controlled UVY
CGraphics::SetModelMatrix(xf * zeus::CTransform::RotateY(zeus::degToRad(-x4c8_beamAngle)));
RenderBeam(8, x4b8_beamWidth, x494_outerColor, flags | 0x3, m_renderObjs->m_beamStrip3);
// Pass4: textured | alpha-controlled additive | glow texture
CGraphics::SetModelMatrix(xf);
RenderBeam(6, 1.25f * x4b8_beamWidth, x494_outerColor, flags | 0xd, m_renderObjs->m_beamStrip4);
}
} // namespace urde } // namespace urde

View File

@ -3,18 +3,111 @@
#include "Weapon/CBeamProjectile.hpp" #include "Weapon/CBeamProjectile.hpp"
#include "Weapon/CBeamInfo.hpp" #include "Weapon/CBeamInfo.hpp"
#include "World/CDamageInfo.hpp" #include "World/CDamageInfo.hpp"
#include "Graphics/Shaders/CColoredStripShader.hpp"
namespace urde { namespace urde {
class CPlasmaProjectile : public CBeamProjectile { class CPlasmaProjectile : public CBeamProjectile {
public:
struct PlayerEffectResoures : rstl::reserved_vector<u64, 8> {
PlayerEffectResoures(u64 a = UINT64_MAX, u64 b = UINT64_MAX, u64 c = UINT64_MAX, u64 d = UINT64_MAX,
u64 e = UINT64_MAX, u64 f = UINT64_MAX, u64 g = UINT64_MAX, u64 h = UINT64_MAX)
: rstl::reserved_vector<u64, 8>({a, b, c, d, e, f, g, h}) {}
};
private:
std::vector<TUniqueId> x468_lights;
s32 x478_beamAttributes;
float x47c_lifeTime;
float x480_pulseSpeed;
float x484_shutdownTime;
float x488_expansionSpeed;
float x48c_;
zeus::CColor x490_innerColor;
zeus::CColor x494_outerColor;
CDamageInfo x498_phazonDamage;
enum class EExpansionState {
Inactive,
Attack,
Sustain,
Release,
Done
};
EExpansionState x4b4_expansionState = EExpansionState::Inactive;
float x4b8_beamWidth = 0.f;
float x4bc_lifeTimer = 0.f;
float x4c0_expansionT = 0.f;
float x4c4_expansion = 0.f;
float x4c8_beamAngle = 0.f;
float x4cc_energyPulseStartY = 0.f;
float x4d0_shutdownTimer = 0.f;
float x4d4_contactPulseTimer = 0.f;
float x4d8_energyPulseTimer = 0.f;
float x4dc_playerEffectPulseTimer = 0.f;
float x4e0_playerDamageDuration = 0.f;
float x4e4_playerDamageTimer = 0.f;
TLockedToken<CTexture> x4e8_texture;
TLockedToken<CTexture> x4f4_glowTexture;
TCachedToken<CGenDescription> x500_contactFxDesc;
TCachedToken<CGenDescription> x50c_pulseFxDesc;
std::unique_ptr<CElementGen> x518_contactGen;
std::unique_ptr<CElementGen> x51c_pulseGen;
std::unique_ptr<CElementGen> x520_weaponGen;
CAssetId x524_freezeSteamTxtr;
CAssetId x528_freezeIceTxtr;
TToken<CElectricDescription> x52c_visorElectric; // Used to be optional
TToken<CGenDescription> x538_visorParticle; // Used to be optional
u16 x544_freezeSfx;
u16 x546_electricSfx;
union {
struct {
bool x548_24_ : 1;
bool x548_25_enableEnergyPulse : 1;
bool x548_26_firing : 1;
bool x548_27_texturesLoaded : 1;
bool x548_28_drawOwnerFirst : 1;
bool x548_29_activePlayerPhazon : 1;
};
u32 _dummy3 = 0;
};
struct RenderObjects {
CColoredStripShader m_beamStrip1;
CColoredStripShader m_beamStrip2;
CColoredStripShader m_beamStrip3;
CColoredStripShader m_beamStrip4;
CColoredStripShader m_motionBlurStrip;
RenderObjects(boo::IGraphicsDataFactory::Context& ctx,
boo::ObjToken<boo::ITexture> tex,
boo::ObjToken<boo::ITexture> glowTex);
};
mutable std::optional<RenderObjects> m_renderObjs;
void SetLightsActive(bool active, CStateManager& mgr);
void CreatePlasmaLights(u32 sourceId, const CLight& l, CStateManager& mgr);
void DeletePlasmaLights(CStateManager& mgr);
void UpdateLights(float expansion, float dt, CStateManager& mgr);
void UpdateEnergyPulse(float dt);
void RenderMotionBlur() const;
void RenderBeam(s32 subdivs, float width, const zeus::CColor& color, s32 flags,
CColoredStripShader& shader) const;
float UpdateBeamState(float dt, CStateManager& mgr);
void MakeBillboardEffect(const std::experimental::optional<TToken<CGenDescription>>& particle,
const std::experimental::optional<TToken<CElectricDescription>>& electric,
std::string_view name, CStateManager& mgr);
void UpdatePlayerEffects(float dt, CStateManager& mgr);
public: public:
CPlasmaProjectile(const TToken<CWeaponDescription>& wDesc, std::string_view name, EWeaponType wType, CPlasmaProjectile(const TToken<CWeaponDescription>& wDesc, std::string_view name, EWeaponType wType,
const CBeamInfo& bInfo, const zeus::CTransform& xf, EMaterialTypes matType, const CBeamInfo& bInfo, const zeus::CTransform& xf, EMaterialTypes matType,
const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, u32 w1, bool b1, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner,
EProjectileAttrib attribs); const PlayerEffectResoures& res, bool growingBeam, EProjectileAttrib attribs);
void Accept(IVisitor& visitor); void Accept(IVisitor& visitor);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr);
void UpdateFx(const zeus::CTransform&, float, CStateManager&) {} void ResetBeam(CStateManager& mgr, bool fullReset);
void Fire(const zeus::CTransform&, CStateManager&, bool); void UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr);
void Fire(const zeus::CTransform& xf, CStateManager& mgr, bool b);
void Touch(CActor& other, CStateManager& mgr);
bool CanRenderUnsorted(const CStateManager& mgr) const;
void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const;
void Render(const CStateManager& mgr) const;
}; };
} // namespace urde } // namespace urde

View File

@ -304,7 +304,7 @@ void CPatterned::Think(float dt, CStateManager& mgr) {
x460_knockBackController.Update(thinkDt, mgr, *this); x460_knockBackController.Update(thinkDt, mgr, *this);
x4e4_latestPredictedTranslation = GetTranslation() + PredictMotion(thinkDt).x0_translation; x4e4_latestPredictedTranslation = GetTranslation() + PredictMotion(thinkDt).x0_translation;
x328_26_longJump = false; x328_26_solidCollision = false;
if (x420_curDamageRemTime > 0.f) if (x420_curDamageRemTime > 0.f)
x420_curDamageRemTime -= dt; x420_curDamageRemTime -= dt;
@ -320,7 +320,7 @@ void CPatterned::Think(float dt, CStateManager& mgr) {
if (x3cc_playerLeashRadius != 0.f) { if (x3cc_playerLeashRadius != 0.f) {
zeus::CVector3f diffVec = (GetTranslation() - mgr.GetPlayer().GetTranslation()); zeus::CVector3f diffVec = (GetTranslation() - mgr.GetPlayer().GetTranslation());
if (diffVec.magSquared() > x3cc_playerLeashRadius) if (diffVec.magSquared() > x3cc_playerLeashRadius * x3cc_playerLeashRadius)
x3d4_curPlayerLeashTime += dt; x3d4_curPlayerLeashTime += dt;
else else
x3d4_curPlayerLeashTime = 0.f; x3d4_curPlayerLeashTime = 0.f;
@ -333,6 +333,44 @@ void CPatterned::Think(float dt, CStateManager& mgr) {
x2f8_waypointPauseRemTime -= dt; x2f8_waypointPauseRemTime -= dt;
} }
void CPatterned::CollidedWith(TUniqueId other, const CCollisionInfoList& list, CStateManager& mgr) {
if (x420_curDamageRemTime <= 0.f) {
if (TCastToPtr<CPlayer> player = mgr.ObjectById(other)) {
bool jumpOnHead = player->GetTimeSinceJump() < 5.f && list.GetCount() != 0 &&
list.Front().GetNormalLeft().z() > 0.707f;
if (x400_25_alive || jumpOnHead) {
CDamageInfo cDamage = GetContactDamage();
if (!x400_25_alive || x450_bodyController->IsFrozen())
cDamage.SetDamage(0.f);
if (jumpOnHead) {
mgr.ApplyDamage(GetUniqueId(), player->GetUniqueId(), GetUniqueId(), cDamage,
CMaterialFilter::skPassEverything, -player->GetVelocity());
player->ResetTimeSinceJump();
} else if (x400_25_alive && !x450_bodyController->IsFrozen()) {
mgr.ApplyDamage(GetUniqueId(), player->GetUniqueId(), GetUniqueId(), cDamage,
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::CVector3f::skZero);
}
x420_curDamageRemTime = x424_damageWaitTime;
}
}
}
static CMaterialList testList(EMaterialTypes::Solid, EMaterialTypes::Ceiling, EMaterialTypes::Wall,
EMaterialTypes::Floor, EMaterialTypes::Character);
for (const CCollisionInfo& info : list) {
if (info.GetMaterialLeft().Intersection(testList)) {
if (!info.GetMaterialLeft().HasMaterial(EMaterialTypes::Floor)) {
if (!x310_moveVec.isZero() && info.GetNormalLeft().dot(x310_moveVec) >= 0.f)
continue;
} else if (!x400_31_isFlyer) {
continue;
}
x328_26_solidCollision = true;
return;
}
}
CPhysicsActor::CollidedWith(other, list, mgr);
}
void CPatterned::Touch(CActor& act, CStateManager& mgr) { void CPatterned::Touch(CActor& act, CStateManager& mgr) {
if (!x400_25_alive) if (!x400_25_alive)
return; return;
@ -604,8 +642,7 @@ bool CPatterned::Leash(CStateManager&, float arg) {
bool ret = x3d4_curPlayerLeashTime > x3d0_playerLeashTime; bool ret = x3d4_curPlayerLeashTime > x3d0_playerLeashTime;
if (ret) { if (ret) {
float posToLeashMagSq = (x3a0_latestLeashPosition - GetTranslation()).magSquared(); float posToLeashMagSq = (x3a0_latestLeashPosition - GetTranslation()).magSquared();
if (posToLeashMagSq > x3c8_leashRadius * x3c8_leashRadius) return posToLeashMagSq > x3c8_leashRadius * x3c8_leashRadius;
return true;
} }
return ret; return ret;
} }
@ -1586,7 +1623,7 @@ void CPatterned::ThinkAboutMove(float dt) {
switch (x3f8_moveState) { switch (x3f8_moveState) {
case EMoveState::Zero: case EMoveState::Zero:
if (!x328_26_longJump) if (!x328_26_solidCollision)
break; break;
case EMoveState::One: case EMoveState::One:
doMove = false; doMove = false;
@ -1601,7 +1638,7 @@ void CPatterned::ThinkAboutMove(float dt) {
x3f8_moveState = EMoveState::Three; x3f8_moveState = EMoveState::Three;
case EMoveState::Three: case EMoveState::Three:
doMove = true; doMove = true;
if (!x328_26_longJump) { if (!x328_26_solidCollision) {
x3f8_moveState = EMoveState::Zero; x3f8_moveState = EMoveState::Zero;
break; break;
} }

View File

@ -120,7 +120,7 @@ protected:
struct { struct {
bool x328_24_inPosition : 1; bool x328_24_inPosition : 1;
bool x328_25_verticalMovement : 1; bool x328_25_verticalMovement : 1;
bool x328_26_longJump : 1; bool x328_26_solidCollision : 1;
bool x328_27_onGround : 1; bool x328_27_onGround : 1;
bool x328_28_prevOnGround : 1; bool x328_28_prevOnGround : 1;
bool x328_29_noPatternShagging : 1; bool x328_29_noPatternShagging : 1;
@ -263,6 +263,7 @@ public:
void PreRender(CStateManager&, const zeus::CFrustum&); void PreRender(CStateManager&, const zeus::CFrustum&);
void Render(const CStateManager& mgr) const; void Render(const CStateManager& mgr) const;
void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager& mgr);
void Touch(CActor& act, CStateManager& mgr); void Touch(CActor& act, CStateManager& mgr);
std::experimental::optional<zeus::CAABox> GetTouchBounds() const; std::experimental::optional<zeus::CAABox> GetTouchBounds() const;
bool CanRenderUnsorted(const CStateManager& mgr) const; bool CanRenderUnsorted(const CStateManager& mgr) const;
@ -373,7 +374,7 @@ public:
void SetCoverPoint(CScriptCoverPoint* cp, TUniqueId& id); void SetCoverPoint(CScriptCoverPoint* cp, TUniqueId& id);
void ReleaseCoverPoint(CStateManager& mgr, TUniqueId& id); void ReleaseCoverPoint(CStateManager& mgr, TUniqueId& id);
bool CanLongJump() const { return x328_26_longJump; } bool MadeSolidCollision() const { return x328_26_solidCollision; }
bool IsMakingBigStrike() const { return x402_28_isMakingBigStrike; } bool IsMakingBigStrike() const { return x402_28_isMakingBigStrike; }
// region Casting Functions // region Casting Functions

View File

@ -588,6 +588,8 @@ public:
const std::vector<TUniqueId>& GetOnScreenOrbitObjects() const { return x354_onScreenOrbitObjects; } const std::vector<TUniqueId>& GetOnScreenOrbitObjects() const { return x354_onScreenOrbitObjects; }
const std::vector<TUniqueId>& GetOffScreenOrbitObjects() const { return x364_offScreenOrbitObjects; } const std::vector<TUniqueId>& GetOffScreenOrbitObjects() const { return x364_offScreenOrbitObjects; }
void SetPlayerHitWallDuringMove(); void SetPlayerHitWallDuringMove();
float GetTimeSinceJump() const { return x2a8_timeSinceJump; }
void ResetTimeSinceJump() { x2a8_timeSinceJump = 1000.f; }
ESurfaceRestraints GetCurrentSurfaceRestraint() const { return x2ac_surfaceRestraint; } ESurfaceRestraints GetCurrentSurfaceRestraint() const { return x2ac_surfaceRestraint; }
ESurfaceRestraints GetSurfaceRestraint() const { ESurfaceRestraints GetSurfaceRestraint() const {
return x2b0_outOfWaterTicks == 2 ? GetCurrentSurfaceRestraint() : ESurfaceRestraints::Water; return x2b0_outOfWaterTicks == 2 ? GetCurrentSurfaceRestraint() : ESurfaceRestraints::Water;

View File

@ -35,7 +35,7 @@ void CScriptBeam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CSt
mgr.AddObject(new CPlasmaProjectile(xe8_weaponDescription, x10_name + "-Projectile", mgr.AddObject(new CPlasmaProjectile(xe8_weaponDescription, x10_name + "-Projectile",
x138_damageInfo.GetWeaponMode().GetType(), xf4_beamInfo, x34_transform, x138_damageInfo.GetWeaponMode().GetType(), xf4_beamInfo, x34_transform,
EMaterialTypes::Projectile, x138_damageInfo, x8_uid, x4_areaId, EMaterialTypes::Projectile, x138_damageInfo, x8_uid, x4_areaId,
x154_projectileId, 8, false, EProjectileAttrib::PlasmaProjectile)); x154_projectileId, {}, false, EProjectileAttrib::PlasmaProjectile));
} else if (msg == EScriptObjectMessage::Deleted) { } else if (msg == EScriptObjectMessage::Deleted) {
} }

View File

@ -791,14 +791,14 @@ CEntity* ScriptLoader::LoadNewIntroBoss(CStateManager& mgr, CInputStream& in, in
CActorParameters actParms = LoadActorParameters(in); CActorParameters actParms = LoadActorParameters(in);
float f1 = in.readFloatBig(); float f1 = in.readFloatBig();
CAssetId w1(in); CAssetId projectile(in);
CDamageInfo dInfo(in); CDamageInfo dInfo(in);
CAssetId w2(in); CAssetId beamContactFxId(in);
CAssetId w3(in); CAssetId beamPulseFxId(in);
CAssetId w4(in); CAssetId beamTextureId(in);
CAssetId w5(in); CAssetId beamGlowTextureId(in);
const CAnimationParameters& aParms = pInfo.GetAnimationParameters(); const CAnimationParameters& aParms = pInfo.GetAnimationParameters();
FourCC animType = g_ResFactory->GetResourceTypeById(aParms.GetACSFile()); FourCC animType = g_ResFactory->GetResourceTypeById(aParms.GetACSFile());
@ -808,7 +808,7 @@ CEntity* ScriptLoader::LoadNewIntroBoss(CStateManager& mgr, CInputStream& in, in
CAnimRes res(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, aParms.GetInitialAnimation(), true); CAnimRes res(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, aParms.GetInitialAnimation(), true);
return new MP1::CNewIntroBoss(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, res, pInfo, actParms, return new MP1::CNewIntroBoss(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, res, pInfo, actParms,
f1, w1, dInfo, w2, w3, w4, w5); f1, projectile, dInfo, beamContactFxId, beamPulseFxId, beamTextureId, beamGlowTextureId);
} }
CEntity* ScriptLoader::LoadSpawnPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { CEntity* ScriptLoader::LoadSpawnPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) {

View File

@ -255,6 +255,14 @@ public:
using const_reverse_iterator = typename base::const_reverse_iterator; using const_reverse_iterator = typename base::const_reverse_iterator;
reserved_vector() : x0_size(0) {} reserved_vector() : x0_size(0) {}
template <size_t LN>
reserved_vector(const T(&l)[LN])
: x0_size(LN) {
static_assert(LN <= N, "initializer array too large for reserved_vector");
for (size_t i = 0; i < LN; ++i)
::new (static_cast<void*>(std::addressof(_value(i)))) T(l[i]);
}
reserved_vector(const reserved_vector& other) : x0_size(other.x0_size) { reserved_vector(const reserved_vector& other) : x0_size(other.x0_size) {
for (size_t i = 0; i < x0_size; ++i) for (size_t i = 0; i < x0_size; ++i)
::new (static_cast<void*>(std::addressof(_value(i)))) T(other._value(i)); ::new (static_cast<void*>(std::addressof(_value(i)))) T(other._value(i));

View File

@ -0,0 +1,151 @@
#shader CColoredStripShader
#attribute position4
#attribute color
#attribute uv4
#srcfac srcalpha
#dstfac invsrcalpha
#primitive tristrips
#depthtest lequal
#depthwrite false
#culling none
#vertex glsl
layout(location=0) in vec4 posIn;
layout(location=1) in vec4 colorIn;
layout(location=2) in vec4 uvIn;
UBINDING0 uniform ColoredQuadUniform
{
mat4 xf;
vec4 color;
};
struct VertToFrag
{
vec4 color;
vec2 uv;
};
SBINDING(0) out VertToFrag vtf;
void main()
{
vtf.color = colorIn * color;
vtf.uv = uvIn.xy;
gl_Position = xf * vec4(posIn.xyz, 1.0);
}
#fragment glsl
struct VertToFrag
{
vec4 color;
vec2 uv;
};
SBINDING(0) in VertToFrag vtf;
layout(location=0) out vec4 colorOut;
TBINDING0 uniform sampler2D tex;
void main()
{
colorOut = vtf.color * texture(tex, vtf.uv);
}
#vertex hlsl
struct VertData
{
float4 posIn : POSITION;
float4 colorIn : COLOR;
float4 uvIn : UV;
};
cbuffer ColoredQuadUniform : register(b0)
{
float4x4 xf;
float4 color;
};
struct VertToFrag
{
float4 position : SV_Position;
float4 color : COLOR;
float2 uv : UV;
};
VertToFrag main(in VertData v)
{
VertToFrag vtf;
vtf.color = v.colorIn * color;
vtf.uv = v.uvIn.xy;
vtf.position = mul(xf, float4(v.posIn.xyz, 1.0));
return vtf;
}
#fragment hlsl
SamplerState samp : register(s0);
Texture2D tex0 : register(t0);
struct VertToFrag
{
float4 position : SV_Position;
float4 color : COLOR;
float2 uv : UV;
};
float4 main(in VertToFrag vtf) : SV_Target0
{
return vtf.color * tex0.Sample(samp, vtf.uv);
}
#vertex metal
struct VertData
{
float4 posIn [[ attribute(0) ]];
float4 colorIn [[ attribute(1) ]];
float4 uvIn [[ attribute(2) ]];
};
struct ColoredQuadUniform
{
float4x4 xf;
float4 color;
};
struct VertToFrag
{
float4 position [[ position ]];
float4 color;
float2 uv;
};
vertex VertToFrag vmain(VertData v [[ stage_in ]], constant ColoredQuadUniform& cqu [[ buffer(2) ]])
{
VertToFrag vtf;
vtf.color = v.colorIn * cqu.color;
vtf.uv = v.uvIn.xy;
vtf.position = cqu.xf * float4(v.posIn.xyz, 1.0);
return vtf;
}
#fragment metal
struct VertToFrag
{
float4 position [[ position ]];
float4 color;
float2 uv;
};
fragment float4 fmain(VertToFrag vtf [[ stage_in ]],
sampler samp [[ sampler(0) ]],
texture2d<float> tex0 [[ texture(0) ]])
{
return vtf.color * tex0.sample(samp, vtf.uv);
}
#shader CColoredStripShaderAdditive : CColoredStripShader
#srcfac srcalpha
#dstfac one
#shader CColoredStripShaderFullAdditive : CColoredStripShader
#srcfac one
#dstfac one

View File

@ -7,6 +7,7 @@ include_directories(../hecl/include
add_shader(CAABoxShader) add_shader(CAABoxShader)
add_shader(CCameraBlurFilter) add_shader(CCameraBlurFilter)
add_shader(CColoredQuadFilter) add_shader(CColoredQuadFilter)
add_shader(CColoredStripShader)
add_shader(CDecalShaders) add_shader(CDecalShaders)
add_shader(CElementGenShaders) add_shader(CElementGenShaders)
add_shader(CEnergyBarShader) add_shader(CEnergyBarShader)

2
hecl

@ -1 +1 @@
Subproject commit cdba678eee605cf0aff96f1276bc3593fca0de2b Subproject commit d4a0f17336f19906a6c4f2ed83fd34945f017593