Decompile no0 main Ouija Table function (#1859)

Match on both
PSX: https://decomp.me/scratch/A79x5
PSP: https://decomp.me/scratch/HJrWp

The functions directly after this are related to the sub-entities such
as vase and beaker I believe, so I'll decompile those next. Possible
this might lead to changes in the extensions I've added here.

Think this was my first time adding new extension(s) so let me know if
something's wrong there

Once all that's done I'll split into a separate Ouija Table file with
all the related code.
This commit is contained in:
Josh Schreuder 2024-11-02 06:38:44 +11:00 committed by GitHub
parent 55a696cba9
commit 8dbb75fb78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 151 additions and 2 deletions

View File

@ -189,6 +189,7 @@ func_801C4550 = 0x801DB470;
EntityAxeKnight = 0x801DB4DC;
EntityAxeKnightRotateAxe = 0x801DBBE0;
EntityAxeKnightThrowingAxe = 0x801DBC38;
EntityOuijaTable = 0x801DBDCC;
SkeletonAttackCheck = 0x801DCAB0;
EntitySkeleton = 0x801DCB48;
EntitySkeletonPieces = 0x801DD018;

View File

@ -1986,6 +1986,25 @@ typedef struct {
/* 0xAE */ s16 unkAE;
} ET_BackgroundVortex;
typedef struct {
/* 0x7C */ s32 : 32;
/* 0x80 */ s16 attackTimer;
/* 0x82 */ s16 : 16;
/* 0x84 */ s32 : 32;
/* 0x88 */ s32 : 32;
/* 0x8C */ s32 : 32;
/* 0x90 */ s32 unk90;
} ET_OuijaTable;
typedef struct {
/* 0x7C */ s32 : 32;
/* 0x80 */ s32 : 32;
/* 0x84 */ s32 spawned;
/* 0x88 */ struct Entity* parent;
/* 0x8C */ s32 : 32;
/* 0x90 */ s32 isThrown;
} ET_OuijaTableContents;
// ====== RIC ENTITIES ======
// ==========================
@ -2166,6 +2185,8 @@ typedef union { // offset=0x7C
ET_ClockTower clockTower;
ET_BackgroundVortex bgVortex;
ET_MedusaUnk1A medusaUnk1A;
ET_OuijaTable ouijaTable;
ET_OuijaTableContents ouijaTableContents;
} Ext;
#define SYNC_FIELD(struct1, struct2, field) \

View File

@ -1,8 +1,134 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
#include "common.h"
#include "game.h"
#include "no0.h"
INCLUDE_ASM("st/no0/nonmatchings/5BDCC", func_us_801DBDCC);
#define VASE self + 1
#define BEAKER self + 2
#define WALKING_TABLE self + 3
extern u16 D_us_80180C14[];
extern s16 D_us_801825CC[];
extern u16 D_us_801825D4[];
extern u8 D_us_801825F4[];
typedef enum {
/* 0 */ OUIJA_TABLE_INIT,
/* 1 */ OUIJA_TABLE_INIT_SUBENTITIES,
/* 2 */ OUIJA_TABLE_COME_ALIVE,
/* 3 */ OUIJA_TABLE_ATTACK,
/* 4 */ OUIJA_TABLE_UNUSED,
/* 255 */ OUIJA_TABLE_DEBUG = 255,
} OuijaTableSteps;
// Main Ouija Table entity
void EntityOuijaTable(Entity* self) {
Entity* otherEntity;
if (self->flags & FLAG_DEAD) {
otherEntity = AllocEntity(&g_Entities[224], &g_Entities[256]);
if (otherEntity != NULL) {
CreateEntityFromEntity(E_EXPLOSION, self, otherEntity);
otherEntity->params = 1;
}
PlaySfxPositional(SFX_STUTTER_FIREBALL);
// Destroy the spinning objects on the table
otherEntity = VASE;
otherEntity->flags |= FLAG_UNK_2000;
otherEntity = BEAKER;
otherEntity->flags |= FLAG_UNK_2000;
DestroyEntity(self);
return;
}
switch (self->step) {
case OUIJA_TABLE_INIT:
InitializeEntity(D_us_80180C14);
self->animCurFrame = 5;
self->hitboxOffY = 2;
return;
case OUIJA_TABLE_INIT_SUBENTITIES:
if (UnkCollisionFunc3(D_us_801825D4) & 1) {
// Spawn objects on the table
otherEntity = VASE;
CreateEntityFromEntity(E_OUIJA_TABLE_COMPONENT, self, otherEntity);
otherEntity->params = 0;
otherEntity->ext.ouijaTableContents.parent = self;
otherEntity->posX.i.hi -= 4;
otherEntity->posY.i.hi -= 16;
otherEntity = BEAKER;
CreateEntityFromEntity(E_OUIJA_TABLE_COMPONENT, self, otherEntity);
otherEntity->params = 1;
otherEntity->ext.ouijaTableContents.parent = self;
otherEntity->posX.i.hi += 2;
otherEntity->posY.i.hi -= 20;
otherEntity = WALKING_TABLE;
CreateEntityFromEntity(E_OUIJA_TABLE_COMPONENT, self, otherEntity);
otherEntity->params = 2;
otherEntity->ext.ouijaTableContents.parent = self;
if (self->params) {
otherEntity->posX.i.hi += 24;
otherEntity->facingLeft = 1;
} else {
otherEntity->posX.i.hi -= 24;
}
#ifndef VERSION_PSP
// Looks like a coding error
otherEntity->posY.i.hi = otherEntity->posY.i.hi;
#endif
self->step++;
}
break;
case OUIJA_TABLE_COME_ALIVE:
// When player approaches, spring to life
if ((GetDistanceToPlayerX() < 80) && (GetDistanceToPlayerY() < 64)) {
self->facingLeft = (GetSideToPlayer() & 1) ^ 1;
otherEntity = BEAKER;
otherEntity->ext.ouijaTableContents.spawned = true;
otherEntity = VASE;
otherEntity->ext.ouijaTableContents.spawned = true;
SetStep(3);
}
break;
case OUIJA_TABLE_ATTACK:
if (!self->step_s) {
self->ext.ouijaTable.attackTimer = 128;
self->step_s += 1;
}
if (AnimateEntity(D_us_801825F4, self) == 0) {
self->facingLeft = (GetSideToPlayer() & 1) ^ 1;
}
UnkCollisionFunc2(D_us_801825CC);
if (self->facingLeft) {
self->velocityX = FIX(0.5);
} else {
self->velocityX = FIX(-0.5);
}
if (!(--self->ext.ouijaTable.attackTimer)) {
self->ext.ouijaTable.attackTimer = 192;
// Throw out one of the objects on the table
if (self->ext.ouijaTable.unk90 != 0) {
otherEntity = VASE;
} else {
otherEntity = BEAKER;
}
otherEntity->ext.ouijaTableContents.isThrown = true;
// Alternate between throwing vase and beaker
self->ext.ouijaTable.unk90 ^= 1;
}
break;
case OUIJA_TABLE_UNUSED:
break;
case OUIJA_TABLE_DEBUG:
#include "../pad2_anim_debug.h"
}
}
INCLUDE_ASM("st/no0/nonmatchings/5BDCC", func_us_801DC194);

View File

@ -34,6 +34,7 @@ typedef enum EntityIDs {
/* 0x3C */ E_SLINGER_PIECES,
/* 0x48 */ E_AXE_KNIGHT_AXE = 0x48,
/* 0x49 */ E_WARG_EXP_OPAQUE,
/* 0x4B */ E_OUIJA_TABLE_COMPONENT = 0x4B,
/* 0x4D */ E_SKELETON = 0x4D,
/* 0x4E */ E_SKELETON_THROWN_BONE,
/* 0x4F */ E_SKELETON_PIECES,