mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-04-23 09:04:21 +00:00
Enemy: Implement CatchBomb (#897)
This commit is contained in:
parent
c73ac5d56d
commit
76a75719a4
|
|
@ -27501,216 +27501,216 @@ Enemy/CatchBomb.o:
|
|||
- offset: 0x0f190c
|
||||
size: 180
|
||||
label: _ZN9CatchBombC2EPKc
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f19c0
|
||||
size: 192
|
||||
label: _ZN9CatchBombC1EPKc
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f1a80
|
||||
size: 468
|
||||
label: _ZN9CatchBomb4initERKN2al13ActorInitInfoE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f1c54
|
||||
size: 584
|
||||
label: _ZN9CatchBomb12attackSensorEPN2al9HitSensorES2_
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f1e9c
|
||||
size: 72
|
||||
label: _ZNK9CatchBomb17isEnableExplosionEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f1ee4
|
||||
size: 96
|
||||
label: _ZN9CatchBomb15tryShiftExplodeEb
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f1f44
|
||||
size: 124
|
||||
label: _ZNK9CatchBomb19isEnableEnemyAttackEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f1fc0
|
||||
size: 100
|
||||
label: _ZN9CatchBomb14tryShiftAttackEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2024
|
||||
size: 644
|
||||
label: _ZN9CatchBomb10receiveMsgEPKN2al9SensorMsgEPNS0_9HitSensorES5_
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f22a8
|
||||
size: 108
|
||||
label: _ZN9CatchBomb22tryReceiveMsgPushLocalEPKN2al9SensorMsgEPNS0_9HitSensorES5_
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2314
|
||||
size: 16
|
||||
label: _ZNK9CatchBomb17isCapReflectNerveEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2324
|
||||
size: 184
|
||||
label: _ZNK9CatchBomb12isUncapNerveEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f23dc
|
||||
size: 396
|
||||
label: _ZN9CatchBomb7exeWaitEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2568
|
||||
size: 56
|
||||
label: _ZN9CatchBomb11calcGravityEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f25a0
|
||||
size: 16
|
||||
label: _ZN9CatchBomb9calcBrakeEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f25b0
|
||||
size: 72
|
||||
label: _ZN9CatchBomb12tryShiftFallEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f25f8
|
||||
size: 156
|
||||
label: _ZN9CatchBomb30tryShiftDamageCollisionExplodeEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2694
|
||||
size: 444
|
||||
label: _ZN9CatchBomb7exeFindEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2850
|
||||
size: 52
|
||||
label: _ZN9CatchBomb12tryShiftWaitEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2884
|
||||
size: 616
|
||||
label: _ZN9CatchBomb7exeMoveEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2aec
|
||||
size: 404
|
||||
label: _ZN9CatchBomb7exeTurnEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2c80
|
||||
size: 252
|
||||
label: _ZN9CatchBomb7exeFallEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2d7c
|
||||
size: 100
|
||||
label: _ZN9CatchBomb7exeBackEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2de0
|
||||
size: 380
|
||||
label: _ZN9CatchBomb9exeAttackEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f2f5c
|
||||
size: 492
|
||||
label: _ZN9CatchBomb8exeCatchEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f3148
|
||||
size: 16
|
||||
label: _ZN9CatchBomb21requestCapHitReactionEPKcb
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f3158
|
||||
size: 420
|
||||
label: _ZN9CatchBomb7exePullEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f32fc
|
||||
size: 312
|
||||
label: _ZN9CatchBomb21checkCollisionExplodeERKN4sead7Vector3IfEE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f3434
|
||||
size: 592
|
||||
label: _ZN9CatchBomb8exeMarchEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f3684
|
||||
size: 188
|
||||
label: _ZN9CatchBomb10exeExplodeEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f3740
|
||||
size: 124
|
||||
label: _ZN9CatchBomb7exeHideEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f37bc
|
||||
size: 164
|
||||
label: _ZN9CatchBomb9exeAppearEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f3860
|
||||
size: 144
|
||||
label: _ZN9CatchBomb8exeThrowEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f38f0
|
||||
size: 232
|
||||
label: _ZN9CatchBomb9initThrowERKN2al13ActorInitInfoE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f39d8
|
||||
size: 96
|
||||
label: _ZN9CatchBomb11appearThrowERKN4sead7Vector3IfEES4_
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f3a38
|
||||
size: 468
|
||||
label: _ZN9CatchBomb7controlEv
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
- offset: 0x0f3c0c
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_116CatchBombNrvWait7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3c14
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_117CatchBombNrvCatch7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3c1c
|
||||
size: 128
|
||||
label: _ZNK12_GLOBAL__N_116CatchBombNrvHide7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3c9c
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_119CatchBombNrvExplode7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3ca4
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_116CatchBombNrvPull7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3cac
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_117CatchBombNrvMarch7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3cb4
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_116CatchBombNrvFind7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3cbc
|
||||
size: 104
|
||||
label: _ZNK12_GLOBAL__N_116CatchBombNrvBack7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3d24
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_116CatchBombNrvMove7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3d2c
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_116CatchBombNrvTurn7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3d34
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_118CatchBombNrvAppear7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3d3c
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_117CatchBombNrvThrow7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3d44
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_118CatchBombNrvAttack7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
- offset: 0x0f3d4c
|
||||
size: 8
|
||||
label: _ZNK12_GLOBAL__N_116CatchBombNrvFall7executeEPN2al11NerveKeeperE
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
guess: true
|
||||
Enemy/Chorobon.o:
|
||||
'.text':
|
||||
|
|
@ -133910,7 +133910,7 @@ Scene/ProjectActorFactory.o:
|
|||
- offset: 0x4b7188
|
||||
size: 52
|
||||
label: _ZN2al19createActorFunctionI9CatchBombEEPNS_9LiveActorEPKc
|
||||
status: NotDecompiled
|
||||
status: Matching
|
||||
lazy: true
|
||||
- offset: 0x4b71bc
|
||||
size: 52
|
||||
|
|
|
|||
27
src/Boss/Loop/LoopAnimState.h
Normal file
27
src/Boss/Loop/LoopAnimState.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include "Library/Nerve/NerveStateBase.h"
|
||||
|
||||
namespace al {
|
||||
class LiveActor;
|
||||
}
|
||||
|
||||
class LoopAnimState : public al::ActorStateBase {
|
||||
public:
|
||||
LoopAnimState(al::LiveActor*, const char*, bool);
|
||||
void appear() override;
|
||||
void end();
|
||||
void exeStart();
|
||||
void startAction(const char*);
|
||||
void exeLoop();
|
||||
void exeEnd();
|
||||
|
||||
private:
|
||||
const char* _20;
|
||||
const char* _28;
|
||||
const char* _30;
|
||||
const char* _38;
|
||||
bool _40;
|
||||
};
|
||||
|
||||
static_assert(sizeof(LoopAnimState) == 0x48);
|
||||
636
src/Enemy/CatchBomb.cpp
Normal file
636
src/Enemy/CatchBomb.cpp
Normal file
|
|
@ -0,0 +1,636 @@
|
|||
#include "Enemy/CatchBomb.h"
|
||||
|
||||
#include <math/seadMathCalcCommon.h>
|
||||
|
||||
#include "Library/Collision/KCollisionServer.h"
|
||||
#include "Library/Joint/JointControllerKeeper.h"
|
||||
#include "Library/Joint/JointSpringControllerHolder.h"
|
||||
#include "Library/LiveActor/ActorActionFunction.h"
|
||||
#include "Library/LiveActor/ActorAreaFunction.h"
|
||||
#include "Library/LiveActor/ActorClippingFunction.h"
|
||||
#include "Library/LiveActor/ActorCollisionFunction.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/Nerve/NerveSetupUtil.h"
|
||||
#include "Library/Nerve/NerveUtil.h"
|
||||
#include "Library/Placement/PlacementFunction.h"
|
||||
#include "Library/Player/PlayerUtil.h"
|
||||
#include "Library/Se/SeFunction.h"
|
||||
#include "Library/Shadow/ActorShadowUtil.h"
|
||||
|
||||
#include "Boss/Loop/LoopAnimState.h"
|
||||
#include "Enemy/DisregardReceiver.h"
|
||||
#include "MapObj/CapMessageShowInfo.h"
|
||||
#include "Util/Hack.h"
|
||||
#include "Util/PlayerUtil.h"
|
||||
#include "Util/SensorMsgFunction.h"
|
||||
|
||||
namespace {
|
||||
NERVE_IMPL(CatchBomb, Wait);
|
||||
NERVE_IMPL(CatchBomb, Catch);
|
||||
NERVE_IMPL(CatchBomb, Hide);
|
||||
NERVE_IMPL(CatchBomb, Explode);
|
||||
NERVE_IMPL(CatchBomb, Pull);
|
||||
NERVE_IMPL(CatchBomb, March);
|
||||
NERVE_IMPL(CatchBomb, Find);
|
||||
NERVE_IMPL(CatchBomb, Back);
|
||||
NERVE_IMPL(CatchBomb, Move);
|
||||
NERVE_IMPL(CatchBomb, Turn);
|
||||
NERVE_IMPL(CatchBomb, Appear);
|
||||
NERVE_IMPL(CatchBomb, Throw);
|
||||
NERVE_IMPL(CatchBomb, Attack);
|
||||
NERVE_IMPL(CatchBomb, Fall);
|
||||
|
||||
NERVES_MAKE_STRUCT(CatchBomb, Wait, Catch, Hide, Explode, Pull, March, Find, Back, Move, Turn,
|
||||
Appear, Throw, Attack, Fall);
|
||||
} // namespace
|
||||
|
||||
CatchBomb::CatchBomb(const char* name) : al::LiveActor(name) {}
|
||||
|
||||
void CatchBomb::init(const al::ActorInitInfo& info) {
|
||||
al::initActor(this, info);
|
||||
al::initNerve(this, &NrvCatchBomb.Wait, 1);
|
||||
mCatchState = new LoopAnimState(this, "Catch", false);
|
||||
al::initNerveState(this, mCatchState, &NrvCatchBomb.Catch, "キャッチ");
|
||||
al::invalidateHitSensor(this, "Explosion");
|
||||
al::tryGetArg(&mIsRevival, info, "Revival");
|
||||
mSpawnPos.set(al::getTrans(this));
|
||||
mCapTargetInfo = rs::createCapTargetInfo(this, nullptr);
|
||||
mCollisionPartsFilter = new al::CollisionPartsFilterSpecialPurpose("MoveLimit");
|
||||
al::setColliderFilterCollisionParts(this, mCollisionPartsFilter);
|
||||
al::initJointControllerKeeper(this, 2);
|
||||
mJointSpringControllerHolder = new al::JointSpringControllerHolder();
|
||||
mJointSpringControllerHolder->init(this, "InitJointSpringCtrl");
|
||||
makeActorAlive();
|
||||
al::invalidateShadowMask(this, "ダミー帽子影");
|
||||
mDisregardReceiver = new DisregardReceiver(this, nullptr);
|
||||
mCatchBombGeneratePoint = new al::LiveActor("キャッチボム出現ポイント");
|
||||
al::initActorWithArchiveName(mCatchBombGeneratePoint, info, "CatchBombGeneratePoint", nullptr);
|
||||
mCatchBombGeneratePoint->makeActorAlive();
|
||||
}
|
||||
|
||||
inline bool isAppearNew(const CatchBomb* self) {
|
||||
return al::isNerve(self, &NrvCatchBomb.Appear) && al::isLessEqualStep(self, 60);
|
||||
}
|
||||
|
||||
void CatchBomb::attackSensor(al::HitSensor* self, al::HitSensor* other) {
|
||||
if (al::isSensorName(other, "SpinAttack") || al::isNerve(this, &NrvCatchBomb.Hide))
|
||||
return;
|
||||
|
||||
if (al::isSensorName(self, "Explosion")) {
|
||||
if (!al::isSensorPlayer(other))
|
||||
al::sendMsgExplosion(other, self, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (al::isNerve(this, &NrvCatchBomb.Explode))
|
||||
return;
|
||||
|
||||
if (isEnableExplosion()) {
|
||||
if (al::isSensorName(self, "Head") &&
|
||||
!(al::isSensorPlayer(other) && rs::isPlayerSquat(this))) {
|
||||
if (!rs::sendMsgCatchBombThrough(other, self) &&
|
||||
al::sendMsgExplosion(other, self, nullptr)) {
|
||||
tryShiftExplode(false);
|
||||
return;
|
||||
}
|
||||
|
||||
al::sendMsgPush(other, self);
|
||||
rs::sendMsgPushToPlayer(other, self);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((al::isSensorPlayer(other) || al::isSensorEnemyBody(other)) &&
|
||||
al::isSensorName(self, "Body")) {
|
||||
if (isEnableEnemyAttack() && al::sendMsgEnemyAttack(other, self)) {
|
||||
tryShiftAttack();
|
||||
return;
|
||||
}
|
||||
|
||||
al::sendMsgPush(other, self);
|
||||
rs::sendMsgPushToPlayer(other, self);
|
||||
}
|
||||
}
|
||||
|
||||
bool CatchBomb::isEnableExplosion() const {
|
||||
return al::isNerve(this, &NrvCatchBomb.Pull) || al::isNerve(this, &NrvCatchBomb.March);
|
||||
}
|
||||
|
||||
bool CatchBomb::tryShiftExplode(bool unused) {
|
||||
if (!al::isNerve(this, &NrvCatchBomb.Explode)) {
|
||||
requestCapHitReaction("キャッチボム捕まって爆発", false);
|
||||
al::setNerve(this, &NrvCatchBomb.Explode);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CatchBomb::isEnableEnemyAttack() const {
|
||||
if (isAppearNew(this) || al::isNerve(this, &NrvCatchBomb.Explode) ||
|
||||
al::isNerve(this, &NrvCatchBomb.Pull) || al::isNerve(this, &NrvCatchBomb.March)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CatchBomb::tryShiftAttack() {
|
||||
if (al::isNerve(this, &NrvCatchBomb.Wait) || al::isNerve(this, &NrvCatchBomb.Move) ||
|
||||
al::isNerve(this, &NrvCatchBomb.Turn)) {
|
||||
al::setNerve(this, &NrvCatchBomb.Attack);
|
||||
}
|
||||
}
|
||||
|
||||
bool CatchBomb::receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
|
||||
al::HitSensor* self) {
|
||||
if (rs::tryReceiveMsgInitCapTargetAndSetCapTargetInfo(message, mCapTargetInfo))
|
||||
return true;
|
||||
|
||||
if (mDisregardReceiver->receiveMsg(message, other, self))
|
||||
return true;
|
||||
|
||||
if (al::isNerve(this, &NrvCatchBomb.Hide))
|
||||
return false;
|
||||
|
||||
if (al::isNerve(this, &NrvCatchBomb.Wait) && tryReceiveMsgPushLocal(message, other, self))
|
||||
return true;
|
||||
|
||||
if (rs::isMsgCapReflect(message))
|
||||
return isCapReflectNerve();
|
||||
|
||||
if (!isUncapNerve()) {
|
||||
if (rs::isMsgCapStartLockOn(message)) {
|
||||
mCap = al::getSensorHost(other);
|
||||
al::invalidateClipping(this);
|
||||
mExplodeTimer = 0;
|
||||
al::setNerve(this, &NrvCatchBomb.Catch);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tryReceiveMsgPushLocal(message, other, self))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (al::isNerve(this, &NrvCatchBomb.Catch) || isEnableExplosion()) {
|
||||
if (rs::isMsgCapKeepLockOn(message))
|
||||
return true;
|
||||
|
||||
if (rs::isMsgCapIgnoreCancelLockOn(message))
|
||||
return true;
|
||||
|
||||
if (tryReceiveMsgPushLocal(message, other, self))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rs::isMsgCapCancelLockOn(message)) {
|
||||
tryShiftExplode(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!al::isNerve(this, &NrvCatchBomb.Explode) &&
|
||||
(al::isMsgExplosion(message) || rs::isMsgTsukkunThrust(message, nullptr))) {
|
||||
tryShiftExplode(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rs::isMsgNpcScareByEnemy(message))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CatchBomb::tryReceiveMsgPushLocal(const al::SensorMsg* message, al::HitSensor* other,
|
||||
al::HitSensor* self) {
|
||||
if (al::isSensorName(self, "Body") &&
|
||||
al::tryReceiveMsgPushAndAddVelocityH(this, message, other, self, 3.0f)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CatchBomb::isCapReflectNerve() const {
|
||||
return al::isNerve(this, &NrvCatchBomb.Throw);
|
||||
}
|
||||
|
||||
bool CatchBomb::isUncapNerve() const {
|
||||
return isAppearNew(this) || al::isNerve(this, &NrvCatchBomb.Back) ||
|
||||
al::isNerve(this, &NrvCatchBomb.Hide) || al::isNerve(this, &NrvCatchBomb.Catch) ||
|
||||
isEnableExplosion() || al::isNerve(this, &NrvCatchBomb.Explode) || isCapReflectNerve();
|
||||
}
|
||||
|
||||
void CatchBomb::exeWait() {
|
||||
if (al::isFirstStep(this))
|
||||
al::startAction(this, "Wait");
|
||||
|
||||
calcGravity();
|
||||
calcBrake();
|
||||
|
||||
if (mIsFirstWait) {
|
||||
mIsFirstWait = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (tryShiftFall())
|
||||
return;
|
||||
|
||||
if (tryShiftDamageCollisionExplode())
|
||||
return;
|
||||
|
||||
if (mPlayerFarCounter == 0 && al::isNear(this, al::getPlayerActor(this, 0), 1000.0f)) {
|
||||
al::setNerve(this, &NrvCatchBomb.Find);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPlayerFarCounter > 120 && al::isFar(this, mSpawnPos, 300.0f))
|
||||
al::setNerve(this, &NrvCatchBomb.Back);
|
||||
}
|
||||
|
||||
void CatchBomb::calcGravity() {
|
||||
if (al::isOnGround(this, 0))
|
||||
al::setVelocityZeroY(this);
|
||||
al::addVelocityY(this, -0.5f);
|
||||
}
|
||||
|
||||
void CatchBomb::calcBrake() {
|
||||
al::scaleVelocityHV(this, 0.95f, 1.0f);
|
||||
}
|
||||
|
||||
bool CatchBomb::tryShiftFall() {
|
||||
if (!al::isOnGround(this, 4)) {
|
||||
al::setNerve(this, &NrvCatchBomb.Fall);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CatchBomb::tryShiftDamageCollisionExplode() {
|
||||
if (al::isCollidedFloorCode(this, "DamageFire") || al::isCollidedFloorCode(this, "Needle") ||
|
||||
al::isCollidedFloorCode(this, "Poison")) {
|
||||
tryShiftExplode(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CatchBomb::exeFind() {
|
||||
if (al::isFirstStep(this)) {
|
||||
al::startAction(this, "Find");
|
||||
mTurnTarget.set(al::getPlayerPos(this, 0));
|
||||
}
|
||||
|
||||
calcGravity();
|
||||
calcBrake();
|
||||
al::turnToTarget(this, mTurnTarget, 7.0f);
|
||||
|
||||
if (tryShiftFall())
|
||||
return;
|
||||
|
||||
if (tryShiftDamageCollisionExplode())
|
||||
return;
|
||||
|
||||
if (tryShiftWait())
|
||||
return;
|
||||
|
||||
if (al::isActionEnd(this)) {
|
||||
sead::Vector3f frontDir;
|
||||
al::calcFrontDir(&frontDir, this);
|
||||
if (al::isFaceToTargetDegreeH(this, al::getPlayerPos(this, 0), frontDir, 90.0f))
|
||||
al::setNerve(this, &NrvCatchBomb.Move);
|
||||
else
|
||||
al::setNerve(this, &NrvCatchBomb.Turn);
|
||||
}
|
||||
}
|
||||
|
||||
bool CatchBomb::tryShiftWait() {
|
||||
if (mPlayerFarCounter > 60) {
|
||||
al::setNerve(this, &NrvCatchBomb.Wait);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CatchBomb::exeMove() {
|
||||
if (al::isFirstStep(this))
|
||||
al::tryStartActionIfNotPlaying(this, "Walk");
|
||||
|
||||
if (al::isCollidedWallVelocity(this)) {
|
||||
sead::Vector3f* vel = al::getVelocityPtr(this);
|
||||
al::verticalizeVec(vel, al::getCollidedWallNormal(this), *vel);
|
||||
}
|
||||
|
||||
calcGravity();
|
||||
calcBrake();
|
||||
|
||||
if (!al::isNearPlayer(this, 100.0f))
|
||||
al::turnToTarget(this, al::getPlayerPos(this, 0), 2.0f);
|
||||
|
||||
sead::Vector3f dir = al::getPlayerPos(this, 0) - al::getTrans(this);
|
||||
dir.y = 0.0f;
|
||||
al::tryNormalizeOrZero(&dir);
|
||||
sead::Vector3f vel = al::getVelocity(this);
|
||||
vel.y = 0.0f;
|
||||
al::addVelocity(this, (dir * 5.0f - vel) * 0.05f);
|
||||
|
||||
if (tryShiftFall())
|
||||
return;
|
||||
|
||||
if (tryShiftDamageCollisionExplode())
|
||||
return;
|
||||
|
||||
if (tryShiftWait())
|
||||
return;
|
||||
|
||||
sead::Vector3f frontDir;
|
||||
al::calcFrontDir(&frontDir, this);
|
||||
if (!al::isFaceToTargetDegreeH(this, al::getPlayerPos(this, 0), frontDir, 90.0f))
|
||||
al::setNerve(this, &NrvCatchBomb.Turn);
|
||||
}
|
||||
|
||||
void CatchBomb::exeTurn() {
|
||||
if (al::isFirstStep(this))
|
||||
al::startAction(this, "Turn");
|
||||
|
||||
calcGravity();
|
||||
calcBrake();
|
||||
|
||||
al::turnToTarget(this, al::getPlayerPos(this, 0), 2.0f);
|
||||
|
||||
if (tryShiftFall())
|
||||
return;
|
||||
|
||||
if (tryShiftDamageCollisionExplode())
|
||||
return;
|
||||
|
||||
if (tryShiftWait())
|
||||
return;
|
||||
|
||||
sead::Vector3f frontDir;
|
||||
al::calcFrontDir(&frontDir, this);
|
||||
if (al::isFaceToTargetDegreeH(this, al::getPlayerPos(this, 0), frontDir, 30.0f))
|
||||
al::setNerve(this, &NrvCatchBomb.Move);
|
||||
}
|
||||
|
||||
void CatchBomb::exeFall() {
|
||||
if (al::isFirstStep(this))
|
||||
al::startAction(this, "Wait");
|
||||
|
||||
calcGravity();
|
||||
|
||||
if (tryShiftDamageCollisionExplode())
|
||||
return;
|
||||
|
||||
if (isOnGround(this, 0))
|
||||
al::setNerve(this, &NrvCatchBomb.Move);
|
||||
}
|
||||
|
||||
void CatchBomb::exeBack() {
|
||||
if (al::isFirstStep(this)) {
|
||||
al::startAction(this, "Disappear");
|
||||
al::setVelocityZeroH(this);
|
||||
}
|
||||
|
||||
if (al::isActionEnd(this))
|
||||
al::setNerve(this, &NrvCatchBomb.Hide);
|
||||
}
|
||||
|
||||
void CatchBomb::exeAttack() {
|
||||
if (al::isFirstStep(this)) {
|
||||
al::startAction(this, "Attack");
|
||||
al::setVelocityZeroH(this);
|
||||
}
|
||||
|
||||
calcGravity();
|
||||
calcBrake();
|
||||
|
||||
if (tryShiftFall())
|
||||
return;
|
||||
|
||||
if (tryShiftDamageCollisionExplode())
|
||||
return;
|
||||
|
||||
if (al::isActionPlaying(this, "Attack") && al::isActionEnd(this))
|
||||
al::startAction(this, "Wait");
|
||||
|
||||
if (al::isActionPlaying(this, "Wait") && al::isGreaterEqualStep(this, 90))
|
||||
al::setNerve(this, &NrvCatchBomb.Move);
|
||||
}
|
||||
|
||||
void CatchBomb::exeCatch() {
|
||||
if (al::isFirstStep(this)) {
|
||||
al::setColliderFilterCollisionParts(this, nullptr);
|
||||
rs::tryShowCapMsgCatchBombCatchFirst(this);
|
||||
al::validateShadowMask(this, "ダミー帽子影");
|
||||
}
|
||||
|
||||
if (al::isGreaterEqualStep(this, 106))
|
||||
al::holdSe(this, "CountFastLv");
|
||||
else
|
||||
al::holdSe(this, "CountNormalLv");
|
||||
|
||||
if (al::getNerveStep(this) == al::getActionFrameMax(this, "CatchStart"))
|
||||
requestCapHitReaction("キャッチボム捕まった", false);
|
||||
|
||||
if (al::getNerveStep(this) == al::getActionFrameMax(this, "CatchStart") + 38.0f)
|
||||
requestCapHitReaction("キャッチボム突進予兆1", false);
|
||||
|
||||
if (al::getNerveStep(this) == al::getActionFrameMax(this, "CatchStart") + 91.0f)
|
||||
requestCapHitReaction("キャッチボム突進予兆2", false);
|
||||
|
||||
al::faceToTarget(this, al::getPlayerPos(this, 0));
|
||||
calcGravity();
|
||||
calcBrake();
|
||||
al::updateNerveState(this);
|
||||
|
||||
if (al::isGreaterEqualStep(this, 146))
|
||||
al::setNerve(this, &NrvCatchBomb.Pull);
|
||||
}
|
||||
|
||||
void CatchBomb::requestCapHitReaction(const char* reactionName, bool unused) {
|
||||
rs::requestLockOnCapHitReaction(this, mCapTargetInfo, reactionName);
|
||||
}
|
||||
|
||||
void CatchBomb::exePull() {
|
||||
if (al::isFirstStep(this)) {
|
||||
al::startAction(this, "CatchEnd");
|
||||
al::setVelocityZero(this);
|
||||
}
|
||||
|
||||
if (!al::isActionPlaying(this, "CatchEndLoop") && al::isActionEnd(this)) {
|
||||
al::startAction(this, "CatchEndLoop");
|
||||
requestCapHitReaction("キャッチボム捕まって突進", false);
|
||||
}
|
||||
|
||||
sead::Vector3f dir = rs::getPlayerHeadPos(this) - al::getTrans(this);
|
||||
dir.y = 0.0f;
|
||||
if (!al::tryNormalizeOrZero(&dir))
|
||||
al::calcFrontDir(&dir, this);
|
||||
al::faceToDirection(this, dir);
|
||||
|
||||
if (checkCollisionExplode(dir))
|
||||
return;
|
||||
|
||||
if (al::isGreaterEqualStep(this, 2) && al::isNearPlayerH(this, 1000.0f)) {
|
||||
al::setNerve(this, &NrvCatchBomb.March);
|
||||
return;
|
||||
}
|
||||
|
||||
al::addVelocity(this, (dir * 35.0 - al::getVelocity(this)) * 0.3f);
|
||||
}
|
||||
|
||||
bool CatchBomb::checkCollisionExplode(const sead::Vector3f& dir) {
|
||||
al::HitSensor* hitSensor = nullptr;
|
||||
if (al::isCollidedWallVelocity(this))
|
||||
hitSensor = al::getCollidedWallSensor(this);
|
||||
|
||||
if (!hitSensor && al::isCollidedGround(this) &&
|
||||
dir.dot(sead::Vector3f::ey) < sead::Mathf::cos(sead::Mathf::deg2rad(135.0f))) {
|
||||
hitSensor = al::getCollidedGroundSensor(this);
|
||||
}
|
||||
|
||||
if (!hitSensor && al::isCollidedCeilingVelocity(this))
|
||||
hitSensor = al::getCollidedCeilingSensor(this);
|
||||
|
||||
if (hitSensor) {
|
||||
al::sendMsgExplosionCollide(hitSensor, al::getHitSensor(this, "Body"), nullptr);
|
||||
al::invalidateHitSensors(this);
|
||||
|
||||
tryShiftExplode(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CatchBomb::exeMarch() {
|
||||
if (al::isFirstStep(this)) {
|
||||
f32 speed = al::getVelocity(this).length();
|
||||
sead::Vector3f dir = rs::getPlayerHeadPos(al::getPlayerActor(this, 0)) - al::getTrans(this);
|
||||
dir.y = 0.0f;
|
||||
if (al::tryNormalizeOrZero(&dir))
|
||||
al::getVelocityPtr(this)->set(dir * speed);
|
||||
}
|
||||
|
||||
if (!al::isActionPlaying(this, "CatchEndLoop") && al::isActionEnd(this)) {
|
||||
al::startAction(this, "CatchEndLoop");
|
||||
requestCapHitReaction("キャッチボム捕まって突進", false);
|
||||
}
|
||||
|
||||
if (al::getVelocity(this).squaredLength() < sead::Mathf::square(35.0f)) {
|
||||
sead::Vector3f dir = al::getVelocity(this);
|
||||
al::tryNormalizeOrZero(&dir);
|
||||
dir *= 35.0f;
|
||||
al::addVelocity(this, (dir - al::getVelocity(this)) * 0.3f);
|
||||
}
|
||||
|
||||
sead::Vector3f frontDir;
|
||||
al::calcFrontDir(&frontDir, this);
|
||||
if (!checkCollisionExplode(frontDir) && al::isGreaterEqualStep(this, 150))
|
||||
tryShiftExplode(false);
|
||||
}
|
||||
|
||||
void CatchBomb::exeExplode() {
|
||||
if (al::isFirstStep(this)) {
|
||||
al::startAction(this, "Explode");
|
||||
al::validateHitSensor(this, "Explosion");
|
||||
al::setVelocityZero(this);
|
||||
al::invalidateShadowMask(this, "ダミー帽子影");
|
||||
}
|
||||
|
||||
if (al::isActionEnd(this)) {
|
||||
al::validateHitSensors(this);
|
||||
al::invalidateHitSensor(this, "Explosion");
|
||||
if (mIsRevival) {
|
||||
al::setNerve(this, &NrvCatchBomb.Hide);
|
||||
return;
|
||||
}
|
||||
kill();
|
||||
}
|
||||
}
|
||||
|
||||
void CatchBomb::exeHide() {
|
||||
if (al::isFirstStep(this)) {
|
||||
al::hideModelIfShow(this);
|
||||
al::invalidateShadowMask(this, "ダミー帽子影");
|
||||
}
|
||||
|
||||
if (al::isGreaterEqualStep(this, 60)) {
|
||||
al::validateClipping(this);
|
||||
al::resetPosition(this, mSpawnPos);
|
||||
al::setNerve(this, &NrvCatchBomb.Appear);
|
||||
}
|
||||
}
|
||||
|
||||
void CatchBomb::exeAppear() {
|
||||
if (al::isFirstStep(this)) {
|
||||
al::showModelIfHide(this);
|
||||
al::startAction(this, "Appear");
|
||||
al::setColliderFilterCollisionParts(this, mCollisionPartsFilter);
|
||||
al::invalidateShadowMask(this, "ダミー帽子影");
|
||||
mCap = nullptr;
|
||||
}
|
||||
|
||||
calcGravity();
|
||||
if (al::isActionEnd(this))
|
||||
al::setNerve(this, &NrvCatchBomb.Wait);
|
||||
}
|
||||
|
||||
void CatchBomb::exeThrow() {
|
||||
if (al::isFirstStep(this)) {
|
||||
al::startAction(this, "Throw");
|
||||
mCap = nullptr;
|
||||
}
|
||||
|
||||
calcGravity();
|
||||
if (al::isOnGround(this, 0)) {
|
||||
al::setVelocityZeroY(this);
|
||||
al::setNerve(this, &NrvCatchBomb.Move);
|
||||
}
|
||||
}
|
||||
|
||||
void CatchBomb::initThrow(const al::ActorInitInfo& info) {
|
||||
al::initChildActorWithArchiveNameNoPlacementInfo(this, info, "CatchBomb", nullptr);
|
||||
al::initNerve(this, &NrvCatchBomb.Throw, 1);
|
||||
mCatchState = new LoopAnimState(this, "Catch", false);
|
||||
al::initNerveState(this, mCatchState, &NrvCatchBomb.Catch, "キャッチ");
|
||||
al::invalidateHitSensor(this, "Explosion");
|
||||
al::createAndSetColliderSpecialPurpose(this, "MoveLimit");
|
||||
mCapTargetInfo = rs::createCapTargetInfo(this, nullptr);
|
||||
makeActorDead();
|
||||
}
|
||||
|
||||
void CatchBomb::appearThrow(const sead::Vector3f& pos, const sead::Vector3f& vel) {
|
||||
mExplodeTimer = 0;
|
||||
al::setVelocity(this, vel);
|
||||
al::resetPosition(this, pos);
|
||||
al::setNerve(this, &NrvCatchBomb.Throw);
|
||||
al::invalidateClipping(this);
|
||||
appear();
|
||||
}
|
||||
|
||||
void CatchBomb::control() {
|
||||
mDisregardReceiver->set44(al::getSensorPos(this, "Body") +
|
||||
al::getSensorRadius(this, "Body") * sead::Vector3f::ey);
|
||||
|
||||
bool isUncap = isUncapNerve();
|
||||
mDisregardReceiver->setEDC(false, false, isUncap);
|
||||
|
||||
if (!al::isNearPlayerH(this, 2000.0f) ||
|
||||
sead::Mathf::abs(al::getPlayerPos(this, 0).y - al::getTrans(this).y) > 200.0f)
|
||||
mPlayerFarCounter += 1;
|
||||
else
|
||||
mPlayerFarCounter = 0;
|
||||
|
||||
if (al::isNerve(this, &NrvCatchBomb.Explode) || al::isNerve(this, &NrvCatchBomb.Hide))
|
||||
return;
|
||||
|
||||
if (al::isInDeathArea(this))
|
||||
tryShiftExplode(false);
|
||||
|
||||
if (mExplodeTimer > 0) {
|
||||
mExplodeTimer--;
|
||||
if (mExplodeTimer == 0)
|
||||
tryShiftExplode(false);
|
||||
}
|
||||
}
|
||||
76
src/Enemy/CatchBomb.h
Normal file
76
src/Enemy/CatchBomb.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#pragma once
|
||||
|
||||
#include <basis/seadTypes.h>
|
||||
#include <math/seadVector.h>
|
||||
|
||||
#include "Library/LiveActor/LiveActor.h"
|
||||
|
||||
namespace al {
|
||||
struct ActorInitInfo;
|
||||
class CollisionPartsFilterSpecialPurpose;
|
||||
class HitSensor;
|
||||
class JointSpringControllerHolder;
|
||||
class SensorMsg;
|
||||
} // namespace al
|
||||
class CapTargetInfo;
|
||||
class DisregardReceiver;
|
||||
class LoopAnimState;
|
||||
|
||||
class CatchBomb : public al::LiveActor {
|
||||
public:
|
||||
CatchBomb(const char* name);
|
||||
void init(const al::ActorInitInfo& info) override;
|
||||
void attackSensor(al::HitSensor* self, al::HitSensor* other) override;
|
||||
bool isEnableExplosion() const;
|
||||
bool tryShiftExplode(bool unused);
|
||||
bool isEnableEnemyAttack() const;
|
||||
void tryShiftAttack();
|
||||
bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
|
||||
al::HitSensor* self) override;
|
||||
bool tryReceiveMsgPushLocal(const al::SensorMsg* message, al::HitSensor* other,
|
||||
al::HitSensor* self);
|
||||
bool isCapReflectNerve() const;
|
||||
bool isUncapNerve() const;
|
||||
void exeWait();
|
||||
void calcGravity();
|
||||
void calcBrake();
|
||||
bool tryShiftFall();
|
||||
bool tryShiftDamageCollisionExplode();
|
||||
void exeFind();
|
||||
bool tryShiftWait();
|
||||
void exeMove();
|
||||
void exeTurn();
|
||||
void exeFall();
|
||||
void exeBack();
|
||||
void exeAttack();
|
||||
void exeCatch();
|
||||
void requestCapHitReaction(const char* reactionName, bool unused);
|
||||
void exePull();
|
||||
bool checkCollisionExplode(const sead::Vector3f& dir);
|
||||
void exeMarch();
|
||||
void exeExplode();
|
||||
void exeHide();
|
||||
void exeAppear();
|
||||
void exeThrow();
|
||||
void initThrow(const al::ActorInitInfo& info);
|
||||
void appearThrow(const sead::Vector3f& pos, const sead::Vector3f& vel);
|
||||
void control() override;
|
||||
|
||||
private:
|
||||
LoopAnimState* mCatchState = nullptr;
|
||||
al::LiveActor* mCap = nullptr;
|
||||
sead::Vector3f _118 = sead::Vector3f::zero;
|
||||
bool mIsRevival = false;
|
||||
sead::Vector3f mSpawnPos = {0.0f, 0.0f, 0.0f};
|
||||
s32 mExplodeTimer = 0;
|
||||
CapTargetInfo* mCapTargetInfo = nullptr;
|
||||
al::CollisionPartsFilterSpecialPurpose* mCollisionPartsFilter = nullptr;
|
||||
u32 mPlayerFarCounter = 0;
|
||||
bool mIsFirstWait = true;
|
||||
al::JointSpringControllerHolder* mJointSpringControllerHolder = nullptr;
|
||||
sead::Vector3f mTurnTarget;
|
||||
DisregardReceiver* mDisregardReceiver = nullptr;
|
||||
al::LiveActor* mCatchBombGeneratePoint = nullptr;
|
||||
};
|
||||
|
||||
static_assert(sizeof(CatchBomb) == 0x178);
|
||||
|
|
@ -38,6 +38,7 @@
|
|||
#include "Boss/BossForest/BossForestWander.h"
|
||||
#include "Boss/Mofumofu/MofumofuScrap.h"
|
||||
#include "Enemy/Bubble.h"
|
||||
#include "Enemy/CatchBomb.h"
|
||||
#include "Enemy/Gamane.h"
|
||||
#include "Enemy/KaronWing.h"
|
||||
#include "Enemy/Kuribo2D.h"
|
||||
|
|
@ -204,7 +205,7 @@ const al::NameToCreator<al::ActorCreatorFunction> sProjectActorFactoryEntries[]
|
|||
{"CarSandWorld", nullptr},
|
||||
{"CarWatcher", nullptr},
|
||||
{"CardboardBox", nullptr},
|
||||
{"CatchBomb", nullptr},
|
||||
{"CatchBomb", al::createActorFunction<CatchBomb>},
|
||||
{"Chair", nullptr},
|
||||
{"CheckpointFlag", nullptr},
|
||||
{"ChorobonHolder", nullptr},
|
||||
|
|
|
|||
Loading…
Reference in a new issue