mirror of
https://github.com/Xeeynamo/sotn-decomp.git
synced 2024-11-26 22:40:33 +00:00
Decompile no0
Skelerang entities (#1900)
~~Planning on giving this a tidy up when I import data and do some analysis in debugger so I'll fix up some of the naming then unless there's something glaring that sticks out here.~~ `func_us_801D191C` / `EntitySkelerangUnknown` was previous decompiled but slightly updated here for PSP match: https://decomp.me/scratch/8lEH0 `func_us_801D20A4` / `EntitySkelerangBoomerang` matching both PSX: https://decomp.me/scratch/SMgwb PSP: https://decomp.me/scratch/WFD0w `func_us_801D191C` / `EntitySkelerang` matching both PSX: https://decomp.me/scratch/BUkq2 PSP: https://decomp.me/scratch/OYg4D Thanks to Discord gang for helping with some PSP stuff here ^
This commit is contained in:
parent
fe8c58f3a1
commit
dfea3429ae
@ -185,6 +185,9 @@ EntityStoneDoor = 0x801CE0F8;
|
||||
EntityClockRoomUnused = 0x801CE2D8;
|
||||
StageNamePopupHelper = 0x801CE654;
|
||||
EntityStageNamePopup = 0x801CE824;
|
||||
EntitySkelerang = 0x801D191C;
|
||||
EntitySkelerangBoomerang = 0x801D20A4;
|
||||
EntitySkelerangUnknown = 0x801D2318;
|
||||
func_801CD78C = 0x801D2374;
|
||||
EntityGhostEnemy = 0x801D5E4C;
|
||||
EntityGhostEnemySpawner = 0x801D606C;
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define LOHU(x) (*(u16*)&(x))
|
||||
#define LOW(x) (*(s32*)&(x))
|
||||
#define LOWU(x) (*(u32*)&(x))
|
||||
#define F(x) (*(f32*)&(x))
|
||||
|
||||
#if defined(HACKS) && !defined(PERMUTER)
|
||||
#define ALIGNED4 __attribute__((aligned(4)))
|
||||
|
@ -2055,10 +2055,6 @@ typedef struct {
|
||||
/* 0x84 */ u32 speed;
|
||||
} ET_GhostEnemy;
|
||||
|
||||
// ====== RIC ENTITIES ======
|
||||
|
||||
// ==========================
|
||||
|
||||
typedef struct {
|
||||
/* 0x7C */ struct Entity* next;
|
||||
/* 0x80 */ s16 timer;
|
||||
@ -2081,6 +2077,14 @@ typedef struct {
|
||||
/* 0x94 */ s16 unk94;
|
||||
} ET_StoneRose;
|
||||
|
||||
typedef struct {
|
||||
/* 0x7C */ s32 : 32;
|
||||
/* 0x80 */ u8 angle;
|
||||
/* 0x81 */ u8 : 8;
|
||||
/* 0x82 */ u16 : 16;
|
||||
/* 0x84 */ s16 unk84;
|
||||
} ET_Skelerang;
|
||||
|
||||
typedef union { // offset=0x7C
|
||||
struct Primitive* prim;
|
||||
ET_Placeholder ILLEGAL;
|
||||
@ -2257,6 +2261,7 @@ typedef union { // offset=0x7C
|
||||
ET_StoneRose stoneRose;
|
||||
ET_GhostEnemy ghostEnemy;
|
||||
ET_GhostEnemySpawner ghostEnemySpawner;
|
||||
ET_Skelerang skelerang;
|
||||
} Ext;
|
||||
|
||||
#define SYNC_FIELD(struct1, struct2, field) \
|
||||
|
@ -46,9 +46,9 @@ void func_us_801C27A4(Entity*);
|
||||
void func_us_801C2A34(Entity*);
|
||||
void func_us_801C2CD8(Entity*);
|
||||
void func_us_801C2E7C(Entity*);
|
||||
void func_us_801D191C(Entity*);
|
||||
void func_us_801D20A4(Entity*);
|
||||
void func_us_801D2318(Entity*);
|
||||
void EntitySkelerang(Entity*);
|
||||
void EntitySkelerangBoomerang(Entity*);
|
||||
void EntitySkelerangUnknown(Entity*);
|
||||
void func_us_801D2A64(Entity*);
|
||||
void func_us_801D4324(Entity*);
|
||||
void func_us_801D44A0(Entity*);
|
||||
@ -129,9 +129,9 @@ PfnEntityUpdate OVL_EXPORT(EntityUpdates)[] = {
|
||||
func_us_801C2A34,
|
||||
func_us_801C2CD8,
|
||||
func_us_801C2E7C,
|
||||
func_us_801D191C,
|
||||
func_us_801D20A4,
|
||||
func_us_801D2318,
|
||||
EntitySkelerang,
|
||||
EntitySkelerangBoomerang,
|
||||
EntitySkelerangUnknown,
|
||||
func_us_801D2A64,
|
||||
func_us_801D4324,
|
||||
func_us_801D44A0,
|
||||
@ -189,8 +189,8 @@ EInit D_us_80180B3C = {ANIMSET_OVL(0x09), 0x08, 0x4B, 0x20E, 0x005};
|
||||
EInit D_us_80180B48 = {ANIMSET_OVL(0x09), 0x16, 0x4B, 0x20E, 0x012};
|
||||
EInit D_us_80180B54 = {ANIMSET_OVL(0x0D), 0x00, 0x4E, 0x2C0, 0x013};
|
||||
EInit g_EInitElevator = {ANIMSET_OVL(0x0B), 0x01, 0x48, 0x223, 0x005};
|
||||
EInit D_us_80180B6C = {ANIMSET_OVL(0x04), 0x01, 0x48, 0x228, 0x00B};
|
||||
EInit D_us_80180B78 = {ANIMSET_OVL(0x04), 0x2B, 0x48, 0x228, 0x00C};
|
||||
EInit g_EInitSkelerang = {ANIMSET_OVL(0x04), 0x01, 0x48, 0x228, 0x00B};
|
||||
EInit g_EInitSkelerangBoomerang = {ANIMSET_OVL(0x04), 0x2B, 0x48, 0x228, 0x00C};
|
||||
EInit D_us_80180B84 = {ANIMSET_OVL(0x05), 0x01, 0x4C, 0x22B, 0x061};
|
||||
EInit D_us_80180B90 = {ANIMSET_OVL(0x05), 0x16, 0x4C, 0x22B, 0x062};
|
||||
EInit g_EInitGhostEnemy = {ANIMSET_OVL(0x06), 0x01, 0x4A, 0x200, 0x09C};
|
||||
|
@ -2,17 +2,351 @@
|
||||
#include "common.h"
|
||||
#include "no0.h"
|
||||
|
||||
INCLUDE_ASM("st/no0/nonmatchings/e_skelerang", func_us_801D191C);
|
||||
typedef enum {
|
||||
SKELERANG_INIT,
|
||||
SKELERANG_GROUND_INIT,
|
||||
SKELERANG_IDLE = 3,
|
||||
SKELERANG_ATTACK_INIT,
|
||||
SKELERANG_WAKE_ANIM,
|
||||
SKELERANG_BOOMERANG_CHECK,
|
||||
SKELERANG_ATTACK_PREAMBLE,
|
||||
SKELERANG_COWER,
|
||||
SKELERANG_POST_ATTACK,
|
||||
SKELERANG_DEATH_COWER,
|
||||
SKELERANG_DEATH = 12,
|
||||
SKELERANG_DEATH_FLY = 14,
|
||||
SKELERANG_DEBUG = 16
|
||||
} SkelerangSteps;
|
||||
|
||||
INCLUDE_ASM("st/no0/nonmatchings/e_skelerang", func_us_801D20A4);
|
||||
typedef enum {
|
||||
BOOMERANG_INIT,
|
||||
BOOMERANG_PRETHROW,
|
||||
BOOMERANG_FLY,
|
||||
BOOMERANG_IN_HAND,
|
||||
BOOMERANG_DESTROY
|
||||
} SkelerangBoomerangSteps;
|
||||
|
||||
extern u16 g_EInitInteractable[];
|
||||
extern u16 D_us_80181E94[]; // sensors_ground
|
||||
extern Point16 D_us_80181EA4[]; // positions
|
||||
extern u8 D_us_80181EC8[]; // anim
|
||||
extern u8 D_us_80181EDC[]; // anim
|
||||
extern u8 D_us_80181F00[]; // anim
|
||||
extern u8 D_us_80181F34[]; // anim
|
||||
extern u8 D_us_80181F38[]; // anim
|
||||
extern u8 D_us_80181F4C[]; // anim
|
||||
extern u8 D_us_80181F60[]; // anim
|
||||
|
||||
void func_us_801D2318(Entity* entity) {
|
||||
if (entity->step == 0) {
|
||||
void EntitySkelerang(Entity* self) {
|
||||
Entity* entity;
|
||||
Entity* entityTwo;
|
||||
s32 i;
|
||||
u8 index;
|
||||
|
||||
if (self->step % 2 && GetDistanceToPlayerY() < 32 &&
|
||||
GetDistanceToPlayerX() < 80) {
|
||||
SetStep(SKELERANG_COWER);
|
||||
}
|
||||
|
||||
if ((self->flags & FLAG_DEAD) && self->step < 10) {
|
||||
self->hitboxState = 0;
|
||||
PlaySfxPositional(SFX_SKELETON_DEATH_C);
|
||||
DestroyEntity(self + 1);
|
||||
(self + 2)->step = BOOMERANG_DESTROY;
|
||||
(self + 3)->step = BOOMERANG_DESTROY;
|
||||
if (self->animCurFrame > 39) {
|
||||
SetStep(SKELERANG_DEATH_COWER);
|
||||
} else {
|
||||
SetStep(SKELERANG_DEATH);
|
||||
}
|
||||
}
|
||||
|
||||
switch (self->step) {
|
||||
case SKELERANG_INIT:
|
||||
InitializeEntity(g_EInitSkelerang);
|
||||
CreateEntityFromEntity(E_SKELERANG_UNK, self, self + 1);
|
||||
|
||||
entity = self + 2;
|
||||
CreateEntityFromEntity(E_SKELERANG_BOOMERANG, self, entity);
|
||||
entity->params = 0;
|
||||
entity->facingLeft = self->params;
|
||||
|
||||
entity = self + 3;
|
||||
CreateEntityFromEntity(E_SKELERANG_BOOMERANG, self, entity);
|
||||
entity->params = 1;
|
||||
entity->facingLeft = self->params;
|
||||
|
||||
self->facingLeft = self->params;
|
||||
break;
|
||||
case SKELERANG_GROUND_INIT:
|
||||
if (UnkCollisionFunc3(D_us_80181E94) & 1) {
|
||||
SetStep(SKELERANG_IDLE);
|
||||
}
|
||||
break;
|
||||
case SKELERANG_IDLE:
|
||||
self->animCurFrame = 1;
|
||||
// When player gets close enough shift into wake up animation
|
||||
if (!(self->posY.i.hi & 256) && GetDistanceToPlayerX() < 128) {
|
||||
if (((GetSideToPlayer() & 1) ^ 1) == self->facingLeft) {
|
||||
SetStep(SKELERANG_WAKE_ANIM);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SKELERANG_WAKE_ANIM:
|
||||
if (!AnimateEntity(D_us_80181EC8, self)) {
|
||||
SetStep(SKELERANG_ATTACK_INIT);
|
||||
}
|
||||
break;
|
||||
case SKELERANG_POST_ATTACK:
|
||||
if (!self->step_s) {
|
||||
self->ext.skelerang.unk84 = 0;
|
||||
self->step_s++;
|
||||
}
|
||||
if (!AnimateEntity(D_us_80181EDC, self)) {
|
||||
self->ext.skelerang.unk84++;
|
||||
}
|
||||
if (self->ext.skelerang.unk84 == 3) {
|
||||
self->ext.skelerang.unk84 = 0;
|
||||
// If player is still in range after throwing 3 boomerangs, keep
|
||||
// attacking, else return to idle
|
||||
if (GetDistanceToPlayerX() < 144 && GetDistanceToPlayerY() < 144 &&
|
||||
((GetSideToPlayer() & 1) ^ 1) == self->facingLeft) {
|
||||
SetStep(SKELERANG_ATTACK_INIT);
|
||||
} else {
|
||||
SetStep(SKELERANG_IDLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SKELERANG_ATTACK_INIT:
|
||||
// Play catch animation
|
||||
if (!AnimateEntity(D_us_80181F00, self)) {
|
||||
SetStep(SKELERANG_BOOMERANG_CHECK);
|
||||
}
|
||||
if (self->animCurFrame == 30) {
|
||||
// Spawn thrown boomerangs
|
||||
PlaySfxPositional(SFX_THROW_WEAPON_SWISHES);
|
||||
entityTwo = &PLAYER;
|
||||
entity = self + 1;
|
||||
entity->posX.i.hi = entityTwo->posX.i.hi;
|
||||
entity->posY.i.hi = entityTwo->posY.i.hi;
|
||||
|
||||
entity = self + 2;
|
||||
entity->posX.i.hi = self->posX.i.hi;
|
||||
entity->posY.i.hi = self->posY.i.hi;
|
||||
entity->animCurFrame = 43;
|
||||
entity->step++;
|
||||
|
||||
entity = self + 3;
|
||||
entity->posX.i.hi = self->posX.i.hi;
|
||||
entity->posY.i.hi = self->posY.i.hi;
|
||||
entity->animCurFrame = 43;
|
||||
entity->step++;
|
||||
}
|
||||
break;
|
||||
case SKELERANG_BOOMERANG_CHECK:
|
||||
entity = self + 2;
|
||||
entityTwo = self + 3;
|
||||
// If boomerangs are back in hand, prep for another attack
|
||||
if (entity->step == BOOMERANG_IN_HAND &&
|
||||
entityTwo->step == BOOMERANG_IN_HAND) {
|
||||
entity->step = BOOMERANG_PRETHROW;
|
||||
entityTwo->step = BOOMERANG_PRETHROW;
|
||||
SetStep(SKELERANG_ATTACK_PREAMBLE);
|
||||
}
|
||||
break;
|
||||
case SKELERANG_ATTACK_PREAMBLE:
|
||||
if (!AnimateEntity(D_us_80181F34, self)) {
|
||||
self->ext.skelerang.unk84++;
|
||||
// Throw boomerangs 3 times, then return to attack init
|
||||
if (self->ext.skelerang.unk84 > 2) {
|
||||
SetStep(SKELERANG_POST_ATTACK);
|
||||
} else {
|
||||
SetStep(SKELERANG_ATTACK_INIT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SKELERANG_COWER:
|
||||
switch (self->step_s) {
|
||||
case 0:
|
||||
if (!AnimateEntity(D_us_80181F38, self)) {
|
||||
self->animFrameIdx = 0;
|
||||
self->animFrameDuration = 0;
|
||||
self->step_s++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// Play cower animation until player gets far enough away
|
||||
AnimateEntity(D_us_80181F60, self);
|
||||
if ((GetDistanceToPlayerX() > 80) ||
|
||||
(GetDistanceToPlayerY() > 48)) {
|
||||
self->animFrameIdx = 0;
|
||||
self->animFrameDuration = 0;
|
||||
self->step_s++;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// Once player is far enough away move out of cower and back into
|
||||
// potential attack state
|
||||
if (!AnimateEntity(D_us_80181F4C, self)) {
|
||||
SetStep(SKELERANG_POST_ATTACK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SKELERANG_DEATH_COWER:
|
||||
entity = AllocEntity(&g_Entities[224], &g_Entities[256]);
|
||||
if (entity != NULL) {
|
||||
CreateEntityFromEntity(2, self, entity);
|
||||
entity->params = 2;
|
||||
entity->posY.i.hi += 24;
|
||||
}
|
||||
DestroyEntity(self);
|
||||
break;
|
||||
case SKELERANG_DEATH:
|
||||
for (i = 0; i < 8; i++) {
|
||||
entity = AllocEntity(&g_Entities[224], &g_Entities[256]);
|
||||
if (entity != NULL) {
|
||||
MakeEntityFromId(E_SKELERANG, self, entity);
|
||||
entity->flags = FLAG_DESTROY_IF_OUT_OF_CAMERA |
|
||||
FLAG_POS_CAMERA_LOCKED | FLAG_UNK_2000;
|
||||
entity->hitboxState = 0;
|
||||
entity->animCurFrame = i + 44;
|
||||
entity->params = i;
|
||||
entity->facingLeft = self->facingLeft;
|
||||
if ((GetSideToPlayer() & 1) ^ 1) {
|
||||
// Sus store to Entity 0xA
|
||||
F(entity->velocityX).i.hi = -(Random() & 3);
|
||||
} else {
|
||||
// Sus store to Entity 0xA
|
||||
// This + 1 - 1 is an oddity that is required to align PSP
|
||||
F(entity->velocityX).i.hi = (Random() & 3) + 1 - 1;
|
||||
}
|
||||
// Sus store to Entity 0xE
|
||||
F(entity->velocityY).i.hi = -2 - (Random() & 3);
|
||||
entity->ext.skelerang.unk84 = 16;
|
||||
entity->step = SKELERANG_DEATH_FLY;
|
||||
}
|
||||
}
|
||||
|
||||
entity = AllocEntity(&g_Entities[224], &g_Entities[256]);
|
||||
if (entity != NULL) {
|
||||
CreateEntityFromEntity(2, self, entity);
|
||||
entity->params = 2;
|
||||
}
|
||||
DestroyEntity(self);
|
||||
break;
|
||||
case SKELERANG_DEATH_FLY:
|
||||
// When dying body goes flying back in flames
|
||||
MoveEntity();
|
||||
self->velocityY += FIX(0.1875);
|
||||
if (!--self->ext.skelerang.unk84) {
|
||||
entity = AllocEntity(&g_Entities[224], &g_Entities[256]);
|
||||
if (entity != NULL) {
|
||||
CreateEntityFromEntity(2, self, entity);
|
||||
index = self->params;
|
||||
if (self->facingLeft) {
|
||||
entity->posX.i.hi -= D_us_80181EA4[index].x;
|
||||
} else {
|
||||
entity->posX.i.hi += D_us_80181EA4[index].x;
|
||||
}
|
||||
entity->posY.i.hi += D_us_80181EA4[index].y;
|
||||
}
|
||||
DestroyEntity(self);
|
||||
}
|
||||
break;
|
||||
case SKELERANG_DEBUG:
|
||||
#include "../pad2_anim_debug.h"
|
||||
}
|
||||
|
||||
if (self->animCurFrame > 39) {
|
||||
self->hitboxOffX = -1;
|
||||
self->hitboxOffY = 16;
|
||||
self->hitboxWidth = 8;
|
||||
self->hitboxHeight = 8;
|
||||
} else {
|
||||
self->hitboxOffX = 0;
|
||||
self->hitboxOffY = 2;
|
||||
self->hitboxWidth = 5;
|
||||
self->hitboxHeight = 21;
|
||||
}
|
||||
}
|
||||
|
||||
void EntitySkelerangBoomerang(Entity* self) {
|
||||
Entity* entity;
|
||||
u8 step;
|
||||
s16 angle;
|
||||
s16 posX;
|
||||
s16 posY;
|
||||
|
||||
switch (self->step) {
|
||||
case BOOMERANG_INIT:
|
||||
InitializeEntity(g_EInitSkelerangBoomerang);
|
||||
self->drawFlags |= FLAG_DRAW_ROTZ;
|
||||
self->animCurFrame = 0;
|
||||
self->hitboxState = 0;
|
||||
break;
|
||||
case BOOMERANG_PRETHROW:
|
||||
entity = (self - 2) - self->params;
|
||||
self->posX.i.hi = entity->posX.i.hi;
|
||||
self->posY.i.hi = entity->posY.i.hi;
|
||||
self->hitboxState = 0;
|
||||
self->animCurFrame = 0;
|
||||
self->step_s = 0;
|
||||
self->ext.skelerang.unk84 = 48;
|
||||
if (self->params) {
|
||||
self->ext.skelerang.angle = 0;
|
||||
return;
|
||||
}
|
||||
self->ext.skelerang.angle = 128;
|
||||
break;
|
||||
case BOOMERANG_FLY:
|
||||
self->hitboxState = 1;
|
||||
MoveEntity();
|
||||
self->rotZ += 256;
|
||||
if (!self->ext.skelerang.unk84) {
|
||||
self->step_s = 1;
|
||||
} else {
|
||||
self->ext.skelerang.unk84--;
|
||||
}
|
||||
entity = (self - 1) - self->params - self->step_s;
|
||||
angle = GetAngleBetweenEntitiesShifted(self, entity);
|
||||
step = self->step_s + 3;
|
||||
self->ext.skelerang.angle =
|
||||
AdjustValueWithinThreshold(step, self->ext.skelerang.angle, angle);
|
||||
SetEntityVelocityFromAngle(self->ext.skelerang.angle, 48);
|
||||
posX = entity->posX.i.hi - self->posX.i.hi;
|
||||
posY = entity->posY.i.hi - self->posY.i.hi;
|
||||
posX = abs(posX);
|
||||
posY = abs(posY);
|
||||
if (posX < 6 && posY < 6) {
|
||||
PlaySfxPositional(SFX_MULTI_CLOCK_TICK);
|
||||
self->step_s++;
|
||||
}
|
||||
if (self->step_s == 2) {
|
||||
self->step++;
|
||||
}
|
||||
break;
|
||||
case BOOMERANG_IN_HAND:
|
||||
self->hitboxState = 0;
|
||||
self->rotZ = 512;
|
||||
break;
|
||||
case BOOMERANG_DESTROY:
|
||||
entity = AllocEntity(&g_Entities[224], &g_Entities[256]);
|
||||
if (entity != NULL) {
|
||||
CreateEntityFromEntity(2, self, entity);
|
||||
entity->params = 1;
|
||||
}
|
||||
DestroyEntity(self);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EntitySkelerangUnknown(Entity* entity) {
|
||||
Entity* parent;
|
||||
if (!entity->step) {
|
||||
InitializeEntity(g_EInitInteractable);
|
||||
}
|
||||
if ((entity - 1)->entityId != 0x2E) {
|
||||
parent = entity - 1;
|
||||
if (parent->entityId != E_SKELERANG) {
|
||||
DestroyEntity(entity);
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,9 @@ typedef enum EntityIDs {
|
||||
/* 0x14 */ E_ID_14 = 0x14,
|
||||
/* 0x15 */ E_GREY_PUFF,
|
||||
/* 0x1D */ E_CLOCK_ROOM_SHADOW = 0x20,
|
||||
/* 0x2E */ E_SKELERANG = 0x2E,
|
||||
/* 0x2F */ E_SKELERANG_BOOMERANG,
|
||||
/* 0x30 */ E_SKELERANG_UNK,
|
||||
/* 0x37 */ E_GHOST_ENEMY = 0x37,
|
||||
/* 0x3B */ E_SLINGER_THROWN_BONE = 0x3B,
|
||||
/* 0x3C */ E_SLINGER_PIECES,
|
||||
@ -52,6 +55,7 @@ typedef enum EntityIDs {
|
||||
extern s16 g_SineTable[];
|
||||
extern u16 g_EInitCommon[];
|
||||
extern u16 g_EInitParticle[];
|
||||
extern u16 g_EInitInteractable[];
|
||||
|
||||
// Axe knight
|
||||
extern EInit g_EInitAxeKnightAxe;
|
||||
@ -76,6 +80,10 @@ extern EInit g_EInitSlingerRib;
|
||||
// Ghost (enemy)
|
||||
extern EInit g_EInitGhostEnemy;
|
||||
|
||||
// Skelerang
|
||||
extern EInit g_EInitSkelerang;
|
||||
extern EInit g_EInitSkelerangBoomerang;
|
||||
|
||||
// Clock room
|
||||
extern EInit g_Statues;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user