diff options
Diffstat (limited to 'src')
125 files changed, 16320 insertions, 1416 deletions
diff --git a/src/chooseFile.c b/src/chooseFile.c index 0c5a9474..143819f2 100755 --- a/src/chooseFile.c +++ b/src/chooseFile.c @@ -55,7 +55,7 @@ static void sub_08050624(u32); static void sub_0805066C(void); static void sub_080507FC(void); -extern void sub_0801D66C(const void* src, void* dest, u32 size); +extern void _DmaCopy(const void* src, void* dest, u32 size); extern void sub_08056FEC(u32, struct_020227E8*); extern void sub_0805F46C(u32, struct_080FC844*); extern void sub_0801C4A0(u32, u32); @@ -83,7 +83,7 @@ void sub_08050318(u32 arg0, u32 arg1) { struct_080FC844 var0; sub_08050384(); - sub_0801D66C(&gUnk_080FC844, &var0, sizeof(gUnk_080FC844)); + _DmaCopy(&gUnk_080FC844, &var0, sizeof(gUnk_080FC844)); sub_08056FEC(arg1, &gUnk_020227E8); var0.unk10 |= gUnk_080FC85C[arg0][0] << 0xC; sub_0805F46C(gUnk_080FC85C[arg0][1], &var0); @@ -136,7 +136,7 @@ void sub_0805041C(u32 saveFileId) { if (saveFileId < 3) { ((struct_02000000 *)0x2000000)->saveFileId = saveFileId; saveFile = &gSaveFiles[saveFileId]; - sub_0801D66C(saveFile, &gUnk_02002A40, sizeof(*saveFile)); + _DmaCopy(saveFile, &gUnk_02002A40, sizeof(*saveFile)); } sub_080503E4(saveFileId); } @@ -281,7 +281,7 @@ void sub_0805070C(void) { for (j = 0; j < 6; j++) { sub_0805F7DC(playerName[j], var0); } - sub_0801D66C(var0->unk8, (void*)(OBJ_VRAM0 + 0x4000 + i * 0x200), 0x200); + _DmaCopy(var0->unk8, (void*)(OBJ_VRAM0 + 0x4000 + i * 0x200), 0x200); } sub_0805F300(var0); } @@ -307,7 +307,7 @@ void sub_08050790(void) { sub_0805F7DC(var1, var0); var1++; } - sub_0801D66C(gUnk_02000D00, (void*)(BG_VRAM + i * 0x400), 0x400); + _DmaCopy(gUnk_02000D00, (void*)(BG_VRAM + i * 0x400), 0x400); } sub_0805F300(var0); } diff --git a/src/code_0805436C.c b/src/code_0805436C.c index 595670e8..abdc457d 100644 --- a/src/code_0805436C.c +++ b/src/code_0805436C.c @@ -160,7 +160,7 @@ void sub_08054524(void) { bVar1 = 0; } - sub_0801D66C(&gUnk_080015BC + gUnk_080FE1C6[bVar1] * 0x8, &gUnk_02034398, 0x20); + _DmaCopy(&gUnk_080015BC + gUnk_080FE1C6[bVar1] * 0x8, &gUnk_02034398, 0x20); } #else NAKED diff --git a/src/code_08077DF4.c b/src/code_08077DF4.c index 1f6d9246..69dd5820 100644 --- a/src/code_08077DF4.c +++ b/src/code_08077DF4.c @@ -29,9 +29,9 @@ void UpdateItemAnim(Entity *ent) sub_08077E54(ent); } -void sub_08077E3C(Entity *ent) +void sub_08077E3C(Entity *ent, u32 idx) { - sub_080042BA(&gPlayerEntity); + sub_080042BA(&gPlayerEntity, idx); sub_08077E54(ent); } diff --git a/src/code_0808091C.c b/src/code_0808091C.c index dcb86728..ae04dcad 100644 --- a/src/code_0808091C.c +++ b/src/code_0808091C.c @@ -5,10 +5,12 @@ #include "room.h" extern void sub_0805E5A8(); +extern void sub_08080BC4(void); extern RoomControls gRoomControls; extern u32 gUnk_0200B650; extern u32 gUnk_02025EB0; +extern u8 gUnk_02000070; extern void DoExitTransition(ScreenTransitionData*); extern void sub_080809D4(); @@ -53,7 +55,6 @@ void sub_08080930(void) } u32* GetLayerByIndex(u32 param_1) - { if (param_1 == 2) { @@ -64,9 +65,79 @@ u32* GetLayerByIndex(u32 param_1) } void sub_08080964(u16 time, u32 magnitude) - { gRoomControls.screenShakeTime = time; gRoomControls.screenShakeMagnitude = magnitude & 7; return; } + +void sub_08080974(u32 arg0, u32 arg1) { + u32 var0, var1; + RoomControls* roomControls = &gRoomControls; + + var0 = roomControls->roomOriginX; + if (arg0 <= var0 + 120) { + roomControls->roomScrollX = var0; + } else { + var0 += roomControls->width; + var1 = var0 - 120; + if (arg0 < var1) { + var1 = arg0; + } + roomControls->roomScrollX = var1 - 120; + } + + var0 = roomControls->roomOriginY; + if (arg1 <= var0 + 80) { + roomControls->roomScrollY = var0; + } else { + var0 += roomControls->height; + var1 = var0 - 80; + if (arg1 < var1) { + var1 = arg1; + } + roomControls->roomScrollY = var1 - 80; + } + + sub_080809D4(); + gUnk_02000070 = 1; +} + +void sub_080809D4(void) { + register Entity* target asm("r4"); + int x, y; + int var1, var0; + RoomControls* roomControls = &gRoomControls; + roomControls->unk6 &= 0xFB; + + target = roomControls->cameraTarget; + x = target->x.HALF.HI; + var0 = roomControls->roomOriginX; + if (x <= var0 + 120) { + roomControls->roomScrollX = var0; + } else { + var0 += roomControls->width; + var1 = var0 - 120; + if (x < var1) { + var1 = (u16)target->x.HALF.HI; + } + roomControls->roomScrollX = var1 - 120; + } + + target = roomControls->cameraTarget; + y = target->y.HALF.HI; + var0 = roomControls->roomOriginY; + if (y <= var0 + 80) { + roomControls->roomScrollY = var0; + } else { + var0 += roomControls->height; + var1 = var0 - 80; + if (y < var1) { + var1 = (u16)target->y.HALF.HI; + } + roomControls->roomScrollY = var1 - 80; + } + + sub_08080BC4(); + gUnk_02000070 = 1; +} diff --git a/src/code_080A29BC.c b/src/code_080A29BC.c index e9d5e763..bb9d1701 100644 --- a/src/code_080A29BC.c +++ b/src/code_080A29BC.c @@ -52,7 +52,7 @@ Entity * sub_080A2A3C(Entity *parent, u32 form, u32 subtype, u32 param_4) ent = CreateObjectWithParent(parent, 0, form, subtype); if (ent != NULL) { ent->actionDelay = 5; - ent->field_0x86 = param_4; + *(u32*)(&ent->field_0x86) = param_4; } return ent; } diff --git a/src/createObject.c b/src/createObject.c index 93db1d93..ad852900 100644 --- a/src/createObject.c +++ b/src/createObject.c @@ -1,21 +1,94 @@ #include "global.h" #include "entity.h" +#include "room.h" extern Entity* GetEmptyEntity(); extern void AppendEntityToList(Entity*, u8); -Entity* CreateObject(u32 subtype, u32 param1, u32 param2) +Entity* CreateObject(u32 subtype, u32 form, u32 parameter) { + Entity* ent; -{ - Entity* newEnt; + ent = GetEmptyEntity(); + if (ent != NULL) { + ent->entityType.type = 6; + ent->entityType.subtype = subtype; + ent->entityType.form = form; + ent->entityType.parameter = parameter; + AppendEntityToList(ent, 6); + } + return ent; +} + +Entity* CreateObjectWithParent(Entity* parentEnt, u32 subtype, u32 form, u32 parameter) { + Entity* ent; + + ent = CreateObject(subtype, form, parameter); + if (ent != NULL) { + ent->parent = parentEnt; + CopyPosition(parentEnt, ent); + } + + return ent; +} + +Entity* CreateFx(Entity* parentEnt, u32 form, u32 parameter) { + return CreateObjectWithParent(parentEnt, 0xf, form, parameter); +} + +void CreateDust(Entity* parent) { + CreateFx(parent, 2, 0); +} + +void CreateDustAt(s32 xOff, s32 yOff, u32 layer) { + Entity* ent; + + ent = CreateObject(0xf, 2, 0); + if (ent != NULL) { + ent->x.HALF.HI = gRoomControls.roomOriginX + xOff; + ent->y.HALF.HI = gRoomControls.roomOriginY + yOff; + ent->collisionLayer = layer; + } +} + +void CreateDustSmall(Entity* parent) { + CreateFx(parent, 0x11, 0); +} + +void CreateExplosionBroken(Entity* parent) { + CreateFx(parent, 0x6, 0); +} + +void CreateWaterSplash(Entity* parent) { + CreateFx(parent, 0xb, 0); +} + +Entity* sub_080A2A20(Entity* parent, u32 form, u32 parameter) { + Entity* ent; + + ent = CreateObjectWithParent(parent, 0, form, parameter); + if (ent != NULL) { + ent->actionDelay = 5; + } + return ent; +} + +Entity* sub_080A2A3C(Entity* parent, u32 form, u32 subtype, u32 param_4) { + Entity* ent; + + ent = CreateObjectWithParent(parent, 0, form, subtype); + if (ent != NULL) { + ent->actionDelay = 5; + ent->field_0x86.HWORD = param_4; + } + return ent; +} + +Entity* CreateWaterTrace(Entity* parent) { + Entity* ent; - newEnt = GetEmptyEntity(); - if (newEnt != NULL) { - (newEnt->entityType).type = 6; - (newEnt->entityType).subtype = subtype; - (newEnt->entityType).form = param1; - (newEnt->entityType).parameter = param2; - AppendEntityToList(newEnt, 6); + ent = CreateFx(parent, 0x20, 0); + if (ent != NULL) { + ent->spritePriority.b0 = 7; } - return newEnt; + return ent; } diff --git a/src/createObjectWithParent.c b/src/createObjectWithParent.c deleted file mode 100644 index bee2c86c..00000000 --- a/src/createObjectWithParent.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "global.h" -#include "entity.h" - -extern Entity* CreateObject(); -extern void CopyPosition(); - -Entity* CreateObjectWithParent(Entity* parentEnt, u32 subtype, u32 param1, u32 param2) { - Entity* ent; - - ent = CreateObject(subtype, param1, param2); - if (ent != NULL) { - ent->parent = parentEnt; - CopyPosition(parentEnt, ent); - } - - return ent; -} @@ -12,13 +12,12 @@ void _DmaFill32(u32 value, u8* dest, u32 size) { DmaFill32(3, value, dest, size); } -void _DmaZero(u8 *src, u32 size) -{ +void _DmaZero(u8* src, u32 size) { u32 zero = 0; switch (((u32)src | size) & 3) { case 0: - _DmaFill32(0,src, size); + _DmaFill32(0, src, size); break; case 2: _DmaFill16(0, src, size); @@ -28,6 +27,23 @@ void _DmaZero(u8 *src, u32 size) *src = zero; src++; size--; - } while (size != 0); + } while (size != 0); + } +} + +void _DmaCopy(const u8* src, u8* dst, u32 size) { + switch (((u32)src | (u32)dst | size) & 3) { + case 0: + DmaCopy32(3, src, dst, size); + break; + case 2: + DmaCopy16(3, src, dst, size); + break; + default: + do { + *dst = *src; + src++; + dst++; + } while (--size); } } diff --git a/src/enemy/acroBandits.c b/src/enemy/acroBandits.c index 7289d3a7..724880ac 100644 --- a/src/enemy/acroBandits.c +++ b/src/enemy/acroBandits.c @@ -4,7 +4,6 @@ extern u32 sub_080002D4(s32, s32, u32); extern s32 sub_080012DC(Entity*); -extern void sub_08001324(Entity*); extern u32 sub_080044EC(Entity*, u32); extern u32 sub_08031E04(Entity*); extern void sub_08031E48(Entity*, Entity*); @@ -13,12 +12,10 @@ extern u32 sub_080322A4(Entity*); void sub_080322E8(Entity*); extern void sub_08032338(Entity*); extern Entity* sub_08049DF4(u32); -extern void sub_0804A9FC(Entity*, u32); extern void sub_0804AA30(Entity*, void (*const funcs[])(Entity*)); extern u32 sub_0806FCB8(Entity*, u32, u32, u32); extern u32 GetNextFunction(Entity*); extern void SetChildOffset(Entity*, s32, s32, s32); -extern u32 Random(void); extern Entity* gUnk_020000B0; extern u8 gEntCount; @@ -29,7 +26,7 @@ extern void (*const gUnk_080CE58C[])(Entity*); extern void (*const gUnk_080CE5C8[])(Entity*); extern u8 gUnk_080CE5B0[8]; extern u8 gUnk_080CE5B8[8]; -extern union SplitHWord gUnk_080CE5C0[4]; +extern s8 gUnk_080CE5C0[8]; extern u16 gUnk_080CE5F0[5]; extern u8 gUnk_080CE5FA[20]; // Directions @@ -209,15 +206,14 @@ void sub_08031C1C(Entity* this) { } } -#if NON_MATCHING + void sub_08031C58(Entity* this) { - u8 tmp; Entity *a, *b; GetNextFrame(this); if (this->frames.b.f3) { if (gEntCount < 0x43) { - tmp = Random(); + u32 tmp = Random(); tmp &= 3; a = CreateEnemy(0x2e, 1); @@ -225,30 +221,30 @@ void sub_08031C58(Entity* this) { a->parent = NULL; a->field_0x74.HALF.LO = tmp; sub_08031E48(this, a); + a->attachedEntity = CreateEnemy(0x2e, 1); - b = CreateEnemy(0x2e, 1); - a->attachedEntity = b; + b = a->attachedEntity; b->entityType.parameter = 1; b->parent = a; b->field_0x74.HALF.LO = tmp; sub_08031E48(this, b); + b->attachedEntity = CreateEnemy(0x2e, 1); - a = CreateEnemy(0x2e, 1); - b->attachedEntity = a; + a = b->attachedEntity; a->entityType.parameter = 2; a->parent = b; a->field_0x74.HALF.LO = tmp; sub_08031E48(this, a); + a->attachedEntity = CreateEnemy(0x2e, 1); - b = CreateEnemy(0x2e, 1); - a->attachedEntity = b; + b = a->attachedEntity; b->entityType.parameter = 3; b->parent = a; b->field_0x74.HALF.LO = tmp; sub_08031E48(this, b); + b->attachedEntity = CreateEnemy(0x2e, 1); - a = CreateEnemy(0x2e, 1); - b->attachedEntity = a; + a = b->attachedEntity; a->entityType.parameter = 4; a->parent = b; a->attachedEntity = NULL; @@ -267,12 +263,6 @@ void sub_08031C58(Entity* this) { } } } -#else -NAKED -void sub_08031C58(Entity* this) { - asm(".include \"asm/non_matching/acroBandits/sub_08031C58.inc\""); -} -#endif void sub_08031D70(Entity* this) { GetNextFrame(this); @@ -308,35 +298,25 @@ void sub_08031DC4(Entity* this) { } } -#if NON_MATCHING u32 sub_08031E04(Entity* this) { Entity* ent; - union SplitHWord* tmp; - int x, y; + s8* tmp; ent = sub_08049DF4(1); if (ent == NULL) return 0; tmp = &gUnk_080CE5C0[this->frames.all & 6]; - x = ent->x.HALF.HI + tmp->HALF.LO; - y = ent->y.HALF.HI + tmp->HALF.HI; - return sub_0806FCB8(this, x, y, 0x50); -} -#else -NAKED -u32 sub_08031E04(Entity* this) { - asm(".include \"asm/non_matching/acroBandits/sub_08031E04.inc\""); + return sub_0806FCB8(this, ent->x.HALF.HI + tmp[0], ent->y.HALF.HI + tmp[1], 0x50); } -#endif void sub_08031E48(Entity* this, Entity* child) { CopyPosition(this, child); child->field_0x6c.HALF.LO = this->field_0x6c.HALF.LO; child->field_0x70.HALF.LO = this->field_0x70.HALF.LO; child->field_0x70.HALF.HI = this->field_0x70.HALF.HI; - child->filler4[0] = this->filler4[0]; - child->filler4[1] = this->filler4[1]; + child->field_0x6e.HALF.LO = this->field_0x6e.HALF.LO; + child->field_0x6e.HALF.HI = this->field_0x6e.HALF.HI; child->field_0x7c.WORD = (s32)this; } @@ -362,7 +342,7 @@ void sub_08031EE8(Entity* this) { if (this->height.HALF.HI < 1) { draw = this->spriteSettings.b.draw; if (!draw) - sub_08004488(299); + EnqueueSFX(299); this->spriteSettings.b.draw = 1; } @@ -429,11 +409,11 @@ void sub_08032008(Entity* this) { } } - if (this->direction & 0xf) { - this->spriteSettings.b.flipX = !(!(this->direction & 0x10) ^ 1); - } + if (this->direction & 0xf) + this->spriteSettings.b.flipX = (this->direction >> 4 ^ 1); + - sub_080AEF88(this); + ProcessMovement(this); } else { if (this->field_0x76.HALF.HI == 0) { if (sub_0806FCB8(this, parent->x.HALF.HI, parent->y.HALF.HI, 1) == 0) { diff --git a/src/enemy/beetle.c b/src/enemy/beetle.c new file mode 100644 index 00000000..aa51a736 --- /dev/null +++ b/src/enemy/beetle.c @@ -0,0 +1,359 @@ +#include "entity.h" +#include "functions.h" +#include "player.h" + +extern u32 PlayerInRange(Entity*, u32, u32); + +u32 sub_08021D00(); +void sub_08021D44(Entity* this, u32 param_2); + +extern void (*const gUnk_080CB590[])(Entity*); +extern void (*const gUnk_080CB5A8[])(Entity*); +extern void (*const gUnk_080CB5C8[])(Entity*); +extern void (*const gUnk_080CB5D4[])(Entity*); + +extern const s8 gUnk_080CB5DC[]; +extern const s8 gUnk_080CB5E4[]; + +void Beetle(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CB590); +} + +void sub_08021768(Entity* this) { + gUnk_080CB5A8[this->action](this); +} + +void sub_08021780(Entity* this) { + switch (this->bitfield) { + case 0x80: + if (gPlayerState.field_0xa8 == 24) { + sub_08021768(this); + } else { + this->action = 5; + this->actionDelay = 0xb4; + this->field_0xf = 0; + this->flags &= ~0x80; + this->spritePriority.b0 = 3; + CopyPositionAndSpriteOffset(&gPlayerEntity, this); + this->height.HALF.HI = -1; + ((u8*)&this->field_0x86)[1] = 1; + InitializeAnimation(this, 6); + } + break; + case 0x93: + sub_08021768(this); + break; + } + + if (this->currentHealth == 0) + this->field_0x42 = 0; + + sub_0804AA30(this, gUnk_080CB590); +} + +void sub_08021818(Entity* this) { + if (this->entityType.form == 0) { + sub_0804A7D4(this); + } else { + Entity* ent = this->parent; + if (ent) { + ent->field_0xf--; + this->parent = NULL; + } + CreateDeathFx(this, 0xf0, 0); + } +} + +void sub_08021848(Entity* this) { + if (sub_0806F520(this)) { + gUnk_080CB5C8[this->previousActionFlag](this); + } else { + this->action = 3; + this->height.HALF.HI = 0; + InitializeAnimation(this, 2); + } +} + +void sub_0802187C(Entity* this) { + this->previousActionFlag = 2; +} + +void nullsub_130(Entity* this) { +} + +void sub_08021888(Entity* this) { + if (sub_0806F3E4(this)) + sub_08021818(this); +} + +void Beetle_Initialize(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->field_0x1c = 1; + InitializeAnimation(this, 3); +} + +void sub_080218B4(Entity* this) { + gUnk_080CB5D4[this->entityType.parameter](this); +} + +void sub_080218CC(Entity* this) { + if (this->previousActionFlag == 0) { + this->previousActionFlag = 1; + this->spriteSettings.b.draw = 1; + this->direction = ((sub_08049F84(this, 1) ^ 0x10) + gUnk_080CB5DC[Random() & 7]) & 0x1f; + this->nonPlanarMovement = 0x100; + this->field_0x20 = 0x12000; + } + + GetNextFrame(this); + if (this->frames.all & 1) { + sub_080AEFE0(this); + if (sub_080044EC(this, 0x1c00) == 0) + this->frameDuration = 1; + } + + if (this->frames.all & 0x80) { + this->action = 2; + this->actionDelay = (Random() & 0x38) + 8; + this->field_0xf = 1; + this->flags |= 0x80; + this->nonPlanarMovement = 0x180; + InitializeAnimation(this, 0); + } +} + +void sub_08021984(Entity* this) { + if (this->previousActionFlag == 0) { + this->previousActionFlag = 1; + this->flags |= 0x80; + this->spriteSettings.b.draw = 3; + this->height.HALF.HI = -0x80; + this->spriteRendering.b3 = 1; + this->spriteOrientation.flipY = 1; + EnqueueSFX(0x12d); + } + + if (sub_08003FC4(this, 0x1800) == 0) { + this->action = 2; + this->actionDelay = 16; + this->field_0xf = 1; + this->spriteSettings.b.draw = 1; + this->nonPlanarMovement = 0x180; + ((u8*)&this->field_0x86)[0] = 60; + InitializeAnimation(this, 0); + UpdateSpriteForCollisionLayer(this); + } +} + +void sub_08021A10(Entity* this) { + GetNextFrame(this); + if (sub_080041A0(this, &gPlayerEntity, 120, 80) && sub_08021D00(this) == 0) { + if (--this->actionDelay == 0) { + this->action = 3; + this->actionDelay = (Random() & 0x3f) + 30; + sub_08021D44(this, this->direction); + InitializeAnimation(this, 2); + } + } +} + +void sub_08021A64(Entity* this) { + if (!sub_08021D00(this)) { + if (--this->actionDelay == 0) { + this->action = 2; + this->actionDelay = (Random() & 0x1f) + 0x1e; + InitializeAnimation(this, 0); + } + + if (--this->field_0xf == 0) { + u32 tmp; + + this->field_0xf = 8; + tmp = sub_08049F84(this, 1); + if (tmp == 0xff) { + this->action = 7; + InitializeAnimation(this, 1); + return; + } + sub_08021D44(this, tmp); + } + ProcessMovement(this); + GetNextFrame(this); + } +} + +void sub_08021AD8(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 1) { + if (this->actionDelay) { + u32 tmp; + + this->actionDelay = 0; + tmp = sub_08049F84(this, 1); + if (tmp == 0xff) { + this->action = 2; + this->actionDelay = '\b'; + InitializeAnimation(this, 0); + return; + } + this->direction = (u8)tmp; + EnqueueSFX(0x7c); + } + sub_080AEFE0(this); + if (!sub_08003FC4(this, 0x1800)) + this->frameDuration = 1; + } + + if (this->frames.all & 0x80) { + this->action = 2; + this->actionDelay = 20; + ((u8*)&this->field_0x86)[0] = 60; + InitializeAnimation(this, 0); + } +} + +void sub_08021B64(Entity* this) { + if (gPlayerState.flags.all & 4) { + this->action = 3; + this->height.WORD = 0; + InitializeAnimation(this, 2); + } else { + int iVar4 = 1; + if (gPlayerState.field_0xa8 != 11 && gPlayerState.field_0xa8 != 20) { + if (sub_0807953C()) + iVar4 = this->entityType.form * 3 + 8; + + iVar4 = this->actionDelay - iVar4; + if (iVar4 < 0) + iVar4 = 0; + + this->actionDelay = (u8)iVar4; + } + + if (gPlayerState.flags.all & 0x110) + iVar4 = 0; + + if (iVar4 == 0) { + this->action = 6; + this->field_0x20 = 0x10000; + ((u8*)&this->field_0x86)[1] = 0; + if (gPlayerEntity.direction != 0xff) { + this->direction = 0x10 ^ gPlayerEntity.direction; + } else { + this->direction = (gPlayerEntity.animationState << 2) ^ 0x10; + } + InitializeAnimation(this, 5); + } else { + gPlayerState.field_0x1a[0] |= 0x80; + gPlayerState.field_0x80 -= 0x50; + gPlayerState.field_0xaa++; + CopyPositionAndSpriteOffset(&gPlayerEntity, this); + this->x.HALF.HI += gUnk_080CB5E4[(this->field_0xf++ & 0xe) >> 1]; + this->height.HALF.HI--; + GetNextFrame(this); + } + } +} + +void sub_08021C58(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 1) { + sub_080AEFE0(this); + if (sub_08003FC4(this, 0x1800) == 0) + this->frameDuration = 1; + } + + if (this->frames.all & 0x80) { + this->action = 2; + this->actionDelay = 60; + this->field_0xf = 1; + this->flags |= 0x80; + this->spritePriority.b0 = 4; + ((u8*)&this->field_0x86)[0] = 60; + InitializeAnimation(this, 0); + } +} + +void sub_08021CD0(Entity* this) { + if ((this->frames.all & 0x80) == 0) + GetNextFrame(this); + + if (sub_08049F84(this, 1) == 0xff) + return; + + this->action = 3; + InitializeAnimation(this, 2); +} + +u32 sub_08021D00(Entity* this) { + u32 ret; + + if (((u8*)&this->field_0x86)[0]) { + ((u8*)&this->field_0x86)[0]--; + ret = 0; + } else if (PlayerInRange(this, 1, 0x10) == 0) { + ret = 0; + } else { + this->action = 4; + this->actionDelay = 1; + this->field_0x20 = 0x18000; + InitializeAnimation(this, 4); + ret = 1; + } + + return ret; +} + +void sub_08021D44(Entity* this, u32 direction) { + direction = DirectionRoundUp(direction); + this->direction = direction; + if (DirectionIsHorizontal(direction)) { + this->nonPlanarMovement = 0x180; + } else { + this->nonPlanarMovement = 0xc0; + } +} + + +// clang-format off +void (*const gUnk_080CB590[])(Entity*) = { + sub_08021768, + sub_08021780, + sub_08001324, + sub_08021818, + sub_08001242, + sub_08021848, +}; + +void (*const gUnk_080CB5A8[])(Entity*) = { + Beetle_Initialize, + sub_080218B4, + sub_08021A10, + sub_08021A64, + sub_08021AD8, + sub_08021B64, + sub_08021C58, + sub_08021CD0, +}; + +void (*const gUnk_080CB5C8[])(Entity*) = { + sub_0802187C, + nullsub_130, + sub_08021888, +}; + +void (*const gUnk_080CB5D4[])(Entity*) = { + sub_080218CC, + sub_08021984, +}; + +const s8 gUnk_080CB5DC[] = { + -1, -2, 1, 2, -3, 3, -4, 4, +}; + +const s8 gUnk_080CB5E4[] = { + -1, -2, -1, 0, 1, 2, 1, 0, +}; +// clang-format on + diff --git a/src/enemy/bladeTrap.c b/src/enemy/bladeTrap.c index 7f77861c..b58ef0d6 100644 --- a/src/enemy/bladeTrap.c +++ b/src/enemy/bladeTrap.c @@ -3,7 +3,7 @@ #include "room.h" extern void sub_080A2CC0(); extern void sub_0806F69C(); -extern void sub_08004488(); +extern void EnqueueSFX(); extern Entity* GetCurrentRoomProperty(); void BladeTrap(Entity* ent) { @@ -27,7 +27,7 @@ void BladeTrap(Entity* ent) { *puVar3 = uVar1 - 1; if ((*puVar3) == 0) { if ((u16)(ent->direction & 0x80) == 0) { - sub_08004488(0x74); + EnqueueSFX(0x74); } sub_080A2CC0((EntityData*)ent, &ent->attachedEntity, puVar3); } diff --git a/src/enemy/bobomb.c b/src/enemy/bobomb.c new file mode 100644 index 00000000..bf4b4372 --- /dev/null +++ b/src/enemy/bobomb.c @@ -0,0 +1,331 @@ +#include "enemy.h" +#include "functions.h" + +extern void CreateDustSmall(Entity*); +extern void sub_08078930(Entity*); +extern void sub_08078954(Entity*); + +void sub_0802CB68(Entity*); +void sub_0802CBC4(Entity*); +void sub_0802CC18(Entity*); + +extern void (*const gUnk_080CD5D4[])(Entity*); +extern void (*const gUnk_080CD5EC[])(Entity*); +extern void (*const gUnk_080CD600[])(Entity*); +extern void (*const gUnk_080CD618[])(Entity*); + +void Bobomb(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CD5D4); +} + +void sub_0802C670(Entity* this) { + gUnk_080CD5EC[this->action](this); +} + +void sub_0802C688(Entity* this) { + if (this->bitfield & 0x80) { + switch (this->bitfield & 0x7f) { + case 0: + case 1: + if (this->field_0x82.HALF.LO) { + this->field_0x42 = 0; + gPlayerEntity.field_0x42 = 4; + } + return; + case 0xe: + case 0x14: + case 0x15: + case 0x16: + this->action = 3; + this->field_0x42 = 0; + sub_0802CBC4(this); + return; + } + this->field_0x82.HALF.LO++; + this->field_0x80.HALF.LO = 28; + switch (this->field_0x82.HALF.LO) { + case 1: + sub_0802CB68(this); + EnqueueSFX(0x14d); + break; + case 2: + this->action = 3; + this->damageType = 0x6e; + this->field_0xf = 1; + this->field_0x20 = 0x18000; + this->nonPlanarMovement = 0; + this->field_0x80.HALF.HI = 1; + InitializeAnimation(this, this->direction >> 4 | 6); + break; + } + } + sub_0804AA30(this, gUnk_080CD5D4); +} + +void sub_0802C7AC(Entity* this) { + if (this->previousActionFlag < 3 && !sub_0806F520(this)) { + this->previousActionFlag = 0; + this->field_0xf = 1; + this->height.HALF.HI = 0; + if (this->field_0x82.HALF.LO != 2) { + this->nonPlanarMovement = this->field_0x82.HALF.LO ? 0x200 : 0x80; + } + this->field_0x20 = 0x18000; + this->field_0x82.HALF.HI = 0; + this->field_0x80.HALF.HI = 0; + } else { + this->height.HALF.HI = -1; + gUnk_080CD600[this->previousActionFlag](this); + if (this->actionDelay != 0) { + GetNextFrame(this); + } + } +} + +void sub_0802C820(Entity* this) { + this->previousActionFlag = 1; + this->field_0x1d = 60; +} + +void sub_0802C82C(Entity* this) { + sub_0806F4E8(this); +} + +void sub_0802C834(Entity* this) { + sub_0806F3E4(this); +} + +void sub_0802C83C(Entity* this) { + if (this->field_0x82.HALF.LO) { + if (--this->actionDelay == 0) { + this->action = 3; + switch (gPlayerEntity.animationState & 6) { + case 2: + this->x.HALF.HI -= 6; + break; + case 6: + this->x.HALF.HI += 6; + break; + } + sub_0802CBC4(this); + } else { + sub_0802CC18(this); + this->flags &= ~0x80; + this->damageType = 0x6e; + } + } else { + this->field_0x82.HALF.LO = 2; + this->actionDelay = 120; + InitializeAnimation(this, (this->direction >> 4) | 6); + this->flags &= ~0x80; + this->damageType = 0x6e; + } +} + +void nullsub_149(Entity* this) { + /* ... */ +} + +void sub_0802C8B8(Entity* this) { + this->action = 3; + sub_0802CBC4(this); +} + +void sub_0802C8C4(Entity* this) { + sub_0804A7D4(this); + this->spriteSettings.b.draw = 0; +} + +void sub_0802C8D8(Entity* this) { + this->action = 1; + this->actionDelay = 0x3c; + this->field_0xf = 0; + this->direction = (Random() & 0x18) | 4; + this->field_0x16 = 0; + this->field_0x1c = 0x12; + this->field_0x82.HALF.LO = 0; + this->field_0x82.HALF.HI = 0; + this->field_0x80.HALF.LO = 0; + this->field_0x80.HALF.HI = 0; + InitializeAnimation(this, this->direction >> 4); +} + +void sub_0802C91C(Entity* this) { + GetNextFrame(this); + ProcessMovement(this); + if (this->field_0x82.HALF.LO) { + if (this->collisions) { + sub_0800417E(this, this->collisions); + InitializeAnimation(this, (this->direction >> 4) | 2); + } + if (--this->actionDelay == 0) { + sub_0802CBC4(this); + } else { + if ((this->actionDelay & 0xf) == 8) { + CreateDustSmall(this); + } + sub_0802CC18(this); + } + } else { + if (this->collisions) { + sub_0800417E(this, this->collisions); + InitializeAnimation(this, this->direction >> 4); + } + if (--this->actionDelay == 0) { + this->actionDelay = 60; + this->direction = (this->direction + 8) & 0x1c; + InitializeAnimation(this, this->direction >> 4); + } + } +} + +void sub_0802C9B8(Entity* this) { + gUnk_080CD618[this->previousActionFlag](this); +} + +void sub_0802C9D0(Entity* this) { + this->previousActionFlag = 1; + this->flags &= ~0x80; + this->spritePriority.b1 = 0; + this->field_0x82.HALF.HI = 1; + sub_0802CC18(this); + InitializeAnimation(this, (this->direction >> 4) | 6); + GetNextFrame(this); +} + +void sub_0802CA10(Entity* this) { + if (gPlayerState.heldObject != 5) { + if (--this->actionDelay == 0) { + sub_0802CBC4(this); + } else { + sub_0802CC18(this); + GetNextFrame(this); + } + } else { + this->field_0x82.HALF.HI = 2; + this->direction = (((gPlayerEntity.animationState) << 2) | 4) & 0x1c; + sub_0802CC18(this); + GetNextFrame(this); + } +} + +void sub_0802CA6C(Entity* this) { + if (--this->actionDelay == 0) { + sub_0802CBC4(this); + } else { + sub_0802CC18(this); + GetNextFrame(this); + } +} + +void sub_0802CA94(Entity* this) { + this->action = 3; + this->flags &= ~0x80; + this->field_0xf = 1; + this->spritePriority.b1 = 1; + this->field_0x20 = 0x18000; + this->nonPlanarMovement = 0; + this->field_0x82.HALF.HI = 0; + this->field_0x80.HALF.HI = 0; + this->direction = ((gPlayerEntity.animationState << 2) | 4) & 0x1c; + InitializeAnimation(this, (this->direction >> 4) | 6); +} + +void sub_0802CAF8(Entity* this) { + if (--this->actionDelay == 0) { + sub_0802CBC4(this); + } else { + if (this->field_0x80.HALF.HI && sub_080044EC(this, 0x2800) == 1) { + EnqueueSFX(0x104); + } + sub_0802CC18(this); + sub_08078930(this); + if (this->field_0xf && this->height.HALF.HI == 0) { + this->field_0xf = 0; + this->flags = this->flags | 0x80; + this->damageType = 0x6e; + } + GetNextFrame(this); + } +} + +void nullsub_150(Entity* this) { + /* ... */ +} + +void sub_0802CB68(Entity* this) { + this->action = 1; + this->previousActionFlag = 0; + this->direction = Random() & 0x18; + this->direction |= 4; + this->flags |= 0x80; + if (this->field_0x82.HALF.LO) { + this->actionDelay = 200; + this->nonPlanarMovement = 0x200; + InitializeAnimation(this, (this->direction >> 4) | 2); + } else { + this->actionDelay = 0x3c; + this->nonPlanarMovement = 0x80; + InitializeAnimation(this, this->direction >> 4); + } +} + +void sub_0802CBC4(Entity* this) { + Entity* ent; + + this->action = 4; + this->spriteSettings.b.draw = 0; + this->flags &= ~0x80; + this->currentHealth = 0; + if (this->field_0x82.HALF.HI) { + sub_08079184(); + } + sub_08078954(this); + + ent = CreateObjectWithParent(this, 0x20, 0, 0); + if (ent) { + ent->collisionLayer = this->collisionLayer; + } +} + +void sub_0802CC18(Entity* this) { + if (--this->field_0x80.HALF.LO == 0) { + this->field_0x80.HALF.LO = 28; + EnqueueSFX(0x14d); + } +} + +// clang-format off +void (*const gUnk_080CD5D4[])(Entity*) = { + sub_0802C670, + sub_0802C688, + sub_08001324, + sub_0802C8C4, + sub_08001242, + sub_0802C7AC, +}; + +void (*const gUnk_080CD5EC[])(Entity*) = { + sub_0802C8D8, + sub_0802C91C, + sub_0802C9B8, + sub_0802CAF8, + nullsub_150, +}; + +void (*const gUnk_080CD600[])(Entity*) = { + sub_0802C820, + sub_0802C82C, + sub_0802C834, + sub_0802C83C, + nullsub_149, + sub_0802C8B8, +}; + +void (*const gUnk_080CD618[])(Entity*) = { + sub_0802C9D0, + sub_0802CA10, + sub_0802CA6C, + sub_0802CA94, +}; +// clang-format on diff --git a/src/enemy/bombPeahat.c b/src/enemy/bombPeahat.c index 90ae7830..98f54841 100644 --- a/src/enemy/bombPeahat.c +++ b/src/enemy/bombPeahat.c @@ -3,24 +3,43 @@ #include "functions.h" #include "player.h" +extern void sub_08078954(Entity*); +extern u32 sub_0800442E(Entity*); +extern void sub_08078930(Entity*); extern s32 sub_080012DC(Entity*); extern u32 GetNextFunction(Entity*); -extern void sub_0802AD54(Entity*); -extern void sub_0802B048(Entity*); extern void sub_0806F4E8(Entity*); +extern Entity* sub_08049DF4(u32); +extern void sub_08079BD8(Entity*); +extern u32 GetTileTypeByEntity(Entity*); + +void sub_0802AD1C(Entity*, u32); +void sub_0802AD54(Entity*); +void sub_0802B048(Entity*); +void sub_0802ACDC(Entity*, u32); +void sub_0802ADDC(Entity*); +void sub_0802AC40(Entity*); +bool32 sub_0802B234(Entity*); +Entity* sub_0802B250(Entity*); +void sub_0802B264(Entity*); extern void (*const gUnk_080012C8[])(Entity*); + extern void (*const gUnk_080CD0F0[])(Entity*); +extern void (*const gUnk_080CD108[])(Entity*); extern void (*const gUnk_080CD120[])(Entity*); extern void (*const gUnk_080CD134[])(Entity*); -extern void (*const gUnk_080CD108[])(Entity*); extern void (*const gUnk_080CD140[])(Entity*); +extern void (*const gUnk_080CD158[])(Entity*); + +extern const BoundingBox gUnk_080CD16C; +extern const BoundingBox gUnk_080CD174; +extern const BoundingBox gUnk_080CD17C; void BombPeahat(Entity* this) { s32 iVar1; - u32 uVar2; - if (((this->entityType).form == 2) && (iVar1 = sub_080012DC(this), iVar1)) { + if ((this->entityType.form == 2) && (iVar1 = sub_080012DC(this), iVar1)) { gUnk_080012C8[iVar1](this); } else { gUnk_080CD0F0[GetNextFunction(this)](this); @@ -32,54 +51,618 @@ void sub_0802A84C(Entity* this) { default: gUnk_080CD108[this->action](this); sub_0802AD54(this); - return; + break; case 2: gUnk_080CD120[this->action](this); sub_0802B048(this); - return; + break; case 3: gUnk_080CD134[this->action](this); + break; } } -void sub_0802A8AC(Entity *this) { +void sub_0802A8AC(Entity* this) { this->field_0x80.HALF.HI = 0; if (this->entityType.form < 2) { InitializeAnimation(this, 0); } } -void sub_0802A8C8(Entity* this) -{ - gUnk_080CD140[this->previousActionFlag](this); +void sub_0802A8C8(Entity* this) { + gUnk_080CD140[this->previousActionFlag](this); } -void sub_0802A8E0(Entity *this) -{ - this->previousActionFlag = 1; - this->field_0x1d = 0x3c; +void sub_0802A8E0(Entity* this) { + this->previousActionFlag = 1; + this->field_0x1d = 60; } -void sub_0802A8EC(Entity *this) -{ +void sub_0802A8EC(Entity* this) { sub_0806F4E8(this); } -void sub_0802A8F4(Entity *this) -{ +void sub_0802A8F4(Entity* this) { sub_0806F3E4(this); } -void sub_0802A8FC(Entity *this) -{ - if ((gPlayerState.field_0x1c & 0xf) == 0) { - this->currentHealth = gPlayerState.field_0x1c & 0xf; - } +void sub_0802A8FC(Entity* this) { + if ((gPlayerState.field_0x1c & 0xf) == 0) { + this->currentHealth = gPlayerState.field_0x1c & 0xf; + } +} + +void nullsub_143(Entity* this) { + /* ... */ +} + +void sub_0802A91C(Entity* this) { + this->currentHealth = 0; +} + +void sub_0802A924(Entity* this) { + this->action = 1; + this->previousActionFlag = 0; + this->actionDelay = 0; + this->field_0xf = 0; + this->boundingBox = (BoundingBox*)&gUnk_080CD16C; + this->height.HALF.HI = -0x30; + this->field_0x80.HALF.LO = Random() & 1; + this->field_0x82.HWORD = 0; + this->field_0x7a.HALF.HI = 0; + this->field_0x80.HALF.HI = 0; + this->field_0x7a.HALF.LO = 0; + this->field_0x78.HALF.LO = 0; + this->field_0x78.HALF.HI = 0; + this->collisionLayer = 3; + this->spriteOrientation.flipY = 1; + this->spriteRendering.b3 = 1; + this->spritePriority.b0 = 1; + InitializeAnimation(this, this->entityType.form + 1); +} + +void sub_0802A9A8(Entity* this) { + if (this->field_0xf) { + this->field_0xf--; + } else { + if (this->actionDelay) { + if (--this->actionDelay == 0) { + this->action = 2; + this->previousActionFlag = 0; + this->actionDelay = 0x40; + sub_0802ACDC(this, 8); + } + } else { + if (gRoomControls.unk2 != 0) { + return; + } + this->spriteSettings.b.draw = 1; + this->field_0x82.HWORD = 1; + if (this->field_0x80.HALF.LO) { + this->x.HALF.HI = gRoomControls.roomScrollX - 0x10; + this->direction = 8; + } else { + this->x.HALF.HI = gRoomControls.roomScrollX + 0x100; + this->direction = 0x18; + } + this->y.HALF.HI = gRoomControls.roomScrollY + 0x40; + this->actionDelay = 0x80; + sub_0802ADDC(this); + } + sub_0802AC40(this); + } +} + +void sub_0802AA40(Entity* this) { + sub_0802AC40(this); + if (--this->field_0xf == 0) { + sub_0802ACDC(this, 8); + this->field_0x7a.HALF.HI++; + } + if (this->actionDelay) { + this->actionDelay--; + } else { + Entity* ent = this->attachedEntity; + if (ent) { + if (ent->next == NULL) { + this->attachedEntity = NULL; + } else { + u32 direction = DirectionRound(this->field_0x80.HALF.LO * 0x10 + 0x18); + + if (0x20 < this->field_0x7a.HALF.HI) { + this->direction = direction; + } + if (this->direction == direction) { + this->action = 3; + this->nonPlanarMovement = 0x180; + this->field_0x7a.HALF.HI = 0; + ent->field_0x80.HALF.LO = 1; + ent->actionDelay = 0x96; + } + } + } + } +} + +void sub_0802AAC0(Entity* this) { + sub_0802AC40(this); + if (--this->field_0xf == 0) { + sub_0802AD1C(this, 4); + } + + if (this->field_0x80.HALF.HI) { + Entity* ent = this->attachedEntity; + if (ent == NULL) { + this->field_0x80.HALF.HI = 0; + } else if (ent->next == NULL) { + this->field_0x80.HALF.HI = 0; + this->attachedEntity = NULL; + } else if (ent->actionDelay == 0 && ent->field_0xf < 0x51) { + this->field_0x80.HALF.HI = 0; + } + } else { + this->action = 4; + this->actionDelay = 0xc0; + this->field_0xf = 4; + this->field_0x80.HALF.LO ^= 1; + this->field_0x78.HALF.LO = 0; + this->field_0x78.HALF.HI = 4; + this->direction = 0xff; + InitializeAnimation(this, 0); + } +} + +void sub_0802AB40(Entity* this) { + sub_0802AC40(this); + switch (this->field_0x78.HALF.LO) { + case 0: + if (this->height.HALF.HI) { + if (--this->field_0x78.HALF.HI == 0) { + this->field_0x78.HALF.HI = 4; + this->height.HALF.HI++; + } + } else { + this->field_0x78.HALF.LO = 1; + this->field_0x78.HALF.HI = 0x30; + this->direction = sub_08049F84(this, 0); + } + break; + case 1: + if (--this->field_0x78.HALF.HI == 0) { + this->field_0x78.HALF.LO = 2; + this->field_0x78.HALF.HI = 4; + } else if ((this->field_0x78.HALF.HI & 7) == 0) { + this->direction = sub_08049F84(this, 0); + } + break; + case 2: + if (-0x30 < this->height.HALF.HI) { + if (--this->field_0x78.HALF.HI == 0) { + this->field_0x78.HALF.HI = 4; + this->height.HALF.HI--; + sub_0802ACDC(this, 4); + } + } else { + this->action = 5; + this->nonPlanarMovement = 0; + InitializeAnimation(this, this->entityType.form + 1); + } + break; + } +} + +void sub_0802AC08(Entity* this) { + if (this->frames.all & 0x80) { + this->action = 2; + this->previousActionFlag = 0; + this->actionDelay = 0x40; + this->nonPlanarMovement = 0xc0; + sub_0802ACDC(this, 8); + sub_0802ADDC(this); + } + GetNextFrame(this); +} + +void sub_0802AC40(Entity* this) { + GetNextFrame(this); + sub_0806F69C(this); + if (this->field_0x7a.HALF.LO) { + if (sub_0802B234(this) == 0) { + this->field_0x7a.HALF.LO = 0; + this->spritePriority.b1 = 0; + } else { + if (this->height.HALF.HI == 0) { + if (this->spritePriority.b1 != 1) { + this->spritePriority.b1 = 1; + } + } else { + if (this->spritePriority.b1 != 3) { + this->spritePriority.b1 = 3; + } + } + } + } else { + if (sub_0802B234(this)) { + this->field_0x7a.HALF.LO = 1; + if (this->height.HALF.HI == 0) { + this->spritePriority.b1 = 1; + } else { + this->spritePriority.b1 = 3; + } + } + } +} + +void sub_0802ACDC(Entity* this, u32 param_2) { + u32 x; + if (this->field_0x80.HALF.LO) { + x = sub_080045B4(this, gRoomControls.roomScrollX + 0x20, gRoomControls.roomScrollY + 0x60); + } else { + x = sub_080045B4(this, gRoomControls.roomScrollX + 0xd0, gRoomControls.roomScrollY + 0x60); + } + sub_08004596(this, x); + this->field_0xf = param_2; +} + +void sub_0802AD1C(Entity* this, u32 param_2) { + Entity* ent = sub_08049DF4(1); + if (ent) { + u32 y = ent->y.HALF.HI - 0x18; + u32 x = ent->x.HALF.HI; + sub_08004596(this, sub_080045B4(this, x, y)); + this->field_0xf = param_2; + } else { + sub_0802ACDC(this, param_2); + } +} + +void sub_0802AD54(Entity* this) { + if (this->field_0x82.HWORD != 0) { + if (gRoomControls.unk2 != 0) { + this->spriteSettings.b.draw = 0; + DeleteEntity(this); + return; + } + if (gRoomControls.roomOriginY > this->y.HALF.HI || + (gRoomControls.roomOriginY + gRoomControls.height + 0x20) < this->y.HALF.HI) { + this->spriteSettings.b.draw = 0; + } else { + this->spriteSettings.b.draw = 1; + } + } + if (this->field_0x80.HALF.HI) { + if (this->attachedEntity == NULL || this->attachedEntity->next == NULL) { + this->action = 4; + this->actionDelay = 0xc0; + this->field_0xf = 4; + this->field_0x80.HALF.LO ^= 1; + } + } +} + +void sub_0802ADDC(Entity* this) { + Entity* ent = CreateEnemy(0x1b, this->entityType.form + 2); + if (ent != NULL) { + ent->entityType.parameter = !!sub_0802B234(this); + ent->parent = this; + this->attachedEntity = ent; + CopyPosition(this, ent); + this->field_0x80.HALF.HI = 1; + if (this->entityType.form == 0) { + this->field_0x7a.HALF.LO++; + } + } +} + +void sub_0802AE24(Entity* this) { + this->action = 1; + this->actionDelay = 0xf0; + this->field_0x20 = 0x8000; + this->boundingBox = (BoundingBox*)&gUnk_080CD174; + this->field_0x3c = 3; + this->field_0x16 = 0; + this->field_0x1c = 2; + this->field_0x80.HALF.HI = 0; + this->field_0x7a.HALF.HI = 1; + InitializeAnimation(this, 3); +} + +void sub_0802AE68(Entity* this) { + Entity* ent = sub_0802B250(this); + if (ent == 0) { + this->action = 3; + this->field_0x80.HALF.LO = 1; + sub_0802B264(this); + } else { + if (ent->field_0x80.HALF.HI) { + CopyPosition(ent, this); + this->spriteSettings.b.draw = 0; + } else { + this->action = 3; + this->field_0x80.HALF.LO = 1; + sub_0802B264(this); + } + } +} + +void sub_0802AEBC(Entity* this) { + gUnk_080CD158[this->previousActionFlag](this); +} + +void sub_0802AED4(Entity* this) { + GetNextFrame(this); + if (this->field_0x80.HALF.HI < 2) { + if (sub_080044EC(this, 0x2800) == 1) { + this->field_0x80.HALF.HI++; + } + } else { + if (!sub_0800442E(this)) { + sub_08078930(this); + } + } + if (this->entityType.parameter != 0 && this->field_0x80.HALF.HI) { + this->actionDelay = 0; + this->field_0xf = 1; + } +} + +void sub_0802AF28(Entity* this) { + this->previousActionFlag = 1; + sub_08079BD8(this); + this->spritePriority.b1 = 2; + GetNextFrame(this); +} + +void sub_0802AF50(Entity* this) { + GetNextFrame(this); +} + +void sub_0802AF58(Entity* this) { + GetNextFrame(this); + this->spritePriority.b1 = 3; +} + +void sub_0802AF74(Entity* this) { + this->action = 3; + this->previousActionFlag = 0; + if (this->actionDelay > 60) { + this->actionDelay = 60; + } + GetNextFrame(this); +} + +void sub_0802AF94(Entity* this) { + DeleteEntity(this); +} + +void sub_0802AF9C(Entity* this) { + GetNextFrame(this); + if (--this->actionDelay == 0) { + if (this->parent->field_0x7a.HALF.LO) { + this->parent->field_0x7a.HALF.LO--; + } + DeleteEntity(this); + } +} + +#if NON_MATCHING +void sub_0802AFC8(Entity* this) { + u32 flag = 8; + if (this->field_0xf < 0x29) { + u32 tmp; + + flag = 4; + if (this->field_0x82.HWORD & 0x8000) { + this->field_0x82.HWORD -= 0x10; + } else { + this->field_0x82.HWORD += 0x10; + } + if (0x7f < (this->field_0x82.HWORD & 0xf0) - 1) { + this->field_0x82.HWORD ^= 0x8000; + } + + tmp = 0x130 - (this->field_0x82.HWORD & 0xf0); + sub_0805EC9C(this, tmp, tmp, 0); + } + + if (this->field_0xf & flag) { + this->palette.b.b0 = 0; + } else { + this->palette.b.b0 = this->palette.b.b4; + } +} +#else +NAKED +void sub_0802AFC8(Entity* this) { + asm(".include \"asm/non_matching/bombPeahat/sub_0802AFC8.inc\""); +} +#endif + +void sub_0802B048(Entity* this) { + Entity* ent; + u32 action; + + if (this->field_0x7a.HALF.HI) { + if (gRoomControls.roomOriginY > this->y.HALF.HI || + (gRoomControls.roomOriginY + gRoomControls.height + 0x20) < this->y.HALF.HI) { + this->flags &= ~0x80; + } else { + this->flags |= 0x80; + } + } + + ent = this->parent; + if (ent && this->action == 1) { + this->spriteRendering.b3 = ent->spriteRendering.b3; + this->spritePriority.b0 = ent->spritePriority.b0; + this->spriteOrientation.flipY = ent->spriteOrientation.flipY; + } + + action = this->action; + if (action != 4 && this->field_0x80.HALF.LO) { + if (this->actionDelay) { + if (--this->actionDelay == 0) { + this->field_0xf = 0x50; + this->field_0x82.HWORD = 0; + this->spriteRendering.b0 = 3; + sub_0805EC9C(this, 0x100, 0x100, 0); + } + } else { + if (this->field_0xf) { + if (--this->field_0xf == 0) { + if (action == 2 && this->previousActionFlag == 1) { + gPlayerState.heldObject = 0; + } + sub_0805EC60(this); + this->action = 4; + this->boundingBox = (BoundingBox*)&gUnk_080CD17C; + this->actionDelay = 0xf; + this->spriteSettings.b.draw = 0; + this->flags |= 0x80; + this->field_0x7a.HALF.HI = 0; + sub_08078954(this); + if (this->parent->next) { + this->parent->field_0x80.HALF.HI = 0; + } + ent = CreateObjectWithParent(this, 0x20, 0, 0); + if (ent != NULL) { + this->collisionLayer = 1; + } else { + DeleteEntity(this); + } + } else { + sub_0802AFC8(this); + } + } + } + } +} + +void sub_0802B1A0(Entity* this) { + this->action = 1; + this->actionDelay = 0; + this->field_0xf = 0x4f; + this->field_0x80.HALF.HI = 1; + InitializeAnimation(this, 0); } -void nullsub_143(Entity* this){} +void sub_0802B1BC(Entity* this) { + Entity* ent; + + if (this->actionDelay) { + this->actionDelay--; + } -void sub_0802A91C(Entity *this) -{ - this->currentHealth = 0; + ent = sub_0802B250(this); + if (ent == 0) { + this->action = 2; + sub_0802B264(this); + } else { + if (ent->field_0x80.HALF.HI) { + CopyPosition(ent, this); + } else { + this->action = 2; + sub_0802B264(this); + } + } +} + +void sub_0802B204(Entity* this) { + if (sub_080044EC(this, 0x2800) == 1) { + Entity* ent = CreateEnemy(0x22, 1); + if (ent) { + CopyPosition(this, ent); + ent->parent = this->parent; + } + DeleteThisEntity(); + } +} + +bool32 sub_0802B234(Entity* this) { + bool32 ret = FALSE; + if (GetTileTypeByEntity(this) - 0x1c4 > 1) + ret = TRUE; + return ret; } + +Entity* sub_0802B250(Entity* this) { + Entity* parent = this->parent; + if (parent && parent->next == NULL) { + parent = NULL; + } + return parent; +} + +void sub_0802B264(Entity* this) { + this->spriteSettings.b.draw = 1; + if (sub_0802B234(this)) { + this->spritePriority.b1 = 3; + } else { + + this->spritePriority.b1 = 0; + } + GetNextFrame(this); +} + +// clang-format off +void (*const gUnk_080CD0F0[])(Entity*) = { + sub_0802A84C, + sub_0802A8AC, + sub_08001324, + sub_0804A7D4, + sub_08001242, + sub_0802A8C8, +}; + +void (*const gUnk_080CD108[])(Entity*) = { + sub_0802A924, + sub_0802A9A8, + sub_0802AA40, + sub_0802AAC0, + sub_0802AB40, + sub_0802AC08, +}; + +void (*const gUnk_080CD120[])(Entity*) = { + sub_0802AE24, + sub_0802AE68, + sub_0802AEBC, + sub_0802AED4, + sub_0802AF9C, +}; + +void (*const gUnk_080CD134[])(Entity*) = { + sub_0802B1A0, + sub_0802B1BC, + sub_0802B204, +}; + +void (*const gUnk_080CD140[])(Entity*) = { + sub_0802A8E0, + sub_0802A8EC, + sub_0802A8F4, + sub_0802A8FC, + nullsub_143, + sub_0802A91C, +}; + +void (*const gUnk_080CD158[])(Entity*) = { + sub_0802AF28, + sub_0802AF50, + sub_0802AF58, + sub_0802AF74, + sub_0802AF94, +}; + +const BoundingBox gUnk_080CD16C = { + 0x00, 0xFB, 0x05, 0x03, 0x03, 0x05, 0x06, 0x06, +}; + +const BoundingBox gUnk_080CD174 = { + 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x04, 0x04, +}; + +const BoundingBox gUnk_080CD17C = { + 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x16, 0x16, +}; +// clang-format on
\ No newline at end of file diff --git a/src/enemy/businessScrub.c b/src/enemy/businessScrub.c new file mode 100644 index 00000000..924ace96 --- /dev/null +++ b/src/enemy/businessScrub.c @@ -0,0 +1,608 @@ +#include "enemy.h" +#include "entity.h" +#include "flags.h" +#include "functions.h" +#include "textbox.h" + +extern void sub_0801D040(Entity*, u32); +extern Entity* sub_08049DF4(u32); +extern bool32 sub_08056338(void); +extern void UnloadOBJPalette(Entity*); + +bool32 sub_0802915C(Entity*); +bool32 sub_080291DC(Entity*); +void sub_0802922C(Entity*); +void sub_08028E9C(Entity*); +u32 sub_080001DA(u32, u32); +void sub_08028FFC(Entity*); +void sub_0802925C(Entity*); +void sub_080290E0(Entity*, u32); +bool32 sub_08028F98(Entity*, u32); +void sub_08029078(Entity*); +bool32 sub_08028FDC(Entity*); +void sub_080290FC(Entity*); +void sub_08028EDC(Entity*); + +extern const struct SalesOffering gUnk_080CC954[]; +extern const u8 gUnk_080CC9C0[]; +extern void (*const gUnk_080CC9C8[])(Entity*); +extern void (*const gUnk_080CC9E0[])(Entity*); +extern const u8 gUnk_080CCA04[]; + +struct SalesOffering { + u8 field_0x0; + u8 field_0x1; + u16 price; + u16 field_0x4; + u16 field_0x6; + u8 field_0x8; + u8 field_0x9; + u16 field_0xa; +}; + +void BusinessScrub(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CC9C8); +} + +void sub_0802891C(Entity* this) { + gUnk_080CC9E0[this->action](this); +} + +void sub_08028934(Entity* this) { + Entity* pEVar1; + + if (this->damageType == 1 && (this->bitfield & 0x7f) == 0x42) { + this->action = 3; + this->previousActionFlag = 0; + this->actionDelay = 0x28; + this->flags &= ~0x80; + sub_080290E0(this, 4); + pEVar1 = CreateFx(this, 3, 0); + if (pEVar1 != NULL) { + pEVar1->height.HALF.HI -= 8; + } + EnqueueSFX(0x1bb); + } +} + +void nullsub_140(Entity* this) { + /* ... */ +} + +void sub_08028994(Entity* this) { + this->field_0xf = 0; + this->field_0x78.HWORD = this->x.HALF.HI; + this->field_0x7a.HWORD = this->y.HALF.HI; + this->animationState = 0; + this->direction = 0x10; + sub_08028E9C(this); + if ((*(u8*)this->field_0x7c.WORD & 1) || CheckFlags(this->field_0x86.HWORD)) { + this->action = 4; + this->actionDelay = 0x78; + this->spritePriority.b1 = 1; + sub_0802925C(this); + sub_080290E0(this, 0); + } else { + this->actionDelay = 0; + this->field_0x76.HWORD = COORD_TO_TILE(this); + this->field_0x74.HWORD = sub_080001DA(this->field_0x76.HWORD, this->collisionLayer); + this->field_0x40 = 0x41; + sub_08028FFC(this); + } +} + +void sub_08028A48(Entity* this) { + if (this->actionDelay) { + this->actionDelay--; + } else if (sub_08028F98(this, 0)) { + sub_08029078(this); + this->previousActionFlag = 0; + this->field_0xf = 1; + } +} + +void sub_08028A74(Entity* this) { + u32 unk; + + GetNextFrame(this); + switch (this->previousActionFlag) { + case 0: + unk = 1; + if (this->frames.all & 0x80) { + this->previousActionFlag = 1; + this->actionDelay = 0x3c; + this->field_0xf = 0x10; + sub_08028FDC(this); + sub_080290E0(this, 1); + } + break; + case 1: + unk = 1; + if (--this->actionDelay == 0) { + this->previousActionFlag = 2; + this->actionDelay = 0x20; + this->field_0xf = 0; + sub_08028FDC(this); + sub_080290E0(this, 2); + } else if (--this->field_0xf == 0) { + if (sub_08028FDC(this)) { + sub_080290E0(this, 1); + } + this->field_0xf = 0x10; + } + break; + case 2: + unk = 1; + sub_080290FC(this); + if (this->frames.all & 1) { + Entity* ent = sub_0804A98C(this, 4, 0); + if (ent != NULL) { + ent->parent = this; + ent->direction = this->direction; + this->frames.all &= ~1; + this->previousActionFlag = 3; + } + } + break; + case 3: + unk = 2; + if (this->frames.all & 0x80) { + this->previousActionFlag = 4; + this->actionDelay = 0x50; + sub_080290E0(this, 1); + } + break; + case 4: + unk = 2; + if (--this->actionDelay == 0) { + if (sub_08028F98(this, 0)) { + this->previousActionFlag = 1; + this->actionDelay = 0x3c; + this->field_0xf = 0x10; + sub_08028FDC(this); + } else { + sub_08028FFC(this); + this->previousActionFlag = 0; + this->actionDelay = 0x50; + this->field_0xf = 0; + } + return; + } + break; + } + + if (!sub_08028F98(this, unk)) { + sub_08028FFC(this); + this->previousActionFlag = 0; + this->actionDelay = 0x50; + this->field_0xf = 0; + } +} + +void sub_08028BC4(Entity* this) { + Entity* iVar1; + + switch (this->previousActionFlag) { + case 0: + if (this->actionDelay == 0) { + if (this->frames.all & 0x80) { + this->previousActionFlag = 1; + sub_08028FDC(this); + sub_080290E0(this, 5); + this->spritePriority.b1 = 1; + } + } else { + this->actionDelay--; + } + break; + case 1: + if (this->frames.all & 0x80) { + this->action = 4; + this->previousActionFlag = 0; + this->actionDelay = 0x1e; + this->field_0xf = 5; + sub_080290E0(this, 0); + iVar1 = sub_0804A9FC(this, 0x1c); + if (iVar1 != NULL) { + iVar1->spritePriority.b0 = 3; + iVar1->height.HALF.HI -= 12; + sub_0805E3A0(iVar1, 2); + } + SetFlag(this->field_0x86.HWORD); + sub_0802925C(this); + } + break; + } + + GetNextFrame(this); + sub_0800445C(this); +} + +extern void sub_0804AA1C(Entity*); +void sub_08028F0C(Entity*); + +void sub_08028C84(Entity* this) { + if (--this->actionDelay == 0) { + this->actionDelay = 0x30; + if (this->field_0xf) { + if (--this->field_0xf == 0) { + sub_0804AA1C(this); + } + } else if (sub_08028FDC(this) || this->field_0x80.HALF.LO) { + this->field_0x80.HALF.LO = 0; + sub_080290E0(this, 0); + } + } + GetNextFrame(this); + sub_0800445C(this); + sub_08028F0C(this); +} + +void sub_08028CE8(Entity* this) { + struct SalesOffering* offer = (struct SalesOffering*)this->field_0x7c.WORD; + u32 subtype; + + if ((gTextBox.doTextBox & 0x7f) == 0 && sub_0802915C(this) && !sub_08056338()) { + if (offer->price <= gUnk_02002A40.stats.rupees) { + if (sub_080291DC(this)) { + /* Bag full. */ + TextboxNoOverlapFollow(0x2904); + sub_08078A90(0); + } else { + ModRupees(-offer->price); + switch (offer->field_0x0 >> 2) { + case 0: + subtype = offer->field_0x9; + if (subtype == 0xff) { + subtype = gUnk_080CC9C0[Random() & 7]; + } + + CreateItemEntity(offer->field_0x8, subtype, 0); + + this->action = 6; + this->actionDelay = 4; + this->field_0x80.HALF.HI = 0; + sub_080290E0(this, 3); + SetLocalFlag(0x87); + return; + case 1: + CreateItemEntity(offer->field_0x8, offer->field_0x9, 0); + this->actionDelay = 4; + sub_0802922C(this); + return; + case 2: + CreateItemEntity(offer->field_0x8, offer->field_0x9, 0); + this->actionDelay = 8; + sub_0802922C(this); + return; + } + } + } else { + /* Not enough money. */ + TextboxNoOverlapFollow(0x2903); + sub_08078A90(0); + } + } + + sub_0800445C(this); + this->action = 4; + this->actionDelay = 0x30; + sub_080290E0(this, 0); +} + +void sub_08028DE8(Entity* this) { + if (gPlayerEntity.action == 8) { + if (this->field_0x80.HALF.HI == 0) { + sub_08078A90(1); + this->field_0x80.HALF.HI = 1; + } + } else { + TextboxNoOverlapFollow(0x2902); + this->action = 4; + this->field_0x80.HALF.HI = 0; + this->actionDelay = 1; + sub_08028EDC(this); + sub_08078A90(0); + sub_0800445C(this); + GetNextFrame(this); + } +} + +void sub_08028E40(Entity* this) { + if ((gTextBox.doTextBox & 0x7f) == 0) { + struct SalesOffering* offer = (struct SalesOffering*)this->field_0x7c.WORD; + + this->action = 4; + this->previousActionFlag = gTextBox.doTextBox & 0x7f; + this->actionDelay = 1; + if (CheckLocalFlag(offer->field_0xa) == 0) { + SetLocalFlag(offer->field_0xa); + } + sub_08078A90(0); + } + sub_0800445C(this); + GetNextFrame(this); +} + +void sub_08028E84(Entity* this) { + if (UpdateFuseInteraction()) { + this->action = 4; + this->actionDelay = 1; + } +} + +bool32 sub_08029198(const struct SalesOffering*); + +void sub_08028E9C(Entity* this) { + const struct SalesOffering* offer = &gUnk_080CC954[this->entityType.form]; + if (sub_08029198(offer) && (offer->field_0x0 & 2)) { + offer = &gUnk_080CC954[offer->field_0xa]; + } + this->field_0x7c.WORD = (u32)offer; + this->field_0x80.HALF.LO = 0; +} + +void sub_08028EDC(Entity* this) { + const struct SalesOffering* offer = (const struct SalesOffering*)this->field_0x7c.WORD; + if (sub_08029198(offer) && (offer->field_0x0 & 2)) { + offer = &gUnk_080CC954[offer->field_0xa]; + this->field_0x7c.WORD = (u32)offer; + } +} + +void sub_08028F0C(Entity* this) { + if (this->interactType == 2) { + this->action = 8; + this->interactType = 0; + sub_0806F118(this); + } else if (this->interactType != 0) { + u16 dialog; + const struct SalesOffering* offer = (const struct SalesOffering*)this->field_0x7c.WORD; + + this->interactType = 0; + sub_0804AA1C(this); + this->direction = (GetAnimationState(this) << 3); + sub_080290E0(this, 3); + this->field_0x80.HALF.LO = 1; + this->actionDelay = 0x20; + this->field_0xf = 0; + if (sub_08029198(offer)) { + dialog = offer->field_0x6; + } else { + if ((offer->field_0x0 & 0xfc) != 0xc) { + this->action = 5; + } else { + this->action = 7; + } + dialog = offer->field_0x4; + sub_08078A90(1); + } + TextboxNoOverlapFollow(dialog); + gTextBox.field_0x10 = offer->price; + } +} + +bool32 sub_08028F98(Entity* this, u32 param_2) { + Entity* ent = sub_08049DF4(1); + if (ent == NULL || sub_080041A0(this, ent, 0x28, 0x28)) { + return FALSE; + } + + if (param_2 != 2) { + u32 distance = param_2 ? 0x58 : 0x50; + + if (!sub_080041A0(this, ent, distance, distance)) { + return FALSE; + } + } + + return TRUE; +} + +bool32 sub_08028FDC(Entity* this) { + u32 direction = DirectionRoundUp(sub_08049F84(this, 1)); + if (direction == this->direction) { + return FALSE; + } else { + this->direction = direction; + return TRUE; + } +} + +void sub_08028FFC(Entity* this) { + this->action = 1; + this->flags &= ~0x80; + this->spritePriority.b1 = 0; + sub_080AE068(this); + UnloadOBJPalette(this); + this->spriteVramOffset = 0xe8; + this->palette.b.b0 = 2; + this->palette.b.b4 = 2; + this->spriteIndex = 0xa7; + this->x.HALF.HI = this->field_0x78.HWORD; + this->y.HALF.HI = this->field_0x7a.HWORD; + InitializeAnimation(this, 0); + SetTile(0x4022, this->field_0x76.HWORD, this->collisionLayer); +} + +void sub_08029078(Entity* this) { + this->action = 2; + this->flags = this->flags | 0x80; + this->spritePriority.b1 = 1; + if (LoadFixedGFX(this, 0x72) == 0) { + DeleteEntity(this); + } else { + sub_0801D040(this, 0x6e); + this->spriteIndex = 0xd0; + sub_08028FDC(this); + sub_080290E0(this, 1); + SetTile(this->field_0x74.HWORD, this->field_0x76.HWORD, this->collisionLayer); + } +} + +void sub_080290E0(Entity* this, u32 param_2) { + InitializeAnimation(this, this->direction >> 3 | gUnk_080CCA04[param_2]); +} + +void sub_080290FC(Entity* this) { + if (this->actionDelay != 0) { + if (--this->actionDelay < 0x10 && (this->actionDelay & 1) == 0) { + s32 sVar3 = (this->direction & 0x10) ? -1 : 1; + if ((this->direction & 8)) { + this->x.HALF.HI += (this->actionDelay & 8) ? -sVar3 : sVar3; + } else { + this->y.HALF.HI += (this->actionDelay & 8) ? sVar3 : -sVar3; + } + } + } +} + +bool32 sub_0802915C(Entity* this) { + const struct SalesOffering* offer = (const struct SalesOffering*)this->field_0x7c.WORD; + + switch (offer->field_0x8) { + case 0x44: + if (GetInventoryValue(0x44) == 0) + return TRUE; + break; + case 0x1c: + if (CheckGlobalFlag(0x5a) == 0) + return TRUE; + break; + case 0x5c: + case 0x6c: + case 0x6f: + return TRUE; + } + return FALSE; +} + +bool32 sub_08029198(const struct SalesOffering* offer) { + u32 tmp; + + if ((offer->field_0x0 & 0xfc) != 0xc) { + switch (offer->field_0x8) { + case 0x1c: + tmp = CheckGlobalFlag(0x5a); + break; + case 0x9: + case 0x44: + tmp = GetInventoryValue(offer->field_0x8); + break; + default: + return 0; + } + } else { + tmp = CheckLocalFlag(offer->field_0xa); + } + + if (tmp == 0) { + return FALSE; + } + + return TRUE; +} + +bool32 sub_080291DC(Entity* this) { + const struct SalesOffering* offer = (const struct SalesOffering*)this->field_0x7c.WORD; + + switch (offer->field_0x8) { + case 0x6c: + if (gBombBagSizes[gUnk_02002A40.stats.bombBagType] <= gUnk_02002A40.stats.bombCount) + return TRUE; + break; + case 0x6f: + if (gQuiverSizes[gUnk_02002A40.stats.quiverType] <= gUnk_02002A40.stats.arrowCount) + return TRUE; + break; + } + + return FALSE; +} + +#if NON_MATCHING +void sub_0802922C(Entity* this) { + const struct SalesOffering* offer = (const struct SalesOffering*)this->field_0x7c.WORD; + + this->action = 6; + this->field_0x80.HALF.HI = 0; + + switch (offer->field_0x8) { + case 0x1c: + SetGlobalFlag(0x5a); + break; + } + + sub_080290E0(this, 3); +} +#else +NAKED +void sub_0802922C(Entity* this) { + asm(".include \"asm/non_matching/businessScrub/sub_0802925C.inc\""); +} +#endif + +void sub_0802925C(Entity* this) { + sub_08078784(this, sub_0801E99C(this)); +} + +void sub_08029270(Entity* this) { + if (this->action == 0) { + this->action++; + this->spriteSettings.b.draw = 1; + InitializeAnimation(this, 0xe); + } else { + GetNextFrame(this); + } +} + +// clang-format off +const struct SalesOffering gUnk_080CC954[] = { + {0x06, 0x00, 0xffff, 0x290f, 0x2902, 0x09, 0xff, 0x0001}, + {0x04, 0x00, 0x001e, 0x290e, 0x2902, 0x6f, 0xff, 0xffff}, + {0x04, 0x00, 0x001e, 0x290b, 0x2902, 0x6c, 0xff, 0xffff}, + {0x08, 0x00, 0x0028, 0x290c, 0x2911, 0x44, 0xff, 0xffff}, + {0x00, 0x00, 0x0064, 0x290d, 0x2902, 0x5c, 0xff, 0xffff}, + {0x04, 0x00, 0x0014, 0x2910, 0x2911, 0x1c, 0xff, 0xffff}, + {0x0c, 0x00, 0xffff, 0x2912, 0x2913, 0xff, 0xff, 0x0046}, + {0x04, 0x00, 0x0064, 0x2913, 0x2902, 0x5c, 0x75, 0xffff}, + {0x00, 0x00, 0x00C8, 0x290d, 0x2902, 0x5c, 0xff, 0xffff}, +}; + +const u8 gUnk_080CC9C0[] = { + 0x6e, + 0x6f, + 0x70, + 0x71, + 0x72, + 0x73, + 0x74, + 0x75, + +}; + +void (*const gUnk_080CC9C8[])(Entity*) = { + sub_0802891C, + sub_08028934, + sub_08001324, + sub_0804A7D4, + sub_08001242, + nullsub_140, +}; + +void (*const gUnk_080CC9E0[])(Entity*) = { + sub_08028994, + sub_08028A48, + sub_08028A74, + sub_08028BC4, + sub_08028C84, + sub_08028CE8, + sub_08028DE8, + sub_08028E40, + sub_08028E84, +}; + +const u8 gUnk_080CCA04[] = { + 0, 4, 8, 12, 16, 20, +}; +// clang-format on diff --git a/src/enemy/chaser.c b/src/enemy/chaser.c new file mode 100644 index 00000000..a5f1f522 --- /dev/null +++ b/src/enemy/chaser.c @@ -0,0 +1,91 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern s32 sub_080012DC(Entity*); +extern u32 sub_0804A024(Entity*, u32, u32); +extern bool32 sub_080AF038(Entity*); + +extern void (*const gUnk_080012C8[])(Entity*); + +extern void (*const gUnk_080CD27C[])(Entity*); +extern void (*const gUnk_080CD298[])(Entity*); + +void Chaser(Entity* this) { + u32 idx = sub_080012DC(this); + if (idx) { + gUnk_080012C8[idx](this); + } else { + gUnk_080CD27C[GetNextFunction(this)](this); + } +} + +void sub_0802B518(Entity* this) { + gUnk_080CD298[this->action](this); +} + +void sub_0802B530(Entity* this) { + this->action = 1; + InitializeAnimation(this, 0); +} + +void sub_0802B540(Entity* this) { + if (this->actionDelay) { + this->actionDelay--; + } else { + u32 direction = sub_0804A024(this, 1, 0xc); + if (direction != 0xff) { + this->action = 2; + this->nonPlanarMovement = 0x40; + this->direction = direction; + } + } +} + +void sub_0802B56C(Entity* this) { + GetNextFrame(this); + if (this->bitfield & 0x80) { + this->nonPlanarMovement = 0x40; + } + + if (sub_080AF038(this)) { + if (this->animIndex != 1) { + InitializeAnimation(this, 1); + } + if (this->nonPlanarMovement < 0x220) { + this->nonPlanarMovement += 4; + } + } else { + this->action = 3; + InitializeAnimation(this, 2); + } +} + +void sub_0802B5C8(Entity *this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 1; + this->actionDelay = 30; + InitializeAnimation(this,0); + } +} + + +// clang-format off +void (*const gUnk_080CD27C[])(Entity*) = { + sub_0802B518, + sub_0802B518, + sub_08001324, + sub_0804A7D4, + sub_08001242, + sub_0802B518, + sub_0802B518, +}; + +void (*const gUnk_080CD298[])(Entity*) = { + sub_0802B530, + sub_0802B540, + sub_0802B56C, + sub_0802B5C8, +}; +// clang-format on diff --git a/src/enemy/chuchu.c b/src/enemy/chuchu.c new file mode 100644 index 00000000..9b816805 --- /dev/null +++ b/src/enemy/chuchu.c @@ -0,0 +1,764 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern s32 sub_080012DC(Entity*); +extern void sub_08001318(Entity*); +extern void sub_080043A8(Entity*); +extern u32 sub_08049F1C(Entity*, Entity*, u32); +extern u32 PlayerInRange(Entity*, u32, u32); +extern void sub_0804AA1C(Entity*); +extern void sub_080AF160(Entity*); + +extern Entity* gUnk_020000B0; + +void sub_0801F328(Entity*); +void sub_0801F340(Entity*); +void sub_0801F360(Entity*); +void sub_0801F3AC(Entity*); +void sub_0801F730(Entity*); +void sub_0801F748(Entity*); +void sub_0801F764(Entity*); +void sub_0801FAE0(Entity*); +void sub_0801FAF8(Entity*); +void sub_0801FB14(Entity*); +void sub_0801FB34(Entity*); +void sub_0801FB68(Entity*); +u32 sub_0801FBD0(Entity*); +void Chuchu_JumpAtPlayer(Entity*); + +extern void (*const gUnk_080012C8[])(Entity*); +extern void (*const gUnk_080CA21C[])(Entity*); +extern void (*const gUnk_080CA234[])(Entity*); +extern void (*const gUnk_080CA25C[])(Entity*); +extern void (*const gUnk_080CA288[])(Entity*); + +extern const s8 gUnk_080CA2B4[]; + +void Chuchu(Entity* this) { + int index; + + index = sub_080012DC(this); + switch (index) { + default: + gUnk_080012C8[index](this); + return; + case 0: + /* ... */ + break; + case 2: + this->field_0x3a &= 0xfe; + if (index != this->field_0x80.HALF.HI) { + switch (this->entityType.form) { + case 0: + if (this->flags & 0x80) { + this->action = 6; + this->flags &= ~0x80; + this->nonPlanarMovement = 0x20; + this->damageType = 0x5c; + InitializeAnimation(this, 5); + } + break; + case 1: + /* ... */ + break; + case 2: + sub_080043A8(this); + return; + } + } + break; + } + this->field_0x80.HALF.HI = index; + gUnk_080CA21C[GetNextFunction(this)](this); + if (*(char*)(*(int*)&this->field_0x68 + 10) == 0x1c) { + SetChildOffset(this, 0, 1, -0x10); + } else if (this->entityType.form == 2) { + sub_0801FB34(this); + } +} + +void Chuchu_OnTick(Entity* this) { + switch (this->entityType.form) { + case 0: + sub_0801F3AC(this); + gUnk_080CA234[this->action](this); + break; + case 1: + sub_0801F764(this); + gUnk_080CA25C[this->action](this); + break; + case 2: + gUnk_080CA288[this->action](this); + break; + } +} + +void sub_0801EF40(Entity* this) { + u8 health; + + if (this->entityType.form == 2) { + if (this->bitfield == 0x8e || this->bitfield == 0x95) { + this->flags &= ~0x80; + this->currentHealth = 0; + } + } + + health = this->currentHealth; + if (health) { + if (this->bitfield == 0x94) { + sub_0801FB68(this); + sub_0804A9FC(this, 0x1c); + InitializeAnimation(this, 6); + } else if (this->field_0x80.HALF.LO != health) { + sub_0801FB68(this); + InitializeAnimation(this, 6); + } + } else { + sub_0804AA1C(this); + this->field_0x20 = 0; + InitializeAnimation(this, 9); + } + this->field_0x80.HALF.LO = this->currentHealth; + sub_0804AA30(this, gUnk_080CA21C); +} + +void sub_0801EFD8(Entity* this) { + if (sub_0806F520(this) == 0 && this->field_0x43) { + sub_0804A9FC(this, 0x1c); + InitializeAnimation(this, 6); + } else { + if (this->animIndex != 8) { + sub_0801FB68(this); + InitializeAnimation(this, 8); + } + sub_08003FC4(this, 0x1800); + GetNextFrame(this); + } +} + +void sub_0801F02C(Entity* this) { + if (this->animIndex == 6) + GetNextFrame(this); + sub_08001318(this); +} + +void sub_0801F048(Entity* this) { + sub_08003FC4(this, 0x1800); + GetNextFrame(this); + if (this->entityType.form == 0) { + sub_0804A7D4(this); + } else if (this->entityType.form == 1) { + CreateDeathFx(this, 0xf2, 0); + } else { + CreateDeathFx(this, 0xf1, 0); + } +} + +void sub_0801F084(Entity* this) { + if ((this->frames.all & 0x80) == 0) + GetNextFrame(this); + sub_08001242(this); +} + +void sub_0801F0A4(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->field_0x80.HALF.LO = this->currentHealth; + this->field_0x82.HALF.LO = 0; +} + +void nullsub_4(Entity* this) { + (void)this; +} + +void sub_0801F0C8(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 3; + this->actionDelay = (Random() & 3) + 0xc; + this->field_0xf = Random(); + this->direction = sub_08049F84(this, 1); + this->flags |= 0x80; + this->spritePriority.b0 = 4; + this->spritePriority.b1 = 3; + InitializeAnimation(this, 2); + } +} + +void sub_0801F12C(Entity* this) { + if (sub_0801FBD0(this)) { + sub_0801F328(this); + } else { + if ((this->field_0xf++ & 7) == 0) { + this->direction = sub_08049F84(this, 1); + } + ProcessMovement(this); + GetNextFrame(this); + if (--this->actionDelay == 0) { + if (PlayerInRange(this, 1, 0x38)) { + this->action = 4; + Chuchu_JumpAtPlayer(this); + } else if (PlayerInRange(this, 1, 0x48)) { + this->actionDelay = (Random() & 3) + 0xc; + } else { + sub_0801F328(this); + } + } + } +} + +void sub_0801F1B0(Entity* this) { + if (this->frames.all & 0x10) { + if (this->frames.all & 1) { + this->frames.all ^= 1; + this->damageType = 90; + EnqueueSFX(299); + } + sub_080AEFE0(this); + if (sub_08003FC4(this, 0x4000) == 0) + GetNextFrame(this); + } else { + GetNextFrame(this); + } + + if (this->frames.all & 0x80) { + if (sub_0801FBD0(this)) { + sub_0801F328(this); + } else { + sub_0801F340(this); + } + } +} + +void sub_0801F228(Entity* this) { + if (--this->actionDelay == 0) { + this->action = 3; + this->direction = sub_08049F84(this, 1); + } + GetNextFrame(this); +} + +void sub_0801F250(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) + sub_0801F360(this); +} + +void sub_0801F270(Entity* this) { + if ((this->field_0xf++ & 7) == 0) { + this->direction = sub_08049F84(this, 1); + } + + sub_080AF160(this); + GetNextFrame(this); + if (sub_0801FBD0(this)) + return; + + if (--this->actionDelay) + return; + + if (this->field_0x80.HALF.HI == 0) { + this->action = 2; + InitializeAnimation(this, 4); + } else { + this->actionDelay = 8; + } +} + +void sub_0801F2CC(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 1; + this->spriteSettings.b.draw = 0; + InitializeAnimation(this, 4); + } +} + +void sub_0801F2F8(Entity* this) { + sub_08003FC4(this, 0x1800); + GetNextFrame(this); + if (this->frames.all & 0x80) { + sub_0801F340(this); + sub_0804AA1C(this); + } +} + +void sub_0801F328(Entity* this) { + this->action = 6; + this->flags &= ~0x80; + InitializeAnimation(this, 5); +} + +void sub_0801F340(Entity* this) { + this->action = 5; + this->actionDelay = 60; + this->nonPlanarMovement = 0x20; + this->damageType = 92; + InitializeAnimation(this, 2); +} + +void sub_0801F360(Entity* this) { + this->action = 7; + this->actionDelay = (Random() & 0x38) + 0xb4; + this->field_0xf = Random(); + this->direction = sub_08049F84(this, 1); + this->spritePriority.b1 = 2; + this->spritePriority.b0 = 6; + InitializeAnimation(this, 1); +} + +void sub_0801F3AC(Entity* this) { + if (this->action == 9 || this->action == 0) + return; + + if (sub_08049FDC(this, 1)) { + if (this->field_0x82.HALF.LO || PlayerInRange(this, 1, 0x48)) { + if (this->action == 1) { + this->action = 2; + this->spriteSettings.b.draw = 1; + this->field_0x82.HALF.LO = 1; + InitializeAnimation(this, 0); + } + } else if (this->action == 3) { + sub_0801F328(this); + } + } else if (this->action == 3) { + sub_0801F328(this); + } else if (this->action == 7) { + this->action = 8; + InitializeAnimation(this, 7); + } +} + +void sub_0801F428(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->actionDelay = Random(); + this->field_0x80.HALF.LO = this->currentHealth; + this->field_0x82.HALF.LO = 0; + if (this->entityType.parameter == 0) + return; + + this->action = 3; + this->field_0xf = 30; + this->flags |= 0x80; + this->spritePriority.b1 = 3; + this->spriteSettings.b.draw = 1; + InitializeAnimation(this, 2); +} + +void sub_0801F48C(Entity* this) { + GetNextFrame(this); +} + +void sub_0801F494(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 3; + this->field_0xf = 30; + this->direction = sub_08049F84(this, 1); + this->flags |= 0x80; + this->spritePriority.b0 = 4; + this->spritePriority.b1 = 3; + InitializeAnimation(this, 2); + } +} + +void sub_0801F4EC(Entity* this) { + GetNextFrame(this); + if (--this->field_0xf == 0) + this->action = 4; +} + +void sub_0801F508(Entity* this) { + if (sub_0801FBD0(this)) { + this->field_0x82.HALF.HI = 0; + sub_0801F730(this); + } else { + u8 tmp = ++this->actionDelay & 7; + if (tmp == 0 && PlayerInRange(this, 1, 0x38)) { + if (Random() & 1) { + this->action = 5; + Chuchu_JumpAtPlayer(this); + } else { + this->field_0x82.HALF.HI = 120; + sub_0801F730(this); + } + } else { + if (tmp == 4) { + this->direction = sub_08049F84(this, 1); + } + ProcessMovement(this); + GetNextFrame(this); + } + } +} + +void sub_0801F584(Entity* this) { + if (this->frames.all & 0x10) { + if (this->frames.all & 0x1) { + this->frames.all ^= 1; + this->damageType = 91; + EnqueueSFX(299); + } + sub_080AEFE0(this); + if (sub_08003FC4(this, 0x4000) == 0) + GetNextFrame(this); + + } else { + GetNextFrame(this); + } + + if (this->frames.all & 0x80) { + if (sub_0801FBD0(this)) { + this->field_0x82.HALF.HI = 0; + sub_0801F730(this); + } else { + this->action = 6; + this->field_0xf = 60; + this->nonPlanarMovement = 0x20; + this->damageType = 92; + InitializeAnimation(this, 2); + } + } +} + +void sub_0801F61C(Entity* this) { + if (--this->field_0xf == 0) + this->action = 4; + GetNextFrame(this); +} + +void sub_0801F638(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 8; + this->field_0xf = 30; + this->direction = sub_08049F84(this, 1); + this->spritePriority.b1 = 2; + this->spritePriority.b0 = 6; + InitializeAnimation(this, 1); + } +} + +void sub_0801F688(Entity* this) { + if (this->field_0x82.HALF.HI) + this->field_0x82.HALF.HI--; + + if (sub_0801FBD0(this) || this->field_0x82.HALF.HI) { + this->direction = sub_08049F84(this, 1); + sub_080AF160(this); + GetNextFrame(this); + } else { + sub_0801F748(this); + } +} + +void sub_0801F6CC(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 1; + this->spriteSettings.b.draw = 0; + InitializeAnimation(this, 4); + } +} + +void sub_0801F6F8(Entity* this) { + sub_08003FC4(this, 0x1800); + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 4; + this->nonPlanarMovement = 0x20; + sub_0804AA1C(this); + InitializeAnimation(this, 2); + } +} + +void sub_0801F730(Entity* this) { + this->action = 7; + this->flags &= ~0x80; + InitializeAnimation(this, 5); +} + +void sub_0801F748(Entity* this) { + this->action = 2; + this->spriteSettings.b.draw = 1; + InitializeAnimation(this, 4); +} + +void sub_0801F764(Entity* this) { + if (this->action == 10 || this->action == 0) + return; + + if (sub_08049FDC(this, 1)) { + if (this->action == 1) { + if (this->field_0x82.HALF.LO || PlayerInRange(this, 1, 0x48)) { + this->action = 2; + this->spriteSettings.b.draw = 1; + this->field_0x82.HALF.LO = 1; + InitializeAnimation(this, 0); + } + } + } else if (this->action == 4) { + sub_0801F730(this); + } else if (this->action == 8) { + this->action = 9; + InitializeAnimation(this, 7); + } +} + +void sub_0801F7D8(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->actionDelay = Random(); + this->field_0x80.HALF.LO = this->currentHealth; + this->field_0x82.HALF.LO = 0; +} + +void sub_0801F7FC(Entity* this) { + if (sub_08049FDC(this, 1) == 0) + return; + + if (this->field_0x82.HALF.LO || PlayerInRange(this, 1, 0x48)) { + this->action = 2; + this->spriteSettings.b.draw = 1; + this->field_0x82.HALF.LO = 1; + InitializeAnimation(this, 0); + } +} + +void sub_0801F840(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + sub_0801FB14(this); + this->flags |= 0x80; + this->spritePriority.b0 = 4; + this->spritePriority.b1 = 3; + } +} + +void sub_0801F884(Entity* this) { + GetNextFrame(this); + if (this->field_0xf) { + this->field_0xf--; + } else { + Entity* ent = sub_0804A9FC(this, 0x1b); + if (ent) { + ent->entityType.parameter = 64; + this->action = 4; + this->damageType = 165; + EnqueueSFX(0x193); + } + } +} + +void sub_0801F8C0(Entity* this) { + if (sub_0801FBD0(this)) { + sub_0801FAE0(this); + } else if (sub_08049FDC(this, 1) == 0) { + sub_0801F730(this); + } else { + u8 tmp = ++this->actionDelay & 7; + if (tmp == 0 && sub_08049F1C(this, gUnk_020000B0, 0x38)) { + this->action = 5; + Chuchu_JumpAtPlayer(this); + } else { + if (tmp == 4) { + this->direction = GetFacingDirection(this, gUnk_020000B0); + } + ProcessMovement(this); + GetNextFrame(this); + } + } +} + +void sub_0801F940(Entity* this) { + if (this->frames.all & 0x10) { + if (this->frames.all & 1) { + this->frames.all ^= 1; + EnqueueSFX(299); + } + sub_080AEFE0(this); + if (sub_08003FC4(this, 0x4000) == 0) + GetNextFrame(this); + } else { + GetNextFrame(this); + } + + if (this->frames.all & 0x80) { + if (sub_0801FBD0(this)) { + sub_0801FAE0(this); + } else { + this->action = 6; + this->field_0xf = 60; + this->nonPlanarMovement = 0x20; + InitializeAnimation(this, 2); + } + } +} + +void sub_0801F9C4(Entity* this) { + if (--this->field_0xf == 0) + this->action = 4; + GetNextFrame(this); +} + +void sub_0801F9E0(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 8; + this->field_0xf = 30; + this->direction = sub_08049F84(this, 1); + this->spritePriority.b1 = 2; + this->spritePriority.b0 = 6; + InitializeAnimation(this, 1); + } +} + +void sub_0801FA30(Entity* this) { + if (sub_0801FBD0(this)) { + this->direction = sub_08049F84(this, 1); + sub_080AF160(this); + GetNextFrame(this); + } else if (sub_08049FDC(this, 1) == 0) { + this->action = 9; + InitializeAnimation(this, 7); + } else { + sub_0801FAF8(this); + } +} + +void sub_0801FA78(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 1; + this->spriteSettings.b.draw = 0; + InitializeAnimation(this, 4); + sub_0804AA1C(this); + } +} + +void sub_0801FAAC(Entity* this) { + sub_08003FC4(this, 0x1800); + GetNextFrame(this); + if (this->frames.all & 0x80) { + sub_0801FB14(this); + this->nonPlanarMovement = 0x20; + sub_0804AA1C(this); + } +} + +void sub_0801FAE0(Entity* this) { + this->action = 7; + this->flags &= ~0x80; + InitializeAnimation(this, 5); +} + +void sub_0801FAF8(Entity* this) { + this->action = 2; + this->spriteSettings.b.draw = 1; + InitializeAnimation(this, 4); +} + +void sub_0801FB14(Entity* this) { + this->action = 3; + this->field_0xf = 30; + this->direction = sub_08049F84(this, 1); + InitializeAnimation(this, 2); +} + +void sub_0801FB34(Entity* this) { + if (*(Entity**)&this->field_0x68) { + sub_0806FA90(this, *(Entity**)&this->field_0x68, gUnk_080CA2B4[this->frames.all & 0xf], 1); + (*(Entity**)&this->field_0x68)->spriteOffsetY--; + } +} + +void sub_0801FB68(Entity* this) { + switch (this->entityType.form) { + case 0: + this->action = 9; + break; + case 1: + this->action = 10; + this->flags |= 0x80; + this->spriteSettings.b.draw = 1; + this->spritePriority.b1 = 3; + break; + case 2: + this->action = 10; + this->damageType = 92; + sub_0804AA1C(this); + break; + } + + this->field_0x20 = 0; +} + +u32 sub_0801FBD0(Entity* this) { + if (sub_080002B8(this) == 0x10) { + return 1; + } else { + return 0; + } +} + +void Chuchu_JumpAtPlayer(Entity* this) { + this->nonPlanarMovement = 0x180; + this->field_0x20 = 0x20000; + this->direction = sub_08049F84(this, 1); + InitializeAnimation(this, 3); +} + +// clang-format off +void (*const gUnk_080CA21C[])(Entity*) = { + Chuchu_OnTick, + sub_0801EF40, + sub_0801F02C, + sub_0801F048, + sub_0801F084, + sub_0801EFD8, +}; + +void (*const gUnk_080CA234[])(Entity*) = { + sub_0801F0A4, + nullsub_4, + sub_0801F0C8, + sub_0801F12C, + sub_0801F1B0, + sub_0801F228, + sub_0801F250, + sub_0801F270, + sub_0801F2CC, + sub_0801F2F8, +}; + +void (*const gUnk_080CA25C[])(Entity*) = { + sub_0801F428, + sub_0801F48C, + sub_0801F494, + sub_0801F4EC, + sub_0801F508, + sub_0801F584, + sub_0801F61C, + sub_0801F638, + sub_0801F688, + sub_0801F6CC, + sub_0801F6F8, +}; + +void (*const gUnk_080CA288[])(Entity*) = { + sub_0801F7D8, + sub_0801F7FC, + sub_0801F840, + sub_0801F884, + sub_0801F8C0, + sub_0801F940, + sub_0801F9C4, + sub_0801F9E0, + sub_0801FA30, + sub_0801FA78, + sub_0801FAAC, +}; +// clang-format on diff --git a/src/enemy/chuchuBoss.c b/src/enemy/chuchuBoss.c index 169deeb4..ee21e03c 100644 --- a/src/enemy/chuchuBoss.c +++ b/src/enemy/chuchuBoss.c @@ -1,12 +1,28 @@ +#include "enemy.h" #include "entity.h" #include "functions.h" -#include "enemy.h" -extern void (*const gUnk_080CC19C[])(Entity*); +extern void sub_08078B48(void); -extern void sub_08001324(Entity*); void sub_08027870(Entity*); +extern void (*const gUnk_080CC19C[])(Entity*); +extern void (*const gUnk_080CC1B0[])(Entity*); +extern const u8 gUnk_080CC1B8[]; +extern void (*const gUnk_080CC1C8[])(Entity*); +extern void (*const gUnk_080CC1DC[])(Entity*); +extern void (*const gUnk_080CC20C[])(Entity*); +extern const u8 gUnk_080CC234[]; +extern const u8 gUnk_080CC24F[]; +extern void (*const gUnk_080CC258[])(Entity*); +extern void (*const gUnk_080CC264[])(Entity*); +extern void (*const gUnk_080CC26C[])(Entity*); +extern const u8 gUnk_080CC278[]; +extern const u16 gUnk_080CC27C[]; +extern const u16 gUnk_080CC29C[]; +extern const u16 gUnk_080CC2BC[]; +extern const s8 gUnk_080CC2DC[]; + void ChuchuBoss(Entity* this) { gUnk_080CC19C[GetNextFunction(this)]((Entity*)this); } @@ -17,3 +33,168 @@ void sub_08025CBC(Entity* this) { sub_08027870(this); } } + +void sub_08025DC0(Entity*); +void sub_08025CD4(Entity*); +void sub_08001242(Entity*); +void sub_08025DD8(Entity*); +void sub_08026060(Entity*); +void sub_08026110(Entity*); +void sub_080272D4(Entity*); +void sub_0802720C(Entity*); +void sub_0802720C(Entity*); +void sub_08026090(Entity*); +void sub_0802626C(Entity*); +void sub_08026580(Entity*); +void sub_08026634(Entity*); +void sub_08026750(Entity*); +void sub_0802686C(Entity*); +void sub_080268C8(Entity*); +void sub_0802694C(Entity*); +void sub_08026C40(Entity*); +void sub_08026E1C(Entity*); +void sub_08026FA4(Entity*); +void sub_08027064(Entity*); +void sub_08026F1C(Entity*); +void sub_080262A8(Entity*); +void sub_08026328(Entity*); +void sub_08026358(Entity*); +void sub_080263B4(Entity*); +void sub_08026414(Entity*); +void sub_0802647C(Entity*); +void sub_080264AC(Entity*); +void sub_080264D4(Entity*); +void sub_0802650C(Entity*); +void sub_0802653C(Entity*); +void sub_08026774(Entity*); +void sub_080267D0(Entity*); +void sub_08026808(Entity*); +void sub_080268EC(Entity*); +void sub_08026914(Entity*); +void sub_08026968(Entity*); +void sub_080269CC(Entity*); +void sub_08026BE8(Entity*); + +// clang-format off +void (*const gUnk_080CC19C[])(Entity*) = { + sub_08025DC0, + sub_08025DC0, + sub_08025CBC, + sub_08025CD4, + sub_08001242, +}; + +void (*const gUnk_080CC1B0[])(Entity*) = { + sub_08025DD8, + sub_08026060, +}; + +const u8 gUnk_080CC1B8[] = { + 0, 4, + 0, 0, + 0, 4, + 0, 0, + 1, 4, + 0, 0, + 2, 4, + 0, 0, +}; + +void (*const gUnk_080CC1C8[])(Entity*) = { + sub_08026110, + sub_080272D4, + sub_0802720C, + sub_0802720C, + sub_08026090, +}; + +void (*const gUnk_080CC1DC[])(Entity*) = { + sub_0802626C, + sub_08026580, + sub_08026634, + sub_08026750, + sub_0802686C, + sub_080268C8, + sub_0802694C, + sub_08026C40, + sub_08026E1C, + sub_08026FA4, + sub_08027064, + sub_08026F1C, +}; + +void (*const gUnk_080CC20C[])(Entity*) = { + sub_080262A8, + sub_08026328, + sub_08026358, + sub_080263B4, + sub_08026414, + sub_0802647C, + sub_080264AC, + sub_080264D4, + sub_0802650C, + sub_0802653C, +}; + +const u8 gUnk_080CC234[] = { + 0x3C, 0x1E, 0x1E, 0x1E, + 0x1E, 0x0F, 0x0F, 0x0F, + 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x0A, 0x0A, + 0x0A, 0x0F, 0x0F, 0x0F, + 0x1E, 0x1E, 0x2D, 0x0A, + 0x5A, 0x1E, 0xFF, +}; + +const u8 gUnk_080CC24F[] = { + 2, 2, 4, 4, + 4, 6, 6, 8, +}; + +void (*const gUnk_080CC258[])(Entity*) = { + sub_08026774, + sub_080267D0, + sub_08026808, +}; + +void (*const gUnk_080CC264[])(Entity*) = { + sub_080268EC, + sub_08026914, +}; + +void (*const gUnk_080CC26C[])(Entity*) = { + sub_08026968, + sub_080269CC, + sub_08026BE8, +}; + +const u8 gUnk_080CC278[] = { + 150, 180, 210, 250, +}; + +const u16 gUnk_080CC27C[] = { + 0x80, 0x8, 0x100, 0x6, + 0x80, 0x18, 0x100, 0x8, + 0x180, 0x6, 0x100, 0x10, + 0x0, 0x0, 0xA0, 0x18, +}; + +const u16 gUnk_080CC29C[] = { + 0x80, 0x8, 0x100, 0x4, + 0x80, 0xC, 0x80, 0x6, + 0x200, 0x6, 0x100, 0xC, + 0x0, 0x0, 0xA0, 0x14, +}; + +const u16 gUnk_080CC2BC[] = { + 0x80, 0x8, 0x100, 0x0, + 0x60, 0x2, 0x80, 0x2, + 0x200, 0x6, 0x100, 0x8, + 0x0, 0x0, 0xA0, 0x10, +}; + + +const s8 gUnk_080CC2DC[] = { + -7, -9, -7, +}; +// clang-format on diff --git a/src/enemy/cuccoChickAggr.c b/src/enemy/cuccoChickAggr.c new file mode 100644 index 00000000..686e5100 --- /dev/null +++ b/src/enemy/cuccoChickAggr.c @@ -0,0 +1,167 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern Entity* sub_08049DF4(u32); + +void sub_08022A88(Entity*); +void sub_08022AA4(Entity*); +void sub_08022B0C(Entity*); +u32 sub_08022B20(Entity*); +void sub_08022B44(Entity*); + +extern void (*const gUnk_080CBB64[])(Entity*); +extern void (*const gUnk_080CBB7C[])(Entity*); + +void CuccoChickAggr(Entity* this) { + gUnk_080CBB64[GetNextFunction(this)](this); +} + +void sub_08022934(Entity* this) { + gUnk_080CBB7C[this->action](this); +} + +void sub_0802294C(Entity* this) { + sub_0804AA30(this, gUnk_080CBB64); +} + +void nullsub_132(Entity* this) { +} + +void sub_08022960(Entity* this) { + sub_0804A720(this); + sub_08022A88(this); +} + +void sub_08022970(Entity* this) { + if (--this->actionDelay == 0) { + sub_08022AA4(this); + } +} + +void sub_08022988(Entity* this) { + if (this->height.HALF.HI == 0 && sub_08022B20(this)) { + sub_08022B0C(this); + } else { + if (this->field_0xf) { + if (--this->field_0xf) + return; + + this->frameIndex = 1; + this->field_0x20 = 0x10000; + EnqueueSFX(0xd6); + } + + ProcessMovement(this); + if (sub_08003FC4(this, 0x2000) == 0) { + if (--this->actionDelay == 0) { + sub_08022A88(this); + } else { + this->field_0xf = 4; + this->frameIndex = 0; + } + } + } +} + +void sub_080229F8(Entity* this) { + if (sub_08003FC4(this, 0x2800) == 0) { + if (--this->actionDelay == 0) { + this->action = 4; + this->actionDelay = 6; + this->field_0xf = 8; + this->frameIndex = 0; + this->nonPlanarMovement = 0xc0; + sub_08022B44(this); + } else { + this->field_0x20 = 0x10000; + EnqueueSFX(0xd6); + } + } +} + +void sub_08022A40(Entity* this) { + if (this->field_0xf) { + if (--this->field_0xf) + return; + + this->frameIndex = 1; + } + + ProcessMovement(this); + if (sub_08003FC4(this, 0x2000) == 0) { + if (--this->actionDelay == 0) { + sub_08022A88(this); + } else { + sub_08022B44(this); + } + } +} + +void sub_08022A88(Entity* this) { + this->action = 1; + this->actionDelay = (Random() & 0xf) + 8; + this->frameIndex = 0; +} + +void sub_08022AA4(Entity* this) { + u32 rand = Random(); + + this->action = 2; + this->actionDelay = (rand & 3) + 1; + this->field_0xf = 1; + this->nonPlanarMovement = 0x80; + + if (!sub_08049FA0(this) && (rand >> 8) & 3) { + this->direction = sub_08049EE4(this); + } else { + this->direction = (rand >> 0x10) & 0x1f; + } + + if (this->direction & 0xf) + this->spriteSettings.b.flipX = (this->direction >> 4) ^ 1; +} + +void sub_08022B0C(Entity* this) { + this->action = 3; + this->actionDelay = 3; + this->field_0xf = 8; + sub_08022B44(this); +} + +u32 sub_08022B20(Entity* this) { + if (!sub_08049DF4(2)) + return 0; + + return sub_080041A0(this, &gPlayerEntity, 0x24, 0x24); +} + +void sub_08022B44(Entity *this){ + this->field_0x20 = 0xc000; + this->direction = GetFacingDirection(this,&gPlayerEntity); + + if (this->direction & 0xf) + this->spriteSettings.b.flipX = (this->direction >> 4)^1; + + EnqueueSFX(0xd6); +} + + +// clang-format off +void (*const gUnk_080CBB64[])(Entity*) = { + sub_08022934, + sub_0802294C, + sub_08001324, + sub_0804A7D4, + sub_08001242, + nullsub_132, +}; + +void (*const gUnk_080CBB7C[])(Entity*) = { + sub_08022960, + sub_08022970, + sub_08022988, + sub_080229F8, + sub_08022A40, +}; +// clang-format on diff --git a/src/enemy/darkNut.c b/src/enemy/darkNut.c new file mode 100644 index 00000000..b0c63e8a --- /dev/null +++ b/src/enemy/darkNut.c @@ -0,0 +1,754 @@ +#include "entity.h" +#include "functions.h" + +typedef struct { + u8 field_0x0; + u8 field_0x1; +} PACKED stuct_080CAB14; + +void sub_08021218(); +void sub_08021588(); +void sub_080213D0(); +void sub_08021390(); +void sub_0802159C(); +void sub_0804AA1C(); +void sub_080213F0(); +u32 sub_080214FC(); +void sub_08021540(); +void sub_08021600(); +void sub_080213B0(); +u32 PlayerInRange(); +u32 sub_0802169C(); +void sub_0802124C(); +void sub_08021644(); +void sub_08021414(); +void sub_08021400(); +u32 sub_08021274(u32, u32); +u32 sub_08021664(Entity*, Entity*); +u32 sub_0804A044(Entity*, Entity*, u32); +void sub_08021424(Entity*); + +extern Entity* gUnk_020000B0; + +extern void (*const gUnk_080CAA98[])(Entity*); +extern void (*const gUnk_080CAAB0[])(Entity*); + +extern const s8 gUnk_080CAB00[]; +extern const s8 gUnk_080CAB04[]; +extern const u8 gUnk_080CAB08[]; +extern const s8 gUnk_080CAB0C[]; +extern const s8 gUnk_080CAB10[]; +extern const stuct_080CAB14 gUnk_080CAB14[]; +extern const u8 gUnk_080CAB3A[]; +extern const u8 gUnk_080CAB42[]; +extern const u8 gUnk_080CAB4A[]; +extern const u8 gUnk_080CAB52[]; +extern const u8 gUnk_080CAB68[]; + +extern void (*const gUnk_080CAB58[])(Entity*); + +void DarkNut(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CAA98); + SetChildOffset(this, 0, 1, -22); +} + +void sub_08020BA0(Entity* this) { + gUnk_080CAAB0[this->action](this); +} + +void sub_08020BB8(Entity* this) { + switch (this->bitfield & 0x7f) { + case 0x1c: + this->action = 11; + this->actionDelay = gUnk_080CAB0C[this->entityType.form]; + this->damageType = 81; + sub_08021218(this, 8, DirectionToAnimationState(this->field_0x3e ^ 0x10)); + sub_08021588(this); + sub_0804A9FC(this, 0x1c); + break; + case 0x16: + this->action = 11; + this->actionDelay = gUnk_080CAB10[this->entityType.form]; + this->damageType = 81; + sub_08021218(this, 8, DirectionToAnimationState(this->field_0x3e ^ 0x10)); + sub_08021588(this); + sub_0804A9FC(this, 0x1c); + break; + case 0x4b: + if (this->action == 13 || this->action == 15 || this->action == 19 || this->action == 18) + break; + switch (this->field_0x78.HALF.HI) { + case 8 ... 12: + this->field_0x7a.HALF.LO = gUnk_080CAB04[this->entityType.form]; + break; + case 4 ... 6: + this->field_0x7a.HALF.LO = gUnk_080CAB00[this->entityType.form]; + break; + default: + this->field_0x7a.HALF.LO = 0; + break; + } + this->action = 10; + sub_08021218(this, 0xb, this->animationState); + EnqueueSFX(0x15d); + sub_08021588(this); + break; + case 0x4c: + if (this->action == 15) { + u8 bVar3 = 0xff; + if (this->attachedEntity != NULL) { + bVar3 = this->attachedEntity->bitfield & 0x7f; + } + if (bVar3 == 2) { + sub_080213D0(this, gUnk_080CAB08[this->entityType.form]); + } else { + sub_080213D0(this, 0); + } + } + break; + default: + if (this->currentHealth != this->field_0x78.HALF.LO) { + sub_08021588(this); + sub_08021390(this); + sub_0804AA1C(this); + } + break; + } + this->field_0x78.HALF.LO = this->currentHealth; + sub_0804AA30(this, gUnk_080CAA98); +} + +void nullsub_129(Entity* this) { +} + +void sub_08020D70(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->field_0x74.HALF.HI = 0; + this->field_0x78.HALF.LO = this->currentHealth; + this->animationState = -1; + sub_08021218(this, 0, 2); +} + +void sub_08020D9C(Entity* this) { + if (sub_08049FDC(this, 1)) + sub_080213F0(this); +} + +void sub_08020DB4(Entity* this) { + UpdateAnimationSingleFrame(this); + if (this->frames.all & 0x80) + sub_08021390(this); +} + +void sub_08020DD4(Entity* this) { + if (sub_080214FC(this)) { + sub_080213F0(this); + } else if (--this->field_0x76.HWORD == 0) { + this->action = 5; + sub_08021218(this, 5, this->animationState); + } else { + if (--this->actionDelay == 0) + sub_08021540(this); + ProcessMovement(this); + UpdateAnimationSingleFrame(this); + } +} + +void sub_08020E28(Entity* this) { + UpdateAnimationSingleFrame(this); + if (this->frames.all & 0x80) + sub_080213B0(this); +} + +void sub_08020E48(Entity* this) { + if (sub_080214FC(this)) { + sub_080213F0(this); + } else { + UpdateAnimationSingleFrame(this); + if (this->frames.all & 0x80) + sub_080213B0(this); + } +} + +void sub_08020E78(Entity* this) { + UpdateAnimationSingleFrame(this); + if (this->frames.all & 0x80) + sub_08021390(this); +} + +void sub_08020E98(Entity* this) { + if (PlayerInRange(this, 1, 0x38)) { + if (sub_0802169C(this, gUnk_020000B0)) { + this->action = 8; + sub_08021218(this, 7, this->animationState); + } else { + this->direction = GetFacingDirection(gUnk_020000B0, this); + if (ProcessMovement(this) == 0) { + this->action = 8; + sub_08021218(this, 7, this->animationState); + } else { + this->direction ^= 0x10; + sub_0802124C(this); + sub_08021644(this); + } + } + } else { + if (gUnk_020000B0 == NULL) { + sub_08021414(this); + } else { + this->direction = GetFacingDirection(this, gUnk_020000B0); + ProcessMovement(this); + sub_0802124C(this); + sub_08021644(this); + } + } +} + +void sub_08020F28(Entity* this) { + UpdateAnimationSingleFrame(this); + if (this->frames.all & 0x80) + sub_08021400(this); +} + +void sub_08020F48(Entity* this) { + if (PlayerInRange(this, 1, 0x48)) { + if (sub_08021664(this, gUnk_020000B0)) { + u32 uVar2 = sub_0804A044(this, gUnk_020000B0, 9); + if (uVar2 == 0xff) { + sub_08021424(this); + } else { + Entity* pEVar3; + + this->action = 14; + sub_08021218(this, 13, uVar2 >> 3); + pEVar3 = sub_0804A98C(this, 0, 1); + if (pEVar3) { + pEVar3->parent = this; + this->attachedEntity = pEVar3; + } + } + } else { + sub_08021424(this); + } + } else { + sub_08021390(this); + } +} + +void sub_08020FAC(Entity* this) { + if (this->frames.all & 0x80) { + if (this->field_0x7a.HALF.LO) { + this->field_0x7a.HALF.LO--; + } else { + this->hurtBlinkTime = -8; + sub_08021390(this); + } + } else { + UpdateAnimationSingleFrame(this); + } +} + +void sub_08020FE4(Entity* this) { + UpdateAnimationSingleFrame(this); + if (--this->actionDelay == 0) { + this->action = 12; + sub_08021218(this, 9, this->animationState); + sub_0804AA1C(this); + } +} + +void sub_08021010(Entity* this) { + UpdateAnimationSingleFrame(this); + if (this->frames.all & 0x80) { + this->damageType = 0x56; + sub_080213F0(this); + } +} + +void sub_08021038(Entity* this) { + if (this->attachedEntity == NULL && this->frames.all) { + Entity* pEVar2 = (Entity*)sub_0804A98C(this, 0, 0); + if (pEVar2) { + pEVar2->parent = this; + this->attachedEntity = pEVar2; + } + EnqueueSFX(270); + } + + if (this->frames.all & 0x80) { + sub_08021588(this); + if (this->field_0x7c.BYTES.byte0) { + this->field_0x7c.BYTES.byte0--; + } else { + sub_08021390(this); + } + } else { + UpdateAnimationSingleFrame(this); + if (this->frames.all == 4) + this->damageType = 81; + } +} + +void sub_080210A8(Entity* this) { + UpdateAnimationSingleFrame(this); + if (this->frames.all & 1) { + this->frames.all = 0; + sub_08021588(this); + EnqueueSFX(349); + } else if (this->frames.all & 0x80) { + sub_08021390(this); + } +} + +void sub_080210E4(Entity* this) { + UpdateAnimationSingleFrame(this); + if (this->frames.all & 1) { + Entity* ent; + + this->frames.all &= ~1; + ent = sub_0804A98C(this, 0, 2); + if (ent) { + ent->parent = this; + this->attachedEntity = ent; + } + + EnqueueSFX(270); + } + + sub_08021644(this); + if ((this->frames.all & 0x10) && + (!ProcessMovement(this) || (this->attachedEntity && (this->attachedEntity->bitfield & 0x80)))) { + sub_080213D0(this, 0); + } else { + if (--this->field_0x76.HWORD == 0) + sub_080213D0(this, 0); + } +} + +void sub_08021170(Entity* this) { + if (this->frames.all & 0x80) { + if (this->field_0x7a.HALF.HI) { + this->field_0x7a.HALF.HI--; + } else { + sub_08021390(this); + } + } else { + UpdateAnimationSingleFrame(this); + } +} + +void sub_080211A0(Entity* this) { + if (sub_080214FC(this)) { + sub_08021390(this); + } else { + UpdateAnimationSingleFrame(this); + if (this->frames.all & 0x80) + sub_080213B0(this); + } +} + +void sub_080211D0(Entity* this) + +{ + UpdateAnimationSingleFrame(this); + sub_0802159C(this); + + if (this->frames.all & 0x80) + sub_08021390(this); +} + +void sub_080211F4(Entity* this) { + UpdateAnimationSingleFrame(this); + sub_08021600(this); + + if (this->frames.all & 0x80) + sub_08021390(this); +} + +void sub_08021218(Entity* this, u32 param_2, u32 param_3) { + const stuct_080CAB14* unk; + + if (this->field_0x74.HALF.LO == param_2 && this->animationState == param_3) + return; + + this->animationState = param_3; + this->field_0x74.HALF.LO = param_2; + + unk = &gUnk_080CAB14[param_2]; + this->spriteIndex = unk->field_0x1; + InitAnimationForceUpdate(this, unk->field_0x0 + param_3); +} + +void sub_0802124C(Entity* this) { + u32 iVar1 = sub_08021274(this->animationState, this->direction); + if (iVar1 != 0xff) { + sub_08021218(this, this->field_0x74.HALF.LO, iVar1); + } else { + UpdateAnimationSingleFrame(this); + } +} + +NAKED +u32 sub_08021274(u32 a, u32 b) { + asm(".include \"asm/non_matching/darkNut/sub_08021274.inc\""); +} + +void sub_080212B0(Entity* this) { + u8 tmp; + + switch (this->field_0x74.HALF.HI) { + default: + this->field_0x74.HALF.HI = 1; + tmp = gUnk_080CAB3A[Random() & 7]; + break; + case 1: + this->field_0x74.HALF.HI = 2; + tmp = gUnk_080CAB42[Random() & 7]; + break; + case 2: + this->field_0x74.HALF.HI = 0; + tmp = gUnk_080CAB4A[Random() & 7]; + break; + } + + if (this->entityType.form < 2 && tmp == 2) + tmp = gUnk_080CAB52[Random() & 3]; + + this->attachedEntity = NULL; + gUnk_080CAB58[tmp](this); +} + +void sub_08021328(Entity* this) { + this->action = 13; + this->field_0x7c.BYTES.byte0 = gUnk_080CAB68[this->entityType.form]; + sub_08021218(this, 0xc, this->animationState); +} + +void sub_0802134C(Entity* this) { + this->action = 15; + this->direction = DirectionFromAnimationState(this->animationState); + this->nonPlanarMovement = 0x200; + this->field_0x76.HWORD = 0x78; + sub_08021218(this, 0xe, this->animationState); +} + +void sub_08021370(Entity* this) { + this->action = 18; + sub_08021218(this, 0x10, this->animationState); +} + +void sub_08021380(Entity* this) { + this->action = 19; + sub_08021218(this, 0x11, this->animationState); +} + +void sub_08021390(Entity* this) { + this->action = 7; + this->nonPlanarMovement = 0x200; + this->damageType = 0x56; + sub_08021218(this, 6, this->animationState); +} + +void sub_080213B0(Entity* this) { + this->action = 3; + this->actionDelay = 1; + this->nonPlanarMovement = 0xc0; + this->field_0x76.HWORD = 0xf0; + sub_08021218(this, 3, this->animationState); +} + +void sub_080213D0(Entity* this, u32 param_2) { + this->action = 16; + this->field_0x7a.HALF.HI = param_2; + sub_08021218(this, 0xf, this->animationState); + sub_08021588(this); +} + +void sub_080213F0(Entity* this) { + this->action = 6; + sub_08021218(this, 1, this->animationState); +} + +void sub_08021400(Entity* this) { + this->action = 9; + this->nonPlanarMovement = 0x60; + sub_08021218(this, 10, this->animationState); +} + +void sub_08021414(Entity* this) { + this->action = 17; + sub_08021218(this, 5, this->animationState); +} + +void sub_08021424(Entity* this) { + s32 x, y; + u32 tmp; + + u32 dir = GetFacingDirection(this, gUnk_020000B0); + tmp = sub_08021274(this->animationState, dir); + if (tmp != 0xff) { + sub_08021218(this, this->field_0x74.HALF.LO, tmp); + } else { + tmp = this->animationState; + } + + switch (tmp) { + case 0: + x = gUnk_020000B0->x.HALF.HI; + y = gUnk_020000B0->y.HALF.HI + 0x2c; + break; + case 1: + x = gUnk_020000B0->x.HALF.HI - 0x24; + y = gUnk_020000B0->y.HALF.HI; + break; + case 2: + x = gUnk_020000B0->x.HALF.HI; + y = gUnk_020000B0->y.HALF.HI - 0x1d; + break; + default: + x = gUnk_020000B0->x.HALF.HI + 0x24; + y = gUnk_020000B0->y.HALF.HI; + break; + } + + if (!(6 < (x - this->x.HALF.HI) + 3U) && !(4 < (y - this->y.HALF.HI) + 2U)) { + sub_080212B0(this); + } else { + this->direction = sub_080045D4(this->x.HALF.HI, this->y.HALF.HI, x, y); + if (!ProcessMovement(this)) { + sub_080212B0(this); + } else { + UpdateAnimationSingleFrame(this); + } + } +} + +u32 sub_080214FC(Entity* this) { + u32 direction; + + if (!sub_08049FDC(this, 1)) + return 0; + + direction = GetFacingDirection(this, gUnk_020000B0); + if (4 < (direction - (this->frames.all & 0x1f)) - 2) + return 0; + + this->animationState = DirectionToAnimationState(direction); + return 1; +} + +void sub_08021540(Entity* this) { + u32 tmp, tmp2; + u32 rand; + + rand = Random(); + if (!sub_08049FA0(this) && (rand & 1)) { + tmp2 = DirectionRoundUp(sub_08049EE4(this)); + } else { + tmp2 = DirectionRound(rand >> 0x10); + } + this->direction = tmp2; + + tmp = sub_08021274(this->animationState, tmp2); + if (tmp != 0xff) + sub_08021218(this, 3, tmp); + + this->actionDelay = 30; +} + +void sub_08021588(Entity* this) { + if (this->attachedEntity) { + this->attachedEntity->parent = NULL; + this->attachedEntity = NULL; + } +} + +void sub_0802159C(Entity* this) { + if (this->frames.all == 1) { + Entity* ent; + + this->frames.all = 0; + this->damageType = 0x51; + ent = sub_0804A98C(this, 0, 3); + if (ent) { + ent->parent = this; + this->attachedEntity = ent; + } + EnqueueSFX(0x116); + } else if (this->frames.all == 2) { + this->frames.all = 0; + sub_08021588(this); + } else if (this->frames.all & 0x20) { + this->frames.all &= ~0x20; + EnqueueSFX(0x115); + } +} + +void sub_08021600(Entity* this) { + if (this->frames.all == 1) { + Entity* ent; + + this->frames.all = 0; + this->damageType = 0x51; + ent = sub_0804A98C(this, 0, 4); + if (ent) { + ent->parent = this; + this->attachedEntity = ent; + } + EnqueueSFX(0x10e); + } else if (this->frames.all == 2) { + this->frames.all = 0; + sub_08021588(this); + } +} + +void sub_08021644(Entity* this) { + if (this->frames.all & 0x20) { + this->frames.all &= ~0x20; + EnqueueSFX(0x7d); + } +} + +extern u32 sub_08049F1C(Entity*, Entity*, u32); + +u32 sub_08021664(Entity* this, Entity* ent) { + switch (this->animationState) { + case 0: + return sub_08049F1C(this, ent, 0x22); + case 1: + return sub_08049F1C(this, ent, 0x1a); + case 2: + return sub_08049F1C(this, ent, 0x13); + case 3: + return sub_08049F1C(this, ent, 0x1a); + } + return 0; +} + +u32 sub_0802169C(Entity* this, Entity* ent) { + u32 ret; + + switch (this->animationState) { + case 0: + ret = 0x2c; + break; + case 2: + ret = 0x1d; + break; + case 1: + case 3: + ret = 0x24; + break; + default: + return 0; + } + + if (sub_08049F1C(this, ent, ret)) { + return 0; + } else { + return 1; + } +} + +// clang-format off +void (*const gUnk_080CAA98[])(Entity*) = { + sub_08020BA0, + sub_08020BB8, + sub_08001324, + sub_0804A7D4, + sub_08001242, + nullsub_129, +}; +void (*const gUnk_080CAAB0[])(Entity*) = { + sub_08020D70, + sub_08020D9C, + sub_08020DB4, + sub_08020DD4, + sub_08020E28, + sub_08020E48, + sub_08020E78, + sub_08020E98, + sub_08020F28, + sub_08020F48, + sub_08020FAC, + sub_08020FE4, + sub_08021010, + sub_08021038, + sub_080210A8, + sub_080210E4, + sub_08021170, + sub_080211A0, + sub_080211D0, + sub_080211F4, +}; + +const s8 gUnk_080CAB00[] = { + 30, 30, 20, 10, +}; + +const s8 gUnk_080CAB04[] = { + 60, 60, 45, 30, +}; + +const u8 gUnk_080CAB08[] = { + 90, 90, 60, 30, +}; + +const s8 gUnk_080CAB0C[] = { + 90, 90, 60, 30, +}; + +const s8 gUnk_080CAB10[] = { + 90, 90, 45, 8, +}; + +const stuct_080CAB14 gUnk_080CAB14[] = { + {0x00, 0x62}, + {0x04, 0x62}, + {0x08, 0x62}, + {0x0C, 0x62}, + {0x10, 0x62}, + {0x14, 0x62}, + {0x18, 0x62}, + {0x1C, 0x62}, + {0x20, 0x62}, + {0x24, 0x62}, + {0x28, 0x62}, + {0x2C, 0x62}, + {0x00, 0x63}, + {0x04, 0x63}, + {0x08, 0x63}, + {0x0C, 0x63}, + {0x10, 0x63}, + {0x14, 0x63}, + {0x18, 0x63}, +}; + +const u8 gUnk_080CAB3A[] = { + 0, 1, 1, 0, 3, 0, 1, 0, +}; + +const u8 gUnk_080CAB42[] = { + 1, 1, 3, 0, 1, 2, 0, 0, +}; + +const u8 gUnk_080CAB4A[] = { + 0, 0, 3, 1, 2, 2, 3, 1, +}; + +const u8 gUnk_080CAB52[] = { + 0, 3, 1, 0, 0, 0 +}; + +void (*const gUnk_080CAB58[])(Entity*) = { + sub_08021328, + sub_0802134C, + sub_08021370, + sub_08021380, +}; + +const u8 gUnk_080CAB68[] = { + 90, 90, 45, 7, +}; +// clang-format on diff --git a/src/enemy/doorMimic.c b/src/enemy/doorMimic.c new file mode 100644 index 00000000..069c205b --- /dev/null +++ b/src/enemy/doorMimic.c @@ -0,0 +1,246 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern s16 sub_080001DA(u32, u32); // ? +extern void sub_08049CF4(); +extern u32 sub_0806FBFC(u32, u32, u32, u32); +void sub_080221C0(); + +typedef struct { + s8 h; + s8 v; +} PACKED PosOffset; + +extern void (*const gUnk_080CB734[])(Entity*); +extern void (*const gUnk_080CB74C[])(Entity*); + +extern const s8 gUnk_080CB764[]; +extern const PosOffset gUnk_080CB76C[4][6]; +extern const u16 gUnk_080CB79C[]; +extern const BoundingBox* const* const gUnk_080CB8A4[]; + +extern s16 gUnk_080B4488[]; + +void DoorMimic(Entity* this) { + gUnk_080CB734[GetNextFunction(this)](this); + this->boundingBox = (BoundingBox*)gUnk_080CB8A4[this->entityType.parameter][this->frameIndex]; +} + +void sub_08021FDC(Entity* this) { + gUnk_080CB74C[this->action](this); +} + +void sub_08021FF4(Entity* this) { + sub_0804AA30(this, gUnk_080CB734); +} + +void sub_08022004(Entity* this) { + SetTile((u16)this->field_0x7c.HALF.LO, (u16)this->field_0x7c.HALF.HI, this->collisionLayer); + CreateFx(this, 5, 0); + sub_08049CF4(this); + DeleteThisEntity(); +} + +void sub_08022034(Entity* this) { + this->action = 1; + this->entityType.parameter = this->entityType.form & 3; + this->spritePriority.b0 = 5; + this->field_0x78.HWORD = gUnk_080CB764[this->entityType.parameter * 2 + 0] + this->x.HALF.HI; + this->field_0x7a.HWORD = gUnk_080CB764[this->entityType.parameter * 2 + 1] + this->y.HALF.HI; + InitializeAnimation(this, this->entityType.parameter); + sub_080221C0(this); +} + +void sub_0802209C(Entity* this) { + if (this->actionDelay == 0) { + if (sub_0806FBFC(this->field_0x78.HWORD, this->field_0x7a.HWORD, 0x10, 0x10)) { + this->action = 2; + this->actionDelay = 0x12; + InitializeAnimation(this, this->entityType.parameter + 4); + } + } else { + this->actionDelay = this->actionDelay - 1; + } +} + +void sub_080220D8(Entity* this) { + if (--this->actionDelay == 0) + this->action = 3; +} + +void sub_080220F0(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + const PosOffset* off; + u32 i; + + this->action = 4; + this->actionDelay = 0x78; + this->field_0x44 = 0; + off = gUnk_080CB76C[this->entityType.parameter]; + for (i = 0; i < 6; i++, off++) { + Entity* fx = CreateFx(this, 0x11, 0); + if (fx) { + fx->x.HALF.HI += off->h; + fx->y.HALF.HI += off->v; + } + } + EnqueueSFX(260); + } else if (this->frames.all & 1) { + this->field_0x44 = 4; + } +} + +void sub_08022174(Entity* this) { + sub_0800445C(this); + if (--this->actionDelay == 0) { + this->action = 5; + InitializeAnimation(this, this->entityType.parameter + 8); + } +} + +void sub_08022198(Entity* this) { + sub_0800445C(this); + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 1; + this->actionDelay = 0x5a; + } +} + +void sub_080221C0(Entity* this) { + u32 tile = COORD_TO_TILE(this) + gUnk_080B4488[this->entityType.parameter]; + this->field_0x7c.HALF.HI = tile; + this->field_0x7c.HALF.LO = sub_080001DA(tile, this->collisionLayer); + SetTile(gUnk_080CB79C[this->entityType.parameter], tile, this->collisionLayer); +} + +// clang-format off +void (*const gUnk_080CB734[])(Entity*) = { + sub_08021FDC, + sub_08021FF4, + sub_08001324, + sub_08022004, + sub_08001242, + sub_08021FDC, +}; + +void (*const gUnk_080CB74C[])(Entity*) = { + sub_08022034, + sub_0802209C, + sub_080220D8, + sub_080220F0, + sub_08022174, + sub_08022198, +}; + +const s8 gUnk_080CB764[] = { + -0x08, 0x00, + -0x10, -0x08, + -0x08, -0x10, + 0x00, -0x08, +}; + +const PosOffset gUnk_080CB76C[][6] = { + { + {-0x04, 0x1a}, + { 0x04, 0x1a}, + {-0x0c, 0x10}, + { 0x0c, 0x10}, + {-0x0c, 0x08}, + { 0x0c, 0x08}, + }, + { + {-0x1a, -0x04}, + {-0x1a, 0x04}, + {-0x10, -0x0c}, + {-0x10, 0x0c}, + {-0x08, -0x0c}, + {-0x08, 0x0c}, + }, + { + {-0x04, -0x1a}, + { 0x04, -0x1a}, + {-0x0c, -0x10}, + { 0x0c, -0x10}, + {-0x0c, -0x08}, + { 0x0c, -0x08}, + }, + { + { 0x1a, -0x04}, + { 0x1a, 0x04}, + { 0x10, -0x0c}, + { 0x10, 0x0c}, + { 0x08, -0x0c}, + { 0x08, 0x0c}, + }, +}; + +const u16 gUnk_080CB79C[] = { + 0x4023, + 0x4025, + 0x4026, + 0x4024, +}; + + +const BoundingBox gUnk_080CB7A4 = { 0x00, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x08, 0x06 }; +const BoundingBox gUnk_080CB7AC = { 0x00, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04 }; +const BoundingBox gUnk_080CB7B4 = { 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04 }; +const BoundingBox gUnk_080CB7BC = { 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08 }; +const BoundingBox gUnk_080CB7C4 = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0c }; +const BoundingBox gUnk_080CB7CC = { 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08 }; +const BoundingBox gUnk_080CB7D4 = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04 }; +const BoundingBox gUnk_080CB7DC = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04 }; +const BoundingBox gUnk_080CB7E4 = { 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08 }; +const BoundingBox gUnk_080CB7EC = { 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0c }; + +const BoundingBox *const gUnk_080CB7F4[] = { + &gUnk_080CB7A4, + &gUnk_080CB7AC, + &gUnk_080CB7B4, + &gUnk_080CB7BC, + &gUnk_080CB7C4, + &gUnk_080CB7C4, + &gUnk_080CB7CC, + &gUnk_080CB7D4, + &gUnk_080CB7DC, + &gUnk_080CB7E4, + &gUnk_080CB7EC, + &gUnk_080CB7EC, +}; + +const BoundingBox gUnk_080CB824 = { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08 }; +const BoundingBox gUnk_080CB82C = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08 }; +const BoundingBox gUnk_080CB834 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08 }; +const BoundingBox gUnk_080CB83C = { 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08 }; +const BoundingBox gUnk_080CB844 = { 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x08 }; +const BoundingBox gUnk_080CB84C = { 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08 }; +const BoundingBox gUnk_080CB854 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08 }; +const BoundingBox gUnk_080CB85C = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08 }; +const BoundingBox gUnk_080CB864 = { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08 }; +const BoundingBox gUnk_080CB86C = { 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x08 }; + +const BoundingBox *const gUnk_080CB874[] = { + &gUnk_080CB84C, + &gUnk_080CB854, + &gUnk_080CB85C, + &gUnk_080CB864, + &gUnk_080CB86C, + &gUnk_080CB86C, + &gUnk_080CB824, + &gUnk_080CB82C, + &gUnk_080CB834, + &gUnk_080CB83C, + &gUnk_080CB844, + &gUnk_080CB844, +}; + +const BoundingBox *const *const gUnk_080CB8A4[] = { + gUnk_080CB7F4, + gUnk_080CB874, + gUnk_080CB7F4, + gUnk_080CB874, +}; +// clang-format on diff --git a/src/enemy/enemy4D.c b/src/enemy/enemy4D.c new file mode 100644 index 00000000..3c168052 --- /dev/null +++ b/src/enemy/enemy4D.c @@ -0,0 +1,55 @@ +#include "global.h" +#include "entity.h" +#include "enemy.h" +#include "functions.h" + +extern void sub_0803EE8C(Entity*); + +extern void (*const gUnk_080D0880[])(Entity*); +extern void (*const gUnk_080D0898[])(Entity*); + +void Enemy4D(Entity* this) { + EnemyFunctionHandler(this, gUnk_080D0880); +} + +void sub_0803EAFC(Entity* this) { + gUnk_080D0898[this->action](this); +} + +void sub_0803EB14(Entity* this) { + sub_0804AA30(this, gUnk_080D0880); +} + +void sub_0803EB24(Entity* this) { + sub_08001324(this); + sub_0803EAFC(this); +} + +void sub_0803EB34(Entity* this) { + CreateDeathFx(this, 0xff, 0x57); +} + +void nullsub_21() { +} + +void sub_0803EB44(Entity* this) { + Entity* pEVar1; + + sub_0804A720(this); + pEVar1 = sub_0804A98C(this, 0x19, 0); + if (pEVar1 != NULL) { + pEVar1->parent = this; + this->attachedEntity = pEVar1; + this->flags |= 0x80; + this->spriteSettings.b.draw = TRUE; + this->animationState = 2; + *((u8*)&this->field_0x7a + 1) = 0; + *(u8*)&this->field_0x7c = 0; + *((u8*)&this->field_0x7c + 2) = 0x28; + *((u8*)&this->field_0x7c + 3) = 0xfe; + this->field_0x80.HWORD = this->x.HALF.HI; + this->field_0x82.HWORD = this->y.HALF.HI; + InitAnimationForceUpdate(this, this->animationState << 2); + sub_0803EE8C(this); + } +}
\ No newline at end of file diff --git a/src/enemy/enemyE.c b/src/enemy/enemyE.c new file mode 100644 index 00000000..9f6a0b6d --- /dev/null +++ b/src/enemy/enemyE.c @@ -0,0 +1,69 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +void sub_08023000(Entity*, int); + +extern void (*const gUnk_080CBBC8[])(Entity*); +extern void (*const gUnk_080CBBDC[])(Entity*); + +void EnemyE(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CBBC8); +} + +void sub_08022FB4(Entity* this) { + gUnk_080CBBDC[this->action](this); +} + +void nullsub_133(Entity* this) { +} + +void sub_08022FD0(Entity* this) { + this->action = 1; + this->spriteSettings.b.draw = 1; + sub_08023000(this, 0); +} + +void sub_08022FEC(Entity* this) { + sub_08023000(this, 0x80); +} + +void sub_08022FF8(Entity* this) { +} + +void sub_08022FFC(Entity* this) { +} + +void sub_08023000(Entity* this, int frames) { + int tmp; + + if (frames == 0x80) { + UpdateAnimationSingleFrame(this); + } else { + InitAnimationForceUpdate(this, frames); + } + + tmp = 0x80; + if (this->frameSpriteSettings == 0x40) + tmp *= -1; + + this->spriteRendering.b0 = 3; + sub_0805EC9C(this, tmp, 0x80, 0); +} + +// clang-format off +void (*const gUnk_080CBBC8[])(Entity*) = { + sub_08022FB4, + nullsub_133, + sub_08001324, + sub_0804A7D4, + sub_08001242, +}; + +void (*const gUnk_080CBBDC[])(Entity*) = { + sub_08022FD0, + sub_08022FEC, + sub_08022FF8, + sub_08022FFC, +}; +// clang-format on diff --git a/src/enemy/fallingBoulder.c b/src/enemy/fallingBoulder.c new file mode 100644 index 00000000..435e6b21 --- /dev/null +++ b/src/enemy/fallingBoulder.c @@ -0,0 +1,254 @@ +#include "enemy.h" +#include "functions.h" + +void sub_0802C4B0(Entity*); +void sub_0802C62C(Entity*); + +extern void (*const gUnk_080CD540[])(Entity*); +extern void (*const gUnk_080CD558[])(Entity*); +extern const u16 gUnk_080CD568[]; +extern const u8 gUnk_080CD580[]; +extern const s16 gUnk_080CD58C[]; + +void FallingBoulder(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CD540); +} + +void sub_0802C238(Entity* this) { + gUnk_080CD558[this->action](this); +} + +void sub_0802C250(Entity* this) { + /* ... */ +} + +void sub_0802C254(Entity* this) { + /* ... */ +} + +void sub_0802C258(Entity* this) { + sub_0804A720(this); + this->field_0x20 = 0x20000; + this->actionDelay = 2; + this->field_0x7a.HWORD = Random() & 0x70; + switch (this->entityType.form) { + case 1: + this->field_0x7a.HWORD |= 0x100; + break; + case 2: + this->field_0x7a.HWORD |= 0x200; + break; + } + this->field_0x80.HWORD = this->x.HALF.HI; + this->field_0x82.HWORD = this->y.HALF.HI; + this->height.HALF.HI = -0x10; + this->collisionLayer = 3; + this->spriteRendering.b3 = 1; + this->spritePriority.b0 = 2; + this->field_0x7c.HALF.LO = 0; + this->field_0x7c.HALF.HI = COORD_TO_TILE(this); + sub_0802C62C(this); + sub_0802C4B0(this); +} + +void sub_0802C318(Entity* this) { + if (--this->field_0x7a.HWORD == 0) { + this->action = 2; + } +} + +#if NON_MATCHING +void sub_0802C334(Entity* this) { + if ((u16)this->field_0x7c.HALF.LO == 0) { + u32 tmp = gRoomControls.roomOriginY; + if (&gPlayerEntity == NULL) + return; + if (tmp - gPlayerEntity.y.HALF.HI <= 0x38) { + return; + } + this->field_0x7c.HALF.LO = 1; + this->spriteSettings.b.draw = 1; + } + GetNextFrame(this); + this->field_0x7c.HALF.HI = COORD_TO_TILE(this); + if (sub_080044EC(this, *(u32*)&this->cutsceneBeh) == 1) { + EnqueueSFX(0x14c); + this->flags = this->flags | 0x80; + this->field_0x7a.HWORD = 0xc; + sub_0802C4B0(this); + } else { + s32 y; + + if (this->field_0x7a.HWORD) { + u16 tmp = --this->field_0x7a.HWORD; + switch (tmp) { + case 0: + this->flags &= ~0x80; + break; + case 8: + if (this->entityType.parameter != 0 && !sub_08049FA0(this)) { + u32 diff = 0; + s32 i; + for (i = 1; i > -1; i--) { + Entity* ent = CreateFx(this, 0x15, 0); + if (ent) { + ent->x.HALF.HI += 12; + ent->x.HALF.HI -= diff; + } + diff += 0x18; + } + sub_0802C62C(this); + this->field_0x7a.HWORD = Random() & 0xff | 0x100; + return; + } + break; + } + } + + y = gRoomControls.roomOriginY + gRoomControls.height - this->y.HALF.HI; + if (y >= 5) { + sub_080AEFB4(this); + } else { + sub_0806F69C(this); + if (this->height.HALF.HI - y > 0x38) { + sub_0802C62C(this); + this->field_0x7a.HWORD = (Random() & 0x7f) | 0x80; + if (this->entityType.form == 3) { + this->action = 3; + } + } + } + } + this->collisionLayer = 3; + this->spritePriority.b0 = 1; + UpdateSpriteForCollisionLayer(this); +} +#else +NAKED +void sub_0802C334(Entity* this) { + asm(".include \"asm/non_matching/fallingBoulder/sub_0802C334.inc\""); +} +#endif + +void nullsub_148(Entity* this) { + /* ... */ +} + +extern u32 sub_080001DA(u32, u32); + +void sub_0802C4B0(Entity* this) { + u32 offset; + u32 index; + u32 rand; + + switch (sub_080001DA(this->field_0x7c.HALF_U.HI, this->collisionLayer)) { + case 0x1ab ... 0x1af: + offset = 8; + break; + case 0x1c4: + offset = 4; + break; + default: + offset = 0; + break; + } + + rand = Random() & 7; + if (rand & 4) { + if (rand & 3) { + this->nonPlanarMovement = gUnk_080CD568[offset | 2]; + } else { + this->nonPlanarMovement = gUnk_080CD568[offset | 0]; + } + } else { + if (rand & 3) { + this->nonPlanarMovement = gUnk_080CD568[offset | 1]; + } else { + this->nonPlanarMovement = gUnk_080CD568[offset | 3]; + } + } + + rand = Random() & 7; + if (rand & 4) { + if (this->actionDelay != 0) { + this->actionDelay = 0; + InitializeAnimation(this, 0); + } + if (rand & 3) { + this->direction = gUnk_080CD580[offset | 1]; + } else { + this->direction = gUnk_080CD580[offset | 0]; + } + } else { + if (this->actionDelay != 1) { + this->actionDelay = 1; + InitializeAnimation(this, 1); + } + if (rand & 3) { + this->direction = gUnk_080CD580[offset | 2]; + } else { + this->direction = gUnk_080CD580[offset | 3]; + } + } + + rand = Random() & 7; + this->field_0x20 = 0x20000; + if (rand & 4) { + if (rand & 3) { + *(u32*)&this->cutsceneBeh = gUnk_080CD58C[offset | 1]; + } else { + *(u32*)&this->cutsceneBeh = gUnk_080CD58C[offset | 3]; + } + } else { + if (rand & 3) { + *(u32*)&this->cutsceneBeh = gUnk_080CD58C[offset | 2]; + } else { + *(u32*)&this->cutsceneBeh = gUnk_080CD58C[offset | 0]; + } + } +} + +void sub_0802C62C(Entity *this) { + this->action = 1; + this->y.HALF.HI = this->field_0x82.HWORD; + this->x.HALF.HI = this->field_0x80.HWORD; + this->spriteSettings.b.draw = 0; + this->flags &= ~0x80; + this->field_0x7c.HALF.LO = 0; +} + +// clang-format off +void (*const gUnk_080CD540[])(Entity*) = { + sub_0802C238, + sub_0802C250, + sub_08001324, + sub_0804A7D4, + sub_08001242, + sub_0802C254, +}; + +void (*const gUnk_080CD558[])(Entity*) = { + sub_0802C258, + sub_0802C318, + sub_0802C334, + nullsub_148, +}; + +const u16 gUnk_080CD568[] = { + 0x80, 0x100, 0x180, 0x200, + 0x80, 0x100, 0x180, 0x200, + 0x100, 0x200, 0x300, 0x400, +}; + +const u8 gUnk_080CD580[] = { + 10, 14, 18, 22, + 10, 14, 18, 22, + 10, 14, 18, 22, +}; + +const s16 gUnk_080CD58C[] = { + 0x1800, 0x2000, 0x2800, 0x3000, + 0x1800, 0x2000, 0x2800, 0x3000, + 0x1800, 0x2000, 0x2800, 0x3000, +}; +// clang-format on diff --git a/src/enemy/fireballGuy.c b/src/enemy/fireballGuy.c new file mode 100644 index 00000000..bd033058 --- /dev/null +++ b/src/enemy/fireballGuy.c @@ -0,0 +1,121 @@ +#include "global.h" +#include "entity.h" +#include "functions.h" + +typedef struct { + s8 h, v; +} PACKED PosOffset; + +extern void sub_08045524(Entity*); +void sub_08045178(Entity*, Entity*, int, int); + +extern void (*const gUnk_080D17E8[])(Entity*); +extern void (*const gUnk_080D1800[])(Entity*); +extern u8 gUnk_080D180C[4]; // Entity count per form +extern PosOffset gUnk_080D1810[4]; + +extern u8 gEntCount; + +void FireballGuy(Entity* this) { + EnemyFunctionHandler(this, gUnk_080D17E8); +} + +void sub_080453A4(Entity* this) { + gUnk_080D1800[this->action](this); +} + +void sub_080453BC(Entity* this) { + if (this->currentHealth && this->cutsceneBeh.HALF.LO != this->currentHealth) { + this->action = 2; + } else { + sub_0804AA30(this, gUnk_080D17E8); + } +} + +void nullsub_172(void) { +} + +void sub_080453E8(Entity* this) { + this->action = 1; + this->actionDelay = 0; + this->spriteSettings.b.draw = 1; + this->nonPlanarMovement = 0x80; + this->cutsceneBeh.HALF.LO = this->currentHealth; + this->field_0x3c |= 0x10; + sub_0804A720(this); + InitializeAnimation(this, 0); + sub_08045524(this); +} + +void sub_08045430(Entity* this) { + sub_080AEFE0(this); + GetNextFrame(this); + if (sub_08003FC4(this, 0x1800) == 0) + sub_08045524(this); +} + +/* Split FireballGuy into new ones */ +void sub_08045454(Entity* this) { + Entity* entities[4]; + Entity* ent; + s32 count, i; + PosOffset* off; + u32 tmp; + + /* Can we create enough new entities? */ + count = gUnk_080D180C[this->entityType.form]; + if (72 - count <= gEntCount) + return; + + /* Create 2-5 new MiniFireballGuy */ + for (i = 0; i < count; i++) + entities[i] = CreateEnemy(0x59, this->entityType.form); + + off = gUnk_080D1810; + for (i = 0; i < count; i++) { + ent = entities[i]; + ent->attachedEntity = entities[(i + 1) % count]; + ent->parent = entities[(i + count - 1) % count]; + tmp = 0; + ent->entityType.parameter = 1; + ent->height.HALF.HI = tmp; + ent->hurtBlinkTime = -0x10; + + /* Set MiniFireballGuy offset relative to killed slime. */ + sub_08045178(this, ent, off->h, off->v); + off++; + } + + ent = CreateFx(this, 2, 0); + if (ent) + CopyPosition(this, ent); + + DeleteEntity(this); +} + +u32 sub_0804A024(Entity*, u32, u32); + +void sub_08045524(Entity *this) { + u32 tmp, tmp1, tmp2; + + this->field_0x20 = 0x1c000; + tmp = sub_0804A024(this,1,8); + if (tmp != 0xff && (Random() & 3) == 0) { + this->actionDelay = Random() & 3; + this->direction = DirectionRound(tmp); + } else { + if (this->actionDelay) { + this->actionDelay--; + return; + } + this->actionDelay = Random() & 3; + if (sub_08049FA0(this) == 0 && (Random() & 3)) { + tmp1 = sub_08049EE4(this); + tmp2 = Random() & 8; + tmp2 += 0xfc; + this->direction = DirectionRound(tmp1 + tmp2); + } else { + this->direction = DirectionRound(Random()); + } + } +} diff --git a/src/enemy/hangingSeed.c b/src/enemy/hangingSeed.c index fbdcdb0b..f819287f 100644 --- a/src/enemy/hangingSeed.c +++ b/src/enemy/hangingSeed.c @@ -1,39 +1,53 @@ -#include "global.h" #include "entity.h" +#include "functions.h" -extern void EnemyFunctionHandler(Entity*, void (*const funcs[])(Entity*)); -extern void DeleteThisEntity(); - -extern void (*const gUnk_080CB570[])(Entity*); +extern void (*const gHangingSeedFunctions[])(Entity*); extern void (*const gUnk_080CB588[])(Entity*); -void HangingSeed(Entity *this) -{ - EnemyFunctionHandler(this, gUnk_080CB570); +void HangingSeed(Entity* this) { + EnemyFunctionHandler(this, gHangingSeedFunctions); } -void sub_080216E4(Entity *this) -{ - gUnk_080CB588[this->action](this); +void HangingSeed_OnTick(Entity* this) { + gUnk_080CB588[this->action](this); } -void sub_080216FC(Entity *this) -{ - if ((this->bitfield & 0x80) != 0) { - CreateFx(this, 3, 0x80); - DeleteThisEntity(); - } +void sub_080216FC(Entity* this) { + if (this->bitfield & 0x80) { + CreateFx(this, 3, 0x80); + DeleteThisEntity(); + } } -void nullsub_7(Entity* this){} +void nullsub_7(Entity* this) { + /* ... */ +} -void sub_08021720(Entity *this) -{ - this->action = 1; - this->spriteSettings.b.draw = 1; - this->frameIndex = (this->entityType).form; - this->spriteRendering.b3 = 1; - this->spritePriority.b0 = 3; +void HangingSeed_Initialize(Entity* this) { + this->action = 1; + this->spriteSettings.b.draw = 1; + this->frameIndex = this->entityType.form; + this->spriteRendering.b3 = 1; + this->spritePriority.b0 = 3; } -void nullsub_08(Entity* this){} +void HangingSeed_Hang(Entity* this) { + /* ... */ +} + +// clang-format off +void (*const gHangingSeedFunctions[])(Entity*) = { + HangingSeed_OnTick, + sub_080216FC, + sub_08001324, + sub_0804A7D4, + sub_08001242, + nullsub_7, +}; + +void (*const gUnk_080CB588[])(Entity*) = { + HangingSeed_Initialize, + HangingSeed_Hang, +}; +// clang-format on + diff --git a/src/enemy/helmasaur.c b/src/enemy/helmasaur.c new file mode 100644 index 00000000..645924dc --- /dev/null +++ b/src/enemy/helmasaur.c @@ -0,0 +1,436 @@ +#include "enemy.h" +#include "functions.h" + +extern void sub_08008796(Entity*, u32, u32, u32); +extern u32 sub_0804A024(Entity*, u32, u32); +extern bool32 sub_080AE4CC(Entity*, u32, u32, u32); + +extern Entity gUnk_0200D654; +extern Entity gUnk_02027EB4; + +void sub_0802C18C(Entity*); +void sub_0802C218(Entity*); +void sub_0802C1C0(Entity*); +u32 sub_0802C020(Entity*); +void sub_0802C058(Entity*, u32); +bool32 sub_0802C06C(Entity*); +void sub_08080964(u32, u32); +void sub_0802C1CC(Entity*); +bool32 sub_0802C0E8(Entity*); + +extern void (*const gUnk_080CD3E4[])(Entity*); +extern void (*const gUnk_080CD3FC[])(Entity*); +extern void (*const gUnk_080CD408[])(Entity*); +extern void (*const gUnk_080CD42C[])(Entity*); +extern void (*const gUnk_080CD438[])(Entity*); +extern void (*const gUnk_080CD450[])(Entity*); +extern const s8 gUnk_080CD45C[]; +extern const s8 gUnk_080CD464[]; + +void Helmasaur(Entity* this) { + if (this->entityType.form == 0) { + EnemyFunctionHandler(this, gUnk_080CD3E4); + SetChildOffset(this, 0, 1, -0x10); + } else { + gUnk_080CD3FC[this->action](this); + } +} + +void sub_0802BBAC(Entity* this) { + gUnk_080CD408[this->action](this); +} + +void sub_0802BBC4(Entity* this) { + if (this->damageType != 0x19) { + switch (this->bitfield & 0x7f) { + case 0: + case 2: + case 3: + if (this->action == 4) { + this->field_0x42 = 0; + sub_0802C218(this); + } + break; + } + } + if (this->field_0x43 != 0) { + sub_0804A9FC(this, 0x1c); + } + + sub_0804AA30(this, gUnk_080CD3E4); +} + +void sub_0802BC20(Entity* this) { + if (this->damageType != 0x19) { + if (sub_0806F520(this)) { + gUnk_080CD42C[this->previousActionFlag](this); + } + } else if (2 < this->previousActionFlag || sub_0806F520(this)) { + gUnk_080CD438[this->previousActionFlag](this); + } +} + +void sub_0802BC74(Entity* this) { + sub_0802C1C0(this); + this->previousActionFlag = 1; + this->field_0x1d = 60; + this->animationState = (gPlayerEntity.animationState >> 1) ^ 2; + InitializeAnimation(this, this->animationState); +} + +void sub_0802BCA0(Entity* this) { + sub_0806F4E8(this); +} + +void sub_0802BCA8(Entity* this) { + if (this->damageType != 0x19) { + Entity* ent; + + this->action = 7; + this->actionDelay = 0x5a; + this->field_0x20 = 0x18000; + this->damageType = 0x19; + this->field_0x3a = this->field_0x3a & 0xfb; + this->field_0x1c = 0x12; + ent = CreateEnemy(0x20, 1); + if (ent) { + ent->animationState = this->animationState; + CopyPosition(this, ent); + } + InitializeAnimation(this, this->animationState + 4); + } +} + +void sub_0802BCFC(Entity* this) { + this->previousActionFlag = 1; + this->field_0x1d = 60; +} + +void sub_0802BD08(Entity* this) { + sub_0806F3E4(this); +} + +void sub_0802BD10(Entity* this) { + this->flags &= ~0x80; + UpdateAnimationVariableFrames(this, 2); +} + +void nullsub_145(Entity* this) { + /* ... */ +} + +void sub_0802BD28(Entity* this) { + if (this->flags & 0x80) { + this->flags |= 0x80; + this->field_0x3a &= ~0x4; + } else { + this->currentHealth = 0; + } +} + +void sub_0802BD54(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->field_0x78.HALF.LO = Random(); + this->field_0x1d = 60; + this->field_0x78.HALF.HI = 0xff; + this->direction = DirectionRound(Random()); + this->animationState = this->direction >> 3; + InitializeAnimation(this, this->animationState); +} + +void sub_0802BD8C(Entity* this) { + if (this->actionDelay) { + this->actionDelay--; + } else { + u32 direction; + + if (sub_08049FDC(this, 1)) { + direction = sub_0804A024(this, 1, 0x10); + if (direction != 0xff && direction != this->field_0x78.HALF.HI) { + sub_0802C058(this, direction); + return; + } + } + + direction = sub_0802C020(this); + if (direction != this->direction) { + sub_0802C058(this, direction); + } + } +} + +void sub_0802BDE0(Entity* this) { + if (sub_0802C06C(this)) { + this->action = 3; + this->actionDelay = 60; + this->field_0x78.HALF.HI = 0xff; + } else { + this->action = 1; + this->actionDelay = (Random() & 0xf) + 0xf; + this->field_0x78.HALF.HI = this->direction; + } +} + +void sub_0802BE18(Entity* this) { + UpdateAnimationVariableFrames(this, 2); + if (--this->actionDelay == 0) { + this->action = 4; + this->actionDelay = 0x1e; + this->nonPlanarMovement = 0x300; + } else { + sub_0802C18C(this); + } +} + +void sub_0802BE48(Entity* this) { + if (!sub_080AEFE0(this)) { + sub_0802C218(this); + sub_08080964(8, 0); + } else { + GetNextFrame(this); + sub_0802C1CC(this); + if (sub_0802C0E8(this)) { + this->action = 5; + } + } +} + +void sub_0802BE80(Entity* this) { + this->nonPlanarMovement -= 0x20; + if (0xff < this->nonPlanarMovement) { + sub_0802C1CC(this); + } + + if (this->nonPlanarMovement > 0) { + sub_080AEFE0(this); + sub_0802C18C(this); + } else { + sub_0802C1C0(this); + this->actionDelay += 30; + } +} + +void sub_0802BEBC(Entity* this) { + this->direction ^= 0x10; + sub_080AEFE0(this); + this->direction ^= 0x10; + if (!sub_080044EC(this, 0x2000)) { + sub_0802C1C0(this); + } +} + +void sub_0802BEEC(Entity* this) { + if (this->actionDelay) { + if ((--this->actionDelay & 0x1f) == 0) { + this->animationState ^= 2; + this->direction = this->animationState << 3; + InitializeAnimation(this, this->animationState + 4); + } + } else if (!sub_08003FC4(this, 0x1c00)) { + this->action = 8; + this->actionDelay = 30; + this->nonPlanarMovement = 0x120; + } +} + +void sub_0802BF3C(Entity* this) { + ProcessMovement(this); + GetNextFrame(this); + if (--this->actionDelay == 0) { + u32 sprite; + + this->actionDelay = 30; + this->direction = sub_0802C020(this); + sprite = this->direction >> 3; + if (sprite != this->animationState) { + this->animationState = sprite; + InitializeAnimation(this, sprite + 4); + } + } +} + +void sub_0802BF78(Entity* this) { + this->action = 1; + this->flags2 = 4; + this->field_0x1c = 1; + this->direction = this->animationState << 3; + InitializeAnimation(this, this->animationState + 8); +} + +void sub_0802BF98(Entity* this) { + if (sub_0806F520(this)) { + gUnk_080CD450[this->previousActionFlag](this); + } else { + this->action = 2; + this->actionDelay = 30; + this->flags &= ~0x80; + } +} + +void sub_0802BFD0(Entity* this) { + this->previousActionFlag = 2; +} + +void sub_0802BFD8(Entity* this) { + sub_0806F4E8(this); +} + +void sub_0802BFE0(Entity* this) { + if (sub_0806F3E4(this)) { + DeleteEntity(this); + } +} + +void sub_0802BFF4(Entity* this) { + this->spriteSettings.b.draw ^= 1; + if (--this->actionDelay == 0) { + DeleteEntity(this); + } +} + +u32 sub_0802C020(Entity* this) { + u32 uVar1 = Random(); + + if (sub_08049FA0(this) || (uVar1 & 1)) + return DirectionRound(uVar1); + + return (sub_08049EE4(this) + (uVar1 >> 0x10 & 1) * 4) & 0x18; +} + +void sub_0802C058(Entity* this, u32 param_2) { + this->action = 2; + this->direction = param_2; + this->animationState = param_2 >> 3; + InitializeAnimation(this, this->animationState); +} + +bool32 sub_0802C06C(Entity* this) { + u32 x = this->x.HALF.HI + (s8)this->boundingBox->unknown[0]; + u32 y = this->y.HALF.HI + (s8)this->boundingBox->unknown[1]; + u32 xdiff = gUnk_080CD45C[(this->direction >> 2) + 0]; + u32 ydiff = gUnk_080CD45C[(this->direction >> 2) + 1]; + + Entity* ent = this->collisionLayer == 2 ? &gUnk_0200D654 : &gUnk_02027EB4; + + u32 i; + for (i = 0; i < 8; i++) { + x += xdiff; + y += ydiff; + if (sub_080AE4CC(ent, x, y, 0)) + return FALSE; + } + + return TRUE; +} + +bool32 sub_0806FC24(u32, u32); + +bool32 sub_0802C0E8(Entity* this) { + if (--this->actionDelay == 0) { + return TRUE; + } else { + const s8* ptr = &gUnk_080CD45C[this->direction >> 2]; + s32 x = this->x.HALF.HI + (s8)this->boundingBox->unknown[0] + ptr[0] * 6; + s32 y = this->y.HALF.HI + (s8)this->boundingBox->unknown[1] + ptr[1] * 6; + + Entity* ent = this->collisionLayer == 2 ? &gUnk_0200D654 : &gUnk_02027EB4; + u32 ret = FALSE; + if (!sub_0806FC24(TILE(x, y), 9)) { + u32 tmp = sub_080AE4CC(ent, x, y, 0); + ret = (-tmp | tmp) >> 0x1f; + } + return ret; + } +} + +void sub_0802C18C(Entity* this) { + this->field_0x78.HALF.LO--; + if ((this->field_0x78.HALF.LO & 7) == 0) { + Entity* ent = CreateObject(0xf, 0x11, 0x40); + if (ent) { + PositionRelative(this, ent, 0, 0x10000); + } + } +} + +void sub_0802C1C0(Entity* this) { + this->action = 1; + this->actionDelay = 30; +} + +void sub_0802C1CC(Entity* this) { + const s8* ptr = &gUnk_080CD464[this->animationState << 2]; + sub_08008796(this, 9, this->x.HALF.HI + ptr[0], this->y.HALF.HI + ptr[1]); + sub_08008796(this, 9, this->x.HALF.HI + ptr[2], this->y.HALF.HI + ptr[3]); +} + +void sub_0802C218(Entity* this) { + this->action = 6; + this->nonPlanarMovement = 0xe0; + this->field_0x20 = 0x18000; +} + +// clang-format off +void (*const gUnk_080CD3E4[])(Entity*) = { + sub_0802BBAC, + sub_0802BBC4, + sub_08001324, + sub_0804A7D4, + sub_08001242, + sub_0802BC20, +}; + +void (*const gUnk_080CD3FC[])(Entity*) = { + sub_0802BF78, + sub_0802BF98, + sub_0802BFF4, +}; + +void (*const gUnk_080CD408[])(Entity*) = { + sub_0802BD54, + sub_0802BD8C, + sub_0802BDE0, + sub_0802BE18, + sub_0802BE48, + sub_0802BE80, + sub_0802BEBC, + sub_0802BEEC, + sub_0802BF3C, +}; + +void (*const gUnk_080CD42C[])(Entity*) = { + sub_0802BC74, + sub_0802BCA0, + sub_0802BCA8, +}; + +void (*const gUnk_080CD438[])(Entity*) = { + sub_0802BCFC, + sub_0802BCA0, + sub_0802BD08, + sub_0802BD10, + nullsub_145, + sub_0802BD28, +}; + +void (*const gUnk_080CD450[])(Entity*) = { + sub_0802BFD0, + sub_0802BFD8, + sub_0802BFE0, +}; + +const s8 gUnk_080CD45C[] = { + 0, -8, + 8, 0, + 0, 8, + -8, 0, +}; + +const s8 gUnk_080CD464[] = { + -3, -8, 3, -8, + 8, -3, 8, 3, + -3, 8, 3, 8, + -8, -3, -8, 3, +}; +// clang-format on diff --git a/src/enemy/keaton.c b/src/enemy/keaton.c index 94c2ab33..4d7e003d 100644 --- a/src/enemy/keaton.c +++ b/src/enemy/keaton.c @@ -34,12 +34,11 @@ void sub_080323DC(Entity* this) { void sub_080323F4(Entity* this) { u32 var; - if ((u8)(this->action - 3) >= 2) { + if (this->action != 3 && this->action != 4) { this->action = 3; this->actionDelay = 0xC; - var = ((this->field_0x3e + 4) & 0x18) ^ 0x10; - this->direction = var; - InitAnimationForceUpdate(this, var >> 3); + this->direction = DirectionTurnAround(this->field_0x3e); + InitAnimationForceUpdate(this, this->direction >> 3); } else if (this->bitfield == 0xCC) { if (this->field_0x43 == 0) { sub_0803275C(this); @@ -69,7 +68,7 @@ void sub_0803248C(Entity* this) { if (this->actionDelay == 0) { sub_08032650(this); } - if (sub_080AEF88(this) == 0) { + if (ProcessMovement(this) == 0) { this->actionDelay = 1; } UpdateAnimationSingleFrame(this); @@ -142,10 +141,10 @@ void sub_080325C4(Entity* this) { u32 sub_080325E8(Entity* this) { if (((sub_08049FA0(this) != 0) && (sub_08049FDC(this, 1) != 0)) && (sub_080041A0(this, gUnk_020000B0, 0x68, 0x40) != 0)) { - if (((GetFacingDirection(this, gUnk_020000B0) - ((this->frames.all & 0x18)) + 2) & 0x1F) < 5) { + if (((GetFacingDirection(this, gUnk_020000B0) - (DirectionRound(this->frames.all)) + 2) & 0x1F) < 5) { this->action = 3; this->actionDelay = 0xC; - this->direction = this->frames.all & 0x18; + this->direction = DirectionRound(this->frames.all); return 1; } } @@ -158,9 +157,9 @@ void sub_08032650(Entity* this) { uVar3 = Random(); this->actionDelay = gUnk_080CE7E0[uVar3 & 0xf]; if (!((sub_08049FA0(this) == 0) && ((uVar3 >> 8 & 1) == 0))) { - this->direction = (uVar3 >> 0x10) & 0x18; + this->direction = DirectionRound(uVar3 >> 0x10); } else { - this->direction = (sub_08049EE4(this) + 4) & 0x18; + this->direction = DirectionRoundUp(sub_08049EE4(this)); } sub_0803269C(this, this->direction); } @@ -169,13 +168,13 @@ void sub_0803269C(Entity* this, u32 param_2) { u32 uVar1; if (((param_2 - 3) & 7) < 3) { - uVar1 = ((param_2 + 4) & 0x18) >> 3; + uVar1 = DirectionToAnimationState(param_2); if (((this->animationState - uVar1) & 3) > 1) { this->animationState = uVar1; InitAnimationForceUpdate(this, (this->animIndex & 0xFC) + uVar1); } } else { - uVar1 = ((param_2 + 4) & 0x18) >> 3; + uVar1 = DirectionToAnimationState(param_2); if (uVar1 != this->animationState) { this->animationState = uVar1; InitAnimationForceUpdate(this, (this->animIndex & 0xFC) + uVar1); diff --git a/src/enemy/keese.c b/src/enemy/keese.c index f8ad42cc..d73475f3 100644 --- a/src/enemy/keese.c +++ b/src/enemy/keese.c @@ -2,155 +2,172 @@ #include "entity.h" #include "enemy.h" #include "player.h" +#include "functions.h" -extern void sub_0804AA30(Entity*, void *); +extern void sub_08001328(Entity*); extern u32 sub_0806F520(Entity*); extern void sub_0806F4E8(Entity*); extern u32 sub_0806F3E4(Entity*); extern void sub_0804A7D4(Entity*); extern void sub_0804A720(Entity*); -extern u32 Random(); -extern void sub_08021EF0(Entity*); +extern void Keese_StartFly(Entity*); extern void sub_080AEFB4(Entity*); extern void sub_08021F24(Entity*); extern u32 sub_0806FCB8(Entity*, s32, s32, u32); extern u32 sub_08049FA0(Entity*); extern u32 sub_08049EE4(Entity*); -extern void (*gUnk_080CB69C[])(Entity*); -extern void (*gUnk_080CB6B4[])(Entity*); -extern void (*gUnk_080CB6C4[])(Entity*); +extern void (*const gKeeseFunctions[])(Entity*); +extern void (*const gKeeseActions[])(Entity*); +extern void (*const gUnk_080CB6C4[])(Entity*); -extern u8 gUnk_080CB6D0[]; -extern u16 gUnk_080CB6D6[]; -extern u8 gUnk_080CB6F6[]; +extern const s8 gKeeseSpriteOffsets[]; +extern const u16 gKeeseFlyDurations[]; +extern const u8 gKeeseRestDurations[]; -void Keese(Entity *this) -{ - gUnk_080CB69C[GetNextFunction(this)](this); +enum { + KeeseAnimation_Fly, + KeeseAnimation_Rest, +}; + +void Keese(Entity* this) { + gKeeseFunctions[GetNextFunction(this)](this); } -void sub_08021D80(Entity *this) -{ - gUnk_080CB6B4[this->action](this); +void Keese_OnTick(Entity* this) { + gKeeseActions[this->action](this); } -void sub_08021d98(Entity *this) -{ - sub_0804AA30(this, &gUnk_080CB69C); +void sub_08021d98(Entity* this) { + sub_0804AA30(this, gKeeseFunctions); } -void sub_08021DA8(Entity *this) -{ - if (sub_0806F520(this)) { - gUnk_080CB6C4[this->previousActionFlag](this); - } +void sub_08021DA8(Entity* this) { + if (sub_0806F520(this)) { + gUnk_080CB6C4[this->previousActionFlag](this); + } } -void sub_08021DCC(Entity *this) -{ - this->previousActionFlag = 2; +void sub_08021DCC(Entity* this) { + this->previousActionFlag = 2; } -void sub_08021DD4(Entity *this) -{ - sub_0806F4E8(this); +void sub_08021DD4(Entity* this) { + sub_0806F4E8(this); } -void sub_08021DDC(Entity *this) -{ - if (sub_0806F3E4(this)) { - sub_0804A7D4(this); - } +void sub_08021DDC(Entity* this) { + if (sub_0806F3E4(this)) { + sub_0804A7D4(this); + } } -void sub_08021DF0(Entity *this) -{ - - sub_0804A720(this); - if ((this->entityType).form != 0) { - this->spritePriority.b1 = 1; - this->height.HALF.HI = -0x10; - } - this->direction = Random() & 0x1f; - this->field_0x1c = 1; - this->spritePriority.b0 = 3; - this->collisionLayer = 3; - UpdateSpriteForCollisionLayer(this); - sub_08021EF0(this); +void Keese_Initialize(Entity* this) { + sub_0804A720(this); + if (this->entityType.form != 0) { + this->spritePriority.b1 = 1; + this->height.HALF.HI = -0x10; + } + this->direction = Random() & 0x1f; + this->field_0x1c = 1; + this->spritePriority.b0 = 3; + this->collisionLayer = 3; + UpdateSpriteForCollisionLayer(this); + Keese_StartFly(this); } -void sub_08021E4C(Entity *this) -{ - if (this->field_0x78.HWORD != 0) { - this->field_0x78.HWORD--; - } - if (this->field_0x7a.HWORD != 0) { - (this->field_0x7a.HWORD)--; - } - GetNextFrame(this); - if ((this->frames.b.f3) != 0) { - sub_08021F24(this); - } - else { - sub_080AEFB4(this); - } - this->spriteOffsetY = gUnk_080CB6D0[this->frames.all]; +void Keese_Fly(Entity* this) { + if (this->field_0x78.HWORD != 0) { + this->field_0x78.HWORD--; + } + if (this->field_0x7a.HWORD != 0) { + this->field_0x7a.HWORD--; + } + GetNextFrame(this); + if ((this->frames.b.f3) != 0) { + sub_08021F24(this); + } else { + sub_080AEFB4(this); + } + this->spriteOffsetY = gKeeseSpriteOffsets[this->frames.all]; } -void sub_08021EA4(Entity *this) -{ - if (--this->actionDelay == 0) { - sub_08021EF0(this); - } +void Keese_Rest(Entity* this) { + if (--this->actionDelay == 0) { + Keese_StartFly(this); + } } -void sub_08021EBC(Entity *this) -{ - s32 iVar1; - +void Keese_Sleep(Entity* this) { if (this->actionDelay != 0) { this->actionDelay--; - } - else { - iVar1 = sub_0806FCB8(this, gPlayerEntity.x.HALF.HI, gPlayerEntity.y.HALF.HI, 0x70); - if (iVar1 != 0) { - sub_08021EF0(this); - } + } else { + if (sub_0806FCB8(this, gPlayerEntity.x.HALF.HI, gPlayerEntity.y.HALF.HI, 0x70)) + Keese_StartFly(this); } } -void sub_08021EF0(Entity *this) -{ - u32 uVar1; - - this->action = 1; - this->field_0x78.HWORD = gUnk_080CB6D6[Random() & 0xf]; - this->field_0x7a.HWORD = 0x3c; - InitializeAnimation(this, 0); +void Keese_StartFly(Entity* this) { + this->action = 1; + this->field_0x78.HWORD = gKeeseFlyDurations[Random() & 0xf]; + this->field_0x7a.HWORD = 60; + InitializeAnimation(this, KeeseAnimation_Fly); } -void sub_08021F24(Entity *this) -{ - u32 bVar1; - +void sub_08021F24(Entity* this) { if (this->field_0x78.HWORD == 0) { this->action = 2; - this->actionDelay = gUnk_080CB6F6[Random() & 0xf]; - InitializeAnimation(this, 1); - } - else if (!this->field_0x7a.HWORD && !(sub_0806FCB8(this, gPlayerEntity.x.HALF.HI, gPlayerEntity.y.HALF.HI, 0x70))) { + this->actionDelay = gKeeseRestDurations[Random() & 0xf]; + InitializeAnimation(this, KeeseAnimation_Rest); + } else if (!this->field_0x7a.HWORD && + !(sub_0806FCB8(this, gPlayerEntity.x.HALF.HI, gPlayerEntity.y.HALF.HI, 0x70))) { this->action = 3; - this->actionDelay = 0x1e; - InitializeAnimation(this, 1); - } - else { + this->actionDelay = 30; + InitializeAnimation(this, KeeseAnimation_Rest); + } else { if (sub_08049FA0(this) != 0) { this->direction = Random() & 0x1f; - } - else { + } else { this->direction = sub_08049EE4(this); } - InitializeAnimation(this, 0); + InitializeAnimation(this, KeeseAnimation_Fly); } } + +// clang-format off +void (*const gKeeseFunctions[])(Entity*) = { + Keese_OnTick, + sub_08021d98, + sub_08001328, + sub_0804A7D4, + sub_08001242, + sub_08021DA8, +}; + +void (*const gKeeseActions[])(Entity*) = { + Keese_Initialize, + Keese_Fly, + Keese_Rest, + Keese_Sleep, +}; + +void (*const gUnk_080CB6C4[])(Entity*) = { + sub_08021DCC, + sub_08021DD4, + sub_08021DDC, +}; + +const s8 gKeeseSpriteOffsets[] = { + 1, -2, -5, -2, 1, 0, +}; + +const u16 gKeeseFlyDurations[] = { + 180, 180, 300, 300, 300, 300, 300, 300, + 480, 480, 480, 480, 480, 480, 720, 720, +}; + +const u8 gKeeseRestDurations[] = { + 30, 30, 45, 45, 45, 45, 45, 45, + 60, 60, 60, 60, 60, 60, 75, 75, +}; +// clang-format on diff --git a/src/enemy/lakitu.c b/src/enemy/lakitu.c index 1440d8eb..5225f644 100644 --- a/src/enemy/lakitu.c +++ b/src/enemy/lakitu.c @@ -5,7 +5,87 @@ #include "random.h" #include "player.h" -#include "lakitu.h" +extern void (*const LakituActionFuncs[])(Entity *); + +// Lakitu +extern void EnemyFunctionHandler(Entity *, void (*const funcs[])(Entity*)); + +// sub_0803C784 +extern void sub_0804AA30(Entity *, void (*const funcs[])(Entity *)); + +// sub_0803C820 +extern u32 sub_0806F520(Entity *); + +// sub_0803C850 +extern void sub_0806F4E8(Entity *); + +// Lakitu_Initialize +extern void sub_0804A720(Entity *); + +// Lakitu_Cloudless +extern u32 sub_08003FC4(Entity *, u32); + +// sub_0803CA4C +extern u32 sub_080041A0(Entity *, Entity *, u32, u32); + +// sub_0803CAD0 +extern u32 sub_080AEFE0(Entity *); + +// Lakitu_SpawnLightning +void PositionRelative(Entity*, Entity*, s32, s32); +extern void EnqueueSFX(u32); + +// sub_0803CC08 +extern void DeleteEntity(Entity *); + +// Part of function tables +extern void sub_08001324(Entity *); +extern void sub_0804A7D4(Entity *); +extern void sub_08001242(Entity *); + +// Used in multiple functions +extern Entity *CreateFx(Entity*, u32, u32); +extern Entity *sub_0804A98C(Entity *positionEntity, u8 subtype, u8 form); // Creates a projectile positioned at the given entity +extern void UpdateAnimationSingleFrame(Entity *); +extern void InitAnimationForceUpdate(Entity *, u32); +extern u32 sub_0806FCB8(Entity *, u32, u32, u32); +extern u32 GetFacingDirection(Entity *, Entity *); + + +// Forward references to functions in lakitu.c +extern void sub_0803CAD0(Entity *); +extern void sub_0803CBAC(Entity *); +extern void sub_0803CA84(Entity *, u32); +extern bool32 sub_0803CA4C(Entity *); +extern bool32 sub_0803CB04(Entity *); +extern void Lakitu_SpawnLightning(Entity *); +extern void sub_0803CB34(Entity *); +extern void sub_0803CC08(Entity *this); + +enum { + INIT, + HIDDEN, + END_HIDE, + IDLE, + BEGIN_HIDE, + LIGHTNING_THROW, + LIGHTNING_DELAY, + CLOUDLESS, +}; + +typedef struct { + s8 x; + s8 y; +} PACKED OffsetCoords; + +// sub_0803CC08 +extern void DeleteEntity(Entity *); + +// Variables +extern void (*const gUnk_080D0110[])(Entity *); +extern void (*const gUnk_080D0128[])(Entity *); +extern void (*const gUnk_080D0148[])(Entity *); +extern const OffsetCoords gUnk_080D0154[]; void Lakitu(Entity *this) { EnemyFunctionHandler(this, gUnk_080D0110); @@ -223,8 +303,7 @@ void sub_0803CA84(Entity *this, u32 unkParameter) { u32 altAnimState = GetFacingDirection(this, &gPlayerEntity); if (((altAnimState - 3) & 7) > 2 || ((this->animationState - (altAnimState >> 3)) & 3) > 1) { - u32 intermediate = (altAnimState + 4) & 0x18; - altAnimState = intermediate >> 3; + altAnimState = DirectionRoundUp(altAnimState) >> 3; if (altAnimState != this->animationState) { this->animationState = altAnimState; @@ -287,7 +366,7 @@ void Lakitu_SpawnLightning(Entity *this) { PositionRelative(this, lightning, offset->x << 16, offset->y << 16); - sub_08004488(0x193); + EnqueueSFX(0x193); } void sub_0803CBAC(Entity *this) { diff --git a/src/enemy/leever.c b/src/enemy/leever.c index 5c06ce5f..a71c28c0 100644 --- a/src/enemy/leever.c +++ b/src/enemy/leever.c @@ -4,31 +4,43 @@ #include "functions.h" extern void SetChildOffset(Entity*, s32, s32, s32); -extern void sub_0804A9FC(Entity*, u32); extern void sub_0804AA30(Entity*, void (*const func[])(Entity*)); extern void sub_0804A7D4(Entity*); extern Entity* CreateDeathFx(Entity*, u32, u32); extern void sub_0804A720(Entity*); -bool32 sub_0801FE68(Entity*, s32); -extern void sub_0801FED4(Entity*); extern u32 sub_080002D4(s32, s32, u32); extern u32 sub_080002BC(s32, s32, u32); extern u32 sub_08049FDC(Entity*, u32); -bool32 sub_0801FDE4(Entity*, s32, s32); -extern void (*const gUnk_080CA49C[])(Entity*); -extern void (*const gUnk_080CA4B4[])(Entity*); extern Entity* gUnk_020000B0; -extern u8 gUnk_080CA4C8[]; -extern u16 gUnk_080CA4CA[]; extern s16 gSineTable[]; + +bool32 Leever_PlayerInRange(Entity*, s32); +void Leever_Move(Entity*); + +extern void (*const gLeeverFunctions[])(Entity*); +extern void (*const gLeeverActions[])(Entity*); +extern const s8 gLeeverDrift[]; +extern const u16 gUnk_080CA4CA[]; + +enum { + LeeverAnimation_DigUp, + LeeverAnimation_DigDown, + LeeverAnimation_Attack, +}; + +enum { + LeeverForm_Red, + LeeverForm_Blue, +}; + void Leever(Entity* this) { - EnemyFunctionHandler(this, gUnk_080CA49C); + EnemyFunctionHandler(this, gLeeverFunctions); SetChildOffset(this, 0, 1, -0x10); } -void sub_0801FC28(Entity* this) { - gUnk_080CA4B4[this->action](this); +void Leever_OnTick(Entity* this) { + gLeeverActions[this->action](this); } void sub_0801FC40(Entity* this) { @@ -41,69 +53,67 @@ void sub_0801FC40(Entity* this) { sub_0804A9FC(this, 0x1c); } } - sub_0804AA30(this, gUnk_080CA49C); + sub_0804AA30(this, gLeeverFunctions); } void sub_0801FC7C(Entity* this) { - if ((this->entityType).form == 0) { + if (this->entityType.form == LeeverForm_Red) { sub_0804A7D4(this); } else { CreateDeathFx(this, 0xf1, 0); } } -void sub_0801FC9C(Entity* this) { +void Leever_Initialize(Entity* this) { sub_0804A720(this); this->action = 1; this->actionDelay = Random(); } -void sub_0801FCB0(Entity* this) { +void Leever_Idle(Entity* this) { if (--this->actionDelay == 0) { - if (sub_0801FE68(this, Random() & 0x1f) != 0) { + if (Leever_PlayerInRange(this, Random() & 0x1f)) { this->action = 2; this->spriteSettings.b.draw = TRUE; - this->direction = (GetFacingDirection(this, gUnk_020000B0) + gUnk_080CA4C8[Random() & 1]) & 0x1f; - InitializeAnimation(this, 0); + this->direction = (GetFacingDirection(this, gUnk_020000B0) + gLeeverDrift[Random() & 1]) & 0x1f; + InitializeAnimation(this, LeeverAnimation_DigUp); UpdateSpriteForCollisionLayer(this); } else { - this->actionDelay = (Random() & 0x18) + 8; + this->actionDelay = DirectionRound(Random()) + 8; } } } -void sub_0801FD2C(Entity* this) { - +void Leever_DigUp(Entity* this) { GetNextFrame(this); if (this->frames.b.f3 != 0) { this->action = 3; - if (this->entityType.form == 0) { - this->field_0x74.HWORD = 0xb4; + if (this->entityType.form == LeeverForm_Red) { + this->field_0x74.HWORD = 180; } else { - this->field_0x74.HWORD = 0x6e; + this->field_0x74.HWORD = 110; } - InitializeAnimation(this, 2); + InitializeAnimation(this, LeeverAnimation_Attack); } else if (this->frames.b.f0 != 0) { this->frames.all &= 0xfe; this->flags |= 0x80; } } -void sub_0801FD80(Entity* this) { - - sub_0801FED4(this); +void Leever_Attack(Entity* this) { + Leever_Move(this); GetNextFrame(this); if (--this->field_0x74.HWORD == 0) { this->action = 4; this->flags &= 0x7f; - InitializeAnimation(this, 1); + InitializeAnimation(this, LeeverAnimation_DigDown); } } -void sub_0801FDB4(Entity* this) { - sub_0801FED4(this); +void Leever_DigDown(Entity* this) { + Leever_Move(this); GetNextFrame(this); if ((this->frames.b.f3) != 0) { this->action = 1; @@ -114,7 +124,7 @@ void sub_0801FDB4(Entity* this) { u32 sub_0801FDE4(Entity* ent, s32 x, s32 y) { u32 uVar3; - u16* puVar4; + const u16* puVar4; if (sub_080002D4(x, y, gUnk_020000B0->collisionLayer) != 0) { return 0; @@ -132,7 +142,7 @@ u32 sub_0801FDE4(Entity* ent, s32 x, s32 y) { } } -bool32 sub_0801FE68(Entity* ent, s32 arg2) { +bool32 Leever_PlayerInRange(Entity* ent, s32 arg2) { s32 sin, cos; s32 x, y; u32 i; @@ -157,23 +167,53 @@ bool32 sub_0801FE68(Entity* ent, s32 arg2) { extern u32 sub_0800132C(Entity*, Entity*); -void sub_0801FED4(Entity* this) { - s16 sVar2; - +void Leever_Move(Entity* this) { if (sub_08049FDC(this, 1) == 0) { this->field_0x74.HWORD = 1; } - sVar2 = (this->frames.all & 0xf) * 0x20; - this->nonPlanarMovement = sVar2; - if (this->entityType.form == 0) { + + this->nonPlanarMovement = (this->frames.all & 0xf) * 0x20; + if (this->entityType.form == LeeverForm_Red) { if ((this->field_0xf++ & 0xf) == 0) { sub_08004596(this, sub_0800132C(this, gUnk_020000B0)); } } else { - this->nonPlanarMovement = sVar2 + 0x40; + this->nonPlanarMovement += 0x40; if ((this->field_0xf++ & 0x7) == 0) { sub_08004596(this, sub_0800132C(this, gUnk_020000B0)); } } - sub_080AEF88(this); + + ProcessMovement(this); } + +// clang-format off +void (*const gLeeverFunctions[])(Entity*) = { + Leever_OnTick, + sub_0801FC40, + sub_08001324, + sub_0801FC7C, + sub_08001242, + Leever_OnTick, +}; + +void (*const gLeeverActions[])(Entity*) = { + Leever_Initialize, + Leever_Idle, + Leever_DigUp, + Leever_Attack, + Leever_DigDown, +}; + +const s8 gLeeverDrift[] = { + 6, -6, +}; + +const u16 gUnk_080CA4CA[] = { + 0x000A, + 0x0009, + 0x000C, + 0x000B, + 0xFFFF, +}; +// clang-format on diff --git a/src/enemy/likeLike.c b/src/enemy/likeLike.c new file mode 100644 index 00000000..ca50374f --- /dev/null +++ b/src/enemy/likeLike.c @@ -0,0 +1,287 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" +#include "textbox.h" + +extern bool32 sub_080544B4(u32); +extern void sub_0807CAA0(u32, u32); + +void sub_0802810C(Entity*); +void sub_080281A0(Entity*); +bool32 sub_080281E0(u32); +void sub_08028224(u32); + +extern void (*const gUnk_080CC6FC[])(Entity*); +extern void (*const gUnk_080CC714[])(Entity*); + +void LikeLike(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CC6FC); + SetChildOffset(this, 0, 1, -0x10); +} + +void sub_08027D8C(Entity* this) { + gUnk_080CC714[this->action](this); +} + +void sub_08027DA4(Entity* this) { + if (this->damageType == 1) { + this->action = 3; + this->flags &= ~0x80; + this->damageType = 0x8c; + } else { + if (this->action == 7) { + sub_0802810C(this); + } else if (this->bitfield & 0x80) { + u8 tmp = this->bitfield & ~0x80; + if (!tmp) { + this->action = 7; + this->actionDelay = 0x5f; + this->field_0xf = tmp; + this->flags2 &= 0xfc; + this->field_0x82.HALF.HI = gPlayerEntity.spritePriority.b1; + } + } + } + + if (this->currentHealth == 0) { + this->actionDelay = 0x20; + } + + if (this->field_0x43) { + sub_0804A9FC(this, 0x1c); + } + + sub_0804AA30(this, gUnk_080CC6FC); +} + +void sub_08027E40(Entity* this) { + if (this->actionDelay == 2 && this->field_0x80.HALF.LO != 0xff) { + sub_0805E3A0(this, 3); + sub_08028224(this->field_0x80.HALF.LO); + } + sub_0804A7D4(this); +} + +void nullsub_139(Entity* this) { + /* ... */ +} + +void sub_08027E70(Entity* this) { + sub_0804A720(this); + + switch (this->entityType.form) { + case 0: + this->action = 3; + this->spriteSettings.b.draw = 0; + this->flags = this->flags & 0x7f; + this->actionDelay = 0; + break; + case 1: + this->action = 1; + this->spriteSettings.b.draw = 1; + this->actionDelay = 8; + InitializeAnimation(this, 1); + break; + case 2: + this->action = 1; + this->spriteSettings.b.draw = 0; + this->actionDelay = 0; + this->damageType = 1; + InitializeAnimation(this, 0); + break; + } + + this->direction = 0; + this->field_0x82.HALF.LO = 0; + this->animationState = 0; + this->field_0x82.HALF.HI = 0; + this->field_0x80.HALF.LO = 0xff; +} + +void sub_08027EFC(Entity* this) { + if (this->damageType == 1) + return; + + if (sub_08049FDC(this, 1)) { + if (!sub_08049FA0(this) && (Random() & 0x30)) { + this->direction = sub_08049EE4(this); + } else { + this->direction = this->field_0x82.HALF.LO; + } + + if (--this->actionDelay == 0) { + this->direction = sub_08049F84(this, 1); + this->field_0x82.HALF.LO = this->direction; + this->actionDelay = 8; + } + ProcessMovement(this); + GetNextFrame(this); + } else { + this->action = 6; + this->flags &= ~0x80; + InitializeAnimation(this, 2); + } +} + +void nullsub_12(Entity* this) { + /* ... */ +} + +void sub_08027F84(Entity* this) { + if (sub_08049FDC(this, 1)) { + this->action = 5; + this->spriteSettings.b.draw = 1; + InitializeAnimation(this, 0); + CreateDust(this); + } +} + +void sub_08027FB4(Entity* this) { + if (--this->actionDelay == 0) { + this->action = 1; + this->actionDelay = 1; + this->flags2 |= 1; + } + GetNextFrame(this); +} + +void sub_08027FE0(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 1) { + this->action = 1; + this->flags |= 0x80; + this->direction = sub_08049F84(this, 1); + this->actionDelay = 8; + this->spritePriority.b1 = 1; + InitializeAnimation(this, 1); + } +} + +void sub_0802802C(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 1) { + this->action = 3; + this->spriteSettings.b.draw = 0; + this->direction = 0; + this->actionDelay = 0; + CreateDust(this); + } +} + +void sub_0802805C(Entity* this) { + u8* tmp; + + UpdateAnimationVariableFrames(this, 2); + + if (sub_0807953C()) { + u32 tmp2 = Random(); + u32 tmp3 = this->field_0xf + 1; + tmp3 += (tmp2 & 1); + this->field_0xf = tmp3; + } + + if (this->field_0xf >= 0x19 || gUnk_02002A40.stats.health == 0) { + sub_0802810C(this); + } else { + ResetPlayer(); + gPlayerState.field_0x1a[0] |= 0x80; + PositionRelative(this, &gPlayerEntity, 0, 0x10000); + + tmp = GetSpriteSubEntryOffsetDataPointer((u16)this->spriteIndex, this->frameIndex); + gPlayerEntity.spriteOffsetX = tmp[0]; + gPlayerEntity.spriteOffsetY = tmp[1]; + gPlayerEntity.spritePriority.b1 = 0; + + if (--this->actionDelay == 0) { + sub_080281A0(this); + } + + if ((this->actionDelay & 3) == 0) { + EnqueueSFX(0x104); + } + } +} + +#if NON_MATCHING +void sub_0802810C(Entity* this) { + gPlayerState.jumpStatus = 0x41; + gPlayerState.field_0xa = 0; + gPlayerState.flags.all &= 0xffffffef; + gPlayerEntity.flags |= 0x80; + gPlayerEntity.field_0x20 = 0x18000; + gPlayerEntity.hurtBlinkTime = -60; + gPlayerEntity.direction = gPlayerEntity.animationState << 2; + gPlayerEntity.spritePriority.b1 = this->field_0x82.HALF.HI; + gPlayerEntity.height.HALF.HI = gPlayerEntity.spriteOffsetY; + gPlayerEntity.spriteOffsetY = 0; + this->action = 4; + this->actionDelay = 0x50; + this->field_0xf = 0; + this->flags2 |= 2; + if (this->hurtBlinkTime == 0) { + this->hurtBlinkTime = -18; + } +} +#else +NAKED +void sub_0802810C(Entity* this) { + asm(".include \"asm/non_matching/likeLike/sub_0802810C.inc\""); +} +#endif + +void sub_080281A0(Entity* this) { + this->field_0xf = 0x19; + if (sub_080281E0(0xe)) { + this->field_0x80.HALF.LO = 0xe; + TextboxNoOverlapFollow(0x578); + } else if (sub_080281E0(0xd)) { + this->field_0x80.HALF.LO = 0xd; + TextboxNoOverlapFollow(0x578); + } else { + ModHealth(-1); + } +} + +bool32 sub_080281E0(u32 param_1) { + bool32 ret = FALSE; + if (GetInventoryValue(param_1) == 1) { + if (sub_080544B4(gUnk_02002A40.stats.itemOnA)) { + gUnk_02002A40.stats.itemOnA = 0; + } + + if (sub_080544B4(gUnk_02002A40.stats.itemOnB)) { + gUnk_02002A40.stats.itemOnB = 0; + } + + sub_0807CAA0(param_1, 0); + ret = TRUE; + } + + return ret; +} + +void sub_08028224(u32 param_1) { + sub_080A7C18(param_1, 0, 1); + TextboxNoOverlapFollow(0x579); +} + + +void (*const gUnk_080CC6FC[])(Entity *) = { + sub_08027D8C, + sub_08027DA4, + sub_08001324, + sub_08027E40, + sub_08001242, + nullsub_139, +}; + +void (*const gUnk_080CC714[])(Entity *) = { + sub_08027E70, + sub_08027EFC, + nullsub_12, + sub_08027F84, + sub_08027FB4, + sub_08027FE0, + sub_0802802C, + sub_0802805C, +}; diff --git a/src/enemy/madderpillar.c b/src/enemy/madderpillar.c new file mode 100644 index 00000000..69f61aee --- /dev/null +++ b/src/enemy/madderpillar.c @@ -0,0 +1,582 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern u8 gEntCount; +extern BoundingBox gUnk_080FD298; +extern BoundingBox gUnk_080FD2A0; + +void sub_08029E0C(Entity*); +void sub_08029EEC(Entity*); +void sub_0802A098(Entity*); +void sub_0802A16C(Entity*); +void sub_0802A058(Entity*); +bool32 sub_0802A14C(Entity*); +void sub_0802A18C(Entity*); +bool32 sub_08029FE4(Entity*); +void sub_08029FB4(Entity*, u32, u32); +void sub_0802A0F8(Entity*); + +extern void (*const gUnk_080CCD44[])(Entity*); +extern void (*const gUnk_080CCD60[])(Entity*); +extern void (*const gUnk_080CCD78[])(Entity*); +extern void (*const gUnk_080CCD88[])(Entity*); +extern const u8 gUnk_080CCDA0[]; +extern void (*const gUnk_080CCDA8[])(Entity*); +extern const u8 gUnk_080CCDC8[]; +extern const u16 gUnk_080CCDD4[]; + +void Madderpillar(Entity* this) { + gUnk_080CCD44[this->entityType.form](this); +} + +void sub_08029870(Entity* this) { + gUnk_080CCD60[GetNextFunction(this)](this); +} + +void sub_0802988C(Entity* this) { + gUnk_080CCD78[this->action](this); +} + +void sub_080298A4(Entity* this) { + if (this->action == 1) { + switch (this->bitfield & 0x7f) { + case 0: + case 1: + case 2: + case 3: + case 0xf: + case 0x13: + case 0x1b: + case 0x1e: + break; + default: + this->action = 2; + this->actionDelay = 0; + this->damageType = 0x6b; + this->field_0x76.HALF.HI = 0; + sub_0801D2B4(this, 0x7f); + EnqueueSFX(0xfe); + this->attachedEntity->action = 2; + break; + } + } + + sub_0804AA30(this, gUnk_080CCD60); +} + +void sub_08029980(Entity* this) { + if (this->field_0xf) { + this->field_0xf--; + } else { + sub_0804A7D4(this); + } +} + +void nullsub_14(Entity* this) { + /* ... */ +} + +void sub_0802999C(Entity* this) { + if (gEntCount < 0x44) { + Entity *ent1, *ent2, *ent3, *ent4, *ent5, *ent6; + + ent1 = CreateEnemy(0x18, 1); + ent1->parent = this; + PositionRelative(this, ent1, 0, 5); + this->attachedEntity = ent1; + + ent2 = CreateEnemy(0x18, 2); + ent2->parent = this; + PositionRelative(this, ent2, 0, 4); + ent1->attachedEntity = ent2; + + ent3 = CreateEnemy(0x18, 3); + ent3->parent = this; + PositionRelative(this, ent3, 0, 3); + ent2->attachedEntity = ent3; + + ent4 = CreateEnemy(0x18, 4); + ent4->parent = this; + PositionRelative(this, ent4, 0, 2); + ent3->attachedEntity = ent4; + + ent5 = CreateEnemy(0x18, 5); + ent5->parent = this; + PositionRelative(this, ent5, 0, 1); + ent4->attachedEntity = ent5; + + ent6 = CreateEnemy(0x18, 6); + ent6->attachedEntity = this; + ent6->parent = this; + PositionRelative(this, ent6, 0, 0); + ent5->attachedEntity = ent6; + + this->action = 1; + this->flags |= 0x80; + this->direction = DirectionRound(Random()); + this->nonPlanarMovement = 0xa0; + this->animationState = 0xff; + this->y.WORD += 6; + this->parent = this; + this->field_0x74.HALF.LO = 0xff; + this->field_0x74.HALF.HI = 0; + this->field_0x76.HALF.HI = 1; + sub_08029E0C(this); + sub_08029EEC(this); + } +} + +void sub_08029A94(Entity* this) { + UpdateAnimationSingleFrame(this); + sub_0802A098(this); +} + +void sub_08029AA4(Entity* this) { + if (this->field_0x76.HALF.HI != 0) { + this->action = 3; + this->nonPlanarMovement = 0x108; + this->damageType = 0x6a; + this->field_0x7a.HWORD = 0x168; + this->field_0x74.HALF.HI = 4; + sub_08029EEC(this); + EnqueueSFX(0x19d); + } +} + +void sub_08029AE0(Entity* this) { + UpdateAnimationSingleFrame(this); + sub_0802A16C(this); + sub_0802A098(this); + if (--this->field_0x7a.HWORD == 0) { + this->action = 1; + this->nonPlanarMovement = 0xa0; + this->field_0x74.HALF.HI = 0; + sub_08029EEC(this); + sub_0801D2B4(this, 0x77); + EnqueueSFX(0x182); + } +} + +void sub_08029B2C(Entity* this) { + if (sub_0802A14C(this)) { + if (this->field_0x86.HALF.LO) { + if (--this->actionDelay == 0) { + CreateFx(this, 0x48, 0); + DeleteEntity(this); + } + } else { + this->flags &= ~0x80; + this->actionDelay = -(this->entityType.form * 15 - 90); + this->field_0x86.HALF.LO = 1; + } + } else { + gUnk_080CCD88[this->action](this); + } +} + +void sub_08029B90(Entity* this) { + this->action = 1; + this->spriteSettings.b.draw = 1; + sub_0802A058(this); + if (this->entityType.form < 2) { + InitializeAnimation(this, 0); + } else { + InitializeAnimation(this, 4); + } +} + +void sub_08029BC4(Entity* this) { + u32 uVar1; + u32 uVar2; + + sub_0802A18C(this); + uVar1 = this->x.HALF.HI; + uVar2 = this->y.HALF.HI; + if (sub_08029FE4(this)) { + u32 index; + if (this->entityType.form < 2) { + index = 0; + } else { + index = 4; + } + InitializeAnimation(this, this->animationState + index); + } + sub_08029FB4(this, this->x.HALF.HI - uVar1, this->y.HALF.HI - uVar2); +} + +void sub_08029C08(Entity* this) { + this->action = 3; + this->actionDelay = gUnk_080CCDA0[this->entityType.form]; + this->damageType = 0x6b; + this->attachedEntity->action = 2; +} + +void sub_08029C2C(Entity* this) { + if (--this->actionDelay == 0) { + this->action = 4; + sub_0801D2B4(this, 0x7f); + EnqueueSFX(0x6c); + } +} + +void sub_08029C50(Entity* this) { + if (this->parent->field_0x76.HALF.HI != 0) { + this->action = 5; + this->damageType = 0x6a; + } +} + +void sub_08029C6C(Entity* this) { + sub_0802A18C(this); + sub_08029BC4(this); + if (this->parent->action != 3) { + this->action = 1; + sub_0801D2B4(this, 0x77); + } else { + sub_0802A16C(this); + } +} + +void sub_08029C98(Entity* this) { + if (sub_0802A14C(this)) { + CreateFx(this, 0x48, 0); + DeleteEntity(this); + } else { + gUnk_080CCDA8[this->action](this); + } +} + +void sub_08029CCC(Entity* this) { + this->action = 1; + this->spriteSettings.b.draw = 1; + sub_0802A058(this); + InitializeAnimation(this, 8); +} + +void sub_08029CF0(Entity* this) { + if (sub_08029FE4(this)) { + InitializeAnimation(this, this->animationState + 8); + } +} + +void sub_08029D08(Entity* this) { + this->action = 3; + this->actionDelay = 0x47; +} + +void sub_08029D14(Entity* this) { + if (this->actionDelay) { + if (--this->actionDelay == 0) { + InitializeAnimation(this, this->animationState + 0xc); + sub_0801D2B4(this, 0x7f); + EnqueueSFX(0x6c); + } + } else { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 4; + this->actionDelay = 0x78; + this->damageType = 0x6c; + this->boundingBox = &gUnk_080FD298; + EnqueueSFX(0x6b); + } + } +} + +void sub_08029D78(Entity* this) { + sub_0802A0F8(this); + if (--this->actionDelay == 0) { + this->action = 5; + this->damageType = 0x6a; + this->boundingBox = (BoundingBox*)&gUnk_080FD2A0; + InitializeAnimation(this, this->animationState + 0x10); + } +} + +void sub_08029DAC(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 6; + this->parent->field_0x76.HALF.HI = 1; + InitializeAnimation(this, this->animationState + 8); + } +} + +void sub_08029DDC(Entity* this) { + this->action = 7; +} + +void sub_08029DE4(Entity* this) { + sub_08029CF0(this); + if (this->parent->action != 3) { + this->action = 1; + sub_0801D2B4(this, 0x77); + } else { + sub_0802A16C(this); + } +} + +NAKED +void sub_08029E0C(Entity* this) { + asm(".include \"asm/non_matching/madderpillar/sub_08029E0C.inc\""); +} + +void sub_08029EEC(Entity* this) { + u32 uVar1 = (this->direction >> 3) + this->field_0x74.HALF.HI; + if (uVar1 != this->animationState) { + this->animationState = uVar1; + InitAnimationForceUpdate(this, uVar1); + } +} + +void sub_08029F0C(Entity* this) { + switch (this->direction >> 3) { + case 0: + this->field_0x78.HWORD = this->y.HALF.HI - 0x10; + break; + case 1: + this->field_0x78.HWORD = this->x.HALF.HI + 0x10; + break; + case 2: + this->field_0x78.HWORD = this->y.HALF.HI + 0x10; + break; + case 3: + this->field_0x78.HWORD = this->x.HALF.HI - 0x10; + break; + } +} + +bool32 sub_08029F48(Entity* this) { + switch (this->direction >> 3) { + case 0: + if (this->y.HALF.HI <= this->field_0x78.HWORD) { + this->y.HALF.HI = this->field_0x78.HWORD; + return TRUE; + } + break; + case 1: + if (this->x.HALF.HI >= this->field_0x78.HWORD) { + this->x.HALF.HI = this->field_0x78.HWORD; + return TRUE; + } + break; + case 2: + if (this->y.HALF.HI >= this->field_0x78.HWORD) { + this->y.HALF.HI = this->field_0x78.HWORD; + return TRUE; + } + break; + case 3: + if (this->x.HALF.HI <= this->field_0x78.HWORD) { + this->x.HALF.HI = this->field_0x78.HWORD; + return TRUE; + } + break; + } + + return FALSE; +} + +void sub_08029FB4(Entity* this, u32 x, u32 y) { + u8* dst = (u8*)&this->attachedEntity->field_0x78; + s32 unk = this->parent->field_0x7c.BYTES.byte2; + u8 idx = unk % 0xe; + dst[idx] = ((x + 8) & 0xf) | (((y + 8) & 0xf) << 4); +} + +/* The optimizer is strong within you. */ +bool32 sub_08029FE4(Entity* this) { + u8 state; + u8* dst = (u8*)&this->field_0x78; + s32 unk = this->parent->field_0x7c.BYTES.byte2 + 1; + s8 iVar6 = (dst[unk % 0xe] & 0xf) - 8; + s8 iVar5 = (dst[unk % 0xe] >> 4) - 8; + this->x.HALF.HI += iVar6; + this->y.HALF.HI += iVar5; + GetNextFrame(this); + + state = 0xff; + if (iVar6 != 0) { + if (0 < iVar6) { + state = 1; + } else { + state = 3; + } + } + + if (iVar5 != 0) { + if (0 < iVar5) { + state = 2; + } else { + state = 0; + } + } + + if (state != 0xff && state != this->animationState) { + this->animationState = state; + return TRUE; + } else { + return FALSE; + } +} + +void sub_0802A058(Entity* this) { + this->field_0x78.HALF.LO = 0x88; + this->field_0x78.HALF.HI = 0x88; + this->field_0x7a.HALF.LO = 0x88; + this->field_0x7a.HALF.HI = 0x88; + this->field_0x7c.BYTES.byte0 = 0x88; + this->field_0x7c.BYTES.byte1 = 0x88; + this->field_0x7c.BYTES.byte2 = 0x88; + this->field_0x7c.BYTES.byte3 = 0x88; + this->field_0x80.HALF.LO = 0x88; + this->field_0x80.HALF.HI = 0x88; + this->field_0x82.HALF.LO = 0x88; + this->field_0x82.HALF.HI = 0x88; + this->cutsceneBeh.HALF.LO = 0x88; + this->cutsceneBeh.HALF.HI = 0x88; +} + +void sub_0802A098(Entity* this) { + u32 uVar1; + u32 uVar2; + s32 unk = (++this->field_0x7c.BYTES.byte2, this->field_0x7c.BYTES.byte2); + u8 idx = unk % 0xe; + if (idx == 0) { + this->field_0x7c.BYTES.byte2 = 0; + } + uVar1 = this->x.HALF.HI; + uVar2 = this->y.HALF.HI; + ProcessMovement(this); + if (sub_08029F48(this)) { + sub_08029E0C(this); + sub_08029EEC(this); + EnqueueSFX(0x104); + } + + sub_08029FB4(this, this->x.HALF.HI - uVar1, this->y.HALF.HI - uVar2); +} + +void sub_0802A0F8(Entity* this) { + if (this->currentHealth != 0) { + if ((this->bitfield & 0x80) && this->hurtBlinkTime != 0) { + Entity* ent = this; + u32 i; + for (i = 0; i < 6; i++) { + ent = ent->attachedEntity; + ent->hurtBlinkTime = this->hurtBlinkTime; + } + } + } else { + this->parent->flags &= ~0x80; + this->parent->currentHealth = 0; + this->parent->field_0xf = 0x69; + } +} + +bool32 sub_0802A14C(Entity* this) { + u32 ret = FALSE; + + if (this->parent->currentHealth == 0 || this->field_0x86.HALF.LO) { + ret = TRUE; + } else { + ret = FALSE; + } + return ret; +} + +void sub_0802A16C(Entity* this) { + sub_0801D2B4(this, gUnk_080CCDD4[this->parent->field_0x7a.HWORD >> 2 & 3]); +} + +void sub_0802A18C(Entity* this) { + if (this->bitfield & 0x80) { + switch (this->bitfield & 0x7f) { + case 0: + case 1: + case 2: + case 3: + case 0xf: + case 0x13: + case 0x1b: + case 0x1e: + break; + default: + EnqueueSFX(0x12e); + break; + } + } +} + +// clang-format off +void (*const gUnk_080CCD44[])(Entity*) = { + sub_08029870, + sub_08029B2C, + sub_08029B2C, + sub_08029B2C, + sub_08029B2C, + sub_08029B2C, + sub_08029C98, +}; + +void (*const gUnk_080CCD60[])(Entity*) = { + sub_0802988C, + sub_080298A4, + sub_0802988C, + sub_08029980, + sub_08001242, + nullsub_14, +}; + +void (*const gUnk_080CCD78[])(Entity*) = { + sub_0802999C, + sub_08029A94, + sub_08029AA4, + sub_08029AE0, +}; + +void (*const gUnk_080CCD88[])(Entity*) = { + sub_08029B90, + sub_08029BC4, + sub_08029C08, + sub_08029C2C, + sub_08029C50, + sub_08029C6C, +}; + +const u8 gUnk_080CCDA0[] = { + 0x00, 0x24, + 0x30, + 0x3A, + 0x41, + 0x45, + 0x00, + 0x00, +}; + +void (*const gUnk_080CCDA8[])(Entity*) = { + sub_08029CCC, + sub_08029CF0, + sub_08029D08, + sub_08029D14, + sub_08029D78, + sub_08029DAC, + sub_08029DDC, + sub_08029DE4, +}; + +const u8 gUnk_080CCDC8[] = { + 0x08, 0x00, + 0x18, 0x00, + 0x10, 0x08, + 0x10, 0x08, + 0x18, 0x00, + 0x18, 0x10, +}; + +const u16 gUnk_080CCDD4[] = { + 0x80, 0x81, + 0x82, 0x81, +}; +// clang-format on diff --git a/src/enemy/miniFireballGuy.c b/src/enemy/miniFireballGuy.c index f9e70364..d5d7b0e6 100644 --- a/src/enemy/miniFireballGuy.c +++ b/src/enemy/miniFireballGuy.c @@ -11,66 +11,59 @@ extern void sub_08045678(Entity*); extern void (*const gUnk_080D1868[])(Entity*); extern void (*const gUnk_080D1880[])(Entity*); -void MiniFireballGuy(Entity *this) -{ - EnemyFunctionHandler(this, gUnk_080D1868); +void MiniFireballGuy(Entity* this) { + EnemyFunctionHandler(this, gUnk_080D1868); } -void sub_080455BC(Entity *this) -{ - gUnk_080D1880[this->action](this); +void sub_080455BC(Entity* this) { + gUnk_080D1880[this->action](this); } -void sub_080455D4(Entity *this) -{ - sub_0804AA30(this, gUnk_080D1868); +void sub_080455D4(Entity* this) { + sub_0804AA30(this, gUnk_080D1868); } -void sub_080455E4(Entity *this) -{ - if ((this != this->parent) && (this->parent != NULL)) { - this->field_0x6c.HALF.LO &= 0x7f; - this->parent->attachedEntity = this->attachedEntity; - this->attachedEntity->parent = this->parent; - } - sub_0804A7D4(this); +void sub_080455E4(Entity* this) { + if ((this != this->parent) && (this->parent != NULL)) { + this->field_0x6c.HALF.LO &= 0x7f; + this->parent->attachedEntity = this->attachedEntity; + this->attachedEntity->parent = this->parent; + } + sub_0804A7D4(this); } -void nullsub_23(Entity* this) {} - -void sub_08045618(Entity *this) -{ - this->action = 1; - this->spriteSettings.b.draw = 1; - this->nonPlanarMovement = 0x80; - this->field_0x3c = this->field_0x3c | 0x10; - sub_0804A720(this); - InitializeAnimation(this, 1); - sub_08045678(this); +void nullsub_23(Entity* this) { } -void sub_08045654(Entity *this) -{ - sub_080AEFE0(this); - GetNextFrame(this); - if (sub_08003FC4(this, 0x1800) == 0) { +void sub_08045618(Entity* this) { + this->action = 1; + this->spriteSettings.b.draw = 1; + this->nonPlanarMovement = 0x80; + this->field_0x3c = this->field_0x3c | 0x10; + sub_0804A720(this); + InitializeAnimation(this, 1); sub_08045678(this); - } } -void sub_08045678(Entity *this) -{ - - this->field_0x20 = 0x1c000; - if (this->actionDelay != 0) { - this->actionDelay--; - } else { - this->actionDelay = Random() & 3; - if ((sub_08049FA0(this) == 0) && (Random() & 3)) { - this->direction = (sub_08049EE4(this) - 4 + (Random() & 8)) & 0x18; +void sub_08045654(Entity* this) { + sub_080AEFE0(this); + GetNextFrame(this); + if (sub_08003FC4(this, 0x1800) == 0) { + sub_08045678(this); } - else { - this->direction = Random() & 0x18; +} + +void sub_08045678(Entity* this) { + + this->field_0x20 = 0x1c000; + if (this->actionDelay != 0) { + this->actionDelay--; + } else { + this->actionDelay = Random() & 3; + if ((sub_08049FA0(this) == 0) && (Random() & 3)) { + this->direction = DirectionRound(sub_08049EE4(this) - 4 + (Random() & 8)); + } else { + this->direction = DirectionRound(Random()); + } } - } } diff --git a/src/enemy/miniSlime.c b/src/enemy/miniSlime.c new file mode 100644 index 00000000..973f8839 --- /dev/null +++ b/src/enemy/miniSlime.c @@ -0,0 +1,94 @@ +#include "global.h" +#include "entity.h" +#include "room.h" +#include "functions.h" + +void sub_08045374(Entity*); + +extern u32 sub_0806FA04(u32, u32); +extern void sub_0804A720(); +extern void sub_080452E4(); +extern void sub_0804AA30(); +extern void ReplaceMonitoredEntity(Entity*, Entity*); +extern void sub_0804A7D4(Entity*); + +extern void (*const gUnk_080D17C0[])(Entity*); +extern void (*const gUnk_080D17D8[])(Entity*); + +void MiniSlime(Entity* this) { + EnemyFunctionHandler(this, gUnk_080D17C0); + SetChildOffset(this, 0, 1, -8); +} + +void sub_08045220(Entity* this) { + gUnk_080D17D8[this->action](this); +} + +void sub_08045238(Entity* this) { + if (this->field_0x43) + sub_0804A9FC(this, 0x1c); + + sub_0804AA30(this, gUnk_080D17C0); +} + +void sub_0804525C(Entity* this) { + Entity* parent = this->parent; + if (this != parent && parent) { + this->field_0x6c.HALF.LO &= 0x7f; + this->parent->attachedEntity = this->attachedEntity; + this->attachedEntity->parent = this->parent; + if (this->field_0x6c.HALF.HI & 0x40) + ReplaceMonitoredEntity(this, parent); + } + sub_0804A7D4(this); +} + +void nullsub_22(void) { +} + +void sub_080452A4(Entity* this) { + this->action = 1; + this->spriteSettings.b.draw = 1; + this->nonPlanarMovement = 0x100; + sub_0804A720(this); + InitializeAnimation(this, 6); + if (this->entityType.parameter) { + this->action = 2; + this->actionDelay = 1; + } else { + sub_080452E4(this); + } +} + +void sub_080452E4(Entity* this) { + this->action = 2; + this->actionDelay = (Random() & 0x1f) + 1; +} + +void sub_080452FC(Entity *this) { + u32 cVar2, bVar3; + GetNextFrame(this); + if (--this->actionDelay == 0) { + this->action = 3; + this->actionDelay = 1; + if (0 < this->nonPlanarMovement) + this->actionDelay = sub_0806FA04(0x1000, this->nonPlanarMovement) >> 0x8; + + if (sub_08049FA0(this) == 0 && (Random() & 3)) { + cVar2 = sub_08049EE4(this); + bVar3 = Random() & 8; + bVar3 += 0xfc; + this->direction = DirectionRound(cVar2 + bVar3); + } else { + this->direction = DirectionRound(Random()); + sub_08045374(this); + } + } +} + +void sub_08045374(Entity* this) { + ProcessMovement(this); + GetNextFrame(this); + if (--this->actionDelay == 0) + this->action = 1; +} diff --git a/src/enemy/moldorm.c b/src/enemy/moldorm.c new file mode 100644 index 00000000..3338a15a --- /dev/null +++ b/src/enemy/moldorm.c @@ -0,0 +1,211 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +void sub_08022EAC(Entity*); +void sub_08022F14(Entity*); + +extern void (*const gUnk_080CBB90[])(Entity*); +extern void (*const gUnk_080CBBA0[])(Entity*); +extern void (*const gUnk_080CBBB4[])(Entity*); +extern void (*const gUnk_080CBBBC[])(Entity*); + +extern u8 gEntCount; +extern const s8 gUnk_080CBBC4[]; + +void Moldorm(Entity* this) { + gUnk_080CBB90[this->entityType.form](this); +} + +void sub_08022BA0(Entity* this) { + this->field_0x78.HALF.HI++; + this->field_0x74.HWORD = this->x.HALF.HI; + this->field_0x76.HWORD = this->y.HALF.HI; + EnemyFunctionHandler(this, gUnk_080CBBA0); + sub_08022EAC(this); +} + +void sub_08022BD4(Entity* this) { + gUnk_080CBBB4[this->action](this); +} + +void sub_08022BEC(Entity* this) { + if (this->field_0x7a.HALF.LO != this->currentHealth) + this->field_0x7a.HALF.HI = 30; + + this->field_0x7a.HALF.LO = this->currentHealth; + this->actionDelay = 1; + this->direction = this->field_0x3e; + + this->animationState = ((this->direction + 2) & 0x1c) >> 2; + this->frameIndex = this->animationState; + + this->attachedEntity->hurtBlinkTime = this->hurtBlinkTime; + (*(Entity**)&this->field_0x7c)->hurtBlinkTime = this->hurtBlinkTime; + (*(Entity**)&this->field_0x80)->hurtBlinkTime = this->hurtBlinkTime; + sub_0804AA30(this, gUnk_080CBBA0); +} + +void sub_08022C58(Entity* this) { + Entity *tail0, *tail1, *tail2; + + this->flags &= ~0x80; + + if (gEntCount >= 0x45) + return; + + tail0 = CreateEnemy(0xd, 1); + this->attachedEntity = tail0; + tail0->spritePriority.b0 = 5; + tail0->parent = this; + CopyPosition(this, tail0); + + tail1 = CreateEnemy(0xd, 2); + tail0->attachedEntity = tail1; + tail1->spritePriority.b0 = 5; + tail1->parent = this; + CopyPosition(this, tail1); + + tail2 = CreateEnemy(0xd, 3); + tail1->attachedEntity = tail2; + tail2->spritePriority.b0 = 5; + tail2->parent = this; + CopyPosition(this, tail2); + + sub_0804A720(this); + this->action = 1; + this->actionDelay = 1; + this->field_0xf = 1; + this->flags = this->flags | 0x80; + this->parent = this; + this->attachedEntity = tail0; + *(Entity**)&this->field_0x7c = tail1; + *(Entity**)&this->field_0x80 = tail2; + + this->direction = Random() & 0x1f; + this->animationState = ((this->direction + 2) & 0x1c) >> 2; + this->frameIndex = this->animationState; + this->field_0x7a.HALF.LO = this->currentHealth; +} + +void sub_08022D40(Entity* this) { + if (this->field_0x7a.HALF.HI) { + if (this->field_0x7a.HALF.HI-- & 1) { + this->animationState = (this->animationState + 1) & 7; + this->frameIndex = this->animationState; + } + } else { + sub_08022F14(this); + ProcessMovement(this); + + if (this->collisions) { + sub_0800417E(this, this->collisions); + this->animationState = ((this->direction + 2) & 0x1c) >> 2; + this->frameIndex = this->animationState; + } + } +} + +void sub_08022D90(Entity* this) { + if (this->parent->next) { + Entity* parent; + + gUnk_080CBBBC[this->action](this); + parent = this->parent; + this->spriteOrientation.flipY = parent->spriteOrientation.flipY; + this->spriteRendering.b3 = parent->spriteRendering.b3; + this->collisionLayer = parent->collisionLayer; + } else { + DeleteEntity(this); + } +} + +void sub_08022DE8(Entity* this) { + this->action = 1; + this->field_0x7c.BYTES.byte0 = 0x88; + this->field_0x7c.BYTES.byte1 = 0x88; + this->field_0x7c.BYTES.byte2 = 0x88; + this->field_0x7c.BYTES.byte3 = 0x88; + this->field_0x80.HALF.LO = 0x88; + this->field_0x80.HALF.HI = 0x88; + this->field_0x82.HALF.LO = 0x88; + this->field_0x82.HALF.HI = 0x88; + this->animationState = this->parent->animationState; + *(u32*)&this->cutsceneBeh = this->animationState * 0x11111111; + + if (this->entityType.form != 3) { + this->frameIndex = this->entityType.form + 7; + } else { + this->frameIndex = this->animationState + 10; + } +} + +NAKED +void sub_08022E40(Entity* this) { + asm(".include \"asm/non_matching/moldorm/sub_08022E40.inc\""); +} + +NAKED +void sub_08022EAC(Entity* this) { + asm(".include \"asm/non_matching/moldorm/sub_08022EAC.inc\""); +} + +void sub_08022F14(Entity* this) { + if (sub_08049FA0(this) == 0) { + u32 bVar6 = (sub_08049EE4(this) - this->direction) & 0x1f; + if (8 < ((bVar6 + 4) & 0x1f)) { + this->field_0xf = 8; + if (bVar6 < 0x10) { + this->field_0x78.HALF.LO = 1; + } else { + this->field_0x78.HALF.LO = -1; + } + } + } + + if (--this->actionDelay == 0) { + this->actionDelay = 4; + + if (--this->field_0xf == 0) { + this->field_0xf = 8; + this->field_0x78.HALF.LO = gUnk_080CBBC4[Random() & 1]; + } + + this->direction += this->field_0x78.HALF.LO; + this->direction &= 0x1f; + + this->animationState = ((this->direction + 2) & 0x1c) >> 2; + this->frameIndex = this->animationState; + } +} + +// clang-format off +void (*const gUnk_080CBB90[])(Entity*) = { + sub_08022BA0, + sub_08022D90, + sub_08022D90, + sub_08022D90, +}; + +void (*const gUnk_080CBBA0[])(Entity*) = { + sub_08022BD4, + sub_08022BEC, + sub_08001324, + sub_0804A7D4, + sub_08001242, +}; + +void (*const gUnk_080CBBB4[])(Entity*) = { + sub_08022C58, + sub_08022D40, +}; + +void (*const gUnk_080CBBBC[])(Entity*) = { + sub_08022DE8, + sub_08022E40, +}; + +const s8 gUnk_080CBBC4[] = { + 1, -1, 0, 0, +}; +// clang-format off diff --git a/src/enemy/moldworm.c b/src/enemy/moldworm.c new file mode 100644 index 00000000..ffa1dc94 --- /dev/null +++ b/src/enemy/moldworm.c @@ -0,0 +1,585 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern void sub_0800449C(Entity*, u32); +extern bool32 sub_08023A38(u32); +extern void sub_08023990(Entity*, u32, u32); +extern void sub_08023A88(Entity*, u32); + +void sub_080235BC(Entity*); +void sub_08023644(Entity*); +void sub_08023730(Entity*); +void sub_080237D8(Entity*); +void sub_0802390C(Entity*); +void sub_080239F0(Entity*); +bool32 sub_08023B38(Entity*); + +extern u8 gEntCount; +extern const u8 gUnk_080B37A0[]; + +extern void (*const gUnk_080CBC38[])(Entity*); +extern void (*const gUnk_080CBC50[])(Entity*); +extern const s8 gUnk_080CBC70[]; +extern const s8 gUnk_080CBC90[]; +extern void (*const gUnk_080CBC98[])(Entity*); +extern void (*const gUnk_080CBCA8[])(Entity*); +extern const s8 gUnk_080CBCB8[]; + +#if NON_MATCHING +void Moldworm(Entity* this) { + u16 prevX = this->x.HALF.HI; + u16 prevY = this->y.HALF.HI; + + if (this->entityType.form == 0) { + if (this->action != 0) { + sub_0802390C(this); + } + this->field_0x7c.BYTES.byte1 = this->field_0x7c.BYTES.byte0; + EnemyFunctionHandler(this, gUnk_080CBC38); + } else { + if (this->parent->next) { + if (this->entityType.form != 8) { + sub_080235BC(this); + } else { + sub_08023730(this); + } + } else { + DeleteEntity(this); + return; + } + } + + if (this->parent->field_0x7c.BYTES.byte0 != this->parent->field_0x7c.BYTES.byte1 && this->attachedEntity) { + ((u8*)&this->attachedEntity->field_0x78)[(this->parent->field_0x7c.BYTES.byte0 - 1) & 0xf] = + (((this->x.HALF.HI - prevX + 8) & 0xf) << 4) | ((this->y.HALF.HI - prevY + 8U) & 0xf); + } +} +#else +NAKED +void Moldworm(Entity* this) { + asm(".include \"asm/non_matching/moldworm/moldworm.inc\""); +} +#endif + +void sub_080230CC(Entity* this) { + gUnk_080CBC50[this->action](this); +} + +void sub_080230E4(Entity* this) { + if (this->previousActionFlag == 0xff) { + this->action = 7; + this->actionDelay = 1; + this->previousActionFlag = 0; + this->damageType = 0x85; + this->hurtBlinkTime = -8; + this->field_0x7c.BYTES.byte3 = 0; + this->field_0x7a.HALF.HI = 0; + if (this->bitfield == 0x80 || this->bitfield == 0x9e) { + this->entityType.parameter = 0; + this->field_0x80.HALF.LO = 0x14; + } else { + this->entityType.parameter = 1; + this->field_0x80.HALF.LO = 8; + } + } + + if (this->currentHealth == 0 && this->field_0x7c.BYTES.byte3 == 0 && this->action == 7) { + CopyPosition(this, &gPlayerEntity); + gPlayerEntity.flags = gPlayerEntity.flags | 0x80; + gPlayerEntity.spriteSettings.b.draw = 1; + gPlayerEntity.field_0x20 = 0x18000; + gPlayerEntity.direction = 0xff; + gPlayerEntity.hurtBlinkTime = -0x14; + gPlayerState.jumpStatus = 0x41; + gPlayerState.flags.all &= 0xfff7ffff; + } + + sub_0804AA30(this, gUnk_080CBC38); +} + +void sub_080231A4(Entity* this) { + this->field_0x7c.BYTES.byte0++; + sub_08001324(this); +} + +void nullsub_135(Entity* this) { +} + +void sub_080231BC(Entity* this) { + if (gEntCount < 0x40) { + Entity* ent; + + ent = this->attachedEntity = CreateEnemy(0xf, 1); + ent->parent = this; + + ent = ent->attachedEntity = CreateEnemy(0xf, 2); + ent->parent = this; + + ent = ent->attachedEntity = CreateEnemy(0xf, 3); + ent->parent = this; + + ent = ent->attachedEntity = CreateEnemy(0xf, 4); + ent->parent = this; + + ent = ent->attachedEntity = CreateEnemy(0xf, 5); + ent->parent = this; + + ent = ent->attachedEntity = CreateEnemy(0xf, 6); + ent->parent = this; + + ent = ent->attachedEntity = CreateEnemy(0xf, 7); + ent->parent = this; + + ent->attachedEntity = CreateEnemy(0xf, 8); + *(Entity**)&ent->attachedEntity->field_0x74 = ent; + ent = ent->attachedEntity; + ent->parent = this; + ent->attachedEntity = NULL; + sub_0804A720(this); + this->action = 6; + this->actionDelay = 0x1e; + this->parent = this; + this->field_0x78.HWORD = 0x1e; + this->palette.b.b0 = 5; + this->direction = Random() & 0x1f; + this->animationState = Direction8ToAnimationState(this->direction); + InitializeAnimation(this, this->animationState); + } +} + +void nullsub_136(Entity* this) { +} + +void sub_08023288(Entity* this) { + if (sub_08049FDC(this, 1) && (this->actionDelay++ & 0xf) == 0) { + u32 idx = Random() & 0x1e; + u32 i; + + for (i = 0; i < 0x10; i++) { + u32 x = gPlayerEntity.x.HALF.HI + gUnk_080CBC70[idx + 0]; + u32 y = gPlayerEntity.y.HALF.HI + gUnk_080CBC70[idx + 1]; + if (sub_08023A38(GetTileTypeByPos(x, y, gPlayerEntity.collisionLayer))) { + sub_08023990(this, x, y); + return; + } + idx += 2; + idx &= 0x1e; + } + } +} + +void sub_08023330(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 4; + this->actionDelay = 0x19; + this->flags |= 0x80; + this->field_0x78.HWORD = 600; + this->direction = Random() & 0x1c; + this->animationState = this->direction >> 2; + this->field_0x7a.HALF.HI = 0; + this->field_0x7c.BYTES.byte3 = 0; + sub_08023A88(this, this->animationState); + CopyPosition(this, this->attachedEntity); + CreateFx(this, 4, 0); + } +} + +void sub_08023A68(Entity*); +void sub_08023AB0(Entity*); + +void sub_08023398(Entity* this) { + this->field_0x7c.BYTES.byte0++; + + if (this->field_0x7c.BYTES.byte3 && sub_08049FDC(this, 1) == 0) { + this->field_0x78.HWORD = 1; + } + + if (--this->field_0x78.HWORD == 0) { + if (sub_08023A38(GetTileTypeByEntity(this))) { + this->action = 5; + this->field_0x7c.BYTES.byte3 = 0; + this->flags = this->flags & 0x7f; + this->damageType = 0x85; + this->attachedEntity->actionDelay = 1; + sub_08023A68(this); + CreateFx(this, 4, 0); + return; + } + this->field_0x78.HWORD = 0x28; + } + + if (this->field_0x7c.BYTES.byte3) { + sub_08023AB0(this); + } + + if (--this->actionDelay < 3) { + if (this->actionDelay == 0) + this->actionDelay = 25; + } else { + int prevX = this->x.WORD; + int prevY = this->y.WORD; + ProcessMovement(this); + if (this->x.WORD == prevX && this->y.WORD == prevY) { + this->field_0x7c.BYTES.byte0--; + } + + if ((gScreenTransition.frameCount & 7) == 0) { + u32 uVar4; + + sub_08004596(this, sub_08049F84(this, 1)); + uVar4 = Direction8ToAnimationState(this->direction); + if (uVar4 != this->animationState) { + this->animationState = uVar4; + InitializeAnimation(this, uVar4 + this->field_0x7a.HALF.HI); + } + } + } +} + +void sub_080234A4(Entity* this) { + this->field_0x7c.BYTES.byte0++; + GetNextFrame(this); + if (this->field_0x7c.BYTES.byte3) { + this->action = 6; + this->spriteSettings.b.draw = 0; + this->field_0x78.HWORD = 300; + } +} + +void sub_080234D8(Entity* this) { + if (--this->field_0x78.HWORD == 0) { + this->action = 2; + this->palette.b.b0 = 5; + this->direction = Random() & 0x1f; + this->animationState = Direction8ToAnimationState(this->direction); + sub_08023A88(this, this->animationState); + } +} + +void sub_0802351C(Entity* this) { + if (this->actionDelay != 0 && (this->entityType.parameter == 1 || gPlayerEntity.frameIndex == 0xff)) { + this->actionDelay = 0; + this->attachedEntity->action = 3; + this->attachedEntity->field_0xf = this->field_0x80.HALF.LO; + InitializeAnimation(this->attachedEntity, this->attachedEntity->animationState + 1); + InitializeAnimation(this, this->animationState); + } + + if (this->field_0x7c.BYTES.byte3 == 0) { + if (this->entityType.parameter == 0) { + gPlayerEntity.animationState = this->animationState & 7; + gPlayerState.flags.all |= 0x80000; + PositionRelative(this, &gPlayerEntity, 0, gUnk_080CBC90[this->animationState & 7] << 0x10); + gPlayerEntity.spriteOffsetY = -gUnk_080CBC90[this->animationState & 7]; + } + } else { + this->action = 4; + } +} + +void sub_080235BC(Entity* this) { + gUnk_080CBC98[this->action](this); +} + +void sub_080235D4(Entity* this) { + Entity* parent; + + this->action = 1; + parent = this->parent; + this->x.HALF.HI = parent->x.HALF.HI; + this->y.HALF.HI = parent->y.HALF.HI; + sub_080239F0(this); + if (this->entityType.form == 1) { + this->animationState = 0x10; + } else { + this->animationState = 0x12; + } + InitializeAnimation(this, this->animationState); +} + +void sub_08023604(Entity* this) { + if (((u8*)&this->field_0x78)[this->parent->field_0x7c.BYTES.byte0 & 0xf] != 0x88) { + this->action = 2; + this->actionDelay = 0; + this->flags |= 0x80; + this->spriteSettings.b.draw = 1; + sub_08023644(this); + } +} + +void sub_08023644(Entity* this) { + Entity* parent = this->parent; + + if (parent->animIndex == 0x17 && this->actionDelay != 0 && this->x.HALF.HI == parent->x.HALF.HI && + this->y.HALF.HI == parent->y.HALF.HI) { + this->action = 1; + this->flags &= ~0x80; + this->spriteSettings.b.draw = 0; + this->attachedEntity->actionDelay = 1; + sub_080239F0(this); + } + + if (parent->field_0x7c.BYTES.byte0 != parent->field_0x7c.BYTES.byte1) { + u8* tmp = &((u8*)&this->field_0x78)[parent->field_0x7c.BYTES.byte0 & 0xf]; + this->x.HALF.HI += (*tmp >> 4) - 8; + this->y.HALF.HI += (*tmp & 0xf) - 8; + this->spriteOrientation.flipY = parent->spriteOrientation.flipY; + this->spriteRendering.b3 = parent->spriteRendering.b3; + this->collisionLayer = parent->collisionLayer; + } +} + +void sub_080236F8(Entity* parent) { + if (--parent->field_0xf == 0) { + parent->action = 2; + parent->attachedEntity->action = 3; + parent->attachedEntity->field_0xf = parent->parent->field_0x80.HALF.LO; + InitializeAnimation(parent->attachedEntity, parent->attachedEntity->animationState + 1); + InitializeAnimation(parent, parent->animationState); + } +} + +void sub_08023730(Entity* this) { + gUnk_080CBCA8[this->action](this); +} + +void sub_08023748(Entity* this) { + Entity* parent; + + this->action = 1; + this->animationState = 20; + parent = this->parent; + this->x.HALF.HI = parent->x.HALF.HI; + this->y.HALF.HI = parent->y.HALF.HI; + sub_080239F0(this); + sub_08023A68(this); +} + +void sub_0802376C(Entity* this) { + Entity* parent = this->parent; + + if (parent->spriteSettings.b.draw == 1 && parent->animIndex < 0x10) { + this->spriteSettings.b.draw = 1; + GetNextFrame(this); + } + + if (((u8*)&this->field_0x78)[parent->field_0x7c.BYTES.byte0 & 0xf] != 0x88) { + this->action = 2; + this->actionDelay = 0; + this->flags |= 0x80; + this->parent->field_0x7c.BYTES.byte3 = 1; + sub_08023A88(this, 20); + sub_080237D8(this); + } +} + +void sub_080237D8(Entity* this) { + Entity* parent = this->parent; + + if (parent->animIndex == 0x17 && this->actionDelay != 0 && this->x.HALF.HI == parent->x.HALF.HI && + this->y.HALF.HI == parent->y.HALF.HI) { + this->action = 1; + this->flags &= ~0x80; + this->spriteSettings.b.draw = 0; + parent->field_0x7c.BYTES.byte3 = 1; + sub_080239F0(this); + sub_08023A68(this); + } + + if (parent->field_0x7c.BYTES.byte0 != parent->field_0x7c.BYTES.byte1) { + u8* tmp = &((u8*)&this->field_0x78)[parent->field_0x7c.BYTES.byte0 & 0xf]; + this->x.HALF.HI += (*tmp >> 4) - 8; + this->y.HALF.HI += (*tmp & 0xf) - 8; + + this->spriteOrientation.flipY = parent->spriteOrientation.flipY; + this->spriteRendering.b3 = parent->spriteRendering.b3; + this->collisionLayer = parent->collisionLayer; + } +} + +void sub_08023894(Entity* this) { + if (--this->field_0xf == 0) { + this->action = 2; + this->parent->field_0x7c.BYTES.byte3 = 1; + InitializeAnimation(this, this->animationState); + if ((this->parent->entityType).parameter == 0) { + gPlayerState.flags.all |= 0x200000; + gPlayerEntity.x.HALF.HI = this->x.HALF.HI; + gPlayerEntity.y.HALF.HI = this->y.HALF.HI; + gPlayerEntity.direction = DirectionRoundUp(GetFacingDirection(*(Entity**)&this->field_0x74, this)); + gPlayerEntity.animationState = gPlayerEntity.direction >> 2; + gPlayerEntity.hurtBlinkTime = 12; + ModHealth(-0x10); + sub_0800449C(&gPlayerEntity, 0x7a); + } + } +} + +void sub_0802390C(Entity* this) { + if (this->bitfield & 0x80) { + Entity* ent = this->attachedEntity; + do { + ent->hurtBlinkTime = this->hurtBlinkTime; + } while (ent = ent->attachedEntity, ent != NULL); + } else { + Entity* ent = this->attachedEntity; + do { + if (ent->bitfield & 0x80) { + u8 bVar2 = 0xff - ent->currentHealth; + if (bVar2 != 0) { + u32 tmp; + ent->currentHealth = 0xff; + tmp = (u8)ent->hurtBlinkTime; + if (this->currentHealth >= bVar2) { + this->currentHealth -= bVar2; + } else { + this->currentHealth = 0; + } + + ent = this; + do { + ent->hurtBlinkTime = tmp; + } while (ent = ent->attachedEntity, ent != NULL); + break; + } + } + } while (ent = ent->attachedEntity, ent != NULL); + } +} + +void sub_08023990(Entity* this, u32 param_2, u32 param_3) { + Entity* ent; + + this->action = 3; + this->spriteSettings.b.draw = 1; + this->palette.b.b0 = 0x5; + this->palette.b.b4 = 0x5; + this->spritePriority.b0 = 7; + this->x.HALF.HI = param_2; + this->y.HALF.HI = param_3; + this->collisionLayer = gPlayerEntity.collisionLayer; + UpdateSpriteForCollisionLayer(this); + InitializeAnimation(this, 0x16); + + ent = this->attachedEntity; + do { + sub_080239F0(ent); + CopyPosition(this, ent); + } while (ent = ent->attachedEntity, ent != NULL); +} + +/* TODO: fix struct */ +NAKED +void sub_080239F0(Entity* this) { + asm(".include \"asm/non_matching/moldworm/sub_080239F0.inc\""); +} + +bool32 sub_08023A38(u32 unk) { + if (unk == 0x1a || unk == 0x29) { + return TRUE; + } else { + unk = gUnk_080B37A0[unk]; + if (unk == 9 || unk == 11 || unk == 10 || unk == 12) { + return TRUE; + } else { + return FALSE; + } + } +} + +void sub_08023A68(Entity* this) { + sub_0801D2B4(this, 5); + this->spritePriority.b0 = 7; + InitializeAnimation(this, 0x17); +} + +void sub_08023A88(Entity* this, u32 unk) { + sub_0801D2B4(this, 0x22); + this->spritePriority.b0 = 4; + InitializeAnimation(this, unk); +} + +void sub_08023AB0(Entity* this) { + if (this->field_0x7a.HALF.HI == 8) { + if (this->field_0x7c.BYTES.byte2) { + this->field_0x7c.BYTES.byte2--; + } else if (!sub_08023B38(this) || 0x1d >= this->field_0x78.HWORD) { + this->damageType = 0x85; + this->field_0x7a.HALF.HI = 0; + this->field_0x7c.BYTES.byte2 = 30; + InitializeAnimation(this, this->animationState); + } + } else if (this->field_0x7c.BYTES.byte2) { + this->field_0x7c.BYTES.byte2--; + } else if (this->field_0x78.HWORD >= 90 && sub_08023B38(this)) { + this->damageType = 0x87; + this->field_0x7a.HALF.HI = 8; + this->field_0x7c.BYTES.byte2 = 10; + InitializeAnimation(this, this->animationState + 8); + } +} + +NAKED +bool32 sub_08023B38(Entity* this) { + asm(".include \"asm/non_matching/moldworm/sub_08023B38.inc\""); +} + +// clang-format off +void (*const gUnk_080CBC38[])(Entity*) = { + sub_080230CC, + sub_080230E4, + sub_080231A4, + sub_0804A7D4, + sub_08001242, + nullsub_135, +}; + +void (*const gUnk_080CBC50[])(Entity*) = { + sub_080231BC, + nullsub_136, + sub_08023288, + sub_08023330, + sub_08023398, + sub_080234A4, + sub_080234D8, + sub_0802351C, +}; + +const s8 gUnk_080CBC70[] = { + 0x00, 0xd0, 0x00, 0x30, + 0xd0, 0x00, 0x30, 0x00, + 0xe0, 0xe0, 0xe0, 0x20, + 0x20, 0xe0, 0x20, 0x20, + 0xf0, 0xe0, 0x10, 0xe0, + 0xf0, 0x20, 0x10, 0x20, + 0xe0, 0xf0, 0x20, 0xf0, + 0xe0, 0x10, 0x20, 0x10, +}; + +const s8 gUnk_080CBC90[] = { + 0xff, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, +}; + +void (*const gUnk_080CBC98[])(Entity*) = { + sub_080235D4, + sub_08023604, + sub_08023644, + sub_080236F8, +}; + +void (*const gUnk_080CBCA8[])(Entity*) = { + sub_08023748, + sub_0802376C, + sub_080237D8, + sub_08023894, +}; + +const s8 gUnk_080CBCB8[] = { + 0x00, 0xe4, 0x14, 0xec, + 0x1c, 0x00, 0x14, 0x14, + 0x00, 0x1c, 0xec, 0x14, + 0xe4, 0x00, 0xec, 0xec, +}; +// clang-format on diff --git a/src/enemy/octorok.c b/src/enemy/octorok.c index a5b63f96..7e563ab0 100644 --- a/src/enemy/octorok.c +++ b/src/enemy/octorok.c @@ -1,119 +1,244 @@ #include "global.h" #include "entity.h" +#include "functions.h" extern void EnemyFunctionHandler(); extern void SetChildOffset(); extern void sub_0804AA30(); -extern void sub_0804A9FC(); extern void sub_0804A7D4(); -extern void CreateDeathFx(); -extern void sub_0801ECFC(); extern u32 sub_0806F520(); extern void sub_0806F4E8(); -extern void sub_0806F3E4(); extern void UpdateAnimationVariableFrames(); extern void sub_0804A720(); -extern u32 Random(); -extern void sub_0801ED14(); +extern Entity* sub_08049DF4(u32); -extern void(*gOctorok[2]); -extern void (*gOctorokIdle[4])(Entity*); -extern void (*gUnk_080CA158[4])(Entity*); +void Octorok_Pause(); +bool32 Octorok_FacesPlayer(); +void Octorok_Turn(); + +extern void (*const gOctorok[6])(Entity*); +extern void (*const gOctorokActions[4])(Entity*); +extern void (*const gUnk_080CA158[6])(Entity*); + +extern Entity* gUnk_020000B0; +extern const u8 gOctorokWalkDuration[4]; +extern const u8 gOctorokSpitChanceModifier[2]; +extern const u8 gOctorokNutOffset[8]; +extern const s8 gUnk_080CA17E[2]; -extern u8 gUnk_080CA170[8]; // Main -void Octorok(Entity* ent) { - EnemyFunctionHandler(ent, gOctorok); - SetChildOffset(ent, 0, 1, -16); +void Octorok(Entity* this) { + EnemyFunctionHandler(this, gOctorok); + SetChildOffset(this, 0, 1, -16); } // Idle -void sub_0801EAD0(Entity* ent) { - gOctorokIdle[ent->action](ent); +void Octorok_OnTick(Entity* this) { + gOctorokActions[this->action](this); } // Touch player -void sub_0801EAE8(Entity* ent) { - if (ent->field_0x43 != 0) { - sub_0804A9FC(ent, 28); +void sub_0801EAE8(Entity* this) { + if (this->field_0x43 != 0) { + sub_0804A9FC(this, 28); } - sub_0804AA30(ent, gOctorok); + sub_0804AA30(this, gOctorok); } // Death -void sub_0801EB0C(Entity* ent) { - if ((ent->entityType).form == 0) { - sub_0804A7D4(ent); +void sub_0801EB0C(Entity* this) { + if (this->entityType.form == 0) { + sub_0804A7D4(this); } else { - CreateDeathFx(ent, 241, 0); + CreateDeathFx(this, 241, 0); } } -void sub_0801EB2C(Entity* ent) { - s32 iVar1; - - if ((ent->previousActionFlag < 3) && (iVar1 = sub_0806F520(ent), iVar1 == 0)) { - sub_0801ECFC(ent); - InitializeAnimation(ent, ent->animationState); +void sub_0801EB2C(Entity* this) { + if (this->previousActionFlag < 3 && !sub_0806F520(this)) { + Octorok_Pause(this); + InitializeAnimation(this, this->animationState); } else { - gUnk_080CA158[ent->previousActionFlag](ent); + gUnk_080CA158[this->previousActionFlag](this); } } -void sub_0801EB68(Entity* ent) { - ent->previousActionFlag = 1; - ent->field_0x1d = 60; +void sub_0801EB68(Entity* this) { + this->previousActionFlag = 1; + this->field_0x1d = 60; } -void sub_0801EB74(Entity* ent) { - sub_0806F4E8(ent); +void sub_0801EB74(Entity* this) { + sub_0806F4E8(this); } -void sub_0801EB7C(Entity* ent) { - sub_0806F3E4(ent); +void sub_0801EB7C(Entity* this) { + sub_0806F3E4(this); } -void sub_0801EB84(Entity* ent) { - ent->flags = ent->flags & 127; - UpdateAnimationVariableFrames(ent, 2); +void sub_0801EB84(Entity* this) { + this->flags &= 0x7f; + UpdateAnimationVariableFrames(this, 2); } -void nullsub_3() { +void nullsub_3(Entity* this) { + /* ... */ } -void sub_0801EB9C(Entity* ent) { - if ((ent->flags & 128) != 0) { - ent->flags = ent->flags | 128; - ent->field_0x3a = ent->field_0x3a & 251; +void sub_0801EB9C(Entity* this) { + if (this->flags & 0x80) { + this->flags |= 0x80; + this->field_0x3a &= 0xfb; } else { - ent->currentHealth = 0; + this->currentHealth = 0; } } // Init -#ifdef NON_MATCHING -void sub_0801EBC8(Entity* ent) { - sub_0804A720(); - ent->animationState = (ent->entityType).form == 2 ? (ent->entityType).form : Random() & 3; - ent->filler[0] = 18; - sub_0801ECFC(ent); - InitializeAnimation(ent, ent->animationState); -} -#else -NAKED -void sub_0801EBC8(Entity* ent) { - asm(".include \"asm/octorok/sub_0801EBC8.inc\""); -} -#endif - -void sub_0801EBF4(Entity* ent) { - u32 uVar2; - - if (--ent->actionDelay == 0) { - ent->action = 2; - uVar2 = Random(); - ent->actionDelay = gUnk_080CA170[uVar2 & 3]; - sub_0801ED14(ent); +void Octorok_Initialize(Entity* this) { + sub_0804A720(this); + if (this->entityType.form == 2) { + this->animationState = this->entityType.form; + } else { + this->animationState = Random() & 3; + } + this->field_0x1c = 18; + Octorok_Pause(this); + InitializeAnimation(this, this->animationState); +} + +void Octorok_Idle(Entity* this) { + if (--this->actionDelay == 0) { + this->action = 2; + this->actionDelay = gOctorokWalkDuration[Random() & 3]; + Octorok_Turn(this); } - GetNextFrame(ent); + GetNextFrame(this); +} + +void Octorok_Move(Entity* this) { + ProcessMovement(this); + GetNextFrame(this); + if (--this->actionDelay == 0) { + if (Octorok_FacesPlayer(this) && gOctorokSpitChanceModifier[this->entityType.form] <= (Random() & 3)) { + this->action = 3; + InitializeAnimation(this, this->animationState + 4); + } else { + Octorok_Pause(this); + } + } +} + +void Octorok_ShootNut(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 1) { + Entity* ent = sub_0804A98C(this, 1, 0); + if (ent) { + const s8* off; + ent->direction = this->direction; + off = &gOctorokNutOffset[this->direction / 4]; + ent->x.HALF.HI += off[0]; + ent->y.HALF.HI += off[1]; + ent->height.HALF.HI = -3; + this->frames.all &= 0xfe; + EnqueueSFX(0x18d); + } + } + + if (this->frames.all & 0x80) + Octorok_Pause(this); } + +void Octorok_Pause(Entity* this) { + this->action = 1; + this->actionDelay = (Random() & 0x38) + 0x18; +} + +void Octorok_Turn(Entity* this) { + if (this->entityType.form != 2) { + if (sub_08049FA0(this)) { + if (this->entityType.form == 1 && (Random() & 3) == 0 && sub_08049FDC(this, 1)) { + this->direction = DirectionRoundUp(GetFacingDirection(this, gUnk_020000B0)); + } else { + this->direction = DirectionRound(Random()); + } + } else if (Random() & 3) { + this->direction = DirectionRound(sub_08049EE4(this) + gUnk_080CA17E[Random() & 1]); + } else { + this->direction = DirectionRound(Random()); + } + } else { + if (sub_08049FDC(this, 1) == 0) { + if (sub_08049FA0(this)) { + this->direction = DirectionRound(Random()); + } else if (Random() & 3) { + this->direction = DirectionRound(sub_08049EE4(this) + gUnk_080CA17E[Random() & 1]); + } else { + this->direction = DirectionRoundUp(GetFacingDirection(this, gUnk_020000B0)); + } + } else { + this->direction = DirectionRoundUp(GetFacingDirection(this, gUnk_020000B0)); + } + } + + this->animationState = this->direction >> 3; + InitializeAnimation(this, this->animationState); +} + +bool32 Octorok_FacesPlayer(Entity* this) { + Entity* ent = sub_08049DF4(1); + + if (ent == NULL) + return FALSE; + + if (DirectionRoundUp(GetFacingDirection(this, ent)) != this->direction) + return FALSE; + + return TRUE; +} + +// clang-format off +void (*const gOctorok[])(Entity*) = { + Octorok_OnTick, + sub_0801EAE8, + sub_08001324, + sub_0801EB0C, + sub_08001242, + sub_0801EB2C, +}; + +void (*const gOctorokActions[])(Entity*) = { + Octorok_Initialize, + Octorok_Idle, + Octorok_Move, + Octorok_ShootNut, +}; + +void (*const gUnk_080CA158[])(Entity*) = { + sub_0801EB68, + sub_0801EB74, + sub_0801EB7C, + sub_0801EB84, + nullsub_3, + sub_0801EB9C, +}; + +const u8 gOctorokWalkDuration[] = { + 30, 60, 60, 90, +}; + +const u8 gOctorokSpitChanceModifier[] = { + 1, 0, +}; + +const u8 gOctorokNutOffset[] = { + 0, -3, + 4, 0, + 0, 2, + -4, 0, +}; + +const s8 gUnk_080CA17E[] = { + 4, -4, +}; +// clang-format on diff --git a/src/enemy/peahat.c b/src/enemy/peahat.c new file mode 100644 index 00000000..664e1615 --- /dev/null +++ b/src/enemy/peahat.c @@ -0,0 +1,417 @@ +#include "entity.h" +#include "functions.h" + +extern void (*const gPeahatFunctions[])(Entity*); +extern void (*const gPeahatPropellerFunctions[])(Entity*); +extern void (*const gPeahatActions[])(Entity*); +extern void (*const gUnk_080CA5BC[])(Entity*); + +extern const s8 gPeahatFlightHeights[]; +extern const s8 gUnk_080CA5D4[]; + +void sub_080205F8(Entity*); +void sub_08020604(Entity*); + +extern u32 sub_08049F1C(Entity*, Entity*, u32); +extern void sub_0804AA1C(Entity*); + +extern Entity* gUnk_020000B0; + +enum { + PeahatForm_Torso, + PeahatForm_Propeller, +}; + +enum { + PeahatAnimation_Flying, + PeahatAnimation_BrokenPropeller, + PeahatAnimation_SlicedPropeller, + PeahatAnimation_Propeller, + PeahatAnimation_NewPropeller, + PeahatAnimation_RepairPropeller, +}; + +void Peahat(Entity* this) { + if (this->entityType.form == PeahatForm_Torso) { + EnemyFunctionHandler(this, gPeahatFunctions); + SetChildOffset(this, 0, 1, -0x10); + } else { + gPeahatPropellerFunctions[this->action](this); + } +} + +void Peahat_OnTick(Entity* this) { + gPeahatActions[this->action](this); + if (this->field_0x80.HALF.HI) + this->height.HALF.HI = gPeahatFlightHeights[(this->field_0xf++ & 0x30) >> 4]; +} + +void sub_0801FFDC(Entity* this) { + if (this->field_0x82.HALF.LO) { + if (this->bitfield == 0x94) { + Entity* ent = CreateEnemy(3, PeahatForm_Propeller); + if (ent) { + CopyPosition(this, ent); + ent->height.HALF.HI -= 8; + } + this->field_0x82.HALF.LO = 0; + this->animationState = PeahatAnimation_SlicedPropeller; + this->action = 5; + this->nonPlanarMovement = 0x80; + this->hurtBlinkTime = -30; + this->field_0x80.HALF.HI = 0; + InitializeAnimation(this, this->animationState); + } else if (this->bitfield == 0x9b) { + this->animationState = PeahatAnimation_BrokenPropeller; + this->action = 5; + this->nonPlanarMovement = 0x80; + this->hurtBlinkTime = -30; + this->field_0x80.HALF.HI = 0; + InitializeAnimation(this, this->animationState); + } else if (this->bitfield == 0x80) { + if (this->animationState == PeahatAnimation_Flying) { + this->action = 1; + this->actionDelay = 30; + this->nonPlanarMovement = 0x80; + this->direction = -1; + this->field_0x82.HALF.HI = 0x78; + GetNextFrame(this); + } + } + } + + if (this->field_0x43) + sub_0804A9FC(this, 0x1c); + + sub_0804AA30(this, gPeahatFunctions); +} + +void sub_08020088(Entity* this) { + if (2 >= this->previousActionFlag && !sub_0806F520(this)) + return; + + gUnk_080CA5BC[this->previousActionFlag](this); +} + +void sub_080200B4(Entity* this) { + this->previousActionFlag = 1; + this->field_0x1d = 60; + if (this->animationState == PeahatAnimation_Flying) { + this->animationState = PeahatAnimation_BrokenPropeller; + this->action = 5; + this->damageType = 0x71; + this->field_0x80.HALF.HI = 0; + InitializeAnimation(this, this->animationState); + } +} + +void sub_080200E4(Entity* this) { + sub_0806F4E8(this); +} + +void sub_080200EC(Entity* this) { + sub_0806F3E4(this); +} + +void sub_080200F4(Entity* this) { + this->flags &= ~0x80; +} + +void nullsub_5(Entity* this) { +} + +void sub_08020104(Entity* this) { + if (this->flags & 0x80) { + this->flags |= 0x80; + this->field_0x3a &= 0xfb; + } else { + this->currentHealth = 0; + } +} + +void Peahat_Initialize(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->actionDelay = 16; + this->field_0xf = Random(); + this->direction = Random() & 0x1f; + this->field_0x1c = 18; + this->field_0x80.HALF.LO = (Random() & 1) ? 2 : -2; + this->field_0x80.HALF.HI = 1; + this->field_0x82.HALF.LO = 1; + this->animationState = PeahatAnimation_Flying; + InitializeAnimation(this, this->animationState); +} + +void Peahat_Fly(Entity* this) { + if (this->field_0x82.HALF.HI) + this->field_0x82.HALF.HI--; + + if (sub_08049FDC(this, 1)) { + if (this->field_0x82.HALF.HI == 0 && (this->field_0xf & 0xf) == 0 && sub_08049F1C(this, gUnk_020000B0, 0x30)) { + this->action = 2; + this->previousActionFlag = Random() & 3; + this->actionDelay = 60; + this->nonPlanarMovement = 160; + } + } + + if (--this->actionDelay == 0) { + this->actionDelay = 16; + sub_08020604(this); + if ((Random() & 3) == 0) { + this->field_0x80.HALF.LO = (Random() & 1) ? 2 : -2; + } + } + + sub_080AEFE0(this); + GetNextFrame(this); +} + +void Peahat_ChargeStart(Entity* this) { + if (sub_08049FDC(this, 1)) { + if (--this->actionDelay) { + UpdateAnimationVariableFrames(this, 4 - ((this->actionDelay >> 4) & 0x3)); + return; + } else { + this->action = 3; + this->actionDelay = 120; + this->nonPlanarMovement = 192; + this->direction = (GetFacingDirection(this, gUnk_020000B0) + gUnk_080CA5D4[Random() & 1]) & 0x1f; + } + } else { + sub_080205F8(this); + } + + UpdateAnimationVariableFrames(this, 4); +} + +void Peahat_ChargeTarget(Entity* this) { + if (sub_08049FDC(this, 1)) { + if (--this->actionDelay == 0) { + sub_080205F8(this); + } + if (60 < this->actionDelay) { + if (this->actionDelay & 1) + this->nonPlanarMovement += 4; + + if ((gScreenTransition.frameCount & 3) == 0) + sub_08004596(this, GetFacingDirection(this, gUnk_020000B0)); + } + sub_080AEFE0(this); + } else { + sub_080205F8(this); + } + UpdateAnimationVariableFrames(this, 4); +} + +void Peahat_ChargeEnd(Entity* this) { + if (--this->actionDelay == 0) { + this->action = 1; + this->actionDelay = 1; + this->nonPlanarMovement = 128; + this->field_0x82.HALF.HI = 120; + GetNextFrame(this); + } else { + if (this->actionDelay & 1) + this->nonPlanarMovement -= 8; + + sub_080AEFE0(this); + UpdateAnimationVariableFrames(this, 4); + } +} + +void Peahat_Stunned(Entity* this) { + switch (this->animationState) { + default: + if (sub_080044EC(this, 0x1800) == 0) { + this->action = 6; + this->actionDelay = 240; + this->field_0xf = 10; + this->damageType = 0x71; + } + + if (this->direction == 0xff) + this->direction = this->field_0x3e; + + ProcessMovement(this); + GetNextFrame(this); + break; + case PeahatAnimation_SlicedPropeller: + sub_08003FC4(this, 0x1c00); + if (this->height.HALF.HI == 0) { + this->action = 7; + this->actionDelay = 150; + this->field_0xf = 10; + this->damageType = 0x71; + } + break; + }; +} + +void Peahat_RepairPropeller(Entity* this) { + if (this->field_0xf) + if (--this->field_0xf == 0) + sub_0804A9FC(this, 0x1c); + + if (!sub_0800442E(this) && --this->actionDelay) + return; + + this->action = 9; + this->field_0x20 = 0x18000; + this->direction = Random() & 0x1f; + sub_0804AA1C(this); + this->animationState = PeahatAnimation_RepairPropeller; + InitializeAnimation(this, this->animationState); +} + +void Peahat_Recover(Entity* this) { + if (this->field_0xf) + if (--this->field_0xf == 0) + sub_0804A9FC(this, 0x1c); + + if (!sub_0800442E(this) && --this->actionDelay) + return; + + this->action = 8; + this->actionDelay = 240; + this->direction = Random() & 0x1f; + sub_0804AA1C(this); +} + +void Peahat_Hop(Entity* this) { + GetNextFrame(this); + if (--this->actionDelay == 0) { + if (this->frames.all & 0x80) { + this->action = 9; + this->field_0x20 = 0x18000; + this->animationState = PeahatAnimation_NewPropeller; + InitializeAnimation(this, this->animationState); + } else { + this->actionDelay = 1; + } + } + + if (this->frames.all & 2) { + this->frames.all &= ~2; + this->direction = Random() & 0x1f; + } + + if (this->frames.all & 1) { + sub_0800442E(this); + } else { + ProcessMovement(this); + } +} + +void Peahat_Takeoff(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 1; + this->damageType = 0x70; + this->field_0x82.HALF.LO = 1; + this->field_0x80.HALF.HI = 1; + this->animationState = PeahatAnimation_Flying; + InitializeAnimation(this, this->animationState); + } else if (this->frames.all & 1) { + sub_0800442E(this); + } else { + sub_08003FC4(this, 0x1c00); + ProcessMovement(this); + } +} + +void PeahatPropeller_Initialize(Entity* this) { + this->action = 1; + this->actionDelay = 240; + this->field_0xf = 40; + this->spriteSettings.b.draw = 1; + this->spriteRendering.b3 = 1; + this->spriteOrientation.flipY = 1; + this->spriteSettings.b.shadow = 0; + this->nonPlanarMovement = 0x20; + this->direction = (Random() & 0x10) + 8; + InitializeAnimation(this, PeahatAnimation_Propeller); +} + +void PeahatPropeller_Fly(Entity* this) { + GetNextFrame(this); + if (--this->actionDelay == 0) { + DeleteEntity(this); + } else { + if (this->actionDelay < 60) + this->spriteSettings.b.draw ^= 1; + + this->height.WORD -= 0xc000; + sub_0806F69C(this); + if (--this->field_0xf == 0) { + this->field_0xf = 40; + this->direction = (Random() & 0x10) + 8; + } + } +} + +void sub_080205F8(Entity* this) { + this->action = 4; + this->actionDelay = 60; +} + +void sub_08020604(Entity *this){ + if (!sub_08049FA0(this) && (Random() & 3)) { + this->direction = sub_08049EE4(this); + } else { + this->direction += this->field_0x80.HALF.LO; + this->direction &= 0x1f; + } +} + + + +// clang-format off +void (*const gPeahatFunctions[])(Entity*) = { + Peahat_OnTick, + sub_0801FFDC, + sub_08001324, + sub_0804A7D4, + sub_08001242, + sub_08020088, +}; + +void (*const gPeahatPropellerFunctions[])(Entity*) = { + PeahatPropeller_Initialize, + PeahatPropeller_Fly, +}; + +void (*const gPeahatActions[])(Entity*) = { + Peahat_Initialize, + Peahat_Fly, + Peahat_ChargeStart, + Peahat_ChargeTarget, + Peahat_ChargeEnd, + Peahat_Stunned, + Peahat_RepairPropeller, + Peahat_Recover, + Peahat_Hop, + Peahat_Takeoff, +}; + +const s8 gPeahatFlightHeights[] = { + -5, -6, -7, -6, +}; + +void (*const gUnk_080CA5BC[])(Entity*) = { + sub_080200B4, + sub_080200E4, + sub_080200EC, + sub_080200F4, + nullsub_5, + sub_08020104, +}; + +/* Alignment issue +const s8 gUnk_080CA5D4[] = { + 4, -4, +}; +*/ +// clang-format on + diff --git a/src/enemy/pesto.c b/src/enemy/pesto.c new file mode 100644 index 00000000..8147d832 --- /dev/null +++ b/src/enemy/pesto.c @@ -0,0 +1,906 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern u32 sub_080002E0(u16, u32); +extern u32 CheckIsDungeon(void); +extern void sub_0800449C(Entity*, u32); +extern u32 sub_08049F1C(Entity*, Entity*, u32); +extern void sub_0804AA30(Entity*, void (*const funcs[])(Entity*)); +extern u32 PlayerInRange(Entity*, u32, u32); +extern void sub_080AEFB4(Entity*); +extern Entity* FindNextEntityOfSameSubtype(Entity* ent, int listIndex); + +void sub_080249F4(Entity*); +void sub_08024940(Entity*); +void sub_080249DC(Entity*); +void sub_08024A14(Entity*, u32, u32); +bool32 sub_08024AD8(Entity*); +bool32 sub_08024B38(Entity*); +bool32 sub_08024C48(Entity*, bool32); +void sub_08024C7C(Entity*); +void sub_08024C94(Entity*); +bool32 sub_08024CC0(Entity*); +void sub_08024D00(Entity*); +void sub_08024E00(Entity*, u32); +void sub_08024E1C(Entity*); +u32 sub_08024E34(void); +void sub_08024E4C(Entity*); +void sub_08024F50(Entity*); + +extern Entity* gUnk_020000B0; + +extern void (*const gUnk_080CBEC4[])(Entity*); +extern void (*const gUnk_080CBEDC[])(Entity*); +extern void (*const gUnk_080CBEF8[])(Entity*); + +extern const u8 gUnk_080CBF10[]; +extern const u16 gUnk_080CBF18[]; +extern const u8 gUnk_080CBF20[]; + +void Pesto(Entity* this) { + gUnk_080CBEC4[GetNextFunction(this)](this); +} + +void sub_08023F44(Entity* this) { + gUnk_080CBEDC[this->action](this); +} + +void sub_08023F5C(Entity* this) { + if (this->damageType != 0x6e) { + if (this->bitfield == 0x80) { + this->field_0x86.HALF.LO = 0x30; + + if ((this->field_0x82.HALF.HI & 0xf) == 3 && this->action == 6) { + switch (this->field_0x80.HALF.LO) { + case 1: + this->height.HALF.HI = -0x10; + this->field_0x82.HALF.LO = 0; + this->field_0x78.HWORD = -0x10; + this->field_0x80.HALF.LO += 1; + /* fallthrough */ + case 2: + this->field_0x82.HALF.HI &= ~0x80; + break; + } + } + } + } else { + this->currentHealth = 0; + } + + sub_0804AA30(this, gUnk_080CBEC4); +} + +void sub_08023FE0(Entity* this) { + sub_08001324(this); + GetNextFrame(this); +} + +void sub_08023FF0(Entity* this) { + if (this->previousActionFlag < 3 && !sub_0806F520(this)) { + this->action = 1; + this->previousActionFlag = 0; + this->flags |= 0x80; + this->damageType = 0x77; + this->actionDelay = 1; + this->nonPlanarMovement = 0x40; + } else { + gUnk_080CBEF8[this->previousActionFlag](this); + } +} + +void sub_08024038(Entity* this) { + this->previousActionFlag = 1; + this->field_0x1d = 60; + GetNextFrame(this); +} + +void sub_08024048(Entity* this) { + sub_0806F4E8(this); + GetNextFrame(this); +} + +void sub_08024058(Entity* this) { + sub_0806F3E4(this); +} + +void sub_08024060(Entity* this) { + if (this->damageType != 0x6e) { + this->flags = this->flags & 0x7f; + this->damageType = 0x6e; + this->spriteRendering.b3 = gPlayerEntity.spriteRendering.b3; + } + + GetNextFrame(this); +} + +void nullsub_138(Entity* this) { + /* ... */ +} + +void sub_0802409C(Entity* this) { + this->currentHealth = 0; + InitializeAnimation(this, this->animationState); + CreateDust(this); +} + +void sub_080240B8(Entity* this) { + u32 direction = (Random() & 0xc0) >> 3; + sub_0804A720(this); + this->action = 1; + this->previousActionFlag = 0; + this->field_0x80.HALF.LO = 0; + if (direction & 8) { + this->y.HALF.HI += (direction & 0x10) ? -0x20 : 0x20; + } else { + this->x.HALF.HI += (direction & 0x10) ? -0x20 : 0x20; + } + + switch (this->entityType.form) { + case 0: + this->field_0x78.HWORD = -0x10; + this->height.HALF.HI = -0x10; + break; + case 1: + this->field_0x78.HWORD = -0x30; + this->height.HALF.HI = -0x30; + break; + } + + UpdateSpriteForCollisionLayer(this); + if (CheckIsDungeon()) + this->spriteOrientation.flipY = 1; + + this->field_0x80.HALF.HI = Random() & 0x40; + this->field_0x82.HALF.LO = 0; + this->field_0x82.HALF.HI = 0x80; + this->field_0x86.HALF.LO = 0; + this->field_0x86.HALF.HI = 0; + this->actionDelay = 0; + this->field_0xf = 0x20; + this->field_0x3c |= 0x10; + this->field_0x1c = 2; + this->direction = direction; + sub_080249DC(this); + + if (this->entityType.form == 1) { + Entity* ent; + + this->field_0x82.HALF.HI = 0; + ent = sub_0804A98C(this, 6, this->field_0x82.HALF.HI); + if (ent) { + this->attachedEntity = ent; + ent->parent = this; + ent->y.HALF.HI += 0x10; + } + } +} + +void sub_080241C0(Entity* this) { + sub_08024940(this); + switch (this->field_0x80.HALF.LO) { + case 0: + if (PlayerInRange(this, 3, (gPlayerState.hurtBlinkSpeed != 0) ? 0xa0 : 0x40) && sub_08049FDC(this, 3) && + gPlayerEntity.action != 0x1e) { + this->field_0x80.HALF.LO++; + this->nonPlanarMovement = 0; + sub_08024A14(this, 3, 10); + } else if (--this->field_0xf == 0) { + sub_08024A14(this, 0, 0x20); + } + break; + case 1: + if (--this->field_0xf == 0) { + if (this->entityType.form != 0) { + u8 tmp = this->field_0x82.HALF.HI & 0x80; + if (tmp) { + sub_08024C94(this); + this->field_0x82.HALF.HI |= 0x40; + } else { + this->action = 3; + this->field_0x80.HALF.LO = tmp; + this->field_0xf = 10; + sub_08024E00(this, 0); + sub_08024E1C(this); + sub_08024A14(this, 3, this->field_0xf); + } + } else { + sub_08024C94(this); + } + } + break; + } +} + +void sub_08024298(Entity* this) { + sub_08024D00(this); +} + +void sub_080242A0(Entity* this) { + sub_08024940(this); + if (sub_08024CC0(this)) { + if (--this->actionDelay == 0) { + this->direction = GetFacingDirection(this, gUnk_020000B0); + sub_08024E00(this, 1); + if (this->nonPlanarMovement != 0) { + this->nonPlanarMovement = 0; + } else { + sub_08024E1C(this); + } + } else if (--this->field_0xf == 0) { + sub_08024A14(this, 3, 10); + } + + if (sub_08049F1C(this, gUnk_020000B0, 0x20) && sub_08049FDC(this, 3)) { + this->action = 4; + this->field_0x80.HALF.LO = 0; + this->actionDelay = 0x10; + this->nonPlanarMovement = 0; + } + } +} + +void sub_0802433C(Entity* this) { + sub_08024940(this); + switch (this->field_0x80.HALF.LO) { + case 0: + if (--this->actionDelay == 0) { + this->field_0x80.HALF.LO++; + this->nonPlanarMovement = 0x100; + this->field_0xf = 8; + sub_08024E00(this, 1); + } + break; + case 1: + if (--this->actionDelay == 0) { + this->action = 5; + this->field_0x80.HALF.LO = 0; + this->nonPlanarMovement = 0x140; + this->actionDelay = 0xc0; + this->field_0xf = 8; + } else { + if (--this->field_0xf == 0) + sub_08024A14(this, 2, 4); + } + break; + } +} + +void sub_080243B8(Entity* this) { + sub_08024940(this); + switch (this->field_0x80.HALF.LO) { + case 0: + if (sub_08024C48(this, TRUE)) { + if (this->attachedEntity == NULL || this->attachedEntity->next == NULL) { + this->field_0x80.HALF.LO = 2; + this->actionDelay = 0x20; + this->nonPlanarMovement = 0x80; + this->field_0x82.HALF.HI = 0x80; + } else if (sub_08049F1C(this, gUnk_020000B0, 0xe)) { + this->field_0x80.HALF.LO++; + this->actionDelay = 0x1e; + this->nonPlanarMovement = 0x100; + this->field_0x82.HALF.HI = 0x80; + this->attachedEntity->action = 2; + } else if (--this->actionDelay) { + if (--this->field_0xf == 0) { + sub_08024A14(this, 2, (this->actionDelay >> 6) + 1); + } + } else { + sub_08024C7C(this); + } + } else { + sub_08024C7C(this); + } + break; + case 1: + if (--this->actionDelay == 0) { + this->field_0x80.HALF.LO++; + this->actionDelay = 0x20; + this->nonPlanarMovement = 0x80; + } + break; + case 2: + if (--this->actionDelay == 0) { + this->action = 6; + this->field_0x80.HALF.LO = 0; + this->nonPlanarMovement = 0x80; + sub_08024B38(this); + + if ((this->field_0x82.HALF.HI & 0x40) == 0) { + switch (this->field_0x82.HALF.HI & 0x3f) { + case 3: + this->actionDelay = 4; + break; + case 1: + this->actionDelay = 0x14; + break; + default: + this->actionDelay = 0x30; + break; + } + sub_08024A14(this, 2, 8); + } else { + this->actionDelay = 0x40; + sub_08024A14(this, 0, 8); + } + } + break; + } +} + +void sub_080244E8(Entity* this) { + sub_08024940(this); + switch (this->field_0x80.HALF.LO) { + case 0: + if (--this->actionDelay == 0) { + if (sub_080002E0(COORD_TO_TILE(this), 1) == 0) { + this->field_0x80.HALF.LO += 1; + this->field_0x82.HALF.LO += 1; + this->field_0xf = 0; + this->nonPlanarMovement = 0; + } else { + this->actionDelay = 0x30; + this->field_0xf = 4; + } + break; + } else { + if (--this->field_0xf == 0) { + sub_08024A14(this, 1, 8); + } + } + break; + case 1: + if (++this->height.HALF.HI >= -0x10) { + this->field_0x82.HALF.LO = 0; + this->field_0x78.HWORD = 0xfff0; + if (sub_08024AD8(this)) { + this->field_0x80.HALF.LO++; + } else { + sub_08024C94(this); + this->field_0x82.HALF.HI |= 0x40; + } + } + break; + case 2: + if (sub_08024AD8(this)) { + u32 tmp; + + if (--this->actionDelay == 0) { + if (this->nonPlanarMovement) { + this->nonPlanarMovement = 0; + } else { + sub_08024E1C(this); + } + this->direction = GetFacingDirection(this, this->attachedEntity); + sub_08024E00(this, 0); + sub_080249DC(this); + } else if (--this->field_0xf == 0) { + sub_08024A14(this, 1, 8); + } + + switch (this->field_0x82.HALF.HI & 0x3f) { + case 3: + tmp = this->field_0x82.HALF.HI & 0x80; + if (tmp == 0) { + this->field_0x80.HALF.LO++; + this->actionDelay = 0xc; + this->direction = 0x10; + this->nonPlanarMovement = tmp; + this->cutsceneBeh.HALF.LO = 0; + this->flags2 &= 0xfc; + sub_080249DC(this); + this->cutsceneBeh.HALF.HI = gPlayerEntity.spritePriority.b1; + gPlayerEntity.flags &= 0x7f; + gPlayerState.flags.all |= 0x100; + gPlayerState.field_0xa |= 0x80; + if (gPlayerState.swimState != 0) { + gPlayerState.swimState = 0; + } + } + break; + case 1: + if (sub_080041A0(this, this->attachedEntity, 6, 6)) { + Entity* ent; + + this->field_0x80.HALF.LO += 1; + this->actionDelay = 0xc; + this->field_0x82.HALF.HI &= ~0x80; + CopyPosition(this->attachedEntity, this); + this->height.HALF.HI -= 0xe; + this->field_0x78.HWORD -= 0xe; + + ent = sub_0804A98C(this, 6, this->field_0x82.HALF.HI); + if (ent) { + ent->parent = this; + ent->height.HALF.HI += 0xe; + ent->attachedEntity = this->attachedEntity; + CopyPosition(ent, ent->attachedEntity); + this->attachedEntity = ent; + } + } + break; + case 2: + if (sub_080041A0(this, this->attachedEntity, 6, 6)) { + Entity* ent; + + this->field_0x80.HALF.LO += 1; + this->actionDelay = 0xc; + this->field_0x82.HALF.HI &= ~0x80; + ent = this->attachedEntity; + SetTile((u16)ent->field_0x70.HALF.LO, COORD_TO_TILE(ent), ent->collisionLayer); + DeleteEntity(ent); + this->height.HALF.HI -= 0xe; + this->field_0x78.HWORD -= 0xe; + + ent = sub_0804A98C(this, 6, this->field_0x82.HALF.HI); + if (ent) { + ent->parent = this; + ent->height.HALF.HI += 0xe; + this->attachedEntity = ent; + } + } + break; + } + break; + } else { + sub_08024C94(this); + this->field_0x82.HALF.HI |= 0x40; + } + break; + case 3: + if (--this->actionDelay == 0) { + this->field_0x80.HALF.LO++; + this->field_0xf = 0; + this->nonPlanarMovement = 0; + this->field_0x82.HALF.LO++; + } + break; + case 4: + this->height.HALF.HI -= 2; + if (-60 > this->height.HALF.HI) { + this->field_0x80.HALF.LO++; + } + break; + case 5: + if (this->height.HALF.HI < -0x30) { + this->height.HALF.HI++; + } else { + if (this->field_0x82.HALF.LO != 0) { + this->field_0x82.HALF.LO = 0; + this->field_0x78.HWORD = -0x30; + } + + switch (this->field_0x82.HALF.HI) { + case 3: + if (0x2f < this->cutsceneBeh.HALF.LO) { + sub_08024F50(this); + } + break; + case 1 ... 2: + this->field_0x80.HALF.LO += 1; + this->actionDelay = 0xc0; + this->field_0xf = 8; + this->nonPlanarMovement = 0x80; + sub_080249DC(this); + break; + default: + sub_08024C7C(this); + break; + } + } + break; + case 6: + if (--this->actionDelay == 0) { + if (this->field_0x82.HALF.HI & 0x80) { + this->field_0x82.HALF.HI = 0xc0; + this->field_0x80.HALF.LO = 0; + this->nonPlanarMovement = 0x40; + this->actionDelay = 0x40; + this->field_0xf = 8; + sub_08024A14(this, 0, 8); + } else { + this->actionDelay = 0x40; + this->field_0xf = 8; + } + } else if (--this->field_0xf == 0) { + sub_08024A14(this, 2, 8); + } + break; + case 7: + if (gPlayerEntity.height.HALF.HI == 0) { + this->field_0x80.HALF.LO = 0; + this->nonPlanarMovement = 0x80; + sub_08024B38(this); + } + } + + if (this->field_0x82.HALF.HI == 3) { + sub_08024E4C(this); + } +} + +void sub_08024940(Entity* this) { + u32 random = Random() & 0x70; + + if (this->collisions != 0) { + sub_0800417E(this, this->collisions); + sub_080249F4(this); + } + + if (this->field_0x82.HALF.LO == 0) { + this->height.HALF.HI = this->field_0x78.HWORD; + if (random) + this->height.HALF.HI += 2; + } + + if (this->entityType.parameter != 0 || CheckIsDungeon()) { + if (!sub_08049FA0(this)) { + this->direction = sub_08049EE4(this); + sub_080249F4(this); + } + + if (this->height.HALF.HI < -0x20) { + this->spritePriority.b0 = 0; + } else { + this->spritePriority.b0 = 1; + } + } + + sub_080AEFB4(this); + GetNextFrame(this); +} + +void sub_080249DC(Entity* this) { + u8 direction = ((this->direction + 2) & 0x1c) >> 2; + this->animationState = direction; + InitializeAnimation(this, this->animationState); +} + +#if NON_MATCHING +void sub_080249F4(Entity* this) { + u8 direction = ((this->direction + 2) & 0x1c) >> 2; + if (direction != this->animationState) { + this->animationState = direction; + InitializeAnimation(this, this->animationState); + } +} +#else +NAKED +void sub_080249F4(Entity* this) { + asm(".include \"asm/non_matching/pesto/sub_080249F4.inc\""); +} +#endif + +void sub_08024A14(Entity* this, u32 param_2, u32 param_3) { + u8 unk = FALSE; + + switch (param_2) { + case 0: + sub_08004596(this, sub_08049EE4(this)); + unk = TRUE; + break; + case 1: + if (sub_08024C48(this, FALSE)) { + sub_08004596(this, GetFacingDirection(this, this->attachedEntity)); + unk = TRUE; + } + break; + case 2: + if (sub_08024C48(this, TRUE)) { + sub_08004596(this, GetFacingDirection(this, gUnk_020000B0)); + unk = TRUE; + } + break; + case 3: + if (sub_08024C48(this, TRUE)) { + this->direction = GetFacingDirection(this, gUnk_020000B0); + unk = TRUE; + } + break; + } + + if (param_2 != 0 && !sub_08049FA0(this) && (Random() & 3)) { + unk = FALSE; + } + + if (!unk) { + sub_08024A14(this, 0, param_3); + } + + sub_080249DC(this); + this->field_0xf = param_3; +} + +bool32 sub_08024AD8(Entity* this) { + if ((this->field_0x82.HALF.HI & 0x40) == 0) { + u8 unk = FALSE; + if ((this->field_0x82.HALF.HI & 0x3f) == 3) { + if (gPlayerState.hurtBlinkSpeed == 0) { + this->attachedEntity->parent = NULL; + this->attachedEntity = NULL; + this->field_0x82.HALF.HI = 0xc0; + return FALSE; + } + unk = TRUE; + } + + if (sub_08024C48(this, unk) == 0) { + this->attachedEntity = NULL; + this->field_0x82.HALF.HI = 0xc0; + return FALSE; + } + } else { + return sub_08024B38(this); + } + + return TRUE; +} + +bool32 sub_08024B38(Entity* this) { + int iVar4 = 0; + Entity* ent; + + if (gPlayerState.hurtBlinkSpeed != 0) { + if (gPlayerState.swimState == 1) { + if (gPlayerState.hurtBlinkSpeed > 3) { + gPlayerState.hurtBlinkSpeed -= 3; + } else { + gPlayerState.hurtBlinkSpeed = 0; + } + } + if (gPlayerState.hurtBlinkSpeed != 0) { + if (sub_08024C48(this, 1) && sub_08049F1C(this, gUnk_020000B0, 0xa0)) { + iVar4 = 1; + this->attachedEntity = gUnk_020000B0; + this->field_0x82.HALF.HI |= 3; + this->field_0x82.HALF.HI &= ~0x40; + } + + if (iVar4 == 0) { + this->attachedEntity = NULL; + } + return iVar4; + } + } + + ent = FindEntityInListBySubtype(8, 2, 2); + if (ent) { + do { + if (ent->action != 2 && ent->height.HALF.HI == 0 && sub_08049F1C(this, ent, 0xa0)) { + iVar4 = 1; + this->attachedEntity = ent; + this->field_0x82.HALF.HI |= 1; + this->field_0x82.HALF.HI &= ~0x40; + break; + } + } while (ent = FindNextEntityOfSameSubtype(ent, 2), ent != NULL); + } + + if (iVar4 != 0) { + return iVar4; + } + + ent = FindEntityInListBySubtype(6, 5, 6); + if (ent) { + do { + if (ent->action == 1 && sub_08049F1C(this, ent, 0xa0)) { + iVar4 = 1; + this->attachedEntity = ent; + this->field_0x82.HALF.HI |= 2; + this->field_0x82.HALF.HI &= ~0x40; + break; + } + } while (ent = FindNextEntityOfSameSubtype(ent, 6), ent != NULL); + } + + if (iVar4 == 0) { + this->attachedEntity = NULL; + } + + return iVar4; +} + +NAKED +bool32 sub_08024C48(Entity* this, bool32 unk) { + asm(".include \"asm/non_matching/pesto/sub_08024C48.inc\""); +} + +void sub_08024C7C(Entity* this) { + this->action = 1; + this->nonPlanarMovement = 0x40; + this->actionDelay = 0; + sub_08024A14(this, 0, 0x20); +} + +void sub_08024C94(Entity* this) { + this->action = 2; + this->field_0x80.HALF.LO = 0; + this->actionDelay = 0x40; + this->field_0xf = 0; + this->nonPlanarMovement = 0xc0; + this->field_0x82.HALF.HI = 0x80; + sub_08024A14(this, 3, this->field_0xf); +} + +bool32 sub_08024CC0(Entity* this) { + bool32 uVar2; + + uVar2 = TRUE; + if (!sub_08024C48(this, 1)) { + uVar2 = FALSE; + } else if (!sub_08049F1C(this, gUnk_020000B0, 0x50) || !sub_08049FDC(this, 3)) { + uVar2 = FALSE; + sub_08024C7C(this); + } + return uVar2; +} + +void sub_08024D00(Entity* this) { + if (this->field_0x86.HALF.LO) { + this->field_0x86.HALF.LO--; + GetNextFrame(this); + } else { + sub_08024940(this); + } + + if ((this->field_0x82.HALF.HI & 0x40) && sub_08024B38(this)) { + this->action = 6; + this->field_0x80.HALF.LO = 2; + } else if (sub_08024CC0(this)) { + switch (this->field_0x80.HALF.LO) { + case 0: + if (--this->actionDelay == 0) { + this->field_0x80.HALF.LO++; + this->actionDelay = (Random() & 0xf) + 0x20; + + this->direction += this->field_0x80.HALF.HI ? 4 : 0x1c; + this->direction &= 0x1f; + + this->field_0x80.HALF.HI ^= 0x40; + sub_08024A14(this, 3, 0x10); + } + break; + case 1: + if (--this->actionDelay == 0) { + this->field_0x80.HALF.LO = 0; + this->actionDelay = (Random() & 0x1f) + 0x20; + } else { + if (--this->field_0xf == 0) { + this->direction += this->field_0x80.HALF.HI ? 1 : 0x1f; + this->direction &= 0x1f; + + this->field_0xf = 0x10; + sub_080249DC(this); + } + } + break; + } + } +} + +void sub_08024E00(Entity* this, u32 unk) { + this->actionDelay = gUnk_080CBF10[sub_08024E34() * 2 | unk]; +} + +void sub_08024E1C(Entity* this) { + this->nonPlanarMovement = gUnk_080CBF18[sub_08024E34()]; +} + +u32 sub_08024E34(void) { + u32 idx = (Random() & 0x3c) >> 2; + return gUnk_080CBF20[idx]; +} + +#if NON_MATCHING +void sub_08024E4C(Entity* this) { + if (this->field_0x82.HALF.HI == 3) { + this->field_0xf++; + this->field_0xf &= 0xff; + this->field_0xf &= 0x1f; + + if (sub_0807953C()) { + this->cutsceneBeh.HALF.LO += 1 + (Random() & 1); + } + + if (gUnk_02002A40.stats.health == 0 || this->field_0x86.HALF.HI == 4) { + this->cutsceneBeh.HALF.LO = 0x30; + this->field_0x86.HALF.HI = 0; + sub_08024F50(this); + this->field_0x80.HALF.LO = 0; + this->nonPlanarMovement = 0x40; + this->actionDelay = 0x40; + this->field_0xf = 8; + sub_08024A14(this, 0, 8); + } else { + Entity* player = &gPlayerEntity; + + ResetPlayer(); + gPlayerState.flags.all |= 0x100; + gPlayerState.field_0xa |= 0x80; + gPlayerState.playerAction = 0xe; + gPlayerState.field_0x38 = 0x14; + gPlayerState.field_0x39 = 1; + *(u8*)&gPlayerState.field_0x3a = 0; + PositionRelative(this, player, 0, 0x10000); + player->spriteOffsetY = 0x1a; + player->animationState = 4; + player->spritePriority.b1 = 0; + if (this->field_0xf == 0) { + (this->field_0x86.HALF.HI++; + player->hurtBlinkTime = 8; + ModHealth(-2); + sub_0800449C(player, 0x7a); + } + } + } +} +#else +NAKED +void sub_08024E4C(Entity* this) { + asm(".include \"asm/non_matching/pesto/sub_08024E4C.inc\""); +} +#endif + +void sub_08024F50(Entity* this) { + gPlayerState.field_0xa = 0; + gPlayerState.flags.all &= 0xfffffeff; + CopyPosition(this, &gPlayerEntity); + gPlayerEntity.action = 1; + gPlayerEntity.flags |= 0x80; + gPlayerEntity.hurtBlinkTime = -0x3c; + gPlayerEntity.direction = gPlayerEntity.animationState << 2; + gPlayerEntity.nonPlanarMovement = 0; + gPlayerEntity.spritePriority.b1 = this->cutsceneBeh.HALF.HI; + gPlayerEntity.height.HALF.HI = gPlayerEntity.spriteOffsetY; + gPlayerEntity.spriteOffsetY = 0; + this->flags2 |= 3; + this->field_0x82.HALF.HI = 0xc0; + this->field_0x80.HALF.LO += 2; + this->cutsceneBeh.HALF.LO = 0; + this->nonPlanarMovement = 0x80; +} + +// clang-format off +void (*const gUnk_080CBEC4[])(Entity*) = { + sub_08023F44, + sub_08023F5C, + sub_08023FE0, + sub_0804A7D4, + sub_08001242, + sub_08023FF0, +}; + +void (*const gUnk_080CBEDC[])(Entity*) = { + sub_080240B8, + sub_080241C0, + sub_08024298, + sub_080242A0, + sub_0802433C, + sub_080243B8, + sub_080244E8, +}; + +void (*const gUnk_080CBEF8[])(Entity*) = { + sub_08024038, + sub_08024048, + sub_08024058, + sub_08024060, + nullsub_138, + sub_0802409C, +}; + +const u8 gUnk_080CBF10[] = { + 30, 60, 50, 90, 70, 100, 90, 120, +}; + +const u16 gUnk_080CBF18[] = { + 0x80, 0xC0, 0x100, 0x140, +}; + +const u8 gUnk_080CBF20[] = { + 0, 2, 1, 1, 3, 1, 2, 0, + 1, 1, 2, 3, 2, 2, 1, 2, +}; +// clang-format on diff --git a/src/enemy/puffstool.c b/src/enemy/puffstool.c new file mode 100644 index 00000000..881437f5 --- /dev/null +++ b/src/enemy/puffstool.c @@ -0,0 +1,732 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern u32 sub_080002E0(u32, u32); +extern u32 sub_080002C8(u16, u8); +extern u16 sub_080002A8(u32, u32, u32); +extern u16 sub_080002D4(u32, u32, u32); +extern void sub_0804AA1C(Entity*); +extern Entity* sub_08049DF4(u32); +extern void sub_0807B7D8(u32, u32, u32); + +extern u8 gUnk_080B37A0[]; +extern u8 gUnk_080B3E80[]; + +bool32 sub_080258C4(Entity*); +void sub_08025B18(Entity*); +void sub_08025C2C(Entity*); +void sub_08025BD4(Entity*); +void sub_080256B4(Entity*); +bool32 sub_08025C44(Entity*); +u32 sub_08025C60(Entity*); +bool32 sub_0802571C(Entity*); +void sub_08025A54(Entity*); +void sub_08025AE8(Entity*); +bool32 sub_0802594C(Entity*, u32); +bool32 sub_080257EC(Entity*, u32, u32); +bool32 sub_08025AB8(u32, u32); + +extern void (*const gUnk_080CBF9C[])(Entity*); +extern void (*const gUnk_080CBFB4[])(Entity*); +extern const u8 gUnk_080CBFE8[]; +extern void (*const gUnk_080CBFEC[])(Entity*); +extern const u8 gUnk_080CBFF8[]; +extern const u16 gUnk_080CC000[]; +extern const s8 gUnk_080CC020[]; +extern const u8 gUnk_080CC050[]; +extern const s8* const gUnk_080CC090[]; +extern const s8 gUnk_080CC0A0[]; +extern const s8 gUnk_080CC0A8[]; +extern const s8 gUnk_080CC0BA[]; +extern const s8 gUnk_080CC0C2[]; + +void Puffstool(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CBF9C); + SetChildOffset(this, 0, 1, -0x10); +} + +void sub_08025008(Entity* this) { + gUnk_080CBFB4[this->action](this); +} + +void sub_08025020(Entity* this) { + u8 tmp; + + switch (this->bitfield & 0x7f) { + case 0 ... 3: + /* ... */ + break; + case 0x1b: + sub_0804AA1C(this); + + tmp = gUnk_080CBFE8[(*(Entity**)&this->field_0x4c)->entityType.form]; + if (tmp < this->field_0x82.HALF.LO) { + this->field_0x82.HALF.LO -= gUnk_080CBFE8[(*(Entity**)&this->field_0x4c)->entityType.form]; + } else { + this->cutsceneBeh.HWORD = 0x294; + this->damageType = 0x83; + this->field_0x82.HALF.LO = 0; + sub_0801D2B4(this, 0x7c); + } + this->action = 7; + this->actionDelay = 0x3c; + if (0 < this->field_0x20) { + this->field_0x20 = 0; + } + this->hurtBlinkTime = -0xc; + this->field_0x42 = 0; + if (this->field_0x80.HALF.LO == 0) { + this->animationState = (*(Entity**)&this->field_0x4c)->direction >> 3; + InitializeAnimation(this, this->animationState + 4); + this->frameDuration = 6; + this->field_0x80.HALF.LO = 1; + } + break; + default: + if (this->damageType == 0x82 && this->hurtBlinkTime < 0) { + Entity* ent = CreateObject(0x21, 2, 0); + if (ent != NULL) { + ent->spritePriority.b0 = 3; + CopyPosition(this, ent); + } + EnqueueSFX(0x186); + } + break; + } + + sub_0804AA30(this, gUnk_080CBF9C); +} + +void sub_0802511C(Entity* this) { + if ((this->field_0x3a & 2) && this->actionDelay == 1 && this->field_0x82.HALF.LO) { + sub_08025B18(this); + } + sub_0804A7D4(this); +} + +void sub_0802514C(Entity* this) { + sub_08003FC4(this, 0x2000); + if (sub_0806F520(this)) { + gUnk_080CBFEC[this->previousActionFlag](this); + } else { + sub_08025C2C(this); + } +} + +void sub_08025180(Entity* this) { + this->previousActionFlag = 1; + this->actionDelay = Random(); + this->animationState = (((*(Entity**)&this->field_0x4c)->direction ^ 0x10) >> 3); + InitializeAnimation(this, this->animationState + 4); + sub_0804AA1C(this); +} + +void sub_080251AC(Entity* this) { + if (this->field_0x82.HALF.LO >= 4) { + this->field_0x82.HALF.LO -= 3; + if ((--this->actionDelay & 3) == 0) { + sub_08025BD4(this); + } + } else { + this->cutsceneBeh.HWORD = 0x294; + this->damageType = 0x83; + this->field_0x82.HALF.LO = 0; + sub_0801D2B4(this, 0x7c); + } + GetNextFrame(this); +} + +void sub_080251FC(Entity* this) { + sub_0804A720(this); + this->field_0x82.HALF.LO = 240; + this->direction = Random() & 0x1c; + this->field_0x80.HALF.LO = 0; + sub_080256B4(this); + InitializeAnimation(this, 0); +} + +void sub_08025230(Entity* this) { + if (this->field_0x80.HALF.HI) + this->field_0x80.HALF.HI--; + + sub_08025C44(this); + GetNextFrame(this); + if (--this->actionDelay == 0) { + this->actionDelay = (Random() & 3) + 4; + this->direction = sub_08025C60(this); + } + + if (this->collisions != 0) { + if (--this->field_0xf == 0) { + sub_0800417E(this, this->collisions); + } + } else { + this->field_0xf = 30; + } + + if (this->field_0x78.HWORD == 0) { + if (sub_0802571C(this)) { + this->action = 2; + this->actionDelay = 240; + this->field_0x86.HWORD = COORD_TO_TILE(this); + } + } else { + this->field_0x78.HWORD--; + } +} + +void sub_080252E0(Entity* this) { + u32 tile; + + this->direction = + sub_080045D4(this->x.HALF.HI, this->y.HALF.HI, (u16)this->field_0x7c.HALF.LO, (u16)this->field_0x7c.HALF.HI); + + sub_08025C44(this); + GetNextFrame(this); + + tile = COORD_TO_TILE(this); + if (tile == this->field_0x86.HWORD) { + if (--this->actionDelay == 0) { + sub_080256B4(this); + } + } else { + this->field_0x86.HWORD = tile; + this->actionDelay = 240; + } + + if (this->x.HALF.HI == (u16)this->field_0x7c.HALF.LO && this->y.HALF.HI == (u16)this->field_0x7c.HALF.HI) { + this->action = 3; + this->actionDelay = 0x1e; + this->field_0xf = 0; + this->field_0x20 = 0x18000; + InitializeAnimation(this, 1); + } +} + +void sub_0802538C(Entity* this) { + if (this->actionDelay) { + this->actionDelay--; + } else { + if (this->frames.all == 0) { + GetNextFrame(this); + } else { + sub_08003FC4(this, 0x2000); + if (this->field_0x20 < 0x2000) { + this->action = 4; + InitializeAnimation(this, 2); + } + } + } +} + +void sub_080253D4(Entity* this) { + GetNextFrame(this); + if (!sub_08003FC4(this, 0x2000)) { + if (this->field_0xf == 0) { + this->action = 5; + InitializeAnimation(this, 3); + } else { + this->action = 6; + this->actionDelay = 0x1e; + InitializeAnimation(this, 3); + sub_08025A54(this); + sub_08025AE8(this); + } + } +} + +void sub_0802541C(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 3; + this->field_0xf = 1; + this->field_0x20 = 0x20000; + InitializeAnimation(this, 1); + } +} + +void sub_0802544C(Entity* this) { + if (this->frames.all == 0) { + GetNextFrame(this); + } else { + if (--this->actionDelay == 0) { + sub_080256B4(this); + InitializeAnimation(this, 0); + } + } +} + +void sub_0802547C(Entity* this) { + sub_08003FC4(this, 0x2000); + GetNextFrame(this); + if ((this->actionDelay & 7) == 0) { + sub_08025BD4(this); + } + + if (--this->actionDelay == 0) { + sub_08025C2C(this); + } +} + +void sub_080254B4(Entity* this) { + sub_08003FC4(this, 0x2000); + if (this->frames.all & 0x80) { + if (this->height.HALF.HI == 0) { + if (this->cutsceneBeh.HWORD == 0) { + this->damageType = 0x82; + this->field_0x82.HALF.LO = -0x10; + sub_080256B4(this); + } else { + this->action = 0xc; + sub_0804A9FC(this, 0x1c); + } + InitializeAnimation(this, 0); + } + } else { + GetNextFrame(this); + } +} + +void sub_08025514(Entity* this) { + GetNextFrame(this); + if (sub_0802594C(this, this->actionDelay++)) { + this->action = 2; + this->actionDelay = 240; + this->field_0x80.HALF.HI = 120; + } else if (3 < this->actionDelay) { + this->action = 10; + this->actionDelay = 0x20; + } +} + +void sub_08025554(Entity* this) { + Entity* ent = sub_08049DF4(1); + if (ent == NULL) { + sub_080256B4(this); + } else { + if ((this->actionDelay & 3) == 0) { + this->direction = GetFacingDirection(ent, this); + } + sub_08025C44(this); + GetNextFrame(this); + if (this->actionDelay != 0) { + this->actionDelay--; + } else { + if (!sub_080258C4(this)) { + sub_080256B4(this); + } + } + } +} + +void sub_080255AC(Entity* this) { + Entity* ent = sub_08049DF4(1); + if (ent == NULL) { + sub_080256B4(this); + } else { + if (this->field_0x80.HALF.HI != 0) { + this->field_0x80.HALF.HI--; + } + + if (--this->actionDelay == 0) { + s32 tmp; + + this->actionDelay = (Random() & 3) + 4; + + tmp = Random() & 0xf; + if (tmp < 8) { + tmp -= 1; + } + tmp -= 7; + + this->direction = (GetFacingDirection(ent, this) + tmp) & 0x1f; + } + + if (this->field_0x78.HWORD == 0) { + if (sub_080258C4(this) == 0) { + sub_080256B4(this); + } + } else { + this->field_0x78.HWORD--; + } + sub_08025C44(this); + GetNextFrame(this); + } +} + +void sub_0802563C(Entity* this) { + GetNextFrame(this); + + if (--this->cutsceneBeh.HWORD == 0) { + sub_0801D2B4(this, 0x28); + this->damageType = 0x82; + this->field_0x82.HALF.LO = 240; + sub_080256B4(this); + sub_0804AA1C(this); + } else if (this->cutsceneBeh.HWORD < 120) { + u32 tmp3 = gUnk_080CBFF8[this->cutsceneBeh.HWORD >> 4]; + if ((this->cutsceneBeh.HWORD & tmp3) == 0) { + if (this->cutsceneBeh.HWORD & (tmp3 + 1)) { + sub_0801D2B4(this, 124); + } else { + sub_0801D2B4(this, 40); + } + } + } +} + +void sub_080256B4(Entity* this) { + this->action = 1; + this->actionDelay = (Random() & 3) + 4; + this->field_0xf = 0x1e; + this->direction = (this->direction + 7 + ((s32)Random() % 7) * 4) & 0x1c; + this->field_0x78.HWORD = gUnk_080CC000[Random() & 0xf]; + this->field_0x7a.HALF.LO = ((s32)Random() % 0x18) << 1; + this->field_0x7a.HALF.HI = 0; +} + +bool32 sub_0802571C(Entity* this) { + RoomControls* ctrl = &gRoomControls; + u16 xDiff = (this->x.HALF.HI - ctrl->roomOriginX + 8) & -0x10; + u16 yDiff = (this->y.HALF.HI - ctrl->roomOriginY + 8) & -0x10; + u16 unk = this->field_0x7a.HALF.LO; + u16 i; + + for (i = 0; i < 4; i++) { + u16 sVar3 = xDiff + gUnk_080CC020[unk + 0]; + u16 sVar4 = yDiff + gUnk_080CC020[unk + 1]; + + if (sub_080257EC(this, sVar3, sVar4)) { + this->field_0x7c.HALF.LO = sVar3 + ctrl->roomOriginX; + this->field_0x7c.HALF.HI = sVar4 + ctrl->roomOriginY; + return TRUE; + } + + unk += 2; + if (0x2f < unk) { + unk = 0; + } + } + + this->field_0x7a.HALF.LO = unk; + this->field_0x7a.HALF.HI++; + return FALSE; +} + +bool32 sub_080257EC(Entity* this, u32 x, u32 y) { + u16 tmp; + + tmp = sub_080002A8(x - 0x00, y - 0x00, this->collisionLayer); + if (tmp != 0x312 && gUnk_080B37A0[tmp] != 0x16 && gUnk_080B3E80[tmp] == 0) { + return TRUE; + } + + tmp = sub_080002A8(x - 0x10, y - 0x00, this->collisionLayer); + if (tmp != 0x312 && gUnk_080B37A0[tmp] != 0x16 && gUnk_080B3E80[tmp] == 0) { + return TRUE; + } + + tmp = sub_080002A8(x - 0x00, y - 0x10, this->collisionLayer); + if (tmp != 0x312 && gUnk_080B37A0[tmp] != 0x16 && gUnk_080B3E80[tmp] == 0) { + return TRUE; + } + + tmp = sub_080002A8(x - 0x10, y - 0x10, this->collisionLayer); + if (tmp != 0x312 && gUnk_080B37A0[tmp] != 0x16 && gUnk_080B3E80[tmp] == 0) { + return TRUE; + } + + return FALSE; +} + +bool32 sub_080258C4(Entity* this) { + Entity* ent = sub_08049DF4(1); + if (ent == NULL) { + return FALSE; + } else { + s32 iVar4; + s32 iVar1; + iVar4 = ent->x.HALF.HI - this->x.HALF.HI; + iVar4 = iVar4 * iVar4; + iVar1 = ent->y.HALF.HI - this->y.HALF.HI; + iVar1 = iVar1 * iVar1; + iVar4 = iVar4 + iVar1; + if (this->cutsceneBeh.HWORD == 0 && this->field_0x80.HALF.HI == 0 && 0x400 >= iVar4) { + this->action = 9; + this->actionDelay = 0; + return TRUE; + } else if (0x900 >= iVar4) { + this->action = 11; + this->actionDelay = 1; + this->field_0x78.HWORD = gUnk_080CC050[Random() & 0xf]; + return TRUE; + } else { + return FALSE; + } + } +} + +#if NON_MATCHING +bool32 sub_0802594C(Entity* this, u32 param_2) { + const s8* unk = gUnk_080CC090[param_2]; + u32 uVar1 = this->collisionLayer; + RoomControls* ctrl = &gRoomControls; + u16 xDiff = (this->x.HALF.HI - ctrl->roomOriginX + 8) & -0x10; + u16 yDiff = (this->y.HALF.HI - ctrl->roomOriginY + 8) & -0x10; + do { + u16 iVar9 = xDiff + unk[0]; + u16 iVar11 = yDiff + unk[1]; + u32 bVar4 = sub_080002D4(iVar9 - 0x00, iVar11 - 0x00, uVar1); + u32 bVar5 = sub_080002D4(iVar9 - 0x10, iVar11 - 0x00, uVar1); + u32 bVar6 = sub_080002D4(iVar9 - 0x00, iVar11 - 0x10, uVar1); + u32 bVar7 = sub_080002D4(iVar9 - 0x10, iVar11 - 0x10, uVar1); + if ((bVar6 | bVar4 | bVar5 | bVar7) == 0) { + this->field_0x7c.HALF.LO = ctrl->roomOriginX + iVar9; + this->field_0x7c.HALF.HI = ctrl->roomOriginY + iVar11; + return TRUE; + } + unk += 2; + } while (unk[0] != 0x7f); + + return 0; +} +#else +NAKED +bool32 sub_0802594C(Entity* this, u32 param_2) { + asm(".include \"asm/non_matching/puffstool/sub_0802594C.inc\""); +} +#endif + +void sub_08025A54(Entity* this) { + u32 layer = this->collisionLayer; + s16 x = this->x.HALF.HI - gRoomControls.roomOriginX; + s16 y = this->y.HALF.HI - gRoomControls.roomOriginY; + + const s8* offset = gUnk_080CC0A0; + u32 i = 0; + + for (; i < 4; i++, offset += 2) { + sub_08025AB8((((x + offset[0]) >> 4) & 0x3fU) | ((((y + offset[1]) >> 4) & 0x3fU) << 6), layer); + } +} + +bool32 sub_08025AB8(u32 tile, u32 layer) { + if (sub_080002E0(tile, layer)) + return FALSE; + + if (sub_080002C8(tile, layer) == 10) { + sub_0807B7D8(0x61, tile, layer); + return TRUE; + } + + return FALSE; +} + +void sub_08025AE8(Entity* this) { + Entity* ent; + + ent = CreateFx(this, 0x22, 0); + if (ent) { + ent->y.WORD--; + } + + ent = CreateFx(this, 0x23, 0); + if (ent) { + ent->y.WORD++; + } +} + +void sub_08025B18(Entity* this) { + Entity* ent; + + s32 x = this->x.HALF.HI - gRoomControls.roomOriginX; + s32 y = this->y.HALF.HI - gRoomControls.roomOriginY; + u32 layer = this->collisionLayer; + + const s8* offset = gUnk_080CC0A8; + u32 i = 0; + + for (; i < 9; i++, offset += 2) { + sub_08025AB8((((x + offset[0]) >> 4) & 0x3fU) | ((((y + offset[1]) >> 4) & 0x3fU) << 6), layer); + + ent = CreateObject(0x21, 2, 0); + if (ent) { + PositionRelative(this, ent, offset[0] * 0x10000, offset[1] * 0x10000); + ent->x.HALF.HI &= -0x10; + ent->x.HALF.HI += 8; + ent->y.HALF.HI &= -0x10; + ent->y.HALF.HI += 8; + ent->height.HALF.HI = -1; + } + } +} + +void sub_08025BD4(Entity* this) { + if (this->field_0x82.HALF.LO && (this->frames.all & 1) == 0) { + Entity* ent = CreateObject(0x21, 0, 0); + if (ent) { + PositionRelative(this, ent, gUnk_080CC0BA[this->animationState * 2 + 0] * 0x10000, + gUnk_080CC0BA[this->animationState * 2 + 1] * 0x10000); + ent->height.HALF.HI = -10; + } + } +} + +void sub_08025C2C(Entity* this) { + this->action = 8; + this->field_0x80.HALF.LO = 0; + InitializeAnimation(this, 8); +} + +bool32 sub_08025C44(Entity* this) { + if ((this->frames.all & 1) == 0) { + return ProcessMovement(this); + } else { + return FALSE; + } +} + +u32 sub_08025C60(Entity* this) { + if (!sub_08049FA0(this) && (Random() & 1)) { + return sub_08049EE4(this); + } + + return (gUnk_080CC0C2[Random() & 7] + this->direction) & 0x1f; +} + +// clang-format off +void (*const gUnk_080CBF9C[])(Entity*) = { + sub_08025008, + sub_08025020, + sub_08001324, + sub_0802511C, + sub_08001242, + sub_0802514C, +}; + +void (*const gUnk_080CBFB4[])(Entity*) = { + sub_080251FC, + sub_08025230, + sub_080252E0, + sub_0802538C, + sub_080253D4, + sub_0802541C, + sub_0802544C, + sub_0802547C, + sub_080254B4, + sub_08025514, + sub_08025554, + sub_080255AC, + sub_0802563C, +}; + +const u8 gUnk_080CBFE8[] = { + 40, 120, 240, 0x0 +}; + +void (*const gUnk_080CBFEC[])(Entity*) = { + sub_08025180, + sub_080251AC, + sub_080251AC, +}; + +const u8 gUnk_080CBFF8[] = { + 1, 1, 1, 3, 3, 3, 7, 7, +}; + +const u16 gUnk_080CC000[] = { + 30, 30, 90, 90, + 180, 180, 180, 180, + 180, 240, 240, 240, + 240, 240, 300, 300, +}; + +const s8 gUnk_080CC020[] = { + -0x20, -0x20, -0x20, -0x10, + -0x20, 0x00, -0x20, 0x10, + -0x20, 0x20, -0x10, -0x20, + -0x10, -0x10, -0x10, 0x00, + -0x10, 0x10, -0x10, 0x20, + 0x00, -0x20, 0x00, -0x10, + 0x00, 0x10, 0x00, 0x20, + 0x10, -0x20, 0x10, -0x10, + 0x10, 0x00, 0x10, 0x10, + 0x10, 0x20, 0x20, -0x20, + 0x20, -0x10, 0x20, 0x00, + 0x20, 0x10, 0x20, 0x20, +}; + +const u8 gUnk_080CC050[] = { + 90, 120, 120, 90, + 180, 180, 180, 180, +}; + +const s8 gUnk_080CC058[] = { + 0x00, 0x00, 0x00, 0xF0, + 0xF0, 0x00, 0x10, 0x00, + 0x00, 0x10, 0x7F, +}; + +const s8 gUnk_080CC063[] = { + 0x00, 0x20, 0x10, 0x10, + 0x20, 0x00, 0x10, 0xF0, + 0x00, 0xE0, 0xF0, 0xF0, + 0xE0, 0x00, 0xF0, 0x10, + 0x7F, +}; + +const s8 gUnk_080CC074[] = { + 0xE0, 0xF0, 0xF0, 0xE0, + 0x10, 0xE0, 0x20, 0xF0, + 0x20, 0x10, 0x10, 0x20, + 0xF0, 0x20, 0xE0, 0x10, + 0x7F, +}; + +const s8 gUnk_080CC085[] = { + 0x20, 0x20, 0x20, 0xE0, + 0xE0, 0xFE, 0xE0, 0x20, + 0x7F, +}; + +const s8 *const gUnk_080CC090[] = { + gUnk_080CC058, + gUnk_080CC063, + gUnk_080CC074, + gUnk_080CC085, +}; + +const s8 gUnk_080CC0A0[] = { + -0x8, -0x8, + -0x8, 0x8, + 0x8, -0x8, + 0x8, 0x8, +}; + +const s8 gUnk_080CC0A8[] = { + -0x10, -0x10, + 0x00, -0x10, + 0x10, -0x10, + -0x10, 0x00, + 0x00, 0x00, + 0x10, 0x00, + -0x10, 0x10, + 0x00, 0x10, + 0x10, 0x10, +}; + +const s8 gUnk_080CC0BA[] = { + 0x00, -0x10, + 0x13, 0x00, + 0x00, 0x14, + -0x13, 0x00, +}; + +const s8 gUnk_080CC0C2[] = { + -1, 1, + -2, 2, + -3, 3, + -4, 4, +}; +// clang-format on diff --git a/src/enemy/rockChuchu.c b/src/enemy/rockChuchu.c new file mode 100644 index 00000000..8c4a82f3 --- /dev/null +++ b/src/enemy/rockChuchu.c @@ -0,0 +1,122 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern void sub_0804A4E4(Entity*, Entity*); + +extern void (*const gUnk_080CB948[])(Entity*); +extern void (*const gUnk_080CB960[])(Entity*); + +void RockChuchu(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CB948); +} + +void sub_0802223C(Entity* this) { + gUnk_080CB960[this->action](this); +} + +void sub_08022254(Entity* this) { + Entity* ent; + + if (this->currentHealth) { + switch (this->bitfield & 0x7f) { + case 4: + case 5: + case 6: + case 8: + case 9: + case 10: + case 0xb: + case 0xc: + case 0xd: + case 0x10: + case 0x11: + case 0x12: + case 0x18: + case 0x19: + case 0x1a: + if ((gPlayerState.field_0xac & 8) == 0) + break; + case 0x16: + case 0x1c: + CreateFx(this, 4, 0); + ent = CreateEnemy(1, 1); + if (ent) { + ent->entityType.parameter = 1; + ent->hurtBlinkTime = -8; + sub_0804A4E4(this, ent); + this->action = 2; + this->flags &= ~0x80; + this->spriteSettings.b.draw = 0; + this->direction = this->field_0x3e; + this->attachedEntity = ent; + } + } + } else { + if (this->damageType != 0x94) + InitializeAnimation(this, 2); + } + + sub_0804AA30(this, gUnk_080CB948); +} + +void nullsub_131(Entity* this) { +} + +void sub_08022368(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->actionDelay = Random(); + this->direction = sub_08049F84(this, 1); + InitializeAnimation(this, 0); +} + +void sub_08022390(Entity* this) { + if (sub_08049FDC(this, 1)) { + if ((this->actionDelay++ & 0xf) == 0) { + this->direction = sub_08049F84(this, 1); + this->field_0xf = Random() & 4; + } + + if (this->field_0xf == 0) { + ProcessMovement(this); + } else { + this->field_0xf = this->field_0xf - 1; + } + } else { + this->actionDelay = Random(); + } + + GetNextFrame(this); +} + +void sub_080223E4(Entity* this) { + Entity* ent; + + ent = this->attachedEntity; + if (ent) { + ent->bitfield = 0x94; + ent->hurtBlinkTime = 0x10; + ent->field_0x42 = 0xc; + ent->field_0x3e = this->direction; + } + + DeleteEntity(this); +} + +// clang-format off +void (*const gUnk_080CB948[])(Entity*) = { + sub_0802223C, + sub_08022254, + sub_08001324, + sub_0804A7D4, + sub_08001242, + nullsub_131, +}; + +void (*const gUnk_080CB960[])(Entity*) = { + sub_08022368, + sub_08022390, + sub_080223E4, +}; +// clang-format on diff --git a/src/enemy/rollobite.c b/src/enemy/rollobite.c new file mode 100644 index 00000000..7ef108b4 --- /dev/null +++ b/src/enemy/rollobite.c @@ -0,0 +1,321 @@ +#include "entity.h" +#include "functions.h" + +extern void (*const gRollobiteFunctions[])(Entity*); +extern void (*const gRollobiteActions[])(Entity*); +extern void (*const gUnk_080CA6A4[])(Entity*); +extern void (*const gUnk_080CA6BC[])(Entity*); + +extern const u8 gUnk_080CA6CC[]; +extern const s8 gUnk_080CA6D4[]; + +void sub_08020A30(Entity*); +void sub_08020A7C(Entity*); +bool32 Rollobite_TryToHoleUp(Entity*); +bool32 Rollobite_IsRolledUp(Entity*); + +extern void sub_080AE58C(); +extern void sub_080AE7E8(); +extern void sub_08078930(); + +void Rollobite(Entity* this) { + EnemyFunctionHandler(this, gRollobiteFunctions); +} + +void Rollobite_OnTick(Entity* this) { + Rollobite_TryToHoleUp(this); + gRollobiteActions[this->action](this); +} + +void sub_08020668(Entity* this) { + if (this->damageType == 34 && this->currentHealth != 0xff) { + this->action = 4; + this->field_0x20 = 0x20000; + this->direction = 0xff; + this->currentHealth = 0xff; + this->damageType = 35; + InitializeAnimation(this, this->animationState + 8); + } + + if (this->bitfield != 0x80) { + if (this->action == 4 || this->action == 5) { + this->action = 4; + this->actionDelay = 180; + this->direction = 0xff; + InitializeAnimation(this, this->animationState + 0x10); + } + } + + if (this->bitfield == 0x93) + Rollobite_OnTick(this); +} + +void sub_080206E0(Entity* this) { + if (Rollobite_TryToHoleUp(this)) { + this->field_0x42 = 0; + } else if (Rollobite_IsRolledUp(this)) { + this->field_0x42--; + sub_080AE58C(this, this->field_0x3e, 10); + sub_080AE7E8(this, this->field_0x46, this->field_0x3e, 10); + } else { + sub_08001324(this); + } +} + +void sub_08020734(Entity* this) { + if (this->previousActionFlag < 3 && !sub_0806F520(this)) { + this->action = 4; + this->flags |= 0x80; + this->direction = 0xff; + InitializeAnimation(this, this->animationState + 0x10); + } else { + gUnk_080CA6A4[this->previousActionFlag](this); + } +} + +void sub_0802077C(Entity* this) { + this->previousActionFlag = 1; + this->field_0x1d = 60; +} + +void sub_08020788(Entity* this) { + sub_0806F4E8(this); +} + +void sub_08020790(Entity* this) { + sub_0806F3E4(this); +} + +void sub_08020798(Entity* this) { + this->flags &= ~0x80; +} + +void nullsub_6(Entity* this) { + /* ... */ +} + +void sub_080207A8(Entity* this) { + this->action = 4; + this->flags |= 0x80; + this->spritePriority.b0 = 4; + this->field_0x3a &= 0xfb; + this->direction ^= 0x10; + this->field_0x20 = 0x18000; + this->nonPlanarMovement = 0x80; + InitializeAnimation(this, this->animationState + 0x10); +} + +void Rollobite_Initialize(Entity* this) { + sub_0804A720(this); + this->field_0x16 = 0x30; + this->field_0x1c = 18; + this->cutsceneBeh.HALF.LO = 0; + this->direction = DirectionRound(Random()); + sub_08020A30(this); +} + +void Rollobite_Walk(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x1) { + this->frames.all &= ~0x1; + if (!ProcessMovement(this)) + this->actionDelay = 1; + } + + if (this->frames.all & 0x10) { + this->frames.all &= ~0x10; + if (--this->actionDelay == 0) { + this->action = 3; + this->actionDelay = 60; + } + } +} + +void sub_08020874(Entity* this) { + gUnk_080CA6BC[this->previousActionFlag](this); +} + +void sub_0802088C(Entity* this) { + this->previousActionFlag = 1; + this->flags &= ~0x80; + this->cutsceneBeh.HALF.HI = gPlayerEntity.animationState; + this->spritePriority.b1 = 0; +} + +void sub_080208B4(Entity* this) { + s8 uVar1 = (this->cutsceneBeh.HALF.HI - gPlayerEntity.animationState) / 2; + if (uVar1) { + this->animationState = (this->animationState + uVar1) & 3; + InitializeAnimation(this, this->animationState + 0x10); + } + this->cutsceneBeh.HALF.HI = gPlayerEntity.animationState; +} + +void sub_080208F0(Entity* this) { + this->spritePriority.b1 = 3; +} + +void sub_08020904(Entity* this) { + this->action = 4; + this->flags |= 0x80; + this->direction = -1; + InitializeAnimation(this, this->animationState + 0x10); +} + +void Rollobite_Turn(Entity* this) { + if (--this->actionDelay == 0) + sub_08020A30(this); +} + +void Rollobite_RolledUp(Entity* this) { + u32 unk; + + if ((this->frames.all & 0x80) == 0) + GetNextFrame(this); + + unk = sub_080044EC(this, 0x2800); + + if (unk == 0) { + if (--this->actionDelay == 0) { + this->action = 5; + InitializeAnimation(this, this->animationState + 12); + } + sub_08078930(this); + } else { + if (unk == 1) + EnqueueSFX(260); + + if ((this->direction & 0x80) == 0) + sub_080AEFE0(this); + } +} + +void Rollobite_Unroll(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->flags |= 0x80; + this->nonPlanarMovement = 0x100; + this->damageType = 34; + sub_08020A30(this); + this->direction = DirectionFromAnimationState(this->animationState); + InitializeAnimation(this, this->animationState); + } else { + if ((this->frames.all & 1) == 0) + sub_08078930(this); + } +} + +void Rollobite_LinedUp(Entity* this) { + if (sub_08003FC4(this, 0x1c00) == 0) { + this->action = 7; + this->spritePriority.b0 = 7; + } + + if (this->frames.all == 0) + GetNextFrame(this); +} + +void Rollobite_Holed(Entity* this) { + GetNextFrame(this); +} + +void sub_08020A30(Entity* this) { + if (this->cutsceneBeh.HALF.LO < 2) { + this->actionDelay = gUnk_080CA6CC[Random() & 7]; + if (this->actionDelay == 0) { + this->action = 3; + this->actionDelay = 60; + this->cutsceneBeh.HALF.LO++; + return; + } + } + this->action = 1; + this->cutsceneBeh.HALF.LO = 0; + sub_08020A7C(this); +} + +void sub_08020A7C(Entity* this) { + int tmp = Random(); + u32 state = DirectionRound(this->direction + gUnk_080CA6D4[tmp % 3]); + + if (sub_08049FA0(this) == 0) { + int tmp = DirectionRoundUp(sub_08049EE4(this)); + if ((state ^ 0x10) == tmp) + state ^= 0x10; + } + + this->direction = state; + this->animationState = (u8)(state >> 3); + InitializeAnimation(this, this->animationState); +} + +bool32 Rollobite_TryToHoleUp(Entity* this) { + if (Rollobite_IsRolledUp(this) && this->height.HALF.HI == 0) { + int tile = COORD_TO_TILE(this); + int iVar1 = GetTileType(tile, this->collisionLayer); + if ((iVar1 * 0x10000 - 0x710000U) >> 0x10 < 2) { + this->action = 6; + this->flags &= ~0x80; + this->x.HALF.HI &= 0xfff0; + this->x.HALF.HI += 8; + this->y.HALF.HI &= 0xfff0; + this->y.HALF.HI += 13; + this->field_0x20 = 0x20000; + InitializeAnimation(this, this->animationState + 0x14); + SetTile(0x4034, tile, this->collisionLayer); + return TRUE; + } + } + return FALSE; +} + +bool32 Rollobite_IsRolledUp(Entity* this) { + u32 tmp = this->animIndex; + if (16 <= tmp && tmp <= 19) { + return TRUE; + } else { + return FALSE; + } +} + +// clang-format off +void (*const gRollobiteFunctions[])(Entity*) = { + Rollobite_OnTick, + sub_08020668, + sub_080206E0, + sub_0804A7D4, + sub_08001242, + sub_08020734, +}; + +void (*const gRollobiteActions[])(Entity*) = { + Rollobite_Initialize, + Rollobite_Walk, + sub_08020874, + Rollobite_Turn, + Rollobite_RolledUp, + Rollobite_Unroll, + Rollobite_LinedUp, + Rollobite_Holed, +}; + +void (*const gUnk_080CA6A4[])(Entity*) = { + sub_0802077C, + sub_08020788, + sub_08020790, + sub_08020798, + nullsub_6, + sub_080207A8, +}; + +void (*const gUnk_080CA6BC[])(Entity*) = { + sub_0802088C, + sub_080208B4, + sub_080208F0, + sub_08020904, +}; + +const u8 gUnk_080CA6CC[] = { + 0, 6, 9, 0, 6, 6, 0, 7, +}; +// clang-format on diff --git a/src/enemy/rupeeLike.c b/src/enemy/rupeeLike.c index 4b907897..b7b43f8b 100644 --- a/src/enemy/rupeeLike.c +++ b/src/enemy/rupeeLike.c @@ -17,8 +17,9 @@ extern void (*const gUnk_080CCC00[])(Entity*); extern void (*const gUnk_080CCC18[])(Entity*); extern void (*const gUnk_080CCC3C[])(Entity*); -extern u8 gUnk_080CCC34[]; -extern u8 gUnk_080CCC47[]; +extern const u8 gUnk_080CCC34[]; +extern const s8 gUnk_080CCC44[]; +extern const u8 gUnk_080CCC47[]; extern BoundingBox gUnk_080FD260; void RupeeLike(Entity* this) { @@ -62,7 +63,7 @@ void sub_08029318(Entity* this) { this->field_0x82.HALF.HI = 0x41; this->flags2 &= 0xfc; this->field_0x80.HALF.LO = gPlayerEntity.spritePriority.b1; - sub_08004488(0x104); + EnqueueSFX(0x104); } else { if (this->field_0x43 != 0) { sub_0804A9FC(this, 0x1c); @@ -136,7 +137,7 @@ void sub_080294D4(Entity* this) { sub_08004596(this, GetFacingDirection(this, &gPlayerEntity)); sub_0802969C(this); } - sub_080AEF88(this); + ProcessMovement(this); sub_080296C8(this); } else { this->action = 6; @@ -146,8 +147,6 @@ void sub_080294D4(Entity* this) { } } -extern s8 gUnk_080CCC44[]; - void sub_0802953C(Entity* this) { u8* pbVar3; @@ -262,7 +261,7 @@ void sub_08029770(Entity* this) { InitializeAnimation(this, 2); this->attachedEntity->spriteSettings.b.draw = TRUE; InitializeAnimation(this->attachedEntity, 6); - sub_080A29BC(this); + CreateDust(this); } } @@ -280,3 +279,43 @@ void sub_080297F0(Entity* this) { this->spriteVramOffset = 9; InitializeAnimation(this, 0x54); } + +// clang-format off +void (*const gUnk_080CCC00[])(Entity*) = { + sub_08029300, + sub_08029318, + sub_08001324, + sub_080293B4, + sub_08001242, + nullsub_141, +}; + +void (*const gUnk_080CCC18[])(Entity*) = { + sub_0802940C, + sub_0802944C, + sub_08029474, + sub_080294D4, + sub_0802953C, + sub_08029610, + sub_08029630, +}; + +const u8 gUnk_080CCC34[] = { + 0x54, 0x55, + 0x56, 0x55, + 0x56, 0x57, +}; + +void (*const gUnk_080CCC3C[])(Entity*) = { + sub_08029660, + sub_08029688, +}; + +const s8 gUnk_080CCC44[] = { + -1, -5, -20, +}; + +const u8 gUnk_080CCC47[] = { + 2, 1, 0, +}; +// clang-format on diff --git a/src/enemy/sensorBladeTrap.c b/src/enemy/sensorBladeTrap.c new file mode 100644 index 00000000..a0a049c0 --- /dev/null +++ b/src/enemy/sensorBladeTrap.c @@ -0,0 +1,120 @@ +#include "enemy.h" +#include "functions.h" + +extern u32 sub_0804A024(Entity*, u32, u32); +extern bool32 sub_080AE4CC(Entity*, u32, u32, u32); +extern bool32 sub_080AF038(Entity*); + +extern Entity gUnk_02027EB4; +extern Entity gUnk_0200D654; + +void sub_0802BB10(Entity*); +bool32 sub_0802BB2C(Entity*, u32); + +extern void (*const gUnk_080CD3C4[])(Entity*); +extern const u16 gUnk_080CD3D4[]; +extern const s8 gUnk_080CD3DC[]; + +void SensorBladeTrap(Entity* this) { + gUnk_080CD3C4[this->action](this); +} + +void sub_0802B9EC(Entity* this) { + this->action = 1; + this->field_0x78.HWORD = gUnk_080CD3D4[this->entityType.form]; + this->field_0x7c.HALF.LO = this->cutsceneBeh.HWORD; + this->field_0x7c.HALF.HI = this->field_0x86.HWORD; +} + +void sub_0802BA18(Entity* this) { + u32 direction = sub_0804A024(this, 1, 0xe); + if (direction == 0xff) + return; + + if (sub_0802BB2C(this, direction)) + return; + + this->action = 2; + this->nonPlanarMovement = this->field_0x78.HWORD; + this->direction = direction; + + switch (direction >> 3) { + case 0: + this->field_0x7a.HWORD = this->y.HALF.HI - this->field_0x7c.HALF.HI; + break; + case 1: + this->field_0x7a.HWORD = this->x.HALF.HI + this->field_0x7c.HALF.LO; + break; + case 2: + this->field_0x7a.HWORD = this->y.HALF.HI + this->field_0x7c.HALF.HI; + break; + case 3: + this->field_0x7a.HWORD = this->x.HALF.HI - this->field_0x7c.HALF.LO; + break; + } +} + +void sub_0802BA8C(Entity* this) { + if (!sub_080AF038(this)) { + sub_0802BB10(this); + } else { + switch (this->direction >> 3) { + case 0: + if (this->field_0x7a.HWORD >= this->y.HALF.HI) + sub_0802BB10(this); + break; + case 1: + if (this->field_0x7a.HWORD <= this->x.HALF.HI) + sub_0802BB10(this); + break; + case 2: + if (this->field_0x7a.HWORD <= this->y.HALF.HI) + sub_0802BB10(this); + break; + case 3: + if (this->field_0x7a.HWORD >= this->x.HALF.HI) + sub_0802BB10(this); + break; + } + } +} + +void sub_0802BAFC(Entity* this) { + if (!sub_080AF038(this)) { + this->action = 1; + } +} + +void sub_0802BB10(Entity* this) { + this->action = 3; + this->nonPlanarMovement = 0xc0; + this->direction = this->direction ^ 0x10; + EnqueueSFX(0x74); +} + +bool32 sub_0802BB2C(Entity* this, u32 param_2) { + Entity* ent = this->collisionLayer == 2 ? &gUnk_0200D654 : &gUnk_02027EB4; + const s8* ptr = &gUnk_080CD3DC[param_2 >> 2]; + return sub_080AE4CC(ent, this->x.HALF.HI + ptr[0], this->y.HALF.HI + ptr[1], 0); +} + +// clang-format off +void (*const gUnk_080CD3C4[])(Entity*) = { + sub_0802B9EC, + sub_0802BA18, + sub_0802BA8C, + sub_0802BAFC, +}; + +const u16 gUnk_080CD3D4[] = { + 0x100, 0x180, + 0x200, 0x280, +}; + +const s8 gUnk_080CD3DC[] = { + 0, -12, + 12, 0, + 0, 12, + -12, 0, +}; +// clang-format on diff --git a/src/enemy/slime.c b/src/enemy/slime.c index 42a5d952..29ec7207 100644 --- a/src/enemy/slime.c +++ b/src/enemy/slime.c @@ -1,5 +1,7 @@ #include "global.h" #include "entity.h" +#include "room.h" +#include "functions.h" typedef struct { void* field_0x0; @@ -7,28 +9,30 @@ typedef struct { u8 freezeTime; } EntityHandler; -extern void EnemyFunctionHandler(Entity*, void*); -extern void SetChildOffset(Entity*, u32, u32, u32); -extern void sub_0804AA30(Entity*, void*); -extern void sub_0804A9FC(Entity*, u32); +typedef struct { + s8 h, v; +} PACKED PosOffset; + +void sub_08044FF8(Entity*); +void sub_08045178(Entity*, Entity*, int, int); + extern void sub_0804A720(Entity*); -extern void sub_08044FF8(Entity*); -extern u32 Random(void); extern u32 sub_0806FA04(u32, u32); extern u32 sub_08049FA0(Entity*); extern u32 sub_08049EE4(Entity*); -extern u32 sub_080AEF88(void); +extern void sub_0804A4E4(Entity*, Entity*); +extern u32 sub_080002CC(Entity*, s32, s32); -extern void (*gUnk_080D16BC[])(Entity*); -extern void (*gUnk_080D16A4[])(Entity*); +extern void (*const gUnk_080D16BC[])(Entity*); +extern void (*const gUnk_080D16A4[])(Entity*); +extern u8 gUnk_080D16D0[4]; // Entity count per form +extern PosOffset gUnk_080D16D4[4]; -extern u8 gUnk_080D16D0; +extern u8 gEntCount; extern EntityHandler gUnk_03003DB8; -void Slime(Entity* this) - -{ - EnemyFunctionHandler(this, &gUnk_080D16A4); +void Slime(Entity* this) { + EnemyFunctionHandler(this, gUnk_080D16A4); SetChildOffset(this, 0, 1, -12); } @@ -40,7 +44,7 @@ void sub_08044F88(Entity* this) { if ((this->currentHealth != 0) && (this->cutsceneBeh.HALF.LO != this->currentHealth)) { this->action = 4; } else { - sub_0804AA30(this, &gUnk_080D16A4); + sub_0804AA30(this, gUnk_080D16A4); } if (this->field_0x43 != 0) { @@ -61,32 +65,21 @@ void sub_08044FC8(Entity* this) { } void sub_08044FF8(Entity* this) { - u32 bVar1; - this->action = 2; - bVar1 = Random(); - this->actionDelay = (bVar1 & 31) + 30; + this->actionDelay = (Random() & 31) + 30; this->cutsceneBeh.HALF.LO = this->currentHealth; } void sub_08045018(Entity* this) { - u32 cVar1; - u32 param3; - u32 iVar3; - u32 randValue; - GetNextFrame(this); - param3 = this->actionDelay -= 1; - if (param3 == 0) { + if (--this->actionDelay == 0) { this->action = 3; this->actionDelay = 1; if (0 < this->nonPlanarMovement) { this->actionDelay = sub_0806FA04(4096, this->nonPlanarMovement) >> 8; } - iVar3 = sub_08049FA0(this); - if ((iVar3 == 0) && (randValue = Random(), (randValue & 3) != 0)) { - cVar1 = sub_08049EE4(this); - this->direction = (cVar1 + 0xfc + (Random() & 8)) & 24; + if (sub_08049FA0(this) == 0 && (Random() & 3)) { + this->direction = (sub_08049EE4(this) + 0xfc + (Random() & 8)) & 24; return; } this->direction = Random() & 24; @@ -94,74 +87,65 @@ void sub_08045018(Entity* this) { } void sub_08045088(Entity* this) { - u8 bVar1; - - sub_080AEF88(); + ProcessMovement(this); GetNextFrame(this); - bVar1 = this->actionDelay -= 1; - if (bVar1 == 0) { + if (--this->actionDelay == 0) { this->action = 1; } } -#ifdef NON_MATCHING -void sub_080450A8(Entity* this) - -{ - u8 bVar1; - u32 uVar2; - s32 iVar3; - s32 iVar4; - Entity* pEVar5; - Entity** ppEVar6; - s32 dividend; - u32 uVar7; - Entity* local_r6_72; - u32 divisor; - u8* pcVar8; - Entity* local_2c[4]; - - ppEVar6 = local_2c; - bVar1 = (&gUnk_080D16D0)[(this->entityType).form]; - divisor = (u32)bVar1; - if ((int)gUnk_03003DB8.entityCount < (int)(72 - divisor)) { - uVar7 = divisor; - if (bVar1 != 0) { - do { - uVar2 = CreateEnemy(87, this->entityType.form); - *ppEVar6 = uVar2; - ppEVar6 = ppEVar6 + 1; - uVar7 = uVar7 - 1; - } while (uVar7 != 0); - } - pcVar8 = "\x06"; - iVar4 = 0; - if (bVar1 != 0) { - do { - local_r6_72 = local_2c[iVar4]; - dividend = iVar4 + 1; - iVar3 = Div(dividend, divisor); - local_r6_72->attachedEntity = local_2c[iVar3]; - iVar4 = Div(iVar4 + divisor + -1, divisor); - local_r6_72->parent = local_2c[iVar4]; - (local_r6_72->entityType).parameter = 1; - local_r6_72->height.WORD = 0; - local_r6_72->hurtBlinkTime = 240; - sub_08045178(this, local_r6_72, *pcVar8, pcVar8[1]); - pcVar8 = pcVar8 + 2; - iVar4 = dividend; - } while (dividend < divisor); - } - pEVar5 = CreateFx(this, 2, 0); - if (pEVar5 != NULL) { - CopyPosition(this, pEVar5); - } - DeleteEnemy(this); +/* Split slime into new ones */ +void sub_080450A8(Entity* this) { + Entity* entities[4]; + Entity* ent; + s32 count, i; + PosOffset* off; + + /* Can we create enough new entities? */ + count = gUnk_080D16D0[this->entityType.form]; + if (72 - count <= gEntCount) + return; + + /* Create 2-4 new MiniSlime */ + for (i = 0; i < count; i++) + entities[i] = CreateEnemy(0x57, this->entityType.form); + + off = gUnk_080D16D4; + for (i = 0; i < count; i++) { + ent = entities[i]; + ent->attachedEntity = entities[(i + 1) % count]; + ent->parent = entities[(i + count - 1) % count]; + ent->entityType.parameter = 1; + ent->height.HALF.HI = 0; + ent->hurtBlinkTime = -0x10; + + /* Set MiniSlime offset relative to killed slime. */ + sub_08045178(this, ent, off->h, off->v); + off++; } + + ent = CreateFx(this, 2, 0); + if (ent) + CopyPosition(this, ent); + + DeleteEntity(this); } -#else -NAKED -void sub_080450A8(Entity* this) { - asm(".include \"asm/non_matching/slime/sub_080450A8.inc\""); + +void sub_08045178(Entity* this, Entity* child, int h, int v) { + int x, y; + + if (child == NULL) + return; + + sub_0804A4E4(this, child); + if (sub_080002CC(child, h, v)) + return; + + x = child->x.HALF.HI + h; + if (0 <= x && x < (gRoomControls.roomOriginX + gRoomControls.width)) + child->x.HALF.HI = x; + + y = child->y.HALF.HI + v; + if (0 <= y && y < (gRoomControls.roomOriginY + gRoomControls.height)) + child->y.HALF.HI = y; } -#endif diff --git a/src/enemy/sluggula.c b/src/enemy/sluggula.c new file mode 100644 index 00000000..e11170bb --- /dev/null +++ b/src/enemy/sluggula.c @@ -0,0 +1,226 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern s32 sub_080012DC(Entity*); +bool32 PlayerInRange(Entity*, u32, u32); + +void sub_08023E10(Entity*); +void sub_08023E54(Entity*); +void sub_08023E9C(Entity*); +void sub_0804A4E4(Entity*, Entity*); + +extern void (*const gUnk_080012C8[])(Entity*); + +extern void (*const gUnk_080CBDBC[])(Entity*); +extern void (*const gUnk_080CBDD4[])(Entity*); +extern void (*const gUnk_080CBDEC[])(Entity*); + +extern const s8 gUnk_080CBDF4[]; +extern const s8 gUnk_080CBDF7[]; +extern const s8 gUnk_080CBDFF[]; + +void Sluggula(Entity* this) { + if (this->entityType.form == 1) { + EnemyFunctionHandler(this, gUnk_080CBDBC); + + SetChildOffset(this, 0, 1, -0x10); + } else if (this->entityType.form == 0) { + if (this->height.HALF.HI == 0) { + u32 idx = sub_080012DC(this); + if (idx != 0) { + gUnk_080012C8[idx](this); + return; + } + } + gUnk_080CBDD4[GetNextFunction(this)](this); + + SetChildOffset(this, 0, 1, -0x10); + } else { + sub_08023E10(this); + } +} + +void sub_08023C08(Entity* this) { + gUnk_080CBDEC[this->action](this); +} + +void sub_08023C20(Entity* this) { + if (this->field_0x43) + sub_0804A9FC(this, 0x1c); + + if (this->entityType.form == 1) { + sub_0804AA30(this, gUnk_080CBDBC); + } else { + sub_0804AA30(this, gUnk_080CBDD4); + } +} + +void nullsub_137(Entity* this) { + /* ... */ +} + +void sub_08023C5C(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->actionDelay = (Random() & 0x30) + 0xb4; + this->direction = DirectionRound(Random()); + this->animationState = this->direction >> 3; + InitializeAnimation(this, this->animationState); +} + +void sub_08023C8C(Entity* this) { + ProcessMovement(this); + GetNextFrame(this); + sub_08023E54(this); + if (--this->actionDelay == 0) { + if (this->frames.all != 1) { + this->actionDelay = 8; + } else { + this->actionDelay = (Random() & 0x30) + 0xb4; + sub_08023E9C(this); + this->animationState = this->direction >> 3; + InitializeAnimation(this, this->animationState); + } + } +} + +void sub_08023CE0(Entity* this) { + switch (this->action) { + case 0: + sub_0804A720(this); + if (this->entityType.parameter == 1) { + this->action = 2; + if (this->actionDelay == 0) { + this->actionDelay = 1; + } + this->spriteSettings.b.draw = 3; + } else { + this->action = 1; + } + this->height.HALF.HI = -0x80; + this->spriteRendering.b3 = 1; + this->spriteOrientation.flipY = 1; + InitializeAnimation(this, 6); + break; + case 1: + if (PlayerInRange(this, 1, 0x20)) { + this->action = 2; + if (this->actionDelay == 0) { + this->actionDelay = 8; + } + this->spriteSettings.b.draw = 3; + } + break; + case 2: + if (this->actionDelay != 0) { + if (--this->actionDelay == 0) { + EnqueueSFX(0x12d); + InitializeAnimation(this, 4); + } + } else if (!sub_08003FC4(this, 0x1800)) { + this->action = 3; + this->spriteSettings.b.draw = 1; + EnqueueSFX(0x84); + UpdateSpriteForCollisionLayer(this); + } + break; + default: + GetNextFrame(this); + if (this->frames.all) { + if (this->frames.all & 0x80) { + Entity* ent = CreateEnemy(0x10, 1); + if (ent) { + sub_0804A4E4(this, ent); + DeleteThisEntity(); + } + } else { + this->y.HALF.HI += gUnk_080CBDF4[this->frames.all - 1]; + this->frames.all = 0; + } + } + break; + } +} + +void sub_08023E10(Entity* this) { + if (this->action == 0) { + this->action = 1; + this->spritePriority.b0 = 6; + InitializeAnimation(this, 5); + } + + GetNextFrame(this); + if (this->frames.all & 0x80) + DeleteEntity(this); +} + +void sub_08023E54(Entity* this) { + Entity* ent; + + if (this->field_0xf++ > 27) { + this->field_0xf = 0; + ent = CreateEnemy(0x10, 2); + if (ent) { + const s8* ptr = &gUnk_080CBDF7[this->animationState * 2]; + PositionRelative(this, ent, ptr[0] << 0x10, ptr[1] << 0x10); + } + } +} + +extern Entity* gUnk_020000B0; + +void sub_08023E9C(Entity* this) { + u32 uVar3 = Random(); + if (sub_08049FA0(this) == 0 && (uVar3 & 1)) { + this->direction = DirectionRoundUp(sub_08049EE4(this)); + } else if (sub_08049FDC(this, 1) && (uVar3 & 6)) { + u32 uVar3 = GetFacingDirection(this, gUnk_020000B0) - this->direction; + if (uVar3 != 0 && ((uVar3 + 4) & 0x1f) > 8) { + if ((uVar3 & 0x1f) < 0x10) { + this->direction = DirectionRound(this->direction + 8); + } else { + this->direction = DirectionRound(this->direction - 8); + } + } + } else { + this->direction = DirectionRound(this->direction + gUnk_080CBDFF[(s32)(uVar3 >> 4) % 3]); + } +} + +// clang-format off +void (*const gUnk_080CBDBC[])(Entity*) = { + sub_08023C08, + sub_08023C20, + sub_08001324, + sub_0804A7D4, + sub_08001242, + nullsub_137, +}; + +void (*const gUnk_080CBDD4[])(Entity*) = { + sub_08023CE0, + sub_08023C20, + sub_08001324, + sub_0804A7D4, + sub_08001242, + nullsub_137, +}; + +void (*const gUnk_080CBDEC[])(Entity*) = { + sub_08023C5C, + sub_08023C8C, +}; + +const s8 gUnk_080CBDF4[] = { + 1, 2, 6, +}; + +const s8 gUnk_080CBDF7[] = { + 0, 2, -2, 2, 0, -2, 2, 2 +}; + +const s8 gUnk_080CBDFF[] = { + 0, -8, 8, +}; +// clang-format on diff --git a/src/enemy/spark.c b/src/enemy/spark.c new file mode 100644 index 00000000..9299c856 --- /dev/null +++ b/src/enemy/spark.c @@ -0,0 +1,140 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern void (*const gUnk_080CD234[])(Entity*); +extern void (*const gUnk_080CD24C[])(Entity*); + +void Spark(Entity* this) { + gUnk_080CD234[GetNextFunction(this)](this); +} + +void sub_0802B2C8(Entity* this) { + gUnk_080CD24C[this->action](this); +} + +void sub_0802B2E0(Entity* this) { + Entity* ent; + + if (this->bitfield & 0x80) { + if ((this->bitfield & 0x7f) == 0x14) { + this->flags &= ~0x80; + this->hurtBlinkTime = 0; + this->spriteSettings.b.draw = 0; + this->action = 2; + ent = CreateFx(this, 2, 0); + if (ent) { + this->attachedEntity = ent; + this->actionDelay = 14; + CopyPosition(this, ent); + } + } + } +} + +void nullsub_15(Entity* this) { + /* ... */ +} + +void sub_0802B33C(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->direction = (this->entityType).parameter; + this->field_0xf = 0x78; + InitializeAnimation(this, 0); +} + +void sub_0802B35C(Entity* this) { + bool32 is_head; + + GetNextFrame(this); + ProcessMovement(this); + is_head = this->entityType.form == 0; + if (this->collisions == 0) { + if (--this->field_0xf == 0) { + this->field_0xf = 0x78; + + this->direction += is_head ? 0x08 : 0x18; + this->direction = DirectionRound(this->direction); + } + } else { + this->field_0xf = 0x78; + switch (DirectionRound(this->direction)) { + case DirectionNorth: + if (this->collisions & 0xe) { + this->direction = is_head ? DirectionWest : DirectionEast; + } else { + if ((this->collisions & 0xe000) == 0x4000 && is_head) { + this->direction = DirectionEast; + } + if ((this->collisions & 0xe00) == 0x400 && !is_head) { + this->direction = DirectionWest; + } + } + break; + case DirectionSouth: + if (this->collisions & 0xe0) { + this->direction = is_head ? DirectionEast : DirectionWest; + } else { + if ((this->collisions & 0xe000) == 0x2000 && !is_head) { + this->direction = DirectionEast; + } + if ((this->collisions & 0xe00) == 0x200 && is_head) { + this->direction = DirectionWest; + } + } + break; + case DirectionWest: + if (this->collisions & 0xe00) { + this->direction = is_head ? DirectionSouth : DirectionNorth; + } else { + if ((this->collisions & 0xe) == 4 && is_head) { + this->direction = DirectionNorth; + } + if ((this->collisions & 0xe0) == 0x40 && !is_head) { + this->direction = DirectionSouth; + } + } + break; + case DirectionEast: + if (this->collisions & 0xe000) { + this->direction = is_head ? DirectionNorth : DirectionSouth; + } else { + if ((this->collisions & 0xe) == 2 && !is_head) { + this->direction = DirectionNorth; + } + if ((this->collisions & 0xe0) == 0x20 && is_head) { + this->direction = DirectionSouth; + } + } + break; + } + } +} + +void sub_0802B4A8(Entity* this) { + if (--this->actionDelay == 0) { + Entity* ent = CreateObjectWithParent(this, 0, 0x60, 0); + if (ent) { + ent->y.HALF.HI -= 4; + } + DeleteEntity(this); + } +} + +// clang-format off +void (*const gUnk_080CD234[])(Entity*) = { + sub_0802B2C8, + sub_0802B2E0, + sub_08001324, + sub_0804A7D4, + sub_08001242, + nullsub_15, +}; + +void (*const gUnk_080CD24C[])(Entity*) = { + sub_0802B33C, + sub_0802B35C, + sub_0802B4A8, +}; +// clang-format on diff --git a/src/enemy/spearMoblin.c b/src/enemy/spearMoblin.c new file mode 100644 index 00000000..ad669ed9 --- /dev/null +++ b/src/enemy/spearMoblin.c @@ -0,0 +1,439 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern bool32 sub_0806FC80(Entity*, Entity*, u32); +extern Entity* sub_080A7EE0(u32); +extern Entity* sub_08049DF4(u32); + +void sub_08028604(Entity*); +void sub_08028754(Entity*); +void sub_08028784(Entity*); +void sub_080287E0(Entity*); +void sub_08028728(Entity*); +bool32 sub_080286CC(Entity*); +bool32 sub_080288A4(Entity*); +void sub_08028858(Entity*); +void sub_080288C0(Entity*); +bool32 sub_08028828(u32, u32); +void sub_080287B4(Entity*); + +extern void (*const gUnk_080CC790[])(Entity*); +extern void (*const gUnk_080CC7A8[])(Entity*); +extern const u8 gUnk_080CC7BC[]; +extern const s8 gUnk_080CC7C0[]; +extern const u8 gUnk_080CC7D0[]; +extern const u16 gUnk_080CC7D8[]; + +extern const BoundingBox* const gUnk_080CC944[]; + +void SpearMoblin(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CC790); + SetChildOffset(this, 0, 1, -0x20); + if (this->attachedEntity && this->attachedEntity->next) { + CopyPosition(this, this->attachedEntity); + } +} + +void sub_0802826C(Entity* this) { + gUnk_080CC7A8[this->action](this); +} + +void sub_08028284(Entity* this) { + if (this->field_0x43 != 0) + sub_0804A9FC(this, 0x1c); + + sub_0804AA30(this, gUnk_080CC790); + if (this->bitfield & 0x80) { + if (this->action != 4) { + sub_08028754(this); + } else { + if ((this->bitfield & 0x3f) == 0) { + this->field_0x7a.HALF.LO++; + this->field_0x80.HALF.HI = 0x16; + sub_08028784(this); + } + } + } + + this->attachedEntity->hurtBlinkTime = this->hurtBlinkTime; + if (this->currentHealth == 0) { + this->nonPlanarMovement = 0; + this->field_0x82.HALF.LO = 0; + sub_080287E0(this); + DeleteEntity(this->attachedEntity); + this->attachedEntity = NULL; + } +} + +void nullsub_13(Entity* this) { + /* ... */ +} + +void sub_08028314(Entity* this) { + Entity* pEVar2; + + sub_0804A720(this); + this->action = 1; + this->animationState = 0; + this->field_0x7a.HALF.HI = 0; + this->field_0x80.HALF.LO = 0; + this->field_0x82.HALF.HI = 0; + this->field_0x80.HALF.HI = 0; + this->field_0x7a.HALF.LO = 0; + this->field_0x82.HALF.LO = 1; + + if (this->actionDelay) { + this->animationState = this->entityType.parameter << 1; + this->actionDelay = 0x1e; + this->nonPlanarMovement = 0x80; + this->direction = this->animationState << 2; + sub_080287E0(this); + } else { + this->animationState = 0x10; + sub_08028604(this); + } + + pEVar2 = sub_080A7EE0(3); + if (pEVar2 != NULL) { + pEVar2->parent = this; + this->attachedEntity = pEVar2; + } +} + +void sub_08028378(Entity* this) { + if (this->field_0x80.HALF.HI != 0) { + this->field_0x80.HALF.HI--; + } + + if (--this->actionDelay == 0) { + if (++this->field_0x80.HALF.LO >= 0x10) { + sub_08028728(this); + } else { + sub_08028604(this); + } + } else { + if (sub_080286CC(this)) { + this->field_0x7a.HALF.HI |= 1; + } + if (sub_080288A4(this)) { + sub_0800417E(this, this->collisions); + this->animationState = DirectionRoundUp(this->direction) >> 2; + this->field_0x82.HALF.HI++; + sub_080287E0(this); + } + } + + if (this->field_0xf >= 0xc) { + if (this->field_0x7a.HALF.HI != 0) { + sub_08028754(this); + } + } else { + this->field_0xf++; + } + + sub_08028858(this); +} + +void sub_08028420(Entity* this) { + if (--this->actionDelay == 0) { + this->action = 3; + this->field_0x82.HALF.LO = 0; + this->field_0x80.HALF.LO = 0; + this->animationState = 0x10; + sub_08028604(this); + } else { + if (sub_080286CC(this)) { + this->field_0x7a.HALF.HI |= 1; + } + } + + if (this->field_0xf >= 0xc) { + if (this->field_0x7a.HALF.HI != 0) { + sub_08028754(this); + } + } else { + this->field_0xf++; + } + + sub_08028858(this); +} + +void sub_08028488(Entity* this) { + if (--this->actionDelay == 0) { + switch (this->field_0x82.HALF.LO) { + case 3: + this->action = 4; + this->nonPlanarMovement = 0x180; + this->direction = sub_08049F84(this, 1); + EnqueueSFX(0x11e); + break; + case 2: + this->action = 2; + this->nonPlanarMovement = 0; + this->actionDelay = (Random() & 7) * 3 + 0x40; + break; + case 4: + this->direction = (this->direction + 0x10) & 0x18; + /* fallthrough */ + case 1: + default: + this->action = 1; + this->field_0x82.HALF.LO = 1; + this->nonPlanarMovement = 0x80; + this->actionDelay = (Random() & 7) * 3 + 0x22; + break; + } + + this->field_0xf = 0; + this->animationState = DirectionRoundUp(this->direction) >> 2; + sub_080287E0(this); + } + + sub_08028858(this); +} + +void sub_08028528(Entity* this) { + Entity* ent = sub_08049DF4(1); + const BoundingBox* box; + + if (ent == NULL) { + this->field_0xf = 0; + sub_08028728(this); + } else { + sub_080288C0(this); + box = gUnk_080CC944[this->animationState >> 1]; + this->boundingBox->unknown[0] = box->unknown[0]; + this->boundingBox->unknown[1] = box->unknown[1]; + this->boundingBox->unknown[6] = box->unknown[6]; + this->boundingBox->unknown[7] = box->unknown[7]; + + if (this->field_0x7a.HALF.LO != 0) { + this->field_0x7a.HALF.LO = 0; + this->field_0x80.HALF.HI = 0x16; + sub_08028784(this); + } else { + if (++this->actionDelay == 0x20) { + u32 direction; + this->actionDelay = 0; + direction = GetFacingDirection(this, ent); + if (sub_08028828(this->direction, direction)) { + this->direction = direction; + } + } + + if ((this->actionDelay & 7) == 0) { + EnqueueSFX(0xf0); + CreateFx(this, 2, 0x40); + } + + if (++this->field_0x7a.HALF.HI == 0x80) { + this->field_0x7a.HALF.LO++; + } + } + + if (0x20 < this->field_0x7a.HALF.HI) { + ProcessMovement(this); + } + + GetNextFrame(this); + } +} + +#if NON_MATCHING +void sub_08028604(Entity* this) { + this->field_0xf = 0; + if (this->field_0x82.HALF.LO == 1) { + this->actionDelay = gUnk_080CC7BC[Random() & 3]; + this->nonPlanarMovement = 0x80; + if (sub_08049FA0(this) != 0) { + this->direction = gUnk_080CC7D0[Random() & 7] + 0x18 + this->direction & 0x18; + } else { + u32 iVar3 = sub_08049EE4(this); + u32 uVar1; + if (this->field_0x82.HALF.HI == '\0') { + uVar1 = gUnk_080CC7C0[Random() & 0xf]; + } else { + uVar1 = gUnk_080CC7C0[Random() & 7]; + this->actionDelay = this->actionDelay + 0x10; + this->field_0x82.HALF.HI--; + } + this->direction = iVar3 + uVar1 + 4U & 0x18; + } + } else { + this->actionDelay = 0xc; + this->nonPlanarMovement = 0; + } + + if (this->direction >> 2 != this->animationState) { + this->animationState = this->direction >> 2; + sub_080287E0(this); + } +} +#else +NAKED +void sub_08028604(Entity* this) { + asm(".include \"asm/non_matching/spearMoblin/sub_08028604.inc\""); +} +#endif + +bool32 sub_080286CC(Entity* this) { + if (this->field_0x80.HALF.HI == 0) { + Entity* ent = sub_08049DF4(1); + if (ent != NULL) { + if (this->field_0x82.HALF.LO == 2 && sub_0806FC80(this, ent, 0x30)) + return TRUE; + + if (sub_0806FC80(this, ent, 0x40) && + DirectionRoundUp(GetFacingDirection(this, ent)) >> 2 == this->animationState) + return TRUE; + } + } + + return FALSE; +} + +void sub_08028728(Entity* this) { + this->animationState = DirectionRoundUp(this->direction) >> 2; + this->direction = this->animationState << 2; + this->field_0x82.HALF.HI >>= 1; + sub_080287B4(this); + this->field_0x82.HALF.LO = 2; +} + +void sub_08028754(Entity* this) { + this->direction = sub_08049F84(this, 1); + this->animationState = DirectionRoundUp(this->direction) >> 2; + this->field_0x82.HALF.HI = 0; + sub_080287B4(this); + this->field_0x82.HALF.LO = 3; +} + +void sub_08028784(Entity* this) { + this->animationState = DirectionRoundUp(this->direction) >> 2; + this->direction = this->animationState << 2; + this->field_0x82.HALF.HI = 0; + sub_080287B4(this); + this->actionDelay <<= 1; + this->field_0x82.HALF.LO = 4; +} + +void sub_080287B4(Entity* this) { + this->action = 3; + this->actionDelay = 0x20; + this->field_0xf = 0; + this->field_0x80.HALF.LO = 0; + this->field_0x7a.HALF.HI = 0; + this->nonPlanarMovement = 0; + this->field_0x82.HALF.LO = 0; + sub_080287E0(this); +} + +void sub_080287E0(Entity* this) { + u32 sprite = this->animationState >> 1; + switch (this->field_0x82.HALF.LO) { + case 0: + /* ... */ + break; + case 1: + case 4: + sprite += 4; + break; + case 3: + sprite += 8; + break; + case 2: + sprite += 0xc; + break; + } + InitializeAnimation(this, sprite); +} + +bool32 sub_08028828(u32 arg0, u32 arg1) { + if (DirectionRoundUp(arg1) == DirectionRoundUp(arg0)) { + u32 angle1 = (arg1 + 5) & 7; + u32 angle0 = (arg0 + 5) & 7; + if (angle1 < 3 && angle0 < 3) + return TRUE; + } + + return FALSE; +} + +void sub_08028858(Entity* this) { + const BoundingBox* box; + + sub_080288C0(this); + box = gUnk_080CC944[this->animationState >> 1]; + this->boundingBox->unknown[0] = box->unknown[0]; + this->boundingBox->unknown[1] = box->unknown[1]; + this->boundingBox->unknown[6] = box->unknown[6]; + this->boundingBox->unknown[7] = box->unknown[7]; + + if (this->field_0x82.HALF.LO == 0) { + this->nonPlanarMovement = 0; + } + + ProcessMovement(this); + GetNextFrame(this); +} + +bool32 sub_080288A4(Entity* this) { + return (this->collisions & gUnk_080CC7D8[this->animationState >> 1]) != 0; +} + +void sub_080288C0(Entity* this) { + Entity* ent = this->attachedEntity; + if (ent && (ent->bitfield & 0x80)) { + this->field_0x3e = ent->field_0x3e; + this->hurtBlinkTime = -ent->hurtBlinkTime; + this->field_0x46 = ent->field_0x46; + this->field_0x42 = ent->field_0x42; + ent->field_0x42 = 0; + } +} + +// clang-format off +void (*const gUnk_080CC790[])(Entity*) = { + sub_0802826C, + sub_08028284, + sub_08001324, + sub_0804A7D4, + sub_08001242, + nullsub_13, +}; + +void (*const gUnk_080CC7A8[])(Entity*) = { + sub_08028314, + sub_08028378, + sub_08028420, + sub_08028488, + sub_08028528, +}; + +const u8 gUnk_080CC7BC[] = { + 0x30, 0x60, 0x6C, 0x91, +}; + +const s8 gUnk_080CC7C0[] = { + 0xF8, 0x0C, + 0xF4, 0x08, + 0x04, 0xFA, + 0x06, 0xFC, + 0x00, 0xFD, + 0x01, 0x03, + 0xFF, 0x02, + 0x00, 0xFE, +}; + +const u8 gUnk_080CC7D0[] = { + 0x08, 0x10, + 0x08, 0x00, + 0x10, 0x08, + 0x10, 0x00, +}; + +const u16 gUnk_080CC7D8[] = { + 0xE, 0xE000, 0xE0, 0xE00, +}; +// clang-format on diff --git a/src/enemy/spikedBeetle.c b/src/enemy/spikedBeetle.c new file mode 100644 index 00000000..e1c32ce0 --- /dev/null +++ b/src/enemy/spikedBeetle.c @@ -0,0 +1,238 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern u32 sub_0804A024(Entity*, u32, u32); + +extern Entity* gUnk_020000B0; + +void sub_0802B9B4(Entity*); +void sub_0802B7A4(Entity*); +void sub_0802B960(Entity*); + +extern void (*const gUnk_080CD2D8[])(Entity*); +extern void (*const gUnk_080CD2F0[])(Entity*); +extern const u8 gUnk_080CD314[]; +extern const s8 gUnk_080CD318[]; + +void SpikedBeetle(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CD2D8); + SetChildOffset(this, 0, 1, -0x10); +} + +void sub_0802B610(Entity* this) { + gUnk_080CD2F0[this->action](this); +} + +void sub_0802B628(Entity* this) { + switch (this->bitfield & 0x7f) { + case 0: + case 4: + case 5: + case 6: + case 8: + case 9: + case 10: + case 0xb: + case 0xc: + if (this->action == 4) { + this->actionDelay = 1; + } + break; + case 2: + case 3: + case 0x16: + case 0x18: + case 0x19: + case 0x1a: + case 0x1d: + if (this->action < 6) { + this->action = 6; + this->field_0x20 = 0x18000; + this->nonPlanarMovement = 0xc0; + this->direction = this->field_0x3e; + this->field_0x42 = 0; + this->hurtBlinkTime = -8; + this->damageType = 100; + InitializeAnimation(this, 9); + } + } + if (this->field_0x43) { + sub_0804A9FC(this, 0x1c); + } + sub_0804AA30(this, gUnk_080CD2D8); +} + +void nullsub_144(Entity* this) { + /* ... */ +} + +void sub_0802B72C(Entity* this) { + sub_0804A720(this); + this->actionDelay = 1; + this->animationState = 0xff; + sub_0802B7A4(this); +} + +void sub_0802B744(Entity* this) { + u32 direction; + + GetNextFrame(this); + if (sub_08049FDC(this, 1) && (direction = sub_0804A024(this, 1, 0xc), direction != 0xff)) { + this->action = 3; + this->actionDelay = 0x1e; + this->direction = DirectionRound(direction); + InitializeAnimation(this, 8); + } else { + if (--this->actionDelay == 0) { + this->action = 2; + this->actionDelay = 0x1e; + } else { + if (!ProcessMovement(this)) { + this->actionDelay = 1; + } + } + } +} + +void sub_0802B7A4(Entity* this) { + if (--this->actionDelay == 0) { + this->action = 1; + this->actionDelay = gUnk_080CD314[Random() & 3]; + this->nonPlanarMovement = 0x60; + sub_0802B960(this); + if (this->direction != 0xff) { + u32 animation = this->direction >> 3; + if (animation != this->animationState) { + this->animationState = animation & 3; + InitializeAnimation(this, animation); + } + } + } +} + +void sub_0802B7FC(Entity* this) { + GetNextFrame(this); + if (--this->actionDelay == 0) { + this->action = 4; + this->actionDelay = 0x78; + this->nonPlanarMovement = 0x1c0; + } +} + +void sub_0802B820(Entity* this) { + if (!sub_080AEFE0(this)) { + this->actionDelay = 1; + } + GetNextFrame(this); + if (--this->actionDelay == 0) { + sub_0802B9B4(this); + } else if (sub_08049FDC(this, 1)) { + if ((this->actionDelay & 0xf) == 0) { + sub_08004596(this, GetFacingDirection(this, gUnk_020000B0)); + } + } else { + sub_0802B9B4(this); + } +} + +void sub_0802B880(Entity* this) { + if (--this->actionDelay == 0) { + this->action = 2; + this->actionDelay = 0x3c; + this->animationState = DirectionToAnimationState(this->direction); + InitializeAnimation(this, this->animationState); + } +} + +void sub_0802B8B0(Entity* this) { + sub_080AEFE0(this); + switch (sub_080044EC(this, 0x1800)) { + case 0: + this->action = 7; + this->actionDelay = 0x96; + /* fallthrough */ + case 1: + EnqueueSFX(299); + break; + } +} + +void sub_0802B8E0(Entity* this) { + if (--this->actionDelay) { + if (this->actionDelay < 0x3c && (this->actionDelay & 1)) { + this->spriteOffsetX += gUnk_080CD318[(this->actionDelay >> 1) & 3]; + } + } else { + this->action = 8; + this->field_0x20 = 0x10000; + this->nonPlanarMovement = 0x60; + this->damageType = 99; + InitializeAnimation(this, this->animationState); + EnqueueSFX(299); + } +} + +void sub_0802B948(Entity* this) { + if (!sub_08003FC4(this, 0x1800)) { + this->action = 1; + this->actionDelay = 1; + } +} + +void sub_0802B960(Entity* this) { + if (sub_08049FDC(this, 1)) { + if ((Random() & 7) == 0) { + this->direction = DirectionRoundUp(sub_08049F84(this, 1)); + return; + } + } else if (!sub_08049FA0(this)) { + if ((Random() & 3) == 0) { + this->direction = DirectionRoundUp(sub_08049EE4(this)); + return; + } + } + + this->direction = DirectionRound(Random()); +} + +void sub_0802B9B4(Entity* this) { + this->action = 5; + this->actionDelay = 0x3c; + this->animationState = (this->direction >> 3) & 3; + InitializeAnimation(this, this->animationState + 4); +} + +// clang-format off +void (*const gUnk_080CD2D8[])(Entity*) = { + sub_0802B610, + sub_0802B628, + sub_08001324, + sub_0804A7D4, + sub_08001242, + nullsub_144, +}; + +void (*const gUnk_080CD2F0[])(Entity*) = { + sub_0802B72C, + sub_0802B744, + sub_0802B7A4, + sub_0802B7FC, + sub_0802B820, + sub_0802B880, + sub_0802B8B0, + sub_0802B8E0, + sub_0802B948, +}; + +const u8 gUnk_080CD314[] = { + 0x30, + 0x48, + 0x60, + 0x78, +}; + +const s8 gUnk_080CD318[] = { + 1, -1, -1, 1, +}; +// clang-format on diff --git a/src/enemy/spinyChuchu.c b/src/enemy/spinyChuchu.c new file mode 100644 index 00000000..273ed695 --- /dev/null +++ b/src/enemy/spinyChuchu.c @@ -0,0 +1,285 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +extern void sub_08001318(Entity*); +extern u32 PlayerInRange(Entity*, u32, u32); +extern void sub_0804A4E4(Entity*, Entity*); +extern void sub_0804AA1C(Entity*); + +u32 sub_080228CC(Entity*); +u32 sub_080228F0(Entity*); + +extern void (*const gUnk_080CBA28[])(Entity*); +extern void (*const gUnk_080CBA40[])(Entity*); + +extern const u8 gUnk_080CBA60[]; + +extern BoundingBox gUnk_080FD468; +extern BoundingBox gUnk_080FD470; + +extern Entity* gUnk_020000B0; + +void SpinyChuchu(Entity* this) { + EnemyFunctionHandler(this, gUnk_080CBA28); + SetChildOffset(this, 0, 1, -0x10); +} + +void sub_08022434(Entity* this) { + gUnk_080CBA40[this->action](this); +} + +void sub_0802244C(Entity* this) { + if (this->currentHealth) { + if (this->damageType == 0x65) { + switch (this->bitfield & 0x7f) { + case 2: + case 3: + this->action = 2; + this->field_0xf = 0x3c; + this->damageType = 0x5c; + this->boundingBox = &gUnk_080FD468; + InitializeAnimation(this, 0); + break; + case 8: + case 9: + case 10: + case 0xb: + case 0xc: + case 0x16: + case 0x18: + case 0x19: + case 0x1a: + sub_0804A9FC(this, 0x1c); + this->action = 5; + this->damageType = 0x5c; + InitializeAnimation(this, 1); + } + } else if (this->bitfield == 0x94) { + sub_0804A9FC(this, 0x1c); + this->action = 5; + InitializeAnimation(this, 1); + } + + if (this->field_0x80.HALF.LO != this->currentHealth) { + this->action = 5; + this->damageType = 0x5c; + InitializeAnimation(this, 1); + } else { + if (this->action == 3) { + this->action = 4; + InitializeAnimation(this, 3); + EnqueueSFX(0x194); + } + } + } else { + InitializeAnimation(this, 1); + } + + this->field_0x80.HALF.LO = this->currentHealth; + sub_0804AA30(this, gUnk_080CBA28); +} + +void sub_080225A0(Entity* this) { + if (this->animIndex == 1) + GetNextFrame(this); + sub_08001318(this); +} + +void sub_080225BC(Entity* this) { + sub_08003FC4(this, 0x1800); + if (this->frames.all & 1) { + sub_0804A7D4(this); + } else { + GetNextFrame(this); + } +} + +void nullsub_9(Entity* this) { +} + +void sub_080225EC(Entity* this) { + sub_0804A720(this); + this->field_0x80.HALF.LO = this->currentHealth; + this->field_0x80.HALF.HI = 0x5a; + if (this->actionDelay == 0) { + this->action = 2; + InitializeAnimation(this, 0); + } else { + this->action = 1; + this->field_0xf = 0x3c; + this->spriteSettings.b.draw = 3; + this->spriteRendering.b3 = 1; + this->spriteOrientation.flipY = 1; + this->height.HALF.HI = -0x80; + InitializeAnimation(this, 6); + } +} + +void sub_08022654(Entity* this) { + switch (this->previousActionFlag) { + case 0: + if (--this->field_0xf) + return; + this->previousActionFlag = 1; + PlaySFX(0x12d); + InitializeAnimation(this, 0); + /* fallthrough */ + case 1: + if (sub_08003FC4(this, 0x1800)) + return; + + this->previousActionFlag = 2; + this->spriteSettings.b.draw = 1; + InitializeAnimation(this, 5); + EnqueueSFX(0x7d); + UpdateSpriteForCollisionLayer(this); + /* fallthrough */ + case 2: + GetNextFrame(this); + if (--this->actionDelay == 0) { + this->action = 3; + this->damageType = 0x65; + InitializeAnimation(this, 2); + } + break; + } +} + +void sub_080226EC(Entity* this) { + if (sub_08049FDC(this, 1)) { + if (sub_080228CC(this)) { + this->action = 3; + this->damageType = 0x65; + InitializeAnimation(this, 2); + return; + } + + if (sub_080228F0(this)) { + this->action = 6; + this->field_0x20 = 0x12000; + this->nonPlanarMovement = 0x140; + this->direction = GetFacingDirection(this, gUnk_020000B0); + this->damageType = 0x5a; + InitializeAnimation(this, 4); + return; + } + + if ((this->actionDelay++ & 7) == 0) { + this->direction = sub_08049F84(this, 1); + } + + ProcessMovement(this); + } + + GetNextFrame(this); +} + +void sub_08022780(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 4; + InitializeAnimation(this, 3); + EnqueueSFX(0x194); + } +} + +void sub_080227AC(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 1) { + this->boundingBox = &gUnk_080FD470; + } else { + this->boundingBox = &gUnk_080FD468; + } + + if (this->frames.all & 2) { + this->frames.all &= ~2; + this->damageType = 0x5c; + } + + if (this->frames.all & 0x80) { + this->action = 2; + this->field_0xf = gUnk_080CBA60[Random() & 3]; + InitializeAnimation(this, 0); + } +} + +void sub_0802281C(Entity* this) { + sub_08003FC4(this, 0x1800); + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 2; + this->nonPlanarMovement = 0x20; + InitializeAnimation(this, 0); + sub_0804AA1C(this); + } +} + +void sub_08022854(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 1) { + sub_080AEFE0(this); + if (sub_08003FC4(this, 0x1800) == 0) { + this->action = 7; + this->damageType = 0x5c; + InitializeAnimation(this, 5); + EnqueueSFX(0x7d); + } + } +} + +void sub_0802289C(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + this->action = 2; + this->nonPlanarMovement = 0x20; + this->field_0x80.HALF.HI = 0x78; + InitializeAnimation(this, 0); + } +} + +u32 sub_080228CC(Entity* this) { + if (this->field_0xf == 0) { + if (PlayerInRange(this, 1, 0x28)) + return 1; + } else { + this->field_0xf--; + } + return 0; +} + +u32 sub_080228F0(Entity* this) { + if (this->field_0x80.HALF.HI == 0) { + if (PlayerInRange(this, 1, 0x40)) + return 1; + } else { + this->field_0x80.HALF.HI--; + } + return 0; +} + +// clang-format off +void (*const gUnk_080CBA28[])(Entity*) = { + sub_08022434, + sub_0802244C, + sub_080225A0, + sub_080225BC, + sub_08001242, + nullsub_9, +}; + +void (*const gUnk_080CBA40[])(Entity*) = { + sub_080225EC, + sub_08022654, + sub_080226EC, + sub_08022780, + sub_080227AC, + sub_0802281C, + sub_08022854, + sub_0802289C, +}; + +const u8 gUnk_080CBA60[] = { + 10, 20, 30, 20, +}; +// clang-format on diff --git a/src/enemy/tektite.c b/src/enemy/tektite.c index 04999029..f2eeee55 100644 --- a/src/enemy/tektite.c +++ b/src/enemy/tektite.c @@ -113,7 +113,7 @@ void sub_0802F300(Entity* this) { u32 rand; GetNextFrame(this); - sub_080AEF88(this); + ProcessMovement(this); temp = this->height.HALF.HI; rand = Random() & 0xf; diff --git a/src/enemy/tektiteGolden.c b/src/enemy/tektiteGolden.c index 5245ff95..e09309eb 100644 --- a/src/enemy/tektiteGolden.c +++ b/src/enemy/tektiteGolden.c @@ -100,7 +100,7 @@ void sub_08038048(Entity* this) { u32 rand; UpdateAnimationVariableFrames(this, 2); - sub_080AEF88(this); + ProcessMovement(this); temp = this->height.HALF.HI; rand = Random() & 0xf; diff --git a/src/enemy/treeItem.c b/src/enemy/treeItem.c new file mode 100755 index 00000000..24cd16bb --- /dev/null +++ b/src/enemy/treeItem.c @@ -0,0 +1,98 @@ +#include "global.h" +#include "enemy.h" +#include "entity.h" +#include "functions.h" + +static bool32 ShouldSpawnTreeItem(Entity*); + +extern u32 sub_080028F4(const u8*); +extern void sub_08049CF4(Entity*); + +extern const u8 gUnk_080D29E0[][16]; +extern const u8 gUnk_080D2AB0[]; + +void TreeItem(Entity* this) { + Entity* itemEntity; + int var0; + + if (this->action == 0) { + this->action++; + this->field_0x68.HALF.LO = sub_080028F4(gUnk_080D29E0[this->entityType.form]); + if (this->field_0x68.HALF.LO > 8) { + DeleteThisEntity(); + } + + if (this->field_0x68.HALF.LO < 8 && GetInventoryValue(0x67) == 0) { + this->field_0x68.HALF.LO = 8; + } + } + + if (!ShouldSpawnTreeItem(this)) { + return; + } + + var0 = this->field_0x68.HALF.LO; + if (var0 >= 0) { + if (var0 > 7) { + if (var0 == 8) { + itemEntity = CreateObject(0x40, 0x60, 0); + if (itemEntity) { + itemEntity->actionDelay = 0; + CopyPosition(this, itemEntity); + } + } + } else { + itemEntity = CreateObject(0x96, 0x7, gUnk_080D2AB0[var0]); + if (itemEntity) { + CopyPosition(this, itemEntity); + itemEntity->y.HALF.HI += 16; + itemEntity->height.HALF.HI = -32; + } + } + } + + sub_08049CF4(this); + DeleteThisEntity(); +} + +static bool32 ShouldSpawnTreeItem(Entity* this) { + int diff; + int expectedStateX, expectedStateY; + int playerState; + + if (gPlayerEntity.action != 0x6) { + return FALSE; + } + + diff = gPlayerEntity.x.HALF.HI - this->x.HALF.HI; + expectedStateX = 6; + if (diff & 0x8000) { + expectedStateX = 2; + } + + diff += 40; + if ((u16)diff >= 80) { + return FALSE; + } + + diff = gPlayerEntity.y.HALF.HI - this->y.HALF.HI; + expectedStateY = 0; + if (diff & 0x8000) { + expectedStateY = 4; + } + + diff += 40; + if ((u16)diff >= 80) { + return FALSE; + } + + playerState = gPlayerEntity.animationState; + if ((playerState == 0 && expectedStateY == 0) || + (playerState == 4 && expectedStateY == 4) || + (playerState == 6 && expectedStateX == 6) || + (playerState == 2 && expectedStateX == 2)) { + return TRUE; + } + + return FALSE; +} diff --git a/src/enemy/vaatiBall.c b/src/enemy/vaatiBall.c new file mode 100644 index 00000000..fcbc04f3 --- /dev/null +++ b/src/enemy/vaatiBall.c @@ -0,0 +1,503 @@ +#include "entity.h" +#include "player.h" +#include "functions.h" +#include "screen.h" + +typedef struct { + s8 h, v; +} PACKED PosOffset; + +extern void (*const gUnk_080D1604[])(Entity*); +extern PosOffset gUnk_080D1620[4]; + +extern void sub_08044E74(Entity*, u32); + +void VaatiBall(Entity* this) { + Entity* parent; + + parent = this->parent; + if (this->action && this->action != 3) { + this->x.WORD += parent->x.WORD - *(int*)&parent->field_0x78; + this->y.WORD += parent->y.WORD - parent->field_0x7c.WORD; + } + + gUnk_080D1604[this->action](this); + + if (this->cutsceneBeh.HALF.LO) { + this->currentHealth = -1; + } + + if (this->bitfield & 0x80) { + if ((this->bitfield & 0x3f) == 0 && this->action == 6) { + ModHealth(-2); + } + + if (this->currentHealth < 0xfd) { + this->spriteSettings.b.draw = 0; + this->flags &= 0x7f; + this->currentHealth = -1; + parent->field_0x80.HALF.LO--; + CreateDust(this); + PlaySFX(0x1c3); + } + } +} + +void sub_0804468C(Entity* this) { + PosOffset* off; + + this->collisionLayer = 3; + this->spriteRendering.b3 = 2; + this->spritePriority.b0 = 5; + this->cutsceneBeh.HALF.LO = 0; + switch (this->entityType.form) { + case 0: + this->action = 1; + this->actionDelay = 1; + this->direction = (this->field_0x78.HALF.HI * 8) & 0x1f; + this->field_0x78.HALF.LO = 0; + this->field_0x82.HALF.HI = 0; + this->spriteSettings.b.draw = 0; + off = &gUnk_080D1620[this->field_0x78.HALF.HI & 3]; + PositionRelative(this->parent, this, off->h << 0x10, (off->v - 0x10) * 0x10000); + this->height.HALF.HI = this->parent->height.HALF.HI; + InitAnimationForceUpdate(this, 0); + break; + case 1: + this->action = 3; + this->field_0x74.HALF.LO = 0; + this->field_0x82.HALF.HI = 1; + this->spriteSettings.b.draw = 1; + InitAnimationForceUpdate(this, 1); + break; + } +} + +void sub_0804474C(Entity* this) { + switch (this->parent->action) { + case 3: + this->action = 3; + this->field_0x74.HALF.LO = 0; + this->actionDelay = 0; + break; + case 5: + this->action = 5; + this->field_0x74.HALF.LO = 0; + this->field_0xf = 1; + break; + case 6: + this->action = 6; + this->field_0x74.HALF.LO = 0; + this->field_0xf = 32; + break; + case 2: + this->action = 2; + this->field_0x74.HALF.LO = 0; + this->damageType = 0; + break; + } + + if (this->action != 1) { + UpdateAnimationSingleFrame(this); + } else { + if (--this->actionDelay == 0) { + this->actionDelay = 2; + this->direction++; + this->direction &= 0x1f; + } + sub_0806F69C(this); + UpdateAnimationSingleFrame(this); + } +} + +void sub_080447E0(Entity* this) { + Entity* vaati = this->parent; + + if (vaati->action == 1) { + this->action = 1; + this->damageType = 43; + sub_08044E74(this, 0); + if (this->flags & 0x80) + this->spriteSettings.b.draw = 1; + } else { + this->field_0x76.HALF.HI++; + this->field_0x76.HALF.HI &= 7; + if (this->flags & 0x80) { + if (this->field_0x76.HALF.HI & 1) { + this->spriteSettings.b.draw = 1; + } else { + this->spriteSettings.b.draw = 0; + } + } + + if (vaati->field_0x74.HALF.LO == 2) { + sub_08044E74(this, 2); + } + } +} + +extern u32 sub_080045B4(); +extern u32 sub_0806FCB8(Entity*, u32, u32, u32); +extern void sub_08044DEC(); + +void sub_08044868(Entity* this) { + Entity* vaati = this->parent; + + switch (vaati->field_0x74.HALF.LO) { + case 0xfe: + if (this->field_0x82.HALF.HI && this->field_0x74.HALF.LO == 2) + DeleteThisEntity(); + break; + case 0xff: + if (this->field_0x82.HALF.HI) { + switch (this->field_0x74.HALF.LO) { + case 0: + if (this->frames.all & 0x80) { + this->field_0x74.HALF.LO = 1; + this->direction = sub_080045B4(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10); + this->nonPlanarMovement = 0x180; + } + break; + case 1: + sub_0806F69C(this); + if (sub_0806FCB8(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10, 0xc)) { + this->field_0x74.HALF.LO++; + this->x.HALF.HI = vaati->x.HALF.HI; + this->y.HALF.HI = vaati->y.HALF.HI - 0x10; + vaati->actionDelay++; + } else { + this->direction = sub_080045B4(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10); + } + break; + } + } + break; + case 1: + if (this->field_0x82.HALF.HI == 0) { + this->field_0x82.HALF.HI++; + this->spriteSettings.b.draw = 1; + } + sub_08044DEC(this); + if (*(u8*)&vaati->field_0x86 > 1) { + u8 draw = this->spriteSettings.b.draw; + if (draw == 1 && this->cutsceneBeh.HALF.LO == 0) { + vaati = sub_0804A98C(this, 0x18, 0); + if (vaati) { + vaati->entityType.parameter = 1; + vaati->parent = this; + this->cutsceneBeh.HALF.LO = 1; + this->damageType = 0; + } + } + } + this->actionDelay = 32; + break; + case 2: + if (this->actionDelay) + if (--this->actionDelay < 0x11) + sub_0806F69C(this); + break; + case 3: { + u8 draw; + + sub_08044E74(this, 1); + draw = this->spriteSettings.b.draw; + if (draw == 1) { + this->flags |= 0x80; + } else { + this->flags &= 0x7f; + } + break; + } + } + UpdateAnimationSingleFrame(this); +} + +void sub_080449F8(Entity* this) { + Entity* vaati = this->parent; + + UpdateAnimationSingleFrame(this); + if (vaati->action == 1) { + sub_08044E74(this, 0); + return; + } + + switch (vaati->field_0x74.HALF.LO) { + case 0: + sub_0806F69C(this); + if (--this->actionDelay) + break; + + if (this->field_0x78.HALF.LO == 0) { + this->field_0x78.HALF.LO++; + this->nonPlanarMovement = 640; + } + + this->actionDelay = 4; + this->direction++; + this->direction &= 0x1f; + if (vaati->field_0x80.HALF.LO == 0) + vaati->field_0x74.HALF.LO = 1; + break; + case 1: + switch (this->actionDelay) { + case 2: + if (vaati->field_0x80.HALF.LO == 0) { + this->field_0xf = 0; + sub_08044E74(this, 0); + } + break; + case 1: + this->direction = (this->direction + 0x10) & 0x1f; + sub_0806F69C(this); + this->direction = (this->direction + 0x10) & 0x1f; + this->actionDelay = 2; + break; + case 3: + sub_0806F69C(this); + this->actionDelay = 2; + break; + case 4: + sub_0806F69C(this); + sub_0806F69C(this); + this->actionDelay = 2; + break; + } + break; + case 2: + if (this->field_0x74.HALF.LO == 0) { + u8 draw; + + this->field_0x74.HALF.LO++; + draw = this->spriteSettings.b.draw; + if (draw) { + vaati = sub_0804A98C(this, 0x1c, 0); + if (vaati) { + vaati->y.HALF.HI += 4; + vaati->parent = this; + this->attachedEntity = vaati; + } + } + } + break; + case 3: + if (this->field_0xf) { + this->field_0xf = 0; + } + break; + } +} + +void sub_08044B04(Entity* this) { + Entity* vaati = this->parent; + + UpdateAnimationSingleFrame(this); + if (vaati->action == 1) { + sub_08044E74(this, 0); + this->actionDelay = 32; + return; + } + + switch (vaati->field_0x74.HALF.LO) { + case 0: + sub_0806F69C(this); + switch (this->field_0x74.HALF.LO) { + case 0: + if (--this->actionDelay == 0) { + this->actionDelay = this->field_0x78.HALF.LO ? 4 : 2; + this->direction++; + this->direction &= 0x1f; + } + if (--this->field_0xf == 0) { + if (this->actionDelay != 2) { + this->field_0xf = 1; + } else { + if (++this->field_0x78.HALF.LO > 2) { + this->field_0x74.HALF.LO++; + this->field_0x78.HALF.LO = 1; + this->actionDelay = 4; + this->field_0xf = 0; + } else { + this->field_0xf = 32; + } + + this->nonPlanarMovement = this->field_0x78.HALF.LO ? 640 : 1280; + } + } + break; + case 1: + if (--this->actionDelay == 0) { + this->actionDelay = 6; + this->direction = (this->direction + 1) & 0x1f; + if (++this->field_0xf == 0x30) { + u32 direction = sub_080045B4(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10); + this->nonPlanarMovement = 0; + this->direction = (direction + 16) & 0x1f; + this->actionDelay = 16; + this->field_0xf = 16; + this->field_0x74.HALF.LO++; + } + } + break; + case 2: + if (this->field_0xf == 0) { + switch (--this->actionDelay) { + case 12: + this->nonPlanarMovement = 1280; + break; + case 0: + this->field_0x74.HALF.LO++; + this->direction = sub_080045B4(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10); + this->nonPlanarMovement = 0; + this->actionDelay = 4; + this->field_0xf = 16; + break; + case 4: + this->nonPlanarMovement = 640; + break; + } + } else { + if (--this->field_0xf == 0) + this->nonPlanarMovement = 640; + } + break; + case 3: + if (this->field_0xf) { + if (--this->field_0xf == 0) + this->nonPlanarMovement = 640; + } else { + if (this->actionDelay) { + if (--this->actionDelay == 0) { + this->nonPlanarMovement = 1280; + PlaySFX(0x14f); + } + } + if (this->field_0x78.HALF.HI == 3) + if (sub_0806FCB8(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10, 0xc)) + vaati->actionDelay++; + this->direction = sub_080045B4(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10); + return; + } + break; + } + break; + case 1: + switch (this->field_0x74.HALF.LO) { + case 3: + this->field_0x74.HALF.LO = 1; + this->actionDelay = 80; + this->flags &= 0x7f; + PositionRelative(vaati, this, 0, -0x100000); + if (this->field_0xf) + this->spriteSettings.b.draw = 0; + break; + case 1: + if (--this->actionDelay == 0) { + this->field_0x74.HALF.LO = 0; + this->actionDelay = 32; + this->field_0xf = 4; + } + break; + } + break; + case 2: + /* ... */ + break; + case 3: + switch (this->field_0x74.HALF.LO) { + case 0: + if (this->field_0xf) { + if (--this->field_0xf == 0) { + sub_08044DEC(this); + this->field_0x74.HALF.LO = 1; + this->actionDelay = 16; + } + } + break; + case 1: + sub_0806F69C(this); + if (--this->actionDelay == 0) + this->field_0x74.HALF.LO++; + break; + case 2: { + u8 draw; + + sub_08044E74(this, 1); + draw = this->spriteSettings.b.draw; + if (draw == 1) { + this->flags |= 0x80; + } else { + this->flags &= 0x7f; + } + vaati->actionDelay++; + break; + } + } + break; + } +} + +extern u8 gUnk_080D1628[4][4]; + +void sub_08044DEC(Entity* this) { + u32 off; + + if (this->parent->field_0x80.HALF.LO > this->field_0x78.HALF.HI) { + this->spriteSettings.b.draw = 1; + this->currentHealth = -1; + } else { + this->spriteSettings.b.draw = 0; + } + this->flags &= 0x7f; + this->field_0x78.HALF.LO = 0; + this->nonPlanarMovement = 0x300; + off = this->parent->field_0x80.HALF.LO - 1; + this->direction = gUnk_080D1628[off][this->field_0x78.HALF.HI]; + PositionRelative(this->parent, this, 0, -0x100000); +} + +void sub_08044E74(Entity* this, u32 state) { + this->action = 1; + this->field_0x74.HALF.LO = 0; + + switch (state) { + case 2: + this->action = 2; + this->direction += 0x18; + this->direction &= 0x1f; + PositionRelative(this->parent, this, 0, -0x100000); + this->nonPlanarMovement = 12288; + sub_0806F69C(this); + this->direction += 0x8; + this->direction &= 0x1f; + this->nonPlanarMovement = 1280; + sub_0806F69C(this); + break; + case 1: + this->direction = (this->direction + 8) & 0x1f; + break; + case 0: + if (this->field_0x78.HALF.LO) { + switch (this->actionDelay) { + case 3 ... 4: + do { + sub_0806F69C(this); + } while (this->actionDelay-- != 3); + break; + case 1: + this->direction = (this->direction + 0x10) & 0x1f; + sub_0806F69C(this); + this->direction = (this->direction + 0x10) & 0x1f; + break; + } + } else { + if (this->actionDelay == 2) { + sub_0806F69C(this); + } + } + break; + } + this->actionDelay = 1; + this->field_0x78.HALF.LO = 0; + this->nonPlanarMovement = 1280; +} diff --git a/src/enemy/wallMaster.c b/src/enemy/wallMaster.c new file mode 100644 index 00000000..8f359f31 --- /dev/null +++ b/src/enemy/wallMaster.c @@ -0,0 +1,219 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" +#include "area.h" + +extern void sub_08001328(Entity*); +extern Entity* sub_08049DF4(u32); +extern void DoExitTransition(u32*); + +extern u32* gUnk_0813AB1C[]; + +void sub_0802A78C(Entity*); +void sub_0802A7D0(Entity*); + +extern void (*const gUnk_080CD07C[])(Entity*); +extern void (*const gUnk_080CD094[])(Entity*); +extern const s8 gUnk_080CD0B0[]; + +void WallMaster(Entity* this) { + gUnk_080CD07C[GetNextFunction(this)](this); + SetChildOffset(this, 0, 1, -0x10); +} + +void sub_0802A434(Entity* this) { + sub_0802A78C(this); + gUnk_080CD094[this->action](this); +} + +void sub_0802A454(Entity* this) { + if (this->damageType != 0x75 && ((this->bitfield & 0x7f) == 0 || (this->bitfield & 0x7f) == 0x1e)) { + this->action = 5; + this->flags &= ~0x80; + this->field_0x7c.HALF.HI = gPlayerEntity.x.HALF.HI; + this->field_0x80.HWORD = gPlayerEntity.y.HALF.HI; + this->field_0x82.HWORD = gPlayerEntity.height.HALF.HI; + if (this->action != 3) { + InitializeAnimation(this, 1); + } + } + + if (this->field_0x42) + if (this->field_0x42 > 4) + this->field_0x42 -= 4; + + if (this->field_0x43 != 0) { + sub_0804A9FC(this, 0x1c); + } + + sub_0804AA30(this, gUnk_080CD07C); +} + +void nullsub_142(Entity* this) { + /* ... */ +} + +void sub_0802A4E4(Entity* this) { + sub_0804A720(this); + this->action = 1; + this->collisionLayer = 3; + this->field_0x7c.BYTES.byte1 = Random(); + this->field_0x7a.HWORD = this->entityType.parameter * 0x3c; + this->field_0x7c.BYTES.byte0 = this->actionDelay; + this->field_0x78.HWORD = this->actionDelay * 0x3c; + UpdateSpriteForCollisionLayer(this); + sub_0802A7D0(this); +} + +void sub_0802A534(Entity* this) { + if (this->field_0x78.HWORD) { + this->field_0x78.HWORD--; + } else if (this->field_0x7a.HWORD == 0) { + Entity* ent = sub_08049DF4(1); + if (ent != NULL) { + this->action = 2; + this->actionDelay = 0x5a; + this->flags |= 0x80; + this->spriteSettings.b.draw = 3; + this->x.HALF.HI = ent->x.HALF.HI; + this->y.HALF.HI = ent->y.HALF.HI; + this->height.HALF.HI = -0x80; + this->spritePriority.b1 = 1; + this->spriteSettings.b.shadow = 2; + InitializeAnimation(this, 2); + sub_0802A7D0(this); + } + } +} + +void sub_0802A5B8(Entity* this) { + sub_0802A7D0(this); + if (this->actionDelay) { + if (--this->actionDelay == 0) { + EnqueueSFX(0x12d); + InitializeAnimation(this, 0); + } + } else { + this->height.HALF.HI += 3; + if (-1 < this->height.HALF.HI) { + this->action = 3; + this->spriteSettings.b.draw = 1; + this->height.HALF.HI = 0; + InitializeAnimation(this, 1); + } + } +} + +/* Kids... don't try to optimize code like this... */ +void sub_0802A610(Entity* this) { + u32 flags; + + GetNextFrame(this); + sub_0802A7D0(this); + flags = this->frames.all & 0x80; + if (flags) { + this->action = 4; + this->actionDelay = 0x1e; + } else if (this->frames.all & 1) { + this->frames.all = flags; + this->damageType = 0x75; + } +} + +void sub_0802A650(Entity* this) { + sub_0802A7D0(this); + this->height.HALF.HI -= 2; + if (-0xa0 > this->height.HALF.HI) { + this->action = 1; + this->flags &= ~0x80; + this->spriteSettings.b.draw = 0; + this->damageType = 0x74; + this->field_0x78.HWORD = this->field_0x7c.BYTES.byte0 * 0x3c; + } +} + +void sub_0802A69C(Entity* this) { + u32 flags; + + sub_0802A7D0(this); + gPlayerState.field_0xa |= 0x80; + gPlayerState.field_0x1a[0] |= 0x80; + gPlayerEntity.x.HALF.HI = this->field_0x7c.HALF.HI; + gPlayerEntity.y.HALF.HI = this->field_0x80.HWORD; + gPlayerEntity.height.HALF.HI = this->field_0x82.HWORD; + + if (gPlayerEntity.height.HALF.HI != this->height.HALF.HI) { + if (gPlayerEntity.height.HALF.HI < this->height.HALF.HI) { + this->height.HALF.HI--; + } else { + this->height.HALF.HI++; + } + } + + /* sigh... */ + GetNextFrame(this); + flags = this->frames.all & 0x80; + if (flags) { + this->action = 6; + this->actionDelay = 0x1e; + } else if (this->frames.all & 0x1) { + this->frames.all = flags; + this->spriteOffsetY = 3; + gPlayerEntity.spriteSettings.b.draw = 0; + } +} + +void sub_0802A734(Entity* this) { + sub_0802A7D0(this); + if (--this->actionDelay == 0) { + sub_0805E5A8(); + DoExitTransition(gUnk_0813AB1C[gArea.regret]); + } else { + this->height.WORD -= 0x20000; + gPlayerState.field_0xa |= 0x80; + gPlayerState.field_0x1a[0] |= 0x80; + } +} + +void sub_0802A78C(Entity* this) { + if (this->action != 0) { + if (sub_08049FDC(this, 1)) { + if (this->field_0x78.HWORD == 0) { + if (this->field_0x7a.HWORD) { + this->field_0x7a.HWORD--; + } + } + } else { + this->field_0x7a.HWORD = this->entityType.parameter * 0x3c + 1; + } + } +} + +void sub_0802A7D0(Entity* this) { + u32 unk = gUnk_080CD0B0[(this->field_0x7c.BYTES.byte1++ >> 3) & 7] + 0x100; + sub_0805EC9C(this, unk, unk, 0); +} +// clang-format off +void (*const gUnk_080CD07C[])(Entity*) = { + sub_0802A434, + sub_0802A454, + sub_08001328, + sub_0804A7D4, + sub_08001242, + nullsub_142, +}; + +void (*const gUnk_080CD094[])(Entity*) = { + sub_0802A4E4, + sub_0802A534, + sub_0802A5B8, + sub_0802A610, + sub_0802A650, + sub_0802A69C, + sub_0802A734, +}; + +const s8 gUnk_080CD0B0[] = { + -2, -4, -2, 0, 2, 4, 2, 0, +}; +// clang-format on diff --git a/src/enemy/wallMaster2.c b/src/enemy/wallMaster2.c new file mode 100644 index 00000000..a788ad58 --- /dev/null +++ b/src/enemy/wallMaster2.c @@ -0,0 +1,205 @@ +#include "enemy.h" +#include "functions.h" +#include "area.h" + +extern void sub_08001328(Entity*); +extern u32 sub_0806FCB8(Entity*, u32, u32, u32); +extern void DoExitTransition(u32*); + +extern Entity* gUnk_020000B0; +extern u32* gUnk_0813AB1C[]; + +void sub_0802CF64(Entity*); +void sub_0802CF8C(Entity*); +void sub_0802CFD8(Entity*); + +extern void (*const gUnk_080CD6FC[])(Entity*); +extern void (*const gUnk_080CD714[])(Entity*); +extern const u16 gUnk_080CD728[]; +extern const u16 gUnk_080CD730[]; +extern const s8 gUnk_080CD740[]; + +void WallMaster2(Entity* this) { + gUnk_080CD6FC[GetNextFunction(this)](this); + SetChildOffset(this, 0, 1, -0x10); +} + +void sub_0802CC68(Entity* this) { + gUnk_080CD714[this->action](this); +} + +void sub_0802CC80(Entity* this) { + u8 bVar1 = this->bitfield & 0x7f; + switch (this->bitfield & 0x7f) { + case 0 ... 1: + case 0x1e: + this->action = 3; + this->flags &= ~0x80; + InitializeAnimation(this, 1); + gPlayerEntity.flags &= ~0x80; + break; + } + if (this->field_0x43 != 0) { + sub_0804A9FC(this, 0x1c); + } + sub_0804AA30(this, gUnk_080CD6FC); +} + +void nullsub_151(Entity* this) { + /* ... */ +} + +void sub_0802CCE0(Entity* this) { + u32 tmp; + + sub_0804A720(this); + this->action = 1; + this->actionDelay = 60; + this->field_0xf = Random(); + this->spriteSettings.b.shadow = 2; + this->animationState = 0xff; + this->height.HALF.HI = -2; + this->collisionLayer = 3; + tmp = Random(); + this->field_0x7a.HALF.LO = tmp; + this->field_0x7a.HALF.HI = (tmp >> 8) & 0x60; + this->field_0x7c.HALF.LO = 0; + UpdateSpriteForCollisionLayer(this); + InitializeAnimation(this, 0); + sub_0802CF64(this); + sub_0802CFD8(this); +} + +void sub_0802CD54(Entity* this) { + GetNextFrame(this); + sub_0802CFD8(this); + + if ((this->field_0x7c.HALF_U.LO == 0 || --this->field_0x7c.HALF_U.LO == 0) && sub_08049FDC(this, 1)) { + if (this->field_0x7a.HALF.HI) { + --this->field_0x7a.HALF.HI; + } else { + u32 tmp; + + this->action = 2; + tmp = Random() >> 0x10; + this->actionDelay = tmp; + this->nonPlanarMovement = 0xc0; + this->field_0x78.HWORD = gUnk_080CD728[Random() & 3]; + this->field_0x7a.HALF.HI = (tmp >> 8) & 0x60; + return; + } + } + + if (--this->actionDelay == 0) { + this->actionDelay = 60; + sub_0802CF64(this); + } + sub_0806F69C(this); +} + +void sub_0802CDE8(Entity* this) { + if (--this->field_0x78.HWORD && sub_08049FDC(this, 1)) { + if ((this->actionDelay++ & 3) == 0) { + sub_08004596(this, GetFacingDirection(this, gUnk_020000B0)); + sub_0802CF8C(this); + } + sub_0806F69C(this); + } else { + this->action = 1; + this->actionDelay = 60; + this->nonPlanarMovement = 0x60; + this->field_0x7c.HALF.LO = (Random() & 0x38) + 0x96; + } + GetNextFrame(this); + sub_0802CFD8(this); +} + +void sub_0802CE68(Entity* this) { + u8 frames; + + gPlayerState.field_0xa |= 0x80; + gPlayerState.field_0x1a[0] |= 0x80; + gPlayerState.flags.all |= 0x100; + if (!sub_0806FCB8(this, gPlayerEntity.x.HALF.HI, gPlayerEntity.y.HALF.HI, 4)) { + this->direction = GetFacingDirection(this, &gPlayerEntity); + sub_0806F69C(this); + } + sub_0802CFD8(this); + GetNextFrame(this); + frames = this->frames.all & 0x80; + if (frames) { + this->action = 4; + this->actionDelay = 30; + } else if (this->frames.all & 1) { + this->frames.all = frames; + gPlayerEntity.spriteSettings.b.draw = 0; + } +} + +void sub_0802CEF4(Entity* this) { + sub_0802CFD8(this); + if (--this->actionDelay == 0) { + sub_0805E5A8(); + DoExitTransition(gUnk_0813AB1C[gArea.regret]); + } else { + this->height.WORD -= 0x20000; + if (this->height.HALF.HI < -0x30) { + this->spriteSettings.b.shadow = 1; + } + gPlayerState.field_0xa |= 0x80; + gPlayerState.field_0x1a[0] |= 0x80; + } +} + +void sub_0802CF64(Entity* this) { + if (sub_08049FA0(this)) { + this->direction = Direction8Round(Random()); + } else { + this->direction = Direction8RoundUp(sub_08049EE4(this)); + } + sub_0802CF8C(this); +} + +NAKED +void sub_0802CF8C(Entity* this) { + asm(".include \"asm/non_matching/wallMaster2/sub_0802CF8C.inc\""); +} + +void sub_0802CFD8(Entity* this) { + u32 unk = gUnk_080CD740[(this->field_0x7a.HALF.LO++ >> 3) & 7]; + sub_0805EC9C(this, (s16)this->field_0x74.HWORD + unk, 0x100 + unk, this->field_0x76.HWORD); +} + +// clang-format off +void (*const gUnk_080CD6FC[])(Entity*) = { + sub_0802CC68, + sub_0802CC80, + sub_08001328, + sub_0804A7D4, + sub_08001242, + nullsub_151, +}; + +void (*const gUnk_080CD714[])(Entity*) = { + sub_0802CCE0, + sub_0802CD54, + sub_0802CDE8, + sub_0802CE68, + sub_0802CEF4, +}; + +const u16 gUnk_080CD728[] = { + 120, 180, 240, 300, +}; + +const u16 gUnk_080CD730[] = { + 0xff00, 0x4000, + 0xff00, 0x0000, + 0x0100, 0x0000, + 0x0100, 0xc000, +}; + +const s8 gUnk_080CD740[] = { + -2, -4, -2, 0, 2, 4, 2, 0, +}; +// clang-format on diff --git a/src/enemy/waterDrop.c b/src/enemy/waterDrop.c new file mode 100644 index 00000000..b95535df --- /dev/null +++ b/src/enemy/waterDrop.c @@ -0,0 +1,99 @@ +#include "enemy.h" +#include "entity.h" +#include "functions.h" +#include "screen.h" + +void sub_0802A39C(Entity*); +void sub_0802A334(Entity*); + +extern u16 gUnk_02001A40[]; + +extern void (*const gUnk_080CD030[])(Entity*); +extern const u8 gUnk_080CD03C[]; +extern const s8 gUnk_080CD040[]; + +void WaterDrop(Entity* this) { + gUnk_080CD030[this->action](this); +} + +void sub_0802A250(Entity* this) { + Entity* ent; + + this->action = 1; + this->actionDelay = 0; + this->field_0x20 = -0x30000; + this->nonPlanarMovement = gUnk_080CD03C[Random() & 3]; + this->direction = gUnk_080CD040[Random() & 3] + 0x18; + this->collisionLayer = 2; + InitializeAnimation(this, 0); + UpdateSpriteForCollisionLayer(this); + + ent = CreateObject(0x66, 0, 0); + if (ent) { + ent->parent = this; + } +} + +void sub_0802A2B4(Entity* this) { + if (!sub_08003FC4(this, 0x2800)) { + this->action = 2; + this->spritePriority.b0 = 7; + EnqueueSFX(0x84); + } else { + sub_0806F69C(this); + } + + sub_0802A39C(this); + if (-8 < this->height.HALF.HI) { + sub_0802A334(this); + } +} + +void sub_0802A2FC(Entity* this) { + GetNextFrame(this); + if (this->frames.all & 0x80) { + DeleteEntity(this); + } else if (this->frames.all & 1) { + this->flags &= ~0x80; + } else { + sub_0802A39C(this); + } +} + +void sub_0802A334(Entity* this) { + u32 x = (this->x.HALF.HI - gRoomControls.roomScrollX + gScreen.bg.bg1yOffset) >> 3; + u32 y = (this->y.HALF.HI - gRoomControls.roomScrollY + gScreen.bg.bg2xOffset) >> 3; + if (gUnk_02001A40[(x & 0x1fU) + (y & 0x1fU) * 0x20 + 0x400]) { + this->collisionLayer = 2; + } else { + this->collisionLayer = 1; + } + UpdateSpriteForCollisionLayer(this); +} + +void sub_0802A39C(Entity* this) { + u32 x = (gPlayerEntity.x.HALF.HI - gRoomControls.roomScrollX + gScreen.bg.bg1yOffset) >> 3; + u32 y = (gPlayerEntity.y.HALF.HI - gRoomControls.roomScrollY + gScreen.bg.bg2xOffset - 10) >> 3; + if (gUnk_02001A40[(x & 0x1fU) + (y & 0x1fU) * 0x20 + 0x400]) { + this->flags &= ~0x80; + } else { + this->flags |= 0x80; + } +} + +// clang-format off +void (*const gUnk_080CD030[])(Entity*) = { + sub_0802A250, + sub_0802A2B4, + sub_0802A2FC, +}; + +const u8 gUnk_080CD03C[] = { + 0x60, 0x80, + 0xA0, 0xC0, +}; + +const s8 gUnk_080CD040[] = { + -2, -1, -1, -3, +}; +// clang-format on diff --git a/src/enemy/wisp.c b/src/enemy/wisp.c index 8a35b3a4..e550363c 100644 --- a/src/enemy/wisp.c +++ b/src/enemy/wisp.c @@ -72,7 +72,7 @@ void sub_08033650(Entity* this) { } void sub_08033658(Entity* this) { - sub_0806F4E8(); + sub_0806F4E8(this); } void sub_08033660(Entity* this) { @@ -98,7 +98,7 @@ void sub_080336A8(Entity* this) { } else if (this->collisions != 0) { sub_0800417E(this, this->collisions); } - sub_080AEF88(this); + ProcessMovement(this); GetNextFrame(this); } @@ -109,7 +109,7 @@ void sub_080336DC(Entity* this) { this->y.HALF.HI = this->field_0x82.HWORD; break; case 0x18: - sub_080A29BC(this); + CreateDust(this); break; case 0xc: this->spriteSettings.b.draw = TRUE; diff --git a/src/entity.c b/src/entity.c index 056644bf..1b8d1cb1 100644 --- a/src/entity.c +++ b/src/entity.c @@ -193,16 +193,16 @@ void sub_0805E92C(u32 param_1) { } extern Entity gUnk_020369F0; -extern void sub_0801D66C(const void* src, void* dest, size_t size); // dma copy +extern void _DmaCopy(const void* src, void* dest, size_t size); // dma copy extern void sub_0805E98C(void); void sub_0805E958(void) { - sub_0801D66C(&gEntityLists, &gUnk_020369F0, 0x48); + _DmaCopy(&gEntityLists, &gUnk_020369F0, 0x48); sub_0805E98C(); } void sub_0805E974(void) { - sub_0801D66C(&gUnk_020369F0, &gEntityLists, 0x48); + _DmaCopy(&gUnk_020369F0, &gEntityLists, 0x48); } void sub_0805E98C(void) { diff --git a/src/loadRoom.c b/src/loadRoom.c index 6761fa14..7a52709d 100644 --- a/src/loadRoom.c +++ b/src/loadRoom.c @@ -12,7 +12,7 @@ extern Entity* LoadRoomEntity(EntityData*); extern void* GetRoomProperty(u32, u32, u32); extern u32 gUnk_02017654; -extern u32* gUnk_080D50FC; +extern u32* gAreaEntities; void LoadRoom(void) { s32 iVar1; @@ -58,7 +58,7 @@ void sub_0804B0B0(u32 arg0, u32 arg1) { void SetCurrentRoomPropertyList(u32 arg0, u32 arg1) { u32** arr; gUnk_02017654 = 0; - arr = &gUnk_080D50FC; + arr = &gAreaEntities; if (arr[arg0] != 0) { gUnk_02017654 = arr[arg0][arg1]; } @@ -78,7 +78,7 @@ void* GetRoomProperty(u32 arg0, u32 arg1, u32 arg2) { u32 temp; u32** arr; temp = 0; - arr = &gUnk_080D50FC; + arr = &gAreaEntities; if (arr[arg0] != NULL) { temp = arr[arg0][arg1]; if (temp != 0) { diff --git a/src/mainLoop.c b/src/mainLoop.c index c46fd8bf..3ad0eaae 100644 --- a/src/mainLoop.c +++ b/src/mainLoop.c @@ -8,7 +8,7 @@ extern void sub_0804FF84(u32); extern u16 gPaletteBuffer[]; extern void VBlankInterruptWait(void); extern void DisableInterruptsAndDMA(void); -extern void sub_0801D66C(void*, u8*, int); +extern void _DmaCopy(void*, u8*, int); extern void sub_08016B34(void); static void sub_08055F70(void); @@ -99,12 +99,12 @@ static void sub_08055F70(void) { _DmaZero(gUnk_02000030, size); size = (u32)gUnk_080B2CD8 - (u32)sub_080B197C; if (size != 0) { - sub_0801D66C(sub_080B197C, gUnk_030056F0, size); + _DmaCopy(sub_080B197C, gUnk_030056F0, size); } size = (u32)gUnk_080B2CD8_2 - (u32)gUnk_080B2CD8_3; if (size != 0) { - sub_0801D66C(gUnk_080B2CD8_3, gUnk_02038560, size); + _DmaCopy(gUnk_080B2CD8_3, gUnk_02038560, size); } sub_0801DA90(0); diff --git a/src/manager/manager15.c b/src/manager/manager15.c new file mode 100644 index 00000000..c4d1f8b0 --- /dev/null +++ b/src/manager/manager15.c @@ -0,0 +1,495 @@ +#include "global.h" +#include "flags.h" +#include "screen.h" +#include "manager.h" +#include "functions.h" + +typedef struct { + Manager manager; + u8 unk_20; + u8 unk_21; + u8 unk_22; + u8 unk_23;//used + u16 unk_24; + u16 unk_26; + void* unk_28; + u16 unk_2c; + u8 unk_2e[0x6]; + s16 unk_34; + s16 unk_36; + s16 unk_38; + s16 unk_3a; + u16 unk_3c; + u16 unk_3e;//used +} Manager15; + +extern void (*const gUnk_081085D8[])(Manager*); + +void sub_0805A280(Manager* this) { + gUnk_081085D8[this->unk_0a](this); +} + + +void sub_0805A89C(Manager15*); +void sub_0805A8EC(Manager15*); +void sub_0805AAF0(u32); + +void sub_0805A298(Manager15* this) { + if (this->manager.action == 0) { + sub_0805A89C(this); + if (!CheckLocalFlag(this->unk_3e)) { + this->unk_23 = 1; + } else { + this->unk_23 = 2; + } + sub_0805AAF0(this->unk_23); + gScreen.lcd.displayControl |= 0x4800; + } + sub_0805A8EC(this); +} + +extern void (*const gUnk_081085F8[])(Manager15*); + +void sub_0805A2E4(Manager15* this) { + if (this->manager.action == 0) { + sub_0805A89C(this); + this->unk_23 = 1; + sub_0805AAF0(1); + if (!CheckLocalFlag(this->unk_3e)) { + this->manager.action = 1; + gScreen.lcd.displayControl &= 0xB7FF; + } else { + if (CheckLocalFlag(0x48)) { + this->manager.action = 4; + } else { + this->manager.action = 3; + } + gScreen.lcd.displayControl |= 0x4800; + } + } else { + gUnk_081085F8[this->manager.action](this); + } + if (this->manager.next) { + sub_0805A8EC(this); + } +} + +extern Entity gUnk_080E4C08; + +void sub_0805A370(Manager15* this) { + if (this->manager.unk_0d) { + LoadRoomEntityList(&gUnk_080E4C08); + this->manager.action = 3; + PlaySFX(0x80100000); + } +} + +void sub_0805A394(Manager15* this) { + Entity* ent; + if ((ent = FindEntityInListBySubtype(0x3,0x13,0x4))) { + if (ent->entityType.form != 4) { + return; + } + } + SetLocalFlag(0x48); + ClearRoomFlag(0); + gScreen.lcd.displayControl &= 0xB7FF; + DeleteThisEntity(); +} + +void nullsub_496(Manager15* this) { +} + +extern void (*const gUnk_0810860C[])(Manager15*); + +void sub_0805A3D4(Manager15* this) { + if (this->manager.action == 0) { + sub_0805A89C(this); + if (this->manager.unk_0a == 3) { + this->unk_23 = 2; + } else { + this->unk_23 = 1; + } + sub_0805AAF0(this->unk_23); + if (!CheckLocalFlag(this->unk_3e)) { + ClearFlag(this->unk_3c); + this->manager.action = 1; + gScreen.lcd.displayControl &= 0xB7FF; + } else { + SetFlag(this->unk_3c); + this->manager.action = 3; + gScreen.lcd.displayControl |= 0x4800; + } + } else { + gUnk_0810860C[this->manager.action](this); + } + sub_0805A8EC(this); +} + +void sub_0805A4CC(Manager15*, u32); + +void sub_0805A464(Manager15* this) { + if (CheckLocalFlag(this->unk_3e)) { + this->manager.action = 2; + sub_0805A4CC(this, 0); + } +} + +void sub_0805A480(Manager15* this) { + if (this->manager.unk_0d != 0) { + this->manager.action = 3; + SetFlag(this->unk_3c); + } +} + +void sub_0805A498(Manager15* this) { + if (!CheckLocalFlag(this->unk_3e)) { + this->manager.action = 4; + sub_0805A4CC(this, 1); + } +} + +void sub_0805A4B4(Manager15* this) { + if (this->manager.unk_0d != 0) { + this->manager.action = 1; + ClearFlag(this->unk_3c); + } +} + +void sub_0805A4CC(Manager15* this, u32 unk_0) { + Entity* tmp; + tmp = CreateObject(0x8e, unk_0, 0); + if (tmp) { + tmp->x.HALF.HI = this->unk_38 + gRoomControls.roomOriginX; + tmp->y.HALF.HI = this->unk_3a + gRoomControls.roomOriginY - 0x30; + tmp->parent = (Entity*) this; + this->manager.unk_0d = 0; + } +} + +extern void (*const gUnk_08108620[])(Manager15*); +void sub_0805AA58(Manager15*); +void sub_0805A9CC(Manager15*); + +void sub_0805A500(Manager15* this) { + if (this->manager.action == 0) { + sub_0805A89C(this); + this->unk_28 = 0; + if (CheckLocalFlag(0x36)) { + this->unk_23 = 3; + this->manager.action = 5; + gScreen.lcd.displayControl |= 0x4800; + } else { + if (CheckLocalFlag(0x34)) { + this->unk_23 = 4; + this->manager.action = 3; + gScreen.lcd.displayControl |= 0x4800; + } else { + this->unk_23 = 4; + this->manager.action = 1; + gScreen.lcd.displayControl &= 0xB7FF; + } + } + sub_0805AAF0(this->unk_23); + } else { + gUnk_08108620[this->manager.action](this); + } + sub_0805AA58(this); + sub_0805A9CC(this); + if (gRoomControls.unk2 == 1) { + gScreen.lcd.displayControl |= 0x80<<7; + this->manager.unk_0d = 1; + return; + } + if (!this->manager.unk_0d) return; + this->manager.unk_0d = 0; + if (this->unk_20 == gRoomControls.roomID) return; + gScreen.lcd.displayControl &= 0xB7FF; + DeleteThisEntity(); +} + +void sub_0805A5FC(Manager15* this) { + if (CheckLocalFlag(0x34)) { + this->manager.action = 2; + sub_0805A4CC(this,2); + } +} + +void sub_0805A618(Manager15* this) { + if (this->manager.unk_0d) { + this->manager.action = 3; + } +} + +void sub_0805A628(Manager15* this) { + if (CheckLocalFlag(0x36)) { + this->manager.action = 4; + this->unk_23 = 3; + sub_0805A4CC(this,3); + } +} + +void sub_0805A64C(Manager15* this) { + if (this->manager.unk_0d) { + this->manager.action = 5; + } +} + +void sub_0805A65C(Manager15* this) {} +void sub_0805A660(Manager15* this) {} + +extern void (*const gUnk_08108638[])(Manager15*); +void sub_0805A68C(Manager15*); + +void sub_0805A664(Manager15* this) { + gUnk_08108638[this->manager.action](this); + sub_0805A8EC(this); + sub_0805A68C(this); +} + +extern u32 sub_0806FBFC(u32, u32, u32, u32); + +void sub_0805A68C(Manager15* this) { + if (sub_0806FBFC(this->unk_38 - 0x18, this->unk_3a - 0x18, 0x30, 0x30)) { + if (this->unk_2c <= 0x1007) { + gScreen.controls.alphaBlend = ++this->unk_2c; + this->unk_22 = 0; + } + } else { + if (this->unk_2c > 0x1000) { + this->unk_2c--; + } + gScreen.controls.alphaBlend=this->unk_2c; + } +} + +u32 sub_0805A73C(Manager15*); + +void sub_0805A6E8(Manager15* this) { + u16 tmp; + sub_0805A89C(this); + this->unk_23 = 0; + sub_0805AAF0(0); + this->unk_38 += gRoomControls.roomOriginX; + this->unk_3a += gRoomControls.roomOriginY; + if (!sub_0805A73C(this)) { + this->manager.action++; + } + this->unk_2c = 0x1000; + tmp = gScreen.lcd.displayControl | 0x4800; + gScreen.lcd.displayControl = tmp; +} + +u32 sub_0805A73C(Manager15* this) { + return sub_0806FBFC(this->unk_38 - 0x6, this->unk_3a - 0x6, 0xC, 0xC); +} + +void sub_0805A758(Manager15* this) { + if (!sub_0805A73C(this)) { + this->manager.action++; + } +} + +extern u8 gUnk_02034490; +extern void sub_0805E4E0(Manager*, u32); +extern void sub_08077B20(void); + +void sub_0805A76C(Manager15* this) { + if ((gPlayerEntity.currentHealth != 0) + && (gPlayerEntity.height.HALF.HI == 0) + && (!gPlayerState.field_0x2c) + ) { + switch (gPlayerState.field_0xa9) { + case 1: + case 0: + if (sub_0805A73C(this)) { + this->manager.action++; + sub_08004168(&gPlayerEntity); + gPlayerEntity.animationState = 4; + sub_0805E4E0(&this->manager, 0x258); + sub_08078A90(0xFF); + gUnk_02034490 = 1; + gRoomControls.cameraTarget = 0; + sub_08077B20(); + } + } + } +} + +void sub_0805A7E4(Manager15* this) { + if (gPlayerState.playerAction != 0x12) { + gPlayerState.playerAction = 0x12; + gPlayerState.field_0x38 = 0; + gPlayerState.field_0x39 = 0; + } +} + +void sub_0805A804(Manager15* this) { + switch (this->manager.action) { + case 0: + if (CheckLocalFlag(this->unk_3e)) { + this->manager.action = 1; + } else { + this->manager.action = 2; + } + this->manager.unk_0d = 1; + this->manager.unk_10 |= 0x20; + sub_0805E3A0(this, 6); + break; + case 1: + if (CheckLocalFlag(this->unk_3e)) break; + this->manager.action = 2; + sub_0805A4CC(this,4); + break; + case 2: + if (this->manager.unk_0d) { + this->manager.action = 3; + } + break; + case 3: + if (!CheckLocalFlag(this->unk_3e)) break; + this->manager.action = 4; + sub_0805A4CC(this,4); + break; + case 4: + if (this->manager.unk_0d) { + this->manager.action = 1; + } + break; + default: + DeleteThisEntity(); + } +} + +void sub_0805AAC8(Manager15*); +extern void sub_08052D74(void*, void*, void*); + +void sub_0805A89C(Manager15* this) { + sub_0805E3A0(this, 6); + this->manager.action = 1; + this->manager.unk_10 |= 0x20; + this->manager.unk_0e = 8; + this->manager.unk_0f = 0x10; + this->unk_21 = 0; + this->unk_22 = 0; + this->unk_20 = gRoomControls.roomID; + this->unk_24 = gRoomControls.roomOriginX; + this->unk_26 = gRoomControls.roomOriginY; + sub_08052D74(this, sub_0805AAC8, 0); +} + +void sub_0805A94C(Manager15* this); + +void sub_0805A8EC(Manager15* this) { + sub_0805AA58(this); + sub_0805A94C(this); + if (gRoomControls.unk2 == 1) { + gScreen.lcd.displayControl |= 0x4000; + this->manager.unk_0d = 1; + } else { + if (!this->manager.unk_0d) return; + this->manager.unk_0d = 0; + if (this->unk_20 == gRoomControls.roomID) return; + gScreen.lcd.displayControl &= 0xB7FF; + DeleteThisEntity(); + } +} + +void sub_0805A94C(Manager15* this) { + int tmp1, tmp2; + gScreen.affine.bg3xOffset = gRoomControls.roomScrollX - this->unk_24 + this->unk_34; + gScreen.affine.bg3yOffset = gRoomControls.roomScrollY - this->unk_26 + this->unk_36; + tmp1 = -gScreen.affine.bg3xOffset; + tmp2 = tmp1 + 0x100; + if (tmp1 < 0) tmp1 = 0; + if (tmp1 > 0xF0) tmp1 = 0xF0; + if (tmp2 < 0) tmp2 = 0; + if (tmp2 > 0xF0) tmp2 = 0xF0; + gScreen.controls.window1HorizontalDimensions = (tmp1 << 8 | tmp2); + tmp1 = -gScreen.affine.bg3yOffset; + tmp2 = tmp1 + 0x100; + if (tmp1 < 0) tmp1 = 0; + if (tmp1 > 0xA0) tmp1 = 0xA0; + if (tmp2 < 0) tmp2 = 0; + if (tmp2 > 0xA0) tmp2 = 0xA0; + gScreen.controls.window1VerticalDimensions = (tmp1 << 8 | tmp2); +} + +extern u8 gUnk_02001A40[]; + +#ifdef NON_MATCHING +void sub_0805A9CC(Manager15* this) { + int tmp1, tmp2; + void* tmp3; + gScreen.affine.bg3xOffset = gRoomControls.roomScrollX - this->unk_24 + this->unk_34; + tmp1 = -gScreen.affine.bg3xOffset; + tmp2 = tmp1 + 0x100; + if (tmp1 < 0) tmp1 = 0; + if (tmp1 > 0xF0) tmp1 = 0xF0; + if (tmp2 < 0) tmp2 = 0; + if (tmp2 > 0xF0) tmp2 = 0xF0; + gScreen.controls.window1HorizontalDimensions = tmp1 << 8 | tmp2; + tmp1 = gRoomControls.roomScrollY - this->unk_26 + this->unk_36; + gScreen.affine.bg3yOffset = tmp1 & 0x3F; + if (tmp1 < 0) tmp1 += 0x3F; + tmp3 = (&gUnk_02001A40[(tmp1 >> 6 << 9)]); + gScreen.affine.unk5 = (u32) tmp3; + gScreen.controls.window1VerticalDimensions = 0xa0; + if (this->unk_28 == tmp3) return; + this->unk_28 = tmp3; + gScreen.affine.unk4 = 1; +} +#else +NAKED +void sub_0805A9CC(Manager15* this) { + asm(".include \"asm/non_matching/manager15/sub_0805A9CC.inc\""); +} +#endif + +extern struct { + u8 unk_00[0x20]; +} gUnk_085A97A0[]; +extern u16 gUnk_081085B8[]; +extern void LoadPalettes(const u8*, u32, u32); + +void sub_0805AA58(Manager15* this) { + if (--this->manager.unk_0e == 0) { + this->manager.unk_0e = 8; + this->unk_21 += 1; + this->unk_21 &= 3; + LoadPalettes(gUnk_085A97A0[this->unk_21].unk_00,5,1); + } + if (--this->manager.unk_0f == 0) { + this->manager.unk_0f = 0x10; + this->unk_22 += 1; + this->unk_22 &= 0xF; + gScreen.controls.alphaBlend = gUnk_081085B8[this->unk_22]; + } +} + +void sub_0805AAC8(Manager15* this) { + sub_0805AAF0(this->unk_23); + sub_0805A280(&this->manager); +} + + +extern u16 gUnk_08108648[]; + +void sub_0805AADC(u32 unk0) { + LoadGfxGroup(gUnk_08108648[unk0]); +} + +void sub_0805AAF0(u32 unk0) { + sub_0805AADC(unk0); + gScreen.controls.layerFXControl = 0x3E48; + gScreen.controls.alphaBlend = 0x1008; + gScreen.affine.bg3Control = 0x1E04; + gScreen.affine.unk5 = &gUnk_02001A40; + gScreen.affine.bg3xOffset = 0; + gScreen.affine.bg3yOffset = 0; + gScreen.affine.unk4 = 1; + gScreen.controls.windowInsideControl = 0x3F3F; + gScreen.controls.windowOutsideControl = 0x37; + gScreen.controls.window1HorizontalDimensions = 0xF0; + gScreen.controls.window1VerticalDimensions = 0xA0; +} diff --git a/src/manager/manager1A.c b/src/manager/manager1A.c new file mode 100644 index 00000000..ff6d8afe --- /dev/null +++ b/src/manager/manager1A.c @@ -0,0 +1,223 @@ +#include "global.h" +#include "manager.h" +#include "flags.h" +#include "entity.h" +#include "room.h" +#include "screen.h" +#include "functions.h" + + +typedef struct { + Manager manager; + s16 unk_20; + s16 unk_22; + u16 unk_24; + u16 unk_26; + u8 unk_28[8]; + u16 unk_30; + u16 unk_32; + u16 unk_34; + u16 unk_36; + u8 unk_38[7]; + u8 unk_3f; +} Manager1A; + +extern void (*const gUnk_08108668[])(Manager1A*); + +extern u8 gGlobalGfxAndPalettes[]; + +void sub_0805B030(Manager1A* this) { + gUnk_08108668[this->manager.action](this); +} + +extern void sub_08052D74(void*, void*, void*); +extern u32 sub_0806FBFC(u32, u32, u32, u32); + +typedef struct struct_08108764 { + u8 unk_00; + u8 unk_01;//area ID? + u8 unk_02;//room ID? + u8 unk_03;//layer? + u16 unk_04; + u16 unk_06; + u8 unk_08; + u8 unk_09; + u8 unk_0a; + u8 unk_0b; + struct { + u32 unk_00; + u16 unk_04; + u16 unk_06; + u16 unk_08; + u16 unk_0a; + }* unk_0c; + struct { + u8 unk_00; + u8 unk_01; + u8 unk_02[2]; + u16 unk_04; + u16 unk_06; + }* unk_10; +} struct_08108764; + +extern struct_08108764 gUnk_08108764[]; + +u32 sub_0805B1CC(Manager1A*); +void sub_0805B210(Manager1A*); +void sub_0805B2B0(Manager1A*); +void sub_0805B328(Manager1A*); +void sub_0805BC4C(void); + +void sub_0805B048(Manager1A* this) { + struct_08108764* tmp; + Entity* obj; + sub_0805E3A0(&this->manager, 6); + _DmaZero(&this->unk_20, 0x20); + this->manager.action = 1; + this->unk_3f = gRoomControls.roomID; + tmp = &gUnk_08108764[this->manager.unk_0a]; + if (!tmp->unk_0a) { + this->unk_20 = gRoomControls.roomOriginX; + this->unk_22 = gRoomControls.roomOriginY; + this->unk_24 = gRoomControls.width; + this->unk_26 = gRoomControls.height; + } else { + this->unk_20 = (tmp->unk_08 << 4) + gRoomControls.roomOriginX; + this->unk_22 = (tmp->unk_09 << 4) + gRoomControls.roomOriginY; + this->unk_24 = (tmp->unk_0a << 4); + this->unk_26 = (tmp->unk_0b << 4); + } + this->manager.unk_0b = tmp->unk_0c != 0; + if (this->manager.unk_0b) { + this->manager.unk_10 |= 0x20; + this->unk_34 = tmp->unk_0c->unk_04; + this->unk_36 = tmp->unk_0c->unk_06; + this->unk_30 = tmp->unk_0c->unk_08; + this->unk_32 = tmp->unk_0c->unk_0a; + sub_0805BC4C(); + sub_0805B2B0(this); + sub_0805B328(this); + sub_08052D74(this, sub_0805B328, 0); + } + if (!tmp->unk_10) return; + obj = CreateObject(0x28, tmp->unk_10->unk_00, tmp->unk_10->unk_01); + if (obj) { + obj->x.HALF.HI = tmp->unk_10->unk_04 + gRoomControls.roomOriginX; + obj->y.HALF.HI = tmp->unk_10->unk_06 + gRoomControls.roomOriginY; + } + if (this->manager.unk_0a != 0xa + || CheckLocalFlag(0x4B)) return; + obj = CreateObject(0x28, 3, 3); + if (obj) { + obj->x.HALF.HI = tmp->unk_10->unk_04 + gRoomControls.roomOriginX; + obj->y.HALF.HI = tmp->unk_10->unk_06 + gRoomControls.roomOriginY; + } +} + +void sub_0805B168(Manager1A* this) { + if (sub_0805B1CC(this)) { + sub_0805B210(this); + DeleteThisEntity(); + return; + } + sub_0805B2B0(this); + if (gRoomControls.unk2 == 1) { + this->manager.unk_0d = 1; + return; + } + if (!this->manager.unk_0d) return; + this->manager.unk_0d = 0; + if (this->unk_3f == gRoomControls.roomID) return; + if (this->manager.unk_0b) { + gScreen.lcd.displayControl &= ~0x800; + } + DeleteThisEntity(); +} + +u32 sub_0805B1CC(Manager1A* this) { + u32 re = 0; + if (sub_0806FBFC(this->unk_20, this->unk_22, this->unk_24, this->unk_26)) { + if ((gPlayerState.flags.all & 0x4) && (gPlayerState.flags.all & 0x1)) { + gPlayerState.flags.all |= 0x8000; + } else if (gPlayerState.flags.all & 0x8000) { + re = 1; + } + } + return re; +} + +void sub_0805B210(Manager1A* this) { + struct_08108764 *tmp; + gScreenTransition.transitioningOut = 1; + gScreenTransition.transitionType = 1; + gScreenTransition.playerState = 4; + tmp = &gUnk_08108764[this->manager.unk_0a]; + gScreenTransition.areaID = tmp->unk_01; + gScreenTransition.roomID = tmp->unk_02; + gScreenTransition.playerLayer = tmp->unk_03; + if (gPlayerState.flags.all & 0x80) { + gScreenTransition.field_0xf = 6; + } else { + gScreenTransition.field_0xf = 2; + } + switch (tmp->unk_00) { + case 0: + gScreenTransition.playerStartPos.HALF.x = tmp->unk_04; + gScreenTransition.playerStartPos.HALF.y = tmp->unk_06; + break; + case 1: + gScreenTransition.playerStartPos.HALF.x = gPlayerEntity.x.HALF.HI - gRoomControls.roomOriginX + tmp->unk_04; + gScreenTransition.playerStartPos.HALF.y = gPlayerEntity.y.HALF.HI - gRoomControls.roomOriginY + tmp->unk_06; + break; + case 2: + gScreenTransition.playerStartPos.HALF.x = tmp->unk_04; + gScreenTransition.playerStartPos.HALF.y = tmp->unk_06; + gScreenTransition.field_0xf = 6; + break; + } +} + +void sub_0805B2B0(Manager1A* this) { + s32 tmp, tmp2; + if (!this->manager.unk_0b) return; + tmp = (this->unk_30 - gRoomControls.roomScrollX) / 4; + tmp2 = (this->unk_32 - gRoomControls.roomScrollY) / 4; + if (tmp < -12) { + tmp = -12; + } + if (tmp > 12) { + tmp = 12; + } + if (tmp2 < -12) { + tmp2 = -12; + } + if (tmp2 > 12) { + tmp2 = 12; + } + gScreen.lcd.displayControl |= 0x800; + gRoomControls.bg3OffsetX.HALF.HI = gRoomControls.roomScrollX + this->unk_34 + tmp; + gScreen.affine.bg3xOffset = gRoomControls.roomScrollX + this->unk_34 + tmp; + gRoomControls.bg3OffsetY.HALF.HI = gRoomControls.roomScrollY + this->unk_36 + tmp2; + gScreen.affine.bg3yOffset = gRoomControls.roomScrollY + this->unk_36 + tmp2; +} + +void sub_0805B328(Manager1A* this) { + struct_08108764 *tmp; + if (!this->manager.unk_0b) return; + tmp = &gUnk_08108764[this->manager.unk_0a]; + LoadAssetAsync(&gGlobalGfxAndPalettes[tmp->unk_0c->unk_00], 0x0600F000, 0x800); + gScreen.affine.bg3Control = 0x1E07; + gScreen.lcd.displayControl |= 0x800; + gScreen.affine.bg3xOffset = gRoomControls.bg3OffsetX.HALF.HI; + gScreen.affine.bg3yOffset = gRoomControls.bg3OffsetY.HALF.HI; + gScreen.controls.layerFXControl &= ~0x8; +} + +void sub_0805B390(u32 unk1) { + Manager* tmp = GetEmptyManager(); + if (!tmp) return; + tmp->type = 0x9; + tmp->subtype = 0x1A; + tmp->unk_0a = unk1; + AppendEntityToList(tmp, 6); +} diff --git a/src/manager/manager20.c b/src/manager/manager20.c new file mode 100644 index 00000000..fe50967e --- /dev/null +++ b/src/manager/manager20.c @@ -0,0 +1,38 @@ +#include "global.h" +#include "manager.h" +#include "flags.h" +#include "entity.h" +#include "room.h" + +typedef struct { + Manager manager; + u8 unk_20[0x12]; + u16 unk_32; + u8 unk_34[2]; + u8 unk_36; + u8 unk_37; + u16 unk_38; + u16 unk_3a; + u16 unk_3c; + u16 unk_3e; +} Manager20; + +extern void DeleteManager(Manager20*); + +void sub_0805B7A0(Manager20* this) { + Entity* tmp = CreateObject(this->manager.unk_0e, this->manager.unk_0a, this->manager.unk_0b); + if (!tmp) return; + tmp->field_0x86.HWORD = this->unk_3e; + if (CheckFlags(this->unk_3e)) { + tmp->x.HALF.HI = this->unk_36 | (this->unk_37&0xF)<<8;//r1 + tmp->y.HALF.HI = this->unk_3c & 0xFFF; + tmp->collisionLayer = this->unk_3c >> 0xC; + } else { + tmp->x.HALF.HI = this->unk_38; + tmp->y.HALF.HI = this->unk_3a; + tmp->collisionLayer = this->unk_37>>4; + } + tmp->x.HALF.HI += gRoomControls.roomOriginX; + tmp->y.HALF.HI += gRoomControls.roomOriginY; + DeleteManager(this); +} diff --git a/src/manager/manager30.c b/src/manager/manager30.c new file mode 100644 index 00000000..5f5ead82 --- /dev/null +++ b/src/manager/manager30.c @@ -0,0 +1,98 @@ +#include "global.h" +#include "manager.h" +#include "flags.h" +#include "functions.h" + +typedef struct Manager30 { + Manager manager; + u8 unk_20[8];//unused + u16 own_tile; + u8 unk_2a[0x2];//unused + u16 player_previous_tile; + u16 player_current_tile; + u8 unk_30[0x6];//unused + u8 width; + u8 height; + s16 x; + s16 y; + u16 flag_succeeded; + u16 flag_reset; +} Manager30; + +extern void sub_0807B7D8(u32, u32, u32); + +enum { + INIT, + IN_PROGRESS, + FAILED, + SUCCEEDED +}; + +/* + * Tile puzzles (step on all blue tiles exactly once). + * + * The Manager's field 0xe is used for the remaining number of tiles to be changed. + * field 0xf is used for the total number of tiles to be changed. +*/ +void Manager30_Main(Manager30* this) { + u32 i, j, tmp, tmp2; + switch (this->manager.action) { + default: + break; + case INIT: + this->manager.action = IN_PROGRESS; + this->manager.unk_0f = this->manager.unk_0e; + this->own_tile = (((this->x >> 4) & 0x3fU) | + ((this->y >> 4) & 0x3fU) << 6); + this->player_previous_tile = this->player_current_tile = COORD_TO_TILE((&gPlayerEntity)); + break; + case 1: + this->player_current_tile = COORD_TO_TILE((&gPlayerEntity)); + if (this->player_current_tile != this->player_previous_tile) { + this->player_previous_tile = this->player_current_tile; + switch (GetTileType(this->player_current_tile, this->manager.unk_0b)) { + case 0x317: + //stepped on a red tile again + this->manager.action = FAILED; + PlaySFX(0x6d); + break; + case 0x318: + //stepped on a blue tile + //turn the tile into a red tile + sub_0807B7D8(0x317, this->player_current_tile, this->manager.unk_0b); + PlaySFX(0x6b); + //decrease the number of remaining tiles and check if we're done + if (--this->manager.unk_0e == 0) { + this->manager.action = SUCCEEDED; + //set up delay for setting the flag/playing the success sfx + this->manager.unk_0e = 0x40; + } + break; + } + } + //fall through, can be reset in-progress + case FAILED: + if (!this->flag_reset) return;//can't be reset + if (!CheckFlags(this->flag_reset)) return;//wait for the flag telling it to reset + ClearFlag(this->flag_reset);//make sure the puzzle can be reset again later + this->manager.action = IN_PROGRESS; + this->manager.unk_0e = this->manager.unk_0f; + for (i = 0; i < this->height; i++) { + tmp = this->own_tile + (i << 6); + for (j = 0; j < this->width; j++) { + sub_0807BA8C(tmp + j, this->manager.unk_0b); + } + } + break; + case SUCCEEDED: + if (this->manager.unk_0e == 0) return; + tmp2 = --this->manager.unk_0e; + if (tmp2) { + if (tmp2 == 0x20) { + SetFlag(this->flag_succeeded); + } + } else { + PlaySFX(0x72); + } + } +} diff --git a/src/manager/manager5.c b/src/manager/manager5.c new file mode 100644 index 00000000..de4e08b9 --- /dev/null +++ b/src/manager/manager5.c @@ -0,0 +1,129 @@ +#include "global.h" +#include "manager.h" +#include "flags.h" +#include "functions.h" + + +typedef struct { + Manager manager; + u8 unk_20[0x08]; + u16 unk_28; + u16 unk_2a; + u16 unk_2c; + u16 unk_2e; + u16 unk_30; + u16 unk_32; + u8 unk_34[0x04]; + s16 unk_38; + s16 unk_3a; + u16 unk_3c; + u16 unk_3e; +} Manager5; + +void sub_08057AE8(Manager5*); +void sub_08057BA4(Manager5*); +void sub_08057C28(Manager5*); + +const u16 gUnk_08108024[] = { + 0, + -1, + 1, + 0, + 0, + 1, + -1, + 0 +}; +const u16 gUnk_08108034[] = { + 0, + 1, + -1, + 0, + 0, + -1, + 1, + 0 +}; + +void (*const gUnk_08108044[])(Manager5*) = { + sub_08057AE8, + sub_08057BA4, + sub_08057C28 +}; + +void sub_08057AD0(Manager5* this) { + gUnk_08108044[this->manager.action](this); +} + +void sub_08057CA4(Manager5*, u32, u32); + +extern void DeleteManager(Manager*); + +void sub_08057AE8(Manager5* this) { + u32 tmp; + tmp = (this->manager.unk_0b & 0x3)<<1; + if (this->manager.unk_0e == 1) { + this->unk_30 = 0x323; + } else { + this->unk_30 = tmp & 2 ? 0x37 : 0x36; + } + this->unk_28 = gUnk_08108024[tmp]; + this->unk_2a = gUnk_08108024[tmp+1]; + this->unk_2c = gUnk_08108034[tmp]; + this->unk_2e = gUnk_08108034[tmp+1]; + this->unk_32 = ((this->manager.unk_0b>>2)&0xF)+1; + this->manager.unk_0e = 0x1C; + this->manager.unk_0f = 0; + this->manager.action = (this->manager.unk_0b & 0x80)?2:1; + if (this->manager.action != 2 + || !CheckFlags(this->unk_3e)) return; + for (;this->unk_32;this->unk_32--) { + sub_08057CA4(this, this->unk_28, this->unk_2a); + sub_0807B7D8(this->unk_30, this->unk_38 | (this->unk_3a << 6),this->unk_3c); + } + DeleteManager(&this->manager); +} + +void sub_08057BA4(Manager5* this) { + if (--this->manager.unk_0e) return; + this->manager.unk_0e = 8; + if (CheckFlags(this->unk_3e)) { + if (this->unk_32 == this->manager.unk_0f) return; + sub_08057CA4(this, this->unk_28, this->unk_2a); + sub_0807B7D8(this->unk_30, this->unk_38 | (this->unk_3a << 6), this->unk_3c); + this->manager.unk_0f++; + PlaySFX(0x71); + } else { + if (!this->manager.unk_0f) return; + sub_0807BA8C(this->unk_38 | (this->unk_3a << 6), this->unk_3c); + sub_08057CA4(this, this->unk_2c, this->unk_2e); + this->manager.unk_0f--; + PlaySFX(0x71); + } +} + +void sub_08057C28(Manager5* this) { + if (!this->manager.unk_0d) { + if (!CheckFlags(this->unk_3e)) return; + this->manager.unk_0d++; + } else { + if (--this->manager.unk_0e) return; + this->manager.unk_0e = 8; + if (this->unk_32 != this->manager.unk_0f) { + sub_08057CA4(this, this->unk_28, this->unk_2a); + sub_0807B7D8(this->unk_30, this->unk_38 | (this->unk_3a << 6), this->unk_3c); + this->manager.unk_0f++; + PlaySFX(0x71); + } else { + if (this->unk_30 != 0x323) { + PlaySFX(0x72); + } + DeleteManager(&this->manager); + } + } +} + +void sub_08057CA4(Manager5* this, u32 unk1, u32 unk2) { + this->unk_38 += unk1; + this->unk_3a += unk2; +} diff --git a/src/manager/manager7.c b/src/manager/manager7.c new file mode 100644 index 00000000..14557946 --- /dev/null +++ b/src/manager/manager7.c @@ -0,0 +1,166 @@ +#include "global.h" +#include "manager.h" +#include "functions.h" +#include "gba/gba.h" + + +typedef struct { + Manager manager; + u8 unk_20; + u8 unk_21[0x1F]; +} Manager7; + +void sub_08057E30(); +u32 sub_08057E40(); +void sub_08057E64(); +void sub_08057E7C(u32); + +extern void sub_08052D74(); +extern u32 sub_08056300(const u16*); +extern void sub_0805E3A0(); + +extern u8 gUnk_02034490; +extern const u8 gGlobalGfxAndPalettes[]; + +const u16 gUnk_08108050[0x2A] = { + 0, 0, 0x20, 0xE0, + 0xE0, 1, 0, 0x1D0, + 0x80, 0x60, 2, 0x170, + 0x278, 0xF8, 0xA0, 3, + 0x310, 0x178, 0xC0, 0x150, + 3, 0x340, 0x2C8, 0x60, + 0x90, 4, 0x1D0, 0, + 0x200, 0xE0, 1, 0x108, + 0x188, 0xD0, 0x80, 2, + 0x1E8, 0x338, 0x50, 0xC0, + 0xFF, 0 +}; + +const u32 gUnk_081080A4[0x50] = { + 0x001095E0, 0x06000000, + 0x0010A5E0, 0x06001000, + 0x0010B5E0, 0x06002000, + 0x0010C5E0, 0x06003000, + 0x0010D5E0, 0x06008000, + 0x0010E5E0, 0x06009000, + 0x0010F5E0, 0x0600A000, + 0x001105E0, 0x0600B000, + 0x001115E0, 0x06000000, + 0x001125E0, 0x06001000, + 0x001135E0, 0x06002000, + 0x001145E0, 0x06003000, + 0x001155E0, 0x06008000, + 0x001165E0, 0x06009000, + 0x001175E0, 0x0600A000, + 0x001185E0, 0x0600B000, + 0x001195E0, 0x06000000, + 0x0011A5E0, 0x06001000, + 0x0011B5E0, 0x06002000, + 0x0011C5E0, 0x06003000, + 0x0011D5E0, 0x06008000, + 0x0011E5E0, 0x06009000, + 0x0011F5E0, 0x0600A000, + 0x001205E0, 0x0600B000, + 0x001215E0, 0x06000000, + 0x001225E0, 0x06001000, + 0x001235E0, 0x06002000, + 0x001245E0, 0x06003000, + 0x001255E0, 0x06008000, + 0x001265E0, 0x06009000, + 0x001275E0, 0x0600A000, + 0x001285E0, 0x0600B000, + 0x001295E0, 0x06000000, + 0x0012A5E0, 0x06001000, + 0x0012B5E0, 0x06002000, + 0x0012C5E0, 0x06003000, + 0x0012D5E0, 0x06008000, + 0x0012E5E0, 0x06009000, + 0x0012F5E0, 0x0600A000, + 0x001305E0, 0x0600B000 +}; + +const u8 gUnk_081081E4[] = { + 0x16, + 0x17, + 0x17, + 0x18, + 0x18 +}; + +void Manager7_Main(Manager7* this) { + u32 tmp; + const u32 * tmp2; + if (!this->manager.action) { + this->manager.action = 1; + this->manager.unk_0e = 8; + this->unk_20 = 0xFF; + sub_0805E3A0(this, 6); + sub_08052D74(this, sub_08057E30, 0); + } + if (sub_08057E40(this)) { + tmp = gRoomVars.unk_10; + if (this->unk_20 != tmp) { + this->unk_20 = tmp; + this->manager.unk_0e = 0; + } + } + if (gRoomControls.unk2) return; + tmp = this->unk_20; + tmp2 = &gUnk_081080A4[tmp<<4]; + switch (this->manager.unk_0e) { + case 0: + gUnk_02034490 = 1; + LoadAssetAsync(&gGlobalGfxAndPalettes[tmp2[0]], tmp2[1], 0x1000); + LoadPaletteGroup(gUnk_081081E4[tmp]); + this->manager.unk_0e++; + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + LoadAssetAsync(&gGlobalGfxAndPalettes[tmp2[(this->manager.unk_0e << 1)]], tmp2[(this->manager.unk_0e << 1)+1], 0x1000); + this->manager.unk_0e++; + break; + case 8: + gUnk_02034490 = 0; + this->manager.unk_0e++; + break; + } +} + +void sub_08057E30(Manager7* this) { + sub_08057E7C(gRoomVars.unk_10); +} + +u32 sub_08057E40(Manager7* this) { + u32 tmp = sub_08056300(gUnk_08108050); + if (tmp != 0xFF) { + gRoomVars.unk_10 = tmp; + return 1; + } else { + return 0; + } +} + +void sub_08057E64() { + u32 tmp; + tmp = sub_08056300(gUnk_08108050); + if (tmp != 0xFF) { + sub_08057E7C(tmp); + } +} + +void sub_08057E7C(u32 unk1) { + u32 tmp; + const u32* tmp2; + if (unk1 > 4) return; + LoadPaletteGroup(gUnk_081081E4[unk1]); + tmp2 = &gUnk_081080A4[unk1<<4]; + for (tmp = 0; tmp < 8; tmp++, tmp2 += 2) { + DmaSet(3,&gGlobalGfxAndPalettes[tmp2[0]],tmp2[1],0x84000400); + } + gRoomVars.unk_10 = unk1; +} diff --git a/src/manager/manager8.c b/src/manager/manager8.c new file mode 100644 index 00000000..2688bc42 --- /dev/null +++ b/src/manager/manager8.c @@ -0,0 +1,137 @@ +#include "global.h" +#include "manager.h" +#include "screen.h" +#include "functions.h" +#include "gba/gba.h" + +typedef struct { + Manager manager; + u8 unk_20; + u8 unk_21[0x17]; + u32 unk_38; + u32 unk_3c; +} Manager8; + +void sub_08057F20(Manager8*); +void sub_08057EFC(); +void sub_08058034(void); +void sub_08058084(u16*, u16*); + +extern void sub_08052D74(void*, void*, void*); + +extern u16 gMapDataTopSpecial[]; + +void sub_08057ED0(Manager8* this) { + sub_08057F20(this); + if (!this->manager.action) { + this->manager.action = 1; + gScreen.bg.bg2yOffset = 0; + gScreen.affine.unk4 = 0; + sub_08052D74(this, sub_08057EFC, 0); + } +} + +void sub_08057EFC(Manager8* this) { + LoadGfxGroup(gRoomVars.unk_10); + sub_08058034(); + this->unk_3c = 0; + this->unk_38 = 0; + sub_08057F20(this); +} + +void sub_08058004(u32, void*, void*); + +extern u8 gUnk_02001A40[]; +extern u8 gUnk_02006F00[]; + +void sub_08057F20(Manager8* this) { + u32 tmp; + tmp = gRoomControls.roomScrollX - gRoomControls.roomOriginX; + tmp = tmp + (tmp >> 3) + ((0x400 - gRoomControls.width)/2); + gScreen.affine.bg3xOffset = tmp&0xF; + gScreen.affine.bg3yOffset = 0x30 - ((0x30 - (gRoomControls.roomScrollY - gRoomControls.roomOriginY))>>2); + gScreen.affine.unk5 = gUnk_02001A40; + sub_08058004(tmp, gUnk_02006F00, gUnk_02001A40); + tmp = ((tmp>>4)<<1); + if (this->unk_38 != tmp) { + this->unk_38 = tmp; + gScreen.affine.unk4 = 1; + } + tmp = (gRoomControls.roomScrollX - gRoomControls.roomOriginX); + tmp = tmp + (tmp >> 2) + ((0x400 - gRoomControls.width)/2); + gScreen.bg.bg1yOffset = tmp&0xF; + gScreen.bg.bg2xOffset = 0x30 - ((0x30 - (gRoomControls.roomScrollY - gRoomControls.roomOriginY))>>1); + gScreen.bg.unk_14 = gUnk_02001A40 + 0x800; + sub_08058004(tmp, gUnk_02006F00 + 0x2000, gUnk_02001A40 + 0x800); + tmp = ((tmp>>4)<<1); + if (this->unk_3c != tmp) { + this->unk_3c = tmp; + gScreen.bg.bg2yOffset = 1; + } +} + +void sub_08058004(u32 unk1, void* unk2, void* unk3) { + u32 tmp = 0x20; + unk2 += (unk1 >> 4) << 2; + for (tmp; tmp != 0; tmp--) { + DmaSet(3, unk2, unk3, 0x80000020); + unk2 += 0x100; + unk3 += 0x40; + } +} + +void sub_08058034() { + u32 tmp; + u16 *tmp2, *tmp3; + tmp2 = gMapDataTopSpecial; + tmp3 = gMapDataTopSpecial + 0x2000; + for (tmp = 0; tmp < 4; tmp++) { + sub_08058084(tmp2, tmp3); + tmp2 += 0x400; + tmp3 += 0x20; + } + tmp2 = gMapDataTopSpecial + 0x1000; + tmp3 = gMapDataTopSpecial + 0x3000; + for (tmp = 0; tmp < 4; tmp++) { + sub_08058084(tmp2, tmp3); + tmp2 += 0x400; + tmp3 += 0x20; + } +} + +void sub_08058084(u16* unk1, u16* unk2) { + u32 tmp; + for (tmp = 0; tmp < 0x20; tmp++, unk1+=0x20, unk2+=0x80) { + DmaSet(3,unk1,unk2,0x80000020); + } +} + +extern u32 gUnk_0200B650; + +void sub_080580B0(u32 unk1) { + s32 tmp; + gUnk_0200B650 = 0; + REG_DISPCNT = 0; + LoadGfxGroup(unk1); + gRoomVars.unk_10 = unk1; + sub_08058034(); + tmp = gRoomControls.roomScrollX - gRoomControls.roomOriginX;//r7 + tmp = tmp + (tmp >> 3) + (0x400 - gRoomControls.width) / 2; + sub_08058004(tmp, gUnk_02006F00, gUnk_02001A40); + gScreen.affine.bg3xOffset = tmp & 0xF; + gScreen.affine.bg3yOffset = 0x30 - ((0x30 - (gRoomControls.roomScrollY - gRoomControls.roomOriginY))>>1);//? + gScreen.affine.bg3Control = 0x1D09; + gScreen.affine.unk5 = gUnk_02001A40; + gScreen.affine.unk4 = 1; + tmp = gRoomControls.roomScrollX - gRoomControls.roomOriginX;//r7 + tmp = tmp + (tmp >> 2) + (0x400 - gRoomControls.width) / 2; + sub_08058004(tmp, gUnk_02006F00 + 0x2000, gUnk_02001A40 + 0x800); + gScreen.bg.bg1yOffset = tmp & 0xF; + gScreen.bg.bg2xOffset = 0x30 - ((0x30 - (gRoomControls.roomScrollY - gRoomControls.roomOriginY))>>1);//? + gScreen.bg.bg1xOffset = 0x1E09; + gScreen.bg.unk_14 = gUnk_02001A40 + 0x800; + gScreen.bg.bg2yOffset = 1; + gScreen.controls.layerFXControl = 0x3C48; + gScreen.controls.alphaBlend = 0x609; + gScreen.lcd.displayControl |= 0xa00; +} diff --git a/src/manager/managerB.c b/src/manager/managerB.c index 763e89ea..a23faacf 100644 --- a/src/manager/managerB.c +++ b/src/manager/managerB.c @@ -6,25 +6,42 @@ #include "area.h" #include "functions.h" -extern void (*(gUnk_08108208[]))(Manager*); +/* + * Manager B is used to create fights: + * It possibly waits for an inhibitor flag to be set, then spawns a bunch of entities (based on room data). + * Once all enemies created this way are dead, it sets a flag. + * (There is also a part about changing the music and setting it back when the fight is done, which is song 0x33 (a fight theme) by default but can be overridden through room data) +*/ + +void (*const ManagerB_ActionFuncs[])(Manager*); void sub_080585F0(Manager* this) { - gUnk_08108208[this->unk_0a](this); + //make a distincion if this is a controller (unk_0a = 0) or a helper (unk_0a = 1) + ManagerB_ActionFuncs[this->unk_0a](this); } -extern void (*(gUnk_08108210[]))(Manager*); +enum ManagerB_State { + Init, + WaitForFlag, + WaitForDone +}; + +void (*const ManagerB_StateFuncs[])(ManagerB*); -void sub_08058608(Manager* this) { - gUnk_08108210[this->action](this); +void ManagerB_Main(ManagerB* this) { + //make a distinction based on the state of this controller + ManagerB_StateFuncs[this->manager.action](this); } -void sub_080586EC(Manager*); +void ManagerB_LoadFight(Manager*); -void sub_08058620(ManagerB* this) { +void ManagerB_Init(ManagerB* this) { + //check if the fight was already completed previously (checks the flag that gets set after the fight is done) if (!CheckFlags(this->unk_3e)) { - this->manager.action = 1; + this->manager.action = WaitForFlag; + //if there is no flag that needs to be set before the fight is started, start it immediately if (!this->unk_3c) { - sub_080586EC(&this->manager); + ManagerB_LoadFight(&this->manager); } sub_0805E3A0(this, 3); } else { @@ -33,10 +50,10 @@ void sub_08058620(ManagerB* this) { } extern void sub_080186C0(u32); -void sub_08058650(ManagerB* this) { +void ManagerB_WaitForFlag(ManagerB* this) { int tmp; if (CheckFlags(this->unk_3c)) { - sub_080586EC(&this->manager); + ManagerB_LoadFight(&this->manager); if (!this->unk_35) { tmp = gRoomVars.field_0x9 ? gRoomVars.field_0x9 : 0x33; this->unk_20 = gArea.musicIndex; @@ -49,9 +66,12 @@ void sub_08058650(ManagerB* this) { extern void sub_0801855C(void); -void sub_080586A8(ManagerB* this) { +void ManagerB_WaitForDone(ManagerB* this) { + //check if all helpers are done if (this->manager.unk_0e) return; + //set the completion flag for the fight SetFlag(this->unk_3e); + //restore music (if it was set, which apparently is only possible if there's a flag the fight waited for) if (this->unk_3c) { if (!this->unk_35) { gArea.musicIndex = this->unk_20; @@ -62,40 +82,45 @@ void sub_080586A8(ManagerB* this) { DeleteThisEntity(); } -ManagerBHelper* sub_08058760(Manager*); -void sub_08058798(ManagerBHelper*, Entity*, u32); +ManagerBHelper* CreateHelper(Manager*); +void ManagerBHelper_Monitor(ManagerBHelper*, Entity*, u32); extern EntityData* GetCurrentRoomProperty(u8); extern Entity* LoadRoomEntity(EntityData*); -void sub_080586EC(Manager* this) { - ManagerBHelper* tmp; +void ManagerB_LoadFight(Manager* this) { + ManagerBHelper* monitor; EntityData* prop; Entity* ent; u32 counter; this->action = 2; this->unk_0e = 0; counter = 0; - tmp = sub_08058760(this); - if (!tmp) DeleteThisEntity(); + //Create a helper to keep track of the created entities. + monitor = CreateHelper(this); + if (!monitor) DeleteThisEntity(); prop = (EntityData*) GetCurrentRoomProperty(this->unk_0b); if (prop) { while (*((u8*)prop) != 0xFF) { ent = LoadRoomEntity(prop++); if (ent && (ent->entityType.type == 3)) { ent->field_0x6c.HALF.HI |= 0x40; - sub_08058798(tmp, ent, counter++); + ManagerBHelper_Monitor(monitor, ent, counter++); } if (counter >= 7) { counter = 0; - tmp = sub_08058760(this); - if (!tmp) return; + monitor = CreateHelper(this); + if (!monitor) return; } } } } -ManagerBHelper* sub_08058760(Manager* this) { +/* + * Create a helper and increment the counter for the number of helpers (unk_0e). + * The helper will decrease said counter when it deletes itself (when none of the enemies it monitors remain). +*/ +ManagerBHelper* CreateHelper(Manager* this) { ManagerBHelper* extra; extra = (ManagerBHelper*) GetEmptyManager(); if (extra) { @@ -110,51 +135,67 @@ ManagerBHelper* sub_08058760(Manager* this) { return extra; } -void sub_08058798(ManagerBHelper* this, Entity* value, u32 index) { - this->enemies[index]=value; +void ManagerBHelper_Monitor(ManagerBHelper* this, Entity* ent, u32 index) { + this->enemies[index]=ent; this->manager.unk_0e++; } -void sub_080587AC(ManagerBHelper* this) { - u8 i, tmp; +//case unk_0a is 1: The manager is a helper + +void ManagerBHelper_Main(Manager* this) { + u8 i, anyRemaining; Entity* current; - if (this->manager.action == 0) { - this->manager.action = 1; + if (this->action == 0) { + this->action = 1; sub_0805E3A0(this,3); } - tmp = 0; + //go through and check all monitored enemies. + anyRemaining = 0; for (i = 0; i < 8; i++) { - if ((current = this->enemies[i])) { + if ((current = ((ManagerBHelper*)this)->enemies[i])) { if (!current->next) { - this->enemies[i] = 0; + ((ManagerBHelper*) this)->enemies[i] = 0; } else { - tmp = 1; + anyRemaining = 1; } } } - if (!tmp) { - if (((ManagerB*) this->manager.parent)->manager.unk_0e) { - ((ManagerB*) this->manager.parent)->manager.unk_0e--; + if (!anyRemaining) { + //inform the parent that we're done + if (((ManagerB*) this->parent)->manager.unk_0e) { + ((ManagerB*) this->parent)->manager.unk_0e--; } - DeleteThisEntity(); + DeleteThisEntity(); } } extern Manager gUnk_03003DB0; -void sub_08058800(Entity* this, Entity* unk1) { +/* + * Replace an entity that is currently being monitored with a new one +*/ +void ReplaceMonitoredEntity(Entity* old, Entity* new) { ManagerBHelper* current; Manager* end = &gUnk_03003DB0; u32 i; for (current = (ManagerBHelper*) end->next; (Manager*)current != end; current=(ManagerBHelper*)current->manager.next) { if (current->manager.type != 0x9 || current->manager.subtype != 0xB) continue; for (i = 0; i < 8; i++) { - if (this == current->enemies[i]) { - current->enemies[i] = unk1; + if (old == current->enemies[i]) { + current->enemies[i] = new; return; } } } } +void (*const ManagerB_ActionFuncs[])(Manager*) = { + (void (*)(Manager*)) ManagerB_Main, + (void (*)(Manager*)) ManagerBHelper_Main +}; +void (*const ManagerB_StateFuncs[])(ManagerB*) = { + ManagerB_Init, + ManagerB_WaitForFlag, + ManagerB_WaitForDone +}; diff --git a/src/npc/bigGoron.c b/src/npc/bigGoron.c index 694ec6f7..bb28c9f0 100644 --- a/src/npc/bigGoron.c +++ b/src/npc/bigGoron.c @@ -2,16 +2,15 @@ #include "entity.h" #include "player.h" #include "structures.h" +#include "functions.h" extern void (*gUnk_081140D4[])(Entity*); extern u16 gUnk_081140CC[]; -extern void sub_0805E3A0(Entity*, u32); extern void sub_0806D0B0(Entity*); extern void sub_0807DD64(Entity*); extern void sub_0807DDAC(Entity*, u32); extern void sub_0807DDE4(Entity*); -extern u32 Random(void); extern void PlaySFX(u32); extern void sub_0806D02C(Entity*); extern Entity* FindEntityInListByForm(u32, u32, u32, u32, u32); diff --git a/src/npc/carlov.c b/src/npc/carlov.c index 6265d07c..b5251365 100644 --- a/src/npc/carlov.c +++ b/src/npc/carlov.c @@ -10,7 +10,7 @@ extern void sub_0807DD50(Entity *); extern void sub_0807DD94(Entity *,u32); -extern void sub_08004488(u32); +extern void EnqueueSFX(u32); extern void sub_08080964(u32,u32); @@ -25,11 +25,11 @@ void Carlov(Entity *this) } if ((this->frames.all & 0x10) != 0) { this->frames.all = this->frames.all & 0xef; - sub_08004488(0x104); + EnqueueSFX(0x104); sub_08080964(0x10,0); } if ((this->frames.all & 0x20) != 0) { this->frames.all = this->frames.all & 0xdf; - sub_08004488(0x7c); + EnqueueSFX(0x7c); } } diff --git a/src/npc/cow.c b/src/npc/cow.c index 9c62c898..edd4a9d3 100644 --- a/src/npc/cow.c +++ b/src/npc/cow.c @@ -1,23 +1,20 @@ #include "global.h" #include "entity.h" #include "player.h" +#include "functions.h" -extern void sub_0806ED78(Entity*); extern void sub_0806920C(Entity*); extern u32 sub_0805ACC0(Entity*); extern u32 sub_0801E99C(Entity*); extern void sub_0806924C(Entity*); -extern void sub_080AEF88(Entity*); -extern void ShowNPCDialogue(Entity*, u32*); extern void sub_08078778(Entity*); extern void sub_080787A8(Entity*, u32); extern void sub_0806F118(Entity*); extern void sub_080791D0(); extern void (*gUnk_08111914[])(Entity*); extern void (*gUnk_08111928[])(Entity*); -extern u32 gUnk_08111938[]; +extern Dialog gUnk_08111938[]; extern void PlaySFX(u32); -extern u32 Random(); extern u32 UpdateFuseInteraction(Entity*); extern PlayerState gPlayerState; @@ -96,7 +93,7 @@ void sub_08069068(Entity* ent) { InitAnimationForceUpdate(ent, ent->animationState + 4); } - sub_080AEF88(ent); + ProcessMovement(ent); UpdateAnimationSingleFrame(ent); { @@ -184,9 +181,7 @@ void sub_080691E0(Entity* ent) { // Show dialogue void Cow_ShowDialogue(Entity* ent) { - u32 var0 = ent->entityType.form; - u32* var1 = gUnk_08111938 + (var0 * 2); - ShowNPCDialogue(ent, var1); + ShowNPCDialogue(ent, &gUnk_08111938[ent->entityType.form]); } void sub_0806920C(Entity* ent) { diff --git a/src/npc/epona.c b/src/npc/epona.c index 89c18204..69368bc3 100644 --- a/src/npc/epona.c +++ b/src/npc/epona.c @@ -8,7 +8,7 @@ void sub_08065A64(Entity* this); void sub_08065AA4(Entity*); extern void (*gUnk_0811006C[])(Entity*); -extern u32 gUnk_08110080[]; +extern Dialog gUnk_08110080[]; void Epona(Entity* this) { gUnk_0811006C[this->action](this); @@ -50,7 +50,7 @@ void sub_08065A34(Entity* this) { } void sub_08065A50(Entity* this) { - ShowNPCDialogue(this, &gUnk_08110080[this->entityType.form * 2]); + ShowNPCDialogue(this, &gUnk_08110080[this->entityType.form]); } void sub_08065A64(Entity* this) { diff --git a/src/npc/festari.c b/src/npc/festari.c index 3a86130c..dccde267 100644 --- a/src/npc/festari.c +++ b/src/npc/festari.c @@ -10,7 +10,6 @@ extern void sub_0807DD50(Entity*); extern void sub_0806F118(Entity*); extern void ExecuteScriptCommandSet(Entity*, void *); extern void sub_0805FF2C(Entity*, void*); -extern void sub_0806ED78(Entity*); extern void (*const gUnk_08109BBC[])(Entity*); diff --git a/src/npc/forestMinish.c b/src/npc/forestMinish.c index 08555a0c..abf4878d 100644 --- a/src/npc/forestMinish.c +++ b/src/npc/forestMinish.c @@ -5,31 +5,29 @@ #include "textbox.h" #include "player.h" #include "structures.h" +#include "functions.h" -extern void sub_0805E3A0(Entity*, u32); -extern void StartCutscene(Entity*, void*); extern void sub_0807DD50(Entity*); extern void sub_0806F118(Entity*); extern void sub_0807DDAC(Entity*, u32); extern void sub_0807DDE4(Entity*); extern void sub_080600F0(Entity*); +extern s32 sub_0806EDD8(Entity*, u32, u32); +extern u32 sub_0806F5B0(u32); extern u32 sub_0801E99C(Entity*); extern void sub_08078784(Entity*, u32); extern void sub_0807000C(Entity*); -extern void sub_080042BA(Entity*, u32); extern void sub_08060158(Entity*); extern u32 CheckKinstoneFused(u32); extern Entity* FindEntityInListBySubtype(u32, u32, u32); -extern void sub_080A29BC(Entity* parent); extern void DeleteEntity(Entity*); -extern u32 Random(void); extern void ModBombs(s32); extern SpriteLoadData gUnk_0810A348; -extern void* gUnk_08109D18[]; +extern u8* gUnk_08109D18[]; extern u8 gUnk_08109C98[]; extern u16 gUnk_0810A354[]; -extern u32 gUnk_08109DC8[]; +extern Dialog gUnk_08109DC8[]; extern u16 gUnk_0810A35A[]; extern u16 gUnk_0810A362[]; @@ -116,40 +114,36 @@ void sub_0806014C(Entity* this) { sub_08060158(this); } -#if 0 -void sub_08060158(Entity *this) -{ - u8 bVar1; - u8 bVar2; - s32 iVar4; - u32 temp; - if (this->actionDelay != 0) { - this->actionDelay--; - } - else { - this->actionDelay = 2; - iVar4 = sub_0806EDD8(this, 0x20, 0x20); - if (iVar4 < 0) { - this->animationState = this->field_0x68.HALF.HI; - iVar4 = this->field_0x68.HALF.HI << 2; - } - temp = (this->animationState >> 1) * 0x20 + (iVar4 >> 1) * 2; - bVar1 = gUnk_08109C98[temp]; - bVar2 = gUnk_08109C98[temp + 1]; - if ((bVar2 & 0x80) != 0) { - this->animationState = sub_0806F5B0(iVar4); - } - this->frames.all = bVar1; - this->frameIndex = bVar2 & 0x7f; - this->frameSpriteSettings = 1; - this->animIndex = 0; - this->frameDuration = 0xf0; - } -} -#endif -NAKED void sub_08060158(Entity* this) { - asm(".include \"asm/non_matching/forestMinish/sub_08060158.inc\""); + int index; + u8* idx3; + u8 tmp1, tmp2; + + if (this->actionDelay) { + this->actionDelay--; + } else { + this->actionDelay = 2; + index = sub_0806EDD8(this, 0x20, 0x20); + if (index < 0) { + int state = this->field_0x68.HALF.HI; + this->animationState = state; + index = state * 4; + } + + idx3 = gUnk_08109C98 + (this->animationState / 2) * 0x20 + (index >> 1) * 2; + tmp1 = idx3[0]; + tmp2 = idx3[1]; + + if (tmp2 & 0x80) { + this->animationState = sub_0806F5B0(index); + } + tmp2 &= 0x7f; + this->frames.all = tmp1; + this->frameIndex = tmp2; + this->frameSpriteSettings = 1; + this->animIndex = 0; + this->frameDuration = 0xf0; + } } void sub_080601D4(Entity* this) { @@ -165,141 +159,125 @@ void sub_080601D4(Entity* this) { TextboxNoOverlap(gUnk_0810A354[uVar2], this); } -void sub_08060208(Entity *this) -{ - ShowNPCDialogue(this, &gUnk_08109DC8[this->entityType.parameter * 0x8]); +void sub_08060208(Entity* this) { + ShowNPCDialogue(this, &gUnk_08109DC8[this->entityType.parameter * 0x4]); } -void sub_0806021C(Entity *this) -{ - u32 uVar1; - u32 uVar2; - - //jabber nut - uVar1 = GetInventoryValue(0x5B); - uVar2 = (-uVar1 | uVar1) >> 0x1f; - - //earth element - if (GetInventoryValue(0x40)) { - uVar2 = 2; - } - - //mole mitts - if (GetInventoryValue(0x13)) { - uVar2 = 3; - } - ShowNPCDialogue(this, gUnk_08109DC8 + this->entityType.parameter * 0x8 + uVar2 * 2); +void sub_0806021C(Entity* this) { + u32 uVar1; + u32 uVar2; + + // jabber nut + uVar1 = GetInventoryValue(0x5B); + uVar2 = (-uVar1 | uVar1) >> 0x1f; + + // earth element + if (GetInventoryValue(0x40)) { + uVar2 = 2; + } + + // mole mitts + if (GetInventoryValue(0x13)) { + uVar2 = 3; + } + ShowNPCDialogue(this, gUnk_08109DC8 + this->entityType.parameter * 0x4 + uVar2); } -void sub_0806025C(Entity *this) -{ - ShowNPCDialogue(this, &gUnk_08109DC8[this->entityType.parameter * 0x8]); +void sub_0806025C(Entity* this) { + ShowNPCDialogue(this, &gUnk_08109DC8[this->entityType.parameter * 0x4]); } -void sub_08060270(Entity *this) -{ - u32 index; +void sub_08060270(Entity* this) { + u32 index; - //flippers - if (GetInventoryValue(0x46) == 0) { - index = 1; - if (CheckGlobalFlag(MIZUKAKI_START) == 0) { - index = 0; - SetGlobalFlag(MIZUKAKI_START); - } - } - else { - index = 3; - if (CheckLocalFlag(0x76) == 0) { - index = 2; - SetLocalFlag(0x76); + // flippers + if (GetInventoryValue(0x46) == 0) { + index = 1; + if (CheckGlobalFlag(MIZUKAKI_START) == 0) { + index = 0; + SetGlobalFlag(MIZUKAKI_START); + } + } else { + index = 3; + if (CheckLocalFlag(0x76) == 0) { + index = 2; + SetLocalFlag(0x76); + } } - } - TextboxNoOverlap(gUnk_0810A35A[index], this); + TextboxNoOverlap(gUnk_0810A35A[index], this); } -void sub_080602BC(Entity *this) -{ - u32 index; - - //spin attack +void sub_080602BC(Entity* this) { + u32 index; + + // spin attack if (GetInventoryValue(0x48) != 0) { - index = (Random() & 1) + 2; - } - else { - if (gUnk_02002A40.stats.bombCount < gBombBagSizes[gUnk_02002A40.stats.bombBagType]) { - index = 1; - } - else { - index = 0; + index = (Random() & 1) + 2; + } else { + if (gUnk_02002A40.stats.bombCount < gBombBagSizes[gUnk_02002A40.stats.bombBagType]) { + index = 1; + } else { + index = 0; + } } - } - TextboxNoOverlap(gUnk_0810A362[index], this); + TextboxNoOverlap(gUnk_0810A362[index], this); } -void sub_0806030C(Entity* this, u32 *arg1) -{ +void sub_0806030C(Entity* this, u32* arg1) { ModBombs(*(arg1 + 1)); } -void sub_08060318(void) -{ - Entity *ent; - int i; - - for (i = 2; i >= 0; i--) { - ent = FindEntityInListBySubtype(8, 2, 2); - if (ent != NULL) { - sub_080A29BC(ent); - DeleteEntity(ent); +void sub_08060318(void) { + Entity* ent; + int i; + + for (i = 2; i >= 0; i--) { + ent = FindEntityInListBySubtype(8, 2, 2); + if (ent != NULL) { + CreateDust(ent); + DeleteEntity(ent); + } } - } } -void sub_08060340(void) -{ - gUnk_02002A40.unk490 = gUnk_02002A40.unk50; +void sub_08060340(void) { + gUnk_02002A40.unk490 = gUnk_02002A40.unk50; } -u32 sub_08060354(void) -{ - u32 iVar1; - s32 iVar2; - - iVar2 = gUnk_02002A40.unk50 - gUnk_02002A40.unk490; - if (CheckGlobalFlag(DRUG_1) == 0) { - if (4 < iVar2) { - return 0x8444; - } - } - else { - if (CheckGlobalFlag(DRUG_2) == 0) { - if (iVar2 > 9) { - return 0x8444; - } - } - else { - if (CheckGlobalFlag(DRUG_3) == 0) { - if (iVar2 > 14) { - return 0x8444; - } - } +u32 sub_08060354(void) { + u32 iVar1; + s32 iVar2; + + iVar2 = gUnk_02002A40.unk50 - gUnk_02002A40.unk490; + if (CheckGlobalFlag(DRUG_1) == 0) { + if (4 < iVar2) { + return 0x8444; + } + } else { + if (CheckGlobalFlag(DRUG_2) == 0) { + if (iVar2 > 9) { + return 0x8444; + } + } else { + if (CheckGlobalFlag(DRUG_3) == 0) { + if (iVar2 > 14) { + return 0x8444; + } + } + } } - } - return 0; + return 0; } -void ForestMinish_Fusion(Entity *this) -{ - if (this->action == 0) { - if (LoadExtraSpriteData(this, &gUnk_0810A348)) { - this->action++; - this->spriteSettings.b.draw = TRUE; - sub_0805E3A0(this, 2); - InitializeAnimation(this, 6); +void ForestMinish_Fusion(Entity* this) { + if (this->action == 0) { + if (LoadExtraSpriteData(this, &gUnk_0810A348)) { + this->action++; + this->spriteSettings.b.draw = TRUE; + sub_0805E3A0(this, 2); + InitializeAnimation(this, 6); + } + } else { + GetNextFrame(this); } - } - else { - GetNextFrame(this); - } } diff --git a/src/npc/goron.c b/src/npc/goron.c index 0fa725e4..08ddcc5a 100644 --- a/src/npc/goron.c +++ b/src/npc/goron.c @@ -3,9 +3,10 @@ #include "functions.h" #include "textbox.h" +extern u8 gUnk_02033280[]; extern void (*gUnk_08111A80[])(Entity*); extern void (*gUnk_08111A8C[])(Entity*); -extern u8 gUnk_02033280[]; +extern Dialog gUnk_08111A94[]; void Goron(Entity* this) { if (this->flags & 2) { @@ -72,7 +73,7 @@ void sub_080693D0(Entity* this) { } if (this->frames.all == 2) { this->frames.all = 0; - sub_08069428(this, 0x80<<12, createFx65); + sub_08069428(this, 0x80 << 12, createFx65); } } } @@ -110,16 +111,16 @@ void sub_080694B0(Entity* this) { } } -extern u64 gUnk_08111A94[]; //array of unknown 64 bit structure type void sub_080694D8(Entity* this) { - ShowNPCDialogue(this, (u32*)&gUnk_08111A94[this->entityType.form]); + ShowNPCDialogue(this, &gUnk_08111A94[this->entityType.form]); } void sub_080694EC(Entity* this) { u32 anim; this->animationState = 4; anim = 2; - if (!CheckKinstoneFused(47)) anim = 8; + if (!CheckKinstoneFused(47)) + anim = 8; InitAnimationForceUpdate(this, anim); this->field_0x80.HWORD = anim; } diff --git a/src/npc/librari.c b/src/npc/librari.c index 23a7a846..27b20ad8 100644 --- a/src/npc/librari.c +++ b/src/npc/librari.c @@ -84,24 +84,12 @@ void sub_0806b2b4(Entity* this) { TextboxNoOverlap(gUnk_08112D50[index], this); } -void Librari_Fusion(Entity *this) -{ - if (this->action == 0) { - this->action++; - this->spriteSettings.b.draw = TRUE; - InitAnimationForceUpdate(this, 9); - } - else { - UpdateAnimationSingleFrame(this); - } -} - -void Percy_Head(Entity *this) // ??? -{ - SetExtraSpriteFrame(this, 0, (this->frameSpriteSettings & 0x3f) + 0x13); - SetExtraSpriteFrame(this, 1, (this->frames.all & 0x7f) + 0xb); - SetExtraSpriteFrame(this, 2, this->frameIndex); - SetSpriteSubEntryOffsetData1(this, 2, 1); - SetSpriteSubEntryOffsetData2(this, 2, 0); - sub_0807000C(this); +void Librari_Fusion(Entity* this) { + if (this->action == 0) { + this->action++; + this->spriteSettings.b.draw = TRUE; + InitAnimationForceUpdate(this, 9); + } else { + UpdateAnimationSingleFrame(this); + } } diff --git a/src/npc/mayorHagen.c b/src/npc/mayorHagen.c index 7572e907..c337bbea 100644 --- a/src/npc/mayorHagen.c +++ b/src/npc/mayorHagen.c @@ -7,33 +7,30 @@ #include "textbox.h" #include "npc.h" #include "structures.h" +#include "functions.h" extern void sub_0807DD50(Entity*); extern u32 sub_0806F5A4(u32); extern void sub_0806F118(Entity*); -extern u32 sub_0801E99C(); -extern void sub_08078784(Entity*,u32); -extern void sub_0807DDAC(Entity*,u32); -extern void sub_0805E3A0(Entity*,u32); +extern void sub_08078784(Entity*, u32); +extern void sub_0807DDAC(Entity*, u32); extern void sub_0807DDE4(Entity*); extern void sub_08078850(); extern u32 gUnk_08113F44; -extern u32 gUnk_08113F48; +extern Dialog gUnk_08113F48[]; extern u32 GetInventoryValue(u32); extern u32 CheckLocalFlag(u32); extern void SetLocalFlag(); -extern void ShowNPCDialogue(); -void MayorHagen(Entity *this) -{ +void MayorHagen(Entity* this) { u32 v; switch (this->action) { case 0: - this->action = 1; - this->field_0x68.HALF.HI = 0; - this->field_0x68.HALF.LO = sub_0801E99C(this); - sub_0805E3A0(this, 2); - sub_0807DD50(this); + this->action = 1; + this->field_0x68.HALF.HI = 0; + this->field_0x68.HALF.LO = sub_0801E99C(this); + sub_0805E3A0(this, 2); + sub_0807DD50(this); break; case 1: v = this->interactType; @@ -41,11 +38,11 @@ void MayorHagen(Entity *this) this->action = v; this->interactType = 0; this->field_0x68.HALF.HI = this->animIndex; - InitAnimationForceUpdate(this,4 + sub_0806F5A4(GetFacingDirection(this, &gPlayerEntity))); + InitAnimationForceUpdate(this, 4 + sub_0806F5A4(GetFacingDirection(this, &gPlayerEntity))); sub_0806F118(this); break; } - sub_0807DDAC(this,0); + sub_0807DDAC(this, 0); sub_0807DDE4(this); UpdateAnimationSingleFrame(this); break; @@ -57,49 +54,43 @@ void MayorHagen(Entity *this) } } -void sub_0806CE5C(Entity *this) -{ - sub_08078784(this,sub_0801E99C()); - sub_08078850(this,1,0,&gUnk_08113F44); +void sub_0806CE5C(Entity* this) { + sub_08078784(this, sub_0801E99C(this)); + sub_08078850(this, 1, 0, &gUnk_08113F44); } -void sub_0806CE80(Entity *this) -{ +void sub_0806CE80(Entity* this) { u32 v; u32 v2; v = gUnk_02002A40.unk8; - if (v == 5) { - //flippers - if (GetInventoryValue(0x46) == 0) { - if (CheckLocalFlag(0x70) != 0) { - v2 = CheckLocalFlag(0x71); - if (v2 == 0) { - v = 0xb; - SetLocalFlag(0x71); - } - else { - v = 0xc; - } - } - else { + if (v == 5) { + // flippers + if (GetInventoryValue(0x46) == 0) { + if (CheckLocalFlag(0x70) != 0) { + v2 = CheckLocalFlag(0x71); + if (v2 == 0) { + v = 0xb; + SetLocalFlag(0x71); + } else { + v = 0xc; + } + } else { v = 0xa; } - } - else { - v2 = CheckLocalFlag(0x89); - if (v2 == 0) { - v = 0xd; - SetLocalFlag(0x89); - } - else { - v = 0xe; - } + } else { + v2 = CheckLocalFlag(0x89); + if (v2 == 0) { + v = 0xd; + SetLocalFlag(0x89); + } else { + v = 0xe; + } + } } - } - ShowNPCDialogue(this,&gUnk_08113F48 + 2*v); + ShowNPCDialogue(this, &gUnk_08113F48[v]); } -void MayorHagen_Fusion(Entity *this) { +void MayorHagen_Fusion(Entity* this) { if (this->action == 0) { this->action++; this->spriteSettings.b.draw = 1; diff --git a/src/npc/melari.c b/src/npc/melari.c index a50d4aad..ed324001 100644 --- a/src/npc/melari.c +++ b/src/npc/melari.c @@ -4,16 +4,14 @@ #include "textbox.h" #include "functions.h" -extern void sub_0806ED78(Entity*); extern void sub_08068780(Entity*); extern void sub_08078778(Entity*); -extern u32 Random(void); extern void sub_0807DD50(Entity*); extern void sub_0806F118(Entity*); extern void sub_0807DDAC(Entity*, u32); extern void sub_0807DDE4(Entity*); extern u32 sub_080040A8(Entity*); -extern void sub_08004488(u32); +extern void EnqueueSFX(u32); extern u32 sub_0801E99C(Entity*); extern void sub_08078784(Entity*, u32); extern void sub_0807000C(Entity*); @@ -100,7 +98,7 @@ void sub_08068780(Entity* this) { if (sub_080040A8(this) == 0) { PlaySFX(gUnk_0811153E[(s32)Random() % 3]); } else { - sub_08004488(gUnk_08111538[(s32)Random() % 3]); + EnqueueSFX(gUnk_08111538[(s32)Random() % 3]); } ent = CreateFx(this, 0x3d, 0x20); if (ent != NULL) { diff --git a/src/npc/mutoh.c b/src/npc/mutoh.c index f0a28ff5..1be4d5e8 100644 --- a/src/npc/mutoh.c +++ b/src/npc/mutoh.c @@ -5,8 +5,8 @@ #include "textbox.h" #include "npc.h" #include "structures.h" +#include "functions.h" -extern void sub_0805E3A0(Entity*, u32); extern void sub_0807DD50(Entity*); extern u32 GetFacingDirection(Entity*, Entity*); extern u32 sub_0806F5A4(u32); @@ -19,10 +19,9 @@ extern void sub_08078784(Entity*, u32); extern SpriteLoadData gUnk_08110C00; extern u16 gUnk_08110C0C[]; -extern u32 gUnk_08110C10[]; +extern Dialog gUnk_08110C10[]; -void Mutoh(Entity* this) -{ +void Mutoh(Entity* this) { if (*(u32*)&this->cutsceneBeh == 0) { DeleteThisEntity(); } @@ -30,11 +29,11 @@ void Mutoh(Entity* this) switch (this->action) { case 0: if (LoadExtraSpriteData(this, &gUnk_08110C00)) { - this->action = 1; - this->spriteSettings.b.draw = TRUE; - sub_0805E3A0(this, 2); - sub_0807DD50(this); - } + this->action = 1; + this->spriteSettings.b.draw = TRUE; + sub_0805E3A0(this, 2); + sub_0807DD50(this); + } break; case 1: if (this->interactType == 2) { @@ -53,48 +52,42 @@ void Mutoh(Entity* this) } } -void Mutoh_Head(Entity *this) -{ - SetExtraSpriteFrame(this, 0, (this->frames.all & -0x81)); - SetExtraSpriteFrame(this, 1, this->frameIndex); - SetSpriteSubEntryOffsetData1(this,1,0); - sub_0807000C(this); +void Mutoh_Head(Entity* this) { + SetExtraSpriteFrame(this, 0, (this->frames.all & -0x81)); + SetExtraSpriteFrame(this, 1, this->frameIndex); + SetSpriteSubEntryOffsetData1(this, 1, 0); + sub_0807000C(this); } -void sub_080670B4(Entity *this) -{ - u32 uVar1; - u32 uVar2; - - uVar2 = 0; - if (GetInventoryValue(0x11) == 0) { - uVar1 = CheckGlobalFlag(TABIDACHI); - uVar2 = (-uVar1 | uVar1) >> 0x1f; - } - TextboxNoOverlap(gUnk_08110C0C[uVar2],this); +void sub_080670B4(Entity* this) { + u32 uVar1; + u32 uVar2; + + uVar2 = 0; + if (GetInventoryValue(0x11) == 0) { + uVar1 = CheckGlobalFlag(TABIDACHI); + uVar2 = (-uVar1 | uVar1) >> 0x1f; + } + TextboxNoOverlap(gUnk_08110C0C[uVar2], this); } -void sub_080670E4(Entity *this) -{ - ShowNPCDialogue(this, &gUnk_08110C10[gUnk_02002A40.unk8 * 2]); +void sub_080670E4(Entity* this) { + ShowNPCDialogue(this, &gUnk_08110C10[gUnk_02002A40.unk8]); } -void sub_08067100(Entity *this) -{ - this->field_0x68.HALF.LO = sub_0801E99C(this); - sub_08078784(this, this->field_0x68.HALF.LO); +void sub_08067100(Entity* this) { + this->field_0x68.HALF.LO = sub_0801E99C(this); + sub_08078784(this, this->field_0x68.HALF.LO); } -void Mutoh_Fusion(Entity *this) -{ - if (this->action == 0) { - if (LoadExtraSpriteData(this, &gUnk_08110C00) != 0) { - this->action++; - this->spriteSettings.b.draw = TRUE; - InitializeAnimation(this, 2); +void Mutoh_Fusion(Entity* this) { + if (this->action == 0) { + if (LoadExtraSpriteData(this, &gUnk_08110C00) != 0) { + this->action++; + this->spriteSettings.b.draw = TRUE; + InitializeAnimation(this, 2); + } + } else { + GetNextFrame(this); } - } - else { - GetNextFrame(this); - } } diff --git a/src/npc/percy.c b/src/npc/percy.c index 759b94d3..47a9fa43 100644 --- a/src/npc/percy.c +++ b/src/npc/percy.c @@ -3,12 +3,28 @@ #include "npc.h" #include "textbox.h" #include "functions.h" +#include "flags.h" extern void sub_0806B41C(Entity*); -void sub_0806B3CC(Entity*); +extern void sub_0806B3CC(Entity*); +extern u32 sub_08002632(Entity*); +extern void sub_0801DFB4(Entity*, u32, u32, u32); + +extern u16* gUnk_08001A7C[40]; +extern u16 gUnk_08112E54[4]; +extern Dialog gUnk_08112E2C[5]; extern SpriteLoadData gUnk_08112E1C; +void Percy_Head(Entity* this) { + SetExtraSpriteFrame(this, 0, (this->frameSpriteSettings & 0x3f) + 0x13); + SetExtraSpriteFrame(this, 1, (this->frames.all & 0x7f) + 0xb); + SetExtraSpriteFrame(this, 2, this->frameIndex); + SetSpriteSubEntryOffsetData1(this, 2, 1); + SetSpriteSubEntryOffsetData2(this, 2, 0); + sub_0807000C(this); +} + void Percy(Entity* this) { if ((this->flags & 2) != 0) { sub_0806B41C(this); @@ -17,20 +33,75 @@ void Percy(Entity* this) { } } -void sub_0806B3CC(Entity *this) -{ - if (this->action == 0) { - if (!LoadExtraSpriteData(this, &gUnk_08112E1C)) { - return; +void sub_0806B3CC(Entity* this) { + if (this->action == 0) { + if (!LoadExtraSpriteData(this, &gUnk_08112E1C)) { + return; + } + this->action = 1; + InitializeAnimation(this, 0); + sub_08078778(this); + } + GetNextFrame(this); + if (this->interactType != 0) { + this->interactType = 0; + TextboxNoOverlapFollow(0); + } + sub_0806ED78(this); +} + +void sub_0806B41C(Entity* this) { + u16* tmp; + u32 idx; + + switch (this->action) { + case 0: + if (LoadExtraSpriteData(this, &gUnk_08112E1C)) { + this->action = 1; + this->spriteSettings.b.draw = 1; + if (this->entityType.parameter == 2) { + CreateFx(this, 0x25, 0); + } + sub_0807DD50(this); + } + break; + case 1: + if (this->interactType == 2) { + this->action = 2; + this->interactType = 0; + InitializeAnimation(this, sub_0806F5A4(GetFacingDirection(this, &gPlayerEntity)) + 4); + idx = sub_08002632(this); + tmp = gUnk_08001A7C[idx]; + if (this->field_0x68.HALF.LO == 33) + tmp += 3; + sub_0801DFB4(this, tmp[0], tmp[1], tmp[2]); + gPlayerState.field_0x8b = 3; + } else { + sub_0807DD94(this, 0); + } + break; + case 2: + if (UpdateFuseInteraction(this)) { + this->action = 1; + } + break; } - this->action = 1; - InitializeAnimation(this, 0); - sub_08078778(this); - } - GetNextFrame(this); - if (this->interactType != 0) { - this->interactType = 0; - TextboxNoOverlapFollow(0); - } - sub_0806ED78(this); +} + +void sub_0806B4F0(Entity* this) { + ShowNPCDialogue(this, &gUnk_08112E2C[this->entityType.parameter]); +} + +void sub_0806B504(Entity* this) { + int idx; + + idx = 1; + if (CheckKinstoneFused(0x21)) { + idx = 3; + } else if (!CheckLocalFlag(0x86)) { + idx = 0; + SetLocalFlag(0x86); + } + + TextboxNoOverlap(gUnk_08112E54[idx], this); } diff --git a/src/npc/postman.c b/src/npc/postman.c index f3d9bd96..0624935b 100644 --- a/src/npc/postman.c +++ b/src/npc/postman.c @@ -18,7 +18,6 @@ extern void sub_0806EE04(Entity*, void*, u32); extern void sub_080604DC(Entity*); extern s32 sub_0806ED9C(Entity*, u32, u32); extern void sub_0806EE20(Entity*); -extern void sub_0806ED78(Entity*); extern u32 sub_080040A8(Entity*); extern u32 sub_0801E99C(Entity*); extern void sub_0807DD50(Entity*); @@ -28,7 +27,7 @@ extern u32 GetFacingDirection(Entity*, Entity*); extern void sub_080606D8(Entity*); extern void sub_0807DD94(Entity*, u32); extern void sub_080788E0(Entity*); -extern void sub_08004488(u32); +extern void EnqueueSFX(u32); extern void sub_080606C0(Entity*); extern void sub_0800451C(Entity*); extern void sub_08078784(Entity*, u32); @@ -43,7 +42,7 @@ extern Coords16 gUnk_0810A66C[]; extern s8* gUnk_0810A918[]; extern void (*const gUnk_0810AA24[])(Entity*); -extern u32 gUnk_0810AA30[]; +extern Dialog gUnk_0810AA30[]; extern struct_02033280 gUnk_02033280; void Postman(Entity* this) { @@ -179,7 +178,7 @@ void sub_08060528(Entity *this) this->field_0x20 = 0x20000; this->field_0x6c.HALF.HI = 1; sub_080788E0(this); - sub_08004488(0x7c); + EnqueueSFX(0x7c); } else { this->field_0x6a.HWORD -= 1; @@ -205,13 +204,13 @@ void sub_080606C0(Entity *this) void sub_080606D8(Entity* this) { - s32 iVar1; + s32 index; - iVar1 = gUnk_02002A40.unk8 - 2; - if (iVar1 < 0) { - iVar1 = 0; + index = gUnk_02002A40.unk8 - 2; + if (index < 0) { + index = 0; } - ShowNPCDialogue(this, &gUnk_0810AA30[iVar1 * 2]); + ShowNPCDialogue(this, &gUnk_0810AA30[index]); } void sub_08060700(Entity *entity, u32 arg1) diff --git a/src/npc/rem.c b/src/npc/rem.c index b183f687..6d17b95d 100644 --- a/src/npc/rem.c +++ b/src/npc/rem.c @@ -4,7 +4,6 @@ extern void sub_0807DDAC(Entity*, u32); extern void sub_0807DDE4(Entity*); -extern void sub_0806ED78(Entity*); extern void PlaySFX(u32); extern void sub_0806A8C8(Entity*); extern void sub_0807DD94(Entity*, u32); diff --git a/src/npc/smith.c b/src/npc/smith.c index fd5f08fb..fa912abb 100644 --- a/src/npc/smith.c +++ b/src/npc/smith.c @@ -1,30 +1,21 @@ #include "global.h" #include "entity.h" #include "textbox.h" - -typedef struct { - u8 filler[8]; - u8 unk; -} SaveFile; +#include "functions.h" extern u32 GetFacingDirection(Entity*, Entity*); extern u32 sub_0806F5A4(u32); extern void sub_0806F118(Entity*); -extern void sub_0806ED78(Entity*); extern Entity* CreateFx(Entity*, u32, u32); extern void PlaySFX(u32); -extern u32 Random(void); extern void sub_0807000C(Entity*); extern u32 sub_0801E99C(Entity*); -extern u32 sub_0806ED9C(Entity*, u32, u32); -extern u32 sub_0806F078(Entity*, u32); extern void sub_0807DD50(Entity*); extern void sub_0807DD94(Entity*, u32); extern void sub_0807DDAC(Entity*, u32); extern void sub_0807DDE4(Entity*); extern u32 UpdateFuseInteraction(Entity*); extern u32 GetAnimationState(Entity*); -extern void ShowNPCDialogue(Entity*, u32*); extern void sub_08078850(u32, u32, u32, u32*); extern void sub_08078784(Entity*, u32); @@ -33,193 +24,162 @@ extern void (*const gUnk_0811036C[])(Entity*); extern u16 gUnk_08110380[]; extern SpriteLoadData gUnk_08110354; -extern SaveFile gUnk_02002A40; -extern u32 gUnk_08110390[]; +extern Dialog gUnk_08110390[]; extern u16 gUnk_081103D0[]; extern u32 gUnk_081103E0; -#if NON_MATCHING //reg-alloc -void Smith(Entity *this) -{ - u32 iVar2; - u32 iVar4; - - if ((this->flags & 2) != 0) { - if (this->interactType == 2) { - this->action = 4; - this->interactType = 0; - iVar4 = (this->animIndex == 0xc) ? 8 : 0; - iVar2 = sub_0806F5A4(GetFacingDirection(this, &gPlayerEntity)); - InitAnimationForceUpdate(this, iVar2 + iVar4); - sub_0806F118(this); +void Smith(Entity* this) { + u32 index; + + if ((this->flags & 2) != 0) { + if (this->interactType == 2) { + this->action = 4; + this->interactType = 0; + index = (this->animIndex == 0xc) ? 8 : 0; + index += sub_0806F5A4(GetFacingDirection(this, &gPlayerEntity)); + InitAnimationForceUpdate(this, index); + sub_0806F118(this); + } + gUnk_0811036C[this->action](this); + } else { + gUnk_08110360[this->action](this); + sub_0806ED78(this); + } + if (this->animIndex == 0xc) { + this->spritePriority.b1 = 0; + } else { + this->spritePriority.b1 = 1; + } + if ((this->frames.all & 1) != 0) { + this->frames.all &= 0xfe; + CreateFx(this, 0x3d, 0x20); + PlaySFX(gUnk_08110380[(Random() & 7)]); + } +} + +void Smith_Head(Entity* this) { + u8 bVar1; + + bVar1 = this->frames.all; + SetExtraSpriteFrame(this, 0, this->frameIndex); + if ((bVar1 & 0x40) != 0) { + SetExtraSpriteFrame(this, 1, 0x16); + } else { + SetExtraSpriteFrame(this, 1, 0xff); } - gUnk_0811036C[this->action](this); - } - else { - gUnk_08110360[this->action](this); - sub_0806ED78(this); - } - if (this->animIndex == 0xc) { - this->spritePriority.b1 = 0; - } - else { - this->spritePriority.b1 = 1; - } - if ((this->frames.all & 1) != 0) { - this->frames.all &= 0xfe; - CreateFx(this, 0x3d, 0x20); - PlaySFX(gUnk_08110380[(Random() & 7)]); - } -} -#else -NAKED -void Smith(Entity *this) { - asm(".include \"asm/non_matching/smith/smith.inc\""); -} -#endif - -void Smith_Head(Entity *this) -{ - u8 bVar1; - - bVar1 = this->frames.all; - SetExtraSpriteFrame(this, 0, this->frameIndex); - if ((bVar1 & 0x40) != 0) { - SetExtraSpriteFrame(this, 1, 0x16); - } - else { - SetExtraSpriteFrame(this, 1, 0xff); - } - SetSpriteSubEntryOffsetData1(this,0,1); - sub_0807000C(this); -} - -void sub_080660EC(Entity *this) -{ + SetSpriteSubEntryOffsetData1(this, 0, 1); + sub_0807000C(this); +} + +void sub_080660EC(Entity* this) { if (LoadExtraSpriteData(this, &gUnk_08110354) != 0) { - this->action = 1; - this->field_0x68.HALF.LO = sub_0801E99C(this); - InitAnimationForceUpdate(this, 2); - } -} - -void sub_08066118(Entity *this) -{ - s32 uVar1; - u32 iVar2; - - uVar1 = sub_0806ED9C(this, 0x28, 0x28); - if (uVar1 < 0) { - uVar1 = 2; - } - else { - if (this->field_0xf == 0) { - this->field_0xf = 0x10; + this->action = 1; + this->field_0x68.HALF.LO = sub_0801E99C(this); + InitAnimationForceUpdate(this, 2); } - else { - --this->field_0xf; - uVar1 = this->animIndex; +} + +void sub_08066118(Entity* this) { + s32 uVar1; + u32 iVar2; + + uVar1 = sub_0806ED9C(this, 0x28, 0x28); + if (uVar1 < 0) { + uVar1 = 2; + } else { + if (this->field_0xf == 0) { + this->field_0xf = 0x10; + } else { + --this->field_0xf; + uVar1 = this->animIndex; + } + } + if (sub_0806F078(this, uVar1) == 0) { + UpdateAnimationSingleFrame(this); + } + if (this->interactType != 0) { + this->action = 2; + TextboxNoOverlapFollow(0); } - } - if (sub_0806F078(this, uVar1) == 0) { - UpdateAnimationSingleFrame(this); - } - if (this->interactType != 0) { - this->action = 2; - TextboxNoOverlapFollow(0); - } } -void sub_08066170(Entity *this) -{ +void sub_08066170(Entity* this) { this->action = 1; } -void sub_08066178(Entity *this) -{ - if (LoadExtraSpriteData(this, &gUnk_08110354) != 0) { - this->action = 1; - this->spriteSettings.b.draw = 1; - this->field_0x68.HALF.LO = sub_0801E99C(this); - sub_0807DD50(this); - } +void sub_08066178(Entity* this) { + if (LoadExtraSpriteData(this, &gUnk_08110354) != 0) { + this->action = 1; + this->spriteSettings.b.draw = 1; + this->field_0x68.HALF.LO = sub_0801E99C(this); + sub_0807DD50(this); + } } -void sub_080661B0(Entity *this) -{ +void sub_080661B0(Entity* this) { sub_0807DD94(this, 0); } -void sub_080661BC(Entity *this) -{ - u32 sVar1; - - if (this->animIndex == 0xc) { - UpdateAnimationSingleFrame(this); - if ((this->frames.b.f3) != 0) { - this->field_0x80.HWORD = GetAnimationState(this) + 8; - InitAnimationForceUpdate(this, this->field_0x80.HWORD); +void sub_080661BC(Entity* this) { + u32 sVar1; + + if (this->animIndex == 0xc) { + UpdateAnimationSingleFrame(this); + if ((this->frames.b.f3) != 0) { + this->field_0x80.HWORD = GetAnimationState(this) + 8; + InitAnimationForceUpdate(this, this->field_0x80.HWORD); + } + } else { + sub_0807DD94(this, 0); } - } - else { - sub_0807DD94(this,0); - } } -void sub_08066200(Entity *this) -{ - sub_0807DDAC(this, 0); - sub_0807DDE4(this); - UpdateAnimationSingleFrame(this); +void sub_08066200(Entity* this) { + sub_0807DDAC(this, 0); + sub_0807DDE4(this); + UpdateAnimationSingleFrame(this); } -void sub_08066218(Entity *this) -{ - if (UpdateFuseInteraction(this) != 0) { - this->action = 1; - } +void sub_08066218(Entity* this) { + if (UpdateFuseInteraction(this) != 0) { + this->action = 1; + } } -void sub_0806622C(Entity *this) -{ - u32 iVar1; - - if (gUnk_02002A40.unk - 2 < 0) { - iVar1 = 0; - } - else { - iVar1 = gUnk_02002A40.unk - 2; - } - ShowNPCDialogue(this, &gUnk_08110390[iVar1 * 2]); +void sub_0806622C(Entity* this) { + u32 index; + + if (gUnk_02002A40.unk8 - 2 < 0) { + index = 0; + } else { + index = gUnk_02002A40.unk8 - 2; + } + ShowNPCDialogue(this, &gUnk_08110390[index]); } -void nullsub_501(Entity* this) {} +void nullsub_501(Entity* this) { +} -void sub_08066258(void) -{ - PlaySFX(gUnk_081103D0[Random() & 7]); +void sub_08066258(void) { + PlaySFX(gUnk_081103D0[Random() & 7]); } -void sub_08066274(u32 arg0) -{ - sub_08078850(arg0, 1, 0, &gUnk_081103E0); +void sub_08066274(u32 arg0) { + sub_08078850(arg0, 1, 0, &gUnk_081103E0); } -void sub_08066288(Entity *arg0) -{ - sub_08078784(arg0, arg0->field_0x68.HALF.LO); +void sub_08066288(Entity* arg0) { + sub_08078784(arg0, arg0->field_0x68.HALF.LO); } -void Smith_Fusion(Entity *this) -{ - if (this->action == 0) { - if (LoadExtraSpriteData(this, &gUnk_08110354) != 0) { - this->action++; - this->spriteSettings.b.draw = 1; - InitAnimationForceUpdate(this, 6); +void Smith_Fusion(Entity* this) { + if (this->action == 0) { + if (LoadExtraSpriteData(this, &gUnk_08110354) != 0) { + this->action++; + this->spriteSettings.b.draw = 1; + InitAnimationForceUpdate(this, 6); + } + } else { + UpdateAnimationSingleFrame(this); } - } - else { - UpdateAnimationSingleFrame(this); - } } diff --git a/src/npc/stamp.c b/src/npc/stamp.c index db1d7310..f77b1fdd 100644 --- a/src/npc/stamp.c +++ b/src/npc/stamp.c @@ -1,24 +1,21 @@ #include "global.h" #include "entity.h" #include "textbox.h" +#include "functions.h" extern void sub_08078778(Entity*); extern void sub_0805E47C(Entity*); -extern void sub_0806ED78(Entity*); extern void sub_0805E584(); extern void sub_0807DD64(); extern void sub_08062CA4(); extern void sub_0807DDAC(); extern void sub_0807DDE4(); extern u32 CheckKinstoneFused(); -extern void ShowNPCDialogue(); extern void (*gStampBehaviors1[4])(Entity*); extern void (*gStampBehaviors2[2])(Entity*); -extern u32 gUnk_0810C2E4; - - +extern Dialog gUnk_0810C2E4[2]; void Stamp(Entity* ent) { if ((ent->flags & 2) != 0) { @@ -80,7 +77,7 @@ void sub_08062CBC(Entity* ent) { u32 uVar1; uVar1 = CheckKinstoneFused(44); - ShowNPCDialogue(ent, &gUnk_0810C2E4 + ((-uVar1 | uVar1) >> 31) * 2); + ShowNPCDialogue(ent, &gUnk_0810C2E4[(-uVar1 | uVar1) >> 31]); } void sub_08062CE0(Entity* ent) { diff --git a/src/npc/teachers.c b/src/npc/teachers.c index a2bc5cce..e9a316c6 100644 --- a/src/npc/teachers.c +++ b/src/npc/teachers.c @@ -1,27 +1,19 @@ #include "global.h" #include "entity.h" #include "player.h" - -typedef struct { - u8 filler[8]; - u8 unk; -} SaveFile; +#include "functions.h" extern SpriteLoadData gUnk_08113910[]; -extern void sub_0805E3A0(Entity*, u32); extern void sub_0807DD50(Entity*); extern u32 GetFacingDirection(Entity*, Entity*); extern u32 sub_0806F5A4(u32); extern void sub_0806F118(Entity*); extern void sub_0807DD94(Entity*, u32); -extern u32 sub_0801E99C(); extern void sub_08078784(Entity*, u32); extern u32 UpdateFuseInteraction(Entity*); extern void sub_0807000C(Entity*); -extern void ShowNPCDialogue(Entity*, u16*); -extern SaveFile gUnk_02002A40; -extern u16 gUnk_08113930[]; +extern Dialog gUnk_08113930[]; void Teachers(Entity* this) { switch (this->action) { @@ -55,59 +47,52 @@ void Teachers(Entity* this) { } } -void sub_0806C674(Entity *this) -{ - this->field_0x68.HALF.LO = sub_0801E99C(); +void sub_0806C674(Entity* this) { + this->field_0x68.HALF.LO = sub_0801E99C(this); sub_08078784(this, this->field_0x68.HALF.LO); } -void Teachers_Head(Entity *this) -{ - u8 bVar1; - u8 bVar2; - u32 uVar3; - +void Teachers_Head(Entity* this) { + u8 bVar1; + u8 bVar2; + u32 uVar3; - uVar3 = this->frames.all & -0x81; - bVar1 = this->frameIndex; - bVar2 = this->frameSpriteSettings & 0x3f; - if ((this->entityType).form == 0) { - SetExtraSpriteFrame(this,0, (uVar3 + 3)); - SetExtraSpriteFrame(this,1, bVar1); - SetSpriteSubEntryOffsetData1(this, 1, 0); - sub_0807000C(this); - } - else { - SetExtraSpriteFrame(this, 0, (uVar3 + 6)); - SetExtraSpriteFrame(this, 1, ((bVar2) + 3)); - SetExtraSpriteFrame(this, 2, bVar1); - SetSpriteSubEntryOffsetData1(this, 2, 1); - SetSpriteSubEntryOffsetData2(this, 2, 0); - sub_0807000C(this); - } + uVar3 = this->frames.all & -0x81; + bVar1 = this->frameIndex; + bVar2 = this->frameSpriteSettings & 0x3f; + if ((this->entityType).form == 0) { + SetExtraSpriteFrame(this, 0, (uVar3 + 3)); + SetExtraSpriteFrame(this, 1, bVar1); + SetSpriteSubEntryOffsetData1(this, 1, 0); + sub_0807000C(this); + } else { + SetExtraSpriteFrame(this, 0, (uVar3 + 6)); + SetExtraSpriteFrame(this, 1, ((bVar2) + 3)); + SetExtraSpriteFrame(this, 2, bVar1); + SetSpriteSubEntryOffsetData1(this, 2, 1); + SetSpriteSubEntryOffsetData2(this, 2, 0); + sub_0807000C(this); + } } -void sub_0806C70C(Entity *this) -{ - int offset; - - offset = gUnk_02002A40.unk - 2; - if (offset < 0) { - offset = 0; - } - ShowNPCDialogue(this, gUnk_08113930 + this->entityType.form * 0x20 + offset * 4); +void sub_0806C70C(Entity* this) { + int offset; + + offset = gUnk_02002A40.unk8 - 2; + if (offset < 0) + offset = 0; + + ShowNPCDialogue(this, gUnk_08113930 + this->entityType.form * 8 + offset); } -void Teachers_Fusion(Entity *this) -{ - if (this->action == 0) { - if (LoadExtraSpriteData(this, &gUnk_08113910[this->entityType.form * 4])) { - this->action++; - this->spriteSettings.b.draw = TRUE; - InitializeAnimation(this, 2); +void Teachers_Fusion(Entity* this) { + if (this->action == 0) { + if (LoadExtraSpriteData(this, &gUnk_08113910[this->entityType.form * 4])) { + this->action++; + this->spriteSettings.b.draw = TRUE; + InitializeAnimation(this, 2); + } + } else { + GetNextFrame(this); } - } - else { - GetNextFrame(this); - } } diff --git a/src/npc/tingleSiblings.c b/src/npc/tingleSiblings.c index 7ab59fcb..b3d56ae8 100644 --- a/src/npc/tingleSiblings.c +++ b/src/npc/tingleSiblings.c @@ -12,8 +12,7 @@ extern void (*const gUnk_0810FBFC[])(Entity*); void TingleSiblings(Entity* this) { if ((this->flags & 2) != 0) { sub_08064DE4(this); - } - else { + } else { sub_08064D78(this); } } @@ -41,3 +40,42 @@ void sub_08064DCC(Entity* this) { InitAnimationForceUpdate(this, 2); this->action = 1; } +/* +void sub_08064DE4(Entity* this) { + switch (this->action) { + case 0: + this->action = 1; + this->spriteSettings = this->spriteSettings & 0xfc | 1; + this->animationState = '\x04'; + sub_0807DD50(this); + break; + case 1: + if (this->interactType == 2) { + this->action = 2; + this->interactType = 0; + GetFacingDirection(this, &gPlayerEntity); + InitAnimationForceUpdate(this, sub_0806F5A4()); + sub_0806F118(this); + } else { + sub_0807DD94(this, 0); + } + break; + case 2: + if (UpdateFuseInteraction(this)) { + this->action = 1; + sub_0801E99C(this); + } + break; + } + { + u8 bVar1 = this->frames.all; + u8 bVar5 = bVar1 & 0xf; + this->frames.all = bVar5 ^ bVar1; + if (bVar1 & 0xf) { + Entity* fx = CreateFx(this, bVar5 == 3 ? 0x2a : 0x29, 0); + if (fx && bVar5 == 2) { + fx->spriteSettings.b.flipX = 1; + } + } + } +}*/ diff --git a/src/npc/townMinish.c b/src/npc/townMinish.c index 80d207ef..0ef4098e 100644 --- a/src/npc/townMinish.c +++ b/src/npc/townMinish.c @@ -1,35 +1,49 @@ #include "global.h" #include "entity.h" #include "npc.h" +#include "functions.h" +#include "textbox.h" +#include "flags.h" -extern void InitializeAnimation(Entity *, u32); +extern void InitializeAnimation(Entity*, u32); +extern u32 LoadExtraSpriteData(Entity*, SpriteLoadData*); -extern void sub_0806ED78(Entity *); +extern u32 sub_080002C0(); +extern void sub_0806ACC4(Entity*); +extern void sub_0806AEA8(); +extern void sub_0806AEE4(Entity*); +extern void sub_0806AFE8(Entity*, s32*); +extern s32 sub_0806EDD8(Entity*, u32, u32); +extern u32 sub_0806F5B0(u32); +extern void sub_0806F62C(Entity*, s32, s32); +extern void sub_08078784(Entity*, u32); +extern void sub_08078850(Entity*, u32, u32, u32*); -extern void (*gUnk_081126E8[])(); -extern void sub_0806ACC4(Entity *); - -extern u32 LoadExtraSpriteData(Entity *, SpriteLoadData *); +extern u8 gUnk_081125F4[12]; extern SpriteLoadData gUnk_08112674[]; +extern u32 gUnk_081126D4[4]; +extern u8 gUnk_081126E4[4]; +extern void (*gUnk_081126E8[])(); +extern Dialog gUnk_081126F0[0x10]; +extern void (*gUnk_08112BF0[])(Entity*, s32*); +extern u16 gUnk_08112C40[5]; +extern u16 gUnk_08112C4A[3]; +extern u16 gUnk_08112C50[6]; +extern u16 gUnk_08112C5C[2]; +extern u16 gUnk_08112C60[4]; -void TownMinish(Entity *this) -{ +void TownMinish(Entity* this) { if ((this->flags & 2) == 0) { - (*gUnk_081126E8[this->action])(this); + gUnk_081126E8[this->action](this); sub_0806ED78(this); - } - else { + } else { sub_0806ACC4(this); } } -void sub_0806ABFC(Entity *this) -{ - u8 animationState; - - SpriteLoadData* SpriteLoadData = &gUnk_08112674[this->entityType.form << 2]; - if (!LoadExtraSpriteData(this, SpriteLoadData)) - { +void sub_0806ABFC(Entity* this) { + SpriteLoadData* SpriteLoadData = &gUnk_08112674[this->entityType.form * 4]; + if (!LoadExtraSpriteData(this, SpriteLoadData)) { return; } @@ -38,47 +52,298 @@ void sub_0806ABFC(Entity *this) this->field_0x6a.HALF.LO = this->actionDelay; this->animationState = this->field_0x6a.HALF.LO << 1; - animationState = this->animationState; - this->field_0x68.HALF.HI = animationState << 2; + this->field_0x68.HALF.HI = this->animationState * 4; this->actionDelay = 0; } -// Not matching yet, not 100% sure it's functionally identical -/*void sub_0806AC3C(Entity *this) { - if (this->field_0x58 <= 3) { +void sub_0806AC3C(Entity* this) { + if (this->animIndex <= 3) { s32 unk; - u8 field_0x68; - - Entity *link = &gPlayerEntity; + Entity* link = &gPlayerEntity; if (sub_080041A0(this, link, 0x18, 0x18)) { - unk = GetFacingDirection(this, link) & (u8)0x1e; + unk = GetFacingDirection(this, link) & 0x1e; + } else { + unk = this->animationState * 4; } - else { - unk = this->animationState << 2; - } - - field_0x68.HALF.HI = this->field_0x68.HALF.HI; - if (unk != field_0x68.HALF.HI) { + if (unk != this->field_0x68.HALF.HI) { s32 temp; - if (((unk - field_0x68.HALF.HI) & 0x1f) <= 0xf) { - field_0x68.HALF.HI--; - } - else { - field_0x68.HALF.HI++; + if (((unk - this->field_0x68.HALF.HI) & 0x1f) <= 0xf) { + this->field_0x68.HALF.HI--; + } else { + this->field_0x68.HALF.HI++; } - temp = field_0x68.HALF.HI; - this->field_0x68.HALF.HI = temp & 0x1f; + this->field_0x68.HALF.HI &= 0x1f; } if (!(this->field_0x68.HALF.HI & 7)) { this->animationState = sub_0806F5B0(this->field_0x68.HALF.HI); - UpdateSprite(this, (this->animationState >> 1) ^ 2); + InitializeAnimation(this, (this->animationState / 2) ^ 2); } } - sub_080042B8(this); -}*/ + UpdateAnimationSingleFrame(this); +} + +void sub_0806ACC4(Entity* this) { + u8 delay; + switch (this->action) { + case 0: + if (LoadExtraSpriteData(this, &gUnk_08112674[this->entityType.form * 4]) == 0) + return; + + this->action = 1; + delay = this->actionDelay; + this->field_0x6a.HALF.LO = delay; + this->animationState = delay * 2; + this->actionDelay = 0; + + this->field_0x68.HALF.LO = sub_0801E99C(this); + sub_0807DD50(this); + InitializeAnimation(this, (this->animationState / 2) + 8); + break; + case 1: + if (this->interactType == 2) { + this->action = 3; + this->interactType = 0; + sub_0806F118(this); + } else { + sub_0807DDAC(this, 0); + sub_0806AEA8(this); + if (this->entityType.parameter == 10 && this->interactType) { + this->action = 2; + this->interactType = 0; + InitializeAnimation(this, sub_0806F5A4(GetFacingDirection(this, &gPlayerEntity)) + 8); + sub_0806AFE8(this, *(s32**)&this->cutsceneBeh); + } + if (this->entityType.form == 1) { + u8 idx = gPlayerEntity.animationState >> 1; + sub_08078850(this, 1, gUnk_081126E4[idx], &gUnk_081126D4[idx]); + } + } + break; + case 2: + if (gTextBox.doTextBox & 0x7f) + break; + + this->action = 1; + InitializeAnimation(this, this->animationState / 2 + 4); + break; + case 3: + if (UpdateFuseInteraction(this)) + this->action = 1; + break; + } + + if (this->frameDuration != 0xff) { + GetNextFrame(this); + } +} + +void sub_0806ADFC(Entity* this) { + sub_08078784(this, this->field_0x68.HALF.LO); +} + +void TownMinish_Head(Entity* this) { + u32 frames; + + if ((this->flags & 2) == 0) { + frames = this->field_0x68.HALF.HI / 2; + if ((this->frameSpriteSettings & 1)) { + SetExtraSpriteFrame(this, 0, frames + 0x1c); + } else { + SetExtraSpriteFrame(this, 0, 0xff); + } + SetExtraSpriteFrame(this, 1, this->frameIndex); + SetSpriteSubEntryOffsetData1(this, 1, 0); + sub_0807000C(this); + } else { + frames = this->frames.all; + if (frames != 0xff) { + frames &= ~0x80; + } + if ((this->frameSpriteSettings & 1) == 0) { + frames = 0xff; + } + SetExtraSpriteFrame(this, 0, frames); + SetExtraSpriteFrame(this, 1, this->frameIndex); + SetSpriteSubEntryOffsetData1(this, 1, 0); + sub_0807000C(this); + } +} + +void sub_0806AEA8(Entity* this) { + int old = this->field_0x82.HWORD; + this->field_0x82.HWORD &= ~0x20; + if (old & 0x20) { + sub_08003FC4(this, 0x4000); + } + sub_0807DDE4(this); + this->field_0x82.HWORD = old; +} + +void sub_0806AED8(Entity* this) { + this->actionDelay = 0; + sub_0806AEE4(this); +} + +void sub_0806AEE4(Entity* this) { + int index; + u8* idx3; + u8 tmp1, tmp2; + + if (this->actionDelay) { + this->actionDelay--; + } else { + this->actionDelay = 2; + index = sub_0806EDD8(this, 0x20, 0x20); + if (index < 0) { + int state = this->field_0x6a.HALF.LO; + this->animationState = state * 2; + index = state * 8; + } + + idx3 = gUnk_081125F4 + (this->animationState / 2) * 0x20 + (index >> 1) * 2; + tmp1 = idx3[0]; + tmp2 = idx3[1]; + + if (tmp2 & 0x80) { + this->animationState = sub_0806F5B0(index); + } + tmp2 &= 0x7f; + this->frames.all = tmp1; + this->frameIndex = tmp2; + this->frameSpriteSettings = 1; + this->animIndex = 0; + this->frameDuration = 0xff; + } +} + +void sub_0806AF60(Entity* this, int* idx) { + InitializeAnimation(this, idx[1] + (this->animationState / 2)); +} + +void sub_0806AF70(Entity* this, u32 arg1) { + this->field_0x20 = 0x24000; +} + +void sub_0806AF78(Entity* this, u32 arg1) { + sub_08003FC4(this, 0x1800); + if (0 <= this->height.WORD && this->field_0x20 < 1) { + this->height.WORD = 0; + sub_0806AF70(this, arg1); + } +} + +void sub_0806AFA0(Entity* this) { + if (sub_0806ED78(this)) { + sub_0806F62C(this, -this->nonPlanarMovement, this->direction); + } +} + +void sub_0806AFBC(Entity* this) { + int idx = gUnk_02002A40.unk8 - 2; + if (idx < 0) + idx = 0; + + ShowNPCDialogue(this, gUnk_081126F0 + this->entityType.parameter * 8 + idx); +} + +void sub_0806AFE8(Entity* this, s32* unk) { + unk[5] = 0; + gUnk_08112BF0[this->entityType.parameter](this, unk); +} + +void sub_0806B004(Entity* this, int* unk) { + int idx = 0; + + if (CheckGlobalFlag(0x29)) { + if (CheckLocalFlag(0x73)) { + if (GetInventoryValue(0x46) == 0) { + idx = 3; + if (CheckLocalFlag(0x78) == 0) { + idx = 2; + unk[5] = 1; + SetLocalFlag(0x78); + } + } else { + idx = 4; + } + } else { + idx = 1; + SetLocalFlag(0x6a); + } + } + TextboxNoOverlap(gUnk_08112C40[idx], this); +} + +void sub_0806B064(Entity* this) { + int idx = 0; + + if (CheckGlobalFlag(0x29)) { + idx = 1; + if (CheckLocalFlag(0x73)) { + idx = 2; + } + } + TextboxNoOverlap(gUnk_08112C4A[idx], this); +} + +void sub_0806B098(Entity* this) { + u32 f; + int idx = 2; + + if (GetInventoryValue(0x46) == 0) { + idx = 1; + if (CheckGlobalFlag(0x29)) { + f = CheckGlobalFlag(0x2a); + idx = (-f | f) >> 0x1f; + } + } + TextboxNoOverlap(gUnk_08112C50[(this->entityType.parameter - 7) * 3 + idx], this); +} + +void sub_0806B0E0(Entity* this) { + int idx = 0; + + if (sub_080002C0(0x38, 0xb8, 1) == 0x57 && sub_080002C0(0x48, 0xb8, 1) == 0x57 && + sub_080002C0(0x38, 200, 1) == 0x57 && sub_080002C0(0x48, 200, 1) == 0x57) { + idx = 1; + } + + TextboxNoOverlap(gUnk_08112C5C[idx], this); +} + +void sub_0806B134(Entity* this) { + int idx; + + if (GetInventoryValue(0x45)) { + idx = 2; + if (CheckLocalFlag(0x7b) == 0) { + idx = 1; + SetLocalFlag(0x7b); + } + } else { + idx = 0; + SetGlobalFlag(0x4a); + } + if (5 < gUnk_02002A40.unk8) { + idx = 3; + } + TextboxNoOverlap(gUnk_08112C60[idx], this); +} + +void TownMinish_Fusion(Entity* this) { + if (this->action == 0) { + if (LoadExtraSpriteData(this, &gUnk_08112674[this->entityType.form * 4])) { + this->action++; + this->spriteSettings.b.draw = 1; + InitializeAnimation(this, 6); + } + } else { + GetNextFrame(this); + } +} diff --git a/src/npc/townsperson.c b/src/npc/townsperson.c index 4e93bcca..0edca56d 100644 --- a/src/npc/townsperson.c +++ b/src/npc/townsperson.c @@ -5,6 +5,7 @@ #include "textbox.h" #include "flags.h" #include "structures.h" +#include "functions.h" typedef struct { u8 frame1; @@ -21,8 +22,6 @@ typedef struct { extern void (*const gUnk_0810B774[])(Entity*); extern void (*const gUnk_0810B77C[])(Entity*); extern void sub_08061CB4(Entity*, u32); -extern u32 sub_0806ED9C(Entity*, u32, u32); -extern void sub_0806ED78(Entity*); extern u32 sub_0805ACC0(Entity*); extern u32 sub_0801E99C(Entity*); extern void sub_0807DD64(Entity*); @@ -36,8 +35,6 @@ extern void sub_08062048(Entity*); extern void sub_08078784(Entity*, u32); extern void sub_08078778(Entity*); extern u32 sub_0806F5B0(u32); -extern void sub_080AEF88(Entity*); -extern u32 Random(void); extern void ResolveEntityOnTop(Entity*, Entity*); extern void sub_08078850(Entity*, u32, u8, u32*); @@ -50,7 +47,7 @@ extern u8 gUnk_0810B748[]; extern u32 gUnk_0810B740[]; extern u16 gUnk_0810B790[]; extern u16 gUnk_0810B7BA[]; -extern u32 gUnk_0810B7C0[]; +extern Dialog gUnk_0810B7C0[]; void Townsperson(Entity* this) { if ((this->flags & 2) != 0) { @@ -194,7 +191,7 @@ void sub_08061E90(Entity* this, Entity* arg1) { if (arg1->spriteSettings.raw == 0) { arg1->spriteSettings.raw++; arg1->spriteIndex = (Random() & 0x3f) + 0x20; - animIndex = Random() & 0x18; + animIndex = DirectionRound(Random()); switch (this->direction) { case 0x0: if (animIndex == 0x10) { @@ -224,7 +221,7 @@ void sub_08061E90(Entity* this, Entity* arg1) { if (animIndex != this->animIndex) { InitializeAnimation(this, animIndex); } - sub_080AEF88(this); + ProcessMovement(this); iVar4 = this->x.HALF.HI - *(s16*)&this->field_0x6a.HWORD; if (0x10 < iVar4) { this->x.HALF.HI = this->field_0x6a.HWORD + 0x10; @@ -296,30 +293,27 @@ void sub_0806200C(Entity* this) { TextboxNoOverlap(gUnk_0810B7BA[index], this); } -void sub_08062048(Entity *this) -{ - int iVar1; - - if ((this->entityType).subtype == 6) { - iVar1 = gUnk_02002A40.unk8 - 2; - if (iVar1 < 0) { - iVar1 = 0; +void sub_08062048(Entity* this) { + int iVar1; + + if ((this->entityType).subtype == 6) { + iVar1 = gUnk_02002A40.unk8 - 2; + if (iVar1 < 0) { + iVar1 = 0; + } + ShowNPCDialogue(this, gUnk_0810B7C0 + this->entityType.form * 0x8 + iVar1); + } else { + TextboxNoOverlap(0, this); } - ShowNPCDialogue(this, gUnk_0810B7C0 + this->entityType.form * 0x10 + iVar1 * 2); - } - else { - TextboxNoOverlap(0, this); - } } -void Townsperson_Fusion(Entity *this) -{ - if (this->action == 0) { - if (LoadExtraSpriteData(this, gUnk_0810B6EC[this->entityType.form]) == 0) { - return; +void Townsperson_Fusion(Entity* this) { + if (this->action == 0) { + if (LoadExtraSpriteData(this, gUnk_0810B6EC[this->entityType.form]) == 0) { + return; + } + this->action++; + this->spriteSettings.b.draw = TRUE; } - this->action++; - this->spriteSettings.b.draw = TRUE; - } - sub_08061CB4(this, 6); + sub_08061CB4(this, 6); } diff --git a/src/npc/windTribespeople.c b/src/npc/windTribespeople.c index 6a00c3aa..55f7b4ed 100644 --- a/src/npc/windTribespeople.c +++ b/src/npc/windTribespeople.c @@ -4,6 +4,7 @@ #include "textbox.h" #include "flags.h" #include "structures.h" +#include "functions.h" extern u32 LoadExtraSpriteData(Entity*, SpriteLoadData*); extern void sub_0807DD50(Entity*); @@ -23,7 +24,7 @@ extern void (*const gUnk_08113A8C[])(Entity*, Entity*); extern SpriteLoadData gUnk_08113A1C[]; extern u32 gUnk_08014A80; -extern u32 gUnk_08113ABC[]; +extern Dialog gUnk_08113ABC[]; extern u16 gUnk_08113B0C[]; void WindTribespeople(Entity* this) { @@ -74,73 +75,65 @@ void sub_0806C85C(Entity* this) { } } -void sub_0806C870(Entity *this) -{ - u8 bVar1; - - bVar1 = sub_0801E99C(); - this->field_0x68.HALF.LO = bVar1; - sub_08078784(this, this->field_0x68.HALF.LO); +void sub_0806C870(Entity* this) { + u8 bVar1; + + bVar1 = sub_0801E99C(this); + this->field_0x68.HALF.LO = bVar1; + sub_08078784(this, this->field_0x68.HALF.LO); } -void WindTribespeople_Head(Entity *this) -{ - u32 uVar1; - u32 uVar2; - u8 pbVar3; - - pbVar3 = (this->frames.all & 0x3F); - if (this->entityType.form == 4) { - SetExtraSpriteFrame(this, 0, 9); - SetExtraSpriteFrame(this, 1, pbVar3); - SetExtraSpriteFrame(this, 2, this->frameIndex); - SetSpriteSubEntryOffsetData2(this, 2, 0); - SetSpriteSubEntryOffsetData1(this, 2, 1); - sub_0807000C(this); - } - else { - if (this->frames.b.f2 != 0) { - uVar2 = 1; - uVar1 = 0; - } - else { - uVar2 = 0; - uVar1 = 1; +void WindTribespeople_Head(Entity* this) { + u32 uVar1; + u32 uVar2; + u8 pbVar3; + + pbVar3 = (this->frames.all & 0x3F); + if (this->entityType.form == 4) { + SetExtraSpriteFrame(this, 0, 9); + SetExtraSpriteFrame(this, 1, pbVar3); + SetExtraSpriteFrame(this, 2, this->frameIndex); + SetSpriteSubEntryOffsetData2(this, 2, 0); + SetSpriteSubEntryOffsetData1(this, 2, 1); + sub_0807000C(this); + } else { + if (this->frames.b.f2 != 0) { + uVar2 = 1; + uVar1 = 0; + } else { + uVar2 = 0; + uVar1 = 1; + } + SetExtraSpriteFrame(this, uVar2, pbVar3); + SetExtraSpriteFrame(this, uVar1, this->frameIndex); + SetSpriteSubEntryOffsetData1(this, uVar1, uVar2); + sub_0807000C(this); } - SetExtraSpriteFrame(this, uVar2, pbVar3); - SetExtraSpriteFrame(this, uVar1, this->frameIndex); - SetSpriteSubEntryOffsetData1(this, uVar1, uVar2); - sub_0807000C(this); - } } -//body and head entities? -void sub_0806C90C(Entity *param_1,Entity *param_2) -{ - *(u32 *)¶m_2->animationState = 0; - gUnk_08113A8C[param_1->entityType.parameter](param_1, param_2); +// body and head entities? +void sub_0806C90C(Entity* param_1, Entity* param_2) { + *(u32*)¶m_2->animationState = 0; + gUnk_08113A8C[param_1->entityType.parameter](param_1, param_2); } -void sub_0806C928(Entity *this) -{ - ShowNPCDialogue(this, &gUnk_08113ABC[gUnk_02002A40.unk8 * 2]); +void sub_0806C928(Entity* this) { + ShowNPCDialogue(this, &gUnk_08113ABC[gUnk_02002A40.unk8]); } -void sub_0806C944(Entity *this) -{ - int iVar1; - int iVar2; - - iVar1 = CheckGlobalFlag(WARP_EVENT_END); - if (iVar1 == 0) { - iVar2 = 0; - } - else { - iVar1 = CheckLocalFlag(0x63); - iVar2 = 2; - if (iVar1 != 0) { - iVar2 = 1; +void sub_0806C944(Entity* this) { + int iVar1; + int iVar2; + + iVar1 = CheckGlobalFlag(WARP_EVENT_END); + if (iVar1 == 0) { + iVar2 = 0; + } else { + iVar1 = CheckLocalFlag(0x63); + iVar2 = 2; + if (iVar1 != 0) { + iVar2 = 1; + } } - } - TextboxNoOverlap(gUnk_08113B0C[iVar2], this); + TextboxNoOverlap(gUnk_08113B0C[iVar2], this); } diff --git a/src/object/backgroundCloud.c b/src/object/backgroundCloud.c index a6106ca7..6be23764 100644 --- a/src/object/backgroundCloud.c +++ b/src/object/backgroundCloud.c @@ -20,7 +20,7 @@ void sub_0808F658(Entity* this) { this->direction = 8; this->nonPlanarMovement = gUnk_08121EB0[(this->entityType).form]; this->field_0x78.HWORD = gRoomControls.roomOriginX - 0x60; - this->field_0x7a.HWORD = gRoomControls.roomOriginX + gRoomControls.filler2[3] + 0x60; + this->field_0x7a.HWORD = gRoomControls.roomOriginX + gRoomControls.width + 0x60; this->animationState = 0; this->x.HALF.HI += (Random() & 0xf) << 4; this->actionDelay = 0; diff --git a/src/object/bigVortex.c b/src/object/bigVortex.c new file mode 100644 index 00000000..8e8522c0 --- /dev/null +++ b/src/object/bigVortex.c @@ -0,0 +1,111 @@ +#include "global.h" +#include "entity.h" +#include "functions.h" +#include "flags.h" + +extern void sub_08098E3C(Entity*); +extern void sub_08098E88(Entity*); + +extern void (*const gUnk_0812367C[])(Entity*); + +extern u16 gUnk_08123690[]; + +void BigVortex(Entity* this) { + if ((this->entityType).form == 0) { + gUnk_0812367C[this->action](this); + } else { + sub_08098E3C(this); + } +} + +void sub_08098D1C(Entity* this) { + u32 temp; + this->action = 1; + this->height.HALF.HI = -0x10; + + temp = this->field_0x86.HWORD; + + if ((temp != 0) && !CheckFlags(temp)) { + this->action = 1; + } else { + this->action = 3; + this->spriteSettings.b.draw = TRUE; + sub_08098E88(this); + } + sub_0805E3A0(this, 6); + InitAnimationForceUpdate(this, 0); +} + +void sub_08098D6C(Entity* this) { + Entity* ent; + + if (CheckFlags(this->field_0x86.HWORD)) { + this->action = 2; + this->actionDelay = 0x2d; + ent = CreateFx(this, 0x43, 0); + if (ent != NULL) { + ent->y.HALF.HI += 8; + } + } +} + +void sub_08098D9C(Entity* this) { + if (--this->actionDelay == 0) { + this->action = 3; + this->spriteSettings.b.draw = TRUE; + sub_08098E88(this); + } +} + +void sub_08098DC4(Entity* this) { + + if (sub_0800419C(this, &gPlayerEntity, 8, 8) != 0) { + CopyPosition(this, &gPlayerEntity); + sub_08004542(this); + sub_08004542(&gPlayerEntity); + gPlayerEntity.collisionLayer = 1; + ResolveEntityOnTop(this, &gPlayerEntity); + gPlayerState.playerAction = 0x1f; + gPlayerState.field_0x34[4] = 1; + gPlayerState.field_0x34[5] = this->entityType.parameter; + this->action = 4; + if (this->entityType.parameter == 1) { + SetGlobalFlag(0x23); + } + sub_08077B20(); + } + UpdateAnimationSingleFrame(this); +} + +void sub_08098E34(Entity* this) { + UpdateAnimationSingleFrame(this); +} + +void sub_08098E3C(Entity* this) { + u16* temp; + + if (this->action == 0) { + this->action = 1; + this->spriteSettings.b.draw = TRUE; + InitAnimationForceUpdate(this, this->entityType.form); + } + temp = &gUnk_08123690[this->entityType.form & 2]; + sub_0805EC9C(this, temp[0], temp[1], 0); + UpdateAnimationSingleFrame(this); +} + +void sub_08098E88(Entity* this) { + Entity* ent1; + Entity* ent2; + + ent1 = CreateObject(0x82, 1, 0); + if (ent1 != NULL) { + PositionRelative(this, ent1, 0, -0x10000); + ent1->spriteOffsetY = 8; + } + ent2 = CreateObject(0x82, 2, 0); + if (ent2 != NULL) { + PositionRelative(this, ent2, 0, -0x20000); + ent2->spriteOffsetY = 0x10; + } +}
\ No newline at end of file diff --git a/src/object/bird.c b/src/object/bird.c new file mode 100644 index 00000000..83af1b5d --- /dev/null +++ b/src/object/bird.c @@ -0,0 +1,144 @@ +#include "global.h" +#include "entity.h" +#include "flags.h" +#include "functions.h" + +extern void (*const gUnk_08123EC0[])(Entity*); +extern void (*const gUnk_08123EEC[])(Entity*); +extern void (*const gUnk_08123EF4[])(Entity*); +extern void (*const gUnk_08123EFC[])(Entity*); +extern void (*const gUnk_08123F04[])(Entity*); + +void Bird(Entity* this) { + gUnk_08123EC0[this->entityType.form](this); +} + +void sub_0809CF3C(Entity* this) { + gUnk_08123EEC[this->action](this); +} + +void sub_0809CF54(Entity* this) { + Entity* target; + + this->action++; + this->spriteSettings.b.draw = TRUE; + this->actionDelay = 0x31; + this->field_0xf = 1; + this->field_0x20 = -0x18000; + this->height.WORD = -0x38C000; + this->field_0x68.HWORD = -0x800; + this->nonPlanarMovement = 0x280; + this->direction = 8; + this->collisionLayer = 2; + this->x.HALF.HI = gRoomControls.roomScrollX; + PlaySFX(0x123); + UpdateSpriteForCollisionLayer(this); + InitAnimationForceUpdate(this, 0); + target = CreateObject(0x95, 1, 0); + if (target != NULL) { + target->parent = this; + PositionRelative(this, target, 0, 0x80000); + ResolveEntityOnTop(this, target); + } +} + +void sub_0809CFEC(Entity* this) { + + sub_0806F69C(this); + sub_08003FC4(this, *(s16*)&this->field_0x68.HWORD); + if (this->actionDelay != 0) { + if (--this->actionDelay == 0) { + this->field_0xf = 0; + } + } else if (sub_080040A8(this) == 0) { + DeleteThisEntity(); + } + UpdateAnimationSingleFrame(this); +} + +void sub_0809D030(Entity* this) { + gUnk_08123EF4[this->action](this); +} + +void sub_0809D048(Entity* this) { + this->action++; + this->collisionLayer = 1; + UpdateSpriteForCollisionLayer(this); + InitAnimationForceUpdate(this, 0x17); +} + +void sub_0809D06C(Entity* this) { + gUnk_08123EFC[this->previousActionFlag](this); +} + +void sub_0809D084(Entity* this) { + u32 temp; + + if (this->parent != NULL) { + temp = this->parent->field_0xf; + if (temp != 0) { + PositionRelative(this->parent, this, 0, 0x80000); + } else { + this->previousActionFlag++; + this->field_0x20 = temp; + } + } +} + +void sub_0809D0AC(Entity* this) { + Entity* fx; + + if (sub_080044EC(this, 0x1800) < 2) { + (this->entityType).form = 2; + this->action = 1; + this->height.WORD = 0; + this->collisionLayer = 1; + SetLocalFlag(0x45); + PlaySFX(0x72); + fx = CreateFx(this, 0x11, 0); + if (fx != NULL) { + sub_0806FAD8(this, fx); + } + } +} + +void sub_0809D0F4(Entity* this) { + gUnk_08123F04[this->action](this); +} + +void sub_0809D10C(Entity* this) { + this->action++; + this->collisionLayer = 1; + UpdateSpriteForCollisionLayer(this); + InitAnimationForceUpdate(this, 0x17); +} + +void sub_0809D130(Entity* this) { + if ((gPlayerState.flags.all & 0x80) != 0) { + sub_0800445C(this); + } else if (sub_08017850(this) != 0) { + CreateItemEntity(0x17, 0, 0); + gUnk_02002A40.windcrests |= 0x10000000; + DeleteThisEntity(); + } +} + +void sub_0809D178(Entity* this) { + + if (this->action == 0) { + this->action++; + this->collisionLayer = 2; + UpdateSpriteForCollisionLayer(this); + this->frames.all = 0x80; + } + if ((this->frames.all & 0x80) != 0) { + InitializeAnimation(this, Random() & 3); + this->frameDuration = (Random() & 0xf) + 0x10; + this->spriteSettings.b.flipX = FALSE; + if ((Random() & 1) != 0) { + this->spriteSettings.b.flipX = TRUE; + } + } else { + GetNextFrame(this); + } +}
\ No newline at end of file diff --git a/src/object/button.c b/src/object/button.c new file mode 100644 index 00000000..99d018b3 --- /dev/null +++ b/src/object/button.c @@ -0,0 +1,286 @@ +#include "global.h" +#include "entity.h" +#include "flags.h" +#include "room.h" +#include "functions.h" + +extern void (*const gUnk_0811EE38[])(Entity*); + +void Button(Entity* this) { + gUnk_0811EE38[this->action](this); +} + +extern u32 sub_08081E3C(Entity*); + +void sub_08081AE0(Entity* this) { + this->flags &= 0x7F; + this->scriptedScene = 3; + this->y.HALF.HI++; + if (this->cutsceneBeh.HWORD != 0) { + this->collisionLayer = this->cutsceneBeh.HWORD; + } + this->field_0x74.HWORD = (((this->x.HALF.HI - gRoomControls.roomOriginX)>>4) & 0x3F) | + ((((this->y.HALF.HI - gRoomControls.roomOriginY)>>4) & 0x3F) << 6); + this->field_0x70.HALF.HI = GetTileType(this->field_0x74.HWORD, this->collisionLayer); + if (this->entityType.form == 0 && CheckFlags(this->field_0x86.HWORD)) { + this->action = 5; + SetTileType(0x7A, this->field_0x74.HWORD, this->collisionLayer); + } else { + if (sub_08081E3C(this)) { + this->action = 2; + } else { + this->action = 1; + } + } +} + +void sub_08081B84(Entity* this) { + if (sub_08081E3C(this)) { + this->action=2; + this->field_0x70.HALF.HI = GetTileType(this->field_0x74.HWORD, this->collisionLayer); + } +} + +u32 sub_08081CB0(Entity*); +void sub_0805E4E0(Entity*, u32); +void sub_08081FF8(Entity*); + +void sub_08081BAC(Entity* this) { + if (sub_08081CB0(this)) { + this->previousActionFlag = 0; + this->actionDelay = 0xA; + sub_0805E4E0(this, 0xA); + sub_08081FF8(this); + if (this->entityType.form == 1) { + this->action = 3; + } else { + this->action = 5; + } + } +} + +u32 sub_08081F7C(Entity*, u32); +u32 sub_08081D28(Entity*); +void sub_08081E6C(Entity*); + +void sub_08081BE0(Entity* this) { + if (!sub_08081F7C(this, 0x78)) + return; + if (!sub_08081D28(this)) { + this->action = 4; + this->field_0xf = 1; + if ((gPlayerState.heldObject == 2) || (!(gPlayerState.field_0x34[1] & 0x80))) { + this->actionDelay = 0x18; + } else { + this->actionDelay = 0x8; + } + } else { + sub_08081E6C(this); + } +} + +void sub_08081C30(Entity* this) { + if (this->actionDelay != 0) { + this->actionDelay--; + if (this->field_0xf != 0) { + this->field_0xf = 0; + SetTile(0x4035, this->field_0x74.HWORD, this->collisionLayer); + } + if (sub_08081CB0(this)) { + this->action = 3; + this->actionDelay = 0; + } + } else { + this->action = 2; + ClearFlag(this->field_0x86.HWORD); + SetTileType(0x77, this->field_0x74.HWORD, this->collisionLayer); + PlaySFX(0x10C); + } +} + +void sub_08081C98(Entity* this) { + if (sub_08081F7C(this, 0x7a)) { + sub_08081E6C(this); + } +} + +Entity* sub_08081D74(Entity*); +void sub_0807B7D8(u32, u32, u32); +u32 sub_080001DA(u32, u32); + +u32 sub_08081CB0(Entity* this) { + u16 tmp; + if (sub_08081D74(this)) { + this->field_0x70.HALF.LO = -1; + if (GetTileType(this->field_0x74.HWORD, this->collisionLayer) == 0x4035) { + sub_0807B7D8(0x78, this->field_0x74.HWORD, this->collisionLayer); + } + return 1; + } else { + tmp = GetTileType(this->field_0x74.HWORD, this->collisionLayer); + if (tmp != 0x77 && tmp != 0x79 && tmp != 0x4035) { + this->field_0x70.HALF.LO = sub_080001DA(this->field_0x74.HWORD, this->collisionLayer); + return 1; + } + } + return 0; +} + +u32 sub_08081D28(Entity* this) { + if (sub_08081D74(this)) { + this->field_0x70.HALF_U.LO = 0xFFFF; + return 1; + } else { + if (this->field_0x70.HALF_U.LO == 0xFFFF) { + return 0; + } + if (sub_080001DA(this->field_0x74.HWORD, this->collisionLayer) != this->field_0x70.HALF_U.LO) { + return 0; + } + } + return 1; +} + +extern u32 sub_080002E0(u32, u32); +extern Entity* gUnk_03004040[]; +extern u32 sub_080041A0(Entity*, Entity*, u32, u32); +u32 sub_08081E0C(Entity*); + +Entity* sub_08081D74(Entity* this) { + Entity* ent; + if (sub_080002E0(this->field_0x74.HWORD, this->collisionLayer) == 0xF) { + return 0; + } + ent = 0; + if (sub_08081E0C(this)) { + if (!(gPlayerState.flags.all & 0x10) && !(gPlayerState.flags.all & 0x80)) { + ent = &gPlayerEntity; + } + } else { + if (gPlayerState.flags.all & 0x400000) { + if (sub_080041A0(this, gUnk_03004040[0], 5, 6)) { + ent = gUnk_03004040[0]; + } else if (sub_080041A0(this, gUnk_03004040[1], 5, 6)) { + ent = gUnk_03004040[1]; + } else if (sub_080041A0(this, gUnk_03004040[2], 5, 6)) { + ent = gUnk_03004040[2]; + } + } + } + this->attachedEntity=ent; + return ent; +} + +extern u32 sub_08079F8C(); + +u32 sub_08081E0C(Entity* this) { + Entity* tmp = &gPlayerEntity; + if (tmp->height.HALF.HI != 0 || !sub_08079F8C()) { + return 0; + } else { + return sub_080041A0(this, tmp, 5, 6); + } +} + +extern u16 gUnk_0811EE50[]; + +u32 sub_08081E3C(Entity* this) { + u16* tmp1; + int tmp2; + tmp2 = GetTileType(this->field_0x74.HWORD, this->collisionLayer); + tmp1 = gUnk_0811EE50; + do { + if (*tmp1 == tmp2) return 1; + } while (*++tmp1); + return 0; +} + +u32 sub_08081F00(u32*, u32*); + +extern u16 gMapDataTopSpecial[0x2000]; + +#ifdef NON_MATCHING +void sub_08081E6C(Entity* this) { + u32 r4; + u16 *tmp, *r1; + u8 *tmp2; + u32 r6 = this->field_0x74.HWORD; + u32 r5 = this->collisionLayer; + u32 tile = GetTileType(r6,r5); + if (tile < 0x4000) + return; + r1 = GetLayerByIndex(r5); + r4 = (this->entityType.form == 0 ? 0x7a : 0x78); + tmp = r1 + 0x3802; + r1 += 0x3002 + r4; + tmp = tmp + (*r1 << 2); + tmp2 = (r5 == 2 ? gMapDataTopSpecial : (u8*)&gUnk_02019EE0); + tmp2 += (((0x3f & r6)<<1)+((0xfc0 & r6)<<2))<<1; + if (sub_08081F00((u32*)tmp2, (u32*)tmp)) + return; + SetTileType(r4, r6, r5); + SetTile(tile,r6,r5); +} +#else +NAKED +void sub_08081E6C(Entity* this) { + asm(".include \"asm/non_matching/button/sub_08081E6C.s\""); +} +#endif + +u32 sub_08081F00(u32* unk1, u32* unk2) { + if (*unk1 != *unk2) return 0; + if (unk1[0x40] != unk2[1]) return 0; + return 1; +} + +void sub_08081F24(Entity* this) { + Entity* fx = CreateFx(this, 0x11, 0x40); + if (fx) { + fx->scriptedScene = 3; + fx->x.HALF.HI += 7; + fx->y.HALF.HI += 5; + } + fx = CreateFx(this, 0x11, 0x40); + if (fx) { + fx->scriptedScene = 3; + fx->x.HALF.HI -= 7; + fx->y.HALF.HI += 5; + } +} + +u32 sub_08081F7C(Entity* this, u32 r7) { + u16 tmp; + if (this->actionDelay == 0) return 1; + if (--this->actionDelay > 6) { + if(this->attachedEntity) + this->attachedEntity->spriteOffsetY = 0xfc; + } else { + if (this->actionDelay == 6) { + SetFlag(this->field_0x86.HWORD); + SetTileType(r7, this->field_0x74.HWORD, this->collisionLayer); + sub_08081F24(this); + PlaySFX(0x10C); + if (this->field_0x70.HALF_U.LO != 0xFFFF) + SetTile(this->field_0x70.HALF_U.LO, this->field_0x74.HWORD, this->collisionLayer); + return 0; + } + } + return 1; +} + +extern Entity* gUnk_03004040[3]; +extern void sub_080044AE(Entity*, u32, u32); + +void sub_08081FF8(Entity* this) { + u32 direction; + u32 i; + if (this->attachedEntity != &gPlayerEntity) return; + direction = GetFacingDirection(this->attachedEntity, this); + sub_080044AE(this->attachedEntity, 0x200, direction); + for (i = 0; i < 3; i++) { + if (gUnk_03004040[i]) { + sub_080044AE(gUnk_03004040[i],0x200, direction); + } + } +} diff --git a/src/object/cloud.c b/src/object/cloud.c index fce592f1..8a133c2e 100644 --- a/src/object/cloud.c +++ b/src/object/cloud.c @@ -3,6 +3,7 @@ #include "room.h" #include "player.h" #include "flags.h" +#include "functions.h" extern void sub_0809F7BC(Entity*); extern void PlaySFX(u32); @@ -13,7 +14,6 @@ extern void DeleteThisEntity(); extern u32 CheckRoomFlag(u32); extern void sub_08078A90(u32); extern void sub_08078B48(void); -extern u32 Random(void); extern void sub_0806F69C(Entity*); extern void (*gUnk_08124798[])(Entity*); extern void (*gUnk_081247A0[])(Entity*); @@ -23,7 +23,6 @@ extern void PositionEntityOnTop(Entity*, Entity*); extern void sub_0807BB68(u32*, u32, u32); extern u8 gUnk_02034490; -extern u32 gScreenTransition; extern void* gUnk_080DD750; extern Entity gPlayerEntity; extern PlayerState gPlayerState; @@ -62,7 +61,7 @@ void sub_0809F548(Entity* this) { sub_0809F814((((this->x.HALF.HI - gRoomControls.roomOriginX) >> 4) & 63) | (((this->y.HALF.HI - gRoomControls.roomOriginY) >> 4) & 63) << 6); } else { - if ((gScreenTransition & 7) == 0) { + if ((gScreenTransition.frameCount & 7) == 0) { sub_0809F7BC(this); } sub_0809F7F4(this); @@ -110,7 +109,7 @@ void sub_0809F61C(Entity* this) { sub_0809F814((((this->x.HALF.HI - gRoomControls.roomOriginX) >> 4) & 63) | (((this->y.HALF.HI - gRoomControls.roomOriginY) >> 4) & 63) << 6); } else { - if ((gScreenTransition & 7) == 0) { + if ((gScreenTransition.frameCount & 7) == 0) { sub_0809F7BC(this); } sub_0809F7F4(this); @@ -145,7 +144,7 @@ void sub_0809F700(Entity* this) { this->actionDelay = (Random() & 30) + 8; this->flags = this->flags | 12; } - if ((gScreenTransition & 3) == 0) { + if ((gScreenTransition.frameCount & 3) == 0) { uVar2 = Random(); this->spriteOffsetX = gUnk_081247C0[uVar2 & 7]; this->spriteOffsetY = gUnk_081247C0[uVar2 >> 4 & 7]; diff --git a/src/object/fan.c b/src/object/fan.c index e56beeff..04854f4d 100644 --- a/src/object/fan.c +++ b/src/object/fan.c @@ -40,8 +40,8 @@ void sub_0809ED88(Entity *this) { sub_0809F08C(); sub_0809EE44(this); - if (this->field_0x86 != 0) { - if (this->cutsceneBeh.HWORD == this->field_0x86) { + if (this->field_0x86.HWORD != 0) { + if (this->cutsceneBeh.HWORD == this->field_0x86.HWORD) { if (CheckFlags(this->cutsceneBeh.HWORD)) { return; } diff --git a/src/object/floatingBlock.c b/src/object/floatingBlock.c new file mode 100644 index 00000000..3b865e91 --- /dev/null +++ b/src/object/floatingBlock.c @@ -0,0 +1,13 @@ +#include "global.h" +#include "entity.h" +#include "functions.h" + +void FloatingBlock(Entity* this) { + if (this->action == 0) { + this->action = 1; + this->frameIndex=this->entityType.form; + this->spritePriority.b0 = 0xe; + this->collisionLayer = 1; + UpdateSpriteForCollisionLayer(this); + } +}
\ No newline at end of file diff --git a/src/object/greatFairy.c b/src/object/greatFairy.c index 9174ab63..16664216 100644 --- a/src/object/greatFairy.c +++ b/src/object/greatFairy.c @@ -4,6 +4,7 @@ #include "screen.h" #include "greatFairy.h" #include "structures.h" +#include "functions.h" enum { BEHAVIORS, @@ -550,14 +551,14 @@ void sub_08087424(Entity* arg0, struct_08087424* arg1) { void sub_0808747C(u32 arg0, u32 arg1) { u32 iVar1; - iVar1 = FindEntityInListByForm(0x6, 0xf, 0x6, 0xb, 0x0); + iVar1 = (u32)FindEntityInListByForm(0x6, 0xf, 0x6, 0xb, 0x0); if (iVar1 != 0) { iVar1 = 1; } *(u32*)(arg1 + 0x14) = iVar1; } -//clang-format off +// clang-format off void (*const GreatFairy_Main[])(Entity*) = { GreatFairy_CallBehavior, GreatFairy_WingsCallBehavior, @@ -647,5 +648,4 @@ void (*const GreatFairy_Form2Behaviors[])(Entity*) = { sub_08087264, sub_0808727C }; - -//clang-format on +// clang-format on diff --git a/src/object/heartContainer.c b/src/object/heartContainer.c index d55f7171..a2a35887 100644 --- a/src/object/heartContainer.c +++ b/src/object/heartContainer.c @@ -5,9 +5,7 @@ extern void DeleteThisEntity(); extern void sub_08080CB4(Entity*); -extern int sub_08017850(Entity*); -extern void CreateItemEntity(u32, u32, u32); - +extern u32 sub_08017850(Entity*); static void sub_0808E6A0(Entity*); static void sub_0808E6E4(Entity*); static void sub_0808E714(Entity*); @@ -39,7 +37,7 @@ static void sub_0808E6A0(Entity* this) { } static void sub_0808E6E4(Entity* this) { - if (CheckFlags(this->field_0x86)) { + if (CheckFlags(this->field_0x86.HWORD)) { this->action = 2; this->spriteSettings.b.draw = 1; this->spriteRendering.b0 = 3; diff --git a/src/object/hiddenLadderDown.c b/src/object/hiddenLadderDown.c new file mode 100644 index 00000000..932018c8 --- /dev/null +++ b/src/object/hiddenLadderDown.c @@ -0,0 +1,44 @@ +#include "global.h" +#include "entity.h" +#include "functions.h" +#include "room.h" +#include "flags.h" + +extern void (*const gUnk_08122604[])(Entity*); + +void HiddenLadderDown(Entity* this) { + if (this->action < 2) { + gUnk_08122604[this->action](this); + } +} + +void sub_08091F14(Entity* this) { + u16* puVar3; + + this->action = 1; + this->spritePriority.b0 = 7; + this->animIndex = 0; + this->field_0x70.HALF.LO = COORD_TO_TILE(this); + puVar3 = &this->field_0x70.HALF.LO; + if (CheckFlags(this->field_0x86.HWORD) != 0) { + this->action = 2; + this->spriteSettings.b.draw = TRUE; + SetTileType(0x1a2, *puVar3 - 0x41, this->collisionLayer); + SetTileType(0x1a3, *puVar3 - 0x40, this->collisionLayer); + SetTileType(0x1a4, *puVar3 - 0x3f, this->collisionLayer); + SetTileType(0x1a5, *puVar3 - 1, this->collisionLayer); + SetTileType(0x1a6, *puVar3, this->collisionLayer); + SetTileType(0x1a7, *puVar3 + 1, this->collisionLayer); + SetTileType(0x1a8, *puVar3 + 0x3f, this->collisionLayer); + SetTileType(0x1a9, *puVar3 + 0x40, this->collisionLayer); + SetTileType(0x1aa, *puVar3 + 0x41, this->collisionLayer); + } +} + +void sub_08092000(Entity* this) { + if (GetTileType(*(u16*)&this->field_0x70.HALF.LO, this->collisionLayer) == 0x1a6) { + this->action = 2; + this->spriteSettings.b.draw = TRUE; + SetFlag(this->field_0x86.HWORD); + } +}
\ No newline at end of file diff --git a/src/object/itemOnGround.c b/src/object/itemOnGround.c new file mode 100755 index 00000000..ad8bdec9 --- /dev/null +++ b/src/object/itemOnGround.c @@ -0,0 +1,442 @@ +#include "global.h" +#include "entity.h" +#include "flags.h" +#include "functions.h" +#include "player.h" + +static void sub_08081150(Entity*); +static u8 sub_0808147C(u32); +static void sub_080814A4(Entity*); +static u32 sub_080814C0(Entity*); +static void sub_08081500(Entity*); +static void sub_0808153C(Entity*); +static void sub_08081598(Entity*); +static void sub_080813BC(Entity*); +static void sub_080810FC(Entity*); +static bool32 CheckShouldPlayItemGetCutscene(Entity*); + +extern u32 sub_080002D0(Entity*); +extern u32 sub_080177A0(Entity*, Entity*); +extern void GiveItem(u32, u32); +extern u32 sub_0805E40C(Entity*); + +extern void (*const gUnk_0811E7D4[])(Entity*); +extern void (*const gUnk_0811E7E8[])(Entity*); +extern void (*const gUnk_0811E814[])(Entity*); +extern void (*const gUnk_0811E840[])(Entity*); +extern BoundingBox gUnk_080FD1A8; + +typedef struct { + u8 unk0[3]; + u8 unk3; + u8 unk4[4]; +} Unk_080FD5B4; + +extern const Unk_080FD5B4 gUnk_080FD5B4[]; + +typedef struct { + u8 unk0[2]; + u16 sfx; + u8 unk4; + u8 unk5[3]; +} Unk_0811E84C; + +extern const Unk_0811E84C gUnk_0811E84C[]; + +void ItemOnGround(Entity* this) { + if (this->bitfield & 0x80) { + switch (this->bitfield & 0x7F) { + case 20: + this->action = 3; + this->flags &= 0x7F; + this->spriteSettings.b.draw = 1; + this->field_0x3c |= 0x10; + this->attachedEntity = this->field_0x4c; + break; + case 0: + case 1: + case 4: + case 5: + case 6: + case 8: + case 9: + case 10: + case 11: + case 12: + case 30: + sub_08081598(this); + break; + } + } + + if (sub_0806F520(this)) { + sub_080813BC(this); + } else { + gUnk_0811E7D4[this->action](this); + } + + if (this->entityType.form == 0x5C) { + gRoomVars.field_0x4++; + } + + sub_08080CB4(this); +} + +void sub_08080F20(Entity* this) { + if (this->field_0x86.HWORD && CheckFlags(this->field_0x86.HWORD)) { + DeleteThisEntity(); + } + + if (this->entityType.form != 0x60) { + this->spriteSettings.b.draw = 1; + this->spritePriority.b1 = 3; + this->spriteSettings.b.shadow = 0; + this->damageType = 7; + this->field_0x3c = 0x47; + this->field_0x40 = 0x44; + this->currentHealth = 0xFF; + this->boundingBox = &gUnk_080FD1A8; + switch (this->entityType.form - 0x3F) { + case 0: + case 21: + case 22: + case 23: + case 24: + case 25: + case 29: + case 30: + case 31: + case 32: + this->flags2 = 0x17; + break; + default: + this->flags2 = 0x11; + break; + } + + this->field_0x68.HALF.HI = this->actionDelay; + this->field_0x6a.HALF.LO = 0; + this->field_0x6c.HWORD = 0; + this->field_0x68.HALF.LO = 0; + this->actionDelay = 0; + sub_0805E3A0(this, 3); + this->field_0x1c = sub_0808147C(this->entityType.form); + gUnk_0811E7E8[this->field_0x68.HALF.HI](this); + } else { + Entity* entity = CreateObject(0x40, 0x60, 0); + if (entity) { + entity->actionDelay = 0; + if (this->actionDelay == 1) { + entity->entityType.parameter = 2; + } + + CopyPosition(this, entity); + DeleteThisEntity(); + } + } +} + +static void sub_080810A8(Entity* this) { + this->action = 1; + sub_080814A4(this); + if (this->direction & 0x80) { + this->direction &= 0x1F; + if (this->nonPlanarMovement == 0) { + this->nonPlanarMovement = 0x100; + } + } else { + this->direction |= 0xFF; + } + + if (this->field_0x20 == 0) { + this->field_0x20 = 0x1E000; + } + + if (this->collisionLayer == 2) { + sub_08016A30(this); + } +} + +static void sub_080810FC(Entity* this) { + if (this->entityType.form != 0x5F) { + sub_08081598(this); + } else { + this->action = 2; + this->previousActionFlag = 0; + this->flags |= 0x80; + this->flags2 = 0x11; + CopyPosition(&gPlayerEntity, this); + } +} + +void sub_08081134(Entity* this) { + sub_080814A4(this); + this->field_0x6c.HWORD += 80; + sub_08081150(this); +} + +static void sub_08081150(Entity* this) { + this->action = 2; + this->flags |= 0x80; + this->height.HALF.HI = -0x80; + this->spriteOrientation.flipY = 1; + this->spriteRendering.b3 = 1; + PlaySFX(0x12D); +} + +static void sub_08081188(Entity* this) { + this->action = 2; + this->flags |= 0x80; + if (this->collisionLayer == 2) { + sub_08016A30(this); + } +} + +void sub_080811AC(Entity* this) { + this->action = 2; + this->spriteSettings.b.draw = 0; + this->field_0x6e.HWORD = GetTileTypeByEntity(this); +} + +void sub_080811C8(Entity* this) { + this->action = 2; + this->spriteSettings.b.draw = 0; +} + +void sub_080811D8(Entity* this) { + sub_08081188(this); + PlaySFX(0x215); +} + +void sub_080811EC(Entity* this) { + if (this->field_0x68.HALF.HI != 6) { + sub_080AEFE0(this); + } else { + sub_0806F69C(this); + } + + sub_08003FC4(this, 0x2800); + if (this->field_0x20 <= 0) { + this->action = 2; + this->flags |= 0x80; + sub_080814A4(this); + } +} + +void sub_0808122C(Entity* this) { + gUnk_0811E814[this->field_0x68.HALF.HI](this); +} + +void sub_08081248(Entity* this) { + sub_08081500(this); + if (sub_080814C0(this)) { + sub_08081404(this, 0); + } else { + sub_0800442E(this); + } +} + +void sub_0808126C(Entity* this) { + UpdateAnimationSingleFrame(this); + sub_0808153C(this); +} + +void sub_0808127C(Entity* this) { + if (sub_080814C0(this)) { + sub_08081404(this, 0); + } else { + sub_0808153C(this); + } +} + +void nullsub_113(Entity* this) { +} + +void sub_080812A0(Entity* this) { + sub_08081500(this); +} + +void sub_080812A8(Entity* this) { + if (sub_080002D0(this) != 0xF && this->field_0x6e.HWORD != GetTileTypeByEntity(this)) { + this->direction = 0; + this->nonPlanarMovement = 0; + this->spriteSettings.b.draw = 1; + this->field_0x68.HALF.HI = 0; + sub_080810A8(this); + } +} + +void sub_080812E8(Entity* this) { + PlayerState* playerState = &gPlayerState; + if ((playerState->swimState & 0x80) && + !(playerState->flags.all & 0x80) && + sub_080177A0(this, &gPlayerEntity)) { + sub_080810FC(this); + } +} + +void nullsub_510(Entity* this) { +} + +void sub_08081328(Entity* this) { + Entity* other = this->attachedEntity; + if (!(other->entityType.type == 8 && other->entityType.subtype == 3)) { + sub_08081404(this, 0); + } else { + CopyPosition(other, this); + this->height.HALF.HI--; + other = &gPlayerEntity; + if (sub_080177A0(this, other)) { + sub_080810FC(this); + } + } +} + +void sub_0808136C(Entity* this) { + if (--this->actionDelay) { + Entity* other = this->attachedEntity; + this->x.WORD = other->x.WORD; + this->y.WORD = other->y.WORD; + this->spriteOrientation.flipY = other->spriteOrientation.flipY; + this->spriteRendering.b3 = other->spriteRendering.b3; + sub_08003FC4(this, 0x2800); + } else { + sub_08081404(this, 1); + } +} + +static void sub_080813BC(Entity* this) { + gUnk_0811E840[this->previousActionFlag](this); +} + +void sub_080813D4(Entity* this) { + this->previousActionFlag = 1; + this->field_0x1d = 1; + this->spriteSettings.b.draw = 1; +} + +void sub_080813E8(Entity* this) { + sub_0806F4E8(this); +} + +void sub_080813F0(Entity* this) { + if (sub_0806F3E4(this)) { + sub_080810FC(this); + } +} + +void sub_08081404(Entity* this, u32 arg1) { + if (arg1 && this->field_0x86.HWORD) { + SetFlag(this->field_0x86.HWORD); + } + + DeleteThisEntity(); +} + +bool32 sub_08081420(Entity* this) { + if (CheckShouldPlayItemGetCutscene(this)) { + sub_0805E3A0(this, 6); + CreateItemEntity(this->entityType.form, this->entityType.parameter, 0); + return TRUE; + } else { + GiveItem(this->entityType.form, this->entityType.parameter); + return FALSE; + } +} + +static bool32 CheckShouldPlayItemGetCutscene(Entity* this) { + bool32 result = FALSE; + if ((gUnk_080FD5B4[this->entityType.form].unk0[3] & 0x2) || !GetInventoryValue(this->entityType.form)) { + result = TRUE; + } + return result; +} + +static u8 sub_0808147C(u32 arg0) { + const Unk_0811E84C* var0 = &gUnk_0811E84C[arg0]; + return var0->unk4; +} + +void sub_0808148C(u32 arg0) { + const Unk_0811E84C* var0 = &gUnk_0811E84C[arg0]; + if (var0->sfx) { + PlaySFX(var0->sfx); + } +} + +static void sub_080814A4(Entity* this) { + if (this->field_0x68.HALF.HI == 10) { + this->field_0x6c.HWORD = 120; + } else { + this->field_0x6c.HWORD = 600; + } +} + +static u32 sub_080814C0(Entity* this) { + if (!sub_0805E40C(this)) { + if (--this->field_0x6c.HWORD == 0) { + return TRUE; + } + + if (this->field_0x6c.HWORD < 90) { + this->spriteSettings.b.draw ^= 1; + } + } + + return FALSE; +} + +static void sub_08081500(Entity* this) { + if (this->field_0x68.HALF.LO == 0) { + u32 var0 = sub_080044EC(this, 0x2800); + if (var0 == 0) { + this->field_0x68.HALF.LO = 1; + } else { + if (var0 == 1) { + sub_0808148C(this->entityType.form); + UpdateSpriteForCollisionLayer(this); + } + + sub_080AEFE0(this); + } + } +} + +static void sub_0808153C(Entity* this) { + if (this->field_0x68.HALF.LO > 1) + return; + + if (this->field_0x68.HALF.LO == 0) { + if (!sub_08003FC4(this, 0x1000) && !sub_0800442E(this)) { + this->field_0x68.HALF.LO = 1; + this->field_0x20 = 0x1E000; + sub_0808148C(this->entityType.form); + UpdateSpriteForCollisionLayer(this); + } + } else { + if (!sub_08003FC4(this, 0x2800)) { + this->field_0x68.HALF.LO = 2; + sub_0808148C(this->entityType.form); + } + } +} + +static void sub_08081598(Entity* this) { + if (this->currentHealth == 0) { + sub_08081404(this, 1); + } + + this->flags &= 0x7F; + this->action = 4; + this->actionDelay = 14; + this->field_0x20 = 0x20000; + this->spriteSettings.b.draw = 1; + this->spritePriority.b1 = 2; + this->spritePriority.b0 = 3; + this->attachedEntity = &gPlayerEntity; + CopyPosition(this->attachedEntity, this); + this->height.HALF.HI -= 4; + if (this->entityType.form != 0x5F && sub_08081420(this)) { + sub_08081404(this, 1); + } +} diff --git a/src/object/jailBars.c b/src/object/jailBars.c index e4128830..f262e819 100644 --- a/src/object/jailBars.c +++ b/src/object/jailBars.c @@ -18,7 +18,7 @@ void JailBars(Entity *this) void sub_080A08C4(Entity *this) { - if (CheckFlags(this->field_0x86) == 0) { + if (CheckFlags(this->field_0x86.HWORD) == 0) { this->action = 1; sub_080A0960(this, 0); } @@ -34,7 +34,7 @@ void sub_080A08C4(Entity *this) void sub_080A0910(Entity *this) { - if (CheckFlags(this->field_0x86) != 0) { + if (CheckFlags(this->field_0x86.HWORD) != 0) { this->action = 2; sub_080A0960(this, 1); PlaySFX(0x10b); diff --git a/src/object/lightableSwitch.c b/src/object/lightableSwitch.c index 77c6489a..5d3e693c 100644 --- a/src/object/lightableSwitch.c +++ b/src/object/lightableSwitch.c @@ -7,7 +7,7 @@ extern void sub_0809EB30(Entity*); extern void sub_0809EAD8(Entity*); extern void sub_0809EABC(Entity*); -extern void sub_08004488(u32); +extern void EnqueueSFX(u32); extern void sub_080A2CC0(Entity*, Entity**, u16*); extern Entity* GetCurrentRoomProperty(u32); extern void SetTile(u32, u32, u32); @@ -45,12 +45,12 @@ void sub_0809EA34(Entity* this) { void sub_0809EA80(Entity* this) { if ((this->bitfield & 0x80) != 0) { - if (CheckFlags(this->field_0x86) != 0) { - ClearFlag(this->field_0x86); + if (CheckFlags(this->field_0x86.HWORD) != 0) { + ClearFlag(this->field_0x86.HWORD); } else { - SetFlag(this->field_0x86); + SetFlag(this->field_0x86.HWORD); } - sub_08004488(0x110); + EnqueueSFX(0x110); } sub_0809EABC(this); } @@ -59,7 +59,7 @@ void sub_0809EABC(Entity* this) { bool32 anySet; u32 f; - f = CheckFlags(this->field_0x86); + f = CheckFlags(this->field_0x86.HWORD); anySet = (-f | f) >> 0x1F; if (this->frameIndex != anySet) { this->frameIndex = anySet; @@ -122,8 +122,8 @@ void sub_0809EBD8(Entity* this) { this->action = 2; this->actionDelay = 0x10; this->frameIndex = 2; - SetFlag(this->field_0x86); - sub_08004488(0x110); + SetFlag(this->field_0x86.HWORD); + EnqueueSFX(0x110); } } @@ -136,8 +136,8 @@ void sub_0809EC08(Entity* this) { if (--this->actionDelay == 0) { this->action = 1; this->frameIndex = 3; - ClearFlag(this->field_0x86); - sub_08004488(0x110); + ClearFlag(this->field_0x86.HWORD); + EnqueueSFX(0x110); } } } diff --git a/src/object/mask.c b/src/object/mask.c index 675805b8..9fb42c68 100644 --- a/src/object/mask.c +++ b/src/object/mask.c @@ -20,7 +20,7 @@ extern void sub_08000148(u16, u16, u32); extern s16 sub_080001DA(u16, u32); extern u16 sub_080002E0(u16, u32); -extern void sub_08004488(u32); +extern void EnqueueSFX(u32); extern void sub_080044EC(Entity *, u16); extern void sub_0805457C(Entity *, s32); @@ -31,7 +31,7 @@ void Mask(Entity *this) { void sub_080929A4(Entity *this) { if (this->entityType.parameter & 0xC0) { - if (CheckFlags(this->field_0x86)) { + if (CheckFlags(this->field_0x86.HWORD)) { s32 field_0x0a; switch (this->entityType.parameter & 0xC0) { @@ -45,7 +45,7 @@ void sub_080929A4(Entity *this) { goto switchEnd; } - ClearFlag(this->field_0x86); + ClearFlag(this->field_0x86.HWORD); break; case 0x80: DeleteThisEntity(); @@ -115,9 +115,9 @@ void sub_08092B0C(Entity *this) { switch (this->entityType.parameter & 0xC0) { case 0x80: - sub_08004488(0x72); + EnqueueSFX(0x72); case 0x40: - SetFlag(this->field_0x86); + SetFlag(this->field_0x86.HWORD); break; } diff --git a/src/object/metalDoor.c b/src/object/metalDoor.c index 4a4de7f5..888c35f7 100644 --- a/src/object/metalDoor.c +++ b/src/object/metalDoor.c @@ -6,7 +6,7 @@ extern u32 sub_08083734(Entity*, u32); extern void sub_080A080C(Entity*); extern void sub_0806F69C(Entity*); -extern void sub_08004488(u32); +extern void EnqueueSFX(u32); extern void sub_080A0870(Entity*); extern void PlaySFX(u32); extern u32 sub_080001DA(u32, u32); @@ -71,13 +71,13 @@ void sub_080A074C(Entity *this) ent->x.HALF.HI -= 0xc; ent->y.HALF.HI -= 0xc; } - sub_08004488(0x10b); + EnqueueSFX(0x10b); } } void sub_080A07BC(Entity *this) { - if (CheckFlags(this->field_0x86)) { + if (CheckFlags(this->field_0x86.HWORD)) { this->action = 4; this->actionDelay = 0xc; this->direction = 0x10; diff --git a/src/object/minecart.c b/src/object/minecart.c index 783e9696..9207c8c0 100644 --- a/src/object/minecart.c +++ b/src/object/minecart.c @@ -50,7 +50,7 @@ void sub_080916EC(Entity* this) { this->field_0x3c = 0x47; this->field_0x40 = 0x44; this->flags2 = 0x80; - this->direction = this->animationState << 3; + this->direction = DirectionFromAnimationState(this->animationState); this->nonPlanarMovement = 0x700; this->spritePriority.b1 = 3; InitAnimationForceUpdate(this, this->entityType.parameter + 4 + this->animationState); diff --git a/src/object/mineralWaterSource.c b/src/object/mineralWaterSource.c index 61b8a26e..50887521 100644 --- a/src/object/mineralWaterSource.c +++ b/src/object/mineralWaterSource.c @@ -30,8 +30,8 @@ void MineralWaterSource_Init(Entity *this) { this->entityType.parameter = unknownParameters->field_0x00; this->field_0x40 = unknownParameters->field_0x03; - this->boundingBox->field_0x6 = unknownParameters->field_0x01; - this->boundingBox->field_0x7 = unknownParameters->field_0x02; + this->boundingBox->unknown[6] = unknownParameters->field_0x01; + this->boundingBox->unknown[7] = unknownParameters->field_0x02; this->flags |= 0x80; diff --git a/src/object/minishSizedEntrance.c b/src/object/minishSizedEntrance.c index ca261d35..55160cb7 100644 --- a/src/object/minishSizedEntrance.c +++ b/src/object/minishSizedEntrance.c @@ -1,7 +1,6 @@ #include "global.h" #include "entity.h" -extern u32 Random(); extern bool32 CheckIsDungeon(); extern void sub_080AE068(Entity*); extern void LoadFixedGFX(Entity*, u32); diff --git a/src/object/object1A.c b/src/object/object1A.c index 91129a16..a8924998 100644 --- a/src/object/object1A.c +++ b/src/object/object1A.c @@ -1,12 +1,8 @@ #include "global.h" #include "entity.h" +#include "functions.h" -extern void CopyPosition(); extern void sub_08086A6C(); -extern s32 sub_080044EC(); -extern void sub_080AEF88(); -extern void DeleteThisEntity(); -extern u32 Random(void); extern void (*gUnk_081206C4[99])(Entity*); @@ -35,16 +31,14 @@ void sub_080869DC(Entity* ent) { } void sub_08086A28(Entity* ent) { - s32 iVar1; - if (ent->attachedEntity->next == NULL) { ent->action = 2; } else { - iVar1 = sub_080044EC(ent, 10240); + u32 iVar1 = sub_080044EC(ent, 10240); if (iVar1 == 0) { ent->action = 2; } - sub_080AEF88(ent); + ProcessMovement(ent); CopyPosition(ent, ent->attachedEntity); } } diff --git a/src/object/object2A.c b/src/object/object2A.c index 5ce12dc7..44d272c5 100644 --- a/src/object/object2A.c +++ b/src/object/object2A.c @@ -30,11 +30,11 @@ void sub_08089B18(Entity *this) CopyPosition(this->parent, this); break; case 4: - if (!CheckFlags(this->field_0x86)) { + if (!CheckFlags(this->field_0x86.HWORD)) { this->spriteSettings.b.draw = FALSE; this->previousActionFlag = 1; return; } } - sub_08004488(0x124); + EnqueueSFX(0x124); } diff --git a/src/object/object49.c b/src/object/object49.c index e3fa37dd..0617aad2 100644 --- a/src/object/object49.c +++ b/src/object/object49.c @@ -243,10 +243,10 @@ void sub_0808F498(Entity* this) { this->action = 1; this->actionDelay = 64; var0 = this->entityType.parameter != 0 ? 44 : 43; - this->x.HALF.HI -= this->parent->boundingBox->field_0x6; - this->x.HALF.HI += (s32)Random() % (this->parent->boundingBox->field_0x6 * 2); - this->y.HALF.HI -= this->parent->boundingBox->field_0x7; - this->y.HALF.HI += (s32)Random() % (this->parent->boundingBox->field_0x7 * 2); + this->x.HALF.HI -= this->parent->boundingBox->unknown[6]; + this->x.HALF.HI += (s32)Random() % (this->parent->boundingBox->unknown[6] * 2); + this->y.HALF.HI -= this->parent->boundingBox->unknown[7]; + this->y.HALF.HI += (s32)Random() % (this->parent->boundingBox->unknown[7] * 2); sub_0801D2B4(this, var0); InitializeAnimation(this, 4); } diff --git a/src/object/object86.c b/src/object/object86.c index 0520cb55..e6a1b683 100644 --- a/src/object/object86.c +++ b/src/object/object86.c @@ -7,7 +7,6 @@ extern u32 sub_080041A0(Entity*, Entity*, u32, u32); void sub_08099ECC(Entity*); extern void sub_0805E4E0(Entity*, u32); extern void sub_0805B390(u32); -extern void CopyPosition(Entity*, Entity*); extern void (*const gUnk_081237F8[])(Entity*); diff --git a/src/object/object9E.c b/src/object/object9E.c index 8737f21a..5923b167 100644 --- a/src/object/object9E.c +++ b/src/object/object9E.c @@ -5,7 +5,6 @@ extern BoundingBox gUnk_080FD168; extern void SetTile(u32, u32, u32); -extern void CopyPosition(Entity*, Entity*); void Object9E(Entity *this) { diff --git a/src/object/objectA.c b/src/object/objectA.c index 564f83c5..dbb79088 100644 --- a/src/object/objectA.c +++ b/src/object/objectA.c @@ -20,7 +20,7 @@ void ObjectA(Entity *this) { uVar2 = 0x34; } this->field_0x70.HALF.LO = uVar2; - if (CheckFlags(this->field_0x86) != 0) { + if (CheckFlags(this->field_0x86.HWORD) != 0) { SetTileType(*(u16*)&this->field_0x70.HALF.LO, COORD_TO_TILE(this), this->collisionLayer); if ((gRoomControls.unk2 & 1) != 0) { gUnk_02000070 = 0; @@ -31,8 +31,8 @@ void ObjectA(Entity *this) { } } else if (this->interactType != 0) { SetTileType(*(u16*)&this->field_0x70.HALF.LO, COORD_TO_TILE(this), this->collisionLayer); - SetFlag(this->field_0x86); - sub_080A29BC(this); + SetFlag(this->field_0x86.HWORD); + CreateDust(this); sub_080526F8(-1); DeleteThisEntity(); } diff --git a/src/object/objectA8.c b/src/object/objectA8.c index ab7713c5..9f4f4bb4 100644 --- a/src/object/objectA8.c +++ b/src/object/objectA8.c @@ -1,7 +1,7 @@ #include "global.h" #include "entity.h" -extern void CreateItemEntity(u32, u32, u32); +extern Entity* CreateItemEntity(u32, u32, u32); extern void DeleteThisEntity(); extern void sub_08080CB4(Entity*); diff --git a/src/object/objectAF.c b/src/object/objectAF.c index 752cb31f..ac8864bb 100644 --- a/src/object/objectAF.c +++ b/src/object/objectAF.c @@ -2,8 +2,6 @@ #include "entity.h" extern void sub_080A0640(Entity*); -extern void PositionRelative(Entity*, Entity*, s32, s32); -extern void CopyPosition(Entity*, Entity*); extern void (*const gUnk_081248C4[])(Entity*); diff --git a/src/object/objectB2.c b/src/object/objectB2.c index 3db27795..7c4073fb 100644 --- a/src/object/objectB2.c +++ b/src/object/objectB2.c @@ -7,38 +7,32 @@ extern u32 sub_080AE4CC(Entity*, u32, u32, u32); extern void* gUnk_02027EB4; extern void* gUnk_0200D654; -#if 0 +void ObjectB2(Entity* this) { + void* pEVar3; -void ObjectB2(Entity *this) -{ - void* pEVar3; - - if (this->action == 0) { - this->action = 1; - this->actionDelay = 0x10; - this->direction = (this->entityType).form << 3; - if (this->collisionLayer == 2) { - pEVar3 = &gUnk_0200D654; + if (this->action == 0) { + this->action = 1; + this->actionDelay = 0x10; + this->direction = (this->entityType).form << 3; + if (this->collisionLayer == 2) { + pEVar3 = &gUnk_0200D654; + } else { + pEVar3 = &gUnk_02027EB4; + } + this->attachedEntity = pEVar3; + InitializeAnimation(this, this->entityType.form); } - else { - pEVar3 = &gUnk_02027EB4; + this->nonPlanarMovement = this->parent->nonPlanarMovement; + sub_0806F69C(this); + if (sub_080AE4CC(this->attachedEntity, this->x.HALF.HI, this->y.HALF.HI, 9) != 0) { + DeleteThisEntity(); } - this->attachedEntity = pEVar3; - InitializeAnimation(this, this->entityType.form); - } - this->nonPlanarMovement = this->parent->nonPlanarMovement; - sub_0806F69C(this); - if (sub_080AE4CC(this->attachedEntity, this->x.HALF.HI, this->y.HALF.HI, 9) != 0) { - DeleteThisEntity(); - } - if (this->nonPlanarMovement < 0x41) { - this->spriteSettings.b.draw ^= 1; + if (this->nonPlanarMovement < 0x41) { + this->spriteSettings.b.draw ^= 1; - if (--this->actionDelay == 0) { - DeleteThisEntity(); + if (--this->actionDelay == 0) { + DeleteThisEntity(); + } } - } - GetNextFrame(this); + GetNextFrame(this); } - -#endif diff --git a/src/object/pinwheel.c b/src/object/pinwheel.c new file mode 100644 index 00000000..1476bc58 --- /dev/null +++ b/src/object/pinwheel.c @@ -0,0 +1,43 @@ +#include "global.h" +#include "entity.h" +#include "functions.h" + +extern u32 ReadBit(u32*, u32); +extern void DeleteThisEntity(); +extern u32 CheckLocalFlag(u32); + +extern u32 gUnk_020342F8; +extern u16 gUnk_08125050[]; +extern void (*gUnk_0812505C[])(Entity*); + +void Pinwheel(Entity* this) { + u16 x = this->currentHealth; + if ((x & 0x7f) != 0) { + if (ReadBit(&gUnk_020342F8,x-1) == 0) { + DeleteThisEntity(); + } + } + gUnk_0812505C[this->action](this); +} + +void sub_080A23DC(Entity *this) { + this->field_0x68.HWORD = gUnk_08125050[this->entityType.parameter]; + this->spritePriority.b0 = 7; + if (CheckLocalFlag(this->field_0x68.HWORD) !=0) { + this->action = 2; + } + else { + this->action = 1; + } + InitializeAnimation(this,0); +} + +void sub_080A2420(Entity *this) { + if (CheckLocalFlag(this->field_0x68.HWORD) != 0) { + this->action = 2; + CreateDust(this); + } +} +void sub_080A243C(Entity *this) { + GetNextFrame(this); +}
\ No newline at end of file diff --git a/src/object/pot.c b/src/object/pot.c index 5ea63ab5..47ea8c9f 100755 --- a/src/object/pot.c +++ b/src/object/pot.c @@ -18,11 +18,9 @@ extern BoundingBox gUnk_080FD340; // TODO: should be const extern u32 sub_08016A30(Entity*); extern u32 sub_080001DA(u32, u32); -extern u32 GetTileTypeByEntity(Entity*); extern void sub_08078930(Entity*); extern u32 sub_080002B8(Entity*); extern void sub_08016A6C(Entity*); -extern u32 sub_0800442E(Entity*); void Pot(Entity* this) { gUnk_0811F090[this->action](this); @@ -30,7 +28,7 @@ void Pot(Entity* this) { } void sub_0808222C(Entity* this) { - if (this->entityType.parameter == 1 && CheckFlags(this->field_0x86)) { + if (this->entityType.parameter == 1 && CheckFlags(this->field_0x86.HWORD)) { DeleteThisEntity(); } @@ -92,7 +90,7 @@ void sub_08082310(Entity* this) { this->actionDelay = 64; } SetTile((u16)this->field_0x70.HALF.LO, COORD_TO_TILE(this), this->collisionLayer); - sub_08004488(0x10F); + EnqueueSFX(0x10F); break; case 0x4067: SetTile((u16)this->field_0x70.HALF.LO, COORD_TO_TILE(this), this->collisionLayer); @@ -271,7 +269,7 @@ static void sub_08082850(Entity* this, Entity* parent) { } if (this->entityType.parameter == 1) { - SetFlag(this->field_0x86); + SetFlag(this->field_0x86.HWORD); } DeleteThisEntity(); @@ -292,7 +290,7 @@ u32 sub_0808288C(Entity* this, u32 form, u32 arg2, u32 arg3) { if (entity) { if (arg3 == 2) { entity->actionDelay = 5; - entity->field_0x86 = this->field_0x86; + entity->field_0x86.HWORD = this->field_0x86.HWORD; } else { entity->actionDelay = 0; } diff --git a/src/object/railtrack.c b/src/object/railtrack.c index 8ecc8ec0..57f58f76 100644 --- a/src/object/railtrack.c +++ b/src/object/railtrack.c @@ -6,7 +6,7 @@ extern u32* GetLayerByIndex(u32); extern void sub_08085394(Entity*); extern void sub_0808543C(Entity*); -extern void sub_08004488(u32); +extern void EnqueueSFX(u32); extern u32 sub_080854A8(Entity*); extern void SetTile(u32, u32, u32); @@ -32,7 +32,7 @@ void sub_080851AC(Entity* this) { } this->animationState = this->entityType.parameter & 2; if ((this->entityType).form == 3) { - uVar1 = CheckFlags(this->field_0x86); + uVar1 = CheckFlags(this->field_0x86.HWORD); this->field_0x7a.HWORD = uVar1; if ((u16)(uVar1 & -1) != 0) { this->animationState = (this->animationState + 2) & 3; @@ -45,16 +45,16 @@ void sub_080851AC(Entity* this) { } void sub_08085264(Entity* this) { - if (CheckFlags(this->field_0x86)) { + if (CheckFlags(this->field_0x86.HWORD)) { this->action = 2; this->field_0xf = 8; if (this->entityType.form == 1) { - ClearFlag(this->field_0x86); + ClearFlag(this->field_0x86.HWORD); } this->animationState = (this->animationState + *(u8*)&this->field_0x7c) & 3; InitializeAnimation(this, this->animationState); sub_0808543C(this); - sub_08004488(0x151); + EnqueueSFX(0x151); } } @@ -62,11 +62,11 @@ void sub_080852B4(Entity* this) { if (--this->field_0xf == 0) { this->action = 3; this->field_0xf = this->actionDelay; - this->field_0x7a.HWORD = CheckFlags(this->field_0x86); + this->field_0x7a.HWORD = CheckFlags(this->field_0x86.HWORD); this->animationState = (this->animationState + *(u8*)&this->field_0x7c) & 3; InitializeAnimation(this, this->animationState); sub_08085394(this); - sub_08004488(0x151); + EnqueueSFX(0x151); } } @@ -77,13 +77,13 @@ void sub_08085308(Entity* this) { case 1: break; case 2: - if (CheckFlags(this->field_0x86) == 0) { + if (CheckFlags(this->field_0x86.HWORD) == 0) { this->action = 1; return; } break; case 3: - if (CheckFlags(this->field_0x86) == *(u16*)&this->field_0x7a) { + if (CheckFlags(this->field_0x86.HWORD) == *(u16*)&this->field_0x7a) { this->field_0xf = 0xff; } else { this->field_0xf = 1; @@ -96,60 +96,52 @@ void sub_08085308(Entity* this) { this->animationState = (this->animationState + *(u8*)&this->field_0x7c) & 3; InitializeAnimation(this, this->animationState); sub_0808543C(this); - sub_08004488(0x151); + EnqueueSFX(0x151); } } } -#if 0 -void sub_08085394(Entity *this) -{ +void sub_08085394(Entity* this) { u32 uVar1; - u16 *layerData; - u32 iVar3; - u32 uVar4; - u8 *pbVar5; + u16* layerData; + u32 tile; + s8 off; uVar1 = gUnk_081205E0[this->animationState / 2]; - iVar3 = this->animationState / 2; - layerData = *(u16 **)&this->field_0x70; - uVar4 = COORD_TO_TILE(this); - this->field_0x74.HWORD = layerData[gUnk_080B4488[iVar3]]; - pbVar5 = &this->collisionLayer; - SetTile(uVar1, uVar4 - iVar3, *pbVar5); - this->field_0x76 = layerData[0]; - SetTile(uVar1,uVar4, *pbVar5); - *(u16 *)&this->field_0x78 = layerData[iVar3]; - SetTile(uVar1,uVar4 + iVar3, *pbVar5); -} -#endif + off = gUnk_080B4488[this->animationState / 2][0]; + layerData = (u16*)this->field_0x70.WORD; + tile = COORD_TO_TILE(this); -NAKED -void sub_08085394(Entity* this) { - asm(".include \"asm/non_matching/railtrack/sub_08085394.inc\""); + this->field_0x74.HWORD = *(layerData - off); + SetTile(uVar1, tile - off, this->collisionLayer); + + this->field_0x76.HWORD = layerData[0x0]; + SetTile(uVar1, tile - 0x0, this->collisionLayer); + + this->field_0x78.HWORD = layerData[off]; + SetTile(uVar1, tile + off, this->collisionLayer); } -void sub_0808543C(Entity *this) -{ - s8 *cVar1; - u32 uVar2; - s8 temp; - - temp = gUnk_080B4488[this->animationState / 2][0]; - uVar2 = COORD_TO_TILE(this); - SetTile(this->field_0x74.HWORD, uVar2 - temp, this->collisionLayer); - SetTile(this->field_0x76.HWORD, uVar2, this->collisionLayer); - SetTile(this->field_0x78.HWORD, uVar2 + temp, this->collisionLayer); +void sub_0808543C(Entity* this) { + s8* cVar1; + u32 uVar2; + s8 temp; + + temp = gUnk_080B4488[this->animationState / 2][0]; + uVar2 = COORD_TO_TILE(this); + SetTile(this->field_0x74.HWORD, uVar2 - temp, this->collisionLayer); + SetTile(this->field_0x76.HWORD, uVar2, this->collisionLayer); + SetTile(this->field_0x78.HWORD, uVar2 + temp, this->collisionLayer); } -u32 sub_080854A8(Entity *this) { +u32 sub_080854A8(Entity* this) { u16 var0; u16* var1; s8* var2; var0 = gUnk_081205E0[this->animationState / 2]; var2 = gUnk_080B4488[this->animationState / 2]; - var1 = (u16 *)this->field_0x70.WORD; + var1 = (u16*)this->field_0x70.WORD; if (var0 != *(var1 - var2[0])) { return TRUE; } diff --git a/src/object/smoke.c b/src/object/smoke.c index 48fcaff8..54047762 100644 --- a/src/object/smoke.c +++ b/src/object/smoke.c @@ -1,10 +1,8 @@ #include "global.h" #include "entity.h" +#include "functions.h" -extern u32 Random(void); -extern void CopyPosition(Entity*, Entity*); extern void sub_0806F69C(Entity*); -extern void DeleteEntity(Entity*); extern void (*const gUnk_08121060[])(Entity*); extern void (*const gUnk_08121070[])(Entity*); diff --git a/src/object/treeHidingPortal.c b/src/object/treeHidingPortal.c index 446731a8..8d34e3b9 100644 --- a/src/object/treeHidingPortal.c +++ b/src/object/treeHidingPortal.c @@ -6,7 +6,7 @@ extern void sub_0809E96C(Entity*); extern u32 sub_0800419C(Entity*, Entity*, u32, u32); -extern void sub_080A2B80(Entity*); +extern void CreateSparkle(Entity*); extern u32 sub_0809E9A0(void); extern void sub_08078A90(u32); extern void sub_0809E918(Entity*); @@ -23,7 +23,7 @@ void TreeHidingPortal(Entity* this) { } void sub_0809E83C(Entity* this) { - if (CheckFlags(this->field_0x86)) { + if (CheckFlags(this->field_0x86.HWORD)) { sub_0809E96C(this); DeleteThisEntity(); } @@ -37,7 +37,7 @@ void sub_0809E86C(Entity* this) { if (sub_0800419C(this, &gPlayerEntity, 0x30, 0x30)) { if (CheckGlobalFlag(EZERO_1ST)) { if (((gScreenTransition & 3) == 0)) { - sub_080A2B80(this); + CreateSparkle(this); } } } @@ -60,7 +60,7 @@ void sub_0809E8BC(Entity* this) { void sub_0809E8EC(Entity* this) { if (--this->actionDelay == 0) { - SetFlag(this->field_0x86); + SetFlag(this->field_0x86.HWORD); sub_08078A90(0); PlaySFX(0x73); DeleteThisEntity(); @@ -2057,7 +2057,7 @@ extern EntityData gUnk_080DE4C8; void sub_0804CBB0(void) { - if ((gPlayerEntity.y.HALF.HI - gRoomControls.roomOriginY) < (gRoomControls.filler2[4] >> 1)) { + if ((gPlayerEntity.y.HALF.HI - gRoomControls.roomOriginY) < (gRoomControls.height >> 1)) { if (!CheckLocalFlag(0x17)) { LoadRoomEntityList(&gUnk_080DE4C8); } diff --git a/src/sub_08055E08.c b/src/sub_08055E08.c index 19a2ebd6..aeabdb1d 100644 --- a/src/sub_08055E08.c +++ b/src/sub_08055E08.c @@ -1,13 +1,35 @@ - #include "global.h" +#include "menu.h" +#include "room.h" +#include "functions.h" extern u32* _call_via_r0(u32* func); -extern u8 gMenu; -extern u32* gUnk_080FF420; - -void sub_08055E08() { - u32** arr = &gUnk_080FF420; - u8 i = gMenu; - i = *(&gMenu + 6); - _call_via_r0(arr[i]); +extern void (*const gUnk_080FF420[])(); +extern void sub_0804B0B0(u32, u32); +extern void sub_08055B70(u32, u32, u32, u32); + +struct { + /*0x00*/ u8 unk0; + /*0x10*/ u8 filler1[0x1B]; + /*0x1c*/ u8 unk1C; + /*0x1d*/ u8 unk1D; + /*0x1e*/ u8 unk1E; + /*0x1f*/ u8 unk1F; +} gUnk_02000070 = {}; + +extern EntityData gUnk_080FF400; + +void sub_08055E08(void) { + gUnk_080FF420[gMenu.overlayType](); } + +void sub_08055E24(void) { + gMenu.overlayType++; + gUnk_02000070.unk0 = 1; + sub_0804B0B0(gMenu.field_0xc[2], gMenu.field_0xc[3]); + LoadRoomEntityList(&gUnk_080FF400); + sub_08055B70(gMenu.field_0x4, 0, 0, 0); + DoFade(4, 0x10); +} + +void nullsub_493(void) {}
\ No newline at end of file diff --git a/src/sub_0807C998.c b/src/sub_0807C998.c index 1919ea14..8fdf37a3 100644 --- a/src/sub_0807C998.c +++ b/src/sub_0807C998.c @@ -2,28 +2,28 @@ #include "entity.h" extern void sub_0807C960(); -extern u32 gUnk_0202CEB4; -extern u32 gUnk_02012654; +extern u16 gMetatilesBottom[]; +extern u16 gMetatilesTop[]; extern u8 gUnk_08324AE4; void sub_0807C960(void* dest, u32 offset) { - void* temp; + void* src; if (offset != -1) { - temp = &gUnk_08324AE4 + (offset & 0x7fffffff); + src = &gUnk_08324AE4 + (offset & 0x7fffffff); if ((u32)dest >> 0x18 == 6) { - LZ77UnCompVram(temp, (void *)dest); + LZ77UnCompVram(src, (void *)dest); } else { - LZ77UnCompWram(temp, (void *)dest); + LZ77UnCompWram(src, (void *)dest); } } } void sub_0807C998(u32* a1) { - sub_0807C960(&gUnk_0202CEB4, a1[0]); - sub_0807C960(&gUnk_0202CEB4 - 0x800, a1[1]); - sub_0807C960(&gUnk_02012654, a1[2]); - sub_0807C960(&gUnk_02012654 - 0x800, a1[3]); + sub_0807C960(gMetatilesBottom, a1[0]); + sub_0807C960(gMetatilesBottom - 0x1000, a1[1]); + sub_0807C960(gMetatilesTop, a1[2]); + sub_0807C960(gMetatilesTop - 0x1000, a1[3]); } |
