Files
tmc/src/enemy/treeItem.c
T
2024-01-06 12:26:39 +01:00

119 lines
3.8 KiB
C

/**
* @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;
}