summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorElijah Thomas <42302100+elijah-thomas774@users.noreply.github.com>2025-12-05 14:14:59 -0500
committerGitHub <noreply@github.com>2025-12-05 14:14:59 -0500
commitfca71a77bc890960800eef0e331b16dcec114aaf (patch)
tree3aa82a9e98c53936031d3fa569ff29d2de358fef /src
parent4e39bcca32c51cc0fb109d1a6918828499da8309 (diff)
parentad47fd3eb383679d9b502323cd8cbdc3434c10ba (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.cpp477
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;
+}