mirror of
https://github.com/Xeeynamo/sotn-decomp.git
synced 2024-11-23 13:09:44 +00:00
Decompile NZ0 EntityBossFightManager (#1283)
A few changes here. First, Slogra needs to be split out to his own file, as mentioned in my previous PR. I decompiled EntityCloseBossRoom, but I decided it needed a better name, since, while it does close the door to the boss room, it actually does a lot more and in general manages the fight (most importantly, it starts the fight, spawns Slogra and Gaibon, and when they die, spawns the life max up). Therefore I named it BossFightManager. Since this function, and the door blocks it spawns, are the only ones in this file, I decided to call it bossfight. I think we should try to be liberal with naming files, once we know all the functions contained in them. Otherwise I think that should do it! Very cool to have the first boss fight in the game all figured out.
This commit is contained in:
parent
d7200b96a1
commit
93cadd8077
@ -81,9 +81,9 @@ segments:
|
||||
- [0x2085C, tilelayout, D_801A085C]
|
||||
- [0x20A5C, data]
|
||||
- [0x305A4, .rodata, 30958] # func_801B3C38
|
||||
- [0x305B8, rodata]
|
||||
- [0x305E8, .rodata, 33FCC] # EntityBossRoomBlock
|
||||
- [0x305FC, .rodata, 33FCC] # EntitySlogra
|
||||
- [0x305B8, .rodata, bossfight] # EntityBossFightManager
|
||||
- [0x305E8, .rodata, bossfight] # EntityBossRoomBlock
|
||||
- [0x305FC, .rodata, slogra] # EntitySlogra
|
||||
- [0x30618, .rodata, gaibon] # EntityGaibon .rodata, 33FCC
|
||||
- [0x3063C, .rodata, 36DE4] # func_801B7034
|
||||
- [0x3064C, rodata]
|
||||
@ -104,7 +104,8 @@ segments:
|
||||
- [0x30900, .rodata, 48ADC] # EntityStageNamePopup
|
||||
- [0x30934, rodata]
|
||||
- [0x30958, c]
|
||||
- [0x33FCC, c] # Slogra & Gaibon Boss
|
||||
- [0x33FCC, c, bossfight] # Slogra & Gaibon Boss
|
||||
- [0x34690, c, slogra]
|
||||
- [0x35778, c, gaibon]
|
||||
- [0x36DE4, c]
|
||||
- [0x394D4, c, random]
|
||||
|
@ -58,7 +58,7 @@ EntityCannonWall = 0x801B2978;
|
||||
EntityElevator2 = 0x801B2D08;
|
||||
EntityFloorSpikes = 0x801B3294;
|
||||
EntityTableWithGlobe = 0x801B3534;
|
||||
EntityCloseBossRoom = 0x801B3FCC;
|
||||
EntityBossFightManager = 0x801B3FCC;
|
||||
EntityBossRoomBlock = 0x801B4518;
|
||||
EntitySlogra = 0x801B4778;
|
||||
EntitySlograSpear = 0x801B54A8;
|
||||
@ -75,7 +75,6 @@ EntityDamageDisplay = 0x801BAA20;
|
||||
InitRoomEntities = 0x801BB920;
|
||||
UpdateRoomPosition = 0x801BBA98;
|
||||
CreateEntityFromCurrentEntity = 0x801BBB4C;
|
||||
CreateEntityFromEntity = 0x801BBBC0;
|
||||
EntityRedDoor = 0x801BBCB4;
|
||||
DestroyEntity = 0x801BC8EC;
|
||||
AnimateEntity = 0x801BCA1C;
|
||||
|
187
src/st/nz0/bossfight.c
Normal file
187
src/st/nz0/bossfight.c
Normal file
@ -0,0 +1,187 @@
|
||||
#include "nz0.h"
|
||||
|
||||
// This file holds functions to handle the Slogra and Gaibon fight.
|
||||
// Slogra and Gaibon themselves are in individual files.
|
||||
|
||||
void EntityBossFightManager(Entity* self) {
|
||||
Entity* newEnt;
|
||||
s32 i;
|
||||
s16* temp_s1;
|
||||
s32 xPos;
|
||||
s32 newEntY;
|
||||
bool bosses_defeated;
|
||||
|
||||
FntPrint("boss_flag %x\n", g_BossFlag);
|
||||
FntPrint("boss_step %x\n", self->step);
|
||||
switch (self->step) {
|
||||
case 0:
|
||||
bosses_defeated = g_api.TimeAttackController(
|
||||
TIMEATTACK_EVENT_SLOGRA_GAIBON_DEFEAT, TIMEATTACK_GET_RECORD);
|
||||
if (bosses_defeated) {
|
||||
DestroyEntity(self);
|
||||
return;
|
||||
}
|
||||
InitializeEntity(g_EInitGeneric);
|
||||
g_BossFlag = 0;
|
||||
newEnt = self + 1;
|
||||
temp_s1 = &D_80181014[0];
|
||||
for (i = 0; i < 12; i++, newEnt++, temp_s1 += 3) {
|
||||
CreateEntityFromCurrentEntity(E_BOSS_ROOM_BLOCK, newEnt);
|
||||
newEnt->params = temp_s1[2];
|
||||
newEnt->posX.i.hi = temp_s1[0] - g_Tilemap.scrollX.i.hi;
|
||||
newEnt->posY.i.hi = temp_s1[1] - g_Tilemap.scrollY.i.hi;
|
||||
}
|
||||
// This spawns Slogra and Gaibon! Note that they always spawn at slot
|
||||
// 80 and 88, which allows the SLOGRA and GAIBON macros (self[8]) to
|
||||
// work.
|
||||
newEnt = &g_Entities[80];
|
||||
CreateEntityFromCurrentEntity(E_SLOGRA, newEnt);
|
||||
newEnt->posX.i.hi = 0x280 - g_Tilemap.scrollX.i.hi;
|
||||
newEnt->posY.i.hi = 0x1A0 - g_Tilemap.scrollY.i.hi;
|
||||
newEnt = &g_Entities[88];
|
||||
CreateEntityFromCurrentEntity(E_GAIBON, newEnt);
|
||||
newEnt->posX.i.hi = 0x2A0 - g_Tilemap.scrollX.i.hi;
|
||||
newEnt->posY.i.hi = 0x160 - g_Tilemap.scrollY.i.hi;
|
||||
// fall through
|
||||
case 1: // Detect whether player is in the room. If so, close the door.
|
||||
xPos = PLAYER.posX.i.hi + g_Tilemap.scrollX.i.hi;
|
||||
if (24 < xPos && xPos < 968) {
|
||||
g_BossFlag |= BOSS_FLAG_DOORS_CLOSED;
|
||||
// Unknown sound
|
||||
g_api.PlaySfx(0x90);
|
||||
D_80097928 = 0;
|
||||
self->step++;
|
||||
}
|
||||
break;
|
||||
case 2: // Door is now closed. Wait for player to get far enough to start
|
||||
// the fight.
|
||||
xPos = PLAYER.posX.i.hi + g_Tilemap.scrollX.i.hi;
|
||||
if (0x220 < xPos && xPos < 0x340) {
|
||||
g_BossFlag |= BOSS_FLAG_FIGHT_BEGIN;
|
||||
}
|
||||
if (g_BossFlag & BOSS_FLAG_FIGHT_BEGIN) {
|
||||
g_api.TimeAttackController(
|
||||
TIMEATTACK_EVENT_SLOGRA_GAIBON_DEFEAT, TIMEATTACK_SET_VISITED);
|
||||
D_80097928 = 1;
|
||||
D_80097910 = 0x31D;
|
||||
self->step++;
|
||||
}
|
||||
break;
|
||||
case 3: // Fight is now active.
|
||||
if (g_api.func_80131F68() == false) {
|
||||
D_80097928 = 0;
|
||||
g_api.PlaySfx(D_80097910);
|
||||
self->step++;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 4:
|
||||
// Wait for the fight to be over.
|
||||
if ((g_BossFlag & BOSS_FLAG_GAIBON_DEAD) &&
|
||||
(g_BossFlag & BOSS_FLAG_SLOGRA_DEAD)) {
|
||||
g_api.TimeAttackController(
|
||||
TIMEATTACK_EVENT_SLOGRA_GAIBON_DEFEAT, TIMEATTACK_SET_RECORD);
|
||||
if (g_api.func_80131F68() != false) {
|
||||
g_api.PlaySfx(0x90);
|
||||
}
|
||||
D_80097910 = 0x32E;
|
||||
self->step++;
|
||||
}
|
||||
return;
|
||||
case 5: // Fight is now over.
|
||||
xPos = 0x80;
|
||||
newEntY = 0x180 - g_Tilemap.scrollY.i.hi;
|
||||
newEnt = AllocEntity(&g_Entities[160], &g_Entities[192]);
|
||||
if (newEnt == NULL) {
|
||||
return;
|
||||
}
|
||||
CreateEntityFromEntity(E_LIFE_UP_SPAWN, self, newEnt);
|
||||
newEnt->posX.i.hi = xPos;
|
||||
newEnt->posY.i.hi = newEntY;
|
||||
newEnt->params = 5;
|
||||
g_BossFlag |= BOSS_FLAG_DOORS_OPEN; // Reopen the door
|
||||
g_CastleFlags[132] = 1;
|
||||
D_80097928 = 1;
|
||||
D_80097910 = 0x32E;
|
||||
self->step++;
|
||||
return;
|
||||
case 6:
|
||||
if (g_api.func_80131F68() == false) {
|
||||
D_80097928 = 0;
|
||||
g_api.PlaySfx(D_80097910);
|
||||
self->step++;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0xFF: // Unreachable debug state
|
||||
FntPrint("charal %x\n", self->animCurFrame);
|
||||
if (g_pads[1].pressed & PAD_SQUARE) {
|
||||
if (self->params) {
|
||||
return;
|
||||
}
|
||||
self->animCurFrame++;
|
||||
self->params |= 1;
|
||||
} else {
|
||||
self->params = 0;
|
||||
}
|
||||
if (g_pads[1].pressed & PAD_CIRCLE) {
|
||||
if (!self->step_s) {
|
||||
self->animCurFrame--;
|
||||
self->step_s |= 1;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
self->step_s = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// blocks that move to close slogra/gaibon room
|
||||
void EntityBossRoomBlock(Entity* self) {
|
||||
switch (self->step) {
|
||||
case 0:
|
||||
InitializeEntity(D_80180D00);
|
||||
self->animCurFrame = 8;
|
||||
|
||||
case 1:
|
||||
if (g_BossFlag & 1) {
|
||||
self->ext.GS_Props.timer = 16;
|
||||
self->step++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (self->params == 0) {
|
||||
self->velocityX = FIX(1);
|
||||
} else {
|
||||
self->velocityX = FIX(-1);
|
||||
}
|
||||
MoveEntity();
|
||||
GetPlayerCollisionWith(self, 8, 8, 5);
|
||||
if (!(g_Timer & 3)) {
|
||||
g_api.PlaySfx(0x608);
|
||||
}
|
||||
if (--self->ext.GS_Props.timer) {
|
||||
break;
|
||||
}
|
||||
self->step++;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
GetPlayerCollisionWith(self, 8, 8, 5);
|
||||
if (g_BossFlag & BOSS_FLAG_DOORS_OPEN) {
|
||||
self->step++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
self->flags |= FLAG_DESTROY_IF_OUT_OF_CAMERA;
|
||||
if (self->params != 0) {
|
||||
self->velocityX = FIX(1);
|
||||
} else {
|
||||
self->velocityX = FIX(-1);
|
||||
}
|
||||
MoveEntity();
|
||||
break;
|
||||
}
|
||||
}
|
@ -78,8 +78,6 @@ void EntityGaibon(Entity* self) {
|
||||
s32 yVar;
|
||||
s32 xVar;
|
||||
|
||||
s32 stupid;
|
||||
|
||||
if ((self->step) && (!self->ext.GS_Props.nearDeath) &&
|
||||
self->hitPoints < g_api.enemyDefs[0xFE].hitPoints / 2) {
|
||||
self->ext.GS_Props.grabedAscending = 0;
|
||||
|
@ -29,11 +29,14 @@ typedef enum {
|
||||
/* 0x32 */ E_ROTATE_SPITTLEBONE,
|
||||
/* 0x33 */ E_SPITTLEBONE_SPIT,
|
||||
/* 0x38 */ E_FIRE = 0x38,
|
||||
/* 0x41 */ E_SLOGRA_SPEAR = 0x41,
|
||||
/* 0x42 */ E_SLOGRA_SPEAR_PROJECTILE = 0x42,
|
||||
/* 0x43 */ E_GAIBON = 0x43,
|
||||
/* 0x3F */ E_BOSS_ROOM_BLOCK = 0x3F,
|
||||
/* 0x40 */ E_SLOGRA,
|
||||
/* 0x41 */ E_SLOGRA_SPEAR,
|
||||
/* 0x42 */ E_SLOGRA_SPEAR_PROJECTILE,
|
||||
/* 0x43 */ E_GAIBON,
|
||||
/* 0x45 */ E_GAIBON_SMALL_FIREBALL = 0x45,
|
||||
/* 0x46 */ E_GAIBON_BIG_FIREBALL = 0x46,
|
||||
/* 0x46 */ E_GAIBON_BIG_FIREBALL,
|
||||
/* 0x49 */ E_LIFE_UP_SPAWN = 0x49
|
||||
} EntityIDs;
|
||||
|
||||
#define BOSS_FLAG_DOORS_CLOSED (1 << 0)
|
||||
@ -176,6 +179,7 @@ extern const u8 D_80180F74[];
|
||||
extern u8 D_80180F88[];
|
||||
extern u16 D_80180F9C[];
|
||||
extern Unkstruct_80180FE0 D_80180FE0[];
|
||||
extern s16 D_80181014[];
|
||||
extern u32 g_randomNext;
|
||||
extern s8 c_HeartPrizes[];
|
||||
extern Entity* g_CurrentEntity;
|
||||
|
@ -1,8 +1,3 @@
|
||||
/*
|
||||
* Overlay: NZ0
|
||||
* Enemy: Slogra & Gaibon Boss
|
||||
*/
|
||||
|
||||
#include "nz0.h"
|
||||
|
||||
#define GAIBON self[8]
|
||||
@ -50,61 +45,6 @@ typedef enum {
|
||||
SLOGRA_DYING_END,
|
||||
} SlograDyingSubSteps;
|
||||
|
||||
// DECOMP_ME_WIP EntityCloseBossRoom https://decomp.me/scratch/bqgN9 95.04 %
|
||||
// figuring out D_80181014 struct might help
|
||||
// trigger to stop music and close slogra/gaibon room
|
||||
INCLUDE_ASM("st/nz0/nonmatchings/33FCC", EntityCloseBossRoom);
|
||||
|
||||
// blocks that move to close slogra/gaibon room
|
||||
void EntityBossRoomBlock(Entity* self) {
|
||||
switch (self->step) {
|
||||
case 0:
|
||||
InitializeEntity(D_80180D00);
|
||||
self->animCurFrame = 8;
|
||||
|
||||
case 1:
|
||||
if (g_BossFlag & 1) {
|
||||
self->ext.GS_Props.timer = 16;
|
||||
self->step++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (self->params == 0) {
|
||||
self->velocityX = FIX(1);
|
||||
} else {
|
||||
self->velocityX = FIX(-1);
|
||||
}
|
||||
MoveEntity();
|
||||
GetPlayerCollisionWith(self, 8, 8, 5);
|
||||
if (!(g_Timer & 3)) {
|
||||
g_api.PlaySfx(0x608);
|
||||
}
|
||||
if (--self->ext.GS_Props.timer) {
|
||||
break;
|
||||
}
|
||||
self->step++;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
GetPlayerCollisionWith(self, 8, 8, 5);
|
||||
if (g_BossFlag & BOSS_FLAG_DOORS_OPEN) {
|
||||
self->step++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
self->flags |= FLAG_DESTROY_IF_OUT_OF_CAMERA;
|
||||
if (self->params != 0) {
|
||||
self->velocityX = FIX(1);
|
||||
} else {
|
||||
self->velocityX = FIX(-1);
|
||||
}
|
||||
MoveEntity();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s32 EntitySlograSpecialCollision(u16* unused) {
|
||||
/**
|
||||
* This function keeps Slogra between safe
|
Loading…
Reference in New Issue
Block a user