Decompile NP3 EntityOwl (#1330)

Another big one! This required mangling the files a little bit; once the
other functions are decompiled the files should come back together
nicely. The function itself is in 4B018.c, and the function is currently
alone in that file.
This commit is contained in:
bismurphy 2024-06-16 02:32:20 -04:00 committed by GitHub
parent c4e2edfe6e
commit d3bcca25ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 887 additions and 437 deletions

View File

@ -122,8 +122,10 @@ segments:
- [0x3208C, .rodata, 4997C]
- [0x320A0, .rodata, 49BC8]
- [0x320B4, .rodata, 49F98] # EntityBloodyZombie data
- [0x320DC, rodata]
- [0x321EC, .rodata, 4B018]
- [0x320DC, rodata] # Shared charal string for owl and owl knight
- [0x320EC, .rodata, 4B018] # EntityOwl
- [0x3214C, rodata]
- [0x321EC, .rodata, 4BF18]
- [0x3224C, .rodata, 4E69C] #EntityHammer
- [0x322CC, .rodata, 4E69C] # EntityGurkhaBodyParts
- [0x322F8, .rodata, 4F5B8] # EntityGurkha
@ -152,6 +154,7 @@ segments:
- [0x49BC8, c]
- [0x49F98, c] # EntityBloodyZombie
- [0x4B018, c]
- [0x4BF18, c]
- [0x4E69C, c]
- [0x4F5B8, c]
- [0x51F38, c, prim_helpers]

View File

@ -77,7 +77,6 @@ GetDistanceToPlayerY = 0x801BC810;
GetSideToPlayer = 0x801BC844;
MoveEntity = 0x801BC888;
AllocEntity = 0x801BCD44;
AdjustValueWithinThreshold = 0x801BCF20;
SetStep = 0x801BD114;
SetSubStep = 0x801BD134;
InitializeEntity = 0x801BD1E4;

View File

@ -1067,6 +1067,15 @@ typedef struct {
u16 unk8A;
} ET_801B0AA4;
typedef struct {
byte pad[4];
u16 unk80;
u16 unk82;
s16 unk84;
s16 unk86;
s16 unk88;
} ET_Owl;
typedef union { // offset=0x7C
struct Primitive* prim;
char stub[0x40];
@ -1167,4 +1176,5 @@ typedef union { // offset=0x7C
ET_LifeUpSpawn lifeUpSpawn;
ET_AxeKnight axeknight;
ET_801B0AA4 et_801B0AA4;
ET_Owl owl;
} Ext;

View File

@ -1,455 +1,415 @@
#include "np3.h"
INCLUDE_ASM("st/np3/nonmatchings/4B018", EntityOwl);
// Owl's Owl Knight shows up one slot above it, so define this for
// ease of readability.
#define KNIGHT (self + 1)
// an unknown helper entity is also spawned.
#define HELPER (self + 3)
void EntityOwl(Entity* self) {
Collider collider;
Entity* otherEnt;
s16 xVar;
s16 yVar;
s16 angle;
INCLUDE_ASM("st/np3/nonmatchings/4B018", func_801CBF18);
INCLUDE_ASM("st/np3/nonmatchings/4B018", EntityOwlKnight);
void func_801CD540(Entity* self) {
s8* hitbox;
s32 diff;
if (self->step == 0) {
InitializeEntity(D_80180B20);
if (1 < self->step && self->step < 9 && !(g_Timer & 0xF)) {
func_801C2598(0x68C);
}
self->facingLeft = self[-1].facingLeft;
self->posX.i.hi = self[-1].posX.i.hi;
self->posY.i.hi = self[-1].posY.i.hi;
hitbox = D_80182914;
diff = D_80182935[self[-1].animCurFrame];
diff -= 4;
if (diff < 0) {
diff = 0;
}
hitbox += diff * 4;
self->hitboxOffX = *hitbox++;
self->hitboxOffY = *hitbox++;
self->hitboxWidth = hitbox[0];
self->hitboxHeight = hitbox[1];
if (self[-1].entityId != 0x44) {
DestroyEntity(self);
}
}
void func_801CD620(Entity* self) {
if (self->step == 0) {
InitializeEntity(g_EInitGeneric);
}
}
void func_801CD658(void) {
g_CurrentBuffer = g_CurrentBuffer->next;
FntPrint("a:%x\n", D_801D3378);
FntPrint("b:%x\n", D_801D337C);
FntPrint("c:%x\n", D_801D3380);
FntPrint("d:%x\n", D_801D3384);
FntPrint("e:%x\n", D_801D3388);
DrawSync(0);
VSync(0);
PutDrawEnv(&g_CurrentBuffer->draw);
PutDispEnv(&g_CurrentBuffer->disp);
FntFlush(-1);
}
void func_801CD734() {
while (PadRead(0))
func_801CD658();
while (!PadRead(0))
func_801CD658();
}
void func_801CD78C(Point32* src, s32 speed, s16 angle, Point32* dst) {
if (g_CurrentEntity->facingLeft) {
angle = -angle;
}
*dst = *src;
dst->x -= speed * rsin(angle) * 16;
dst->y += speed * rcos(angle) * 16;
}
void func_801CD83C(Entity* self) {
s16 angle = self->ext.GH_Props.rotZ;
Entity* src;
if (g_CurrentEntity->facingLeft != 0) {
angle = -angle;
}
src = self->ext.GH_Props.parent;
self->posX.val = src->posX.val;
self->posY.val = src->posY.val;
self->posX.val -= self->ext.GH_Props.unk9E * rsin(angle) * 16;
self->posY.val += self->ext.GH_Props.unk9E * rcos(angle) * 16;
if (self->ext.GH_Props.unkA8 != 0) {
FntPrint("CAUTION!! WARNING_A AT %x\n", self->animCurFrame);
}
self->ext.GH_Props.unkA8 |= 1;
}
void func_801CD91C(Entity* self) {
s16 angle = self->ext.GH_Props.rotZ;
Entity* src;
if (g_CurrentEntity->facingLeft != 0) {
angle = -angle;
}
src = self->ext.GH_Props.parent;
src->posX.val = self->posX.val;
src->posY.val = self->posY.val;
src->posX.val -= -self->ext.GH_Props.unk9E * rsin(angle) * 16;
src->posY.val =
-self->ext.GH_Props.unk9E * rcos(angle) * 16 + src->posY.val;
if (self->ext.GH_Props.unkA8 != 0) {
FntPrint("CAUTION!! WARNING_B AT %x\n", self->animCurFrame);
}
self->ext.GH_Props.unkA8 |= 1;
}
void func_801CDA14(Entity* ent1, Entity* ent2) {
Entity* temp_a0;
temp_a0 = ent1->ext.GH_Props.parent;
func_801CD78C(
temp_a0, temp_a0->ext.GH_Props.unk9E, temp_a0->ext.GH_Props.rotZ, ent1);
func_801CD78C(
ent1, ent2->ext.GH_Props.unk9E, ent2->ext.GH_Props.rotZ, ent2);
}
void func_801CDA6C(Entity* self, s32 arg1) {
Entity* temp_s0;
temp_s0 = self->ext.GH_Props.parent;
func_801CD78C(
self, -self->ext.GH_Props.unk9E, self->ext.GH_Props.rotZ, temp_s0);
func_801CD78C(temp_s0, -temp_s0->ext.GH_Props.unk9E,
temp_s0->ext.GH_Props.rotZ, arg1);
}
void func_801CDAC8(Entity* ent1, Entity* ent2) {
Point32 sp10;
s32 ratanX;
s32 ratanY;
s32 temp_s2;
s32 temp_s3;
s32 temp_s4;
Point32* parentPos;
s16 temp_s6;
parentPos = (Point32*)ent1->ext.GH_Props.parent;
ratanX = ent2->posX.val - parentPos->x;
if (g_CurrentEntity->facingLeft) {
ratanX = -ratanX;
}
ratanY = ent2->posY.val - parentPos->y;
temp_s6 = ratan2(-ratanX, ratanY);
temp_s4 = ent1->ext.GH_Props.unk9E << 8;
temp_s3 = ent2->ext.GH_Props.unk9E << 8;
ratanX >>= 8;
ratanY >>= 8;
temp_s2 = SquareRoot0((ratanX * ratanX) + (ratanY * ratanY));
if (((temp_s4 + temp_s3) << 8) < temp_s2) {
temp_s2 = ((temp_s4 + temp_s3) << 8);
}
temp_s2 = (temp_s2 * temp_s4) / (temp_s4 + temp_s3);
temp_s3 = (temp_s4 * temp_s4) - (temp_s2 * temp_s2);
temp_s3 = SquareRoot0(temp_s3);
temp_s6 += ratan2(temp_s3, temp_s2);
ent1->ext.GH_Props.unkA4 = temp_s6;
func_801CD78C(parentPos, ent1->ext.GH_Props.unk9E, temp_s6, &sp10);
ratanX = ent2->posX.val - sp10.x;
if (g_CurrentEntity->facingLeft) {
ratanX = -ratanX;
}
ratanY = ent2->posY.val - sp10.y;
ent2->ext.GH_Props.unkA4 = ratan2(-ratanX, ratanY);
}
bool func_801CDC80(s16* arg0, s16 arg1, s16 arg2) {
if (abs(*arg0 - arg1) < arg2) {
*arg0 = arg1;
return true;
}
if (arg1 < *arg0) {
*arg0 = *arg0 - arg2;
}
if (*arg0 < arg1) {
*arg0 = arg2 + *arg0;
}
return false;
}
void func_801CDD00(Entity* entity, s16 arg1, s16 arg2) {
s16 temp_t0 = arg1 - entity->ext.GH_Props.rotZ;
if (temp_t0 > 0x800) {
temp_t0 -= 0x1000;
}
if (temp_t0 < -0x800) {
temp_t0 += 0x1000;
}
do {
entity->ext.GH_Props.unkA4 = arg1;
entity->ext.GH_Props.unkA6 = temp_t0 / arg2;
} while (0);
}
void func_801CDD80(s16* arg0, Entity* arg1) {
s16* posY = arg1->posY.val;
while (*arg0 != 0) {
if (*arg0 != 0xFF) {
func_801CDD00(&g_CurrentEntity[*arg0], *posY, arg1->posX.val);
if (self->ext.owl.unk80 & 0x20) {
if (!(self->flags & FLAG_DEAD)) {
SetStep(8);
self->ext.owl.unk80 ^= 0x20;
}
arg0++;
posY++;
}
}
void func_801CDE10(s16* arg0) {
Entity* temp_a0;
while (*arg0 != 0) {
if (*arg0 != 0xFF) {
temp_a0 = &g_CurrentEntity[*arg0];
temp_a0->ext.GH_Props.rotZ =
temp_a0->ext.GH_Props.rotZ + temp_a0->ext.generic.unkA6;
if (self->flags & FLAG_DEAD) {
if (self->step < 9) {
self->hitboxState = 0;
self->animCurFrame = 12;
self->velocityX = 0;
self->velocityY = 0;
func_801C2598(0x796);
SetStep(9);
KNIGHT->ext.owl.unk80 |= 8;
}
arg0++;
}
}
void func_801CDE88(s16* arg0) {
Entity* temp_a0;
while (*arg0 != 0) {
if (*arg0 != 0xFF) {
temp_a0 = &g_CurrentEntity[*arg0];
temp_a0->ext.GH_Props.rotZ =
temp_a0->ext.GH_Props.rotZ + temp_a0->ext.generic.unkA6;
func_801CD83C(temp_a0);
}
arg0++;
}
}
void func_801CDF1C(s16 entIndices[], s16 arg1[][4], s32 arg2) {
arg1 += (u16)g_CurrentEntity->ext.GH_Props.unkB0[arg2];
if (g_CurrentEntity->ext.GH_Props.unkB0[arg2 + 2] == 0) {
func_801CDD80(entIndices, arg1);
*(arg2 + 2 + g_CurrentEntity->ext.GH_Props.unkB0) = arg1[0][0];
}
// I don't know why the reverse array indexing is needed, but it is. Darn.
if (!(--((arg2 + 2)[g_CurrentEntity->ext.GH_Props.unkB0]))) {
if (arg1[1][0] == 0) {
g_CurrentEntity->ext.GH_Props.unkB0[arg2] = 0;
switch (self->step) {
case 0:
InitializeEntity(&D_80180B2C);
// Turns out the knight is spawned from the owl. Neat!
CreateEntityFromEntity(E_OWL_KNIGHT, self, KNIGHT);
CreateEntityFromEntity(E_801CD620, self, self + 3);
break;
case 1:
AnimateEntity(D_801826EC, self);
otherEnt = KNIGHT;
self->posX.i.hi = KNIGHT->posX.i.hi;
if (self->facingLeft) {
self->posX.i.hi -= 10;
} else {
++g_CurrentEntity->ext.GH_Props.unkB0[arg2];
self->posX.i.hi += 10;
}
}
}
void func_801CDFD8(Entity* self, s32 arg1) {
if (self->ext.et_801CDFD8.unkB4 == 0) {
func_801CDD00(self, self->ext.et_801CDFD8.unkA4, arg1);
self->ext.et_801CDFD8.unkB4 = arg1;
}
self->ext.et_801CDFD8.unkB4--;
self->ext.et_801CDFD8.unk9C += self->ext.et_801CDFD8.unkA6;
func_801CD83C(self);
}
void func_801CE04C(Entity* entity, Collider* collider) {
s16 var_s0 = 0;
g_api.CheckCollision(
entity->posX.i.hi, (s16)(entity->posY.i.hi + collider->unk18), collider,
0);
if (collider->effects & 1) {
var_s0 = 1;
if (collider->effects & 0x8000) {
if (collider->effects & 0x4000) {
if (g_CurrentEntity->facingLeft != 0) {
var_s0 = 4;
} else {
var_s0 = 2;
}
if (otherEnt->animCurFrame == 0x10) {
self->posY.i.hi = otherEnt->posY.i.hi - 0x21;
} else {
self->posY.i.hi = otherEnt->posY.i.hi - 0x20;
}
if (otherEnt->unk44) {
SetStep(2);
}
if (self->ext.owl.unk80 & 1) {
self->ext.owl.unk80 ^= 1;
SetStep(3);
}
break;
case 2:
if (AnimateEntity(D_801826F8, self) == 0) {
SetStep(1);
break;
}
break;
case 3:
if (AnimateEntity(D_80182720, self) == 0) {
KNIGHT->ext.owl.unk80 |= 2;
SetStep(4);
}
MoveEntity();
if (self->animFrameIdx == 6) {
self->velocityY -= FIX(12.0 / 128);
}
if (self->animFrameIdx >= 7) {
self->velocityY += FIX(8.0 / 128);
}
break;
case 4:
MoveEntity();
self->facingLeft = (GetSideToPlayer() & 1) ^ 1;
AnimateEntity(D_80182734, self);
xVar = KNIGHT->posX.i.hi - self->posX.i.hi;
yVar = (KNIGHT->posY.i.hi - self->posY.i.hi);
if (KNIGHT->facingLeft) {
xVar -= 0x20;
} else {
xVar += 0x20;
}
yVar -= 0x40;
switch (self->step_s) {
case 0:
xVar = self->velocityX / 16;
yVar = self->velocityY / 16;
self->ext.owl.unk84 = func_801BCE58(xVar, yVar);
self->step_s++;
break;
case 1:
HELPER->posX.i.hi = (xVar + self->posX.i.hi);
HELPER->posY.i.hi = (yVar + self->posY.i.hi);
// Might be able to change types on these two functions to
// remove the s16 cast.
self->ext.owl.unk84 = AdjustValueWithinThreshold(
6, self->ext.owl.unk84, (s16)func_801BCE90(self, self + 3));
func_801BCDEC(self->ext.owl.unk84, 0x20);
if (self->velocityX > 0) {
self->facingLeft = 1;
} else {
if (g_CurrentEntity->facingLeft != 0) {
var_s0 = 2;
} else {
var_s0 = 4;
}
self->facingLeft = 0;
}
xVar = abs(xVar);
yVar = abs(yVar);
if ((xVar < 0x10) && (yVar < 0x10)) {
self->ext.owl.unk88 = 0x20;
self->step_s++;
}
break;
case 2:
xVar = abs(xVar);
yVar = abs(yVar);
func_801BCDEC(self->ext.owl.unk84, self->ext.owl.unk88);
self->ext.owl.unk88--;
if (self->ext.owl.unk88 < 0) {
self->ext.owl.unk88 = 0;
}
if ((xVar >= 0x29) || (yVar >= 0x29)) {
self->step_s--;
}
break;
}
if (self->ext.owl.unk80 & 8) {
SetStep(6);
}
if (self->ext.owl.unk80 & 2) {
SetStep(5);
self->ext.owl.unk80 ^= 2;
}
if (self->ext.owl.unk80 & 4) {
SetStep(7);
self->ext.owl.unk80 ^= 4;
}
break;
case 5:
AnimateEntity(D_8018274C, self);
MoveEntity();
switch (self->step_s) {
case 0:
self->facingLeft = (GetSideToPlayer() & 1) ^ 1;
xVar = PLAYER.posX.i.hi - self->posX.i.hi;
yVar = PLAYER.posY.i.hi - self->posY.i.hi;
yVar -= 0x10;
angle = ratan2(-yVar, xVar);
self->velocityX = rcos(angle) * 0x30;
self->velocityY = -rsin(angle) * 0x30;
self->ext.owl.unk82 = 0x60;
func_801C2598(0x60C);
self->step_s++;
break;
case 1:
if (self->ext.owl.unk82 < 0x30) {
self->velocityY -= FIX(0.09375);
}
if (!--self->ext.owl.unk82) {
self->step_s++;
}
break;
case 2:
if (self->ext.owl.unk80 & 8) {
SetStep(6);
} else {
KNIGHT->ext.owl.unk80 |= 2;
SetStep(4);
}
}
}
entity->ext.generic.unk88.S16.unk0 = var_s0;
}
s32 func_801CE120(Entity* self, s32 facing) {
Collider collider;
s32 x = self->posX.i.hi;
s32 y = self->posY.i.hi + 9;
s32 ret = 0;
if (facing != 0) {
x += 64;
} else {
x -= 64;
}
g_api.CheckCollision(x, y - 6, &collider, 0);
if (collider.effects & 1) {
ret |= 2;
}
g_api.CheckCollision(x, y + 6, &collider, 0);
if (!(collider.effects & 1)) {
ret |= 4;
}
return ret;
}
void func_801CE1E8(s16 step) {
s32 i;
g_CurrentEntity->step = step;
g_CurrentEntity->step_s = 0;
g_CurrentEntity->animFrameIdx = 0;
g_CurrentEntity->animFrameDuration = 0;
for (i = 0; i < 4; i++) {
g_CurrentEntity->ext.GH_Props.unkB0[i] = 0;
g_CurrentEntity->ext.GH_Props.unkB0[i + 2] = 0;
}
}
void func_801CE228(s16 step) {
s32 i;
for (i = 0; i < 4; i++) {
g_CurrentEntity->ext.GH_Props.unkB0[i] = 0;
g_CurrentEntity->ext.GH_Props.unkB0[i + 2] = 0;
}
}
void func_801CE258(s16* arg0) {
Entity* entity;
while (*arg0 != 0) {
entity = &g_CurrentEntity[*arg0];
if (entity->ext.GH_Props.unkA8 == 0) {
func_801CD83C(entity);
break;
case 7:
switch (self->step_s) {
case 0:
if (AnimateEntity(D_80182734, self) == 0) {
self->facingLeft = (GetSideToPlayer() & 1) ^ 1;
}
MoveEntity();
self->velocityY = FIX(-1.5);
if (self->facingLeft) {
self->velocityX = FIX(16.0 / 128);
} else {
self->velocityX = FIX(-16.0 / 128);
}
if (self->posY.i.hi < 0x30) {
func_801C2598(0x60C);
self->step_s++;
}
break;
case 1:
self->facingLeft = (GetSideToPlayer() & 1) ^ 1;
xVar = PLAYER.posX.i.hi - self->posX.i.hi;
yVar = PLAYER.posY.i.hi - self->posY.i.hi;
angle = ratan2(-yVar, xVar);
self->velocityX = rcos(angle) << 6;
self->velocityY = -rsin(angle) * 0x40;
self->animCurFrame = 4;
self->animFrameIdx = 0;
self->animFrameDuration = 0;
func_801C2598(0x60C);
self->step_s++;
break;
case 2:
MoveEntity();
if (self->posY.i.hi > 0x90) {
self->step_s++;
}
break;
case 3:
AnimateEntity(D_80182740, self);
MoveEntity();
self->velocityY -= FIX(28.0 / 128);
if (self->velocityY < FIX(-2)) {
self->animFrameIdx = 0;
self->animFrameDuration = 0;
self->step_s++;
}
break;
case 4:
AnimateEntity(D_80182734, self);
MoveEntity();
if (self->posY.i.hi < 0x60) {
if (self->ext.owl.unk80 & 8) {
SetStep(6);
} else {
KNIGHT->ext.owl.unk80 |= 2;
SetStep(4);
}
if (self->ext.owl.unk80 & 0x40) {
SetStep(7);
}
}
break;
}
arg0++;
}
}
void func_801CE2CC(s16* arg0) {
s16* var_s0;
func_801CD91C(&g_CurrentEntity[arg0[1]]);
func_801CD91C(&g_CurrentEntity[arg0[0]]);
func_801CD83C(&g_CurrentEntity[arg0[2]]);
func_801CD83C(&g_CurrentEntity[arg0[3]]);
for (arg0 += 4; *arg0 != 0; arg0++) {
if (*arg0 != 0xFF) {
func_801CD83C(&g_CurrentEntity[*arg0]);
break;
case 6:
switch (self->step_s) {
case 0:
yVar = KNIGHT->posY.i.hi - self->posY.i.hi - 0x40;
xVar = KNIGHT->posX.i.hi - self->posX.i.hi;
angle = ratan2(-yVar, xVar);
self->velocityX = rcos(angle) * 0x28;
self->velocityY = -rsin(angle) * 0x28;
if (self->velocityX > 0) {
self->facingLeft = 1;
} else {
self->facingLeft = 0;
}
self->step_s++;
break;
case 1:
AnimateEntity(D_8018274C, self);
MoveEntity();
xVar = KNIGHT->posX.i.hi - self->posX.i.hi;
if (abs(xVar) < 8) {
self->ext.owl.unk84 = 0x400;
self->step_s++;
}
break;
case 2:
AnimateEntity(D_80182734, self);
MoveEntity();
if (KNIGHT->facingLeft) {
HELPER->posX.i.hi = KNIGHT->posX.i.hi - 10;
} else {
HELPER->posX.i.hi = KNIGHT->posX.i.hi + 10;
}
HELPER->posY.i.hi = (KNIGHT->posY.i.hi - 0x20);
// probably not an angle here but reusing variable.
angle = AdjustValueWithinThreshold(
4, self->ext.owl.unk84, (s16)func_801BCE90(self, self + 3));
self->ext.owl.unk84 = angle;
func_801BCDEC(angle, 0x10);
xVar = HELPER->posX.i.hi - self->posX.i.hi;
yVar = HELPER->posY.i.hi - self->posY.i.hi;
if (xVar > 0) {
self->facingLeft = 1;
} else {
self->facingLeft = 0;
}
xVar = abs(xVar);
yVar = abs(yVar);
if ((xVar < 6) && (yVar < 6)) {
SetStep(1);
self->velocityX = 0;
self->velocityY = 0;
self->ext.owl.unk80 = 0;
KNIGHT->ext.owl.unk80 = 1;
self->facingLeft = KNIGHT->facingLeft;
}
break;
}
}
}
void func_801CE3FC(s16* arg0) {
s16* var_s0;
s16 var_v0;
s32 i;
for (i = 0, var_s0 = arg0; i < 4; i++) {
func_801CD83C(&g_CurrentEntity[*var_s0]);
var_s0++;
}
for (arg0 += 4; *arg0 != 0; arg0++) {
if (*arg0 != 0xFF) {
func_801CD83C(&g_CurrentEntity[*arg0]);
break;
case 8:
switch (self->step_s) {
case 0:
yVar = KNIGHT->posY.i.hi - self->posY.i.hi;
xVar = KNIGHT->posX.i.hi - self->posX.i.hi;
if (KNIGHT->facingLeft) {
xVar += 0x20;
} else {
xVar -= 0x20;
}
yVar += 26;
angle = ratan2(-yVar, xVar);
self->velocityX = rcos(angle) * 0x30;
self->velocityY = -rsin(angle) * 0x30;
if (self->velocityX > 0) {
self->facingLeft = 1;
} else {
self->facingLeft = 0;
}
func_801C2598(0x60C);
self->step_s++;
break;
case 1:
MoveEntity();
AnimateEntity(D_80182734, self);
yVar = KNIGHT->posY.i.hi - self->posY.i.hi;
if (yVar < 0x41) {
xVar = self->posX.i.hi;
yVar = self->posY.i.hi + 0x10;
g_api.CheckCollision(xVar, yVar, &collider, 0);
if (collider.effects & 1) {
self->posY.i.hi = self->posY.i.hi + collider.unk18;
self->step_s++;
if (KNIGHT->posX.i.hi > self->posX.i.hi) {
self->facingLeft = 1;
} else {
self->facingLeft = 0;
}
}
}
break;
case 2:
AnimateEntity(D_80182710, self);
if ((g_Timer & 7) == 7) {
func_801C2598(0x66D);
}
if (self->ext.owl.unk80 & 0x40) {
SetStep(7);
break;
}
}
}
}
s32 func_801CE4CC(Entity* self) {
Entity* entity;
s32 step;
s32 x;
if (g_CurrentEntity->ext.et_801CE4CC.unk8E != 0) {
g_CurrentEntity->ext.et_801CE4CC.unk8E--;
}
x = self->posX.i.hi - PLAYER.posX.i.hi;
if (g_CurrentEntity->facingLeft != 0) {
x = -x;
}
if (x < -16) {
func_801CE1E8(10);
return;
}
if (g_CurrentEntity->ext.et_801CE4CC.unk84 == 1) {
entity = g_CurrentEntity + 10;
} else {
entity = g_CurrentEntity + 13;
}
if (func_801CE120(entity, g_CurrentEntity->facingLeft) != 0) {
func_801CE1E8(7);
return;
}
if (func_801CE120(entity, g_CurrentEntity->facingLeft ^ 1) != 0) {
func_801CE1E8(5);
return;
}
if (g_CurrentEntity->step == 8) {
if (x < 80) {
step = 5;
break;
case 9:
switch (self->step_s) {
case 0:
if (func_801BC8E4(D_801826CC) & 1) {
func_801C2598(0x647);
self->animCurFrame = 0xD;
if (self->posX.i.hi > KNIGHT->posX.i.hi) {
self->facingLeft = 1;
} else {
self->facingLeft = 0;
}
self->step_s++;
break;
}
self->velocityY -= FIX(0.125);
break;
case 1:
if (self->ext.generic.unk80.modeS32 & 0x50) {
self->ext.owl.unk82 = 0x80;
self->step++;
}
break;
}
break;
case 10:
if (!(--self->ext.owl.unk82) || (KNIGHT->entityId == 0)) {
func_801C2598(0x683);
otherEnt = AllocEntity(&g_Entities[224], &g_Entities[256]);
if (otherEnt != NULL) {
CreateEntityFromEntity(E_EXPLOSION, self, otherEnt);
otherEnt->params = 2;
}
self->animCurFrame = 0;
self->step = 24;
KNIGHT->ext.owl.unk80 |= 0x10;
DestroyEntity(self);
}
break;
case 16:
FntPrint(&D_801B20DC, self->animCurFrame);
if (g_pads[1].pressed & PAD_SQUARE) {
if (self->params != 0) {
break;
}
self->animCurFrame = self->animCurFrame + 1;
self->params |= 1;
} else {
step = 8;
self->params = 0;
}
} else {
if (x < 80) {
step = 7;
if (g_pads[1].pressed & PAD_CIRCLE) {
if (self->step_s == 0) {
self->animCurFrame = self->animCurFrame - 1;
self->step_s |= 1;
}
} else {
step = 5;
}
if (x > 160) {
step = 8;
}
}
if ((g_CurrentEntity->ext.et_801CE4CC.unk8E == 0) && (x < 96)) {
g_CurrentEntity->ext.et_801CE4CC.unk8E = 3;
step = 6;
}
if (step != g_CurrentEntity->step) {
func_801CE1E8(step);
}
if (g_CurrentEntity->step == 7) {
if (step == 5) {
g_CurrentEntity->ext.et_801CE4CC.unkB0 = 1;
self->step_s = 0;
}
break;
}
}
const s32 rodata_pad_32148 = 0;

453
src/st/np3/4BF18.c Normal file
View File

@ -0,0 +1,453 @@
#include "np3.h"
INCLUDE_ASM("st/np3/nonmatchings/4BF18", func_801CBF18);
INCLUDE_ASM("st/np3/nonmatchings/4BF18", EntityOwlKnight);
void func_801CD540(Entity* self) {
s8* hitbox;
s32 diff;
if (self->step == 0) {
InitializeEntity(D_80180B20);
}
self->facingLeft = self[-1].facingLeft;
self->posX.i.hi = self[-1].posX.i.hi;
self->posY.i.hi = self[-1].posY.i.hi;
hitbox = D_80182914;
diff = D_80182935[self[-1].animCurFrame];
diff -= 4;
if (diff < 0) {
diff = 0;
}
hitbox += diff * 4;
self->hitboxOffX = *hitbox++;
self->hitboxOffY = *hitbox++;
self->hitboxWidth = hitbox[0];
self->hitboxHeight = hitbox[1];
if (self[-1].entityId != 0x44) {
DestroyEntity(self);
}
}
void func_801CD620(Entity* self) {
if (self->step == 0) {
InitializeEntity(g_EInitGeneric);
}
}
void func_801CD658(void) {
g_CurrentBuffer = g_CurrentBuffer->next;
FntPrint("a:%x\n", D_801D3378);
FntPrint("b:%x\n", D_801D337C);
FntPrint("c:%x\n", D_801D3380);
FntPrint("d:%x\n", D_801D3384);
FntPrint("e:%x\n", D_801D3388);
DrawSync(0);
VSync(0);
PutDrawEnv(&g_CurrentBuffer->draw);
PutDispEnv(&g_CurrentBuffer->disp);
FntFlush(-1);
}
void func_801CD734() {
while (PadRead(0))
func_801CD658();
while (!PadRead(0))
func_801CD658();
}
void func_801CD78C(Point32* src, s32 speed, s16 angle, Point32* dst) {
if (g_CurrentEntity->facingLeft) {
angle = -angle;
}
*dst = *src;
dst->x -= speed * rsin(angle) * 16;
dst->y += speed * rcos(angle) * 16;
}
void func_801CD83C(Entity* self) {
s16 angle = self->ext.GH_Props.rotZ;
Entity* src;
if (g_CurrentEntity->facingLeft != 0) {
angle = -angle;
}
src = self->ext.GH_Props.parent;
self->posX.val = src->posX.val;
self->posY.val = src->posY.val;
self->posX.val -= self->ext.GH_Props.unk9E * rsin(angle) * 16;
self->posY.val += self->ext.GH_Props.unk9E * rcos(angle) * 16;
if (self->ext.GH_Props.unkA8 != 0) {
FntPrint("CAUTION!! WARNING_A AT %x\n", self->animCurFrame);
}
self->ext.GH_Props.unkA8 |= 1;
}
void func_801CD91C(Entity* self) {
s16 angle = self->ext.GH_Props.rotZ;
Entity* src;
if (g_CurrentEntity->facingLeft != 0) {
angle = -angle;
}
src = self->ext.GH_Props.parent;
src->posX.val = self->posX.val;
src->posY.val = self->posY.val;
src->posX.val -= -self->ext.GH_Props.unk9E * rsin(angle) * 16;
src->posY.val =
-self->ext.GH_Props.unk9E * rcos(angle) * 16 + src->posY.val;
if (self->ext.GH_Props.unkA8 != 0) {
FntPrint("CAUTION!! WARNING_B AT %x\n", self->animCurFrame);
}
self->ext.GH_Props.unkA8 |= 1;
}
void func_801CDA14(Entity* ent1, Entity* ent2) {
Entity* temp_a0;
temp_a0 = ent1->ext.GH_Props.parent;
func_801CD78C(
temp_a0, temp_a0->ext.GH_Props.unk9E, temp_a0->ext.GH_Props.rotZ, ent1);
func_801CD78C(
ent1, ent2->ext.GH_Props.unk9E, ent2->ext.GH_Props.rotZ, ent2);
}
void func_801CDA6C(Entity* self, s32 arg1) {
Entity* temp_s0;
temp_s0 = self->ext.GH_Props.parent;
func_801CD78C(
self, -self->ext.GH_Props.unk9E, self->ext.GH_Props.rotZ, temp_s0);
func_801CD78C(temp_s0, -temp_s0->ext.GH_Props.unk9E,
temp_s0->ext.GH_Props.rotZ, arg1);
}
void func_801CDAC8(Entity* ent1, Entity* ent2) {
Point32 sp10;
s32 ratanX;
s32 ratanY;
s32 temp_s2;
s32 temp_s3;
s32 temp_s4;
Point32* parentPos;
s16 temp_s6;
parentPos = (Point32*)ent1->ext.GH_Props.parent;
ratanX = ent2->posX.val - parentPos->x;
if (g_CurrentEntity->facingLeft) {
ratanX = -ratanX;
}
ratanY = ent2->posY.val - parentPos->y;
temp_s6 = ratan2(-ratanX, ratanY);
temp_s4 = ent1->ext.GH_Props.unk9E << 8;
temp_s3 = ent2->ext.GH_Props.unk9E << 8;
ratanX >>= 8;
ratanY >>= 8;
temp_s2 = SquareRoot0((ratanX * ratanX) + (ratanY * ratanY));
if (((temp_s4 + temp_s3) << 8) < temp_s2) {
temp_s2 = ((temp_s4 + temp_s3) << 8);
}
temp_s2 = (temp_s2 * temp_s4) / (temp_s4 + temp_s3);
temp_s3 = (temp_s4 * temp_s4) - (temp_s2 * temp_s2);
temp_s3 = SquareRoot0(temp_s3);
temp_s6 += ratan2(temp_s3, temp_s2);
ent1->ext.GH_Props.unkA4 = temp_s6;
func_801CD78C(parentPos, ent1->ext.GH_Props.unk9E, temp_s6, &sp10);
ratanX = ent2->posX.val - sp10.x;
if (g_CurrentEntity->facingLeft) {
ratanX = -ratanX;
}
ratanY = ent2->posY.val - sp10.y;
ent2->ext.GH_Props.unkA4 = ratan2(-ratanX, ratanY);
}
bool func_801CDC80(s16* arg0, s16 arg1, s16 arg2) {
if (abs(*arg0 - arg1) < arg2) {
*arg0 = arg1;
return true;
}
if (arg1 < *arg0) {
*arg0 = *arg0 - arg2;
}
if (*arg0 < arg1) {
*arg0 = arg2 + *arg0;
}
return false;
}
void func_801CDD00(Entity* entity, s16 arg1, s16 arg2) {
s16 temp_t0 = arg1 - entity->ext.GH_Props.rotZ;
if (temp_t0 > 0x800) {
temp_t0 -= 0x1000;
}
if (temp_t0 < -0x800) {
temp_t0 += 0x1000;
}
do {
entity->ext.GH_Props.unkA4 = arg1;
entity->ext.GH_Props.unkA6 = temp_t0 / arg2;
} while (0);
}
void func_801CDD80(s16* arg0, Entity* arg1) {
s16* posY = arg1->posY.val;
while (*arg0 != 0) {
if (*arg0 != 0xFF) {
func_801CDD00(&g_CurrentEntity[*arg0], *posY, arg1->posX.val);
}
arg0++;
posY++;
}
}
void func_801CDE10(s16* arg0) {
Entity* temp_a0;
while (*arg0 != 0) {
if (*arg0 != 0xFF) {
temp_a0 = &g_CurrentEntity[*arg0];
temp_a0->ext.GH_Props.rotZ =
temp_a0->ext.GH_Props.rotZ + temp_a0->ext.generic.unkA6;
}
arg0++;
}
}
void func_801CDE88(s16* arg0) {
Entity* temp_a0;
while (*arg0 != 0) {
if (*arg0 != 0xFF) {
temp_a0 = &g_CurrentEntity[*arg0];
temp_a0->ext.GH_Props.rotZ =
temp_a0->ext.GH_Props.rotZ + temp_a0->ext.generic.unkA6;
func_801CD83C(temp_a0);
}
arg0++;
}
}
void func_801CDF1C(s16 entIndices[], s16 arg1[][4], s32 arg2) {
arg1 += (u16)g_CurrentEntity->ext.GH_Props.unkB0[arg2];
if (g_CurrentEntity->ext.GH_Props.unkB0[arg2 + 2] == 0) {
func_801CDD80(entIndices, arg1);
*(arg2 + 2 + g_CurrentEntity->ext.GH_Props.unkB0) = arg1[0][0];
}
// I don't know why the reverse array indexing is needed, but it is. Darn.
if (!(--((arg2 + 2)[g_CurrentEntity->ext.GH_Props.unkB0]))) {
if (arg1[1][0] == 0) {
g_CurrentEntity->ext.GH_Props.unkB0[arg2] = 0;
} else {
++g_CurrentEntity->ext.GH_Props.unkB0[arg2];
}
}
}
void func_801CDFD8(Entity* self, s32 arg1) {
if (self->ext.et_801CDFD8.unkB4 == 0) {
func_801CDD00(self, self->ext.et_801CDFD8.unkA4, arg1);
self->ext.et_801CDFD8.unkB4 = arg1;
}
self->ext.et_801CDFD8.unkB4--;
self->ext.et_801CDFD8.unk9C += self->ext.et_801CDFD8.unkA6;
func_801CD83C(self);
}
void func_801CE04C(Entity* entity, Collider* collider) {
s16 var_s0 = 0;
g_api.CheckCollision(
entity->posX.i.hi, (s16)(entity->posY.i.hi + collider->unk18), collider,
0);
if (collider->effects & 1) {
var_s0 = 1;
if (collider->effects & 0x8000) {
if (collider->effects & 0x4000) {
if (g_CurrentEntity->facingLeft != 0) {
var_s0 = 4;
} else {
var_s0 = 2;
}
} else {
if (g_CurrentEntity->facingLeft != 0) {
var_s0 = 2;
} else {
var_s0 = 4;
}
}
}
}
entity->ext.generic.unk88.S16.unk0 = var_s0;
}
s32 func_801CE120(Entity* self, s32 facing) {
Collider collider;
s32 x = self->posX.i.hi;
s32 y = self->posY.i.hi + 9;
s32 ret = 0;
if (facing != 0) {
x += 64;
} else {
x -= 64;
}
g_api.CheckCollision(x, y - 6, &collider, 0);
if (collider.effects & 1) {
ret |= 2;
}
g_api.CheckCollision(x, y + 6, &collider, 0);
if (!(collider.effects & 1)) {
ret |= 4;
}
return ret;
}
void func_801CE1E8(s16 step) {
s32 i;
g_CurrentEntity->step = step;
g_CurrentEntity->step_s = 0;
g_CurrentEntity->animFrameIdx = 0;
g_CurrentEntity->animFrameDuration = 0;
for (i = 0; i < 4; i++) {
g_CurrentEntity->ext.GH_Props.unkB0[i] = 0;
g_CurrentEntity->ext.GH_Props.unkB0[i + 2] = 0;
}
}
void func_801CE228(s16 step) {
s32 i;
for (i = 0; i < 4; i++) {
g_CurrentEntity->ext.GH_Props.unkB0[i] = 0;
g_CurrentEntity->ext.GH_Props.unkB0[i + 2] = 0;
}
}
void func_801CE258(s16* arg0) {
Entity* entity;
while (*arg0 != 0) {
entity = &g_CurrentEntity[*arg0];
if (entity->ext.GH_Props.unkA8 == 0) {
func_801CD83C(entity);
}
arg0++;
}
}
void func_801CE2CC(s16* arg0) {
s16* var_s0;
func_801CD91C(&g_CurrentEntity[arg0[1]]);
func_801CD91C(&g_CurrentEntity[arg0[0]]);
func_801CD83C(&g_CurrentEntity[arg0[2]]);
func_801CD83C(&g_CurrentEntity[arg0[3]]);
for (arg0 += 4; *arg0 != 0; arg0++) {
if (*arg0 != 0xFF) {
func_801CD83C(&g_CurrentEntity[*arg0]);
}
}
}
void func_801CE3FC(s16* arg0) {
s16* var_s0;
s16 var_v0;
s32 i;
for (i = 0, var_s0 = arg0; i < 4; i++) {
func_801CD83C(&g_CurrentEntity[*var_s0]);
var_s0++;
}
for (arg0 += 4; *arg0 != 0; arg0++) {
if (*arg0 != 0xFF) {
func_801CD83C(&g_CurrentEntity[*arg0]);
}
}
}
s32 func_801CE4CC(Entity* self) {
Entity* entity;
s32 step;
s32 x;
if (g_CurrentEntity->ext.et_801CE4CC.unk8E != 0) {
g_CurrentEntity->ext.et_801CE4CC.unk8E--;
}
x = self->posX.i.hi - PLAYER.posX.i.hi;
if (g_CurrentEntity->facingLeft != 0) {
x = -x;
}
if (x < -16) {
func_801CE1E8(10);
return;
}
if (g_CurrentEntity->ext.et_801CE4CC.unk84 == 1) {
entity = g_CurrentEntity + 10;
} else {
entity = g_CurrentEntity + 13;
}
if (func_801CE120(entity, g_CurrentEntity->facingLeft) != 0) {
func_801CE1E8(7);
return;
}
if (func_801CE120(entity, g_CurrentEntity->facingLeft ^ 1) != 0) {
func_801CE1E8(5);
return;
}
if (g_CurrentEntity->step == 8) {
if (x < 80) {
step = 5;
} else {
step = 8;
}
} else {
if (x < 80) {
step = 7;
} else {
step = 5;
}
if (x > 160) {
step = 8;
}
}
if ((g_CurrentEntity->ext.et_801CE4CC.unk8E == 0) && (x < 96)) {
g_CurrentEntity->ext.et_801CE4CC.unk8E = 3;
step = 6;
}
if (step != g_CurrentEntity->step) {
func_801CE1E8(step);
}
if (g_CurrentEntity->step == 7) {
if (step == 5) {
g_CurrentEntity->ext.et_801CE4CC.unkB0 = 1;
}
}
}

View File

@ -33,7 +33,19 @@ typedef enum {
/* 0x31 */ E_WATER_DROP,
/* 0x35 */ E_MEDIUM_WATER_SPLASH = 0x35,
/* 0x3F */ E_BONE_SCIMITAR_HEAD = 0x3F,
/* 0x4C */ E_FALLING_ROCK = 0x4C,
/* 0x40 */ E_BAT,
/* 0x41 */ E_ID_49, // This should be renamed, it's not ID 49!
/* 0x42 */ E_ZOMBIE,
/* 0x43 */ E_ZOMBIE_SPAWNER,
/* 0x44 */ E_OWL_KNIGHT,
/* 0x45 */ E_OWL,
/* 0x46 */ E_801CD540,
/* 0x47 */ E_801CD620,
/* 0x48 */ E_BLOODY_ZOMBIE,
/* 0x49 */ E_801CAE0C,
/* 0x4A */ E_BLOOD_SPLATTER,
/* 0x4B */ E_STAIRWAY_PIECE,
/* 0x4C */ E_FALLING_ROCK,
/* 0x4D */ E_ID_4D,
/* 0x4F */ E_SLOGRA_SPEAR = 0x4F,
/* 0x50 */ E_SLOGRA_SPEAR_PROJECTILE,
@ -361,3 +373,16 @@ extern s16 D_80183360[];
extern s16 D_80183378[];
extern s16 D_801833A0[];
extern s16 D_801833CC[];
// For EntityOwl
extern u16 D_80180B2C;
extern u16 D_801826CC[];
extern u8 D_801826EC[];
extern u8 D_801826F8[];
extern u8 D_80182710[];
extern u8 D_80182720[];
extern u8 D_80182734[];
extern u8 D_80182740[];
extern u8 D_8018274C[];
// Remove this when the Owl Knight is done!
extern const char* D_801B20DC;