/** * @file treeItem.c * @ingroup Enemies * * @brief Tree Item enemy */ #include "enemy.h" #include "functions.h" #include "item.h" #include "object.h" typedef struct { /*0x00*/ Entity base; /*0x68*/ u8 unk_68; } TreeItemEntity; static bool32 ShouldSpawnTreeItem(TreeItemEntity*); const u8 gTreeItemDropTables[][16] = { { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, }; const u8 gTreeItemDrops[] = { 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x00, 0x00, 0x00, 0x00 }; #define FAIRY_INDEX 8 void TreeItem(TreeItemEntity* this) { Entity* itemEntity; if (super->action == 0) { super->action++; this->unk_68 = GetRandomByWeight(gTreeItemDropTables[super->type]); if (this->unk_68 > FAIRY_INDEX) { DeleteThisEntity(); } if (this->unk_68 < FAIRY_INDEX && GetInventoryValue(ITEM_KINSTONE_BAG) == 0) { this->unk_68 = FAIRY_INDEX; } } if (!ShouldSpawnTreeItem(this)) { return; } switch (this->unk_68) { case FAIRY_INDEX: itemEntity = CreateObject(FAIRY, 0x60, 0); if (itemEntity) { itemEntity->timer = 0; CopyPosition(super, itemEntity); } break; case 0 ...(FAIRY_INDEX - 1): itemEntity = CreateObject(GRAVEYARD_KEY, 0x7, gTreeItemDrops[this->unk_68]); if (itemEntity) { CopyPosition(super, itemEntity); itemEntity->y.HALF.HI += 16; itemEntity->z.HALF.HI = -32; } break; default: break; } EnemyDisableRespawn(super); DeleteThisEntity(); } static bool32 ShouldSpawnTreeItem(TreeItemEntity* this) { s32 diff; s32 expectedStateX, expectedStateY; s32 playerState; if (gPlayerEntity.base.action != PLAYER_BOUNCE) { return FALSE; } diff = gPlayerEntity.base.x.HALF.HI - super->x.HALF.HI; expectedStateX = 6; if (diff & 0x8000) { expectedStateX = 2; } diff += 40; if ((u16)diff >= 80) { return FALSE; } diff = gPlayerEntity.base.y.HALF.HI - super->y.HALF.HI; expectedStateY = 0; if (diff & 0x8000) { expectedStateY = 4; } diff += 40; if ((u16)diff >= 80) { return FALSE; } playerState = gPlayerEntity.base.animationState; if ((playerState == 0 && expectedStateY == 0) || (playerState == 4 && expectedStateY == 4) || (playerState == 6 && expectedStateX == 6) || (playerState == 2 && expectedStateX == 2)) { return TRUE; } return FALSE; }