diff options
| author | Elijah Thomas <42302100+elijah-thomas774@users.noreply.github.com> | 2025-12-05 14:14:59 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-05 14:14:59 -0500 |
| commit | fca71a77bc890960800eef0e331b16dcec114aaf (patch) | |
| tree | 3aa82a9e98c53936031d3fa569ff29d2de358fef /src | |
| parent | 4e39bcca32c51cc0fb109d1a6918828499da8309 (diff) | |
| parent | ad47fd3eb383679d9b502323cd8cbdc3434c10ba (diff) | |
Merge pull request #280 from lepelog/d_t_insect
d_t_insect
Diffstat (limited to 'src')
| -rw-r--r-- | src/REL/d/t/d_t_insect.cpp | 477 |
1 files changed, 472 insertions, 5 deletions
diff --git a/src/REL/d/t/d_t_insect.cpp b/src/REL/d/t/d_t_insect.cpp index 75e361de..125387f8 100644 --- a/src/REL/d/t/d_t_insect.cpp +++ b/src/REL/d/t/d_t_insect.cpp @@ -1,5 +1,31 @@ #include "d/t/d_t_insect.h" +#include "c/c_lib.h" +#include "c/c_math.h" +#include "common.h" +#include "d/a/d_a_base.h" +#include "d/a/d_a_insect_butterfly.h" +#include "d/a/d_a_item.h" +#include "d/a/d_a_itembase.h" +#include "d/a/obj/d_a_obj_base.h" +#include "d/a/obj/d_a_obj_soil.h" +#include "d/a/obj/d_a_obj_warp.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" +#include "d/flag/itemflag_manager.h" +#include "d/flag/sceneflag_manager.h" +#include "d/flag/storyflag_manager.h" +#include "f/f_base.h" +#include "f/f_manager.h" +#include "f/f_profile.h" +#include "f/f_profile_name.h" +#include "m/m_angle.h" +#include "m/m_vec.h" +#include "nw4r/math/math_geometry.h" +#include "nw4r/math/math_types.h" +#include "rvl/MTX/mtx.h" + SPECIAL_ACTOR_PROFILE(TAG_INSECT, dTgInsect_c, fProfile::TAG_INSECT, 0x167, 0, 0); STATE_DEFINE(dTgInsect_c, Wait); @@ -7,15 +33,456 @@ STATE_DEFINE(dTgInsect_c, WaitCreate); STATE_DEFINE(dTgInsect_c, WaitForceEscape); STATE_DEFINE(dTgInsect_c, End); +static const s32 unused[] = { + 0x001E0100, 0, 0, 0, 0, 0, 0, 0, +}; +const f32 dTgInsect_c::SCALE_X = 100; +const f32 dTgInsect_c::SCALE_Y = 100; + +static const f32 unused2[] = {150, 0.5f}; + +const s32 *useUnused() { + return unused + (s32)unused2; +} + +int dTgInsect_c::actorCreate() { + if (getSubtype() == SUBTYPE_INVALID0) { + return FAILED; + } + if (getSubtype() == SUBTYPE_INVALID1) { + return FAILED; + } + if (getSubtype() == SUBTYPE_INVALID2) { + return FAILED; + } + mInsectCount = getInsectCount(); + if (mInsectCount > 0xF) { + mInsectCount = 0xF; + } else { + if (mInsectCount == 0xF) { + mInsectCount = 1; + } + } + mScale *= 0.01f; + mRevealed = 0; + mRevealedSpawnPos = mPosition; + if (isTrialGateType() || isGossipStoneType() || isGoddessWallType() || isSpawnSubtype(SPAWN_BUG_MINIGAME)) { + field_0x24e = 1; + } + return SUCCEEDED; +} + +inline bool checkProfile(u16 prof, u32 target) { + return prof == target; +} + +int dTgInsect_c::actorPostCreate() { + Subtype subtype = getSubtype(); + // ??? doesn't match without the double comparison + if (subtype == SUBTYPE_WOODLAND_RHINO_BEETLE + || subtype == SUBTYPE_WOODLAND_RHINO_BEETLE + || subtype == SUBTYPE_SAND_CICADA + || subtype == SUBTYPE_VOLCANIC_LADYBUG + || subtype == SUBTYPE_SKY_STAG_BEETLE) { + if (!checkValidSpawnLocation(mPosition, 1)) { + return FAILED; + } + } + dAcBase_c *obj = nullptr; + do { + obj = searchNextActor(obj); + if (obj == nullptr) { + break; + } + u16 prof = obj->mProfileName; + if (( + checkProfile(prof, fProfile::OBJ_TUBO) || checkProfile(prof, fProfile::OBJ_CARRY_STONE) || + checkProfile(prof, fProfile::OBJ_OCT_GRASS_LEAF) || checkProfile(prof, fProfile::OBJ_FRUIT) || + checkProfile(prof, fProfile::OBJ_BARREL) || checkProfile(prof, fProfile::OBJ_VSD) || + checkProfile(prof, fProfile::OBJ_SOIL) + ) && + getSquareDistanceTo(obj->mPosition) < 25) { + if (subtype == SUBTYPE_FARON_GRASSHOPPER + || subtype == SUBTYPE_SKYLOFT_MANTIS + || subtype == SUBTYPE_LANAYRU_ANT + || subtype == SUBTYPE_EDLIN_ROLLER) { + if (prof == fProfile::OBJ_SOIL && static_cast<dAcOsoil_c *>(obj)->isStateHole()) { + return FAILED; + } + setActorRef(obj); + } + break; + } + } while (true); + if (mActorNode.isLinked()) { + mStateMgr.changeState(StateID_WaitCreate); + } else { + if (isSpawnSubtype(SPAWN_BUG_MINIGAME)) { + for (s32 i = 0; i < (s32)ARRAY_LENGTH(field_0x1f8); i++) { + field_0x1f8[i] = 0; + } + mStateMgr.changeState(StateID_Wait); + } else if (isTrialGateType()) { + dAcOWarp_c *warp = static_cast<dAcOWarp_c *>(fManager_c::searchBaseByProfName(fProfile::OBJ_WARP)); + if (warp == nullptr) { + return FAILED; + } + if (!warp->checkThisHasSongItem() || warp->isTrialComplete()) { + return FAILED; + } + if ((warp->mPosition - mPosition).squareMagXZ() < 1000000.f) { + mWarpRef.link(warp); + } else { + return FAILED; + } + mStateMgr.changeState(StateID_WaitForceEscape); + } else if (isGossipStoneType()) { + if (!ItemflagManager::sInstance->getFlagDirect(ITEM_BALLAD_OF_THE_GODDESS)) { + return FAILED; + } + if (!StoryflagManager::sInstance->getFlag(STORYFLAG_IMPRISONED_1_DEFEATED)) { + return FAILED; + } + if (SceneflagManager::sInstance->checkBoolFlag(mRoomID, mParams >> 0xC & 0xFF)) { + return FAILED; + } + } else if (isGoddessWallType()) { + if (!ItemflagManager::sInstance->getFlagDirect(ITEM_BALLAD_OF_THE_GODDESS)) { + return FAILED; + } + if (!StoryflagManager::sInstance->getFlag(STORYFLAG_FARON_TRIAL_COMPLETE)) { + return FAILED; + } + mStateMgr.changeState(StateID_WaitForceEscape); + } else { + mStateMgr.changeState(StateID_End); + } + spawnAll(); + } + return SUCCEEDED; +} + +int dTgInsect_c::doDelete() { + return SUCCEEDED; +} + +int dTgInsect_c::actorExecute() { + mStateMgr.executeState(); + return SUCCEEDED; +} + +int dTgInsect_c::draw() { + return SUCCEEDED; +} + void dTgInsect_c::initializeState_Wait() {} -void dTgInsect_c::executeState_Wait() {} + +#pragma opt_strength_reduction off +void dTgInsect_c::executeState_Wait() { + if (isSpawnSubtype(SPAWN_BUG_MINIGAME)) { + s32 i = 0; + for (; i < mInsectCount; i++) { + if (!mLinks[i].isLinked()) { + if (mInsectRespawnTimers[i] > 0) { + mInsectRespawnTimers[i]--; + } else if (mInsectRespawnTimers[i] == 0) { + nw4r::math::MTX34 mtx; + PSMTXTrans(mtx, mPosition.x, mPosition.y, mPosition.z); + nw4r::math::MTX34 scale; + PSMTXScale(scale, mScale.x, mScale.y, mScale.x); + PSMTXConcat(mtx, scale, mtx); + nw4r::math::AABB aabb(-100, 0, -100, 100, 100, 100); + aabb.Set(&aabb, &mtx); + if (fn_801BB750(&aabb, 10000)) { + spawnInsect(i); + } + } else { + mInsectRespawnTimers[i] = 900; + } + } + } + } +} +#pragma opt_strength_reduction on void dTgInsect_c::finalizeState_Wait() {} -void dTgInsect_c::initializeState_WaitCreate() {} -void dTgInsect_c::executeState_WaitCreate() {} +void dTgInsect_c::initializeState_WaitCreate() { + if (!isSpawnSubtype(SPAWN_BUG_MINIGAME)) { + field_0x24f = 1; + for (s32 i = 0; i < mInsectCount; i++) { + mShouldSpawn[i] = shouldSpawn(); + } + } +} +void dTgInsect_c::executeState_WaitCreate() { + if (mActorNode.isLinked()) { + if (mActorNode.get()->mProfileName == fProfile::OBJ_VSD || + mActorNode.get()->mProfileName == fProfile::OBJ_SOIL) { + if (mRevealed == 0) { + return; + } + } else { + if (mPosition.squareDistanceToXZ(mActorNode.get()->mPosition) < 25) { + return; + } + } + } + mActorNode.unlink(); + for (s32 i = 0; i < mInsectCount; i++) { + if (!isSpawnSubtype(SPAWN_BUG_MINIGAME)) { + if (mShouldSpawn[i] != 0) { + mShouldSpawn[i] = 0; + } else { + continue; + } + } + dAcBase_c *insect = nullptr; + mVec3_c tmp1 = mPosition; + if (mRevealed) { + tmp1 = mRevealedSpawnPos; + } + mAng3_c rot(0, cM::rndFX(65536), 0); + switch (getSubtype()) { + case SUBTYPE_LANAYRU_ANT: + insect = dAcObjBase_c::createInsectActor(this, fProfile::INSECT_ANT, 1, &tmp1, &rot, nullptr, 0, 0x3f); + break; + case SUBTYPE_FARON_GRASSHOPPER: + insect = dAcObjBase_c::createInsectActor( + this, fProfile::INSECT_GRASSHOPPER, 1, &tmp1, &rot, nullptr, 0, 0x3f + ); + break; + case SUBTYPE_SKYLOFT_MANTIS: + insect = dAcObjBase_c::createInsectActor( + this, fProfile::INSECT_GRASSHOPPER, 0x10000001, &tmp1, &rot, nullptr, 0, 0x3f + ); + break; + case SUBTYPE_EDLIN_ROLLER: + insect = + dAcObjBase_c::createInsectActor(this, fProfile::INSECT_SCARAB, 1, &tmp1, &rot, nullptr, 0, 0x3f); + break; + } + if (insect != nullptr) { + mLinks[i].link(insect); + mInsectRespawnTimers[i] = -1; + } + } + if (isSpawnSubtype(SPAWN_BUG_MINIGAME)) { + mStateMgr.changeState(StateID_Wait); + } else { + mStateMgr.changeState(StateID_End); + } +} void dTgInsect_c::finalizeState_WaitCreate() {} -void dTgInsect_c::initializeState_WaitForceEscape() {} -void dTgInsect_c::executeState_WaitForceEscape() {} + +void dTgInsect_c::initializeState_WaitForceEscape() { + for (s32 i = 0; i < mInsectCount; i++) { + dAcOInsect_c* tmp = static_cast<dAcOInsect_c*>(mLinks[i].get()); + if (tmp) { + tmp->setActorProperty(AC_PROP_0x4); + } + } +} + +void dTgInsect_c::executeState_WaitForceEscape() { + if (isTrialGateType()) { + if (mWarpRef.isLinked()) { + dAcOWarp_c *warp = static_cast<dAcOWarp_c *>(mWarpRef.get()); + if (warp->fn_0x90()) { + for (s32 i = 0; i < mInsectCount; i++) { + if (mLinks[i].isLinked()) { + static_cast<dAcInsectButterfly_c *>(mLinks[i].get())->setKillSignal(); + mStateMgr.changeState(StateID_End); + } + } + } + } + } else if (isGoddessWallType() && mKillSignal) { + for (s32 i = 0; i < mInsectCount; i++) { + if (mLinks[i].isLinked()) { + static_cast<dAcInsectButterfly_c *>(mLinks[i].get())->setKillSignal(); + mStateMgr.changeState(StateID_End); + } + } + } +} void dTgInsect_c::finalizeState_WaitForceEscape() {} void dTgInsect_c::initializeState_End() {} void dTgInsect_c::executeState_End() {} void dTgInsect_c::finalizeState_End() {} + +static const f32 FLOAT_ARRAY[] = { + 0.1f, -0.4f, 0.3f, 0.7f, -0.7f, +}; + +void dTgInsect_c::spawnAll() { + for (s32 i = 0; i < mInsectCount; i++) { + if (shouldSpawn()) { + spawnInsect(i); + } + } +} + +void dTgInsect_c::spawnInsect(s32 index) { + f32 scaleX; + f32 scaleY; + f32 scaleXExt; + f32 scaleYExt; + f32 scaledScaleY; + f32 scaledScaleX; + f32 mult; + f32 scaledTemp; + scaleY = mScale.y; + scaleYExt = SCALE_Y; + scaledScaleY = scaleY * scaleYExt; + mult = 0.85f; + scaleXExt = SCALE_X; + scaleX = mScale.x; + scaledTemp = scaleXExt * scaleX; + scaledScaleX = mult * scaledTemp; + s16 angle1; + mVec3_c pos; + mVec3_c tmp; + mAng3_c rot(0, 0, 0); + bool spawnFound = false; + s32 tries = 5; + do { + f32 scale = cM::rndF(scaledScaleX); + angle1 = cM::rndFX(65536.0f); + rot.y = cM::rndFX(65536.0f); + mVec3_c v2 = mVec3_c::Ez * scale; + cLib::offsetPos(pos, mPosition, angle1, v2); + switch (getSubtype()) { + case SUBTYPE_VOLCANIC_LADYBUG: + case SUBTYPE_WOODLAND_RHINO_BEETLE: + case SUBTYPE_SAND_CICADA: + case SUBTYPE_SKY_STAG_BEETLE: + pos = mPosition; + if (getSubtype() == SUBTYPE_SAND_CICADA) { + tmp = mVec3_c::Ez; + tmp.rotY(mAng(mRotation.y + 0x4000)); + f32 arrayResult = FLOAT_ARRAY[index % (s32)ARRAY_LENGTH(FLOAT_ARRAY)]; + f32 scaledX = SCALE_X * mScale.x; + tmp.multScalar(arrayResult * scaledX); + pos = mPosition + tmp; + f32 scaledScale = SCALE_Y * mScale.y; + pos.y = mPosition.y + scaledScale * 0.3f; + pos.y += cM::rndF(scaledScale * 0.5f); + if (!checkValidSpawnLocation(pos, 0)) { + return; + } + } else { + pos.y += cM::rndF(scaledScaleY); + } + spawnFound = true; + break; + case SUBTYPE_FARON_GRASSHOPPER: + case SUBTYPE_LANAYRU_ANT: + case SUBTYPE_SKYLOFT_MANTIS: + case SUBTYPE_EDLIN_ROLLER: + pos.y = 100 + mPosition.y; + if (dBgS_ObjGndChk::CheckPos(pos)) { + spawnFound = true; + } + break; + case SUBTYPE_GERUDO_DRAGONFLY: + case SUBTYPE_BUTTERFLY: + case SUBTYPE_STARRY_FIREFLY: + spawnFound = true; + break; + } + } while (!spawnFound && --tries); + dAcBase_c *ref = nullptr; + switch (getSubtype()) { + case SUBTYPE_VOLCANIC_LADYBUG: + ref = dAcObjBase_c::createInsectActor(this, fProfile::INSECT_LADYBUG, 0, &pos, &rot, NULL, 0, 0x3f); + break; + case SUBTYPE_GERUDO_DRAGONFLY: + ref = dAcObjBase_c::createInsectActor(this, fProfile::INSECT_DRAGONFLY, 0, &pos, &rot, NULL, 0, 0x3f); + break; + case SUBTYPE_WOODLAND_RHINO_BEETLE: + ref = dAcObjBase_c::createInsectActor(this, fProfile::INSECT_BEETLE, 0, &pos, &rot, NULL, 0, 0x3f); + break; + case SUBTYPE_FARON_GRASSHOPPER: + ref = dAcObjBase_c::createInsectActor(this, fProfile::INSECT_GRASSHOPPER, 0, &pos, &rot, NULL, 0, 0x3f); + break; + case SUBTYPE_SAND_CICADA: + ref = dAcObjBase_c::createInsectActor(this, fProfile::INSECT_CICADA, 0, &pos, &rot, NULL, 0, 0x3f); + break; + case SUBTYPE_LANAYRU_ANT: + ref = dAcObjBase_c::createInsectActor(this, fProfile::INSECT_ANT, 0, &pos, &rot, NULL, 0, 0x3f); + break; + case SUBTYPE_SKY_STAG_BEETLE: + ref = dAcObjBase_c::createInsectActor(this, fProfile::INSECT_BEETLE, 0x10000000, &pos, &rot, NULL, 0, 0x3f); + break; + case SUBTYPE_BUTTERFLY: + ref = dAcObjBase_c::createInsectActor( + this, fProfile::INSECT_BUTTERFLY, (s16)mViewClipIdx, &pos, &rot, NULL, 0, 0x3f + ); + break; + case SUBTYPE_SKYLOFT_MANTIS: + ref = dAcObjBase_c::createInsectActor( + this, fProfile::INSECT_GRASSHOPPER, 0x10000000, &pos, &rot, NULL, 0, 0x3f + ); + break; + case SUBTYPE_EDLIN_ROLLER: + ref = dAcObjBase_c::createInsectActor(this, fProfile::INSECT_SCARAB, 0, &pos, &rot, NULL, 0, 0x3f); + break; + case SUBTYPE_STARRY_FIREFLY: + ref = dAcObjBase_c::createInsectActor(this, fProfile::INSECT_FIREFLY, 0, &pos, &rot, NULL, 0, 0x3f); + break; + } + if (ref != nullptr) { + mLinks[index].link(ref); + mInsectRespawnTimers[index] = -1; + } + return; +} + +bool dTgInsect_c::shouldSpawn() { + if (isSpawnSubtype(SPAWN_BUG_MINIGAME)) { + return true; + } else if (isSpawnSubtype(SPAWN_SKYLOFT_BUGKID_TREE)) { + return !SceneflagManager::sInstance->checkBoolFlag(mRoomID, 0x3a); + } else { + if (isTrialGateType()) { + return true; + } else if (isGossipStoneType() || isGoddessWallType()) { + return true; + } else if ((isSubtype(SUBTYPE_STARRY_FIREFLY)) && !dAcItem_c::checkFlag(ITEM_STARRY_FIREFLY)) { + return true; + } else { + if (cM::rndF(1.0f) >= 0.5f) { + return false; + } else { + return true; + } + } + } +} + +bool dTgInsect_c::checkValidSpawnLocation(const mVec3_c &pos, bool updateRotation) { + mVec3_c tmp = mVec3_c::Ez * (SCALE_X * mScale.x); + tmp.rotY(mRotation.y); + tmp += pos; + dBgS_LinChk linChk; + linChk.mBackFlag = true; + linChk.mFrontFlag = false; + linChk.Set(&pos, &tmp, nullptr); + if (!dBgS::GetInstance()->LineCross(&linChk)) { + mAng yRot = mRotation.y + 0x7FFF; + if (updateRotation) { + mRotation.y = yRot; + } + tmp = mVec3_c::Ez * (SCALE_X * mScale.x); + tmp.rotY(yRot); + tmp += pos; + linChk.Set(&pos, &tmp, nullptr); + if (!dBgS::GetInstance()->LineCross(&linChk)) { + return false; + } + } + return true; +} + +void moreUnused() { + static const s32 a = 0x3a; +} |
