summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrobojumper <robojumper@gmail.com>2026-05-12 09:54:02 +0200
committerGitHub <noreply@github.com>2026-05-12 09:54:02 +0200
commit388abef134a6c7156f1309d6453ac2eb260642e1 (patch)
treeb691a600f863bfdb9aacd6c656cc19b91aac2631
parentf7b4c029fd5176e817e3de7209727480c445a3d2 (diff)
parent65b4f57fae58bbad95a4f77b3057665e98f1c876 (diff)
Merge pull request #306 from coleslaw456/main
beetle tag actor
-rw-r--r--config/SOUE01/rels/d_t_beetleNP/symbols.txt21
-rw-r--r--include/d/t/d_t_beetle.h37
-rw-r--r--src/REL/d/t/d_t_beetle.cpp126
3 files changed, 173 insertions, 11 deletions
diff --git a/config/SOUE01/rels/d_t_beetleNP/symbols.txt b/config/SOUE01/rels/d_t_beetleNP/symbols.txt
index 11eec349..91f91a8c 100644
--- a/config/SOUE01/rels/d_t_beetleNP/symbols.txt
+++ b/config/SOUE01/rels/d_t_beetleNP/symbols.txt
@@ -2,21 +2,20 @@ _prolog = .text:0x00000000; // type:function size:0x2C scope:global
_epilog = .text:0x00000030; // type:function size:0x2C scope:global
_unresolved = .text:0x00000060; // type:function size:0x4 scope:global
dTgBeetle_c_classInit__Fv = .text:0x00000070; // type:function size:0x4C
-fn_302_C0 = .text:0x000000C0; // type:function size:0x14C
-fn_302_210 = .text:0x00000210; // type:function size:0x8
-fn_302_220 = .text:0x00000220; // type:function size:0x17C
-fn_302_3A0 = .text:0x000003A0; // type:function size:0x8
-fn_302_3B0 = .text:0x000003B0; // type:function size:0x168
-fn_302_520 = .text:0x00000520; // type:function size:0xFC
-fn_302_620 = .text:0x00000620; // type:function size:0x54
-fn_302_674 = .text:0x00000674; // type:function size:0x4
+create__11dTgBeetle_cFv = .text:0x000000C0; // type:function size:0x14C
+doDelete__11dTgBeetle_cFv = .text:0x00000210; // type:function size:0x8
+actorExecute__11dTgBeetle_cFv = .text:0x00000220; // type:function size:0x17C
+draw__11dTgBeetle_cFv = .text:0x000003A0; // type:function size:0x8
+isWithinCylinder__11dTgBeetle_cCFRC7mVec3_c = .text:0x000003B0; // type:function size:0x168
+isWithinSphere__11dTgBeetle_cCFRC7mVec3_c = .text:0x00000520; // type:function size:0xFC
+updateBeetle__11dTgBeetle_cFR14dAcBoomerang_c = .text:0x00000620; // type:function size:0x58
__dt__11dTgBeetle_cFv = .text:0x00000680; // type:function size:0x5C
_ctors = .ctors:0x00000000; // type:label scope:global
_dtors = .dtors:0x00000000; // type:label scope:global
lbl_302_rodata_0 = .rodata:0x00000000; // type:object size:0x4 data:float
-dTgBeetle__scaleMultiplier = .rodata:0x00000004; // type:object size:0x4 align:4 data:float
-lbl_302_rodata_4.y = .rodata:0x00000008; // type:object size:0x4 align:4 data:float
-lbl_302_rodata_4.z = .rodata:0x0000000C; // type:object size:0xC align:4 data:float
+dTgBeetle__scaleMultiplier = .rodata:0x00000004; // type:object size:0xC align:4 data:float
+lbl_302_rodata_4.y = .rodata:0x00000010; // type:object size:0x4 align:4 data:float
+lbl_302_rodata_4.z = .rodata:0x00000014; // type:object size:0x4 align:4 data:float
g_profile_BEETLE_TAG = .data:0x00000000; // type:object size:0x10
lbl_302_data_10 = .data:0x00000010; // type:object size:0x5 data:string
dTgBeetle__vtable = .data:0x00000018; // type:object size:0x74
diff --git a/include/d/t/d_t_beetle.h b/include/d/t/d_t_beetle.h
index fab00d6d..56fb505e 100644
--- a/include/d/t/d_t_beetle.h
+++ b/include/d/t/d_t_beetle.h
@@ -1,14 +1,51 @@
#ifndef D_T_BEETLE_H
#define D_T_BEETLE_H
+#include "d/a/obj/d_a_obj_boomerang.h"
#include "d/t/d_tg.h"
+#include "m/m_mtx.h"
+
+// This is a tag actor for controlling where the beetle can fly
+// BtlTgC is leaves (beetle plays leaf animation as it passes through)
class dTgBeetle_c : public dTg_c {
public:
dTgBeetle_c() {}
virtual ~dTgBeetle_c() {}
+ virtual int create() override;
+ virtual int doDelete() override;
+ virtual int actorExecute() override;
+ u32 isWithinSphere(const mVec3_c &param) const;
+ u32 isWithinCylinder(const mVec3_c &param) const;
+ void updateBeetle(dAcBoomerang_c &boomerang);
+ virtual int draw() override;
+
+ enum Variant_e {
+ BtlTg,
+ BtlTgA, // is this even used?
+ BtlTgB, // is this even used?
+ BtlTgC, // spherical leaf object
+ };
+
+ enum ZoneType_e {
+ LeafZone = 1,
+ BorderZone = 2,
+ UnknownZone = 3,
+ };
+
+ enum ZoneShape_e {
+ RectangularPrismShape,
+ CylinderShape,
+ SphereShape,
+ };
private:
+ /* 0xFC */ mMtx_c mMatrix1;
+ /* 0x12C*/ u8 mZoneType; // defines what this object does
+ /* 0x12D*/ u8 mZoneShape; // the shape created inside the object that it checks
+ /* 0x12E*/ u8 mUnknown; // unused
+ /* 0x12F*/ u8 mBeetleFlag;
+ /* 0x130*/ u8 mPastOnly; // object only exists in past state
};
#endif
diff --git a/src/REL/d/t/d_t_beetle.cpp b/src/REL/d/t/d_t_beetle.cpp
index 390c6e6f..dbd5432e 100644
--- a/src/REL/d/t/d_t_beetle.cpp
+++ b/src/REL/d/t/d_t_beetle.cpp
@@ -1,3 +1,129 @@
#include "d/t/d_t_beetle.h"
+#include "d/a/d_a_player.h"
+#include "d/a/obj/d_a_obj_base.h"
+#include "d/a/obj/d_a_obj_boomerang.h"
+#include "d/d_sc_game.h"
+#include "d/flag/sceneflag_manager.h"
+#include "toBeSorted/area_math.h"
+#include "toBeSorted/time_area_mgr.h"
+
SPECIAL_ACTOR_PROFILE(BEETLE_TAG, dTgBeetle_c, fProfile::BEETLE_TAG, 0x297, 0, 0);
+
+int dTgBeetle_c::create() {
+ if (dScGame_c::currentSpawnInfo.stageName == "F103") { // flooded faron woods
+ if (mActorSubtype) {
+ mScale *= 0.01f;
+ }
+ // Haven't verfied but I think CO_TEST is an invisible sphere created around leaves
+ // underwater to prevent you from swimming through trees
+ dAcObjBase_c::create(fProfile::CO_TEST, mRoomID, 0, &mPosition, &mRotation, &mScale, 0xFFFFFFFF);
+
+ return FAILED;
+ } else {
+ if (!mActorSubtype) { // BtlTg
+ mZoneType = getFromParams(0, 0xF);
+ mZoneShape = getFromParams(4, 0x3);
+ mUnknown = getFromParams(6, 0xFF);
+ mBeetleFlag = getFromParams(0xE, 0xFF);
+ mPastOnly = getFromParams(0x16, 0x3);
+ } else {
+ mZoneType = LeafZone;
+ if (mActorSubtype == BtlTgA) { // BtlTgA
+ mZoneShape = RectangularPrismShape;
+ } else if (mActorSubtype == BtlTgB) { // BtlTgB
+ mZoneShape = CylinderShape;
+ } else if (mActorSubtype == BtlTgC) { // BtlTgC
+ mZoneShape = SphereShape;
+ }
+ }
+ matrixCreateFromPosRotYScale(mMatrix1, mPosition, mRotation.y, mScale, nullptr, 0);
+ return SUCCEEDED;
+ }
+}
+
+int dTgBeetle_c::doDelete() {
+ return SUCCEEDED;
+}
+
+int dTgBeetle_c::actorExecute() {
+ if (mPastOnly == 1 && !mActorSubtype) {
+ if (dTimeAreaMgr_c::GetInstance()->checkPositionIsInPastState(mRoomID, mPosition, nullptr, 1.0f) == 0) {
+ return SUCCEEDED;
+ }
+ }
+
+ if (!SceneflagManager::sInstance->checkBoolFlag(mRoomID, mBeetleFlag) || mActorSubtype) {
+ dAcBoomerang_c *beetlePtr =
+ (dAcBoomerang_c *)dAcPy_c::GetLink()
+ ->vt_0x1C0(); // boomerang pointer cast required because function currently returns void*
+
+ if (mZoneShape == RectangularPrismShape) { // rectangular prism
+ if (beetlePtr && checkAreaBox(mMatrix1, beetlePtr->mPosition)) {
+ updateBeetle(*beetlePtr);
+ }
+ } else if (mZoneShape == CylinderShape) { // cylinder
+ if (beetlePtr && isWithinCylinder((beetlePtr->mPosition))) {
+ updateBeetle(*beetlePtr);
+ }
+ } else if (mZoneShape == SphereShape) { // sphere
+ if (beetlePtr && isWithinSphere((beetlePtr->mPosition))) {
+ updateBeetle(*beetlePtr);
+ }
+ }
+ }
+ return SUCCEEDED;
+}
+
+u32 dTgBeetle_c::isWithinSphere(
+ const mVec3_c &position
+) const { // fn_302_520 is position within a sphere the size of the zone
+
+ mVec3_c diff = position - (mPosition + mScale.y * mVec3_c::Ey * 1.0f);
+
+ diff.x /= mScale.x;
+ diff.y /= mScale.y;
+ diff.z /= mScale.z;
+
+ return diff.mag() <= 1.0f; // is beetle within a certain distance from center
+}
+
+u32 dTgBeetle_c::isWithinCylinder(
+ const mVec3_c &position
+) const { // is position within a really thin cylinder inside the zone
+
+ mVec3_c diff = (position - (mPosition + mVec3_c::Ey * mScale.y * 0.5f));
+
+ bool returnValue = 0;
+ bool returnCheck = 0;
+
+ diff.x /= mScale.x;
+ diff.y /= mScale.y;
+ diff.z /= mScale.z;
+
+ if (diff.absXZ() <= 0.01f && diff.y <= 0.5f) {
+ returnCheck = 1;
+ }
+
+ if (returnCheck && diff.y >= -0.5f) {
+ returnValue = 1;
+ }
+
+ return returnValue;
+}
+
+void dTgBeetle_c::updateBeetle(dAcBoomerang_c &boomerang) { // fn_302_620 update beetle based on zone type
+ if (mZoneType == LeafZone) { // leaf zone
+ return boomerang.setField_0x8CC(0x20);
+ } else if (mZoneType == BorderZone) { // border zone, reduce flight time
+ return boomerang.setRemainingFlightTime(0x3C);
+ } else if (mZoneType == UnknownZone) { //???
+ return boomerang.setField_0x8CC(0x80);
+ } else { // instant flashing red
+ return boomerang.setRemainingFlightTime(-1);
+ }
+}
+
+int dTgBeetle_c::draw() {
+ return SUCCEEDED;
+}