From 9b65bc74307810f6c5b2bd762496a19269b91222 Mon Sep 17 00:00:00 2001 From: GRAnimated Date: Mon, 23 Feb 2026 16:54:54 -0500 Subject: [PATCH] Boss: Implement BossRaidElectricLine Co-Authored-By: Claude Sonnet 4.6 --- data/file_list.yml | 23 +++--- src/Boss/BossRaid/BossRaidElectric.h | 46 ++++++++++++ src/Boss/BossRaid/BossRaidElectricLine.cpp | 81 ++++++++++++++++++++++ src/Boss/BossRaid/BossRaidElectricLine.h | 29 ++++++++ 4 files changed, 168 insertions(+), 11 deletions(-) create mode 100644 src/Boss/BossRaid/BossRaidElectric.h create mode 100644 src/Boss/BossRaid/BossRaidElectricLine.cpp create mode 100644 src/Boss/BossRaid/BossRaidElectricLine.h diff --git a/data/file_list.yml b/data/file_list.yml index 211267e3..9f0776a5 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -8136,45 +8136,46 @@ Boss/BossRaid/BossRaidElectricLine.o: - offset: 0x0409a8 size: 176 label: _ZN20BossRaidElectricLineC2EPKc - status: NotDecompiled + status: Matching - offset: 0x040a58 size: 188 label: _ZN20BossRaidElectricLineC1EPKc - status: NotDecompiled + status: Matching - offset: 0x040b14 size: 8 label: _ZN20BossRaidElectricLine13setBulletListEPN2al16DeriveActorGroupI16BossRaidElectricEE - status: NotDecompiled + status: Matching - offset: 0x040b1c size: 132 label: _ZN20BossRaidElectricLine4initERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x040ba0 size: 144 label: _ZN20BossRaidElectricLine4shotERKN4sead7Vector3IfEES4_ - status: NotDecompiled + status: Matching - offset: 0x040c30 size: 320 label: _ZN20BossRaidElectricLine7exeMoveEv - status: NotDecompiled + status: Matching - offset: 0x040d70 size: 52 label: _ZN20BossRaidElectricLine9killForceEv - status: NotDecompiled + status: Matching - offset: 0x040da4 size: 8 label: _ZNK12_GLOBAL__N_127BossRaidElectricLineNrvMove7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x040dac size: 12 label: _ZNK12_GLOBAL__N_127BossRaidElectricLineNrvMove13getActionNameEv - status: NotDecompiled + status: Matching guess: true - offset: 0x040db8 size: 64 - label: '' - status: NotDecompiled + label: _GLOBAL__sub_I_BossRaidElectricLine.cpp + status: Matching + guess: true Boss/BossRaid/BossRaidLightning.o: '.text': - offset: 0x040df8 diff --git a/src/Boss/BossRaid/BossRaidElectric.h b/src/Boss/BossRaid/BossRaidElectric.h new file mode 100644 index 00000000..686865a1 --- /dev/null +++ b/src/Boss/BossRaid/BossRaidElectric.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +#include "Library/LiveActor/LiveActor.h" + +namespace al { +template +class DeriveActorGroup; +} + +class BossRaidElectric : public al::LiveActor { +public: + BossRaidElectric(const char* name); + void init(const al::ActorInitInfo& info) override; + void makeActorDead() override; + void attackSensor(al::HitSensor* self, al::HitSensor* other) override; + + void setPrevBullet(BossRaidElectric* bullet); + void setNextBullet(BossRaidElectric* bullet); + + void shot(const sead::Vector3f& pos, const sead::Vector3f& dir, BossRaidElectric* prevBullet, + al::DeriveActorGroup* actorGroup); + void updatePosition(); + void exeWait(); + void updateAnimAndJoint(); + bool isAirAll() const; + void exeDisappear(); + void exeHide(); + bool isHideAll() const; + bool isHide() const; + void updateEffectScale(f32 scale); + void calcNearPos(sead::Vector3f* outPos, const sead::Vector3f& targetPos) const; + +private: + al::DeriveActorGroup* mActorGroup = nullptr; + BossRaidElectric* mNextBullet = nullptr; + BossRaidElectric* mPrevBullet = nullptr; + sead::Vector3f mFrontDir = sead::Vector3f::ez; + sead::Vector3f _12c = sead::Vector3f::zero; + sead::Vector3f mMoveDir = sead::Vector3f::zero; + f32 _144 = 0.0f; + bool _148 = true; +}; + +static_assert(sizeof(BossRaidElectric) == 0x150); diff --git a/src/Boss/BossRaid/BossRaidElectricLine.cpp b/src/Boss/BossRaid/BossRaidElectricLine.cpp new file mode 100644 index 00000000..e6d5ff48 --- /dev/null +++ b/src/Boss/BossRaid/BossRaidElectricLine.cpp @@ -0,0 +1,81 @@ +#include "Boss/BossRaid/BossRaidElectricLine.h" + +#include "Library/LiveActor/ActorActionFunction.h" +#include "Library/LiveActor/ActorFlagFunction.h" +#include "Library/LiveActor/ActorInitUtil.h" +#include "Library/LiveActor/ActorPoseUtil.h" +#include "Library/LiveActor/LiveActorGroup.h" +#include "Library/Nerve/NerveSetupUtil.h" +#include "Library/Nerve/NerveUtil.h" +#include "Library/Player/PlayerUtil.h" + +#include "Boss/BossRaid/BossRaidElectric.h" + +namespace { +NERVE_ACTION_IMPL(BossRaidElectricLine, Move); +NERVE_ACTIONS_MAKE_STRUCT(BossRaidElectricLine, Move); +} // namespace + +BossRaidElectricLine::BossRaidElectricLine(const char* name) : al::LiveActor(name) { + mActors = new al::DeriveActorGroup("電撃アクティブリスト", 64); +} + +void BossRaidElectricLine::init(const al::ActorInitInfo& info) { + al::initNerveAction(this, "Move", &NrvBossRaidElectricLine.collector, 0); + al::initActorWithArchiveName(this, info, "BossRaidElectricLine", nullptr); + makeActorDead(); +} + +void BossRaidElectricLine::setBulletList(al::DeriveActorGroup* bulletList) { + mBulletList = bulletList; +} + +void BossRaidElectricLine::shot(const sead::Vector3f& pos, const sead::Vector3f& dir) { + if (mBulletList == nullptr) + return; + + BossRaidElectric* bullet = mBulletList->tryFindDeadDeriveActor(); + if (bullet == nullptr) + return; + + bullet->shot(pos, dir, mPrevBullet, mActors); + mPrevBullet = bullet; + if (al::isDead(this)) { + al::startNerveAction(this, "Move"); + makeActorAlive(); + } +} + +void BossRaidElectricLine::exeMove() { + s32 actorCount = mActors->getActorCount(); + if (actorCount == 0) { + mPrevBullet = nullptr; + makeActorDead(); + return; + } + + sead::Vector3f nearPos = al::getTrans(this); + f32 minDist = sead::Mathf::maxNumber(); + + for (s32 i = 0; i < actorCount; i++) { + BossRaidElectric* electric = mActors->getDeriveActor(i); + + sead::Vector3f calcPos; + electric->calcNearPos(&calcPos, al::getPlayerPos(this, 0)); + const sead::Vector3f& playerPos = al::getPlayerPos(this, 0); + + f32 dist = sqrtf((playerPos - calcPos).squaredLength()); + if (dist < minDist) { + nearPos.set(calcPos); + minDist = dist; + } + } + + al::setTrans(this, nearPos); +} + +void BossRaidElectricLine::killForce() { + mActors->removeActorAll(); + mPrevBullet = nullptr; + makeActorDead(); +} diff --git a/src/Boss/BossRaid/BossRaidElectricLine.h b/src/Boss/BossRaid/BossRaidElectricLine.h new file mode 100644 index 00000000..efeacda2 --- /dev/null +++ b/src/Boss/BossRaid/BossRaidElectricLine.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Library/LiveActor/LiveActor.h" + +namespace al { +template +class DeriveActorGroup; +} + +class BossRaidElectric; + +class BossRaidElectricLine : public al::LiveActor { +public: + BossRaidElectricLine(const char* name); + void init(const al::ActorInitInfo& info) override; + void setBulletList(al::DeriveActorGroup* bulletList); + void shot(const sead::Vector3f& pos, const sead::Vector3f& dir); + void exeMove(); + void killForce(); + + void resetPrevBullet() { mPrevBullet = nullptr; } + +private: + BossRaidElectric* mPrevBullet = nullptr; + al::DeriveActorGroup* mActors = nullptr; + al::DeriveActorGroup* mBulletList = nullptr; +}; + +static_assert(sizeof(BossRaidElectricLine) == 0x120);