mirror of
https://github.com/Xeeynamo/sotn-decomp.git
synced 2024-12-03 18:30:57 +00:00
Decompile no0
Ghost functions (#1889)
`EntityGhostEnemySpawner` / `func_us_801D606C` matching both PSX: https://decomp.me/scratch/CrIPN PSP: https://decomp.me/scratch/RyIgW `EntityGhostEnemy` / `func_us_801D5E4C` matching both PSX: https://decomp.me/scratch/YEAXd PSP: https://decomp.me/scratch/HpJ4I Also extracted the data and split files. That's for these cute little fellas: ![image](https://github.com/user-attachments/assets/516928da-7969-4908-93b7-6ced09f6dd79)
This commit is contained in:
parent
966cfae72a
commit
6c8454590a
@ -56,6 +56,8 @@ segments:
|
||||
- [0x1C14, data]
|
||||
- [0x1C34, data, clock_room]
|
||||
- [0x1CA0, data]
|
||||
- [0x1FC8, .data, e_ghost]
|
||||
- [0x1FE8, data]
|
||||
- [0x2194, .data, e_slinger]
|
||||
- [0x2268, data]
|
||||
- [0x2478, .data, e_axe_knight]
|
||||
@ -102,6 +104,7 @@ segments:
|
||||
- [0x4E2E0, c]
|
||||
- [0x4E654, c, e_stage_name]
|
||||
- [0x4F4A8, c, unk_4F4A8]
|
||||
- [0x55E4C, c, e_ghost]
|
||||
- [0x56254, c, e_marionette]
|
||||
- [0x575E4, c, e_slinger]
|
||||
- [0x57C20, c, 57C20]
|
||||
|
@ -9,6 +9,7 @@ g_EInitUnkId13 = 0x80180AD0;
|
||||
g_EInitCommon = 0x80180AE8;
|
||||
g_EInitDamageNum = 0x80180B18;
|
||||
g_EInitElevator = 0x80180B60;
|
||||
g_EInitGhostEnemy = 0x80180B9C;
|
||||
g_EInitSlinger = 0x80180BB4;
|
||||
g_EInitSlingerPieces = 0x80180BC0;
|
||||
g_EInitAxeKnight = 0x80180BFC;
|
||||
@ -184,6 +185,8 @@ EntityClockRoomUnused = 0x801CE2D8;
|
||||
StageNamePopupHelper = 0x801CE654;
|
||||
EntityStageNamePopup = 0x801CE824;
|
||||
func_801CD78C = 0x801D2374;
|
||||
EntityGhostEnemy = 0x801D5E4C;
|
||||
EntityGhostEnemySpawner = 0x801D606C;
|
||||
EntitySlinger = 0x801D7670;
|
||||
EntitySlingerPieces = 0x801D7B40;
|
||||
func_801C3F9C = 0x801DAEBC;
|
||||
|
@ -2036,6 +2036,18 @@ typedef struct {
|
||||
/* 0xA4 */ struct Primitive* unkA4;
|
||||
} ET_801D9264;
|
||||
|
||||
typedef struct {
|
||||
/* 0x7C */ s32 : 32;
|
||||
/* 0x80 */ s16 timer;
|
||||
} ET_GhostEnemySpawner;
|
||||
|
||||
typedef struct {
|
||||
/* 0x7C */ s32 : 32;
|
||||
/* 0x80 */ s16 angle;
|
||||
/* 0x82 */ s16 : 16;
|
||||
/* 0x84 */ u32 speed;
|
||||
} ET_GhostEnemy;
|
||||
|
||||
// ====== RIC ENTITIES ======
|
||||
|
||||
// ==========================
|
||||
@ -2220,6 +2232,8 @@ typedef union { // offset=0x7C
|
||||
ET_OuijaTableContents ouijaTableContents;
|
||||
ET_FleaMan fleaMan;
|
||||
ET_801D9264 et_801D9264;
|
||||
ET_GhostEnemy ghostEnemy;
|
||||
ET_GhostEnemySpawner ghostEnemySpawner;
|
||||
} Ext;
|
||||
|
||||
#define SYNC_FIELD(struct1, struct2, field) \
|
||||
|
@ -553,6 +553,7 @@ enum Sfx {
|
||||
SFX_SLOGRA_ROAR_DEFEAT,
|
||||
SFX_SLOGRA_PAIN_A, // Used for Gaibon
|
||||
SFX_SLOGRA_PAIN_B,
|
||||
SFX_GHOST_ENEMY_HOWL = 1849,
|
||||
SFX_CLOCK_BELL = 1958,
|
||||
SFX_CLOCK_ROOM_TICK = 1961
|
||||
};
|
||||
|
112
src/st/no0/e_ghost.c
Normal file
112
src/st/no0/e_ghost.c
Normal file
@ -0,0 +1,112 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
#include "no0.h"
|
||||
|
||||
static u8 anim_phase_in[] = {0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03,
|
||||
0x04, 0x03, 0x05, 0x03, 0x06, 0xFF, 0x00};
|
||||
static u8 anim_burning[] = {0x03, 0x07, 0x03, 0x08, 0x00};
|
||||
static s16 min_max_positions[] = {
|
||||
416, 1152, 288, 480}; // xMin, xMax, yMin, yMax
|
||||
|
||||
void EntityGhostEnemy(Entity* self) {
|
||||
Entity* newEntity;
|
||||
s16 angle;
|
||||
s32 speed;
|
||||
|
||||
if (self->flags & FLAG_DEAD) {
|
||||
PlaySfxPositional(SFX_GHOST_ENEMY_HOWL);
|
||||
newEntity = AllocEntity(&g_Entities[224], &g_Entities[256]);
|
||||
if (newEntity != NULL) {
|
||||
CreateEntityFromEntity(2, self, newEntity);
|
||||
newEntity->params = 1;
|
||||
}
|
||||
DestroyEntity(self);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (self->step) {
|
||||
case 0:
|
||||
InitializeEntity(g_EInitGhostEnemy);
|
||||
self->hitboxOffX = 1;
|
||||
self->hitboxOffY = -1;
|
||||
self->hitboxState = 0;
|
||||
// fallthrough
|
||||
case 1:
|
||||
self->facingLeft = (GetSideToPlayer() & 1) ^ 1;
|
||||
self->step++;
|
||||
break;
|
||||
case 2:
|
||||
if (!AnimateEntity(anim_phase_in, self)) {
|
||||
self->hitboxState = 7;
|
||||
SetStep(3);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (!AnimateEntity(anim_burning, self)) {
|
||||
self->facingLeft = (GetSideToPlayer() & 1) ^ 1;
|
||||
}
|
||||
MoveEntity();
|
||||
|
||||
// Seek towards player
|
||||
newEntity = &PLAYER;
|
||||
angle = GetAngleBetweenEntities(self, newEntity);
|
||||
angle = GetNormalizedAngle(16, self->ext.ghostEnemy.angle, angle);
|
||||
speed = self->ext.ghostEnemy.speed;
|
||||
self->velocityX = (speed * rcos(angle)) >> 12;
|
||||
self->velocityY = (speed * rsin(angle)) >> 12;
|
||||
self->ext.ghostEnemy.angle = angle;
|
||||
|
||||
speed += FIX(0.015625);
|
||||
if (speed > FIX(0.75)) {
|
||||
speed = FIX(0.75);
|
||||
}
|
||||
// If player is hit, bounce back off in opposite direction
|
||||
if (self->hitFlags) {
|
||||
speed = FIX(-0.75);
|
||||
}
|
||||
self->ext.ghostEnemy.speed = speed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityGhostEnemySpawner(Entity* self) {
|
||||
Entity* entity;
|
||||
s32 xPos;
|
||||
s32 yPos;
|
||||
s16* minMaxPositions;
|
||||
|
||||
if (!self->step) {
|
||||
InitializeEntity(D_us_80180A88);
|
||||
self->flags &= ~FLAG_UNK_2000;
|
||||
self->ext.ghostEnemySpawner.timer = 1;
|
||||
}
|
||||
if (!--self->ext.ghostEnemySpawner.timer) {
|
||||
self->ext.ghostEnemySpawner.timer = (Random() & 47) + 48;
|
||||
entity = &PLAYER;
|
||||
xPos = g_Tilemap.scrollX.i.hi + entity->posX.i.hi;
|
||||
yPos = g_Tilemap.scrollY.i.hi + entity->posY.i.hi;
|
||||
if (self->params) {
|
||||
minMaxPositions = &min_max_positions[(self->params - 1) * 4];
|
||||
if (xPos < minMaxPositions[0] || xPos > minMaxPositions[1] ||
|
||||
yPos < minMaxPositions[2] || yPos > minMaxPositions[3]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
entity = AllocEntity(&g_Entities[160], &g_Entities[164]);
|
||||
if (entity != NULL) {
|
||||
CreateEntityFromEntity(E_GHOST_ENEMY, self, entity);
|
||||
entity->zPriority = 170;
|
||||
entity->posX.i.hi = xPos - g_Tilemap.scrollX.i.hi;
|
||||
entity->posY.i.hi = yPos - g_Tilemap.scrollY.i.hi;
|
||||
xPos = (Random() & 63) + 48;
|
||||
if (Random() & 1) {
|
||||
entity->posX.i.hi += xPos;
|
||||
} else {
|
||||
entity->posX.i.hi -= xPos;
|
||||
}
|
||||
|
||||
yPos = ((Random() & 127) - 64);
|
||||
entity->posY.i.hi += yPos;
|
||||
}
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ typedef enum EntityIDs {
|
||||
/* 0x14 */ E_ID_14 = 0x14,
|
||||
/* 0x15 */ E_GREY_PUFF,
|
||||
/* 0x1D */ E_CLOCK_ROOM_SHADOW = 0x20,
|
||||
/* 0x37 */ E_GHOST_ENEMY = 0x37,
|
||||
/* 0x3B */ E_SLINGER_THROWN_BONE = 0x3B,
|
||||
/* 0x3C */ E_SLINGER_PIECES,
|
||||
/* 0x44 */ E_ID_44 = 0x44,
|
||||
@ -51,22 +52,26 @@ extern u16 g_EInitCommon[];
|
||||
extern u16 g_EInitParticle[];
|
||||
|
||||
// Axe knight
|
||||
extern u16 g_EInitAxeKnightAxe[];
|
||||
extern EInit g_EInitAxeKnightAxe;
|
||||
|
||||
// Skeleton
|
||||
extern u16 g_EInitSkeleton[];
|
||||
extern u16 g_EInitSkeletonPieces[];
|
||||
extern u16 g_EInitSkeletonBone[];
|
||||
extern EInit g_EInitSkeleton;
|
||||
extern EInit g_EInitSkeletonPieces;
|
||||
extern EInit g_EInitSkeletonBone;
|
||||
|
||||
// Ouija Table
|
||||
extern u16 g_EInitOuijaTable[];
|
||||
extern u16 g_EInitOuijaTableComponent[];
|
||||
extern EInit g_EInitOuijaTable;
|
||||
extern EInit g_EInitOuijaTableComponent;
|
||||
|
||||
// Flea Man
|
||||
extern u16 g_EInitFleaMan[];
|
||||
extern EInit g_EInitFleaMan;
|
||||
|
||||
// Ghost (enemy)
|
||||
extern EInit g_EInitGhostEnemy;
|
||||
|
||||
// Clock room
|
||||
extern u16 g_Statues[];
|
||||
extern EInit g_Statues;
|
||||
|
||||
// Clocks?
|
||||
extern u16 D_us_80180A88[];
|
||||
// Seems shared between a number of entities - ghost spawner,
|
||||
// func_us_801C2B24 (clocks?), func_us_801CC750
|
||||
extern EInit D_us_80180A88;
|
||||
|
@ -132,7 +132,3 @@ INCLUDE_ASM("st/no0/nonmatchings/unk_4F4A8", func_us_801D52E0);
|
||||
INCLUDE_ASM("st/no0/nonmatchings/unk_4F4A8", func_us_801D5384);
|
||||
|
||||
INCLUDE_ASM("st/no0/nonmatchings/unk_4F4A8", func_us_801D542C);
|
||||
|
||||
INCLUDE_ASM("st/no0/nonmatchings/unk_4F4A8", func_us_801D5E4C);
|
||||
|
||||
INCLUDE_ASM("st/no0/nonmatchings/unk_4F4A8", func_us_801D606C);
|
||||
|
Loading…
Reference in New Issue
Block a user