diff --git a/config/SOUE01/rels/d_a_npc_volcano_f2_salboNP/symbols.txt b/config/SOUE01/rels/d_a_npc_volcano_f2_salboNP/symbols.txt index 52d172e5..0ebf0974 100644 --- a/config/SOUE01/rels/d_a_npc_volcano_f2_salboNP/symbols.txt +++ b/config/SOUE01/rels/d_a_npc_volcano_f2_salboNP/symbols.txt @@ -97,7 +97,7 @@ fn_61_4F40 = .text:0x00004F40; // type:function size:0x2E4 fn_61_5230 = .text:0x00005230; // type:function size:0x100 fn_61_5330 = .text:0x00005330; // type:function size:0x1D4 fn_61_5510 = .text:0x00005510; // type:function size:0x1A8 -fn_61_56C0 = .text:0x000056C0; // type:function size:0x4C +fn_61_56C0__12dAcNpcSlb2_cF7mVec3_cPC7mVec3_cPC4mAng = .text:0x000056C0; // type:function size:0x4C fn_61_5710 = .text:0x00005710; // type:function size:0x48 fn_61_5760 = .text:0x00005760; // type:function size:0x48 fn_61_57B0 = .text:0x000057B0; // type:function size:0x48 diff --git a/config/SOUE01/rels/d_t_scene_changeNP/symbols.txt b/config/SOUE01/rels/d_t_scene_changeNP/symbols.txt index 07ff8c96..a4a1c9aa 100644 --- a/config/SOUE01/rels/d_t_scene_changeNP/symbols.txt +++ b/config/SOUE01/rels/d_t_scene_changeNP/symbols.txt @@ -2,20 +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 dTgSceneChange_c_classInit__Fv = .text:0x00000070; // type:function size:0x4C -TgSceneChange__init = .text:0x000000C0; // type:function size:0xD4 -fn_204_1A0 = .text:0x000001A0; // type:function size:0x74 -TgSceneChange__update = .text:0x00000220; // type:function size:0x160 -fn_204_380 = .text:0x00000380; // type:function size:0x1C4 -fn_204_550 = .text:0x00000550; // type:function size:0x5C -fn_204_5B0 = .text:0x000005B0; // type:function size:0x8 -__dt__16dTgSceneChange_cFv = .text:0x000005C0; // type:function size:0x5C +create__16dTgSceneChange_cFv = .text:0x000000C0; // type:function size:0xD4 +checkDisabled__16dTgSceneChange_cCFv = .text:0x000001A0; // type:function size:0x74 +actorExecute__16dTgSceneChange_cFv = .text:0x00000220; // type:function size:0x160 +checkScrapper__16dTgSceneChange_cFv = .text:0x00000380; // type:function size:0x1C4 +savePlayerPosition__16dTgSceneChange_cFv = .text:0x00000550; // type:function size:0x5C +draw__16dTgSceneChange_cFv = .text:0x000005B0; // type:function size:0x8 +__dt__16dTgSceneChange_cFv = .text:0x000005C0; // type:function size:0x5C scope:weak _ctors = .ctors:0x00000000; // type:label scope:global _dtors = .dtors:0x00000000; // type:label scope:global -lbl_204_rodata_0 = .rodata:0x00000000; // type:object size:0x4 data:float -lbl_204_data_0 = .data:0x00000000; // type:object size:0x13 data:string -lbl_204_data_14 = .data:0x00000014; // type:object size:0x4 data:4byte +lbl_204_rodata_0 = .rodata:0x00000000; // type:object size:0x4 scope:local data:float +lbl_204_data_0 = .data:0x00000000; // type:object size:0x13 scope:local data:string +ScrapperStopEvent = .data:0x00000014; // type:object size:0x4 data:4byte g_profile_SC_CHANGE_TAG = .data:0x00000018; // type:object size:0x10 -lbl_204_data_28 = .data:0x00000028; // type:object size:0x4 data:4byte -lbl_204_data_2C = .data:0x0000002C; // type:object size:0x4 data:4byte -lbl_204_data_30 = .data:0x00000030; // type:object size:0xC data:string -TgSceneChange__vtable = .data:0x0000003C; // type:object size:0x74 +lbl_204_data_28 = .data:0x00000028; // type:object size:0x4 scope:local data:4byte +lbl_204_data_2C = .data:0x0000002C; // type:object size:0x4 scope:local data:4byte +lbl_204_data_30 = .data:0x00000030; // type:object size:0xC scope:local data:string +__vt__16dTgSceneChange_c = .data:0x0000003C; // type:object size:0x74 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index cf0984a4..f4afdda4 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -2521,7 +2521,7 @@ vt_0x280__17daPlayerActBase_cFv = .text:0x8005C720; // type:function size:0x8 getSwordPos__17daPlayerActBase_cCFv = .text:0x8005C730; // type:function size:0x8 vt_0x278__17daPlayerActBase_cCFv = .text:0x8005C740; // type:function size:0x8 vt_0x274__17daPlayerActBase_cFv = .text:0x8005C750; // type:function size:0xC -triggerExitRelated__17daPlayerActBase_cFv = .text:0x8005C760; // type:function size:0x4 +triggerExitRelated__17daPlayerActBase_cFiii = .text:0x8005C760; // type:function size:0x4 doesGameOver__17daPlayerActBase_cFv = .text:0x8005C770; // type:function size:0x8 setActorRef11__17daPlayerActBase_cFv = .text:0x8005C780; // type:function size:0x4 getGroosenatorIfIn__17daPlayerActBase_cFv = .text:0x8005C790; // type:function size:0x8 @@ -2900,8 +2900,8 @@ __sinit_\d_rumble_cpp = .text:0x80066E50; // type:function size:0x108 scope:loca fn_80066F60 = .text:0x80066F60; // type:function size:0x50 lzSafeDecompress__FPCvUlPv = .text:0x80066FB0; // type:function size:0x64 matrixCreateFromPosRotYScale__FR6mMtx_cRC7mVec3_c4mAngRC7mVec3_cP6mMtx_cf = .text:0x80067020; // type:function size:0x138 -checkIfVec3fInMatrix__FRC6mMtx_cRC7mVec3_c = .text:0x80067160; // type:function size:0x88 -fn_800671F0 = .text:0x800671F0; // type:function size:0x84 +checkAreaBox__FRC6mMtx_cRC7mVec3_c = .text:0x80067160; // type:function size:0x88 +checkAreaCyl__FRC6mMtx_cRC7mVec3_c = .text:0x800671F0; // type:function size:0x84 __ct__7mVec2_cFv = .text:0x80067280; // type:function size:0x4 fn_80067290 = .text:0x80067290; // type:function size:0xA8 fn_80067340 = .text:0x80067340; // type:function size:0xC0 diff --git a/configure.py b/configure.py index dd59003f..1598adae 100644 --- a/configure.py +++ b/configure.py @@ -2944,7 +2944,7 @@ config.libs = [ Rel( NonMatching, "d_t_ro_at_target_manager", "REL/d/t/d_t_ro_at_target_manager.cpp" ), - Rel(NonMatching, "d_t_scene_change", "REL/d/t/d_t_scene_change.cpp"), + Rel(Matching, "d_t_scene_change", "REL/d/t/d_t_scene_change.cpp"), Rel(NonMatching, "d_t_ship_flood", "REL/d/t/d_t_ship_flood.cpp"), Rel(NonMatching, "d_t_ship_slope", "REL/d/t/d_t_ship_slope.cpp"), Rel(Matching, "d_t_ship_window", "REL/d/t/d_t_ship_window.cpp"), diff --git a/include/d/a/npc/d_a_npc_volcano_f2_salbo.h b/include/d/a/npc/d_a_npc_volcano_f2_salbo.h index 03b288b1..629911cb 100644 --- a/include/d/a/npc/d_a_npc_volcano_f2_salbo.h +++ b/include/d/a/npc/d_a_npc_volcano_f2_salbo.h @@ -2,6 +2,7 @@ #define D_A_NPC_VOLCANO_F2_SALBO_H #include "d/a/npc/d_a_ordinary_npc.h" +#include "m/m_vec.h" #include "s/s_State.hpp" class dAcNpcSlb2_c : public dAcOrdinaryNpc_c { @@ -10,6 +11,7 @@ public: virtual ~dAcNpcSlb2_c() {} void fn_61_58C0(int, int); + void fn_61_56C0(const mVec3_c, const mVec3_c *, const mAng *); bool fn_61_6A10(); void fn_61_68D0(int); diff --git a/include/d/d_player_act.h b/include/d/d_player_act.h index c8deccaa..a360676f 100644 --- a/include/d/d_player_act.h +++ b/include/d/d_player_act.h @@ -372,7 +372,7 @@ public: /* vt 0x26C */ virtual bool doesGameOver() { return true; } - /* vt 0x270 */ virtual void triggerExitRelated() {} + /* vt 0x270 */ virtual void triggerExitRelated(UNKWORD sceneLink, UNKWORD pathIdx, UNKWORD sceneType) {} /* vt 0x274 */ virtual mAng vt_0x274() { return mRotation.y; } diff --git a/include/d/t/d_t_scene_change.h b/include/d/t/d_t_scene_change.h index 0b6c063b..017c8d58 100644 --- a/include/d/t/d_t_scene_change.h +++ b/include/d/t/d_t_scene_change.h @@ -2,13 +2,53 @@ #define D_T_SCENE_CHANGE_H #include "d/t/d_tg.h" +#include "m/m_mtx.h" +#include "m/m_vec.h" class dTgSceneChange_c : public dTg_c { public: + // TODO: Move this somewhere not in d_t_scene_change. + // The Variable gets passed to dAcPy_c::triggerExitRelated + enum Type_e { + /* 0x0 */ TYPE_0, + /* 0x1 */ TYPE_1, // Restricting Movement? + /* 0x2 */ TYPE_2, + /* 0x3 */ TYPE_3, // Forced Walk + /* 0x4 */ TYPE_4, // Loftwing + /* 0x5 */ TYPE_5, // Landing on Skyloft + /* 0x6 */ TYPE_6, // Enter/Exit Dungeon + /* 0x7 */ TYPE_7, // Minecart + /* 0x8 */ TYPE_8, // Cistern Rope to Basement + /* 0x9 */ TYPE_9, // Light Pillar? + /* 0xA */ TYPE_A, // Boat + /* 0xB */ TYPE_B, // Actor Related + }; + dTgSceneChange_c() {} virtual ~dTgSceneChange_c() {} + virtual int create() override; + virtual int draw() override; + virtual int actorExecute() override; + private: + bool checkDisabled() const; + bool checkScrapper(); + + void savePlayerPosition(); + +private: + /* 0x0FC */ mMtx_c mArea; + /* 0x12C */ u8 mSceneLink; + /* 0x12D */ u8 mSceneType; + /* 0x12E */ u8 mPathId; + /* 0x12F */ u8 mEnableSceneflag; + /* 0x130 */ u16 mEnableStoryflag; + /* 0x132 */ u16 mDisableStoryflag; + /* 0x134 */ bool field_0x134; + /* 0x135 */ bool field_0x135; + /* 0x136 */ bool field_0x136; + /* 0x138 */ mVec3_c field_0x138; // Player position on Scrapper Stop }; #endif diff --git a/include/toBeSorted/area_math.h b/include/toBeSorted/area_math.h index b30a62fa..f4f52600 100644 --- a/include/toBeSorted/area_math.h +++ b/include/toBeSorted/area_math.h @@ -6,6 +6,7 @@ #include "m/m_vec.h" void matrixCreateFromPosRotYScale(mMtx_c &, const mVec3_c &, const mAng, const mVec3_c &, mMtx_c *, f32); -bool checkIfVec3fInMatrix(const mMtx_c &, const mVec3_c &); +bool checkAreaBox(const mMtx_c &, const mVec3_c &); +bool checkAreaCyl(const mMtx_c &, const mVec3_c &); #endif diff --git a/src/REL/d/t/d_t_action.cpp b/src/REL/d/t/d_t_action.cpp index 0bab0b68..a40bbacb 100644 --- a/src/REL/d/t/d_t_action.cpp +++ b/src/REL/d/t/d_t_action.cpp @@ -51,7 +51,7 @@ int dTgAction_c::actorExecute() { break; } if (pObj->mProfileName == fProfile::BOMB) { - if (checkIfVec3fInMatrix(mActiveMtx, pObj->getPosition())) { + if (checkAreaBox(mActiveMtx, pObj->getPosition())) { reinterpret_cast(pObj)->On_0xA3C(0x20000000); } } @@ -59,7 +59,7 @@ int dTgAction_c::actorExecute() { } // Check For Player Within Area - if (enabled && checkIfVec3fInMatrix(mActiveMtx, player->getPosition())) { + if (enabled && checkAreaBox(mActiveMtx, player->getPosition())) { if (mType == FORCE_FADE_RESTART) { player->onFlags_0x358(0x10000000); setActiveArea(50.f); diff --git a/src/REL/d/t/d_t_gate_to_ground.cpp b/src/REL/d/t/d_t_gate_to_ground.cpp index 281109b3..4f0b47e1 100644 --- a/src/REL/d/t/d_t_gate_to_ground.cpp +++ b/src/REL/d/t/d_t_gate_to_ground.cpp @@ -46,7 +46,7 @@ int dTgGateToGround_c::actorExecute() { player = dAcPy_c::LINK; - if (checkIfVec3fInMatrix(matrix, player->mPosition)) { + if (checkAreaBox(matrix, player->mPosition)) { if (player->getRidingActorType() != dAcPy_c::RIDING_LOFTWING) { if (delayFrames > 15) { Event e("CloudHole", 100, 0, nullptr, nullptr); diff --git a/src/REL/d/t/d_t_heat_resist.cpp b/src/REL/d/t/d_t_heat_resist.cpp index 063452b1..045cce17 100644 --- a/src/REL/d/t/d_t_heat_resist.cpp +++ b/src/REL/d/t/d_t_heat_resist.cpp @@ -21,11 +21,11 @@ int dTgHeatResist_c::actorExecute() { dAcPy_c *player = dAcPy_c::LINK; if (mInverted == 1) { - if (!checkIfVec3fInMatrix(matrix, player->mPosition)) { + if (!checkAreaBox(matrix, player->mPosition)) { player->onForceOrPreventActionFlags(0x8000000); } } else { - if (checkIfVec3fInMatrix(matrix, player->mPosition)) { + if (checkAreaBox(matrix, player->mPosition)) { player->onForceOrPreventActionFlags(0x8000000); } } diff --git a/src/REL/d/t/d_t_scene_change.cpp b/src/REL/d/t/d_t_scene_change.cpp index babed843..972d2406 100644 --- a/src/REL/d/t/d_t_scene_change.cpp +++ b/src/REL/d/t/d_t_scene_change.cpp @@ -1,3 +1,139 @@ #include "d/t/d_t_scene_change.h" +#include "c/c_lib.h" +#include "common.h" +#include "d/a/d_a_player.h" +#include "d/a/npc/d_a_npc_volcano_f2_salbo.h" +#include "d/flag/sceneflag_manager.h" +#include "d/flag/storyflag_manager.h" +#include "f/f_base.h" +#include "f/f_profile_name.h" +#include "m/m_angle.h" +#include "m/m_vec.h" +#include "toBeSorted/area_math.h" +#include "toBeSorted/d_path.h" +#include "toBeSorted/event.h" +#include "toBeSorted/event_manager.h" + +const char *ScrapperStopEvent = "HailToPlayerToStop"; + SPECIAL_ACTOR_PROFILE(SC_CHANGE_TAG, dTgSceneChange_c, fProfile::SC_CHANGE_TAG, 0x21, 0, 4); + +int dTgSceneChange_c::create() { + mSceneLink = getFromParams(0, 0xFF); + mPathId = getFromParams(8, 0xFF); + + mSceneType = getFromParams(16, 0xFF); + if (mSceneType == 0xFF) { + mSceneType = 0 /* TODO: Change with enum when used. See note in this files header */; + } + + mEnableSceneflag = getFromParams(24, 0xFF); + mEnableStoryflag = (mRotation.x >> 0) & 0x7FF; + + field_0x134 = ((mRotation.x >> 11) & 0x3) == 1; + mRotation.x = 0; + + mDisableStoryflag = mRotation.z & 0x7FF; + field_0x136 = ((mRotation.z >> 12) & 0xF) != 0; + + mRotation.z = 0; + + matrixCreateFromPosRotYScale(mArea, mPosition, mRotation.y, mScale, nullptr, 0.f); + + return SUCCEEDED; +} + +bool dTgSceneChange_c::checkDisabled() const { + bool disabled = false; + + bool validFlag = mDisableStoryflag != 0 && mDisableStoryflag < 0x7FF; + if (validFlag && StoryflagManager::sInstance->getFlag(mDisableStoryflag)) { + disabled = true; + } + return disabled; +} + +int dTgSceneChange_c::actorExecute() { + if (checkDisabled()) { + return SUCCEEDED; + } + + if (mEnableStoryflag != 0 && mEnableStoryflag < 0x7FF) { + if (!StoryflagManager::sInstance->getFlag(mEnableStoryflag)) { + return SUCCEEDED; + } + } + if (mEnableSceneflag < 0xFF) { + if (!SceneflagManager::sInstance->checkBoolFlag(mRoomID, mEnableSceneflag)) { + return SUCCEEDED; + } + } + + dAcPy_c *pPlayer = dAcPy_c::GetLinkM(); + if ((field_0x134 && checkAreaCyl(mArea, pPlayer->mPosition)) || + (!field_0x134 && checkAreaBox(mArea, pPlayer->mPosition))) { + if (!(field_0x136 && checkScrapper())) { + pPlayer->triggerExitRelated(mSceneLink, mPathId, mSceneType); + } + } else { + if (field_0x136) { + savePlayerPosition(); + } + } + + return SUCCEEDED; +} + +extern "C" dAcOrdinaryNpc_c *SCRAPPER_PTR; + +bool dTgSceneChange_c::checkScrapper() { + if (SCRAPPER_PTR != nullptr && SCRAPPER_PTR->mProfileName == fProfile::NPC_SLB2) { + dAcNpcSlb2_c *pScrapper = static_cast(SCRAPPER_PTR); + + if (!pScrapper->fn_61_6A10()) { + return false; + } + dPath_c path; + if (path.initWithPathIndex(mPathId, mRoomID, 0) && (u32)path.getNumPoints() >= 2) { + if (EventManager::isInEvent(pScrapper, ScrapperStopEvent)) { + mVec3_c p0, p1; + p0.copyFrom(path.getPoint(0)); + p1.copyFrom(path.getPoint(1)); + mAng a = cLib::targetAngleY(p0, p1); + pScrapper->fn_61_56C0(field_0x138, &mPosition, &a); + + return true; + } else { + void *zev = pScrapper->getOarcZev("DesertRobot"); + u32 flag1 = 0x100000; + Event e(ScrapperStopEvent, zev, 100, flag1 + 1, 0, 0); + EventManager::alsoSetAsCurrentEvent(pScrapper, &e, nullptr); + return true; + } + } + } + return false; +} + +void dTgSceneChange_c::savePlayerPosition() { + if (SCRAPPER_PTR == nullptr) { + return; + } + + if (SCRAPPER_PTR->mProfileName != fProfile::NPC_SLB2) { + return; + } + + const dAcPy_c *pPlayer = dAcPy_c::GetLink(); + if (pPlayer->checkActionFlags(0x800000 | 0x400000 | 0x40000 | 0x20000 | 0x10000 | 0x800 | 0x40 | 0x10 | 0x2) && + !pPlayer->checkActionFlags(0x40000)) { + return; + } + + field_0x138 = pPlayer->mPosition; +} + +int dTgSceneChange_c::draw() { + return SUCCEEDED; +} diff --git a/src/REL/d/t/d_t_sw_area.cpp b/src/REL/d/t/d_t_sw_area.cpp index 3ccb0520..cc9cbee1 100644 --- a/src/REL/d/t/d_t_sw_area.cpp +++ b/src/REL/d/t/d_t_sw_area.cpp @@ -32,7 +32,7 @@ bool isValidStoryFlag(u16 storyflag) { } int dTgSwArea_c::actorExecute() { - if (checkIfVec3fInMatrix(area, dAcPy_c::LINK->mPosition)) { + if (checkAreaBox(area, dAcPy_c::LINK->mPosition)) { SceneflagManager::sInstance->setFlag(mRoomID, setSceneflag); SceneflagManager::sInstance->unsetFlag(mRoomID, unsetSceneflag); diff --git a/src/REL/d/t/d_t_time_door_beam.cpp b/src/REL/d/t/d_t_time_door_beam.cpp index 556d1f77..bc9b2aa6 100644 --- a/src/REL/d/t/d_t_time_door_beam.cpp +++ b/src/REL/d/t/d_t_time_door_beam.cpp @@ -27,5 +27,5 @@ bool dTgTimeDoorBeam_c::checkPlayerPosInMtx() { return false; } - return checkIfVec3fInMatrix(matrix, dAcPy_c::LINK->mPosition); + return checkAreaBox(matrix, dAcPy_c::LINK->mPosition); } diff --git a/src/REL/d/t/d_t_touch.cpp b/src/REL/d/t/d_t_touch.cpp index de9b6999..99b46ad2 100644 --- a/src/REL/d/t/d_t_touch.cpp +++ b/src/REL/d/t/d_t_touch.cpp @@ -48,7 +48,7 @@ void dTgTouchTag::executeState_Wait() { dAcBase_c *actor = static_cast(fManager_c::searchBaseByProfName(ACTIVATORS[mActivatorIndex], nullptr)); while (actor != nullptr) { - if (actor->mRoomID == mRoomID && checkIfVec3fInMatrix(mAreaOfEffect, actor->mPosition)) { + if (actor->mRoomID == mRoomID && checkAreaBox(mAreaOfEffect, actor->mPosition)) { mFlagTimer = 5; if (mZoneFlag != 0xFF) { SceneflagManager::sInstance->setFlag(mRoomID, mZoneFlag);