mirror of https://github.com/zeldaret/tmc.git
304 lines
9.2 KiB
C
304 lines
9.2 KiB
C
/**
|
|
* @file objectOnPillar.c
|
|
* @ingroup Objects
|
|
*
|
|
* @brief Object on Pillar object
|
|
*/
|
|
|
|
#define NENT_DEPRECATED
|
|
#include "functions.h"
|
|
#include "global.h"
|
|
#include "hitbox.h"
|
|
#include "object.h"
|
|
|
|
typedef struct {
|
|
/*0x00*/ Entity base;
|
|
/*0x68*/ u8 unk_68[8];
|
|
/*0x70*/ u16 tileIndex;
|
|
/*0x72*/ u16 unk_72;
|
|
/*0x74*/ u16 tilePosition;
|
|
/*0x76*/ u16 unk_76;
|
|
/*0x78*/ u8 unk_78[0x4];
|
|
/*0x7c*/ u8 unk_7c;
|
|
/*0x7d*/ u8 unk_7d;
|
|
/*0x7e*/ u8 unk_7e;
|
|
/*0x7f*/ u8 unk_7f;
|
|
/*0x80*/ u8 unk_80[0x4];
|
|
/*0x84*/ u16 hitFlag;
|
|
/*0x86*/ u16 unk_86;
|
|
} ObjectOnPillarEntity;
|
|
|
|
extern bool32 sub_080896B0(void); // pushableStatue
|
|
|
|
extern s16 gUnk_080B4488[];
|
|
|
|
typedef struct {
|
|
/*0x00*/ Entity base;
|
|
/*0x68*/ u8 unk_68[10 + 0x14];
|
|
/*0x86*/ u16 hitFlag;
|
|
} EntityWithHitFlag;
|
|
|
|
typedef struct {
|
|
u16 key;
|
|
u16 value;
|
|
} KeyValuePair;
|
|
|
|
void sub_080970F4(ObjectOnPillarEntity*);
|
|
void sub_080971E0(ObjectOnPillarEntity*);
|
|
bool32 sub_08097194(ObjectOnPillarEntity*);
|
|
bool32 sub_08097008(ObjectOnPillarEntity*);
|
|
bool32 sub_08097144(ObjectOnPillarEntity*);
|
|
void sub_08097098(ObjectOnPillarEntity*);
|
|
u32 sub_08097074(u32);
|
|
bool32 sub_08097348(u32);
|
|
void ObjectOnPillar_Init(ObjectOnPillarEntity*);
|
|
void ObjectOnPillar_Action1(ObjectOnPillarEntity*);
|
|
void ObjectOnPillar_Action2(ObjectOnPillarEntity*);
|
|
void ObjectOnPillar_Action3(ObjectOnPillarEntity*);
|
|
void ObjectOnPillar_Action4(ObjectOnPillarEntity*);
|
|
void ObjectOnPillar_SubAction0(ObjectOnPillarEntity*);
|
|
void ObjectOnPillar_SubAction1(ObjectOnPillarEntity*);
|
|
|
|
void ObjectOnPillar(ObjectOnPillarEntity* this) {
|
|
static void (*const ObjectOnPillar_Actions[])(ObjectOnPillarEntity*) = {
|
|
ObjectOnPillar_Init, ObjectOnPillar_Action1, ObjectOnPillar_Action2,
|
|
ObjectOnPillar_Action3, ObjectOnPillar_Action4,
|
|
};
|
|
ObjectOnPillar_Actions[super->action](this);
|
|
}
|
|
|
|
void ObjectOnPillar_Init(ObjectOnPillarEntity* this) {
|
|
static const u8 gUnk_08123264[] = {
|
|
0, 2, 4, 3, 7, 5, 0, 0,
|
|
};
|
|
if (CheckFlags(this->unk_86) == 0) {
|
|
super->action = 1;
|
|
super->speed = 0x80;
|
|
super->updatePriority = 3;
|
|
super->spriteSettings.draw = 1;
|
|
super->spritePriority.b1 = 1;
|
|
super->spriteSettings.shadow = 1;
|
|
super->spriteOffsetY = 4;
|
|
super->hitbox = (Hitbox*)&gUnk_080FD1F4;
|
|
super->carryFlags = 1;
|
|
this->unk_72 = 0;
|
|
super->collisionLayer = this->unk_7d >> 4;
|
|
UpdateSpriteForCollisionLayer(super);
|
|
sub_080970F4(this);
|
|
super->frameIndex = gUnk_08123264[super->type];
|
|
} else {
|
|
super->x.HALF.HI = (this->unk_7c | ((this->unk_7d & 0xf) << 8)) + gRoomControls.origin_x;
|
|
super->y.HALF.HI = (this->unk_7e | ((this->unk_7f & 0xf) << 8)) + gRoomControls.origin_y;
|
|
super->collisionLayer = this->unk_7f >> 4;
|
|
sub_080971E0(this);
|
|
}
|
|
}
|
|
|
|
void ObjectOnPillar_Action1(ObjectOnPillarEntity* this) {
|
|
if (sub_08097194(this) == FALSE) {
|
|
if (sub_08097008(this)) {
|
|
super->action = 3;
|
|
} else {
|
|
RegisterCarryEntity(super);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ObjectOnPillar_Action2(ObjectOnPillarEntity* this) {
|
|
static void (*const ObjectOnPillar_SubActions[])(ObjectOnPillarEntity*) = {
|
|
ObjectOnPillar_SubAction0,
|
|
ObjectOnPillar_SubAction1,
|
|
};
|
|
if (this->unk_76 != 0) {
|
|
sub_08097144(this);
|
|
} else {
|
|
if (gPlayerState.heldObject == 0) {
|
|
super->subAction = 6;
|
|
}
|
|
ObjectOnPillar_SubActions[super->subAction - 5](this);
|
|
}
|
|
}
|
|
|
|
void ObjectOnPillar_SubAction0(ObjectOnPillarEntity* this) {
|
|
static const s8 gUnk_08123274[] = { 0, 14, -14, 2, 0, -14, 14, 2 };
|
|
const s8* ptr;
|
|
if (this->unk_72 == 0) {
|
|
this->unk_72 = 1;
|
|
ptr = &gUnk_08123274[gPlayerEntity.animationState];
|
|
PositionRelative(super, &gPlayerEntity, ptr[0] << 0x10, ptr[1] << 0x10);
|
|
}
|
|
sub_08097008(this);
|
|
if (sub_080896B0()) {
|
|
gPlayerState.queued_action = PLAYER_PULL;
|
|
gPlayerState.field_0x38 = 0x20;
|
|
gPlayerState.flags |= PL_BUSY;
|
|
gPlayerEntity.x.HALF.LO = 0;
|
|
gPlayerEntity.y.HALF.LO = 0;
|
|
super->direction = ((gPlayerEntity.animationState ^ 4) << 2);
|
|
sub_08097098(this);
|
|
}
|
|
}
|
|
|
|
void ObjectOnPillar_SubAction1(ObjectOnPillarEntity* this) {
|
|
super->action = 1;
|
|
this->unk_72 = 0;
|
|
}
|
|
|
|
void ObjectOnPillar_Action3(ObjectOnPillarEntity* this) {
|
|
if (sub_08097144(this)) {
|
|
super->action = 1;
|
|
}
|
|
}
|
|
|
|
void ObjectOnPillar_Action4(ObjectOnPillarEntity* this) {
|
|
}
|
|
|
|
bool32 sub_08097008(ObjectOnPillarEntity* this) {
|
|
Entity* effect;
|
|
u32 tileType = GetTileType(this->tilePosition, super->collisionLayer);
|
|
if (tileType != 0x4036) {
|
|
switch (sub_08097074(tileType)) {
|
|
case 1:
|
|
super->direction = (((tileType - 0x37) & 3) << 3);
|
|
sub_08097098(this);
|
|
return TRUE;
|
|
case 2:
|
|
this->tileIndex = tileType;
|
|
break;
|
|
default:
|
|
effect = CreateObject(SPECIAL_FX, 4, 0);
|
|
if (effect != NULL) {
|
|
CopyPosition(super, effect);
|
|
}
|
|
DeleteEntity(super);
|
|
break;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
u32 sub_08097074(u32 tileType) {
|
|
|
|
static const KeyValuePair gUnk_0812327C[] = {
|
|
{ 0x4037, 1 }, { 0x4038, 1 }, { 0x4039, 1 }, { 0x403a, 1 }, { 0x7a, 2 }, { 0x78, 2 }, { 0, 0 },
|
|
};
|
|
const KeyValuePair* entry = gUnk_0812327C;
|
|
for (; entry->key != 0; entry++) {
|
|
if (entry->key == tileType) {
|
|
return entry->value;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void sub_08097098(ObjectOnPillarEntity* this) {
|
|
u16 tileType;
|
|
this->unk_76 = 0x20;
|
|
EnqueueSFX(SFX_10F);
|
|
SetTile(this->tileIndex, this->tilePosition, super->collisionLayer);
|
|
tileType = GetTileType(gUnk_080B4488[super->direction >> 3] + this->tilePosition, super->collisionLayer);
|
|
if ((tileType == 0x79) || tileType == 0x77) {
|
|
super->spriteOffsetY = 2;
|
|
}
|
|
}
|
|
|
|
void sub_080970F4(ObjectOnPillarEntity* this) {
|
|
this->tilePosition = COORD_TO_TILE(super);
|
|
this->tileIndex = GetTileIndex(this->tilePosition, super->collisionLayer);
|
|
SetTile(0x4036, this->tilePosition, super->collisionLayer);
|
|
}
|
|
|
|
bool32 sub_08097144(ObjectOnPillarEntity* this) {
|
|
LinearMoveUpdate(super);
|
|
sub_0800445C(super);
|
|
if (GetTileUnderEntity(super) == 0x19) {
|
|
super->spriteOffsetY = 2;
|
|
}
|
|
if ((--this->unk_76 == 0) && sub_08097194(this) == FALSE) {
|
|
super->spriteOffsetY = 4;
|
|
sub_080970F4(this);
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
bool32 sub_08097194(ObjectOnPillarEntity* this) {
|
|
if (sub_0800442E(super)) {
|
|
return TRUE;
|
|
} else {
|
|
u32 tileType = GetTileTypeByEntity(super);
|
|
if (tileType == 0x71 || tileType == 0x72 || (tileType == 0x4020)) {
|
|
SetFlag(this->unk_86);
|
|
EnqueueSFX(SFX_10B);
|
|
sub_080971E0(this);
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void sub_080971E0(ObjectOnPillarEntity* this) {
|
|
EntityWithHitFlag* entity;
|
|
u32 tilePosition;
|
|
|
|
entity = (EntityWithHitFlag*)CreateObject(SPECIAL_FX, 0x11, 0x40);
|
|
if (entity != NULL) {
|
|
PositionRelative(super, &entity->base, -0x80000, 0x20000);
|
|
}
|
|
entity = (EntityWithHitFlag*)CreateObject(SPECIAL_FX, 0x11, 0x40);
|
|
if (entity != NULL) {
|
|
PositionRelative(super, &entity->base, 0x80000, 0x20000);
|
|
}
|
|
switch (super->type) {
|
|
case 0:
|
|
default:
|
|
super->action = 4;
|
|
super->frameIndex = 1;
|
|
super->spritePriority.b0 = 7;
|
|
SetTile(0, COORD_TO_TILE(super), super->collisionLayer);
|
|
DeleteThisEntity();
|
|
break;
|
|
case 1:
|
|
tilePosition = COORD_TO_TILE(super);
|
|
if (sub_08097348(tilePosition) == 0) {
|
|
SetTileType(0x73, tilePosition, super->collisionLayer);
|
|
}
|
|
DeleteThisEntity();
|
|
break;
|
|
case 2:
|
|
entity = (EntityWithHitFlag*)CreateObject(HITTABLE_LEVER, 0, 0);
|
|
if (entity != NULL) {
|
|
(entity->base).x.HALF.HI = (super->x.HALF.HI & 0xfff0) + 8;
|
|
(entity->base).y.HALF.HI = (super->y.HALF.HI & 0xfff0) + 8;
|
|
(entity->base).collisionLayer = super->collisionLayer;
|
|
entity->hitFlag = this->hitFlag;
|
|
}
|
|
DeleteThisEntity();
|
|
break;
|
|
case 3:
|
|
entity = (EntityWithHitFlag*)CreateObject(HITTABLE_LEVER, 1, 0);
|
|
if (entity != NULL) {
|
|
(entity->base).x.HALF.HI = (super->x.HALF.HI & 0xfff0) + 8;
|
|
(entity->base).y.HALF.HI = (super->y.HALF.HI & 0xfff0) + 8;
|
|
(entity->base).collisionLayer = super->collisionLayer;
|
|
entity->hitFlag = this->hitFlag;
|
|
}
|
|
DeleteThisEntity();
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool32 sub_08097348(u32 tilePosition) {
|
|
u32 index;
|
|
TileEntity* tileEntity = gSmallChests;
|
|
for (index = 0; index < ARRAY_COUNT(gSmallChests); index++, tileEntity++) {
|
|
if (tileEntity->tilePos == tilePosition) {
|
|
return CheckLocalFlag(tileEntity->localFlag);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|