mirror of https://github.com/zeldaret/tmc.git
318 lines
9.8 KiB
C
318 lines
9.8 KiB
C
/**
|
|
* @file chestSpawner.c
|
|
* @ingroup Objects
|
|
*
|
|
* @brief Chest Spawner object
|
|
*/
|
|
|
|
#define NENT_DEPRECATED
|
|
#include "global.h"
|
|
#include "object.h"
|
|
#include "functions.h"
|
|
#include "screen.h"
|
|
#include "structures.h"
|
|
#include "item.h"
|
|
|
|
typedef struct {
|
|
/*0x00*/ Entity base;
|
|
/*0x68*/ u8 unk_68[8];
|
|
/*0x70*/ u16 tilePosition;
|
|
/*0x72*/ u16 unk_72;
|
|
/*0x74*/ u8 unk_74[0x12];
|
|
/*0x86*/ u16 unk_86;
|
|
} ChestSpawnerEntity;
|
|
|
|
extern const Hitbox gUnk_0811F8A8;
|
|
extern const Hitbox gUnk_0811F8B0;
|
|
|
|
void sub_080842D8(ChestSpawnerEntity*);
|
|
void sub_08078828(ChestSpawnerEntity*);
|
|
void sub_08083E20(ChestSpawnerEntity*);
|
|
void sub_08084074(u32);
|
|
void sub_080840A8(s32, s32);
|
|
void ChestSpawner_Type0(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type2(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type0Init(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type0Action1(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type0Action2(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type0Action3(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type2Init(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type2Action1(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type2Action2(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type2Action3(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type2Action4(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type2Action5(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type2Action6(ChestSpawnerEntity*);
|
|
void ChestSpawner_Type2Action7(ChestSpawnerEntity*);
|
|
|
|
void ChestSpawner(ChestSpawnerEntity* this) {
|
|
static void (*const ChestSpawner_Types[])(ChestSpawnerEntity*) = {
|
|
ChestSpawner_Type0, ChestSpawner_Type0, ChestSpawner_Type2, ChestSpawner_Type2,
|
|
ChestSpawner_Type2, ChestSpawner_Type2, ChestSpawner_Type0, ChestSpawner_Type0,
|
|
};
|
|
ChestSpawner_Types[super->type](this);
|
|
}
|
|
|
|
void ChestSpawner_Type0(ChestSpawnerEntity* this) {
|
|
static void (*const ChestSpawner_Type0Actions[])(ChestSpawnerEntity*) = {
|
|
ChestSpawner_Type0Init,
|
|
ChestSpawner_Type0Action1,
|
|
ChestSpawner_Type0Action2,
|
|
ChestSpawner_Type0Action3,
|
|
};
|
|
ChestSpawner_Type0Actions[super->action](this);
|
|
}
|
|
|
|
void ChestSpawner_Type2(ChestSpawnerEntity* this) {
|
|
static void (*const ChestSpawner_Type2Actions[])(ChestSpawnerEntity*) = {
|
|
ChestSpawner_Type2Init, ChestSpawner_Type2Action1, ChestSpawner_Type2Action2, ChestSpawner_Type2Action3,
|
|
ChestSpawner_Type2Action4, ChestSpawner_Type2Action5, ChestSpawner_Type2Action6, ChestSpawner_Type2Action7,
|
|
};
|
|
ChestSpawner_Type2Actions[super->action](this);
|
|
}
|
|
|
|
void sub_08083E20(ChestSpawnerEntity* this) {
|
|
super->action = 3;
|
|
super->spriteSettings.draw = 1;
|
|
super->spriteRendering.alphaBlend = 0;
|
|
sub_080842D8(this);
|
|
sub_08078828(this);
|
|
}
|
|
void ChestSpawner_Type2Init(ChestSpawnerEntity* this) {
|
|
super->hitbox = (Hitbox*)&gUnk_0811F8B0;
|
|
if (CheckLocalFlag(super->type2)) {
|
|
super->spriteSettings.draw = 1;
|
|
super->action = 5;
|
|
sub_080842D8(this);
|
|
InitializeAnimation(super, 1);
|
|
} else {
|
|
if (CheckFlags(this->unk_86) || super->type == 4) {
|
|
sub_08083E20(this);
|
|
} else {
|
|
super->action = 1;
|
|
}
|
|
InitializeAnimation(super, 0);
|
|
}
|
|
}
|
|
|
|
void ChestSpawner_Type2Action1(ChestSpawnerEntity* this) {
|
|
if (CheckFlags(this->unk_86)) {
|
|
gScreen.controls.layerFXControl = 0xf40;
|
|
gScreen.controls.alphaBlend = 0x1000;
|
|
gUnk_02034490.unk0 = 1;
|
|
super->action = 2;
|
|
super->subAction = 0;
|
|
super->field_0xf = 0x1e;
|
|
super->spriteSettings.draw = 1;
|
|
super->spriteRendering.alphaBlend = 1;
|
|
RequestPriorityDuration(super, 0x1e);
|
|
sub_0805BC4C();
|
|
}
|
|
}
|
|
|
|
void ChestSpawner_Type2Action2(ChestSpawnerEntity* this) {
|
|
u32 tmp;
|
|
|
|
SetPriorityTimer(0x1e);
|
|
switch (super->subAction) {
|
|
case 0:
|
|
if (EntityInRectRadius(super, &gPlayerEntity, 0x10, 8)) {
|
|
sub_08078AC0(0x10, 0, 0);
|
|
gPlayerEntity.direction = 0x10;
|
|
}
|
|
super->subAction = 1;
|
|
break;
|
|
case 1:
|
|
if ((super->type == 5) || (gPlayerEntity.action == 1)) {
|
|
super->subAction = 2;
|
|
super->actionDelay = 8;
|
|
super->field_0xf = 0;
|
|
SoundReq(SFX_14A);
|
|
}
|
|
break;
|
|
default:
|
|
sub_0800445C(super);
|
|
CreateMagicSparkles(super->x.HALF.HI, super->y.HALF.HI, 2);
|
|
if (--super->actionDelay == 0) {
|
|
super->actionDelay = 8;
|
|
tmp = ++super->field_0xf;
|
|
gScreen.controls.alphaBlend = (((0x10 - tmp) * 0x100) & 0xff00) | tmp;
|
|
if (gScreen.controls.alphaBlend == 0x10) {
|
|
gUnk_02034490.unk0 = 0;
|
|
gScreen.controls.layerFXControl = 0;
|
|
sub_08083E20(this);
|
|
SoundReq(SFX_SECRET_BIG);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ChestSpawner_Type2Action3(ChestSpawnerEntity* this) {
|
|
sub_0800445C(super);
|
|
if (super->interactType != 0) {
|
|
super->action = 4;
|
|
super->field_0xf = 0x1e;
|
|
sub_080788E0(super);
|
|
RequestPriorityDuration(super, 0x3c);
|
|
SoundReq(SFX_CHEST_OPEN);
|
|
}
|
|
}
|
|
|
|
void ChestSpawner_Type2Action4(ChestSpawnerEntity* this) {
|
|
sub_0800445C(super);
|
|
GetNextFrame(super);
|
|
if ((super->frame & ANIM_DONE) != 0) {
|
|
if (--super->field_0xf == 0) {
|
|
if (super->actionDelay == 0x18) {
|
|
super->action = 6;
|
|
super->actionDelay = 8;
|
|
super->field_0xf = 0x10;
|
|
} else {
|
|
super->action = 5;
|
|
sub_08084074(super->type2);
|
|
}
|
|
}
|
|
SetLocalFlag(super->type2);
|
|
}
|
|
}
|
|
|
|
void sub_08084074(u32 param_1) {
|
|
u8* arr = (u8*)GetCurrentRoomProperty(3);
|
|
if (arr != NULL) {
|
|
for (; arr[0] != 0; arr += 8) {
|
|
if ((arr[0] == 3) && (param_1 == arr[1])) {
|
|
CreateItemEntity(arr[2], arr[3], 0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_080840A8(s32 param_1, s32 param_2) {
|
|
static const u8 gUnk_0811F838[] = { 84, 84, 84, 84, 85, 85, 85, 86 };
|
|
static const s32 gUnk_0811F840[] = { 393216, 458752, 524288, 589824 };
|
|
static const s8 gUnk_0811F850[] = { -6, 0, 0, 6 };
|
|
Entity* obj = CreateObject(GROUND_ITEM, gUnk_0811F838[Random() & 7], 0);
|
|
if (obj != NULL) {
|
|
obj->actionDelay = 6;
|
|
obj->direction = ((Random() & 7) + 0xc) | 0x80;
|
|
obj->speed = (Random() & 0xf) * 2 + 0x20;
|
|
obj->zVelocity = gUnk_0811F840[Random() & 3];
|
|
obj->x.HALF.HI = gUnk_0811F850[Random() & 3] + param_1;
|
|
obj->y.HALF.HI = param_2 + 1;
|
|
obj->z.HALF.HI = 0xfff8;
|
|
ResolveCollisionLayer(obj);
|
|
obj = CreateFx(obj, FX_DASH, 0);
|
|
if (obj != NULL) {
|
|
SoundReq(SFX_124);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ChestSpawner_Type2Action6(ChestSpawnerEntity* this) {
|
|
if (--super->actionDelay == 0) {
|
|
super->actionDelay = 8;
|
|
if (--super->field_0xf != 0) {
|
|
sub_080840A8(super->x.HALF.HI, super->y.HALF.HI);
|
|
} else {
|
|
super->action = 5;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ChestSpawner_Type2Action5(ChestSpawnerEntity* this) {
|
|
sub_0800445C(super);
|
|
}
|
|
|
|
void ChestSpawner_Type2Action7(ChestSpawnerEntity* this) {
|
|
}
|
|
|
|
void ChestSpawner_Type0Init(ChestSpawnerEntity* this) {
|
|
super->action++;
|
|
this->tilePosition = COORD_TO_TILE(super);
|
|
super->hitbox = (Hitbox*)&gUnk_0811F8A8;
|
|
if (GetTileTypeByEntity(super) == 0x74) {
|
|
DeleteThisEntity();
|
|
}
|
|
if (CheckFlags(this->unk_86)) {
|
|
super->action = 3;
|
|
sub_0807B7D8(0x73, this->tilePosition, super->collisionLayer);
|
|
if ((super->type & 1) == 0) {
|
|
DeleteThisEntity();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ChestSpawner_Type0Action1(ChestSpawnerEntity* this) {
|
|
if (CheckFlags(this->unk_86)) {
|
|
super->action = 2;
|
|
}
|
|
}
|
|
|
|
void ChestSpawner_Type0Action2(ChestSpawnerEntity* this) {
|
|
sub_0807B7D8(0x73, this->tilePosition, super->collisionLayer);
|
|
switch (super->type) {
|
|
case 6:
|
|
case 7:
|
|
SoundReq(SFX_215);
|
|
break;
|
|
default:
|
|
SoundReq(SFX_SECRET);
|
|
CreateDust(super);
|
|
break;
|
|
}
|
|
super->action = 3;
|
|
this->unk_72 = super->actionDelay * 0x3c;
|
|
if ((super->type & 1) == 0) {
|
|
DeleteThisEntity();
|
|
}
|
|
}
|
|
|
|
void ChestSpawner_Type0Action3(ChestSpawnerEntity* this) {
|
|
if ((super->type == 1) || (super->type == 7)) {
|
|
if (GetTileTypeByEntity(super) == 0x74) {
|
|
DeleteEntity(super);
|
|
} else {
|
|
if (!CheckFlags(this->unk_86)) {
|
|
if (this->unk_72 != 0) {
|
|
this->unk_72--;
|
|
} else {
|
|
super->action = 1;
|
|
sub_0807BA8C(this->tilePosition, super->collisionLayer);
|
|
CreateDust(super);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_080842D8(ChestSpawnerEntity* this) {
|
|
static const u8 gUnk_0811F854[] = {
|
|
35, 64, 191, 255, 35, 64, 192, 255, 38, 64, 255, 255, 38, 64, 0, 0, 255, 255,
|
|
};
|
|
static const u8 gUnk_0811F866[] = {
|
|
39, 64, 191, 255, 35, 64, 192, 255, 40, 64, 193, 255, 41, 64, 255, 255, 38, 64, 0, 0, 42, 64, 1, 0, 255, 255,
|
|
};
|
|
static const u8 gUnk_0811F880[] = {
|
|
34, 64, 255, 255, 34, 64, 0, 0, 255, 255,
|
|
};
|
|
static const u8 gUnk_0811F88A[] = {
|
|
36, 64, 255, 255, 34, 64, 0, 0, 37, 64, 1, 0, 255, 255,
|
|
};
|
|
static const u8* const gUnk_0811F898[] = {
|
|
gUnk_0811F854,
|
|
gUnk_0811F866,
|
|
gUnk_0811F880,
|
|
gUnk_0811F88A,
|
|
};
|
|
s32 index = -(-(super->x.HALF.HI & 8) >> 0x1f);
|
|
if ((super->y.HALF.HI & 8) != 0) {
|
|
index += 2;
|
|
}
|
|
SetMultipleTiles((u16*)gUnk_0811F898[index], COORD_TO_TILE(super), super->collisionLayer);
|
|
}
|
|
|
|
const Hitbox gUnk_0811F8A8 = { 0, -3, { 0, 0, 0, 0 }, 6, 6 };
|
|
const Hitbox gUnk_0811F8B0 = { 0, -3, { 0, 0, 0, 0 }, 12, 6 };
|