mirror of https://github.com/zeldaret/tmc.git
245 lines
5.9 KiB
C
245 lines
5.9 KiB
C
/**
|
|
* @file book.c
|
|
* @ingroup Objects
|
|
*
|
|
* @brief Book object
|
|
*/
|
|
#include "collision.h"
|
|
#include "functions.h"
|
|
#include "item.h"
|
|
#include "message.h"
|
|
#include "npc.h"
|
|
#include "object.h"
|
|
|
|
typedef struct {
|
|
/*0x00*/ Entity base;
|
|
/*0x68*/ u8 unused1[24];
|
|
/*0x80*/ u8 unk_80;
|
|
/*0x81*/ u8 unused2[5];
|
|
/*0x86*/ u16 unk_86;
|
|
} BookEntity;
|
|
|
|
extern void (*const Book_Actions[])(BookEntity*);
|
|
extern s8 const gUnk_08123D94[];
|
|
|
|
u32 sub_0809B688(Entity*);
|
|
void sub_0809B6B0(Entity*, Entity*);
|
|
|
|
void Book(BookEntity* this) {
|
|
Book_Actions[super->action](this);
|
|
}
|
|
|
|
void Book_Init(BookEntity* this) {
|
|
u32 obtained = GetInventoryValue(super->type + ITEM_QST_BOOK1);
|
|
if (super->type2 != 3) {
|
|
if (obtained != 0) {
|
|
DeleteThisEntity();
|
|
}
|
|
} else {
|
|
if (CheckLocalFlag(MIZUKAKI_BOOK_ALLBACK)) {
|
|
DeleteThisEntity();
|
|
}
|
|
|
|
if (obtained != 2) {
|
|
super->spriteSettings.draw = 0;
|
|
}
|
|
}
|
|
|
|
super->spriteOffsetY = 3;
|
|
if (CheckFlags(this->unk_86)) {
|
|
if (super->type2 == 0) {
|
|
super->y.HALF.HI += 48;
|
|
}
|
|
|
|
super->type2 = 2;
|
|
}
|
|
|
|
UpdateSpriteForCollisionLayer(super);
|
|
InitAnimationForceUpdate(super, super->type + ITEM_QST_BOOK1);
|
|
|
|
switch (super->type2) {
|
|
case 0:
|
|
super->action = 1;
|
|
super->timer = 22;
|
|
super->subtimer = 2;
|
|
this->unk_80 = 0;
|
|
super->spritePriority.b0 = 3;
|
|
break;
|
|
case 1: {
|
|
u32 scroll;
|
|
u32 height;
|
|
|
|
super->action = 3;
|
|
scroll = (u16)gRoomControls.scroll_y - 0x10;
|
|
height = (u16)super->y.HALF.HI - scroll;
|
|
super->z.HALF.HI -= height;
|
|
break;
|
|
}
|
|
case 2:
|
|
super->action = 4;
|
|
break;
|
|
case 3:
|
|
super->action = 5;
|
|
super->subAction = 0;
|
|
super->spritePriority.b0 = 3;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Book_Action1(BookEntity* this) {
|
|
sub_0800445C(super);
|
|
|
|
if (this->unk_80 != 0) {
|
|
this->unk_80--;
|
|
return;
|
|
}
|
|
|
|
if (sub_0809B688(super)) {
|
|
if (--super->timer) {
|
|
return;
|
|
}
|
|
|
|
super->action = 2;
|
|
super->timer = 30;
|
|
super->speed = 0x40;
|
|
super->direction = 0x10;
|
|
|
|
gPlayerState.pushedObject = TREE_THORNS;
|
|
gPlayerState.queued_action = PLAYER_PUSH;
|
|
gPlayerState.flags |= PL_BUSY;
|
|
|
|
gPlayerEntity.base.x.HALF.LO = 0;
|
|
gPlayerEntity.base.y.HALF.LO = 0;
|
|
gPlayerEntity.base.direction = gPlayerEntity.base.animationState << 2;
|
|
EnqueueSFX(SFX_10F);
|
|
} else {
|
|
super->timer = 22;
|
|
}
|
|
}
|
|
|
|
void Book_Action2(BookEntity* this) {
|
|
if (--super->timer == 0) {
|
|
if (--super->subtimer == 0) {
|
|
super->action = 3;
|
|
super->y.HALF.HI += 0x20;
|
|
super->z.HALF.HI -= 0x20;
|
|
} else {
|
|
super->action = 1;
|
|
super->timer = 22;
|
|
this->unk_80 = 0x18;
|
|
}
|
|
}
|
|
|
|
LinearMoveUpdate(super);
|
|
}
|
|
|
|
void Book_Action3(BookEntity* this) {
|
|
Entity* fx;
|
|
|
|
if (BounceUpdate(super, Q_8_8(40.0)) != BOUNCE_INIT_NEXT) {
|
|
return;
|
|
}
|
|
|
|
super->action = 4;
|
|
super->spritePriority.b0 = 4;
|
|
|
|
SetFlag(this->unk_86);
|
|
|
|
fx = CreateFx(super, FX_DEATH, 0);
|
|
if (fx != NULL) {
|
|
SortEntityAbove(super, fx);
|
|
}
|
|
}
|
|
|
|
void Book_Action4(BookEntity* this) {
|
|
if (gPlayerState.flags & PL_MINISH) {
|
|
sub_0800445C(super);
|
|
} else if (IsCollidingPlayer(super)) {
|
|
CreateItemEntity(super->type + ITEM_QST_BOOK1, 0, 0);
|
|
DeleteThisEntity();
|
|
}
|
|
}
|
|
|
|
void Book_Action5(BookEntity* this) {
|
|
if (super->spriteSettings.draw == 1) {
|
|
switch (super->subAction) {
|
|
case 0: {
|
|
Entity* parent = FindEntityByID(NPC, STURGEON, 7);
|
|
if (parent == NULL) {
|
|
return;
|
|
}
|
|
if (parent->x.HALF.HI < super->x.HALF.HI) {
|
|
return;
|
|
}
|
|
if (parent->animationState != 4) {
|
|
return;
|
|
}
|
|
|
|
super->parent = parent;
|
|
super->subAction = 1;
|
|
sub_0809B6B0(super->parent, super);
|
|
break;
|
|
}
|
|
case 1: {
|
|
if ((super->parent == NULL) || (super->parent->next == NULL)) {
|
|
DeleteThisEntity();
|
|
return;
|
|
}
|
|
sub_0809B6B0(super->parent, super);
|
|
break;
|
|
}
|
|
default:
|
|
return;
|
|
}
|
|
|
|
} else {
|
|
switch (super->subAction) {
|
|
default: {
|
|
DeleteThisEntity();
|
|
break;
|
|
}
|
|
case 0: {
|
|
if (GetInventoryValue(super->type + ITEM_QST_BOOK1) == 2) {
|
|
super->subAction = 1;
|
|
}
|
|
break;
|
|
}
|
|
case 1: {
|
|
u8 status = gMessage.state & MESSAGE_ACTIVE;
|
|
if (!status) {
|
|
super->spriteSettings.draw = 1;
|
|
super->subAction = status;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
u32 sub_0809B688(Entity* this) {
|
|
u32 ret = EntityInRectRadius(this, &gPlayerEntity.base, 6, 12);
|
|
|
|
if (ret == 1 && gPlayerState.direction != DirectionSouth) {
|
|
ret = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void sub_0809B6B0(Entity* parent, Entity* this) {
|
|
s32 offset = (s32)gUnk_08123D94[parent->animationState >> 1] << 16;
|
|
|
|
PositionRelative(parent, this, 0, offset);
|
|
|
|
this->z.HALF.HI = -(this->type << 2);
|
|
this->spritePriority.b0 = 3 - this->type;
|
|
}
|
|
|
|
void (*const Book_Actions[])(BookEntity*) = {
|
|
Book_Init, Book_Action1, Book_Action2, Book_Action3, Book_Action4, Book_Action5,
|
|
};
|
|
|
|
const s8 gUnk_08123D94[] = { -22, -20, -20, -20 };
|