From 35bb351dd5f50c09c8dd9f92fa7cbf1d5cfd8e9d Mon Sep 17 00:00:00 2001 From: gamezter Date: Sat, 11 Jan 2025 19:21:59 -0500 Subject: [PATCH] Decompile `no1` EntityBoneArcher --- config/symbols.us.stno1.txt | 3 +- include/entity.h | 12 ++ src/st/no1/e_bone_archer.c | 320 +++++++++++++++++++++++++++++++++++- src/st/no1/e_init.c | 4 +- src/st/no1/no1.h | 4 +- 5 files changed, 335 insertions(+), 8 deletions(-) diff --git a/config/symbols.us.stno1.txt b/config/symbols.us.stno1.txt index ae29fbfb90..b297c86f28 100644 --- a/config/symbols.us.stno1.txt +++ b/config/symbols.us.stno1.txt @@ -6,6 +6,7 @@ g_EInitCommon = 0x801809B0; NO1_RedDoorTiles = 0x80180C9C; g_testCollRandTable = 0x801814FC; D_80182A4C = 0x80182A4C; +D_80182D44 = 0x80182D44; sprites_3 = 0x801A86BC; Random = 0x801C19F0; Update = 0x801C1A20; @@ -30,10 +31,8 @@ GetAngleBetweenEntitiesShifted = 0x801C4B14; GetAnglePointToEntityShifted = 0x801C4B5C; AdjustValueWithinThreshold = 0x801C4BA4; SetStep = 0x801C4D98; -SetSubStep = 0x801C4DB8; EntityExplosionSpawn = 0x801C4DD4; InitializeEntity = 0x801C4E68; -UnkCollisionFunc = 0x801C4F8C; GetPlayerCollisionWith = 0x801C520C; ReplaceBreakableWithItemDrop = 0x801C5550; UnkCollisionFunc5 = 0x801C87A4; diff --git a/include/entity.h b/include/entity.h index 83ddada2a5..72beb3c70f 100644 --- a/include/entity.h +++ b/include/entity.h @@ -2410,6 +2410,17 @@ typedef struct { /* 0x84 */ u32 unk84; } ET_SkeletonApeBarrel; +typedef struct { + /* 0x7C */ s32 : 32; + /* 0x80 */ s32 : 32; + /* 0x84 */ s16 unk84; + /* 0x86 */ s16 unk86; + /* 0x88 */ s16 unk88; + /* 0x8A */ s16 : 16; + /* 0x8C */ u8 unk8C; + /* 0x8D */ u8 : 8; +} ET_801D0598; + typedef union { // offset=0x7C struct Primitive* prim; ET_Placeholder ILLEGAL; @@ -2611,6 +2622,7 @@ typedef union { // offset=0x7C ET_801B9304 et_801B9304; ET_801B7188 et_801B7188; ET_801BBD90 et_801BBD90; + ET_801D0598 et_801D0598; } Ext; #define SYNC_FIELD(struct1, struct2, field) \ diff --git a/src/st/no1/e_bone_archer.c b/src/st/no1/e_bone_archer.c index 46bccbc78a..9fc50b8702 100644 --- a/src/st/no1/e_bone_archer.c +++ b/src/st/no1/e_bone_archer.c @@ -1,8 +1,322 @@ // SPDX-License-Identifier: AGPL-3.0-or-later -#include "common.h" +#include "no1.h" -// Bone Archer -INCLUDE_ASM("st/no1/nonmatchings/e_bone_archer", func_us_801D0598); +typedef struct { + u8* animation; + u8 frameA; + u8 frameB; + s16 xOffset; + s16 yOffset; +} unk_801D0598; + +extern u16 D_us_80180AC4[]; +extern s16 D_us_80182BD8[]; +extern s16 D_us_80182BE8[]; +extern u16 D_us_80182BF0[]; +extern u8 D_us_80182BF8[]; +extern u8 D_us_80182C04[]; +extern u8 D_us_80182C0C[]; +extern unk_801D0598 D_us_80182CD4[]; +extern s32 D_us_80182D04[]; +extern s32 D_us_80182D24[]; +extern u8 D_80182D44[]; + +void EntityBoneArcher(Entity* self) { + unk_801D0598* var_s2; + Entity* tempEntity; + s32 step; + s32 i; + u8* anim; + s32 tempVar; + u8 unused; + + if (self->flags & FLAG_DEAD) { + self->hitboxState = 0; + SetStep(11); + } + switch (self->step) { + case 0: + InitializeEntity(D_us_80180AC4); + if (self->params) { + self->hitboxState = 0; + self->animCurFrame = self->params + 0x18; + self->flags |= FLAG_DESTROY_IF_OUT_OF_CAMERA | + FLAG_DESTROY_IF_BARELY_OUT_OF_CAMERA | + FLAG_UNK_00200000 | FLAG_UNK_2000; + self->step = 12; + } else { + self->facingLeft = (GetSideToPlayer() & 1) ^ 1; + } + break; + + case 1: + if (UnkCollisionFunc3(D_us_80182BD8) & 1) { + self->step = 2; + } + break; + + case 2: + self->facingLeft = (GetSideToPlayer() & 1) ^ 1; + if (GetDistanceToPlayerX() < 0x80) { + SetStep(3); + } + break; + + case 3: + if (!self->step_s) { + self->ext.et_801D0598.unk84 = 0x40; + self->step_s++; + } + self->animCurFrame = 1; + self->facingLeft = (GetSideToPlayer() & 1) ^ 1; + if (GetDistanceToPlayerX() < 0x60) { + SetStep(13); + } + if (!--self->ext.et_801D0598.unk84) { + step = self->ext.et_801D0598.unk8C; + step += 7; + SetStep(step); + if (++self->ext.et_801D0598.unk8C > 2) { + self->ext.et_801D0598.unk8C = 0; + } + } + break; + + case 13: + if (!AnimateEntity(D_us_80182C04, self)) { + SetStep(5); + } + break; + + case 14: + if (!AnimateEntity(D_us_80182C0C, self)) { + SetStep(3); + } + break; + + case 4: + case 5: + if (!self->step_s) { + self->ext.et_801D0598.unk86 = 0x40; + self->step_s++; + } + if (!AnimateEntity(D_us_80182BF8, self)) { + self->facingLeft = (GetSideToPlayer() & 1) ^ 1; + } + step = 0; + tempVar = UnkCollisionFunc2(D_us_80182BE8); + if (self->facingLeft) { + self->velocityX = FIX(0.75); + } else { + self->velocityX = FIX(-0.75); + } + if (self->step == 5) { + self->velocityX = -self->velocityX; + } + switch (self->step) { + case 4: + if (GetDistanceToPlayerX() < 0x40) { + SetStep(5); + } + if (tempVar & 0x80) { + tempVar = UnkCollisionFunc(D_us_80182BF0, 2); + if (tempVar & 2) { + SetStep(6); + } + } + break; + case 5: + if (GetDistanceToPlayerX() > 0x80) { + SetStep(4); + } + if (tempVar & 0x80) { + self->animCurFrame = 1; + self->ext.et_801D0598.unk86 = 1; + step = 0xA; + } + break; + } + if (!--self->ext.et_801D0598.unk86) { + if (step == 0) { + step = self->ext.et_801D0598.unk8C; + step += 7; + } + SetStep(step); + if (++self->ext.et_801D0598.unk8C > 2) { + self->ext.et_801D0598.unk8C = 0; + } + } + break; + + case 6: + if (!self->step_s) { + if (self->facingLeft) { + self->velocityX = FIX(1.0); + } else { + self->velocityX = FIX(-1.0); + } + self->velocityY = FIX(-4.0); + self->step_s++; + self->animCurFrame = 0xE; + } + if (UnkCollisionFunc3(D_us_80182BD8) & 1) { + SetStep(4); + } + break; + + case 7: + case 8: + case 10: + case 9: + switch (self->step_s) { + case 0: + if (self->step == 9) { + if (self->hitboxHeight == 0xE) { + self->step_s = 2; + } else { + self->step_s = 3; + } + } else { + if (self->hitboxHeight == 0x16) { + self->step_s = 1; + } else { + self->step_s = 3; + } + } + break; + case 1: + if (!AnimateEntity(D_us_80182C0C, self)) { + SetSubStep(3); + } + break; + case 2: + if (!AnimateEntity(D_us_80182C04, self)) { + SetSubStep(3); + } + break; + case 3: + tempVar = self->step - 7; + var_s2 = &D_us_80182CD4[tempVar]; + anim = var_s2->animation; + unused = var_s2->frameA; + switch (self->step) { + case 7: + if (!self->animFrameDuration && self->animFrameIdx == 5) { + PlaySfxPositional(SFX_CREAK); + } + break; + case 8: + if (!self->animFrameDuration && self->animFrameIdx == 1) { + PlaySfxPositional(SFX_CREAK); + } + break; + case 10: + if (!self->animFrameDuration && self->animFrameIdx == 2) { + PlaySfxPositional(SFX_CREAK); + } + break; + case 9: + if (!self->animFrameDuration && self->animFrameIdx == 4) { + PlaySfxPositional(SFX_CREAK); + } + break; + } + if (!AnimateEntity(anim, self)) { + self->facingLeft = (GetSideToPlayer() & 1) ^ 1; + self->ext.et_801D0598.unk84 = 0x40; + if (self->step == 9) { + SetStep(14); + } else { + SetStep(3); + } + } else if (!self->animFrameDuration) { + if (self->animCurFrame != var_s2->frameA) { + if (self->animCurFrame == var_s2->frameB) { + tempVar = 1; + } else { + break; + } + } else { + tempVar = 0; + } + tempEntity = AllocEntity(&g_Entities[160], &g_Entities[192]); + if (tempEntity != NULL) { + PlaySfxPositional(SFX_ARROW_SHOT_C); + CreateEntityFromEntity(E_ID_45, self, tempEntity); + tempEntity->facingLeft = self->facingLeft; + if (tempVar != 0) { + var_s2 = &D_us_80182CD4[0]; + } + if (self->facingLeft) { + tempEntity->posX.i.hi += var_s2->xOffset; + } else { + tempEntity->posX.i.hi += var_s2->xOffset; + } + tempEntity->posY.i.hi += var_s2->yOffset; + } + } + break; + } + break; + + case 11: + tempVar = GetSideToPlayer() & 1; + for (i = 0; i < 8; i++) { + tempEntity = AllocEntity(&g_Entities[224], &g_Entities[256]); + if (tempEntity == NULL) { + break; + } + CreateEntityFromEntity(E_ID_44, self, tempEntity); + tempEntity->facingLeft = self->facingLeft; + tempEntity->params = i + 1; + if (tempVar != 0) { + tempEntity->velocityX = D_us_80182D04[i]; + } else { + tempEntity->velocityX = -D_us_80182D04[i]; + } + tempEntity->velocityY = D_us_80182D24[i]; + tempEntity->ext.et_801D0598.unk88 = D_80182D44[i]; + } + + tempEntity = AllocEntity(&g_Entities[224], &g_Entities[256]); + if (tempEntity != NULL) { + PlaySfxPositional(SFX_SKELETON_DEATH_B); + CreateEntityFromEntity(E_EXPLOSION, self, tempEntity); + tempEntity->params = 2; + } + DestroyEntity(self); + return; + + case 12: + MoveEntity(); + self->velocityY += FIX(0.25); + if (!--self->ext.et_801D0598.unk88) { + tempEntity = AllocEntity(&g_Entities[224], &g_Entities[256]); + if (tempEntity != NULL) { + CreateEntityFromEntity(E_EXPLOSION, self, tempEntity); + tempEntity->params = 0; + } + DestroyEntity(self); + return; + } + break; + + case 0xFF: + #include "../pad2_anim_debug.h" + } + tempVar = self->animCurFrame; + if ((tempVar > 10 && tempVar < 15) || tempVar > 32) { + self->hitboxOffX = 4; + self->hitboxOffY = -7; + self->hitboxWidth = 8; + self->hitboxHeight = 22; + } else { + self->hitboxOffX = 0; + self->hitboxOffY = 1; + self->hitboxWidth = 17; + self->hitboxHeight = 14; + } +} // Bone Archer arrow INCLUDE_ASM("st/no1/nonmatchings/e_bone_archer", func_us_801D0F0C); diff --git a/src/st/no1/e_init.c b/src/st/no1/e_init.c index 393ebf76bd..1e2c00d427 100644 --- a/src/st/no1/e_init.c +++ b/src/st/no1/e_init.c @@ -68,7 +68,7 @@ void EntitySkeletonPieces(Entity* self); void func_us_801CDE20(Entity* self); void func_us_801CEA2C(Entity* self); void func_us_801CE958(Entity* self); -void func_us_801D0598(Entity* self); +void EntityBoneArcher(Entity* self); void func_us_801D0F0C(Entity* self); void func_us_801CEB28(Entity* self); void func_us_801CF298(Entity* self); @@ -164,7 +164,7 @@ PfnEntityUpdate OVL_EXPORT(EntityUpdates)[] = { func_us_801CDE20, func_us_801CEA2C, func_us_801CE958, - func_us_801D0598, + EntityBoneArcher, func_us_801D0F0C, func_us_801CEB28, func_us_801CF298, diff --git a/src/st/no1/no1.h b/src/st/no1/no1.h index c24bd0f2b9..409aebf623 100644 --- a/src/st/no1/no1.h +++ b/src/st/no1/no1.h @@ -41,7 +41,9 @@ typedef enum EntityIDs { /* 0x41 */ E_ID_41, /* 0x42 */ E_ID_42, /* 0x43 */ E_ID_43, - /* 0x46 */ E_ID_46 = 0x46, + /* 0x44 */ E_ID_44, + /* 0x45 */ E_ID_45, + /* 0x46 */ E_ID_46, /* 0x47 */ E_ID_47, /* 0x48 */ E_ID_48, /* 0x49 */ E_ID_49,