| 1 | #include "Enemy/Gamane.h" |
| 2 | |
| 3 | #include <math/seadVector.h> |
| 4 | |
| 5 | #include "Library/Collision/KCollisionServer.h" |
| 6 | #include "Library/Effect/EffectSystemInfo.h" |
| 7 | #include "Library/Item/ItemUtil.h" |
| 8 | #include "Library/LiveActor/ActorActionFunction.h" |
| 9 | #include "Library/LiveActor/ActorAnimFunction.h" |
| 10 | #include "Library/LiveActor/ActorAreaFunction.h" |
| 11 | #include "Library/LiveActor/ActorClippingFunction.h" |
| 12 | #include "Library/LiveActor/ActorCollisionFunction.h" |
| 13 | #include "Library/LiveActor/ActorInitUtil.h" |
| 14 | #include "Library/LiveActor/ActorModelFunction.h" |
| 15 | #include "Library/LiveActor/ActorMovementFunction.h" |
| 16 | #include "Library/LiveActor/ActorPoseUtil.h" |
| 17 | #include "Library/LiveActor/ActorSensorUtil.h" |
| 18 | #include "Library/Math/MathUtil.h" |
| 19 | #include "Library/Movement/EnemyStateBlowDown.h" |
| 20 | #include "Library/Nerve/NerveSetupUtil.h" |
| 21 | #include "Library/Nerve/NerveUtil.h" |
| 22 | #include "Library/Player/PlayerUtil.h" |
| 23 | #include "Library/Shadow/ActorShadowUtil.h" |
| 24 | |
| 25 | #include "Enemy/EnemyStateHackStart.h" |
| 26 | #include "Enemy/EnemyStateSwoon.h" |
| 27 | #include "Enemy/GamaneBullet.h" |
| 28 | #include "Enemy/GamaneHackState.h" |
| 29 | #include "Enemy/HackerDepthShadowMapCtrl.h" |
| 30 | #include "Player/HackerJudge.h" |
| 31 | #include "Player/PlayerHackStartShaderCtrl.h" |
| 32 | #include "Util/Hack.h" |
| 33 | #include "Util/ItemUtil.h" |
| 34 | #include "Util/JudgeUtil.h" |
| 35 | #include "Util/SensorMsgFunction.h" |
| 36 | #include "Util/ShadowUtil.h" |
| 37 | |
| 38 | namespace { |
| 39 | NERVE_IMPL(Gamane, Wait) |
| 40 | NERVE_IMPL(Gamane, Find) |
| 41 | NERVE_IMPL(Gamane, Runaway) |
| 42 | NERVE_IMPL(Gamane, Fall) |
| 43 | NERVE_IMPL(Gamane, Land) |
| 44 | NERVE_IMPL(Gamane, Swoon) |
| 45 | NERVE_IMPL(Gamane, HackStart) |
| 46 | NERVE_IMPL(Gamane, Hack) |
| 47 | NERVE_IMPL(Gamane, Trampled) |
| 48 | NERVE_IMPL(Gamane, PressDown) |
| 49 | NERVE_IMPL(Gamane, BlowDown) |
| 50 | |
| 51 | NERVES_MAKE_NOSTRUCT(Gamane, Land) |
| 52 | NERVES_MAKE_STRUCT(Gamane, Wait, Swoon, Hack, BlowDown, HackStart, Trampled, PressDown, Fall, Find, |
| 53 | Runaway) |
| 54 | } // namespace |
| 55 | |
| 56 | static al::EnemyStateBlowDownParam gEnemyStateBlowDownParam = |
| 57 | al::EnemyStateBlowDownParam("BlowDown" , 18.0f, 35.0f, 1.0f, 0.98f, 120, true); |
| 58 | |
| 59 | static PlayerHackStartShaderParam gPlayerHackStartShaderParam = |
| 60 | PlayerHackStartShaderParam(false, 300.0f, 10, 20); |
| 61 | |
| 62 | static EnemyStateSwoonInitParam gEnemyStateSwoonInitParam = EnemyStateSwoonInitParam( |
| 63 | "SwoonStart" , "Swoon" , "SwoonEnd" , nullptr, "SwoonStartFall" , "SwoonStartLand" ); |
| 64 | |
| 65 | Gamane::Gamane(const char* name) : al::LiveActor(name) {} |
| 66 | |
| 67 | void Gamane::init(const al::ActorInitInfo& initInfo) { |
| 68 | al::initActorWithArchiveName(actor: this, initInfo, archiveName: "Gamane" , suffix: nullptr); |
| 69 | al::initNerve(actor: this, nerve: &NrvGamane.Wait, maxStates: 5); |
| 70 | mCapTargetInfo = rs::createCapTargetInfo(this, nullptr); |
| 71 | |
| 72 | mStateSwoon = new EnemyStateSwoon(this, "SwoonStart" , "Swoon" , "SwoonEnd" , false, true); |
| 73 | |
| 74 | gEnemyStateSwoonInitParam.swoonDuration = 180; |
| 75 | gEnemyStateSwoonInitParam.hitReactionAnimName = "着地" ; |
| 76 | mStateSwoon->initParams(initParam: gEnemyStateSwoonInitParam); |
| 77 | mStateSwoon->enableLockOnDelay(hasLockOnDelay: true); |
| 78 | |
| 79 | al::initNerveState(user: this, state: mStateSwoon, nerve: &NrvGamane.Swoon, hostName: "気絶" ); |
| 80 | |
| 81 | mHackState = new GamaneHackState(this); |
| 82 | al::initNerveState(user: this, state: mHackState, nerve: &NrvGamane.Hack, hostName: "憑依" ); |
| 83 | mHackState->initialize(info: initInfo); |
| 84 | |
| 85 | mStateBlowDown = new al::EnemyStateBlowDown(this, &gEnemyStateBlowDownParam, "吹き飛び状態" ); |
| 86 | al::initNerveState(user: this, state: mStateBlowDown, nerve: &NrvGamane.BlowDown, hostName: "吹き飛び" ); |
| 87 | |
| 88 | mJudgeNormalFall = new HackerJudgeNormalFall(this, 5); |
| 89 | |
| 90 | mCollisionPartsFilter = new al::CollisionPartsFilterSpecialPurpose("MoveLimit" ); |
| 91 | al::setColliderFilterCollisionParts(this, mCollisionPartsFilter); |
| 92 | |
| 93 | mStateHackStart = new EnemyStateHackStart(this, nullptr, &gPlayerHackStartShaderParam); |
| 94 | al::initNerveState(user: this, state: mStateHackStart, nerve: &NrvGamane.HackStart, hostName: "ひょうい開始" ); |
| 95 | |
| 96 | al::setMaterialProgrammable(this); |
| 97 | mMaterialIndex = al::getMaterialIndex(actor: this, "TransMT" ); |
| 98 | mShadowMaskIntensity = al::getShadowMaskIntensity(actor: this, maskName: "シャドウマスク" ); |
| 99 | al::hideShadowMask(actor: this); |
| 100 | |
| 101 | al::startVisAnim(this, "Off" ); |
| 102 | al::startVisAnim(this, "CapOff" ); |
| 103 | al::startMtpAnim(this, "CapOff" ); |
| 104 | al::setModelMaterialParameterF32(actor: this, mMaterialIndex, "const_single0" , 1.0f); |
| 105 | makeActorAlive(); |
| 106 | |
| 107 | rs::initHackShadow(this); |
| 108 | mDepthShadowMapCtrl = new HackerDepthShadowMapCtrl(this, "Ground" , 50.0f, 0.3f, 0.5f); |
| 109 | } |
| 110 | |
| 111 | void Gamane::attackSensor(al::HitSensor* self, al::HitSensor* other) { |
| 112 | if (al::isNerve(user: this, nerve: &NrvGamane.PressDown) || al::isNerve(user: this, nerve: &NrvGamane.BlowDown)) |
| 113 | return; |
| 114 | |
| 115 | if (mPlayerHack != nullptr) { |
| 116 | mHackState->attackSensor(self, other); |
| 117 | return; |
| 118 | } |
| 119 | |
| 120 | if (al::isSensorEnemyBody(self) && al::isSensorEnemyBody(other)) |
| 121 | al::sendMsgPushAndKillVelocityToTarget(this, self, other); |
| 122 | |
| 123 | if (al::isSensorEnemyBody(self)) { |
| 124 | al::sendMsgPush(receiver: other, sender: self); |
| 125 | rs::sendMsgPushToPlayer(source: other, target: self); |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | bool Gamane::receiveMsg(const al::SensorMsg* message, al::HitSensor* other, al::HitSensor* self) { |
| 130 | if ((!al::isSensorEnemyBody(self) || al::isNerve(user: this, nerve: &NrvGamane.PressDown) || |
| 131 | al::isNerve(user: this, nerve: &NrvGamane.BlowDown)) && |
| 132 | (al::isMsgPlayerDisregard(msg: message) || rs::isMsgPlayerDisregardHomingAttack(message) || |
| 133 | rs::isMsgPlayerDisregardTargetMarker(message))) |
| 134 | return true; |
| 135 | |
| 136 | if (al::isNerve(user: this, nerve: &NrvGamane.PressDown)) |
| 137 | return false; |
| 138 | |
| 139 | if (al::isNerve(user: this, nerve: &NrvGamane.BlowDown)) |
| 140 | return false; |
| 141 | |
| 142 | if (rs::tryReceiveMsgInitCapTargetAndSetCapTargetInfo(message, mCapTargetInfo)) |
| 143 | return true; |
| 144 | |
| 145 | if (!al::isNerve(user: this, nerve: &NrvGamane.Hack) && !al::isNerve(user: this, nerve: &NrvGamane.HackStart) && |
| 146 | !al::isNerve(user: this, nerve: &NrvGamane.Swoon)) { |
| 147 | if (rs::isMsgCapEnableLockOn(message) || rs::isMsgCapCancelLockOn(message) || |
| 148 | mStateSwoon->tryReceiveMsgStartLockOn(message)) |
| 149 | return true; |
| 150 | if (mStateSwoon->tryReceiveMsgStartHack(message)) { |
| 151 | startHack(message, other, self); |
| 152 | al::setNerve(user: this, nerve: &NrvGamane.HackStart); |
| 153 | return true; |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | if (al::isNerve(user: this, nerve: &NrvGamane.Swoon)) { |
| 158 | if (mStateSwoon->tryReceiveMsgEnableLockOn(message)) |
| 159 | return true; |
| 160 | if (mStateSwoon->tryReceiveMsgStartHack(message)) { |
| 161 | startHack(message, other, self); |
| 162 | al::setNerve(user: this, nerve: &NrvGamane.HackStart); |
| 163 | return true; |
| 164 | } |
| 165 | if (mStateSwoon->tryReceiveMsgEndSwoon(message)) |
| 166 | return true; |
| 167 | } |
| 168 | |
| 169 | if (mPlayerHack != nullptr) { |
| 170 | if (rs::isMsgHackMarioCheckpointFlagWarp(message)) { |
| 171 | rs::endHack(&mPlayerHack); |
| 172 | rs::endHackShadow(this); |
| 173 | al::startVisAnim(this, "CapOff" ); |
| 174 | al::startMtpAnim(this, "CapOff" ); |
| 175 | al::setColliderFilterCollisionParts(this, mCollisionPartsFilter); |
| 176 | return true; |
| 177 | } |
| 178 | |
| 179 | bool result = mHackState->receiveMsg(message, other, self); |
| 180 | if (mHackState->isHackEnd()) { |
| 181 | mPlayerHack = nullptr; |
| 182 | rs::endHackShadow(this); |
| 183 | al::startVisAnim(this, "CapOff" ); |
| 184 | al::startMtpAnim(this, "CapOff" ); |
| 185 | al::setColliderFilterCollisionParts(this, mCollisionPartsFilter); |
| 186 | al::setNerve(user: this, nerve: &NrvGamane.Swoon); |
| 187 | } |
| 188 | |
| 189 | return result; |
| 190 | } |
| 191 | |
| 192 | if ((al::isSensorEnemyBody(other) || al::isSensorMapObj(other)) && |
| 193 | al::tryReceiveMsgPushAndAddVelocity(this, message, other, self, 3.0f)) |
| 194 | return true; |
| 195 | |
| 196 | if (al::isMsgPlayerTrampleReflect(msg: message) || rs::isMsgSenobiTrample(message)) { |
| 197 | rs::requestHitReactionToAttacker(message, self, other); |
| 198 | if (mCoinsLeft > 0) { |
| 199 | rs::tryAppearMultiCoinFromObj(actor: this, sensor: al::getHitSensor(this, "Body" ), step: 0, offsetAbove: 150.0f); |
| 200 | mCoinsLeft--; |
| 201 | } |
| 202 | endRefract(transitionTime: 25); |
| 203 | if (al::isNerve(user: this, nerve: &NrvGamane.Swoon)) { |
| 204 | mStateSwoon->requestTrampled(); |
| 205 | return true; |
| 206 | } |
| 207 | al::setNerve(user: this, nerve: &NrvGamane.Trampled); |
| 208 | return true; |
| 209 | } |
| 210 | |
| 211 | if (rs::isMsgPressDown(message) && !al::isMsgPlayerTrample(msg: message)) { |
| 212 | rs::requestHitReactionToAttacker(message, self, other); |
| 213 | al::setNerve(user: this, nerve: &NrvGamane.PressDown); |
| 214 | return true; |
| 215 | } |
| 216 | |
| 217 | if (rs::isMsgBlowDown(message)) { |
| 218 | if (rs::isMsgGamaneBullet(message)) { |
| 219 | GamaneBullet* bullet = (GamaneBullet*)al::getSensorHost(other); |
| 220 | if (bullet != nullptr && bullet->getParent() == this) |
| 221 | return false; |
| 222 | } |
| 223 | |
| 224 | rs::requestHitReactionToAttacker(message, self, other); |
| 225 | mStateBlowDown->start(other); |
| 226 | al::setNerve(user: this, nerve: &NrvGamane.BlowDown); |
| 227 | return true; |
| 228 | } |
| 229 | |
| 230 | if (rs::isMsgKillByShineGet(message) || rs::isMsgKillByHomeDemo(message)) { |
| 231 | al::tryKillEmitterAndParticleAll(this); |
| 232 | makeActorDead(); |
| 233 | return true; |
| 234 | } |
| 235 | |
| 236 | if (rs::tryReceiveMsgNpcScareByEnemyIgnoreTargetHack(message, mCapTargetInfo)) |
| 237 | return true; |
| 238 | |
| 239 | if (al::isMsgEnemyAttackFire(msg: message)) { |
| 240 | rs::requestHitReactionToAttacker(message, self, other); |
| 241 | return true; |
| 242 | } |
| 243 | |
| 244 | return false; |
| 245 | } |
| 246 | |
| 247 | void Gamane::control() { |
| 248 | updateRefract(); |
| 249 | if (al::isCollidedGround(this)) { |
| 250 | al::setMaterialCode(actor: this, materialCode: al::getCollidedFloorMaterialCodeName(this)); |
| 251 | al::updateMaterialCodePuddle(actor: this); |
| 252 | } |
| 253 | |
| 254 | if (al::isNerve(user: this, nerve: &NrvGamane.Hack) && mPlayerHack != nullptr) |
| 255 | mDepthShadowMapCtrl->update(playerCollider: nullptr); |
| 256 | |
| 257 | if (!al::isNerve(user: this, nerve: &NrvGamane.Hack) || al::isHideModel(actor: this)) |
| 258 | al::hideSilhouetteModelIfShow(actor: this); |
| 259 | else |
| 260 | al::showSilhouetteModelIfHide(actor: this); |
| 261 | |
| 262 | if (al::isInDeathArea(actor: this) || al::isInWaterArea(actor: this) || |
| 263 | al::isCollidedFloorCode(this, "DamageFire" ) || al::isCollidedFloorCode(this, "Poison" )) { |
| 264 | if (!al::isInDeathArea(actor: this) && mPlayerHack != nullptr) |
| 265 | rs::endHack(&mPlayerHack); |
| 266 | |
| 267 | al::startHitReaction(actor: this, name: "消滅" ); |
| 268 | kill(); |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | void Gamane::endClipped() { |
| 273 | al::LiveActor::endClipped(); |
| 274 | if (mIsStartRefract) |
| 275 | al::hideShadowMask(actor: this); |
| 276 | } |
| 277 | |
| 278 | void Gamane::updateCollider() { |
| 279 | if (al::isNerve(user: this, nerve: &NrvGamane.HackStart)) |
| 280 | return; |
| 281 | |
| 282 | if (al::isNerve(user: this, nerve: &NrvGamane.Hack)) { |
| 283 | sead::Vector3f hackVelocity = mHackState->getVelocity(); |
| 284 | sead::Vector3f velocity = al::getVelocity(actor: this); |
| 285 | velocity += hackVelocity; |
| 286 | al::setVelocity(actor: this, vel: velocity); |
| 287 | mHackState->setVelocity(sead::Vector3f(0.0f, 0.0f, 0.0f)); |
| 288 | } |
| 289 | |
| 290 | al::LiveActor::updateCollider(); |
| 291 | } |
| 292 | |
| 293 | void Gamane::startHack(const al::SensorMsg* message, al::HitSensor* other, al::HitSensor* self) { |
| 294 | al::invalidateClipping(actor: this); |
| 295 | mPlayerHack = mStateHackStart->tryStart(message, other, self); |
| 296 | mHackState->setPlayerHackAction(mPlayerHack); |
| 297 | rs::hideShadowHackCap(mPlayerHack); |
| 298 | rs::setupHackShadow(this); |
| 299 | al::setColliderFilterCollisionParts(this, nullptr); |
| 300 | endRefract(transitionTime: 50); |
| 301 | } |
| 302 | |
| 303 | void Gamane::updateRefract() { |
| 304 | if (mRefractTransitionTime == 0) { |
| 305 | al::setShadowMaskIntensity(actor: this, maskName: "シャドウマスク" , intensity: mShadowMaskIntensity); |
| 306 | return; |
| 307 | } |
| 308 | |
| 309 | f32 refractPercentage = mRefractTransitionTime / 50.0f; |
| 310 | if (mIsStartRefract != false) |
| 311 | refractPercentage = 1.0f - refractPercentage; |
| 312 | al::setModelMaterialParameterF32(actor: this, mMaterialIndex, "const_single0" , refractPercentage); |
| 313 | al::setModelMaterialParameterF32(actor: this, mMaterialIndex, "const_single2" , |
| 314 | refractPercentage * 0.5); |
| 315 | mRefractTransitionTime--; |
| 316 | |
| 317 | if (mPlayerHack != nullptr) |
| 318 | return; |
| 319 | |
| 320 | f32 intensity = al::lerpValue(a: mShadowMaskIntensity, b: 1.0, t: refractPercentage); |
| 321 | al::setShadowMaskIntensity(actor: this, maskName: "シャドウマスク" , intensity); |
| 322 | if (mRefractTransitionTime == 0) { |
| 323 | if (mIsStartRefract) { |
| 324 | al::hideShadowMask(actor: this); |
| 325 | al::validateClipping(actor: this); |
| 326 | } else { |
| 327 | al::startVisAnim(this, "On" ); |
| 328 | al::invalidateClipping(actor: this); |
| 329 | } |
| 330 | } |
| 331 | } |
| 332 | |
| 333 | void Gamane::updateMovement() { |
| 334 | sead::Vector3f gravityDir = sead::Vector3f(0.0f, 0.0f, 0.0f); |
| 335 | al::calcGravityDir(gravity: &gravityDir, actor: this); |
| 336 | |
| 337 | if (al::isOnGround(this, 0)) |
| 338 | al::scaleVelocityDirection(actor: this, direction: gravityDir, factor: 0.0f); |
| 339 | |
| 340 | al::scaleVelocityParallelVertical(actor: this, direction: gravityDir, parallel: 0.99f, vertical: 0.1f); |
| 341 | al::addVelocityToGravityNaturalOrFittedGround(actor: this, force: 1.5f); |
| 342 | } |
| 343 | |
| 344 | void Gamane::startRefract(s32 transitionTime) { |
| 345 | if (mRefractTransitionTime < 1 && !mIsStartRefract) { |
| 346 | mRefractTransitionTime = transitionTime; |
| 347 | mIsStartRefract = true; |
| 348 | al::startVisAnim(this, "Off" ); |
| 349 | } |
| 350 | } |
| 351 | |
| 352 | void Gamane::endRefract(s32 transitionTime) { |
| 353 | if (mRefractTransitionTime < 1 && mIsStartRefract) { |
| 354 | mRefractTransitionTime = transitionTime; |
| 355 | mIsStartRefract = false; |
| 356 | al::showShadowMask(actor: this); |
| 357 | } |
| 358 | } |
| 359 | |
| 360 | void Gamane::exeWait() { |
| 361 | if (al::isFirstStep(user: this)) { |
| 362 | al::setVelocityZero(this); |
| 363 | al::startAction(actor: this, actionName: "Wait" ); |
| 364 | rs::resetJudge(judge: mJudgeNormalFall); |
| 365 | } |
| 366 | |
| 367 | updateMovement(); |
| 368 | |
| 369 | if (rs::updateJudgeAndResult(judge: mJudgeNormalFall)) { |
| 370 | al::setNerve(user: this, nerve: &NrvGamane.Fall); |
| 371 | return; |
| 372 | } |
| 373 | |
| 374 | if (al::isStep(user: this, step: 180)) |
| 375 | startRefract(transitionTime: 50); |
| 376 | |
| 377 | if (al::calcDistanceH(actor: this, target: al::getPlayerActor(this, 0)) < 1000.0f) |
| 378 | al::setNerve(user: this, nerve: &NrvGamane.Find); |
| 379 | } |
| 380 | |
| 381 | void Gamane::exeFind() { |
| 382 | if (al::isFirstStep(user: this)) { |
| 383 | al::startAction(actor: this, actionName: "Find" ); |
| 384 | al::setVelocityZero(this); |
| 385 | al::faceToTarget(actor: this, target: al::getPlayerActor(this, 0)); |
| 386 | endRefract(transitionTime: 50); |
| 387 | } |
| 388 | |
| 389 | updateMovement(); |
| 390 | |
| 391 | if (al::isActionEnd(actor: this)) { |
| 392 | al::startVisAnim(this, "On" ); |
| 393 | al::setNerve(user: this, nerve: &NrvGamane.Runaway); |
| 394 | } |
| 395 | } |
| 396 | |
| 397 | void Gamane::exeRunaway() { |
| 398 | if (al::isFirstStep(user: this)) { |
| 399 | al::startAction(actor: this, actionName: "Run" ); |
| 400 | rs::resetJudge(judge: mJudgeNormalFall); |
| 401 | mRunAwayRefractDelay = 0; |
| 402 | } |
| 403 | |
| 404 | sead::Vector3f dirToActor; |
| 405 | al::calcDirToActorH(out: &dirToActor, actor: this, target: al::getPlayerActor(this, 0)); |
| 406 | dirToActor.negate(); |
| 407 | al::turnToDirection(actor: this, dir: dirToActor, deg: 4.0f); |
| 408 | |
| 409 | sead::Vector3f quatFront; |
| 410 | al::calcQuatFront(front: &quatFront, actor: this); |
| 411 | al::addVelocityToDirection(actor: this, dir: quatFront, force: 0.4f); |
| 412 | |
| 413 | sead::Vector3f gravityDir = sead::Vector3f(0.0f, 0.0f, 0.0f); |
| 414 | al::calcGravityDir(gravity: &gravityDir, actor: this); |
| 415 | |
| 416 | if (al::isOnGround(this, 0)) |
| 417 | al::scaleVelocityDirection(actor: this, direction: gravityDir, factor: 0.0f); |
| 418 | |
| 419 | al::scaleVelocityParallelVertical(actor: this, direction: gravityDir, parallel: 0.99f, vertical: 0.95f); |
| 420 | al::addVelocityToGravityNaturalOrFittedGround(actor: this, force: 1.8f); |
| 421 | |
| 422 | if (!mIsStartRefract) |
| 423 | mRunAwayRefractDelay++; |
| 424 | |
| 425 | if (mRunAwayRefractDelay == 240) { |
| 426 | startRefract(transitionTime: 50); |
| 427 | mRunAwayRefractDelay = 0; |
| 428 | } |
| 429 | |
| 430 | if (rs::updateJudgeAndResult(judge: mJudgeNormalFall)) { |
| 431 | al::setNerve(user: this, nerve: &NrvGamane.Fall); |
| 432 | return; |
| 433 | } |
| 434 | |
| 435 | if (al::calcDistanceH(actor: this, target: al::getPlayerActor(this, 0)) > 1500.0f) |
| 436 | al::setNerve(user: this, nerve: &NrvGamane.Wait); |
| 437 | } |
| 438 | |
| 439 | void Gamane::exeFall() { |
| 440 | if (al::isFirstStep(user: this)) { |
| 441 | al::startAction(actor: this, actionName: "Fall" ); |
| 442 | al::invalidateClipping(actor: this); |
| 443 | } |
| 444 | |
| 445 | al::addVelocityToGravity(actor: this, force: 0.7f); |
| 446 | al::scaleVelocity(actor: this, factor: 0.99f); |
| 447 | |
| 448 | if (al::isOnGround(this, 0)) { |
| 449 | al::reboundVelocityFromCollision(actor: this, reboundStrength: 0.0f, reboundMin: 0.0f, friction: 1.0f); |
| 450 | al::setNerve(user: this, nerve: &Land); |
| 451 | al::startHitReaction(actor: this, name: "着地" ); |
| 452 | } |
| 453 | } |
| 454 | |
| 455 | void Gamane::exeLand() { |
| 456 | if (al::isFirstStep(user: this)) { |
| 457 | al::startAction(actor: this, actionName: "Land" ); |
| 458 | al::setVelocityZero(this); |
| 459 | } |
| 460 | |
| 461 | updateMovement(); |
| 462 | |
| 463 | if (al::isActionEnd(actor: this)) |
| 464 | al::setNerve(user: this, nerve: &NrvGamane.Wait); |
| 465 | } |
| 466 | |
| 467 | void Gamane::exeSwoon() { |
| 468 | if (al::isFirstStep(user: this)) { |
| 469 | sead::Vector3f velocity = sead::Vector3f(0.0f, 25.0f, 0.0f); |
| 470 | sead::Vector3f frontDir = sead::Vector3f::ez; |
| 471 | al::calcFrontDir(front: &frontDir, actor: this); |
| 472 | velocity += frontDir * 0.0f; |
| 473 | al::setVelocity(actor: this, vel: velocity); |
| 474 | mIsKeepSwoon = false; |
| 475 | } |
| 476 | |
| 477 | updateMovement(); |
| 478 | |
| 479 | if (al::updateNerveState(user: this) && !mIsKeepSwoon) { |
| 480 | if (al::calcDistanceH(actor: this, target: al::getPlayerActor(this, 0)) < 1000.0f) |
| 481 | al::setNerve(user: this, nerve: &NrvGamane.Runaway); |
| 482 | else |
| 483 | al::setNerve(user: this, nerve: &NrvGamane.Wait); |
| 484 | } |
| 485 | } |
| 486 | |
| 487 | void Gamane::exeHackStart() { |
| 488 | if (mStateHackStart->isHackStart() && mStateHackStart->calcHackStartNerveRate() == 0.0f) { |
| 489 | al::startVisAnim(this, "CapOn" ); |
| 490 | al::startMtpAnim(this, "CapOn" ); |
| 491 | } |
| 492 | |
| 493 | updateMovement(); |
| 494 | |
| 495 | if (al::updateNerveState(user: this)) { |
| 496 | al::startVisAnim(this, "On" ); |
| 497 | al::setNerve(user: this, nerve: &NrvGamane.Hack); |
| 498 | } |
| 499 | } |
| 500 | |
| 501 | void Gamane::exeHack() { |
| 502 | al::updateNerveState(user: this); |
| 503 | if (mCoinsLeft > 0 && mHackCoinAppearCounter == 0) { |
| 504 | rs::tryAppearMultiCoinFromObj(actor: this, sensor: al::getHitSensor(this, "Body" ), step: 0, offsetAbove: 150.0f); |
| 505 | mCoinsLeft--; |
| 506 | } |
| 507 | |
| 508 | mHackCoinAppearCounter = al::modi(a: (mHackCoinAppearCounter++ + 1) + 6, b: 6); |
| 509 | } |
| 510 | |
| 511 | void Gamane::exeTrampled() { |
| 512 | if (al::isFirstStep(user: this)) { |
| 513 | al::setVelocityZero(this); |
| 514 | al::startAction(actor: this, actionName: "Trampled" ); |
| 515 | } |
| 516 | |
| 517 | updateMovement(); |
| 518 | |
| 519 | if (al::isActionEnd(actor: this)) |
| 520 | al::setNerve(user: this, nerve: &NrvGamane.Runaway); |
| 521 | } |
| 522 | |
| 523 | void Gamane::exePressDown() { |
| 524 | if (al::isFirstStep(user: this)) { |
| 525 | al::startAction(actor: this, actionName: "PressDown" ); |
| 526 | al::invalidateClipping(actor: this); |
| 527 | endRefract(transitionTime: 50); |
| 528 | } |
| 529 | |
| 530 | updateMovement(); |
| 531 | |
| 532 | if (al::isActionEnd(actor: this)) { |
| 533 | al::startHitReaction(actor: this, name: "死亡" ); |
| 534 | al::appearItemTiming(actor: this, "倒す" ); |
| 535 | kill(); |
| 536 | } |
| 537 | } |
| 538 | |
| 539 | void Gamane::exeBlowDown() { |
| 540 | if (al::isFirstStep(user: this)) |
| 541 | endRefract(transitionTime: 50); |
| 542 | |
| 543 | if (al::updateNerveState(user: this)) { |
| 544 | al::startHitReaction(actor: this, name: "死亡" ); |
| 545 | al::appearItemTiming(actor: this, "倒す" ); |
| 546 | kill(); |
| 547 | } |
| 548 | } |
| 549 | |