tmc/src/enemy/gyorgFemale.c

458 lines
12 KiB
C

#define NENT_DEPRECATED
#include "global.h"
#include "entity.h"
#include "enemy.h"
#include "sound.h"
#include "asm.h"
#include "functions.h"
#include "enemy/gyorg.h"
extern u8 gEntCount;
extern u8 gMapDataTopSpecial[];
extern u16 gMapDataBottomSpecial[];
extern void sub_080197D4(const void*);
extern u32 sub_08000E62(u32);
extern void RegisterTransitionManager(void*, void (*)(), void (*)());
void sub_08046498();
void sub_0804660C(GyorgFemaleEntity*, u32);
void sub_080464C0(GyorgFemaleEntity*);
void GyorgFemale_SpawnChildren(GyorgFemaleEntity* this, bool32 unlimit_tmp);
void sub_080465C8(void);
void GyorgFemale_ProcessEyeHit(GyorgFemaleEntity* this);
void GyorgFemale_ChooseEyePattern(GyorgFemaleEntity* this);
void sub_08046518(void);
void sub_080467DC(GyorgFemaleEntity*);
extern u8 gUpdateVisibleTiles;
extern u8 gUnk_080B3E80[];
extern u8 gUnk_080B37A0[];
extern const u8 gUnk_080D1A94[];
extern const u8 gUnk_080D1AAC[];
extern const u8 gUnk_080D1AC4[];
extern const u8 gUnk_080D1ADC[];
void GyorgFemale_Setup(GyorgFemaleEntity* this);
void GyorgFemale_Action1(GyorgFemaleEntity* this);
void GyorgFemale_Action2(GyorgFemaleEntity* this);
void GyorgFemale_Action3(GyorgFemaleEntity* this);
void GyorgFemale(Entity* this) {
static void (*const GyorgFemale_Actions[])(GyorgFemaleEntity*) = {
GyorgFemale_Setup,
GyorgFemale_Action1,
GyorgFemale_Action2,
GyorgFemale_Action3,
};
GyorgFemale_Actions[this->action]((GyorgFemaleEntity*)this);
}
void GyorgFemale_Setup(GyorgFemaleEntity* this) {
Entity* tmp;
if (gEntCount > 0x3d)
return;
tmp = CreateProjectile(GYORG_TAIL);
tmp->type = 0;
tmp->parent = super;
((GyorgHeap*)super->myHeap)->tail = (GenericEntity*)tmp;
tmp = CreateEnemy(GYORG_FEMALE_MOUTH, 0);
tmp->parent = super;
((GyorgHeap*)super->myHeap)->mouth = (GyorgFemaleMouthEntity*)tmp;
tmp = CreateEnemy(GYORG_FEMALE_EYE, 0);
tmp->parent = super;
tmp = CreateEnemy(GYORG_FEMALE_EYE, 1);
tmp->parent = super;
tmp = CreateEnemy(GYORG_FEMALE_EYE, 2);
tmp->parent = super;
tmp = CreateEnemy(GYORG_FEMALE_EYE, 3);
tmp->parent = super;
tmp = CreateEnemy(GYORG_FEMALE_EYE, 4);
tmp->parent = super;
tmp = CreateEnemy(GYORG_FEMALE_EYE, 5);
tmp->parent = super;
tmp = CreateEnemy(GYORG_FEMALE_EYE, 6);
tmp->parent = super;
tmp = CreateEnemy(GYORG_FEMALE_EYE, 7);
tmp->parent = super;
super->action = 1;
super->spriteOrientation.flipY = 2;
super->spriteRendering.b3 = 2;
super->collisionLayer = 2;
this->eyesVulnerable = 0;
this->unk_79 = 0;
this->childrenSpawnTimer = 60;
MemClear(&gMapDataBottomSpecial, 0x8000);
MemClear(&gMapDataTopSpecial, 0x8000);
sub_0804660C(this, 0);
sub_080464C0(this);
gPlayerEntity.collisionLayer = 2;
UpdateSpriteForCollisionLayer(&gPlayerEntity);
#ifndef EU
RegisterTransitionManager(this, sub_08046498, 0);
#else
RegisterTransitionManager(this, sub_080464C0, 0);
#endif
}
void GyorgFemale_Action1(GyorgFemaleEntity* this) {
if (this->unk_79 & 0x80) {
this->unk_79 &= ~0x80;
this->unk_79 |= 0x40;
sub_0804660C(this, (this->unk_79 & 3) << 6);
} else {
if (this->unk_79 & 0x40) {
this->unk_79 &= ~0x40;
sub_080464C0(this);
}
}
sub_080465C8();
if (((GyorgHeap*)super->myHeap)->boss->unk_6c & 0x38) {
super->action = 2;
super->timer = 0;
this->eyeTimer = 0;
this->eyesHitFrame = 0;
this->eyesHit = 0;
this->childrenSpawnTimer = 60;
this->unk_80 = 0;
return;
}
if (((GyorgHeap*)super->myHeap)->boss->unk_6c & 0x40) {
super->action = 3;
this->childrenSpawnTimer = 60;
super->timer = 0;
this->eyeTimer = 0;
this->eyesHitFrame = 0;
this->eyesHit = 0;
this->unk_80 = 0;
return;
}
if (((GyorgHeap*)super->myHeap)->boss->unk_6c & 0x100) {
if (--this->childrenSpawnTimer == 0) {
this->childrenSpawnTimer = 360;
GyorgFemale_SpawnChildren(this, TRUE);
}
}
}
void GyorgFemale_Action2(GyorgFemaleEntity* this) {
sub_080465C8();
GyorgFemale_ProcessEyeHit(this);
if (++this->eyeTimer >= 1440) {
this->eyeTimer = 0;
this->eyesHitFrame = 0;
this->eyesHit = 0;
this->unk_80 = 0;
} else {
if (this->eyeTimer == 120) {
GyorgFemale_ChooseEyePattern(this);
} else {
if (this->eyeTimer == 1320) {
this->eyesVulnerable = 0;
#ifndef EU
this->eyesHit = 0;
this->unk_7f = 0;
#endif
}
}
}
if (((GyorgHeap*)super->myHeap)->boss->unk_6c & 0x80 && --this->childrenSpawnTimer == 0) {
this->childrenSpawnTimer = 360;
GyorgFemale_SpawnChildren(this, 0);
}
if ((((GyorgHeap*)super->myHeap)->boss->unk_6c & 0x38) == 0) {
super->action = 1;
this->childrenSpawnTimer = 60;
#ifndef EU
this->eyesVulnerable = 0;
#endif
this->unk_80 = 0;
}
}
void GyorgFemale_Action3(GyorgFemaleEntity* this) {
sub_080465C8();
if (--this->childrenSpawnTimer == 0) {
this->childrenSpawnTimer = 360;
GyorgFemale_SpawnChildren(this, 1);
}
GyorgFemale_ProcessEyeHit(this);
if (++this->eyeTimer >= 1440) {
this->eyeTimer = 0;
this->eyesHitFrame = 0;
this->eyesHit = 0;
this->unk_80 = 0;
} else {
if (this->eyeTimer == 120) {
GyorgFemale_ChooseEyePattern(this);
} else {
if (this->eyeTimer == 1320) {
this->eyesVulnerable = 0;
#ifndef EU
this->eyesHit = 0;
this->unk_7f = 0;
#endif
}
}
}
if (super->health == 0) {
super->action = 1;
#ifdef EU
this->eyesVulnerable = 0;
#endif
this->childrenSpawnTimer = 60;
#ifndef EU
this->eyesVulnerable = 0;
#endif
this->unk_80 = 0;
SoundReq(SFX_BOSS_DIE);
}
}
#ifndef EU
void sub_08046498(GyorgFemaleEntity* this) {
MemClear(&gMapDataBottomSpecial, 0x8000);
MemClear(&gMapDataTopSpecial, 0x8000);
sub_080464C0(this);
}
#endif
void sub_080464C0(GyorgFemaleEntity* this) {
static const void* const gUnk_080D1A74[] = {
gUnk_080D1A94,
gUnk_080D1AAC,
gUnk_080D1AC4,
gUnk_080D1ADC,
};
s32 i;
u8* src;
u8* dst;
sub_080197D4(gUnk_080D1A74[super->animationState >> 6]);
sub_08046518();
for (i = 0x20, src = ((u8*)&gMapDataBottomSpecial), dst = ((u8*)&gMapDataBottomSpecial) + 0x3260; i != 0; i--) {
MemCopy(src, dst, 0x40);
dst += 0x100;
src += 0x40;
}
MemClear(&gMapDataBottomSpecial, 0x800);
gUpdateVisibleTiles = 1;
}
NONMATCH("asm/non_matching/gyorg_female/sub_08046518.inc", void sub_08046518(void)) {
u32 r5;
u16* stack1;
u8* stack2;
u8* r6;
u32 i;
u16* sl;
sl = &gMapTop.metatileTypes[0xFFFFBCB0];
stack1 = &gMapTop.metatileTypes[0xFFFFECB0];
stack2 = (u8*)&gMapTop.metatileTypes[0x00006658];
r6 = (u8*)&gMapTop.metatileTypes[0xFFFFD658];
for (i = 0; i < 0x10; i++) {
sl += 0x40;
stack1 += 0x40;
for (r5 = 0; r5 < 0x10; r5++) {
stack1[r5] = sl[r5];
stack2[r5] = gUnk_080B37A0[gMapTop.metatileTypes[sl[r5]]];
r6[r5] = gUnk_080B3E80[gMapTop.metatileTypes[sl[r5]]];
}
stack2 = stack2 + 0x40;
r6 = r6 + 0x40;
}
}
END_NONMATCH
void sub_080465C8(void) {
s32 x, y;
x = (gPlayerEntity.x.HALF.HI - gRoomControls.origin_x) >> 3;
y = (gPlayerEntity.y.HALF.HI - gRoomControls.origin_y) >> 3;
if (gMapDataBottomSpecial[(y << 7) + x]) {
gPlayerState.field_0x14 = 1;
}
}
void sub_0804660C(GyorgFemaleEntity* this, u32 unk1) {
static const u16 gUnk_080D1A84[] = {
0x200, 0x258, 0x1B8, 0x210, 0x200, 0x1C8, 0x248, 0x210,
};
const u16* p;
super->animationState = unk1;
p = &gUnk_080D1A84[unk1 >> 5];
super->x.HALF.HI = p[0] + gRoomControls.origin_x;
super->y.HALF.HI = p[1] + gRoomControls.origin_y;
}
// todo: correct type
const u8 gUnk_080D1A94[] = {
#if defined(JP) || defined(DEMO_JP)
0x7C,
#elif defined(EU)
0x50,
#else
0x08,
#endif
0x41, 0x22, 0x80, 0xE0, 0x9E, 0x01, 0x02, 0x00, 0x08, 0x00, 0x80,
#if defined(JP) || defined(DEMO_JP)
0x2C, 0xD3,
#elif defined(EU)
0x00, 0xD3,
#else
0xB8, 0xD2,
#endif
0x22, 0x00, 0x54, 0xB6, 0x00, 0x02, 0x80, 0x1F, 0x00, 0x80,
};
const u8 gUnk_080D1AAC[] = {
#if defined(JP) || defined(DEMO_JP)
0xFC,
#elif defined(EU)
0xD0,
#else
0x88,
#endif
0x3D, 0x22, 0x80, 0xE0, 0x9E, 0x01, 0x02, 0x00, 0x08, 0x00, 0x80,
#if defined(JP) || defined(DEMO_JP)
0xF8,
#elif defined(EU)
0xCC,
#else
0x84,
#endif
0xD6, 0x22, 0x00, 0x54, 0xB6, 0x00, 0x02, 0x80, 0x1F, 0x00, 0x80,
};
const u8 gUnk_080D1AC4[] = {
#if defined(JP) || defined(DEMO_JP)
0xE4,
#elif defined(EU)
0xB8,
#else
0x70,
#endif
0x36, 0x22, 0x80, 0xE0, 0x9E, 0x01, 0x02, 0x00, 0x08, 0x00, 0x80,
#if defined(JP) || defined(DEMO_JP)
0xC0,
#elif defined(EU)
0x94,
#else
0x4C,
#endif
0xDA, 0x22, 0x00, 0x54, 0xB6, 0x00, 0x02, 0x80, 0x1F, 0x00, 0x80,
};
const u8 gUnk_080D1ADC[] = {
#if defined(JP) || defined(DEMO_JP)
0x78,
#elif defined(EU)
0x4C,
#else
0x04,
#endif
0x3A, 0x22, 0x80, 0xE0, 0x9E, 0x01, 0x02, 0x00, 0x08, 0x00, 0x80,
#if defined(JP) || defined(DEMO_JP)
0x88,
#elif defined(EU)
0x5C,
#else
0x14,
#endif
0xDE, 0x22, 0x00, 0x54, 0xB6, 0x00, 0x02, 0x80, 0x1F, 0x00, 0x80,
};
void GyorgFemale_SpawnChildren(GyorgFemaleEntity* this, bool32 unlimit_tmp) {
static const u8 gUnk_080D1AF4[] = { 2, 3, 6, 7 };
u32 tmp;
if (unlimit_tmp == 0) {
tmp = gUnk_080D1AF4[Random() & 3];
} else {
tmp = Random() & 7;
}
GyorgBossObject_SpawnChildren(tmp, FALSE, super->animationState >> 3);
}
void GyorgFemale_ChooseEyePattern(GyorgFemaleEntity* this) {
static const u8 gUnk_080D1AF8[] = { 0x16, 0x92, 0x94, 0x86 };
if (super->health == 0) {
return;
}
#ifndef EU
if (this->eyesVulnerable == 0xFF) {
return;
}
#endif
this->eyesVulnerable = gUnk_080D1AF8[Random() & 3];
this->unk_7f = 0;
this->damageTakenCycle = 0;
sub_080467DC(this);
}
void GyorgFemale_ProcessEyeHit(GyorgFemaleEntity* this) {
if (this->eyesHitFrame != 0) {
this->eyesHit |= this->eyesHitFrame;
if (super->timer == 0 && this->eyesVulnerable != 0xFF) {
#ifndef EU
super->timer = 4;
#else
super->timer = 3;
#endif
}
if (sub_08000E62(this->eyesHit) > 2) {
super->timer = 0;
this->eyesHit = 0;
this->eyesVulnerable = 0xFF;
SoundReq(SFX_BOSS_HIT);
if (super->health != 0) {
InitScreenShake(8, 0);
if (++this->damageTakenCycle <= 12) {
super->health--;
}
if (super->health == 0) {
this->eyesVulnerable = 0;
this->eyeTimer = 1320;
} else {
if (this->unk_7f == 0) {
this->unk_7f = 1;
this->eyeTimer = 1080;
}
}
}
sub_080467DC(this);
}
}
if (super->timer != 0 && this->eyesVulnerable != 0xFF && --super->timer == 0) {
Entity* tmp;
this->unk_80 |= this->eyesHit;
this->eyesHit = 0;
sub_080467DC(this);
#ifndef EU
if (((GyorgHeap*)super->myHeap)->unk_3c != 0xFF) {
#endif
tmp = &gPlayerEntity;
tmp->knockbackDirection = ((GyorgHeap*)super->myHeap)->unk_3c;
tmp->iframes = 0xF4;
tmp->knockbackDuration = 0xA;
tmp = CreateFx(super, FX_REFECT3, 0);
if (tmp) {
tmp->x.HALF.HI = ((GyorgHeap*)super->myHeap)->reflectFxPos.HALF.x;
tmp->y.HALF.HI = ((GyorgHeap*)super->myHeap)->reflectFxPos.HALF.y;
tmp->collisionLayer = 1;
UpdateSpriteForCollisionLayer(tmp);
}
#ifndef EU
}
#endif
}
this->eyesHitFrame = 0;
}
void sub_080467DC(GyorgFemaleEntity* this) {
u32 i;
for (i = 0; i < 8; i++) {
(*((GyorgHeap**)(&super->myHeap)))->unk_18[i] = 0;
}
}