diff --git a/include/functions.h b/include/functions.h index 825ce23e..02149d4d 100644 --- a/include/functions.h +++ b/include/functions.h @@ -161,4 +161,7 @@ extern void sub_080AEFB4(Entity*); extern void UnloadOBJPalette(Entity*); void sub_080322E8(Entity*); extern u32 GetTileIndex(u32, u32); +extern void sub_0806FBB4(Entity*); +extern u32 sub_080002D4(s32, s32, u32); +extern void sub_08078930(Entity*); #endif diff --git a/include/object.h b/include/object.h index 35906b66..38a3176a 100644 --- a/include/object.h +++ b/include/object.h @@ -310,7 +310,7 @@ void GiantRock(Entity*); void GiantRock2(Entity*); void Object52(Entity*); void Object53(Entity*); -void PullableLever(Entity*); +void PullableLever(); void Minecart(Entity*); void ThoughtBubble(Entity*); void HiddenLadderDown(Entity*); diff --git a/linker.ld b/linker.ld index 22dad93c..ec0f1d98 100644 --- a/linker.ld +++ b/linker.ld @@ -731,7 +731,7 @@ SECTIONS { asm/object/giantRock2.o(.text); asm/object/object52.o(.text); asm/object/object53.o(.text); - asm/object/pullableLever.o(.text); + src/object/pullableLever.o(.text); src/object/minecart.o(.text); asm/object/minecart.o(.text); src/object/thoughtBubble.o(.text); @@ -1465,7 +1465,7 @@ SECTIONS { data/animations/object/minishSizedEntrance.o(.rodata); data/const/object/giantRock2.o(.rodata); data/const/object/object53.o(.rodata); - data/const/object/pullableLever.o(.rodata); + src/object/pullableLever.o(.rodata); data/animations/object/pullableLever.o(.rodata); data/const/object/minecart.o(.rodata); data/animations/object/minecart.o(.rodata); diff --git a/src/enemy/fallingBoulder.c b/src/enemy/fallingBoulder.c index 3e81632d..aa54cb6e 100644 --- a/src/enemy/fallingBoulder.c +++ b/src/enemy/fallingBoulder.c @@ -137,7 +137,6 @@ void nullsub_148(Entity* this) { /* ... */ } - void sub_0802C4B0(Entity* this) { u32 offset; u32 index; diff --git a/src/object/pullableLever.c b/src/object/pullableLever.c new file mode 100644 index 00000000..3e122953 --- /dev/null +++ b/src/object/pullableLever.c @@ -0,0 +1,286 @@ +/** + * @file pullableLever.c + * @ingroup Objects + * + * @brief Pullable Lever object + */ + +#define NENT_DEPRECATED +#include "global.h" +#include "object.h" +#include "functions.h" +#include "sound.h" + +typedef struct { + /*0x00*/ Entity base; + /*0x68*/ u8 unk_68[8]; + /*0x70*/ u16 pullLength; + /*0x72*/ u16 leverPart; // lever part number? [0,1,2] + /*0x74*/ u8 actionDelay; + /*0x75*/ u8 unk_75; + /*0x76*/ u16 necessaryPullLength; + /*0x78*/ u8 unk_78[6]; + /*0x7e*/ u8 unk_7e; + /*0x7f*/ u8 unk_7f; + /*0x80*/ u16 initialX; + /*0x82*/ u16 initialY; + /*0x84*/ u8 unk_84[2]; + /*0x86*/ u16 pulledFlag; +} PullableLeverEntity; + +enum PullableLeverPart { HANDLE, MIDDLE, SOCKET }; + +extern void sub_080044AE(Entity*, u32, u32); + +extern u16 gUnk_02021F00[]; +extern Hitbox gUnk_080FD270; +extern Hitbox gUnk_080FD278; + +extern void (*const PullableLever_HandleActions[])(PullableLeverEntity*); +extern void (*const PullableLever_MiddleActions[])(PullableLeverEntity*); +extern const s8 PullableLever_InitialOffsets[]; +extern void (*const PullableLever_HandleSubActions[])(PullableLeverEntity*); +extern const s8 gUnk_081222B8[]; +extern const u8 gUnk_081222C0[]; + +void sub_08091504(PullableLeverEntity*); +void PullableLever_UpdateLength(PullableLeverEntity*); +void sub_0809153C(PullableLeverEntity*); + +void PullableLever(PullableLeverEntity* this) { + switch (this->leverPart) { + case HANDLE: + PullableLever_HandleActions[super->action](this); + sub_0800445C(super); + gUnk_02021F00[this->actionDelay] = this->pullLength; + break; + case MIDDLE: + PullableLever_MiddleActions[super->action](this); + break; + case SOCKET: + if (super->action == 0) { + sub_08091504(this); + } + break; + } +} + +void PullableLever_HandleInit(PullableLeverEntity* this) { + if (gEntCount < 0x46) { + PullableLeverEntity* entity1 = (PullableLeverEntity*)CreateObject(PULLABLE_LEVER, super->type, super->type2); + PullableLeverEntity* entity2 = (PullableLeverEntity*)CreateObject(PULLABLE_LEVER, super->type, super->type2); + (entity1->base).parent = super; + (entity2->base).parent = super; + entity1->leverPart = 1; + entity2->leverPart = 2; + CopyPosition(super, &entity2->base); + super->action = 1; + super->spriteSettings.draw = 1; + super->speed = 0x60; + if ((super->type2 & 1)) { + super->hitbox = &gUnk_080FD278; + } else { + super->hitbox = &gUnk_080FD270; + } + super->field_0x16 = 1; + super->x.HALF.HI += PullableLever_InitialOffsets[super->type2 * 2]; + this->initialX = super->x.HALF.HI; + super->y.HALF.HI += PullableLever_InitialOffsets[super->type2 * 2 + 1]; + this->initialY = super->y.HALF.HI; + CopyPosition(super, &entity1->base); + this->necessaryPullLength = this->unk_7e; + this->actionDelay = super->actionDelay; + InitializeAnimation(super, super->type2); + } +} + +void PullableLever_HandleAction1(PullableLeverEntity* this) { + sub_08078930(super); + if (this->pullLength != 0) { + super->direction = super->type2 << 3; + LinearMoveUpdate(super); + PullableLever_UpdateLength(this); + } +} + +void PullableLever_HandleAction2(PullableLeverEntity* this) { + sub_0806FBB4(super); + PullableLever_HandleSubActions[super->subAction - 5](this); +} + +void PullableLever_HandleSubAction0(PullableLeverEntity* this) { + u16 y; + u16 x; + Entity* player = &gPlayerEntity; + + if (this->unk_75 == 0) { + if (-player->animationState + super->type2 * 2 == 0) { + x = gUnk_081222B8[super->type2 * 2] + super->x.HALF_U.HI; + y = gUnk_081222B8[super->type2 * 2 + 1] + super->y.HALF_U.HI; + if (0x10 < sub_080002D4(x, y, player->collisionLayer) - 0xf) { + player->x.HALF.HI = x; + player->y.HALF.HI = y; + } + } + this->unk_75 = 1; + super->field_0xf = 2; + } + if (player->animationState >> 1 == super->type2) { + if (gPlayerState.framestate == 0x1a) { + if (gPlayerState.heldObject & 2) { + if (gPlayerEntity.frame & 2) { + sub_0809153C(this); + if (this->unk_75 == 1) { + this->unk_75 = 2; + EnqueueSFX(SFX_19E); + } + } + } + } + } +} + +void PullableLever_HandleSubAction1(PullableLeverEntity* this) { + super->action = 1; + this->unk_75 = 0; +} + +void PullableLever_MiddleInit(PullableLeverEntity* this) { + super->action = 1; + super->spritePriority.b0 = 5; + InitializeAnimation(super, super->parent->type2 + 8); + UpdateSpriteForCollisionLayer(super); +} + +void PullableLever_MiddleAction1(PullableLeverEntity* this) { + u16 tmp; + PullableLeverEntity* parent = ((PullableLeverEntity*)super->parent); + if (parent->pullLength < 8) { + super->spriteSettings.draw = 0; + } else { + super->spriteSettings.draw = 1; + tmp = (((PullableLeverEntity*)super->parent)->pullLength - 8) & 7; + switch (super->type2) { + case 0: + super->y.HALF.HI = (super->parent->y.HALF.HI - tmp) - 0x11; + break; + case 1: + super->x.HALF.HI = tmp + super->parent->x.HALF.HI + 0x11; + break; + case 2: + super->y.HALF.HI = tmp + super->parent->y.HALF.HI + 0x11; + break; + case 3: + super->x.HALF.HI = (super->parent->x.HALF.HI - tmp) - 0x11; + break; + } + tmp = (parent->pullLength - 8) >> 4; + if (tmp != super->animationState) { + super->animationState = tmp; + InitializeAnimation(super, tmp * 4 + super->type2 + 8); + } + } +} + +void sub_08091504(PullableLeverEntity* this) { + super->action = 1; + super->spriteSettings.draw = 1; + super->spritePriority.b0 = 6; + InitializeAnimation(super, super->type2 + 4); + UpdateSpriteForCollisionLayer(super); +} + +void sub_0809153C(PullableLeverEntity* this) { + s16 prevX; + s16 prevY; + u32 dir; + s16 diff; + s32 radius; + + Entity* player = &gPlayerEntity; + dir = gUnk_081222C0[super->type2]; + if (this->necessaryPullLength <= this->pullLength) { + return; + } + prevX = player->x.HALF.HI; + prevY = player->y.HALF.HI; + sub_080044AE(&gPlayerEntity, super->speed, dir); + if ((prevX == gPlayerEntity.x.HALF.HI) && (prevY == gPlayerEntity.y.HALF.HI)) { + return; + } + + switch (super->type2) { + case 0: + diff = player->y.HALF.HI - prevY; + break; + case 1: + diff = prevX - gPlayerEntity.x.HALF.HI; + break; + case 2: + diff = prevY - gPlayerEntity.y.HALF.HI; + break; + case 3: + diff = gPlayerEntity.x.HALF.HI - prevX; + break; + } + radius = (diff << 0x18); + super->x.WORD += gSineTable[dir * 8] * (radius >> 0x10); + super->y.WORD -= gSineTable[dir * 8 + 0x40] * (radius >> 0x10); + PullableLever_UpdateLength(this); + if (this->necessaryPullLength <= this->pullLength) { + EnqueueSFX(SFX_BUTTON_PRESS); + SetFlag(this->pulledFlag); + } else { + if (--super->field_0xf == 0) { + super->field_0xf = 0x10; + EnqueueSFX(SFX_10F); + } + } +} + +void PullableLever_UpdateLength(PullableLeverEntity* this) { + switch (super->type2) { + case 0: + this->pullLength = super->y.HALF.HI - this->initialY; + break; + case 1: + this->pullLength = this->initialX - super->x.HALF.HI; + break; + case 2: + this->pullLength = this->initialY - super->y.HALF.HI; + break; + case 3: + this->pullLength = super->x.HALF.HI - this->initialX; + break; + } + + if (CheckFlags(this->pulledFlag) && (this->pullLength == 0)) { + ClearFlag(this->pulledFlag); + } +} + +void (*const PullableLever_HandleActions[])(PullableLeverEntity*) = { + PullableLever_HandleInit, + PullableLever_HandleAction1, + PullableLever_HandleAction2, +}; +void (*const PullableLever_MiddleActions[])(PullableLeverEntity*) = { + PullableLever_MiddleInit, + PullableLever_MiddleAction1, +}; +const s8 PullableLever_InitialOffsets[] = { + 0, 9, -9, 0, 0, -9, 9, 0, +}; +void (*const PullableLever_HandleSubActions[])(PullableLeverEntity*) = { + PullableLever_HandleSubAction0, + PullableLever_HandleSubAction1, +}; +const s8 gUnk_081222B8[] = { + 0, 10, -8, 0, 0, -10, 8, 0, +}; +const u8 gUnk_081222C0[] = { + 16, + 24, + 0, + 8, +}; diff --git a/src/object/pushableLever.c b/src/object/pushableLever.c index 503ec5b5..dff5ed9a 100644 --- a/src/object/pushableLever.c +++ b/src/object/pushableLever.c @@ -23,7 +23,7 @@ typedef struct { enum PushableLeverAction { INIT, IDLE, - PUSHING + PUSHING, }; extern void (*const PushableLever_Actions[])(PushableLeverEntity*); @@ -145,4 +145,4 @@ const u8 PushableLever_InitialOffsets[] = { }; const u8 PushableLever_PushedOffsets[] = { 0, 0, 0, 0, 0, 255, 0, 0, -}; \ No newline at end of file +}; diff --git a/src/projectile/spiderWeb.c b/src/projectile/spiderWeb.c index 40bc8007..3f683296 100644 --- a/src/projectile/spiderWeb.c +++ b/src/projectile/spiderWeb.c @@ -8,10 +8,6 @@ typedef struct { u8 direction; } PACKED Struct_0812A074; -extern void sub_0806FBB4(Entity*); -extern u32 sub_080002D4(s32, s32, u32); -extern void sub_08078930(Entity*); - extern void (*const SpiderWeb_Functions[])(Entity*); extern void (*const SpiderWeb_Actions[])(Entity*); extern const u8 gUnk_0812A03C[];