diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 64adb455..954befa5 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -1178,7 +1178,7 @@ checkSlope__11dAcEnBase_cFRC7mVec3_cRsRsf = .text:0x80030030; // type:function s fn_800301b0__11dAcEnBase_cFRC7mVec3_c4mAngbf = .text:0x800301B0; // type:function size:0x1D4 fn_80030390 = .text:0x80030390; // type:function size:0x64 fn_80030400__11dAcEnBase_cFRQ23m3d5mdl_cUcbUc = .text:0x80030400; // type:function size:0x168 -fn_80030570 = .text:0x80030570; // type:function size:0x144 +fn_80030570__11dAcEnBase_cFRQ23m3d5mdl_cUcf = .text:0x80030570; // type:function size:0x144 fn_800306C0 = .text:0x800306C0; // type:function size:0x10 fn_800306D0__11dAcEnBase_cFv = .text:0x800306D0; // type:function size:0x24 fn_80030700__11dAcEnBase_cFv = .text:0x80030700; // type:function size:0x24 @@ -3718,7 +3718,7 @@ fn_800A9860 = .text:0x800A9860; // type:function size:0x50 getRemainingDistanceOnSegment__15ActorOnRail_ExtCFv = .text:0x800A98B0; // type:function size:0x58 getNextPointIndex__15ActorOnRail_ExtCFl = .text:0x800A9910; // type:function size:0x48 getNextPointIndex__15ActorOnRail_ExtCFv = .text:0x800A9960; // type:function size:0x8 -fn_800A9970 = .text:0x800A9970; // type:function size:0x58 +getNextPointIndex2__15ActorOnRail_ExtCFv = .text:0x800A9970; // type:function size:0x58 getClosestXZPoint__15ActorOnRail_ExtCFRC7mVec3_c = .text:0x800A99D0; // type:function size:0xE0 setSegment__15ActorOnRail_ExtFlf = .text:0x800A9AB0; // type:function size:0x50 checkPosInAREA = .text:0x800A9B00; // type:function size:0xC4 @@ -17268,7 +17268,7 @@ addCalcPos__4cLibFP7mVec3_cRC7mVec3_cfff = .text:0x802DFD90; // type:function si addCalcPosXZ__4cLibFP7mVec3_cRC7mVec3_cfff = .text:0x802DFFD0; // type:function size:0x1B8 addCalcPos2__4cLibFP7mVec3_cRC7mVec3_cff = .text:0x802E0190; // type:function size:0x13C cLib__addCalcPosXZ2 = .text:0x802E02D0; // type:function size:0xF8 -cLib__chasePos = .text:0x802E03D0; // type:function size:0x174 +chasePos__4cLibFR7mVec3_cR7mVec3_cf = .text:0x802E03D0; // type:function size:0x174 chasePosXZ__4cLibFR7mVec3_cR7mVec3_cf = .text:0x802E0550; // type:function size:0x124 targetAngleY__4cLibFRC7mVec3_cRC7mVec3_c = .text:0x802E0680; // type:function size:0x1C targetAngleX__4cLibFRC7mVec3_cRC7mVec3_c = .text:0x802E06A0; // type:function size:0x68 diff --git a/include/c/c_lib.h b/include/c/c_lib.h index be7b0d5e..c31d9bf9 100644 --- a/include/c/c_lib.h +++ b/include/c/c_lib.h @@ -12,6 +12,7 @@ s16 offsetPos(mVec3_c &target, const mVec3_c &v1, s16 angle, const mVec3_c &v2); void addCalcPos2(mVec3_c *src, const mVec3_c &target, f32 scale, f32 maxStep); f32 addCalcPosXZ(mVec3_c *src, const mVec3_c &target, f32 scale, f32 maxStep, f32 minStep); f32 addCalcPos(mVec3_c *src, const mVec3_c &target, f32 scale, f32 maxStep, f32 minStep); +bool chasePos(mVec3_c &, mVec3_c &, f32); bool chasePosXZ(mVec3_c &, mVec3_c &, f32); // made up name diff --git a/include/d/a/e/d_a_e_ks.h b/include/d/a/e/d_a_e_ks.h index 73822fae..d63150e8 100644 --- a/include/d/a/e/d_a_e_ks.h +++ b/include/d/a/e/d_a_e_ks.h @@ -186,7 +186,9 @@ private: /* 0xC48 */ f32 field_0xC48; /* 0xC4C */ u8 _0xC4C[0xC70 - 0xC4C]; /* 0xC70 */ f32 field_0xC70; - /* 0xC74 */ u8 _0xC74[0xCE0 - 0xC74]; + /* 0xC74 */ u8 _0xC74[0xC90 - 0xC74]; + /* 0xC90 */ f32 field_0xC90; + /* 0xC94 */ u8 _0xC94[0xCE0 - 0xC94]; /* 0xCE0 */ f32 field_0xCE0; /* 0xCE4 */ f32 field_0xCE4; /* 0xCE8 */ u8 _0xCE8[0xCF8 - 0xCE8]; @@ -232,7 +234,7 @@ private: /* 0xD74 */ s16 field_0xD74; /* 0xD76 */ s16 field_0xD76; /* 0xD78 */ s16 mBlinkTimer; - /* 0xD7A */ s16 field_0xD7A; + /* 0xD7A */ u16 field_0xD7A; /* 0xD7C */ s16 field_0xD7C; /* 0xD7E */ s16 mSqueakSoundTimer; /* 0xD80 */ s16 mStunSoundTimer; @@ -252,7 +254,7 @@ private: /* 0xD9C */ s16 field_0xD9C; /* 0xD9E */ s16 field_0xD9E; /* 0xDA0 */ s16 field_0xDA0; - /* 0xDA2 */ u8 _0xDA2[0xDA4 - 0xDA2]; + /* 0xDA2 */ s16 field_0xDA2; /* 0xDA4 */ u8 field_0xDA4; /* 0xDA5 */ u8 field_0xDA5; /* 0xDA6 */ u8 field_0xDA6; diff --git a/include/d/a/e/d_a_en_base.h b/include/d/a/e/d_a_en_base.h index 3dc5d670..adbc1d0c 100644 --- a/include/d/a/e/d_a_en_base.h +++ b/include/d/a/e/d_a_en_base.h @@ -51,12 +51,14 @@ public: /* 0x33C */ u32 mInteractionFlags; /* 0x340 */ u16 field_0x338; /* 0x342 */ u16 mHealth; - /* 0x344 */ u8 _344[0x358 - 0x344]; + /* 0x344 */ u8 _0x344[0x346 - 0x344]; + /* 0x346 */ u8 field_0x346; + /* 0x347 */ u8 _0x347[0x358 - 0x347]; /* 0x358 */ mVec3_c mFinalBlowPosition; - /* 0x364 */ u8 _364[0x374 - 0x364]; + /* 0x364 */ u8 _0x364[0x374 - 0x364]; /* 0x374 */ dAcEnData *mpEnemyData; - bool checkInteractionFlags(u32 mask) { + bool checkInteractionFlags(u32 mask) const { return mInteractionFlags & mask; } void setInteractionFlags(u32 flag) { @@ -65,6 +67,9 @@ public: void resetInteractionFlags(u32 flag) { mInteractionFlags &= ~flag; } + void setFinalBlowPosition(const mVec3_c &v) { + mFinalBlowPosition = v; + } dAcBomb_c *getBombWithinRadius(f32 radius); // fn_8002f700 @@ -78,6 +83,7 @@ public: // Returns 0-3 based on collision int fn_800301b0(const mVec3_c &pos, mAng ang, bool, f32); void fn_80030400(m3d::mdl_c &, u8, bool, u8); + bool fn_80030570(m3d::mdl_c &, u8, f32); // lighting related void fn_800306D0(); void fn_80030700(); dAcObjBase_c *targetPlayerOrScrapper(f32 biasToScrapper); diff --git a/include/toBeSorted/d_path.h b/include/toBeSorted/d_path.h index 56856008..6337f5b4 100644 --- a/include/toBeSorted/d_path.h +++ b/include/toBeSorted/d_path.h @@ -59,6 +59,11 @@ public: return mpPathPtr->pointCount; } + s32 getLastPointIdx() const { + s32 pnt = getNumPoints() - 1; + return pnt >= 0 ? pnt : 0; + } + bool initWithPathId(s32 pathId, s32 roomId, bool pathSubtype); bool initWithPathIndex(s32 pathIndex, s32 roomId, bool pathSubtype); @@ -138,10 +143,18 @@ public: mSpeed = speed; } + f32 getSpeed() const { + return mSpeed; + } + void getDirection(mVec3_c &result) { mPath.getDirection(mSegmentIndex, mSegmentTime, result); } + const Vec *getPoint(s32 idx) const { + return mPath.getPoint(idx); + } + bool checkFlag(u32 flags) const { return (mFlags & flags) != 0; } @@ -154,6 +167,11 @@ public: mFlags |= flags; } + const dPath_c &getPath() const { + return mPath; + } + s32 getNextPointIndex2() const; + private: s32 getNextPointIndex(s32 point) const; s32 getNextPointIndex() const; diff --git a/src/REL/d/a/e/d_a_e_ks.cpp b/src/REL/d/a/e/d_a_e_ks.cpp index d6bca526..df30c244 100644 --- a/src/REL/d/a/e/d_a_e_ks.cpp +++ b/src/REL/d/a/e/d_a_e_ks.cpp @@ -7,6 +7,7 @@ #include "d/a/d_a_itembase.h" #include "d/a/d_a_player.h" #include "d/a/obj/d_a_obj_base.h" +#include "d/col/bg/d_bg_pc.h" #include "d/col/bg/d_bg_s.h" #include "d/col/bg/d_bg_s_gnd_chk.h" #include "d/col/bg/d_bg_s_lin_chk.h" @@ -36,9 +37,11 @@ #include "nw4r/g3d/res/g3d_resfile.h" #include "nw4r/g3d/res/g3d_resmdl.h" #include "nw4r/g3d/res/g3d_resnode.h" +#include "nw4r/math/math_arithmetic.h" #include "s/s_Math.h" #include "toBeSorted/attention.h" #include "toBeSorted/d_emitter.h" +#include "toBeSorted/d_path.h" #include "toBeSorted/event_manager.h" #include "toBeSorted/time_area_mgr.h" @@ -827,7 +830,6 @@ void dAcEKs_c::fn_155_2270() { field_0xDC5--; } else { if (dAcPy_c::GetLink()->checkCurrentAction(/* SHIELD_BASH*/ 73)) { - ; mWorldMtx.multVecSR(mVec3_c(0, 0, -250), field_0xC1C); mTargetPos += field_0xC1C; field_0xDC5 = 20; @@ -2327,36 +2329,814 @@ void dAcEKs_c::executeState_Chase() { } void dAcEKs_c::finalizeState_Chase() {} -void dAcEKs_c::initializeState_ChaseAttack() {} -void dAcEKs_c::executeState_ChaseAttack() {} -void dAcEKs_c::finalizeState_ChaseAttack() {} +void dAcEKs_c::initializeState_ChaseAttack() { + setBlink(EKS_TEXPAT_BLINK2); + field_0xDA5 = 1; + fn_155_3BE0(mVec3_c(0, 100, 200)); + setPitchYawToPoint(mTargetPos); + field_0xD5A = 0; + field_0xDAB = 0; + startSound(SE_EKs_V_ATTACK); + field_0xD9C = cM::rndF(65536); + if (mType == EKS_ELECTRIC) { + fn_155_3E90(); + field_0xDA9 = 0; + field_0xD60 = 0; + } +} +void dAcEKs_c::executeState_ChaseAttack() { + mMdl.play(); + if (!mAnmTexPat.isStop(0)) { + mAnmTexPat.play(); + } + fn_155_3BE0(mVec3_c(0, 100, 200)); + adjustTargetGnd(); + setPitchYawToPoint(mTargetPos); + if (field_0xD9A > 0) { + field_0xCE0 = 0.f; + } else { + sLib::addCalcScaledDiff(&field_0xCE0, 30, 0.1, 1); + } + cLib::addCalcPos2(&mPosition, mTargetPos, 0.1, field_0xCE0); + sLib::addCalcAngle(mAngle.y.ref(), mYaw_0xC36, 10, 0x71C); + sLib::addCalcAngle(mRotation.y.ref(), mYaw_0xC36, 10, 0x71C); + sLib::addCalcAngle(mRotation.x.ref(), mPitch_0xC34, 12, 0xB6); + clampRotationX(); + field_0xD5A++; + if (field_0xDAB != 0) { + changeState(StateID_Chase); + } else if (field_0xD5A > 8) { + mSph.OnAtSet(); + field_0xDAB = 1; + } +} +void dAcEKs_c::finalizeState_ChaseAttack() { + mSph.ClrAtSet(); + field_0xDAB = 1; + if (mType == EKS_ELECTRIC) { + fn_155_3EC0(); + field_0xDA9 = 1; + } +} -void dAcEKs_c::initializeState_Fighting() {} -void dAcEKs_c::executeState_Fighting() {} +void dAcEKs_c::initializeState_Fighting() { + setAnim("hovering", 1, cM::rndFX(0.2) + 1.f, 0); + if (mCurrentAnmTexPat == EKS_TEXPAT_BLINK2) { + setBlink(EKS_TEXPAT_BLINK3); + field_0xD7A = 0; + } else { + setBlink(EKS_TEXPAT_BLINK1); + field_0xD7A = 17; + } + mBlinkTimer = cM::rndInt(75) + 15; + mSpeed = 0.f; + field_0xC70 = 0.f; + field_0xD6A = cM::rndInt(30) + 15; + if (field_0xDA6 == 0) { + field_0xBC8.set(cM::rndFX(250), cM::rndF(150) + 100.f, cM::rndF(120) + 150.f); + } + adjustTargetGnd(); + adjustTargetRoof(); + fn_155_3BE0(field_0xBC8); + + setPitchYawToPoint(targetPlayerOrScrapper(0)->mPosition + field_0xBEC); + fn_155_1430(); + field_0xDA5 = 1; + field_0xD90 = 3; + field_0xDC5 = 0; + mSqueakSoundTimer = cM::rndInt(20) + 20; + unsetActorProperty(AC_PROP_0x1); + if (dBgS_WtrChk::CheckPos(&mPosition, true, 100, -2000)) { + field_0xD10 = dBgS_WtrChk::GetWaterHeight(); + field_0xDB3 = 1; + } +} +void dAcEKs_c::executeState_Fighting() { + fn_155_3720(field_0xC70, cM::rndFX(0.1) + 1.f); + mMdl.play(); + if (field_0xD7A < (s16)17) { + field_0xD7A++; + } else if (field_0xDA6 != 0) { + if (mCurrentAnmTexPat == EKS_TEXPAT_BLINK2) { + mAnmTexPat.play(); + } else { + playBlinkAnm(); + } + } else { + playBlinkAnm(); + } + soundSqueak(); + fn_155_2270(); +} void dAcEKs_c::finalizeState_Fighting() {} -void dAcEKs_c::initializeState_AttackReady() {} -void dAcEKs_c::executeState_AttackReady() {} -void dAcEKs_c::finalizeState_AttackReady() {} +void dAcEKs_c::initializeState_AttackReady() { + setBlink(EKS_TEXPAT_BLINK2); + mVec3_c v(0, 150, 200); + v += field_0xBC8; + fn_155_3BE0(v); -void dAcEKs_c::initializeState_Attack() {} -void dAcEKs_c::executeState_Attack() {} -void dAcEKs_c::finalizeState_Attack() {} + dAcObjBase_c *pTarget = AttentionManager::GetInstance()->getTargetedActor(); + if (pTarget != this) { + const f32 y = (targetPlayerOrScrapper(0)->mPosition.y + 100.f); + if (field_0xBBC.y > y + 200.f) { + field_0xBBC.y = y + 200.f; + } + } + if (dBgS_ObjLinChk::LineCross(&mPosition, &field_0xBBC, nullptr)) { + field_0xBBC = dBgS_ObjLinChk::GetInstance().GetLinEnd(); + } + mSpeed = 0.f; + field_0xD72 = cM::rndInt(15) + 15; + field_0xC90 = 100.f; + field_0xDA5 = 1; + fn_155_3720(0, 0.7); + if (mType == EKS_ELECTRIC) { + fn_155_3E90(); + field_0xDA9 = 0; + field_0xD60 = 0; + } +} +void dAcEKs_c::executeState_AttackReady() { + f32 f = 10.f; + mMdl.play(); + if (!mAnmTexPat.isStop(0)) { + mAnmTexPat.play(); + } -void dAcEKs_c::initializeState_Damage() {} -void dAcEKs_c::executeState_Damage() {} -void dAcEKs_c::finalizeState_Damage() {} + if (dAcPy_c::GetLink()->isRecovering() || !dAcPy_c::GetLink()->checkFlags0x340(0x100) || + (EventManager::isInEvent() && !EventManager::isInEvent0Or7())) { + if (mType == EKS_ELECTRIC) { + fn_155_3EC0(); + field_0xDA9 = 1; + } + changeState(StateID_Fighting); + return; + } + if (fn_155_3EF0()) { + if (mType == EKS_ELECTRIC) { + fn_155_3EC0(); + field_0xDA9 = 1; + } + changeState(StateID_Fighting); + return; + } + setPitchYawToPoint(targetPlayerOrScrapper(0)->mPosition + field_0xBEC); + sLib::addCalcAngle(mAngle.y.ref(), mYaw_0xC36, 0xc, 0x1555); + sLib::addCalcAngle(mRotation.y.ref(), mYaw_0xC36, 0xc, 0x1555); + sLib::addCalcAngle(mRotation.x.ref(), 0, 0xc, 0x1555); + if (field_0xD9A <= 0) { + sLib::addCalcScaled(&field_0xC90, 0.8, 6.5); + cLib::addCalcPos2(&mPosition, field_0xBBC, 0.1, field_0xC90); + if (std::abs(field_0xC90) < 0.01f) { + fn_155_3720(f, 1.3); + if (--field_0xD72 <= 0) { + changeState(StateID_Attack); + } + } else { + fn_155_3720(0, 0.7); + } + } +} +void dAcEKs_c::finalizeState_AttackReady() { + fn_155_3480(); +} -void dAcEKs_c::initializeState_Stun() {} -void dAcEKs_c::executeState_Stun() {} -void dAcEKs_c::finalizeState_Stun() {} +void dAcEKs_c::initializeState_Attack() { + setAnim("fly", 1.5, cM::rndFX(0.2) + 1.f, 0); + setPitchYawToPoint(targetPlayerOrScrapper(0)->mPosition + field_0xBEC); + fn_155_3BE0(mVec3_c(0, 0, -50)); -void dAcEKs_c::initializeState_WindBlow() {} -void dAcEKs_c::executeState_WindBlow() {} -void dAcEKs_c::finalizeState_WindBlow() {} + /* TODO Probably an inline, but I have no clue what to call it */ + bool b = dAcPy_c::GetLink()->checkActionFlags(0x40000) != 0 && dAcPy_c::GetLink()->checkFlags0x340(0x100); + if (b) { + field_0xBBC.set(dAcPy_c::GetLink()->getHeadTranslation()); + } -void dAcEKs_c::initializeState_PathMove() {} -void dAcEKs_c::executeState_PathMove() {} + field_0xD74 = 15; + field_0xDA5 = 1; + mRotation.x = 0; + startSound(SE_EKs_V_ATTACK); + mSph.OnAtSet(); + mSph.setCenter(mPosition); + if (mType == EKS_ELECTRIC) { + fn_155_3E90(); + field_0xDA9 = 0; + field_0xD60 = 0; + } + field_0xDA2 = 0; +} +void dAcEKs_c::executeState_Attack() { + f32 scale = 25.f; + if (field_0xD9A > 0) { + scale = 0.f; + } + fn_155_3720(scale, cM::rndFX(0.1) + 1.f); + mMdl.play(); + if (!mAnmTexPat.isStop(0)) { + mAnmTexPat.play(); + } + if (dAcPy_c::GetLink()->isRecovering() || !dAcPy_c::GetLink()->checkFlags0x340(0x100) || + (EventManager::isInEvent() && !EventManager::isInEvent0Or7())) { + changeState(StateID_Fighting); + return; + } + if (fn_155_3EF0()) { + changeState(StateID_Fighting); + return; + } + + sLib::addCalcAngle(mRotation.x.ref(), mPitch_0xC34, 12, 0x38E); + if (mSph.ChkAtHit()) { + if (mSph.GetAtFlag0x8() != 0) { + changeState(StateID_Stun); + return; + } + + if (mSph.GetAtActor()->isPlayer()) { + changeState(StateID_Fighting); + return; + } + } + + if (cLib::chasePos(mPosition, field_0xBBC, scale)) { + changeState(StateID_Fighting); + return; + } + + if (ChkHit() && --field_0xD74 <= 0) { + changeState(StateID_Fighting); + return; + } + + if (++field_0xDA2 > 90) { + changeState(StateID_Fighting); + return; + } + + mSph.OnAtSet(); + mSph.moveCenter(mPosition); +} +void dAcEKs_c::finalizeState_Attack() { + mSph.ClrAtSet(); + if (mType == EKS_ELECTRIC) { + fn_155_3EC0(); + field_0xDA9 = 1; + } + field_0xD60 = 40; +} + +void dAcEKs_c::initializeState_Damage() { + if (mHealth == 0) { + setAnim("dead", 4, 1, 0); + mAngle.y = field_0xD96; + mAngle.x = field_0xD98; + } else { + setAnim("hura2", 4, 1, 0); + } + + if (mType == EKS_FIRE) { + field_0xD20 = 0.f; + field_0xD24 = 1.f; + field_0xD28 = mLightInfluence.mScale / (field_0xD5E * 2.f); + } else if (mType == EKS_ELECTRIC) { + field_0xD20 = 0.f; + field_0xD24 = 1.f; + field_0xD28 = mLightInfluence.mScale / (field_0xD5E * 2.f); + } + field_0xDB5 = 1; + field_0x346 = 1; // Part of dAcEnBase_c +} +void dAcEKs_c::executeState_Damage() { + mMdl.play(); + if (mHealth == 0) { + if (field_0xD9A > 0) { + mSpeed = 0; + } + + mRotation.x += field_0xD92; + mRotation.y += field_0xD94; + + if (field_0xD60 > 0) { + field_0xD5E = 0; + field_0xDA9 = 1; + } + if (field_0xD5E > 0) { + field_0xD5E--; + } else { + field_0xDA9 = 1; + } + + if (mAcch.ChkGroundLanding() && field_0xDB5 != 0) { + dJEffManager_c::spawnGroundEffect(mPosition, mPolyAttr0, mPolyAttr1, field_0x1B4, 1, 1, field_0x1B0); + field_0xDB5 = 0; + } + + if (mAcch.ChkGndHit() || mAcch.ChkWallHit(nullptr)) { + field_0xDA9 = 1; + if (dBgS::GetInstance()->GetSpecialCode(mAcch.GetGnd()) == POLY_ATTR_LAVA) { + kill(false); + } else { + kill(true); + } + } else if (mAcch.ChkWaterIn()) { + field_0xDA9 = 1; + kill(false); + } else if (!sLib::calcTimer(&field_0xDBE)) { + field_0xDA9 = 1; + kill(false); + } + + return; + } + + if (std::abs(mSpeed) > 0.01f) { + sLib::addCalcScaled(&mSpeed, 1, 5); + } else { + mSpeed = 0.f; + } + + if (std::abs(mVelocity.y) > 0.01f) { + sLib::addCalcScaled(&mVelocity.y, 1, 5); + } else { + mVelocity.y = 0.f; + } + + if (field_0xDC6 != 0) { + field_0xDC6--; + } else { + field_0x346 = 0; // Part of dAcEnBase_c + changeState(StateID_Fighting); + } +} +void dAcEKs_c::finalizeState_Damage() { + mAngle.x = mRotation.x; + mAngle.y = mRotation.y; + field_0xDBF = 0; +} +void dAcEKs_c::initializeState_Stun() { + setAnim("chance", 1, 1, 0); + setBlink(EKS_TEXPAT_BLINK1); + field_0xD76 = 150; + field_0xDA5 = 0; + mAngle.y = cLib::targetAngleY(dAcPy_c::GetLink()->mPosition, mPosition); + mSpeed = 30.f; + mAcceleration = -2.5f; + field_0xD5C = 5; + mStunSoundTimer = cM::rndInt(20) + 20; + mAcch.SetGroundUpY(0); + field_0xC10.y = 20.f; + field_0xDCC = 0; + if (mType == EKS_FIRE) { + mSph.ClrCo_0x8000(); + } else if (mType == EKS_ELECTRIC) { + fn_155_3EC0(); + } + + unsetActorProperty(AC_PROP_0x1); + + if (mType == EKS_FIRE) { + field_0xD20 = 0.f; + field_0xD24 = 1.f; + field_0xD28 = mLightInfluence.mScale / (field_0xD5C * 2.f); + } else if (mType == EKS_ELECTRIC) { + field_0xD20 = 0.f; + field_0xD24 = 1.f; + field_0xD28 = mLightInfluence.mScale / (field_0xD5C * 2.f); + } + field_0xDB5 = 1; + startSound(SE_EKs_V_DAMAGE); + field_0x346 = 1; // Part of dAcEnBase_c +} +void dAcEKs_c::executeState_Stun() { + setFinalBlowPosition(mPosition); + switch (field_0xDCC) { + case 0: { + mMdl.play(); + soundStun(); + sLib::addCalcAngle(mRotation.x.ref(), 0, 12, 0x1555); + if (field_0xD5C > 0) { + field_0xD5C--; + } else { + field_0xDA9 = 1; + } + if (mAcch.ChkGndHit()) { + if (field_0xDB5 != 0) { + dJEffManager_c::spawnGroundEffect( + mPosition, mPolyAttr0, mPolyAttr1, field_0x1B4, 1, 1, field_0x1B0 + ); + field_0xDB5 = 0; + } + field_0xD5C = 0; + field_0xDA9 = 1; + if (dBgS::GetInstance()->GetSpecialCode(mAcch.GetGnd()) == POLY_ATTR_LAVA) { + dJEffManager_c::spawnGroundEffect( + mPosition, mPolyAttr0, mPolyAttr1, field_0x1B4, 1, 1, field_0x1B0 + ); + resetInteractionFlags(0x1); + startSound(SE_EKs_V_DEATH2); + unsetActorProperty(AC_PROP_0x1); + kill(false); + return; + } + if (std::abs(mSpeed) > 0.01f) { + sLib::addCalcScaled(&mSpeed, 1, 10); + } else { + mSpeed = 0.f; + setInteractionFlags(0x1); + } + + mMdl.getModel().getNodeWorldMtx(mCenterNode, mCenterWorldMtx); + mCenterWorldMtx.getTranslation(field_0xBA4); + field_0xBA4.y += 50.f; + + mEmitter2.holdEffect( + PARTICLE_RESOURCE_ID_MAPPING_309_, field_0xBA4, nullptr, &mScale, nullptr, nullptr + ); + mEmitter2.setGlobalAlpha(dStageMgr_c::GetInstance()->getGlobalAlpha()); + holdSound(SE_E_PIYORI_LV); + } + if (mAcch.ChkWaterIn()) { + resetInteractionFlags(0x1); + startSound(SE_EKs_V_DEATH2); + unsetActorProperty(AC_PROP_0x1); + kill(false); + } else { + if (!dAcPy_c::GetLink()->checkCurrentAction(/* FINAL_BLOW */ 96)) { + field_0xD76--; + mSph.OnCoSet(); + } else { + mSph.ClrCoSet(); + } + if (checkInteractionFlags(0x1000)) { + mSph.ClrCoSet(); + field_0xDCC = 1; + mHealth = 0; + } else { + if (field_0xD76 <= 0) { + resetInteractionFlags(0x1); + mAcch.SetGroundUpY(30); + mAngle.y = mRotation.y; + if (mType == EKS_ELECTRIC) { + field_0xDA9 = 1; + } else { + field_0xDA9 = 0; + } + changeState(StateID_Fighting); + } + } + } + } break; + case 1: { + mSph.ClrTgSet(); + mMdl.play(); + field_0xDCC = 2; + mMdl.setRate(0.5f); + startSound(SE_EKs_V_DEATH2); + field_0xDCD = 5; + field_0xD0C = 1.f; + setAnim("Deliver", 4, 1, 0); + mHealth = 0; + resetInteractionFlags(0x1); + } break; + case 2: { + bool b = false; + if (field_0xDCD != 0) { + field_0xDCD--; + } else { + b = fn_80030570(mMdl.getModel(), 1, 1); + } + mMdl.play(); + if (mMdl.getAnm().isStop() && b) { + kill(true); + } + } break; + } +} +void dAcEKs_c::finalizeState_Stun() { + field_0xC10.y = 0.f; + mAcceleration = 0.f; + mSph.OnCoSet(); + resetInteractionFlags(0x1); + if (mType == EKS_FIRE) { + mSph.SetCo_0x8000(); + field_0xD20 = 400.f; + field_0xD24 = 1.f; + field_0xD28 = 40.f; + } else if (mType == EKS_ELECTRIC) { + field_0xD60 = 0; + field_0xD20 = 400.f; + field_0xD24 = 1.f; + field_0xD28 = 40.f; + } + field_0x346 = 0; // Part of dAcEnBase_c +} + +void dAcEKs_c::initializeState_WindBlow() { + setAnim("hura2", 1, 1, 0); + field_0xD86 = cM::rndInt(30) + 120; + field_0xDA9 = 1; + + if (mType == EKS_FIRE) { + mSph.ClrCo_0x8000(); + field_0xD20 = 0.f; + mLightInfluence.SetScale(0); + } else if (mType == EKS_ELECTRIC) { + fn_155_3EC0(); + field_0xD20 = 0.f; + mLightInfluence.SetScale(0); + } + mAcceleration = -0.5f; + mAcch.ClrRoofNone(); + mAcchCir.SetWall(20, 60); + mAcch.SetField_0xD4(55); + mAcch.SetGroundUpY(30); +} +void dAcEKs_c::executeState_WindBlow() { + s32 _weird_zero = 0; + + mMdl.play(); + + if (field_0xD9A > 0) { + mSpeed = 0.f; + } + + if (mAcch.ChkGroundLanding() && dBgS::GetInstance()->GetSpecialCode(mAcch.GetGnd()) == POLY_ATTR_LAVA) { + dJEffManager_c::spawnGroundEffect(mPosition, mPolyAttr0, mPolyAttr1, field_0x1B4, 1, 1, field_0x1B0); + startSound(SE_EKs_V_DEATH2); + unsetActorProperty(AC_PROP_0x1); + kill(false); + return; + } + + if (mAcch.ChkWaterIn()) { + startSound(SE_EKs_V_DEATH2); + unsetActorProperty(AC_PROP_0x1); + kill(false); + return; + } + + if (nw4r::math::FAbs(mSpeed) < 1.0f) { + if (mSph.ChkTgHit() && mSph.ChkTgAtHitType(AT_TYPE_BELLOWS) && mSph.GetTgDamageFlags() == 0x8) { + mAngle.y = cLib::targetAngleY(dAcPy_c::GetLink()->mPosition, mPosition); + mAngle.x = cLib::targetAngleX(dAcPy_c::GetLink()->mPosition, mPosition); + s32 t = 7281; + field_0xD66 = (cM::rndFX(0.25f + (0.01f * _weird_zero)) + (0.75f + (0.01f * _weird_zero))) * t; + field_0xD68 = (cM::rndFX(0.25f + (0.01f * _weird_zero)) + (0.65f + (0.01f * _weird_zero))) * t; + + if (field_0xD66 < 0) { + field_0xD64 = -0x38E; + } else { + field_0xD64 = 0x38E; + } + + if (mAngle.x > 0xAAB) { + mVelocity.y = 15.f; + } else if (mAngle.x < -0xAAB) { + mVelocity.y = -15.f; + } + + if (field_0xD9A > 0) { + mSpeed = 0.f; + } else { + mSpeed = 35.f; + } + } + } + + if (std::abs(mSpeed) > 0.01f) { + sLib::addCalcScaled(&mSpeed, 0.3, 1.5); + mRotation.x += field_0xD66; + mRotation.y += field_0xD68; + } else { + mSpeed = 0.f; + if (mRotation.x.abs() < 0x444) { + mRotation.x = 0; + } else { + mRotation.x += field_0xD64; + } + } + + sLib::addCalcAngle(&field_0xD66, 0, 16, 0x16C); + sLib::addCalcAngle(&field_0xD68, 0, 16, 0x16C); + + f32 add = 0.1f * _weird_zero; + if (std::abs(mVelocity.y) > 0.01f + add) { + sLib::addCalcScaled(&mVelocity.y, 0.3, 1.5); + } else { + mVelocity.y = -(0.1f * _weird_zero); + } + + if (field_0xD86 > 0) { + field_0xD86--; + } else if (field_0xDA6) { + if (transitionToNextState()) { + return; + } + } else { + changeState(StateID_Fighting); + } +} +void dAcEKs_c::finalizeState_WindBlow() { + mSpeed = 0.f; + mAcceleration = 0.f; + mVelocity.y = 0.f; + mRotation.x = 0; + mAngle.set(mRotation); + field_0xDA9 = 0; + if (mType == EKS_FIRE) { + mSph.SetCo_0x8000(); + field_0xD20 = 400.f; + field_0xD24 = 1.f; + field_0xD28 = 40.f; + } else if (mType == EKS_ELECTRIC) { + field_0xDA9 = 1; + field_0xD20 = 400.f; + field_0xD24 = 1.f; + field_0xD28 = 40.f; + } +} + +void dAcEKs_c::initializeState_PathMove() { + field_0xD30 = 1; + setAnim("fly", 1.5, cM::rndFX(0.2) + 1.f, 0); + + if (mCurrentAnmTexPat == EKS_TEXPAT_BLINK2) { + setBlink(EKS_TEXPAT_BLINK3); + } else { + setBlink(EKS_TEXPAT_BLINK1); + } + mBlinkTimer = cM::rndInt(75) + 15; + mSpeed = 15.f; + if (field_0xDA6 != 0) { + field_0xDC9 = 3; + } else { + if (mRail.getSpeed() >= 0.f) { + mRail.setSpeed(15.f); + } else { + mRail.setSpeed(-15.f); + } + mTargetPos.set(mRail.getPosition()); + field_0xDC9 = 0; + } + setPitchYawToPoint(mTargetPos); + field_0xD54 = cM::rndInt(30) + 30; + field_0xD90 = 3; + field_0xDA5 = 0; + field_0xDB1 = 0; + + if (field_0xDA6 != 0) { + fn_155_3E30(); + } else { + setActorProperty(AC_PROP_0x1); + } + + mSqueakSoundTimer = cM::rndInt(20) + 20; + field_0xDB7 = 0; + field_0xDC1 = 0; + field_0xD52 = cM::rndInt(20) + 20; +} +void dAcEKs_c::executeState_PathMove() { + mMdl.play(); + playBlinkAnm(); + soundSqueak(); + + if (field_0xD54 > 0) { + field_0xD54--; + } + if (field_0xD90 > 0) { + field_0xD90--; + } + + if (field_0xDA6 != 0) { + if (transitionToNextState()) { + if (mNextState == EKS_STATE_ReturnToWait) { + f32 y = getLineCrossYRange(mStartingPos, 300); + mStartingPos.set(mStartingPos.x + cM::rndFX(100), y, mStartingPos.z + cM::rndFX(100)); + } + return; + } + } else { + if (field_0xDC9 == 3) { + field_0xDC9 = 0; + setActorProperty(AC_PROP_0x1); + mRail.setSegment(mRail.getClosestXZPoint(mPosition), 0.f); + setStartingPosition(mRail.getPosition()); + mPnts[0].set(mRail.getPosition()); + mRail.setSpeed(15); + } + + if (!checkBeyondRadius(getStartingPos(), 490000.f)) { + field_0xDC9 = 0; + setStartingPosition(mRail.getPosition()); + mPnts[0].set(mRail.getPosition()); + + if (field_0xD54 <= 0 && field_0xD90 <= 0) { + if (fn_155_2B80(true, 0)) { + changeState(StateID_Chase); + return; + } + field_0xD90 = 3; + } + u8 railStatus = mRail.execute(); + if (railStatus != 0 && (railStatus != 3 || mRail.getSpeed() > 0.f)) { + s32 idx; + if (mRail.getSpeed() > 0.f) { + idx = mRail.getSegmentIndex(); + } else if (mRail.getSpeed() < 0.f) { + idx = mRail.getNextPointIndex2(); + } + field_0xDCA = mRail.getPath().getPointParam(idx, 0); + if (checkPathPntParam(field_0xDCA)) { + setStartingPosition(*(const mVec3_c *)mRail.getPath().getPoint(idx)); + mStartingPos.y = getLineCrossYRange(getStartingPosition(), 300); + changeState(StateID_ReturnToWait); + return; + } + } + } else if (field_0xDC9 == 0) { + field_0xDC9 = 1; + } + if (field_0xDC9 == 1) { + field_0xDC9 = 2; + mVec3_c pnt; + const s32 pntIdx = mRail.getClosestXZPoint(mPosition); + const Vec *pPnt = mRail.getPoint(pntIdx); + pnt.copyFrom(pPnt); + if (mRail.getPosition().squareDistanceToXZ(mPosition) > pnt.squareDistanceToXZ(mPosition)) { + mRail.setSegment(pntIdx, 0.f); + setStartingPosition(mRail.getPosition()); + mPnts[0].set(mRail.getPosition()); + } + } + if (field_0xDC9 == 2) { + if (field_0xD52 > 0) { + field_0xD52--; + } + field_0xB8C.set(mPnts[field_0xD9E]); + f32 dist = mPosition.squareDistance(field_0xB8C); + if (checkWallCross()) { + field_0xDB7++; + + if (field_0xDB7 < 5) { + field_0xDC1 = 0; + mTargetPos.x = field_0xB8C.x + cM::rndFX(800); + mTargetPos.y = field_0xB8C.y + cM::rndF(400); + mTargetPos.z = field_0xB8C.z + cM::rndFX(800); + adjustTargetGnd(); + adjustTargetRoof(); + } else if (field_0xDB7 < 10) { + field_0xDC1 = 1; + + fn_155_3BD0(mVec3_c(cM::rndFX(200), cM::rndFX(200), cM::rndF(-300))); + field_0xD52 = cM::rndInt(20) + 20; + + adjustTargetGnd(); + adjustTargetRoof(); + } else if (field_0xDB7 > 20) { + field_0xDB7 = 0; + } + } + if (field_0xD52 <= 0) { + if (field_0xD9E > 0) { + mVec3_c startPos = mPosition; + for (s32 i = 0; i <= field_0xD9E; ++i) { + if (!dBgS_ObjLinChk::LineCross(&startPos, &mPnts[i], nullptr)) { + field_0xD9E = i; + field_0xB8C.set(mPnts[field_0xD9E]); + } + } + } + field_0xDC1 = 0; + field_0xD52 = cM::rndInt(20) + 20; + mTargetPos.x = field_0xB8C.x + cM::rndFX(800); + mTargetPos.y = field_0xB8C.y + cM::rndFX(400); + mTargetPos.z = field_0xB8C.z + cM::rndFX(800); + adjustTargetGnd(); + adjustTargetRoof(); + } + + chaseTargetY(0.1, 3); + sLib::addCalcAngle(mRotation.y.ref(), mYaw_0xC36, 10, 0x38E); + sLib::addCalcAngle(mRotation.x.ref(), mPitch_0xC34, 12, 0xB6); + clampRotationX(); + if (field_0xD9E != 0 && dist < 2500.f) { + field_0xD9E--; + } + + if (field_0xD9E == 0 && !checkBeyondRadius(getStartingPos(), 490000)) { + field_0xDC9 = 0; + } + } else { + mTargetPos.set(mRail.getPosition()); + } + } + setPitchYawToPoint(mTargetPos); + chaseTargetY(0.5, 4); + sLib::addCalcAngle(mRotation.y.ref(), mYaw_0xC36, 10, 0x38E); + sLib::addCalcAngle(mRotation.x.ref(), mPitch_0xC34, 12, 0xB6); + clampRotationX(); +} void dAcEKs_c::finalizeState_PathMove() { field_0xD30 = 0; } diff --git a/src/toBeSorted/d_path.cpp b/src/toBeSorted/d_path.cpp index 43b2b896..6a539796 100644 --- a/src/toBeSorted/d_path.cpp +++ b/src/toBeSorted/d_path.cpp @@ -589,6 +589,22 @@ s32 ActorOnRail_Ext::getNextPointIndex() const { return getNextPointIndex(mSegmentIndex); } +s32 ActorOnRail_Ext::getNextPointIndex2() const { + if (mSpeed >= 0.0f) { + return mSegmentIndex; + } + + if (mSegmentIndex + 1 < mPath.getNumPoints()) { + return mSegmentIndex + 1; + } + + if (mPath.isWrapping()) { + return 0; + } + + return mPath.getLastPointIdx(); +} + s32 ActorOnRail_Ext::getClosestXZPoint(const mVec3_c &pos) const { f32 max = EGG::Math::maxNumber(); s32 best = 0;