Merge pull request #301 from AxioDL/omegapirate

OmegaPirate implementation
This commit is contained in:
Luke Street 2020-04-20 03:21:04 -04:00 committed by GitHub
commit 7b1e041123
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 2325 additions and 108 deletions

View File

@ -1472,7 +1472,7 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo
beaconAlpha = loc.x4_beaconAlpha;
}
if (beaconAlpha > 0.f) {
const std::array<CTexturedQuadFilter::Vert, 4> verts{{
constexpr std::array<CTexturedQuadFilter::Vert, 4> verts{{
{{-4.f, -8.f, 8.f}, {0.f, 1.f}},
{{-4.f, -8.f, 0.f}, {0.f, 0.f}},
{{4.f, -8.f, 8.f}, {1.f, 1.f}},
@ -1486,7 +1486,7 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo
colorAlpha *= mapAlpha;
zeus::CColor color = zeus::skWhite;
color.a() = colorAlpha;
filter.drawVerts(color, verts.data());
filter.drawVerts(color, verts);
}
}
}

View File

@ -170,13 +170,13 @@ void CMappableObject::Draw(int curArea, const CMapWorldInfo& mwInfo, float alpha
m_texQuadFilter.emplace(EFilterType::Add, tex, CTexturedQuadFilter::ZTest::GEqual);
}
const std::array<CTexturedQuadFilter::Vert, 4> verts{{
constexpr std::array<CTexturedQuadFilter::Vert, 4> verts{{
{{-2.6f, 0.f, 2.6f}, {0.f, 1.f}},
{{-2.6f, 0.f, -2.6f}, {0.f, 0.f}},
{{2.6f, 0.f, 2.6f}, {1.f, 1.f}},
{{2.6f, 0.f, -2.6f}, {1.f, 0.f}},
}};
m_texQuadFilter->drawVerts(iconColor, verts.data());
m_texQuadFilter->drawVerts(iconColor, verts);
}
}

View File

@ -39,10 +39,12 @@ void CSimpleShadow::Render(const TLockedToken<CTexture>& tex) {
m_filter.emplace(EFilterType::InvDstMultiply, tex, CTexturedQuadFilter::ZTest::LEqual);
float radius = x34_radius * x30_scale;
CTexturedQuadFilter::Vert verts[] = {{{-radius, 0.f, -radius}, {0.f, 0.f}},
{{radius, 0.f, -radius}, {0.f, 1.f}},
{{-radius, 0.f, radius}, {1.f, 0.f}},
{{radius, 0.f, radius}, {1.f, 1.f}}};
const std::array<CTexturedQuadFilter::Vert, 4> verts{{
{{-radius, 0.f, -radius}, {0.f, 0.f}},
{{radius, 0.f, -radius}, {0.f, 1.f}},
{{-radius, 0.f, radius}, {1.f, 0.f}},
{{radius, 0.f, radius}, {1.f, 1.f}},
}};
m_filter->drawVerts(zeus::skWhite, verts);
}

View File

@ -258,10 +258,10 @@ void CTexturedQuadFilter::drawCropped(const zeus::CColor& color, float uvScale)
CGraphics::DrawArray(0, 4);
}
void CTexturedQuadFilter::drawVerts(const zeus::CColor& color, const Vert verts[4], float lod) {
void CTexturedQuadFilter::drawVerts(const zeus::CColor& color, std::array<Vert, 4> verts, float lod) {
SCOPED_GRAPHICS_DEBUG_GROUP("CTexturedQuadFilter::drawVerts", zeus::skMagenta);
m_vbo->load(verts, sizeof(Vert) * 4);
m_vbo->load(verts.data(), sizeof(Vert) * verts.size());
m_uniform.m_matrix = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f();
m_uniform.m_color = color;
@ -269,7 +269,7 @@ void CTexturedQuadFilter::drawVerts(const zeus::CColor& color, const Vert verts[
m_uniBuf->load(&m_uniform, sizeof(m_uniform));
CGraphics::SetShaderDataBinding(m_dataBind);
CGraphics::DrawArray(0, 4);
CGraphics::DrawArray(0, verts.size());
}
void CTexturedQuadFilter::DrawFilter(EFilterShape shape, const zeus::CColor& color, float t) {

View File

@ -53,7 +53,7 @@ public:
CTexturedQuadFilter& operator=(CTexturedQuadFilter&&) = default;
void draw(const zeus::CColor& color, float uvScale, const zeus::CRectangle& rect = DefaultRect, float z = 0.f);
void drawCropped(const zeus::CColor& color, float uvScale);
void drawVerts(const zeus::CColor& color, const Vert verts[4], float lod = 0.f);
void drawVerts(const zeus::CColor& color, std::array<Vert, 4> verts, float lod = 0.f);
void DrawFilter(EFilterShape shape, const zeus::CColor& color, float t);
const TLockedToken<CTexture>& GetTex() const { return m_tex; }
const boo::ObjToken<boo::ITexture>& GetBooTex() const { return m_booTex; }

View File

@ -90,14 +90,14 @@ void CAuiImagePane::DoDrawImagePane(const zeus::CColor& color, const CTexture& t
}};
if (noBlur) {
quad.drawVerts(useColor, verts.data());
quad.drawVerts(useColor, verts);
} else if ((x14c_deResFactor == 0.f && alpha == 1.f) || tex.GetNumMips() == 1) {
quad.drawVerts(useColor, verts.data(), 0.f);
quad.drawVerts(useColor, verts, 0.f);
} else {
const float tmp = (1.f - x14c_deResFactor) * alpha;
const float tmp3 = 1.f - tmp * tmp * tmp;
const float mip = tmp3 * static_cast<float>(tex.GetNumMips() - 1);
quad.drawVerts(useColor, verts.data(), mip);
quad.drawVerts(useColor, verts, mip);
}
}

View File

@ -45,12 +45,12 @@ void CScanDisplay::CDataDot::Draw(const zeus::CColor& col, float radius) {
CGraphics::SetModelMatrix(xf);
zeus::CColor useColor = col;
useColor.a() *= x24_alpha;
const CTexturedQuadFilter::Vert verts[4] = {
const std::array<CTexturedQuadFilter::Vert, 4> verts{{
{{-radius, 0.f, radius}, {0.f, 1.f}},
{{-radius, 0.f, -radius}, {0.f, 0.f}},
{{radius, 0.f, radius}, {1.f, 1.f}},
{{radius, 0.f, -radius}, {1.f, 0.f}},
};
}};
m_quad.drawVerts(useColor, verts);
}
}

View File

@ -614,11 +614,11 @@ void CInGameGuiManager::Draw(CStateManager& stateMgr) {
if (!m_deathRenderTexQuad)
m_deathRenderTexQuad.emplace(EFilterType::Blend, CGraphics::g_SpareTexture.get());
m_deathRenderTexQuad->drawVerts(zeus::CColor(1.f, colT), verts.data());
m_deathRenderTexQuad->drawVerts(zeus::CColor(1.f, colT), verts);
if (!m_deathDotQuad)
m_deathDotQuad.emplace(EFilterType::Multiply, x50_deathDot);
m_deathDotQuad->drawVerts(zeus::CColor(1.f, colT), verts.data());
m_deathDotQuad->drawVerts(zeus::CColor(1.f, colT), verts);
}
}
}

View File

@ -372,12 +372,12 @@ void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, CTargetingManager* t
const float uvX1 = float(rect.x4_left + rect.xc_width) / float(g_Viewport.x8_width);
const float uvY0 = float(rect.x8_top) / float(g_Viewport.xc_height);
const float uvY1 = float(rect.x8_top + rect.x10_height) / float(g_Viewport.xc_height);
CTexturedQuadFilter::Vert rttVerts[4] = {
std::array<CTexturedQuadFilter::Vert, 4> rttVerts{{
{{-5.f, 0.f, 4.45f}, {uvX0, uvY0}},
{{5.f, 0.f, 4.45f}, {uvX1, uvY0}},
{{-5.f, 0.f, -4.45f}, {uvX0, uvY1}},
{{5.f, 0.f, -4.45f}, {uvX1, uvY1}},
};
}};
if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) {
rttVerts[0].m_uv.y() = uvY1;
rttVerts[1].m_uv.y() = uvY1;

View File

@ -611,7 +611,7 @@ void CElitePirate::SpecialAttack(CStateManager& mgr, EStateMsg msg, float) {
}
} else if (x568_state == EState::Two) {
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) {
x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation());
x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation());
} else {
x568_state = EState::Over;
}

View File

@ -77,6 +77,15 @@ public:
};
class CElitePirate : public CPatterned {
protected:
enum class EState {
Invalid = -1,
Zero = 0,
One = 1,
Two = 2,
Over = 3,
};
private:
struct SUnknownStruct {
private:
@ -90,14 +99,6 @@ private:
void Clear() { x4_.clear(); }
};
enum class EState {
Invalid = -1,
Zero = 0,
One = 1,
Two = 2,
Over = 3,
};
EState x568_state = EState::Invalid;
CDamageVulnerability x56c_vulnerability;
std::unique_ptr<CCollisionActorManager> x5d4_collisionActorMgr;
@ -189,12 +190,28 @@ public:
virtual void SetupHealthInfo(CStateManager& mgr);
virtual void SetLaunchersActive(CStateManager& mgr, bool val);
virtual SShockWaveData GetShockWaveData() const {
return {x5d8_data.GetXF8(), x5d8_data.GetXFC(), x5d8_data.GetX118(), x5d8_data.GetX11C()};
return {x5d8_data.GetXF8(), x5d8_data.GetXFC(), 16.5217f, x5d8_data.GetX118(), x5d8_data.GetX11C()};
}
private:
void SetupPathFindSearch();
protected:
void SetShotAt(bool val, CStateManager& mgr);
void CreateGrenadeLauncher(CStateManager& mgr, TUniqueId uid);
zeus::CVector3f GetLockOnPosition(const CActor* actor) const;
bool ShouldFireFromLauncher(CStateManager& mgr, TUniqueId launcherId);
bool ShouldCallForBackupFromLauncher(const CStateManager& mgr, TUniqueId uid) const;
void SetupLauncherHealthInfo(CStateManager& mgr, TUniqueId uid);
void SetLauncherActive(CStateManager& mgr, bool val, TUniqueId uid);
void SetupPathFindSearch();
void UpdateActorTransform(CStateManager& mgr, TUniqueId& uid, std::string_view name);
const CElitePirateData& GetData() const { return x5d8_data; }
EState GetState() const { return x568_state; }
void SetState(EState state) { x568_state = state; }
TUniqueId GetLauncherId() const { return x772_launcherId; }
void SetAlert(bool val) { x988_28_alert = val; }
const CCollisionActorManager& GetCollisionActorManager() const { return *x5d4_collisionActorMgr; }
private:
bool IsArmClawCollider(TUniqueId uid, const rstl::reserved_vector<TUniqueId, 7>& vec) const;
void AddSphereCollisionList(const SSphereJointInfo* joints, size_t count,
std::vector<CJointCollisionDescription>& outJoints) const;
@ -204,12 +221,8 @@ private:
void SetupCollisionActorInfo(CStateManager& mgr);
bool IsArmClawCollider(std::string_view name, std::string_view locator, const SJointInfo* info,
size_t infoCount) const;
void CreateGrenadeLauncher(CStateManager& mgr, TUniqueId uid);
void ApplyDamageToHead(CStateManager& mgr, TUniqueId uid);
void CreateEnergyAbsorb(CStateManager& mgr, const zeus::CTransform& xf);
void SetupLauncherHealthInfo(CStateManager& mgr, TUniqueId uid);
void SetLauncherActive(CStateManager& mgr, bool val, TUniqueId uid);
zeus::CVector3f GetLockOnPosition(const CActor* actor) const;
bool CanKnockBack(const CDamageInfo& info) const;
void UpdateDestPos(CStateManager& mgr);
void CheckAttackChance(CStateManager& mgr);
@ -218,13 +231,10 @@ private:
bool IsAttractingEnergy() const;
void UpdateTimers(float dt);
void UpdatePositionHistory();
void UpdateActorTransform(CStateManager& mgr, TUniqueId& uid, std::string_view name);
void UpdateHealthInfo(CStateManager& mgr);
void ExtendTouchBounds(const CStateManager& mgr, const rstl::reserved_vector<TUniqueId, 7>& uids,
const zeus::CVector3f& vec) const;
bool ShouldFireFromLauncher(CStateManager& mgr, TUniqueId launcherId);
bool ShouldCallForBackupFromLauncher(const CStateManager& mgr, TUniqueId uid) const;
bool IsClosestEnergyAttractor(const CStateManager& mgr, const rstl::reserved_vector<TUniqueId, 1024>& charNearList,
const zeus::CVector3f& projectilePos) const;
};
} // namespace urde
} // namespace urde::MP1

View File

@ -131,8 +131,7 @@ void CGrenadeLauncher::PreRender(CStateManager& mgr, const zeus::CFrustum& frust
// Original code redundantly sets a() = 1.f
xb4_drawFlags.addColor = x3f4_color3;
} else {
xb4_drawFlags = CModelFlags{5, 0, 3, zeus::skWhite};
xb4_drawFlags.addColor = x3f4_color3;
xb4_drawFlags = CModelFlags{5, 0, 3, x3f4_color3};
}
CActor::PreRender(mgr, frustum);
}
@ -152,7 +151,7 @@ void CGrenadeLauncher::Think(float dt, CStateManager& mgr) {
UpdateCollision();
UpdateColor(dt);
sub_8022f9e0(mgr, dt);
UpdateFollowPlayer(mgr, dt);
UpdateDamageTime(dt);
const SAdvancementDeltas& deltas = CActor::UpdateAnimation(dt, mgr, true);
@ -212,13 +211,14 @@ void CGrenadeLauncher::CreateExplosion(CStateManager& mgr) {
CSfxManager::SfxStart(x2d0_data.GetExplosionSfx(), 1.f, 1.f, false, 0x7f, false, kInvalidAreaId);
}
void CGrenadeLauncher::sub_8022f9e0(CStateManager& mgr, float dt) {
void CGrenadeLauncher::UpdateFollowPlayer(CStateManager& mgr, float dt) {
CModelData* modelData = GetModelData();
CAnimData* animData = nullptr;
if (modelData != nullptr && (animData = modelData->GetAnimationData()) != nullptr && x258_started == 1 && x3fe_) {
if (modelData != nullptr && (animData = modelData->GetAnimationData()) != nullptr && x258_started == 1 &&
x3fe_followPlayer) {
const zeus::CVector3f target = mgr.GetPlayer().GetAimPosition(mgr, 0.f) - GetTranslation();
const zeus::CVector3f rot = GetTransform().rotate({target.x(), target.y(), 0.f}); // TODO double check
const zeus::CVector3f rot = GetTransform().transposeRotate({target.x(), target.y(), 0.f});
if (rot.canBeNormalized()) {
constexpr float p36d = zeus::degToRad(36.476f);

View File

@ -88,7 +88,7 @@ private:
float x3f8_explodePlayerDistance;
bool x3fc_launchGrenade = false;
bool x3fd_visible = true;
bool x3fe_ = true;
bool x3fe_followPlayer = true;
public:
CGrenadeLauncher(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
@ -108,6 +108,10 @@ public:
void Think(float dt, CStateManager& mgr) override;
void Touch(CActor& act, CStateManager& mgr) override;
void SetColor(const zeus::CColor& color) { x3f4_color3 = color; }
void SetVisible(bool val) { x3fd_visible = val; }
void SetFollowPlayer(bool val) { x3fe_followPlayer = val; }
static zeus::CVector3f GrenadeTarget(const CStateManager& mgr);
static void CalculateGrenadeTrajectory(const zeus::CVector3f& target, const zeus::CVector3f& origin,
const SGrenadeTrajectoryInfo& info, float& angleOut, float& velocityOut);
@ -117,7 +121,7 @@ private:
void UpdateColor(float arg);
void UpdateDamageTime(float arg);
void CreateExplosion(CStateManager& mgr);
void sub_8022f9e0(CStateManager& mgr, float dt);
void UpdateFollowPlayer(CStateManager& mgr, float dt);
void sub_80230438();
void LaunchGrenade(CStateManager& mgr);
};

View File

@ -29,6 +29,8 @@ set(MP1_WORLD_SOURCES
CNewIntroBoss.hpp CNewIntroBoss.cpp
COmegaPirate.hpp COmegaPirate.cpp
CParasite.hpp CParasite.cpp
CPhazonHealingNodule.hpp CPhazonHealingNodule.cpp
CPhazonPool.hpp CPhazonPool.cpp
CPuddleSpore.hpp CPuddleSpore.cpp
CPuddleToadGamma.hpp CPuddleToadGamma.cpp
CPuffer.hpp CPuffer.cpp

File diff suppressed because it is too large Load Diff

View File

@ -7,18 +7,185 @@ class COmegaPirate : public CElitePirate {
private:
class CFlash : public CActor {
private:
CToken xe8_;
int xf0_;
float xf4_;
float xf8_;
float xfc_;
// TToken<CTexture> xe8_thermalSpotToken;
// CTexture* xf0_thermalSpot = nullptr;
float xf4_delay;
float xf8_time = 0.f;
float xfc_size = 0.f;
CFlash(TUniqueId uid, const CEntityInfo& info, const zeus::CVector3f& pos, CToken& p4, float p5);
CTexturedQuadFilter m_thermalSpotAdd;
CTexturedQuadFilter m_thermalSpotSubtract;
public:
CFlash(TUniqueId uid, const CEntityInfo& info, const zeus::CVector3f& pos, TLockedToken<CTexture>& thermalSpot,
float delay);
void Accept(IVisitor& visitor) override;
void Think(float dt, CStateManager& mgr) override;
void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override;
void AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) override;
void Render(CStateManager& mgr) override;
};
TUniqueId x990_launcherId2 = kInvalidUniqueId;
enum class ENormalFadeState {
Zero,
One,
Two,
Three,
} x994_normalFadeState = ENormalFadeState::Zero;
float x998_normalFadeTime = 0.f;
float x99c_normalAlpha = 1.f;
bool x9a0_visible = true;
bool x9a1_fadeIn = true;
std::vector<std::pair<TUniqueId, std::vector<TUniqueId>>> x9a4_scriptWaypointPlatforms;
bool x9b4_ = false;
std::vector<std::pair<TUniqueId, std::string_view>> x9b8_scriptEffects;
enum class EScaleState {
None,
ScaleDownX,
ScaleDownY,
ScaleDownZ,
WaitForTrigger,
ScaleUpX,
ScaleUpY,
ScaleUpZ,
} x9c8_scaleState = EScaleState::None;
float x9cc_scaleTime = 0.f;
zeus::CVector3f x9d0_initialScale;
std::vector<std::pair<TUniqueId, std::string_view>> x9dc_scriptPlatforms;
bool x9ec_decrement = false;
CSkinnedModel x9f0_skeletonModel;
float xa2c_skeletonAlpha = 0.f;
enum class ESkeletonFadeState {
None,
FadeOut,
Flash,
FadeIn,
} xa30_skeletonFadeState = ESkeletonFadeState::None;
float xa34_skeletonStateTime = 0.f;
std::unique_ptr<CCollisionActorManager> xa38_collisionActorMgr1;
bool xa3c_hearPlayer = false;
pas::ELocomotionType xa40_locomotionType = pas::ELocomotionType::Relaxed;
bool xa44_targetable = false;
TUniqueId xa46_ = kInvalidUniqueId;
TUniqueId xa48_ = kInvalidUniqueId;
bool xa4a_heartVisible = false;
zeus::CTransform xa4c_initialXf;
enum class EXRayFadeState {
None,
FadeIn,
WaitForTrigger,
FadeOut,
} xa7c_xrayAlphaState = EXRayFadeState::None;
float xa80_xrayAlpha = 1.f;
float xa84_xrayAlphaStateTime = 0.f;
bool xa88_xrayFadeInTrigger = false;
float xa8c_ = 3.f;
float xa90_ = 1.f;
float xa94_ = 1.f;
float xa98_maxEnergy = 0.f;
std::unique_ptr<CCollisionActorManager> xa9c_collisionActorMgr2;
std::vector<std::pair<TUniqueId, std::string_view>> xaa0_scriptSounds;
float xab0_ = 0.f;
std::vector<u32> xab4_;
int xac4_ = 0;
int xac8_ = 0;
int xacc_ = 0;
bool xad0_scaleUpTrigger = false;
float xad4_cachedSpeed = 1.f;
bool xad8_cover = false;
TUniqueId xada_lastWaypointId = kInvalidUniqueId;
bool xadc_ = false;
bool xadd_ = false;
u8 xade_armorPiecesDestroyed = 0;
bool xadf_launcher1FollowPlayer = true;
bool xae0_launcher2FollowPlayer = true;
CDamageVulnerability xae4_platformVuln = CDamageVulnerability::NormalVulnerabilty();
int xb4c_armorPiecesHealed = 0;
float xb50_ = 0.f;
zeus::CColor xb54_platformColor = zeus::skWhite;
float xb58_ = 2.5f;
float xb5c_ = 0.f;
float xb60_ = 0.f;
float xb64_ = 17.f;
int xb68_ = 0;
bool xb6c_ = false;
bool xb6d_ = false;
bool xb6e_ = false;
TLockedToken<CTexture> xb70_thermalSpot; // was TToken<CTexture>
bool xb78_codeTrigger = false;
bool xb79_ = false;
std::vector<u8> xb7c_;
float xb8c_ = 0.f; // not initialized in ctr
public:
COmegaPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CElitePirateData data,
CAssetId w1, CAssetId w2, CAssetId w3);
void Think(float dt, CStateManager& mgr) override;
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override;
void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override;
void Render(CStateManager& mgr) override;
zeus::CVector3f GetOrbitPosition(const CStateManager& mgr) const override;
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override;
void PathFind(CStateManager& mgr, EStateMsg msg, float dt) override;
void TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) override;
void Run(CStateManager& mgr, EStateMsg msg, float dt) override;
void Attack(CStateManager& mgr, EStateMsg msg, float dt) override;
void JumpBack(CStateManager& mgr, EStateMsg msg, float dt) override;
void DoubleSnap(CStateManager& mgr, EStateMsg msg, float dt) override;
void Shuffle(CStateManager& mgr, EStateMsg msg, float dt) override;
void Skid(CStateManager& mgr, EStateMsg msg, float dt) override;
void Suck(CStateManager& mgr, EStateMsg msg, float dt) override;
void Explode(CStateManager& mgr, EStateMsg msg, float dt) override;
void Retreat(CStateManager& mgr, EStateMsg msg, float dt) override;
void Cover(CStateManager& mgr, EStateMsg msg, float dt) override;
void WallHang(CStateManager& mgr, EStateMsg msg, float dt) override;
void WallDetach(CStateManager& mgr, EStateMsg msg, float dt) override;
void Enraged(CStateManager& mgr, EStateMsg msg, float dt) override;
void Growth(CStateManager& mgr, EStateMsg msg, float dt) override;
void Faint(CStateManager& mgr, EStateMsg msg, float dt) override;
void Dizzy(CStateManager& mgr, EStateMsg msg, float dt) override;
bool Landed(CStateManager& mgr, float arg) override;
bool HearPlayer(CStateManager& mgr, float arg) override;
bool CoverBlown(CStateManager& mgr, float arg) override;
bool AggressionCheck(CStateManager& mgr, float arg) override;
bool ShouldFire(CStateManager& mgr, float arg) override;
bool ShouldMove(CStateManager& mgr, float arg) override;
bool ShotAt(CStateManager& mgr, float arg) override;
bool CodeTrigger(CStateManager& mgr, float arg) override;
bool ShouldCallForBackup(CStateManager& mgr, float arg) override;
bool HasWeakPointHead() const override { return false; }
bool IsElitePirate() const override { return false; }
void SetupHealthInfo(CStateManager& mgr) override;
void SetLaunchersActive(CStateManager& mgr, bool val) override;
SShockWaveData GetShockWaveData() const override {
return {GetData().GetXF8(), GetData().GetXFC(), 24.78255f, GetData().GetX118(), GetData().GetX11C()};
}
private:
void CreateFlash(CStateManager& mgr, float arg);
void SetupCollisionManager(CStateManager& mgr);
void AddSphereCollisionList(const SSphereJointInfo* joints, size_t count,
std::vector<CJointCollisionDescription>& outJoints) const;
void AddOBBAutoSizeCollisionList(const SOBBJointInfo* joints, size_t count,
std::vector<CJointCollisionDescription>& outJoints) const;
void SetupCollisionActorInfo1(const std::unique_ptr<CCollisionActorManager>& actMgr, CStateManager& mgr);
void SetupCollisionActorInfo2(const std::unique_ptr<CCollisionActorManager>& actMgr, CStateManager& mgr);
void sub_8028cbec(u32 arg, CStateManager& mgr);
u8 sub_8028c230() const;
u8 sub_8028bfac() const;
void TeleportToFurthestPlatform(CStateManager& mgr);
void UpdateNormalAlpha(CStateManager& mgr, float dt);
void sub_8028c704(CStateManager& mgr, float dt);
void UpdateXRayAlpha(CStateManager& mgr, float dt);
void UpdateScale(CStateManager& mgr, float dt);
void UpdateSkeletonAlpha(CStateManager& mgr, float dt);
void DeathDestroy(CStateManager& mgr);
void sub_8028c840(u32 arg, CStateManager& mgr);
zeus::CVector3f FindGround(const zeus::CVector3f& pos, CStateManager& mgr) const;
};
} // namespace urde::MP1

View File

@ -0,0 +1,186 @@
#include "Runtime/MP1/World/CPhazonHealingNodule.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/World/CPatternedInfo.hpp"
namespace urde::MP1 {
CPhazonHealingNodule::CPhazonHealingNodule(TUniqueId uid, std::string_view name, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData,
const CActorParameters& actParams, const CPatternedInfo& pInfo,
CAssetId particleDescId, std::string actorLctr)
: CPatterned(ECharacter::PhazonHealingNodule, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParams, EKnockBackVariant::Medium)
, x570_electricDesc(g_SimplePool->GetObj(SObjectTag{SBIG('ELSC'), particleDescId}))
, x580_initialHealthInfo(pInfo.GetHealthInfo())
, x58c_actorLctr(std::move(actorLctr)) {
const CMaterialFilter& filter = GetMaterialFilter();
CMaterialList include = filter.GetIncludeList();
CMaterialList exclude = filter.GetExcludeList();
exclude.Add(EMaterialTypes::Character);
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude));
}
void CPhazonHealingNodule::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
switch (msg) {
case EScriptObjectMessage::Decrement:
x568_active = 0;
x57c_particleElectric.reset();
x56c_emitting = false;
break;
case EScriptObjectMessage::Increment:
x568_active = 1;
break;
case EScriptObjectMessage::Reset:
*HealthInfo(mgr) = x580_initialHealthInfo;
break;
case EScriptObjectMessage::Registered:
if (!GetBodyController()->GetActive()) {
GetBodyController()->Activate(mgr);
}
// TODO remove const_cast
*const_cast<CDamageVulnerability*>(GetDamageVulnerability()) = CDamageVulnerability::ImmuneVulnerabilty();
GetKnockBackController().SetAutoResetImpulse(false);
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed);
RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr);
AddMaterial(EMaterialTypes::Immovable, mgr);
break;
case EScriptObjectMessage::InitializedInArea:
CPatterned::AcceptScriptMsg(msg, uid, mgr);
for (const auto& conn : GetConnectionList()) {
auto connId = mgr.GetIdForScript(conn.x8_objId);
if (conn.x0_state == EScriptObjectState::Patrol && connId != kInvalidUniqueId &&
conn.x4_msg == EScriptObjectMessage::Activate) {
x56e_connId = connId;
}
}
break;
default:
CPatterned::AcceptScriptMsg(msg, uid, mgr);
break;
}
}
void CPhazonHealingNodule::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) {
SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None);
SendScriptMsgs(EScriptObjectState::DeathRattle, mgr, EScriptObjectMessage::None);
}
void CPhazonHealingNodule::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type,
float dt) {
if (type == EUserEventType::EndAction) {
x56c_emitting = false;
x57c_particleElectric.reset();
} else if (type == EUserEventType::BeginAction) {
x56c_emitting = true;
x57c_particleElectric = std::make_unique<CParticleElectric>(x570_electricDesc);
x57c_particleElectric->SetParticleEmission(true);
} else {
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
}
}
void CPhazonHealingNodule::Faint(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Update) {
if (x588_state == 0) {
if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Step) {
x588_state = 2;
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed);
} else {
GetBodyController()->GetCommandMgr().DeliverCmd(
CBCStepCmd(pas::EStepDirection::Backward, pas::EStepType::Normal));
}
} else if (x588_state == 2 && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Step) {
x588_state = 3;
}
} else if (msg == EStateMsg::Activate) {
x588_state = 0;
}
}
void CPhazonHealingNodule::Growth(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Update) {
if (x588_state == 0) {
if (GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Step) {
x588_state = 2;
} else {
GetBodyController()->GetCommandMgr().DeliverCmd(
CBCStepCmd(pas::EStepDirection::Forward, pas::EStepType::Normal));
}
} else if (x588_state == 2 && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Step) {
x588_state = 3;
}
} else if (msg == EStateMsg::Activate) {
x588_state = 0;
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Lurk);
}
}
void CPhazonHealingNodule::KnockBack(const zeus::CVector3f& vec, CStateManager& mgr, const CDamageInfo& info,
EKnockBackType type, bool inDeferred, float magnitude) {}
void CPhazonHealingNodule::Lurk(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Lurk);
}
}
void CPhazonHealingNodule::Patrol(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed);
RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr);
}
}
void CPhazonHealingNodule::Render(CStateManager& mgr) {
if (x57c_particleElectric) {
x57c_particleElectric->Render();
}
CPatterned::Render(mgr);
}
void CPhazonHealingNodule::Think(float dt, CStateManager& mgr) {
if (!GetActive()) {
return;
}
CPatterned::Think(dt, mgr);
if (HealthInfo(mgr)->GetHP() <= 0.f) {
x57c_particleElectric.reset();
x56c_emitting = false;
x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Patrol"sv);
x568_active = 0;
}
if (x57c_particleElectric) {
UpdateParticleElectric(mgr);
x57c_particleElectric->Update(dt);
}
}
void CPhazonHealingNodule::UpdateParticleElectric(CStateManager& mgr) {
if (!x57c_particleElectric) {
return;
}
if (auto entity = static_cast<const CPatterned*>(mgr.GetObjectById(x56e_connId))) {
auto electricityLctrXf = GetLctrTransform("Electricity_LCTR"sv);
auto actorLctrXf = entity->GetLctrTransform(x58c_actorLctr);
x57c_particleElectric->SetOverrideIPos(electricityLctrXf.origin);
x57c_particleElectric->SetOverrideFPos(actorLctrXf.origin);
}
}
bool CPhazonHealingNodule::AnimOver(CStateManager&, float arg) { return x588_state == 3; }
bool CPhazonHealingNodule::InRange(CStateManager&, float arg) { return x568_active == 0; }
bool CPhazonHealingNodule::InDetectionRange(CStateManager&, float arg) { return x568_active == 1; }
void CPhazonHealingNodule::MassiveDeath(CStateManager& mgr) { Death(mgr, zeus::skZero3f, EScriptObjectState::Dead); }
void CPhazonHealingNodule::MassiveFrozenDeath(CStateManager& mgr) {
Death(mgr, zeus::skZero3f, EScriptObjectState::Dead);
}
void CPhazonHealingNodule::PhazeOut(CStateManager& mgr) { Death(mgr, zeus::skZero3f, EScriptObjectState::Dead); }
} // namespace urde::MP1

View File

@ -0,0 +1,50 @@
#pragma once
#include "Runtime/World/CPatterned.hpp"
#include "Runtime/Particle/CParticleElectric.hpp"
namespace urde::MP1 {
class CPhazonHealingNodule : public CPatterned {
private:
int x568_active = 0;
bool x56c_emitting = false;
TUniqueId x56e_connId = kInvalidUniqueId;
TCachedToken<CElectricDescription> x570_electricDesc;
std::unique_ptr<CParticleElectric> x57c_particleElectric; // was rstl::rc_ptr
CHealthInfo x580_initialHealthInfo;
int x588_state = 0; // not init in ctr; same as CElitePirate::EState?
std::string x58c_actorLctr;
// u32 x59c_;
public:
DEFINE_PATTERNED(PhazonHealingNodule);
CPhazonHealingNodule(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CActorParameters& actParams, const CPatternedInfo& pInfo,
CAssetId particleDescId, std::string actorLctr);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override;
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override;
void Render(CStateManager& mgr) override;
void Think(float dt, CStateManager& mgr) override;
void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) override;
void Faint(CStateManager& mgr, EStateMsg msg, float dt) override;
void Growth(CStateManager& mgr, EStateMsg msg, float dt) override;
void KnockBack(const zeus::CVector3f& vec, CStateManager& mgr, const CDamageInfo& info, EKnockBackType type,
bool inDeferred, float magnitude) override;
void Lurk(CStateManager& mgr, EStateMsg msg, float dt) override;
void Patrol(CStateManager& mgr, EStateMsg msg, float dt) override;
bool InRange(CStateManager &, float arg) override;
bool InDetectionRange(CStateManager &, float arg) override;
bool AnimOver(CStateManager &, float arg) override;
void MassiveDeath(CStateManager &mgr) override;
void MassiveFrozenDeath(CStateManager &mgr) override;
void PhazeOut(CStateManager &) override;
private:
void UpdateParticleElectric(CStateManager& mgr);
};
} // namespace urde::MP1

View File

@ -0,0 +1,272 @@
#include "Runtime/MP1/World/CPhazonPool.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Graphics/CBooRenderer.hpp"
#include "TCastTo.hpp" // Generated file, do not modify include path
namespace urde::MP1 {
CPhazonPool::CPhazonPool(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
const zeus::CVector3f& scale, bool active, CAssetId w1, CAssetId w2, CAssetId w3, CAssetId w4,
u32 p11, const CDamageInfo& dInfo, const zeus::CVector3f& orientedForce,
ETriggerFlags triggerFlags, bool p15, float p16, float p17, float p18, float p19)
: CScriptTrigger(uid, name, info, xf.origin, zeus::skNullBox, dInfo, orientedForce, triggerFlags, active, false, false)
, x168_modelData1(std::make_unique<CModelData>(CStaticRes{w1, zeus::skOne3f}))
, x16c_modelData2(std::make_unique<CModelData>(CStaticRes{w2, zeus::skOne3f}))
, x190_scale(scale)
, x19c_(p16)
, x1a0_(p16)
, x1bc_(p17)
, x1c0_(p19)
, x1c8_(p18)
, x1d8_(p11)
, x1e0_24_(p15)
, x1e0_25_(false) {
if (w3.IsValid()) {
x170_elementGen1 = std::make_unique<CElementGen>(g_SimplePool->GetObj(SObjectTag{SBIG('PART'), w3}));
x170_elementGen1->SetParticleEmission(false);
}
if (w4.IsValid()) {
x174_elementGen2 = std::make_unique<CElementGen>(g_SimplePool->GetObj(SObjectTag{SBIG('PART'), w4}));
x174_elementGen2->SetGlobalScale(x190_scale);
x174_elementGen2->SetParticleEmission(false);
}
}
void CPhazonPool::Accept(IVisitor& visitor) { visitor.Visit(this); }
void CPhazonPool::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
switch (msg) {
case EScriptObjectMessage::Activate:
case EScriptObjectMessage::Open:
UpdateParticleGens(mgr);
break;
case EScriptObjectMessage::Close:
if (!x1e0_25_) {
x1e0_25_ = true;
x1c4_ = 0.f;
SetEmitParticles(false);
}
break;
case EScriptObjectMessage::Decrement:
if (x1dc_ == 2) {
x1cc_ += 1.f;
}
break;
case EScriptObjectMessage::Registered:
if (x170_elementGen1) {
x170_elementGen1->SetGlobalTranslation(GetTranslation());
}
if (x168_modelData1) {
x178_bounds = x168_modelData1->GetBounds();
} else {
x178_bounds = zeus::CAABox{0.5f * -x190_scale, 0.5f * x190_scale};
}
x130_bounds = zeus::CAABox{x178_bounds.min * x190_scale, x178_bounds.max * x190_scale};
break;
case EScriptObjectMessage::Deleted:
RemoveInhabitants(mgr);
break;
default:
break;
}
CScriptTrigger::AcceptScriptMsg(msg, uid, mgr);
}
void CPhazonPool::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {
if (GetActive()) {
if (x170_elementGen1) {
g_Renderer->AddParticleGen(*x170_elementGen1);
}
if (x174_elementGen2) {
g_Renderer->AddParticleGen(*x174_elementGen2);
}
}
CActor::AddToRenderer(frustum, mgr);
CActor::EnsureRendered(mgr);
}
std::optional<zeus::CAABox> CPhazonPool::GetTouchBounds() const { return CScriptTrigger::GetTouchBounds(); }
void CPhazonPool::Render(CStateManager& mgr) {
CActor::Render(mgr);
bool discard = x1a4_ < 0.25f;
const CModelFlags flags{5, 0, static_cast<u16>(discard ? 3 : 0), zeus::CColor{1.f, x1a4_}};
if (x168_modelData1) {
x168_modelData1->Render(mgr, GetTransform() * zeus::CTransform::RotateZ(x1ac_rotZ), nullptr, flags);
}
if (x16c_modelData2) {
const zeus::CTransform rot = zeus::CTransform::RotateZ(x1ac_rotZ) * zeus::CTransform::RotateX(x1ac_rotZ) *
zeus::CTransform::RotateY(x1a8_rotY);
x16c_modelData2->Render(mgr, GetTransform() * rot, nullptr, flags);
}
}
void CPhazonPool::Think(float dt, CStateManager& mgr) {
if (!GetActive()) {
return;
}
CScriptTrigger::Think(dt, mgr);
UpdateInhabitants(mgr);
const zeus::CVector3f scale = (x1dc_ == 1 ? x1a4_ : 1.f) * x190_scale;
SetTransform({zeus::CMatrix3f{scale}, GetTranslation()});
x130_bounds = zeus::CAABox{x178_bounds.min * scale, x178_bounds.max * scale};
x1a8_rotY += dt * x1b0_;
x1ac_rotZ += dt * x1b4_;
if (x1a8_rotY > zeus::degToRad(360.f)) {
x1a8_rotY = 0.f;
}
if (x1ac_rotZ > zeus::degToRad(360.f)) {
x1ac_rotZ = 0.f;
}
if (x170_elementGen1) {
x170_elementGen1->SetModulationColor(zeus::CColor{x1a4_, x1a4_, x1a4_, x1a4_});
x170_elementGen1->SetGlobalScale(zeus::CVector3f{scale.x()});
x170_elementGen1->Update(dt);
}
if (x174_elementGen2) {
x174_elementGen2->Update(dt);
}
bool shouldFree = false;
if (x1dc_ == 1) {
x1d4_ += dt;
if (x1d4_ > 2.f) {
x1d4_ = 2.f;
x1a4_ += dt * x1b8_;
if (x1a4_ > 1.f) {
x1a4_ = 1.f;
x1dc_ = 2;
SetEmitParticles(true);
if (x174_elementGen2) {
x174_elementGen2->SetParticleEmission(true);
}
}
}
} else if (x1dc_ == 2) {
float dVar5 = 0.f;
if (x1e0_24_ || x1e0_25_) {
x1c4_ -= dt;
if (x1c4_ <= 0.f) {
x1c4_ = 0.f;
dVar5 = dt;
}
x1a0_ -= x1bc_ * (dt * x1cc_) + dVar5;
x1a4_ = x1a0_ / x19c_;
if (x1a4_ < 0.001f) {
if (x1e0_24_) {
shouldFree = true;
} else {
SetCallTouch(false);
if (x1e0_25_) {
x1dc_ = 0;
SetActive(false);
} else {
x1dc_ = 3;
x1d0_ = x1c8_;
}
}
SetEmitParticles(false);
}
x1cc_ = 0.f;
}
} else if (x1dc_ == 3) {
x1d0_ -= dt;
if (x1d0_ <= 0.f) {
x1d0_ = 0.f;
UpdateParticleGens(mgr);
}
}
if (shouldFree) {
mgr.FreeScriptObject(GetUniqueId());
}
}
void CPhazonPool::Touch(CActor& actor, CStateManager& mgr) {
if (!GetActive() || x1dc_ != 2) {
return;
}
CScriptTrigger::Touch(actor, mgr);
if (actor.GetMaterialList().HasMaterial(EMaterialTypes::PlatformSlave)) {
return;
}
for (auto& entry : x150_inhabitants) {
if (entry.first == actor.GetUniqueId()) {
entry.second = true;
return;
}
}
if (actor.GetTouchBounds().has_value()) {
x150_inhabitants.emplace_back(actor.GetUniqueId(), true);
mgr.SendScriptMsg(&actor, GetUniqueId(), EScriptObjectMessage::AddPhazonPoolInhabitant);
}
}
void CPhazonPool::UpdateInhabitants(CStateManager& mgr) {
auto iter = x150_inhabitants.begin();
const auto end = x150_inhabitants.end();
while (iter != end) {
TCastToPtr<CActor> actor = mgr.ObjectById(iter->first);
if (actor) {
if (actor->GetTouchBounds().has_value()) {
(void)GetTriggerBoundsWR(); // unused?
}
}
if (!actor || !iter->second) {
iter = x150_inhabitants.erase(iter);
if (actor) {
mgr.SendScriptMsg(actor, GetUniqueId(), EScriptObjectMessage::RemovePhazonPoolInhabitant);
}
} else {
mgr.SendScriptMsg(actor, GetUniqueId(), EScriptObjectMessage::UpdatePhazonPoolInhabitant);
iter->second = false;
iter++;
}
}
}
void CPhazonPool::UpdateParticleGens(CStateManager& mgr) {
x1b0_ = mgr.GetActiveRandom()->Range(-0.5f, 0.5f);
x1b4_ = mgr.GetActiveRandom()->Range(-1.f, 1.f);
x1b8_ = mgr.GetActiveRandom()->Range(0.25f, 2.f);
x1cc_ = 0.f;
x1d4_ = 0.f;
x1c4_ = x1c0_;
x1a0_ = x19c_;
x1dc_ = 1;
x1e0_25_ = false;
if (x170_elementGen1) {
x170_elementGen1->SetGlobalTranslation(GetTranslation());
x170_elementGen1->SetParticleEmission(false);
}
if (x174_elementGen2) {
x174_elementGen2->SetGlobalTranslation(GetTranslation());
x174_elementGen2->SetParticleEmission(true);
}
}
void CPhazonPool::RemoveInhabitants(CStateManager& mgr) {
auto iter = x150_inhabitants.begin();
const auto end = x150_inhabitants.end();
while (iter != end) {
if (TCastToPtr<CActor> actor = mgr.ObjectById(iter->first)) {
iter = x150_inhabitants.erase(iter);
mgr.SendScriptMsg(actor, GetUniqueId(), EScriptObjectMessage::RemovePhazonPoolInhabitant);
} else {
iter++;
}
}
}
void CPhazonPool::SetEmitParticles(bool val) {
if (x170_elementGen1) {
x170_elementGen1->SetParticleEmission(val);
}
}
} // namespace urde::MP1

View File

@ -0,0 +1,57 @@
#pragma once
#include "Runtime/World/CScriptTrigger.hpp"
#include "Runtime/Particle/CElementGen.hpp"
namespace urde::MP1 {
class CPhazonPool : public CScriptTrigger {
private:
std::list<std::pair<TUniqueId, bool>> x150_inhabitants;
std::unique_ptr<CModelData> x168_modelData1;
std::unique_ptr<CModelData> x16c_modelData2;
std::unique_ptr<CElementGen> x170_elementGen1;
std::unique_ptr<CElementGen> x174_elementGen2;
zeus::CAABox x178_bounds = zeus::skNullBox;
zeus::CVector3f x190_scale;
float x19c_;
float x1a0_;
float x1a4_ = 0.001f;
float x1a8_rotY = 0.f;
float x1ac_rotZ = 0.f;
float x1b0_ = 0.f;
float x1b4_ = 0.f;
float x1b8_ = 0.f;
float x1bc_;
float x1c0_;
float x1c4_ = 0.f;
float x1c8_;
float x1cc_ = 0.f;
float x1d0_ = 0.f;
float x1d4_ = 0.f;
u32 x1d8_;
u32 x1dc_ = 0;
bool x1e0_24_ : 1;
bool x1e0_25_ : 1;
public:
CPhazonPool(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
const zeus::CVector3f& scale, bool active, CAssetId w1, CAssetId w2, CAssetId w3, CAssetId w4, u32 p11,
const CDamageInfo& dInfo, const zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool p15,
float p16, float p17, float p18, float p19);
void Accept(IVisitor& visitor) override;
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override;
void AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) override;
[[nodiscard]] std::optional<zeus::CAABox> GetTouchBounds() const override;
void Render(CStateManager& mgr) override;
void Think(float dt, CStateManager& mgr) override;
void Touch(CActor& actor, CStateManager& mgr) override;
private:
void UpdateInhabitants(CStateManager& mgr);
void UpdateParticleGens(CStateManager& mgr);
void RemoveInhabitants(CStateManager& mgr);
void SetEmitParticles(bool val);
};
} // namespace urde::MP1

View File

@ -12,14 +12,14 @@ private:
CDamageInfo x8_damageInfo;
float x24_ = 0.f;
float x28_ = 0.5f;
float x2c_ = 16.5217f;
float x2c_;
float x30_ = 0.f;
CAssetId x34_weaponDesc;
u16 x38_electrocuteSfx;
public:
SShockWaveData(CAssetId part, const CDamageInfo& dInfo, CAssetId weapon, u16 sfx)
: x4_particleDesc(part), x8_damageInfo(dInfo), x34_weaponDesc(weapon), x38_electrocuteSfx(sfx) {}
SShockWaveData(CAssetId part, const CDamageInfo& dInfo, float x2c, CAssetId weapon, u16 sfx)
: x4_particleDesc(part), x8_damageInfo(dInfo), x2c_(x2c), x34_weaponDesc(weapon), x38_electrocuteSfx(sfx) {}
[[nodiscard]] CAssetId GetParticleDescId() const { return x4_particleDesc; }
[[nodiscard]] const CDamageInfo& GetDamageInfo() const { return x8_damageInfo; }

View File

@ -995,7 +995,7 @@ void CThardus::RenderFlare(const CStateManager& mgr, float t) {
{{min.x() - offset.x(), min.y() - offset.y(), min.z() - offset.z()}, {1.f, 0.f}},
}};
m_flareFilter->drawVerts({t, t}, verts.data());
m_flareFilter->drawVerts({t, t}, verts);
}
#if 0
@ -1023,4 +1023,4 @@ zeus::CVector3f CThardus::sub801de550(const CStateManager& mgr) const {
return {};
}
} // namespace urde::MP1
} // namespace urde::MP1

View File

@ -935,7 +935,7 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
rot = orient * rot;
CParticleGlobals::instance()->SetEmitterTime(x74_curFrame);
zeus::CColor col = {1.f, 1.f, 1.f, 1.f};
zeus::CColor col = x338_moduColor;
zeus::CVector3f pmopVec;
auto matrixIt = x50_parentMatrices.begin();
@ -992,8 +992,10 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
}
CColorElement* pmcl = desc->x78_x64_PMCL.get();
if (pmcl)
if (pmcl) {
pmcl->GetValue(partFrame, col);
col *= x338_moduColor;
}
CGraphics::SetModelMatrix((x10c_globalScaleTransform * partTrans) * x178_localScaleTransform);
@ -1040,11 +1042,10 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
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::skWhite});
} else {
if (1.f == col.a())
model->Draw({0, 0, 3, zeus::skWhite});
else
model->Draw({5, 0, 1, col});
model->Draw({5, 0, 1, zeus::CColor(1.f, col.a())});
}
}

View File

@ -10,7 +10,9 @@
#include "Runtime/CToken.hpp"
#include "Runtime/rstl.hpp"
#include "Runtime/Graphics/CLineRenderer.hpp"
#include "Runtime/Particle/CElementGen.hpp"
#include "Runtime/Particle/CParticleGen.hpp"
#include "Runtime/Particle/CParticleSwoosh.hpp"
#include <zeus/CAABox.hpp>
#include <zeus/CColor.hpp>
@ -19,8 +21,6 @@
namespace urde {
class CElectricDescription;
class CElementGen;
class CParticleSwoosh;
class CParticleElectric : public CParticleGen {
static u16 g_GlobalSeed;

View File

@ -356,6 +356,7 @@ public:
void DropBomb(EBWeapon weapon, CStateManager& mgr);
TUniqueId DropPowerBomb(CStateManager& mgr);
void SetActorAttached(bool b) { x835_31_actorAttached = b; }
CAuxWeapon& GetAuxWeapon() const { return *x744_auxWeapon; }
};
} // namespace urde

View File

@ -184,6 +184,7 @@ public:
float GetAverageAnimVelocity(int anim) const;
u8 GetTargetableVisorFlags() const { return xe6_31_targetableVisorFlags; }
bool GetIsTargetable() const { return xe7_31_targetable; }
const CModelFlags& GetDrawFlags() const { return xb4_drawFlags; }
void SetDrawFlags(const CModelFlags& flags) { xb4_drawFlags = flags; }
void SetModelData(std::unique_ptr<CModelData>&& mData);
u8 GetFluidCounter() const { return xe6_24_fluidCounter; }

View File

@ -361,6 +361,7 @@ public:
const CBodyController* GetBodyController() const { return x450_bodyController.get(); }
CBodyController* GetBodyController() { return x450_bodyController.get(); }
const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; }
CKnockBackController& GetKnockBackController() { return x460_knockBackController; }
void SetupPlayerCollision(bool);
CGameProjectile* LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed,
EProjectileAttrib attrib, bool playerHoming,

View File

@ -75,6 +75,7 @@ CScriptEffect::CScriptEffect(TUniqueId uid, std::string_view name, const CEntity
xf4_electric->SetGlobalTranslation(xf.origin);
xf4_electric->SetGlobalScale(scale);
xf4_electric->SetParticleEmission(active);
xf4_electric->SetModulationColor(lParms.GetNoLightsAmbient());
}
xe7_29_drawEnabled = true;
}
@ -96,7 +97,6 @@ void CScriptEffect::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt
x104_particleSystem->SetOrientation(newXf);
x104_particleSystem->SetGlobalTranslation(GetTranslation());
x104_particleSystem->SetGlobalScale(scale);
x104_particleSystem->SetParticleEmission(oldActive);
x104_particleSystem->SetModulationColor(color);
x104_particleSystem->SetModelsUseLights(x138_actorLights != nullptr);
}
@ -110,7 +110,6 @@ void CScriptEffect::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt
xf4_electric->SetOrientation(newXf);
xf4_electric->SetGlobalTranslation(GetTranslation());
xf4_electric->SetGlobalScale(scale);
xf4_electric->SetParticleEmission(oldActive);
xf4_electric->SetModulationColor(color);
}
}
@ -151,28 +150,30 @@ void CScriptEffect::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt
mgr.SendScriptMsg(light, uid, msg);
if (oldActive != GetActive()) {
std::vector<TUniqueId> playIds;
for (const SConnection& conn : x20_conns) {
if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) {
continue;
if (GetActive()) {
std::vector<TUniqueId> playIds;
for (const SConnection& conn : x20_conns) {
if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) {
continue;
}
const TUniqueId scriptId = mgr.GetIdForScript(conn.x8_objId);
if (scriptId != kInvalidUniqueId) {
playIds.push_back(scriptId);
}
}
const TUniqueId scriptId = mgr.GetIdForScript(conn.x8_objId);
if (scriptId != kInvalidUniqueId) {
playIds.push_back(scriptId);
}
}
if (playIds.size() > 0) {
TCastToConstPtr<CActor> otherAct =
mgr.GetObjectById(playIds[u32(0.99f * playIds.size() * mgr.GetActiveRandom()->Float())]);
if (otherAct) {
if (light)
light->SetTransform(otherAct->GetTransform());
else
if (!playIds.empty()) {
TCastToConstPtr<CActor> otherAct =
mgr.GetObjectById(playIds[u32(0.99f * playIds.size() * mgr.GetActiveRandom()->Float())]);
if (otherAct) {
SetTransform(otherAct->GetTransform());
if (light)
light->SetTransform(otherAct->GetTransform());
}
}
}
x110_24_enable = true;
if (x104_particleSystem)
x104_particleSystem->SetParticleEmission(GetActive());

View File

@ -20,19 +20,19 @@ namespace urde {
constexpr auto skPlatformMaterialList =
CMaterialList{EMaterialTypes::Solid, EMaterialTypes::Immovable, EMaterialTypes::Platform, EMaterialTypes::Occluder};
CScriptPlatform::CScriptPlatform(
TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData,
const CActorParameters& actParms, const zeus::CAABox& aabb, float speed, bool detectCollision, float xrayAlpha,
bool active, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln,
const std::optional<TLockedToken<CCollidableOBBTreeGroupContainer>>& dcln, bool rainSplashes,
u32 maxRainSplashes, u32 rainGenRate)
CScriptPlatform::CScriptPlatform(TUniqueId uid, std::string_view name, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms,
const zeus::CAABox& aabb, float speed, bool detectCollision, float xrayAlpha,
bool active, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln,
std::optional<TLockedToken<CCollidableOBBTreeGroupContainer>> dcln,
bool rainSplashes, u32 maxRainSplashes, u32 rainGenRate)
: CPhysicsActor(uid, active, name, info, xf, std::move(mData), skPlatformMaterialList, aabb, SMoverData(15000.f),
actParms, 0.3f, 0.1f)
, x25c_currentSpeed(speed)
, x28c_initialHealth(hInfo)
, x294_health(hInfo)
, x29c_damageVuln(dVuln)
, x304_treeGroupContainer(dcln) {
, x304_treeGroupContainer(std::move(dcln)) {
x348_xrayAlpha = xrayAlpha;
x34c_maxRainSplashes = maxRainSplashes;
x350_rainGenRate = rainGenRate;
@ -402,7 +402,7 @@ void CScriptPlatform::BuildSlaveList(CStateManager& mgr) {
void CScriptPlatform::AddRider(std::vector<SRiders>& riders, TUniqueId riderId, const CPhysicsActor* ridee,
CStateManager& mgr) {
const auto search =
const auto& search =
std::find_if(riders.begin(), riders.end(), [riderId](const SRiders& r) { return r.x0_uid == riderId; });
if (search == riders.end()) {
zeus::CTransform xf;
@ -417,7 +417,7 @@ void CScriptPlatform::AddRider(std::vector<SRiders>& riders, TUniqueId riderId,
}
void CScriptPlatform::AddSlave(TUniqueId id, CStateManager& mgr) {
const auto search = std::find_if(x338_slavesDynamic.begin(), x338_slavesDynamic.end(),
const auto& search = std::find_if(x338_slavesDynamic.begin(), x338_slavesDynamic.end(),
[id](const SRiders& r) { return r.x0_uid == id; });
if (search != x338_slavesDynamic.end()) {
return;

View File

@ -30,7 +30,7 @@ struct SRiders {
};
class CScriptPlatform : public CPhysicsActor {
u32 x254_;
// u32 x254_;
TUniqueId x258_currentWaypoint = kInvalidUniqueId;
TUniqueId x25a_targetWaypoint = kInvalidUniqueId;
float x25c_currentSpeed;
@ -82,8 +82,8 @@ public:
CModelData&& mData, const CActorParameters& actParms, const zeus::CAABox& aabb, float speed,
bool detectCollision, float xrayAlpha, bool active, const CHealthInfo& hInfo,
const CDamageVulnerability& dVuln,
const std::optional<TLockedToken<CCollidableOBBTreeGroupContainer>>& dcln,
bool rainSplashes, u32 maxRainSplashes, u32 rainGenRate);
std::optional<TLockedToken<CCollidableOBBTreeGroupContainer>> dcln, bool rainSplashes,
u32 maxRainSplashes, u32 rainGenRate);
void Accept(IVisitor& visitor) override;
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&) override;
@ -111,8 +111,11 @@ public:
TUniqueId GetWaypoint(CStateManager&);
const CDamageVulnerability* GetDamageVulnerability() const override { return &x29c_damageVuln; }
void SetDamageVulnerability(const CDamageVulnerability& vuln) { x29c_damageVuln = vuln; }
CHealthInfo* HealthInfo(CStateManager&) override { return &x294_health; }
void SetControlledAnimation(bool controlled) { x356_25_controlledAnimation = controlled; }
void SetDisableXRayAlpha(bool val) { x356_30_disableXrayAlpha = val; }
void SetXRayFog(bool val) { x356_31_xrayFog = val; }
virtual void SplashThink(const zeus::CAABox&, const CFluidPlane&, float, CStateManager&) const;
virtual zeus::CQuaternion Move(float, CStateManager&);

View File

@ -33,6 +33,8 @@
#include "Runtime/MP1/World/CNewIntroBoss.hpp"
#include "Runtime/MP1/World/COmegaPirate.hpp"
#include "Runtime/MP1/World/CParasite.hpp"
#include "Runtime/MP1/World/CPhazonHealingNodule.hpp"
#include "Runtime/MP1/World/CPhazonPool.hpp"
#include "Runtime/MP1/World/CPuddleSpore.hpp"
#include "Runtime/MP1/World/CPuddleToadGamma.hpp"
#include "Runtime/MP1/World/CPuffer.hpp"
@ -3645,7 +3647,6 @@ CEntity* ScriptLoader::LoadOmegaPirate(CStateManager& mgr, CInputStream& in, int
return nullptr;
}
#if 0
SScaledActorHead actHead = LoadScaledActorHead(in, mgr);
auto pair = CPatternedInfo::HasCorrectParameterCount(in);
if (!pair.first) {
@ -3665,18 +3666,62 @@ CEntity* ScriptLoader::LoadOmegaPirate(CStateManager& mgr, CInputStream& in, int
return new MP1::COmegaPirate(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData),
pInfo, actParms, elitePirateData, CAssetId(in), CAssetId(in), CAssetId(in));
#else
return nullptr;
#endif
}
CEntity* ScriptLoader::LoadPhazonPool(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) {
return nullptr;
if (!EnsurePropertyCount(propCount, 18, "PhazonPool")) {
return nullptr;
}
SScaledActorHead actHead = LoadScaledActorHead(in, mgr);
bool active = in.readBool();
CAssetId w1{in};
CAssetId w2{in};
CAssetId w3{in};
CAssetId w4{in};
u32 u1 = in.readUint32Big();
CDamageInfo dInfo{in};
zeus::CVector3f orientedForce{in.readVec3f()};
ETriggerFlags triggerFlags = static_cast<ETriggerFlags>(in.readUint32Big());
float f1 = in.readFloatBig();
float f2 = in.readFloatBig();
float f3 = in.readFloatBig();
bool b2 = in.readBool();
float f4 = in.readFloatBig();
return new MP1::CPhazonPool(mgr.AllocateUniqueId(), actHead.x0_name, info,
zeus::CTransform::Translate(actHead.x10_transform.origin), actHead.x40_scale, active, w1,
w2, w3, w4, u1, dInfo, orientedForce, triggerFlags, b2, f1, f2, f3, f4);
}
CEntity* ScriptLoader::LoadPhazonHealingNodule(CStateManager& mgr, CInputStream& in, int propCount,
const CEntityInfo& info) {
return nullptr;
if (!EnsurePropertyCount(propCount, 9, "PhazonHealingNodule")) {
return nullptr;
}
SScaledActorHead actHead = LoadScaledActorHead(in, mgr);
auto pair = CPatternedInfo::HasCorrectParameterCount(in);
if (!pair.first) {
return nullptr;
}
CPatternedInfo pInfo(in, pair.second);
CActorParameters actParms = LoadActorParameters(in);
in.readBool();
CAssetId w1{in};
std::string w2 = in.readString();
if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) {
return nullptr;
}
CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(),
actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true));
return new MP1::CPhazonHealingNodule(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform,
std::move(mData), actParms, pInfo, w1, std::move(w2));
}
CEntity* ScriptLoader::LoadNewCameraShaker(CStateManager& mgr, CInputStream& in, int propCount,