diff --git a/data/file_list.yml b/data/file_list.yml index 0e7a7041..5ac64c63 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -21386,104 +21386,104 @@ Boss/SmallWanderBoss/SmallWanderBossBullet.o: - offset: 0x0bab08 size: 156 label: _ZN21SmallWanderBossBulletC2EPKc - status: NotDecompiled + status: Matching - offset: 0x0baba4 size: 168 label: _ZN21SmallWanderBossBulletC1EPKc - status: NotDecompiled + status: Matching - offset: 0x0bac4c size: 276 label: _ZN21SmallWanderBossBullet4initERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x0bad60 size: 44 label: _ZN21SmallWanderBossBullet6appearEv - status: NotDecompiled + status: Matching - offset: 0x0bad8c size: 36 label: _ZN21SmallWanderBossBullet4killEv - status: NotDecompiled + status: Matching - offset: 0x0badb0 size: 240 label: _ZN21SmallWanderBossBullet7controlEv - status: NotDecompiled + status: Matching - offset: 0x0baea0 size: 152 label: _ZN21SmallWanderBossBullet12attackSensorEPN2al9HitSensorES2_ - status: NotDecompiled + status: Matching - offset: 0x0baf38 size: 216 label: _ZN21SmallWanderBossBullet10receiveMsgEPKN2al9SensorMsgEPNS0_9HitSensorES5_ - status: NotDecompiled + status: Matching - offset: 0x0bb010 size: 248 label: _ZN21SmallWanderBossBullet12appearAttachEPKN4sead8Matrix34IfEEPKNS0_7Vector3IfEE - status: NotDecompiled + status: Matching - offset: 0x0bb108 size: 248 label: _ZN21SmallWanderBossBullet21appearAttachParabolicEPKN4sead8Matrix34IfEEPKNS0_7Vector3IfEE - status: NotDecompiled + status: Matching - offset: 0x0bb200 size: 100 label: _ZN21SmallWanderBossBullet20tryStartFlyParabolicERKN4sead7Vector3IfEEf - status: NotDecompiled + status: Matching - offset: 0x0bb264 size: 100 label: _ZN21SmallWanderBossBullet11startLaunchEv - status: NotDecompiled + status: Matching - offset: 0x0bb2c8 size: 208 label: _ZN21SmallWanderBossBullet15exeAppearAttachEv - status: NotDecompiled + status: Matching - offset: 0x0bb398 size: 260 label: _ZN21SmallWanderBossBullet6exeFlyEv - status: NotDecompiled + status: Matching - offset: 0x0bb49c size: 92 label: _ZN21SmallWanderBossBullet19resetPositionByAnimEv - status: NotDecompiled + status: Matching - offset: 0x0bb4f8 size: 292 label: _ZN21SmallWanderBossBullet10exeFlyDownEv - status: NotDecompiled + status: Matching - offset: 0x0bb61c size: 252 label: _ZN21SmallWanderBossBullet16exeSignExplosionEv - status: NotDecompiled + status: Matching - offset: 0x0bb718 size: 156 label: _ZN21SmallWanderBossBullet12exeExplosionEv - status: NotDecompiled + status: Matching - offset: 0x0bb7b4 size: 8 label: _ZNK12_GLOBAL__N_127SmallWanderBossBulletNrvFly7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x0bb7bc size: 8 label: _ZNK12_GLOBAL__N_133SmallWanderBossBulletNrvExplosion7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x0bb7c4 size: 212 label: _ZNK12_GLOBAL__N_136SmallWanderBossBulletNrvAppearAttach7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x0bb898 size: 212 label: _ZNK12_GLOBAL__N_145SmallWanderBossBulletNrvAppearAttachParabolic7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x0bb96c size: 8 label: _ZNK12_GLOBAL__N_131SmallWanderBossBulletNrvFlyDown7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x0bb974 size: 8 label: _ZNK12_GLOBAL__N_137SmallWanderBossBulletNrvSignExplosion7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true Boss/SmallWanderBoss/SmallWanderBossStateAttack.o: '.text': diff --git a/src/Boss/SmallWanderBoss/SmallWanderBossBullet.cpp b/src/Boss/SmallWanderBoss/SmallWanderBossBullet.cpp new file mode 100644 index 00000000..f47f2e69 --- /dev/null +++ b/src/Boss/SmallWanderBoss/SmallWanderBossBullet.cpp @@ -0,0 +1,284 @@ +#include "Boss/SmallWanderBoss/SmallWanderBossBullet.h" + +#include "Library/Demo/DemoFunction.h" +#include "Library/LiveActor/ActorActionFunction.h" +#include "Library/LiveActor/ActorCollisionFunction.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/Math/MathUtil.h" +#include "Library/Math/ParabolicPath.h" +#include "Library/Nature/NatureUtil.h" +#include "Library/Nature/WaterSurfaceFinder.h" +#include "Library/Nerve/NerveSetupUtil.h" +#include "Library/Nerve/NerveUtil.h" +#include "Library/Player/PlayerUtil.h" + +#include "Util/PlayerCollisionUtil.h" +#include "Util/SensorMsgFunction.h" +#include "Util/WaterSurfaceShadow.h" + +namespace { +NERVE_IMPL(SmallWanderBossBullet, Fly) +NERVE_IMPL(SmallWanderBossBullet, Explosion) +NERVE_IMPL(SmallWanderBossBullet, AppearAttach) +NERVE_IMPL_(SmallWanderBossBullet, AppearAttachParabolic, AppearAttach) +NERVE_IMPL(SmallWanderBossBullet, FlyDown) +NERVE_IMPL(SmallWanderBossBullet, SignExplosion) + +NERVES_MAKE_NOSTRUCT(SmallWanderBossBullet, Fly, FlyDown, SignExplosion, Explosion, AppearAttach, + AppearAttachParabolic) +} // namespace + +SmallWanderBossBullet::SmallWanderBossBullet(const char* name) : al::LiveActor(name) { + _108 = {1.0f, 1.0f, 1.0f}; + mParabolicPath = nullptr; + mWaterSurfaceFinder = nullptr; + mAttachMtx = nullptr; + mAttachOffset = nullptr; + mExplosionStepMax = 1200; +} + +void SmallWanderBossBullet::init(const al::ActorInitInfo& initInfo) { + al::initActorWithArchiveName(this, initInfo, "SmallWanderBossBullet", nullptr); + al::initNerve(this, &Fly, 0); + al::setSensorRadius(this, "Attack", 60.0f); + al::setSensorRadius(this, "Body", 75.0f); + al::setColliderRadius(this, 40.0f); + + mParabolicPath = new al::ParabolicPath(); + mWaterSurfaceFinder = new al::WaterSurfaceFinder(this); + mWaterSurfaceShadow = new WaterSurfaceShadow(initInfo, "WaterSurfaceShadow"); + mWaterSurfaceShadow->setScale(8.0f); + + makeActorDead(); +} + +void SmallWanderBossBullet::appear() { + al::LiveActor::appear(); + al::showModelIfHide(this); + al::offCollide(this); +} + +void SmallWanderBossBullet::kill() { + al::LiveActor::kill(); + mWaterSurfaceShadow->disappearShadow(); +} + +void SmallWanderBossBullet::control() { + if (al::isNerve(this, &Explosion)) + return; + + sead::Vector3f groundPos; + groundPos.x = 0.0f; + groundPos.y = 0.0f; + const al::IUseCollision* collision = this; + groundPos.z = 0.0f; + f32 distance = 7500.0f; + rs::calcGroundHeight(&distance, &groundPos, collision, al::getTrans(this), + -al::getGravity(this), 0.0f, 7500.0f); + + mWaterSurfaceShadow->update(al::getTrans(this), -al::getGravity(this), distance); +} + +void SmallWanderBossBullet::attackSensor(al::HitSensor* self, al::HitSensor* other) { + if (al::isNerve(this, &Explosion)) + return; + + if (!al::isSensorEnemyAttack(self)) + return; + + if (al::isNerve(this, &AppearAttach) || al::isNerve(this, &AppearAttachParabolic)) + return; + + if (al::sendMsgEnemyAttack(other, self)) + al::setNerve(this, &Explosion); +} + +bool SmallWanderBossBullet::receiveMsg(const al::SensorMsg* message, al::HitSensor* other, + al::HitSensor* self) { + if (rs::isMsgPlayerDisregardTargetMarker(message) || + rs::isMsgPlayerDisregardHomingAttack(message)) { + return true; + } + + if (rs::isMsgKillByMoonRockDemo(message)) { + al::killForceBeforeDemo(this); + return true; + } + + if (!al::isSensorEnemyBody(self) || al::isNerve(this, &Explosion)) + return false; + + if (rs::isMsgCapReflect(message) || al::isMsgKickStoneAttackReflect(message) || + rs::isMsgSeedAttack(message)) { + rs::requestHitReactionToAttacker(message, self, other); + al::setNerve(this, &Explosion); + return true; + } + + return false; +} + +void SmallWanderBossBullet::appearAttach(const sead::Matrix34f* attachMtx, + const sead::Vector3f* attachOffset) { + const sead::Vector3f* offsetArg = attachOffset; + const sead::Matrix34f* mtxArg = attachMtx; + + mAttachMtx = mtxArg; + mAttachOffset = offsetArg; + + sead::Vector3f* trans = al::getTransPtr(this); + const sead::Vector3f* offset = offsetArg ? offsetArg : &sead::Vector3f::zero; + trans->setMul(*mtxArg, *offset); + + sead::Vector3f* front = al::getFrontPtr(this); + mtxArg->getBase(*front, 2); + + appear(); + al::setNerve(this, &AppearAttach); +} + +void SmallWanderBossBullet::appearAttachParabolic(const sead::Matrix34f* attachMtx, + const sead::Vector3f* attachOffset) { + const sead::Vector3f* offsetArg = attachOffset; + const sead::Matrix34f* mtxArg = attachMtx; + + mAttachMtx = mtxArg; + mAttachOffset = offsetArg; + + sead::Vector3f* trans = al::getTransPtr(this); + const sead::Vector3f* offset = offsetArg ? offsetArg : &sead::Vector3f::zero; + trans->setMul(*mtxArg, *offset); + + sead::Vector3f* front = al::getFrontPtr(this); + mtxArg->getBase(*front, 2); + + appear(); + al::setNerve(this, &AppearAttachParabolic); +} + +bool SmallWanderBossBullet::tryStartFlyParabolic(const sead::Vector3f& front, f32 launchSpeed) { + if (!al::isGreaterEqualStep(this, 5)) + return false; + + al::setFront(this, front); + mLaunchSpeed = launchSpeed; + al::setNerve(this, &FlyDown); + return true; +} + +void SmallWanderBossBullet::startLaunch() { + sead::Vector3f velocity = al::getFront(this) * 10.0f; + al::setVelocity(this, velocity); + al::setNerve(this, &Fly); +} + +void SmallWanderBossBullet::exeAppearAttach() { + const sead::Matrix34f* attachMtx = mAttachMtx; + const sead::Vector3f* attachOffset = mAttachOffset; + sead::Vector3f* trans = al::getTransPtr(this); + const sead::Vector3f* offset = attachOffset ? attachOffset : &sead::Vector3f::zero; + trans->setMul(*attachMtx, *offset); + + sead::Vector3f* front = al::getFrontPtr(this); + attachMtx->getBase(*front, 2); +} + +void SmallWanderBossBullet::exeFly() { + mWaterSurfaceFinder->update(al::getTrans(this), sead::Vector3f::ey, 100.0f); + + if (al::isFirstStep(this)) { + sead::Vector3f jointPos = sead::Vector3f::zero; + al::calcJointPos(&jointPos, this, "SmallWanderBossBullet"); + al::resetPosition(this, jointPos); + al::startAction(this, "Fly"); + al::onCollide(this); + } + + if (al::isCollided(this) || mWaterSurfaceFinder->isFoundSurface()) { + if (mWaterSurfaceFinder->isFoundSurface()) + al::tryAddRippleLarge(this, mWaterSurfaceFinder->getSurfacePosition()); + + al::startHitReaction(this, "破壊"); + kill(); + return; + } + + if (al::isGreaterEqualStep(this, 600)) + kill(); +} + +void SmallWanderBossBullet::resetPositionByAnim() { + sead::Vector3f jointPos = sead::Vector3f::zero; + al::calcJointPos(&jointPos, this, "SmallWanderBossBullet"); + al::resetPosition(this, jointPos); +} + +void SmallWanderBossBullet::exeFlyDown() { + if (al::isFirstStep(this)) { + al::onCollide(this); + const sead::Vector3f& front = al::getFront(this); + f32 randomSpeed = al::getRandom(-200.0f, 200.0f); + al::setVelocitySeparateHV(this, front, randomSpeed + 300.0f, 100.0f); + } + + al::addVelocityToGravity(this, 0.98f); + al::scaleVelocityHV(this, 0.96f, 0.98f); + mWaterSurfaceFinder->update(al::getTrans(this), sead::Vector3f::ey, 40.0f); + + if (al::isCollided(this) || mWaterSurfaceFinder->isFoundSurface()) { + if (mWaterSurfaceFinder->isFoundSurface()) + al::tryAddRippleLarge(this, mWaterSurfaceFinder->getSurfacePosition()); + + al::offCollide(this); + al::setNerve(this, &SignExplosion); + return; + } + + if (al::isGreaterEqualStep(this, 600)) { + al::offCollide(this); + al::setNerve(this, &SignExplosion); + } +} + +void SmallWanderBossBullet::exeSignExplosion() { + mWaterSurfaceFinder->update(al::getTrans(this), sead::Vector3f::ey, 40.0f); + + if (al::isFirstStep(this)) { + al::startAction(this, "SignExplosion"); + mExplosionStepMax = 1200; + } + + if (mExplosionStepMax == 1200 && al::isNearPlayer(this, 3000.0f)) { + s32 step = al::getNerveStep(this) + 90; + if (step >= 1200) + step = 1200; + mExplosionStepMax = step; + } + + al::approachWaterSurfaceSpringDumper(this, mWaterSurfaceFinder, 0.0f, 12.0f, 1.0f, 0.022f, + 0.93f); + + if (al::isGreaterEqualStep(this, mExplosionStepMax)) + al::setNerve(this, &Explosion); +} + +void SmallWanderBossBullet::exeExplosion() { + if (al::isFirstStep(this)) { + if (mWaterSurfaceFinder->isFoundSurface()) { + al::tryAddRippleWithRange(this, mWaterSurfaceFinder->getSurfacePosition(), 0.25f, + 300.0f, 1000.0f, 1000.0f); + } + + al::startHitReaction(this, "破壊"); + al::hideModelIfShow(this); + mWaterSurfaceShadow->disappearShadow(); + } + + if (al::isGreaterEqualStep(this, 30)) + kill(); +} diff --git a/src/Boss/SmallWanderBoss/SmallWanderBossBullet.h b/src/Boss/SmallWanderBoss/SmallWanderBossBullet.h new file mode 100644 index 00000000..3d936417 --- /dev/null +++ b/src/Boss/SmallWanderBoss/SmallWanderBossBullet.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include + +#include "Library/LiveActor/LiveActor.h" + +namespace al { +struct ActorInitInfo; +class HitSensor; +class ParabolicPath; +class SensorMsg; +class WaterSurfaceFinder; +} // namespace al + +class WaterSurfaceShadow; + +class SmallWanderBossBullet : public al::LiveActor { +public: + SmallWanderBossBullet(const char* name); + + void init(const al::ActorInitInfo& initInfo) override; + void appear() override; + void kill() override; + void control() override; + void attackSensor(al::HitSensor* self, al::HitSensor* other) override; + bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other, + al::HitSensor* self) override; + + void appearAttach(const sead::Matrix34f* attachMtx, const sead::Vector3f* attachOffset); + void appearAttachParabolic(const sead::Matrix34f* attachMtx, + const sead::Vector3f* attachOffset); + bool tryStartFlyParabolic(const sead::Vector3f& front, f32 launchSpeed); + void startLaunch(); + void exeAppearAttach(); + void exeFly(); + void resetPositionByAnim(); + void exeFlyDown(); + void exeSignExplosion(); + void exeExplosion(); + +private: + sead::Vector3f _108; // TODO: verify exact meaning + u32 _114; // TODO: verify exact meaning + const sead::Matrix34f* mAttachMtx; + const sead::Vector3f* mAttachOffset; + al::ParabolicPath* mParabolicPath; + al::WaterSurfaceFinder* mWaterSurfaceFinder; + WaterSurfaceShadow* mWaterSurfaceShadow; + f32 mLaunchSpeed; // TODO: verify exact usage + s32 mExplosionStepMax; +}; + +static_assert(sizeof(SmallWanderBossBullet) == 0x148);