/** * @file miscManager.c * @ingroup Managers * * @brief Various different functionalities selected with paramA/unk_0a. */ #include "manager/miscManager.h" #include "area.h" #include "flags.h" #include "item.h" #include "message.h" #include "object.h" #include "asm.h" #include "effects.h" #include "physics.h" #include "player.h" #include "room.h" #include "script.h" #include "sound.h" #include "tiles.h" #include "scroll.h" #include "subtask.h" #if defined(USA) || defined(DEMO_USA) || defined(DEMO_JP) #include "common.h" #endif void MiscManager_Type0(MiscManager*); void MiscManager_Type1(MiscManager*); void MiscManager_Type3(MiscManager*); void MiscManager_Type4(MiscManager*); void MiscManager_Type5(MiscManager*); void MiscManager_Type6(MiscManager*); void MiscManager_Type7(MiscManager*); void MiscManager_Type8(MiscManager*); void MiscManager_Type9(MiscManager*); void MiscManager_TypeA(MiscManager*); void MiscManager_TypeB(MiscManager*); void MiscManager_TypeC(MiscManager*); void MiscManager_TypeD(MiscManager*); #ifndef EU void MiscManager_TypeE(MiscManager*); #endif #if defined(USA) || defined(DEMO_USA) || defined(DEMO_JP) void MiscManager_TypeF(MiscManager*); #endif // clang-format off void (*const MiscManager_Types[])(MiscManager*) = { MiscManager_Type0, MiscManager_Type1, MiscManager_Type1, // dup MiscManager_Type3, MiscManager_Type4, MiscManager_Type5, MiscManager_Type6, MiscManager_Type7, MiscManager_Type8, MiscManager_Type9, MiscManager_TypeA, MiscManager_TypeB, MiscManager_TypeC, MiscManager_TypeD, #ifndef EU MiscManager_TypeE, #endif #if defined(USA) || defined(DEMO_USA) || defined(DEMO_JP) MiscManager_TypeF, #endif }; // clang-format on typedef struct { u16 x; u16 y; u16 width; u16 height; u16 unk_08; } PACKED ALIGNED(2) MiscManager_HelperStruct; const MiscManager_HelperStruct gUnk_08108354[] = { { 0xF0, 0xB0, 0xF0, 0xB0, 0x100 }, { 0x188, 0x190, 0x28, 0x30, 0x100 }, { 0xF0, 0x340, 0xF0, 0xB0, 0x80 }, { 0x180, 0x278, 0x60, 0x38, 0x80 }, }; const u32 gUnk_08108354_terminator = 0xFFFF; // terminator for the previous array extern u16 script_PlayerAtDarkNut1[]; extern u16 script_PlayerAtDarkNut2[]; extern u16 script_PlayerAtDarkNut3[]; extern u16 script_PlayerAtMadderpillar[]; u16* const gUnk_08108380[] = { script_PlayerAtDarkNut1, script_PlayerAtDarkNut2, script_PlayerAtDarkNut3, script_PlayerAtMadderpillar, }; void sub_08058F44(u32, u32, u32); void sub_08058F84(u32, u32); void sub_08059064(MiscManager*); void sub_080592EC(MiscManager*); void sub_0805930C(MiscManager*); u32 sub_080593CC(MiscManager*); // to be moved to headers extern EntityData gUnk_080F4B88[]; void MiscManager_Main(MiscManager* this) { MiscManager_Types[super->type](this); } void MiscManager_Type0(MiscManager* this) { if (super->action == 0) super->action = 1; if (!CheckRoomFlag(super->type2)) return; sub_08058F44(0x128, 0x68, super->type2 + 1); sub_08058F44(0x158, 0x68, super->type2 + 2); sub_08058F44(0x128, 0x98, super->type2 + 3); sub_08058F44(0x158, 0x98, super->type2 + 4); SoundReq(SFX_124); DeleteThisEntity(); } void sub_08058F44(u32 x, u32 y, u32 flag) { if (CheckRoomFlag(flag)) return; if (GetTileTypeAtRoomCoords(x, y, LAYER_BOTTOM) != TILE_TYPE_97) return; SetTileType(TILE_TYPE_38, ((x >> 4) & 0x3F) | (((y >> 4) & 0x3F) << 6), LAYER_BOTTOM); sub_08058F84(x, y); } void sub_08058F84(u32 x, u32 y) { Entity* particle = CreateObject(DIRT_PARTICLE, 0, 0); if (!particle) return; particle->x.HALF.HI = gRoomControls.origin_x + x; particle->y.HALF.HI = gRoomControls.origin_y + y; } void MiscManager_Type1(MiscManager* this) { switch (super->action) { case 0: super->action = 1; if (super->type == 1) { super->subAction = 7; super->subtimer = 6; } else { super->subAction = 8; super->subtimer = 2; } if (CheckFlags(this->flag2)) { DeleteManager(super); } break; case 1: if (CheckFlags(this->flag2)) { super->action = 2; super->timer = 120; RequestPriorityDuration((Entity*)this, 240); sub_08059064(this); } break; case 2: if (super->timer == 90) { SetPlayerControl(2); PutAwayItems(); } if (super->timer == 60) { gPlayerEntity.base.animationState = super->subtimer; } if (!--super->timer) { super->action = 3; MenuFadeIn(5, super->subAction); } break; default: SetFlag(this->flag2); SetPlayerControl(1); DeleteThisEntity(); } } void sub_08059064(MiscManager* this) { Entity* key; key = CreateObject(GROUND_ITEM, ITEM_SMALL_KEY, 0); if (!key) return; key->timer = 2; key->x.HALF.HI = this->x + gRoomControls.origin_x; key->y.HALF.HI = this->y + gRoomControls.origin_y; } void MiscManager_Type3(MiscManager* this) { u32 tmp = 0; if (super->action == 0) { super->action = 1; if (CheckLocalFlag(0x60)) { tmp = 1; } else { SetLocalFlag(0x5F); } } else { if (CheckLocalFlag(0x60)) { ClearLocalFlag(0x5F); tmp = 1; } } if (tmp) { LoadRoomEntityList(gUnk_080F4B88); DeleteManager(super); } } void MiscManager_Type4(MiscManager* this) { if (super->action == 0) { super->action = 1; SetEntityPriority((Entity*)this, PRIO_PLAYER_EVENT); } if (CheckLocalFlag(0x6c)) { if (CheckLocalFlag(0x4b)) { SetLocalFlag(0x4a); } else { ClearLocalFlag(0x4a); } } else { ClearLocalFlag(0x4a); } } void MiscManager_Type5(MiscManager* this) { switch (super->action) { default: if (!--super->timer) { CreateDeathFxAt(this->x, this->y, super->type2); RestorePrevTileEntity(TILE_LOCAL(this->x, this->y), super->type2); SoundReq(SFX_TASK_COMPLETE); DeleteThisEntity(); } break; case 0: if (CheckFlags(this->flag2)) { DeleteThisEntity(); } super->action = 1; SetTileType(TILE_TYPE_869, TILE_LOCAL(this->x, this->y), super->type2); break; case 1: if (CheckFlags(this->flag2)) { RequestPriorityDuration((Entity*)this, 75); super->timer = 45; super->action++; } } } void MiscManager_Type6(MiscManager* this) { if (super->action == 0) { super->action = 1; super->type2 = CheckFlags(this->flag2); if (super->type2) { gRoomVars.lightLevel = this->y; } else { gRoomVars.lightLevel = this->x; } } else { u32 tmp = CheckFlags(this->flag2); if (super->type2 != tmp) { super->type2 = tmp; if (tmp) { gRoomVars.lightLevel = this->y; } else { gRoomVars.lightLevel = this->x; } } } } void MiscManager_Type7(MiscManager* this) { const MiscManager_HelperStruct* data; gRoomVars.lightLevel = 0; for (data = gUnk_08108354; data->x != 0xFFFF; data++) { if (CheckPlayerInRegion(data->x, data->y, data->width, data->height)) { gRoomVars.lightLevel = data->unk_08; } } if (super->action == 0) { super->action = 1; gArea.lightLevel = gRoomVars.lightLevel; } } void sub_08059278(void) { MiscManager* tmp; tmp = (MiscManager*)FindEntityByID(MANAGER, MISC_MANAGER, 0x6); if (tmp) { MiscManager_Main(tmp); } } void MiscManager_Type8(MiscManager* this) { super->action = 1; gRoomControls.camera_target = &gPlayerEntity.base; } void MiscManager_Type9(MiscManager* this) { if (super->action == 0) { super->action = 1; if (CheckFlags(this->flag2)) { sub_080592EC(this); DeleteThisEntity(); } } else { if (CheckFlags(this->flag2)) { sub_080592EC(this); sub_0805930C(this); #ifndef EU SoundReq(SFX_16E); #endif DeleteThisEntity(); } } } void sub_080592EC(MiscManager* this) { SetDirtTile(TILE_LOCAL(this->x, this->y)); } void sub_0805930C(MiscManager* this) { Entity* tmp; #ifdef EU tmp = CreateObject(SPECIAL_FX, FX_BIG_EXPLOSION2, 0x0); #else tmp = CreateObject(SPECIAL_FX, FX_BIG_EXPLOSION2, 0x40); #endif if (!tmp) return; tmp->x.HALF.HI = this->x + gRoomControls.origin_x; tmp->y.HALF.HI = this->y + gRoomControls.origin_y; tmp->collisionLayer = 1; } void SetDirtTile(u32 tilePos) { SetTileType(TILE_TYPE_29, tilePos, LAYER_BOTTOM); SetTileType(TILE_TYPE_0, tilePos, LAYER_TOP); SetTileType(TILE_TYPE_0, tilePos + TILE_POS(0, -1), LAYER_TOP); } void MiscManager_TypeA(MiscManager* this) { super->action = 1; if (this->flag1 == gTextRender.curToken.textIndex) { SetFlag(this->flag2); DeleteThisEntity(); } } void MiscManager_TypeB(MiscManager* this) { if (sub_080593CC(this)) { if (++super->timer >= 8) { DoApplicableTransition(this->x - gRoomControls.origin_x, this->y - gRoomControls.origin_y, 0xFF, 0xA); } } else { super->timer = 0; } } bool32 sub_080593CC(MiscManager* this) { if (!(gPlayerState.flags & PL_MINISH) && gPlayerState.swim_state != 0 && gPlayerEntity.base.animationState == 0 && (gPlayerState.playerInput.heldInput & INPUT_ANY_DIRECTION) == INPUT_UP) { return EntityWithinDistance(&gPlayerEntity.base, this->x, this->y + 12, 6); } return FALSE; } void MiscManager_TypeC(MiscManager* this) { Entity* tmp; if (CheckFlags(this->flag2)) { DeleteThisEntity(); } if (!CheckFlags(this->flag1)) return; tmp = CreateObject(SPECIAL_FX, FX_BIG_EXPLOSION, 0); if (!tmp) return; tmp->collisionLayer = 2; tmp->x.HALF.HI = this->x + gRoomControls.origin_x; tmp->y.HALF.HI = this->y + gRoomControls.origin_y; EnqueueSFX(SFX_1B0); DeleteThisEntity(); } void MiscManager_TypeD(MiscManager* this) { if (!CheckFlags(this->flag2)) { SetPlayerControl(3); if (gRoomControls.reload_flags) return; if (gRoomVars.didEnterScrolling) { StartPlayerScript(gUnk_08108380[gRoomControls.scroll_direction]); } else { StartPlayerScript(gUnk_08108380[gPlayerEntity.base.animationState >> 1]); } } DeleteThisEntity(); } #ifndef EU void MiscManager_TypeE(MiscManager* this) { switch (super->action) { case 0: super->action = 1; // fall through case 1: if (!GetInventoryValue(ITEM_FOURSWORD)) return; if (CheckLocalFlagByBank(FLAG_BANK_10, LV6SOTO_01_CAP_0)) return; super->action = 2; SetNextAreaHint(TEXT_INDEX(TEXT_EZLO, 0xf)); break; case 2: default: if (gArea.unk28.textBaseIndex != 0xFF) { DeleteThisEntity(); } if (CheckLocalFlagByBank(FLAG_BANK_10, LV6SOTO_01_CAP_0)) { sub_0801855C(); DeleteThisEntity(); } } } #endif #if defined(USA) || defined(DEMO_USA) || defined(DEMO_JP) void MiscManager_TypeF(MiscManager* this) { SetEntityPriority((Entity*)this, PRIO_PLAYER_EVENT); if (gPlayerEntity.base.action == PLAYER_TALKEZLO) { DeleteThisEntity(); } gInput.heldKeys |= SELECT_BUTTON; } #endif