diff --git a/data/file_list.yml b/data/file_list.yml index 0e7a7041..d908b13e 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -8047,89 +8047,89 @@ Boss/BossRaid/BossRaidElectric.o: - offset: 0x03fef4 size: 208 label: _ZN16BossRaidElectricC2EPKc - status: NotDecompiled + status: Matching - offset: 0x03ffc4 size: 220 label: _ZN16BossRaidElectricC1EPKc - status: NotDecompiled + status: Matching - offset: 0x0400a0 size: 84 label: _ZN16BossRaidElectric13makeActorDeadEv - status: NotDecompiled + status: Matching - offset: 0x0400f4 size: 8 label: _ZN16BossRaidElectric13setPrevBulletEPS_ - status: NotDecompiled + status: Matching - offset: 0x0400fc size: 8 label: _ZN16BossRaidElectric13setNextBulletEPS_ - status: NotDecompiled + status: Matching - offset: 0x040104 size: 204 label: _ZN16BossRaidElectric4initERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x0401d0 size: 112 label: _ZN16BossRaidElectric12attackSensorEPN2al9HitSensorES2_ - status: NotDecompiled + status: Matching - offset: 0x040240 size: 192 label: _ZN16BossRaidElectric4shotERKN4sead7Vector3IfEES4_PS_PN2al16DeriveActorGroupIS_EE - status: NotDecompiled + status: Matching - offset: 0x040300 size: 76 label: _ZN16BossRaidElectric14updatePositionEv - status: NotDecompiled + status: Matching - offset: 0x04034c size: 180 label: _ZN16BossRaidElectric7exeWaitEv - status: NotDecompiled + status: Matching - offset: 0x040400 size: 588 label: _ZN16BossRaidElectric18updateAnimAndJointEv - status: NotDecompiled + status: Matching - offset: 0x04064c size: 48 label: _ZNK16BossRaidElectric8isAirAllEv - status: NotDecompiled + status: Matching - offset: 0x04067c size: 108 label: _ZN16BossRaidElectric12exeDisappearEv - status: NotDecompiled + status: Matching - offset: 0x0406e8 size: 116 label: _ZN16BossRaidElectric7exeHideEv - status: NotDecompiled + status: Matching - offset: 0x04075c size: 104 label: _ZNK16BossRaidElectric9isHideAllEv - status: NotDecompiled + status: Matching - offset: 0x0407c4 size: 12 label: _ZNK16BossRaidElectric6isHideEv - status: NotDecompiled + status: Matching - offset: 0x0407d0 size: 104 label: _ZN16BossRaidElectric17updateEffectScaleEf - status: NotDecompiled + status: Matching - offset: 0x040838 size: 128 label: _ZNK16BossRaidElectric11calcNearPosEPN4sead7Vector3IfEERKS2_ - status: NotDecompiled + status: Matching - offset: 0x0408b8 size: 8 label: _ZNK12_GLOBAL__N_123BossRaidElectricNrvWait7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x0408c0 size: 112 label: _ZNK12_GLOBAL__N_128BossRaidElectricNrvDisappear7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x040930 size: 120 label: _ZNK12_GLOBAL__N_123BossRaidElectricNrvHide7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true Boss/BossRaid/BossRaidElectricLine.o: '.text': diff --git a/src/Boss/BossRaid/BossRaidElectric.cpp b/src/Boss/BossRaid/BossRaidElectric.cpp new file mode 100644 index 00000000..c0ec8ca5 --- /dev/null +++ b/src/Boss/BossRaid/BossRaidElectric.cpp @@ -0,0 +1,193 @@ +#include "Boss/BossRaid/BossRaidElectric.h" + +#include +#include + +#include "Library/Area/AreaObjUtil.h" +#include "Library/Effect/EffectSystemInfo.h" +#include "Library/Joint/JointControllerKeeper.h" +#include "Library/LiveActor/ActorActionFunction.h" +#include "Library/LiveActor/ActorAreaFunction.h" +#include "Library/LiveActor/ActorClippingFunction.h" +#include "Library/LiveActor/ActorFlagFunction.h" +#include "Library/LiveActor/ActorInitUtil.h" +#include "Library/LiveActor/ActorModelFunction.h" +#include "Library/LiveActor/ActorMovementFunction.h" +#include "Library/LiveActor/ActorPoseUtil.h" +#include "Library/LiveActor/ActorSensorUtil.h" +#include "Library/LiveActor/LiveActorGroup.h" +#include "Library/Math/MathUtil.h" +#include "Library/Nerve/NerveSetupUtil.h" +#include "Library/Nerve/NerveUtil.h" + +namespace { +NERVE_IMPL(BossRaidElectric, Wait); +NERVE_IMPL(BossRaidElectric, Disappear); +NERVE_IMPL(BossRaidElectric, Hide); +NERVES_MAKE_NOSTRUCT(BossRaidElectric, Wait, Disappear, Hide); +} // namespace + +BossRaidElectric::BossRaidElectric(const char* name) : al::LiveActor(name) {} + +void BossRaidElectric::makeActorDead() { + al::LiveActor::makeActorDead(); + if (mNextBullet != nullptr) { + mNextBullet->mPrevBullet = nullptr; + mNextBullet = nullptr; + } + if (mPrevBullet != nullptr) { + mPrevBullet->mNextBullet = nullptr; + mPrevBullet = nullptr; + } + if (mActorGroup != nullptr) { + mActorGroup->removeActor(this); + mActorGroup = nullptr; + } +} + +void BossRaidElectric::setPrevBullet(BossRaidElectric* bullet) { + mPrevBullet = bullet; +} + +void BossRaidElectric::setNextBullet(BossRaidElectric* bullet) { + mNextBullet = bullet; +} + +void BossRaidElectric::init(const al::ActorInitInfo& info) { + al::initActorWithArchiveName(this, info, "BossRaidElectric", nullptr); + al::initNerve(this, &Wait, 0); + al::invalidateClipping(this); + al::offCollide(this); + al::initJointControllerKeeper(this, 1); + al::initJointLocalTransControllerX(this, &_144, "Electric2"); + al::setHitSensorPosPtr(this, "Attack", &_12c); + al::setSensorRadius(this, "Attack", 50.0f); + makeActorDead(); +} + +void BossRaidElectric::attackSensor(al::HitSensor* self, al::HitSensor* other) { + if (al::isNerve(this, &Wait) && al::isHitCylinderSensor(other, _12c, mFrontDir, 50.0f)) + al::sendMsgEnemyAttack(other, self); +} + +void BossRaidElectric::shot(const sead::Vector3f& pos, const sead::Vector3f& vel, + BossRaidElectric* nextBullet, + al::DeriveActorGroup* actorGroup) { + al::setModelAlphaMask(this, 1.0f); + al::showModelIfHide(this); + al::resetPosition(this, pos); + mVelocity.set(vel); + mNextBullet = nextBullet; + if (nextBullet != nullptr) { + al::showModelIfHide(this); + nextBullet->mPrevBullet = this; + } else { + al::hideModelIfShow(this); + } + mActorGroup = actorGroup; + actorGroup->registerActor(this); + _148 = true; + al::setNerve(this, &Wait); + makeActorAlive(); +} + +void BossRaidElectric::updatePosition() { + *al::getTransPtr(this) += mVelocity; +} + +void BossRaidElectric::exeWait() { + if (al::isFirstStep(this)) + al::startAction(this, mNextBullet ? "Wait" : "Hide"); + + updateAnimAndJoint(); + if (_148) { + if (!al::isInAreaObj(this, "BossRaidElectricArea", al::getTrans(this))) + _148 = false; + } + if (isAirAll()) + al::setNerve(this, &Disappear); +} + +void BossRaidElectric::updateAnimAndJoint() { + _144 = -500.0f; + if (!mNextBullet) { + _12c = al::getTrans(this); + al::setSensorRadius(this, "Attack", 50.0f); + + updateEffectScale(100.0f); + + mFrontDir.set(sead::Vector3f::ez); + return; + } + + sead::Vector3f diff = al::getTrans(this) - al::getTrans(mNextBullet); + f32 length = diff.length(); + if (!al::tryNormalizeOrZero(&mFrontDir, diff)) + mFrontDir.set(sead::Vector3f::ez); + + _144 = length - 500.0f; + + if (sead::Mathf::abs(mFrontDir.y) > 0.98f) + al::makeQuatFrontUp(al::getQuatPtr(this), mFrontDir, sead::Vector3f::ex); + else + al::makeQuatFrontUp(al::getQuatPtr(this), mFrontDir, sead::Vector3f::ey); + + al::lerpVec(&_12c, al::getTrans(this), al::getTrans(mNextBullet), 0.5f); + al::setSensorRadius(this, "Attack", length * 0.5f + 50.0f); + updateEffectScale(length); +} + +bool BossRaidElectric::isAirAll() const { + if (_148) + return false; + if (mNextBullet && mNextBullet->_148) + return false; + return true; +} + +void BossRaidElectric::exeDisappear() { + updateAnimAndJoint(); + f32 alpha = al::calcNerveEaseInOutValue(this, 39, 1.0f, 0.0f); + al::setModelAlphaMask(this, alpha); + + if (al::isGreaterEqualStep(this, 40)) { + al::hideModelIfShow(this); + al::setNerve(this, &Hide); + } +} + +void BossRaidElectric::exeHide() { + if (isHideAll()) + makeActorDead(); +} + +bool BossRaidElectric::isHideAll() const { + if (!isHide()) + return false; + + if (mNextBullet && !mNextBullet->isHide()) + return false; + + if (mPrevBullet && !mPrevBullet->isHide()) + return false; + return true; +} + +bool BossRaidElectric::isHide() const { + return al::isNerve(this, &Hide); +} + +void BossRaidElectric::updateEffectScale(f32 scale) { + sead::Vector3f v(1.0f, scale / 100.0f, 1.0f); + al::setEffectEmitterVolumeScale(this, "Spark", v); + al::setEffectParticleScale(this, "Body", v); +} + +void BossRaidElectric::calcNearPos(sead::Vector3f* outPos, const sead::Vector3f& targetPos) const { + if (mNextBullet) { + al::calcClosestSegmentPoint(outPos, al::getTrans(this), al::getTrans(mNextBullet), + targetPos); + } else { + outPos->set(al::getTrans(this)); + } +} diff --git a/src/Boss/BossRaid/BossRaidElectric.h b/src/Boss/BossRaid/BossRaidElectric.h new file mode 100644 index 00000000..28589252 --- /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& vel, BossRaidElectric* nextBullet, + 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 mVelocity = sead::Vector3f::zero; + f32 _144 = 0.0f; + bool _148 = true; +}; + +static_assert(sizeof(BossRaidElectric) == 0x150);