ref: 6ccbc7fba30bab731577a0ce4512bec6ce420e8f
dir: /sprite_main.c/
#include "sprite_main.h"
#include "sprite.h"
#include "tagalong.h"
#include "ancilla.h"
#include "overworld.h"
#include "load_gfx.h"
#include "hud.h"
#include "dungeon.h"
#include "player.h"
#include "misc.h"
#define byte_7FFE01 (*(uint8*)(g_ram+0x1FE01))
static const int8 kSpriteKeese_Tab2[16] = {0, 8, 11, 14, 16, 14, 11, 8, 0, -8, -11, -14, -16, -14, -11, -8};
static const int8 kSpriteKeese_Tab3[16] = {-16, -14, -11, -8, 0, 8, 11, 14, 16, 14, 11, 8, 0, -9, -11, -14};
static const int8 kZazak_Yvel[4] = {0, 0, 16, -16};
static const int8 kFluteBoyAnimal_Xvel[4] = {16, -16, 0, 0};
static const int8 kDesertBarrier_Xv[4] = {16, -16, 0, 0};
static const int8 kDesertBarrier_Yv[4] = {0, 0, 16, -16};
static const uint8 kCrystalSwitchPal[2] = {2, 4};
static const uint8 kZazak_Dir2[8] = {2, 3, 2, 3, 0, 1, 0, 1};
#define moldorm_x_lo ((uint8*)(g_ram+0x1FC00))
#define moldorm_x_hi ((uint8*)(g_ram+0x1FC80))
#define moldorm_y_lo ((uint8*)(g_ram+0x1FD00))
#define moldorm_y_hi ((uint8*)(g_ram+0x1FD80))
static const int8 kBadPullDownSwitch_X[5] = {-4, 12, 0, -4, 4};
static const int8 kBadPullDownSwitch_Y[5] = {-3, -3, 0, 5, 5};
static const uint8 kBadPullDownSwitch_Char[5] = {0xd2, 0xd2, 0xc4, 0xe4, 0xe4};
static const uint8 kBadPullDownSwitch_Flags[5] = {0x40, 0, 0, 0x40, 0};
static const uint8 kBadPullDownSwitch_Ext[5] = {0, 0, 2, 2, 2};
static const uint8 kBadPullSwitch_Tab5[6] = {0, 1, 2, 3, 4, 5};
static const uint8 kBadPullSwitch_Tab4[12] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5};
static const uint8 kThief_Gfx[12] = {11, 8, 2, 5, 9, 6, 0, 3, 10, 7, 1, 4};
#define word_7FFE00 (*(uint16*)(g_ram+0x1FE00))
#define word_7FFE02 (*(uint16*)(g_ram+0x1FE02))
#define word_7FFE04 (*(uint16*)(g_ram+0x1FE04))
#define word_7FFE06 (*(uint16*)(g_ram+0x1FE06))
static const int16 kTutorialSoldier_X[20] = {
4, 0, -6, -6, 2, 0, 0, -7, -7, -7, 0, 0, 0xf, 0xf, 0xf, 6,
0xe, -4, 4, 0,
};
static const int16 kTutorialSoldier_Y[20] = {
0, -10, -4, 12, 12, 0, -9, -11, -3, 5, 0, -9, -11, -3, 5, -11,
5, 0, 0, -9,
};
static const uint8 kTutorialSoldier_Char[20] = {
0x46, 0x40, 0, 0x28, 0x29, 0x4e, 0x42, 0x39, 0x2a, 0x3a, 0x4e, 0x42, 0x39, 0x2a, 0x3a, 0x26,
0x38, 0x64, 0x64, 0x44,
};
static const uint8 kTutorialSoldier_Flags[20] = {
0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0x40, 0x40, 0x40, 0x40, 0,
0x40, 0, 0x40, 0,
};
static const uint8 kTutorialSoldier_Ext[20] = {
2, 2, 2, 0, 0, 2, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2,
0, 2, 2, 2,
};
static const uint8 kSprite_TutorialEntities_Tab[4] = {2, 1, 0, 3};
static const uint8 kSoldier_DirectionLockSettings[4] = {3, 2, 0, 1};
static const uint8 kWishPond_X[8] = {0, 4, 8, 12, 16, 20, 24, 0};
static const uint8 kWishPond_Y[8] = {0, 8, 16, 24, 32, 40, 4, 36};
const uint8 kWishPond2_OamFlags[76] = {
5, 0xff, 5, 5, 5, 5, 5, 1, 2, 1, 1, 1, 2, 2, 2, 4,
4, 4, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 4, 4, 2, 1,
6, 1, 2, 1, 2, 2, 1, 2, 2, 4, 1, 1, 4, 2, 1, 4,
2, 2, 4, 4, 4, 2, 1, 4, 1, 2, 2, 1, 2, 2, 1, 1,
4, 4, 1, 2, 2, 4, 4, 4, 2, 5, 2, 1,
};
static const uint8 kWishPondItemOffs[32] = {
0, 4, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 22, 23, 24, 25, 28, 30, 31, 32, 33, 33, 37, 40, 42, 42, 42, 42
};
static const uint8 kWishPondItemData[50] = {
0x3a, 0x3a, 0x3b, 0x3b, 0x0c, 0x2a, 0x0a, 0x27, 0x29, 0x0d, 0x07, 0x08, 0x0f, 0x10, 0x11, 0x12,
0x09, 0x13, 0x14, 0x4a, 0x21, 0x1d, 0x15, 0x18, 0x19, 0x31, 0x1a, 0x1a, 0x1b, 0x1c, 0x4b, 0x1e,
0x1f, 0x49, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x22, 0x23, 0x29, 0x16, 0x2b, 0x2c, 0x2d, 0x3d, 0x3c, 0x48
};
static const DrawMultipleData kUncleDraw_Table[48] = {
{ 0, -10, 0x0e00, 2},
{ 0, 0, 0x0c06, 2},
{ 0, -10, 0x0e00, 2},
{ 0, 0, 0x0c06, 2},
{ 0, -10, 0x0e00, 2},
{ 0, 0, 0x0c06, 2},
{ 0, -10, 0x0e02, 2},
{ 0, 0, 0x0c06, 2},
{ 0, -10, 0x0e02, 2},
{ 0, 0, 0x0c06, 2},
{ 0, -10, 0x0e02, 2},
{ 0, 0, 0x0c06, 2},
{ -7, 2, 0x0d07, 2},
{ -7, 2, 0x0d07, 2},
{ 10, 12, 0x8d05, 0},
{ 10, 4, 0x8d15, 0},
{ 0, -10, 0x0e00, 2},
{ 0, 0, 0x0c04, 2},
{ -7, 1, 0x0d07, 2},
{ -7, 1, 0x0d07, 2},
{ 10, 13, 0x8d05, 0},
{ 10, 5, 0x8d15, 0},
{ 0, -9, 0x0e00, 2},
{ 0, 1, 0x4c04, 2},
{ -7, 8, 0x8d05, 0},
{ 1, 8, 0x8d06, 0},
{ 0, -10, 0x0e02, 2},
{ -6, -1, 0x4d07, 2},
{ 0, 0, 0x0c23, 2},
{ 0, 0, 0x0c23, 2},
{ -9, 7, 0x8d05, 0},
{ -1, 7, 0x8d06, 0},
{ 0, -9, 0x0e02, 2},
{ -6, 0, 0x4d07, 2},
{ 0, 1, 0x0c25, 2},
{ 0, 1, 0x0c25, 2},
{-10, -17, 0x0d07, 2},
{ 15, -12, 0x8d15, 0},
{ 15, -4, 0x8d05, 0},
{ 0, -28, 0x0e08, 2},
{ -8, -19, 0x0c20, 2},
{ 8, -19, 0x4c20, 2},
{ 0, -28, 0x0e08, 2},
{ 0, -28, 0x0e08, 2},
{ -8, -19, 0x0c20, 2},
{ 8, -19, 0x4c20, 2},
{ -8, -19, 0x0c20, 2},
{ 8, -19, 0x4c20, 2},
};
static const uint8 kUncleDraw_Dma3[8] = {8, 8, 0, 0, 6, 6, 0, 0};
static const uint8 kUncleDraw_Dma4[8] = {0, 0, 0, 0, 4, 4, 0, 0x8b}; // wtf
static const uint8 kUncle_LeaveHouse_Delay[2] = {64, 224};
static const uint8 kUncle_LeaveHouse_Dir[2] = {2, 1};
static const int8 kUncle_LeaveHouse_Xvel[4] = {0, 0, -12, 12};
static const int8 kUncle_LeaveHouse_Yvel[4] = {-12, 12, 0, 0};
static const DrawMultipleData kPriest_Dmd[20] = {
{ 0, -8, 0x0e20, 2},
{ 0, 0, 0x0e26, 2},
{ 0, -8, 0x0e20, 2},
{ 0, 0, 0x4e26, 2},
{ 0, -8, 0x0e0e, 2},
{ 0, 0, 0x0e24, 2},
{ 0, -8, 0x0e0e, 2},
{ 0, 0, 0x0e24, 2},
{ 0, -8, 0x0e22, 2},
{ 0, 0, 0x0e28, 2},
{ 0, -8, 0x0e22, 2},
{ 0, 0, 0x0e2a, 2},
{ 0, -8, 0x4e22, 2},
{ 0, 0, 0x4e28, 2},
{ 0, -8, 0x4e22, 2},
{ 0, 0, 0x4e2a, 2},
{-7, 1, 0x0e0a, 2},
{ 3, 3, 0x0e0c, 2},
{-7, 1, 0x0e0a, 2},
{ 3, 3, 0x0e0c, 2},
};
static const DrawMultipleData kSageMantle_Dmd[4] = {
{0, 0, 0x162c, 2},
{16, 0, 0x562c, 2},
{0, 16, 0x062e, 2},
{16, 16, 0x462e, 2},
};
static const uint8 kCrystalMaiden_Dma[16] = {0x20, 0xc0, 0x20, 0xc0, 0, 0xa0, 0, 0xa0, 0x40, 0x80, 0x40, 0x60, 0x40, 0x80, 0x40, 0x60};
static const DrawMultipleData kCrystalMaiden_SpriteData[16] = {
{1, -7, 0x0120, 2},
{1, 3, 0x0122, 2},
{1, -7, 0x0120, 2},
{1, 3, 0x4122, 2},
{1, -7, 0x0120, 2},
{1, 3, 0x0122, 2},
{1, -7, 0x0120, 2},
{1, 3, 0x4122, 2},
{1, -7, 0x0120, 2},
{1, 3, 0x0122, 2},
{1, -7, 0x0120, 2},
{1, 3, 0x0122, 2},
{1, -7, 0x4120, 2},
{1, 3, 0x4122, 2},
{1, -7, 0x4120, 2},
{1, 3, 0x4122, 2},
};
static const int8 kZelda_Xvel[4] = {0, 0, -9, 9};
static const int8 kZelda_Yvel[4] = {-9, 9, 0, 0};
static const int8 kHeartRefill_AccelX[2] = {1, -1};
static const int8 kHeartRefill_VelTarget[2] = {10, -10};
static const DrawMultipleData kFakeSword_Dmd[2] = {
{4, 0, 0x00f4, 0},
{4, 8, 0x00f5, 0},
};
static const uint8 kThrowableScenery_Char[12] = {0x42, 0x44, 0x46, 0, 0x46, 0x44, 0x42, 0x44, 0x44, 0, 0x46, 0x44};
const uint8 kThrowableScenery_Flags[9] = { 0xc, 0xc, 0xc, 0, 0, 0, 0xb0, 0x08, 0xb4 };
static const int16 kThrowableScenery_DrawLarge_X[4] = {-8, 8, -8, 8};
static const int16 kThrowableScenery_DrawLarge_Y[4] = {-14, -14, 2, 2};
static const uint8 kThrowableScenery_DrawLarge_Flags[4] = {0, 0x40, 0x80, 0xc0};
static const int16 kThrowableScenery_DrawLarge_X2[3] = {-6, 0, 6};
static const uint8 kThrowableScenery_DrawLarge_OamFlags[2] = {0xc, 0};
static const int8 kScatterDebris_X[4] = {-8, 8, -8, 8};
static const int8 kScatterDebris_Y[4] = {-8, -8, 8, 8};
static const uint8 kMovableMantle_X[6] = {0, 0x10, 0x20, 0, 0x10, 0x20};
static const uint8 kMovableMantle_Y[6] = {0, 0, 0, 0x10, 0x10, 0x10};
static const uint8 kMovableMantle_Char[6] = {0xc, 0xe, 0xc, 0x2c, 0x2e, 0x2c};
static const uint8 kMovableMantle_Flags[6] = {0x31, 0x31, 0x71, 0x31, 0x31, 0x71};
static const uint8 kSprite_SimplifiedTileAttr[256] = {
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 3, 3, 3,
0, 0, 0, 0, 0, 0, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
static const uint8 kSoldier_Gfx[4] = {8, 0, 12, 5};
static const uint8 kSoldier_Delay[4] = {0x60, 0xc0, 0xff, 0x40};
static const uint8 kSoldier_Draw1_Char[4] = {0x42, 0x42, 0x40, 0x44};
static const uint8 kSoldier_Draw1_Flags[4] = {0x40, 0, 0, 0};
static const int8 kSoldier_Draw1_Yd[26] = {
7, 8, 7, 8, 8, 7, 8, 7, 8, 7, 8, 8, 7, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
};
static const int8 kSoldier_Draw2_Xd[104] = {
-4, 4, 10, 10, -4, 4, 10, 10, -4, 4, 10, 10, -4, 4, 10, 10,
-4, -4, 0, 0, -4, -4, 0, 0, -3, -3, 0, 0, -3, -3, -4, 4,
-3, -3, -4, 4, -3, -3, -4, 4, -3, -3, -4, 4, 12, 12, 0, 0,
12, 12, 0, 0, 11, 11, 0, 0, -4, 4, 0, 0, -4, 4, 0, 0,
-4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-4, 4, 0, 0, -4, 4, 0, 0, -4, 4, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
static const int8 kSoldier_Draw2_Yd[104] = {
0, 0, 2, 10, 0, 0, 2, 10, 0, 0, 1, 9, 0, 0, 2, 10,
-2, 6, 1, 1, -2, 6, 2, 2, -2, 6, 1, 1, -5, 3, 0, 0,
-4, 4, 0, 0, -4, 4, 0, 0, -5, 3, 0, 0, -2, 6, 1, 1,
-2, 6, 2, 2, -2, 6, 1, 1, 0, 0, 8, 8, 0, 0, 8, 8,
0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8,
0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8,
0, 0, 8, 8, 0, 0, 8, 8,
};
static const uint8 kSoldier_Draw2_Char[104] = {
0x48, 0x49, 0x6d, 0x7d, 0x49, 0x48, 0x6d, 0x7d, 0x46, 0x46, 0x6d, 0x7d, 0x4b, 0x46, 0x6d, 0x7d,
0x4d, 0x5d, 0x4e, 0x4e, 0x4d, 0x5d, 0x60, 0x60, 0x4d, 0x5d, 0x62, 0x62, 0x6d, 0x7d, 0x64, 0x64,
0x6d, 0x7d, 0x66, 0x67, 0x6d, 0x7d, 0x67, 0x66, 0x6d, 0x7d, 0x64, 0x69, 0x4d, 0x5d, 0x4e, 0x4e,
0x4d, 0x5d, 0x60, 0x60, 0x4d, 0x5d, 0x62, 0x62, 2, 3, 0x20, 0x20, 2, 0xc, 0x20, 0x20,
2, 0xc, 0x20, 0x20, 8, 8, 0x20, 0x20, 0xe, 0xe, 0x20, 0x20, 0xe, 0xe, 0x20, 0x20,
5, 6, 0x20, 0x20, 0x22, 6, 0x20, 0x20, 0x22, 6, 0x20, 0x20, 8, 8, 0x20, 0x20,
0xe, 0xe, 0x20, 0x20, 0xe, 0xe, 0x20, 0x20,
};
static const uint8 kSoldier_Draw2_Flags[104] = {
0, 0, 0, 0, 0x40, 0x40, 0, 0, 0, 0x40, 0, 0, 0, 0x40, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40,
0, 0, 0, 0, 0, 0, 0x40, 0x40, 0, 0, 0, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
};
static const uint8 kSoldier_Draw2_Ext[104] = {
2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0,
0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2,
0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2,
0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
};
static const uint8 kSoldier_Draw2_OamIdx[4] = {12, 12, 12, 4};
static const int8 kSoldier_Draw3_Xd[28] = {
-3, -3, -4, -4, -4, -4, -4, -4, -11, -3, -11, -3, -16, -8, 12, 12,
12, 12, 12, 12, 12, 12, 21, 13, 21, 13, 24, 16,
};
static const int8 kSoldier_Draw3_Yd[28] = {
11, 19, 11, 19, 10, 18, 14, 22, 8, 8, 8, 8, 6, 6, -10, -2,
-9, -1, -9, -1, -16, -8, 8, 8, 8, 8, 6, 6,
};
static const uint8 kSoldier_Draw3_Char[28] = {
0x7b, 0x6b, 0x7b, 0x6b, 0x7b, 0x6b, 0x7b, 0x6b, 0x6c, 0x7c, 0x6c, 0x7c, 0x6c, 0x7c, 0x6b, 0x7b,
0x6b, 0x7b, 0x6b, 0x7b, 0x6b, 0x7b, 0x6c, 0x7c, 0x6c, 0x7c, 0x6c, 0x7c,
};
static const uint8 kSoldier_Draw3_Flags[28] = {
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
};
static const uint8 kSoldier_Draw3_OamIdx[4] = {4, 4, 4, 20};
static const int8 kSoldier_Xvel[4] = {8, -8, 0, 0};
static const int8 kSoldier_Yvel[4] = {0, 0, 8, -8};
static const uint8 kSoldier_Gfx2[32] = {
11, 12, 13, 12, 4, 5, 6, 5, 0, 1, 2, 3, 7, 8, 9, 10,
17, 18, 17, 18, 7, 8, 7, 8, 3, 4, 3, 4, 13, 14, 13, 14,
};
static const int8 kSoldierB_Xvel[8] = {1, 1, -1, -1, -1, -1, 1, 1};
static const int8 kSoldierB_Yvel[8] = {-1, 1, 1, -1, -1, 1, 1, -1};
static const int8 kSoldierB_Xvel2[8] = {8, 0, -8, 0, -8, 0, 8, 0};
static const int8 kSoldierB_Yvel2[8] = {0, 8, 0, -8, 0, 8, 0, -8};
static const uint8 kSoldierB_Dir[8] = {0, 2, 1, 3, 1, 2, 0, 3};
static const uint8 kSoldierB_Mask2[8] = {1, 4, 2, 8, 2, 4, 1, 8};
static const uint8 kSoldierB_Mask[8] = {8, 1, 4, 2, 8, 2, 4, 1};
static const uint8 kSoldierB_NextB2[8] = {1, 2, 3, 0, 5, 6, 7, 4};
static const uint8 kSoldierB_NextB[8] = {3, 0, 1, 2, 7, 4, 5, 6};
static const uint8 kSoldier_HeadDirs[32] = {
0, 2, 2, 2, 0, 3, 3, 3, 1, 3, 3, 3, 1, 2, 2, 2,
2, 0, 0, 0, 2, 1, 1, 1, 3, 1, 1, 1, 3, 0, 0, 0,
};
static const uint8 kSoldier_Tab1[4] = {13, 13, 12, 12};
static const uint8 kSoldier_DrawShadow[4] = {0xc, 0xc, 0xa, 0xa};
static const int8 kSoldier_SetTowardsVel[6] = {14, -14, 0, 0, 14, -14};
static const uint8 kSprite_SpawnProbeStaggered_Tab[4] = {0x10, 0x30, 0, 0x20};
static const int8 kSpawnProbe_Xvel[64] = {
-16, -16, -16, -16, -16, -16, -16, -16, -16, -14, -12, -10, -8, -6, -4, -2,
0, 2, 4, 6, 8, 10, 12, 14, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 14, 12, 10, 8, 6, 4, 2, 0,
-2, -4, -6, -8, -10, -12, -14, -16, -16, -16, -16, -16, -16, -16, -16, -16,
};
static const int8 kSpawnProbe_Yvel[64] = {
0, 2, 4, 6, 8, 10, 12, 14, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 14, 12, 10, 8, 6, 4, 2, 0,
-2, -4, -6, -8, -10, -12, -14, -16, -16, -16, -16, -16, -16, -16, -16, -16,
-16, -16, -16, -16, -16, -16, -16, -16, -14, -12, -10, -8, -6, -4, -2, 0,
};
int ctr;
bool foo = false;
static const uint8 kChainBallTrooper_Tab1[4] = {0x0d, 0x60, 0x22, 0x10}; // wtf
static const uint8 kFlailTrooperGfx[32] = {
0x10, 0x11, 0x12, 0x13, 0x10, 0x11, 0x12, 0x13, 6, 7, 8, 9, 6, 7, 8, 9,
0, 1, 2, 3, 0, 1, 4, 5, 0xa, 0xb, 0xc, 0xd, 0xa, 0xb, 0xe, 0xf,
};
static const uint8 kJavelinTrooper_Tab2[64] = {
25, 25, 24, 24, 23, 23, 23, 23, 19, 19, 18, 18, 17, 17, 17, 17,
16, 16, 15, 15, 14, 14, 14, 14, 22, 22, 21, 21, 20, 20, 20, 20,
20, 20, 18, 18, 18, 16, 16, 16, 21, 21, 8, 8, 8, 6, 6, 6,
22, 22, 4, 4, 4, 3, 3, 3, 23, 23, 15, 15, 15, 11, 11, 11,
};
static const int8 kSprite_Recruit_Xvel[8] = {12, -12, 0, 0, 18, -18, 0, 0};
static const int8 kSprite_Recruit_Yvel[8] = {0, 0, 0xc, -0xc, 0, 0, 0x12, -0x12};
static const int8 kSprite_Recruit_Gfx[8] = {0, 2, 4, 6, 1, 3, 5, 7};
static const uint8 kRecruit_Moving_HeadDir[8] = {2, 3, 2, 3, 0, 1, 0, 1};
static const int16 kRecruit_Draw_X[8] = {2, 2, -2, -2, 0, 0, 0, 0};
static const uint8 kRecruit_Draw_Char[8] = {0x8a, 0x8c, 0x8a, 0x8c, 0x86, 0x88, 0x8e, 0xa0};
static const uint8 kRecruit_Draw_Flags[8] = {0x40, 0x40, 0, 0, 0, 0, 0, 0};
static const uint8 kSprite_Zora_SurfacingGfx[16] = {4, 3, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, 0};
static const uint8 kChainBallTrooperHead_Char[4] = {2, 2, 0, 4};
static const uint8 kChainBallTrooperHead_Flags[4] = {0x40, 0, 0, 0};
static const int8 kFlailTrooperBody_X[72] = {
-4, 4, 12, -4, 4, 13, -4, 4, 13, -4, 4, 13, -4, 4, 13, -4,
4, 13, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 4, -4, 4,
-6, -4, 4, -5, -4, 4, -5, -4, 4, -6, -4, 4, -5, -4, 4, -6,
0, 0, 4, 0, 0, 3, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0,
0, 0, -4, 4, 4, -4, 4, 4,
};
static const int8 kFlailTrooperBody_Y[72] = {
0, 0, -4, 0, 0, -4, 0, 0, -3, 0, 0, -2, 0, 0, -3, 0,
0, -2, 0, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 2, 0, 0,
-2, 0, 0, -2, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,
0, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
static const uint8 kFlailTrooperBody_Char[72] = {
0x46, 6, 0x2f, 0x46, 6, 0x2f, 0x48, 0xd, 0x2f, 0x48, 0xd, 0x2f, 0x49, 0xc, 0x2f, 0x49,
0xc, 0x2f, 8, 8, 0x2f, 8, 8, 0x2f, 0x22, 0x22, 0x2f, 0x22, 0x22, 0x2f, 0xa, 0x64,
0x2f, 0xa, 0x64, 0x2f, 0x2c, 0x67, 0x2f, 0x2c, 0x67, 0x2f, 0x2d, 0x66, 0x2f, 0x2d, 0x66, 0x2f,
8, 8, 0x2f, 8, 8, 0x2f, 0x22, 0x22, 0x2f, 0x22, 0x22, 0x2f, 0x62, 0x62, 0x62, 0x62,
0x62, 0x62, 0x46, 0x4b, 0x4b, 0x69, 0x64, 0x64,
};
static const uint8 kFlailTrooperBody_Flags[72] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0x40, 0, 0x40,
0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40,
0x40, 0, 0x40, 0x40, 0, 0, 0x40, 0, 0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0,
0, 0, 0, 0x40, 0x40, 0, 0x40, 0x40,
};
static const uint8 kFlailTrooperBody_Ext[72] = {
2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2,
2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2,
0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0,
2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
};
static const uint8 kFlailTrooperBody_Num[24] = {
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 1, 1, 1, 1,
};
static const uint8 kFlailTrooperBody_SprOffs[24] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 8, 8, 8, 8,
};
const uint16 kSinusLookupTable[256] = {
0, 3, 6, 9, 12, 15, 18, 21, 25, 28, 31, 34, 37, 40, 40, 46,
49, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95,
97, 100, 103, 106, 109, 112, 115, 117, 120, 123, 126, 128, 131, 134, 136, 139,
142, 144, 147, 149, 152, 155, 157, 159, 162, 164, 167, 169, 171, 174, 176, 178,
181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211,
212, 214, 216, 217, 219, 221, 222, 224, 225, 227, 228, 230, 231, 232, 234, 235,
236, 237, 238, 239, 241, 242, 243, 244, 244, 245, 246, 247, 248, 249, 249, 250,
251, 251, 252, 252, 253, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255,
256, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 252, 251,
251, 250, 249, 249, 248, 247, 246, 245, 244, 244, 243, 242, 241, 239, 238, 237,
236, 235, 234, 232, 231, 230, 228, 227, 225, 224, 222, 221, 219, 217, 216, 214,
212, 211, 209, 207, 205, 203, 201, 199, 197, 195, 193, 191, 189, 187, 185, 183,
181, 178, 176, 174, 171, 169, 167, 164, 162, 159, 157, 155, 152, 149, 147, 144,
142, 139, 136, 134, 131, 128, 126, 123, 120, 117, 115, 112, 109, 106, 103, 100,
97, 95, 92, 89, 86, 83, 80, 77, 74, 71, 68, 65, 62, 59, 56, 53,
49, 46, 43, 40, 37, 34, 31, 28, 25, 21, 18, 15, 12, 9, 6, 3,
};
static const uint8 kFlailTrooperWeapon_Tab4[4] = {0x33, 0x66, 0x99, 0xcc};
static const uint8 kFlailTrooperWeapon_Tab0[32] = {
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e,
0x30, 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1e, 0x1c, 0x1a, 0x18, 0x16, 0x14, 0x12,
};
static const int8 kFlailTrooperWeapon_Tab1[4] = {4, 4, 12, -5};
static const int8 kFlailTrooperWeapon_Tab2[4] = {-2, -2, -6, -4};
static const uint8 kFlailTrooperAttackDir[4] = {3, 1, 2, 0};
static const uint8 kSprite_WarpVortex_Flags[4] = {0, 0x40, 0xc0, 0x80};
static const int8 kSpriteRope_Gfx[8] = {0, 0, 2, 3, 2, 3, 1, 1};
static const int8 kSpriteRope_Flags[8] = {0, 0x40, 0, 0, 0x40, 0x40, 0, 0x40};
static const int8 kSpriteRope_Tab1[8] = {4, 5, 2, 3, 0, 1, 6, 7};
static const int8 kSpriteRope_Xvel[8] = {8, -8, 0, 0, 16, -16, 0, 0};
static const int8 kSpriteRope_Yvel[8] = {0, 0, 8, -8, 0, 0, 0x10, -0x10};
static const int8 kSpriteRope_Tab0[4] = {2, 3, 1, 0};
static const uint8 kSpawnBee_InitDelay[4] = {64, 64, 255, 255};
static const int8 kSpawnBee_InitVel[8] = {15, 5, -5, -15, 20, 10, -10, -20};
static const DrawMultipleData kLargeShadow_Dmd[15] = {
{-6, 19, 0x086c, 2},
{ 0, 19, 0x086c, 2},
{ 6, 19, 0x086c, 2},
{-5, 19, 0x086c, 2},
{ 0, 19, 0x086c, 2},
{ 5, 19, 0x086c, 2},
{-4, 19, 0x086c, 2},
{ 0, 19, 0x086c, 2},
{ 4, 19, 0x086c, 2},
{-3, 19, 0x086c, 2},
{ 0, 19, 0x086c, 2},
{ 3, 19, 0x086c, 2},
{-2, 19, 0x086c, 2},
{ 0, 19, 0x086c, 2},
{ 2, 19, 0x086c, 2},
};
static const uint8 kHelmasaur_Tab0[32] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 2, 1,
};
static const uint8 kFluteBoyAnimal_OamFlags[2] = {0x40, 0};
static const uint8 kFluteBoyAnimal_Gfx[3] = {0, 1, 2};
static const uint8 kGibo_OamFlags[4] = {0, 0x40, 0xc0, 0x80};
static const uint8 kGibo_OamFlags2[2] = {11, 7};
#define chainchomp_x_hist ((uint16*)(g_ram+0x1FC00))
#define chainchomp_y_hist ((uint16*)(g_ram+0x1FD00))
static const uint8 kBlindHead_Draw_Char[16] = {0x86, 0x86, 0x84, 0x82, 0x80, 0x82, 0x84, 0x86, 0x86, 0x86, 0x88, 0x8a, 0x8c, 0x8a, 0x88, 0x86};
static const uint8 kBlindHead_Draw_Flags[16] = {0, 0, 0, 0, 0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0, 0, 0, 0};
static const uint8 kGanon_G_Func2[16] = { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
static const int8 kGanon_Draw_X[204] = {
18, -8, 8, -8, 8, -18, -18, 18, -8, 8, -8, 8, 18, -8, 8, -8,
8, -18, -18, 18, -8, 8, -8, 8, 16, -8, 8, -8, 8, -18, -18, 16,
-8, 8, -11, 11, 16, -8, 8, -8, 8, -18, -18, 16, -8, 8, -11, 11,
16, -8, 8, -8, 8, -18, -18, 16, -8, 8, -11, 11, 18, -8, 8, -8,
8, -18, -18, 18, -8, 8, -8, 8, 18, -8, 8, -8, 8, -18, -18, 18,
-8, 8, -8, 8, 18, -8, 8, -8, 8, -18, -18, 18, -8, 8, -11, 11,
-8, 8, -8, 8, -8, 8, -8, 8, -18, -18, 18, 18, -8, 8, -8, 8,
-8, 8, -8, 8, -18, -18, 18, 18, -8, 8, -8, 8, -8, 8, -10, 10,
-18, -18, 18, 18, -8, 8, -8, 8, -8, 8, -10, 10, -18, -18, 18, 18,
-8, 8, -8, 8, -8, 8, -10, 10, -18, -18, 18, 18, -8, 8, -8, 8,
-8, 8, -8, 8, -18, -18, 18, 18, -8, 8, -8, 8, -8, 8, -8, 8,
-18, -18, 18, 18, -7, -8, 8, -8, 8, -9, 8, -14, -14, -8, 8, 8,
-8, 8, -8, 8, -18, -18, 18, 18, -8, 8, -11, 11,
};
static const int8 kGanon_Draw_Y[204] = {
-8, -16, -16, -13, -13, -9, -1, -16, 3, 3, 8, 8, -8, -16, -16, -13,
-13, -9, -1, -16, 3, 3, 8, 8, 5, -10, -10, -13, -13, -7, 1, -3,
3, 3, 8, 8, 5, -10, -10, -13, -13, -7, 1, -3, 3, 3, 8, 8,
5, -10, -10, -13, -13, -7, 1, -3, 3, 3, 8, 8, -1, -16, -16, -13,
-13, -9, -1, -9, 3, 3, 8, 8, -10, -16, -16, -13, -13, -18, -10, -18,
3, 3, 8, 8, 1, -10, -10, -13, -13, -7, 1, -7, 3, 3, 8, 8,
-12, -12, 4, 4, -18, -18, 10, 10, -16, -8, -4, 4, -12, -12, 4, 4,
-18, -18, 10, 10, -16, -8, -4, 4, -12, -12, 4, 4, -12, -12, 10, 10,
-4, 4, -4, 4, -12, -12, 4, 4, -12, -12, 10, 10, -4, 4, -4, 4,
-12, -12, 4, 4, -12, -12, 10, 10, -4, 4, -4, 4, -12, -12, 4, 4,
-18, -18, 10, 10, -4, 4, -4, 4, -12, -12, 4, 4, -18, -18, 10, 10,
-16, -8, -16, -8, -7, -12, -12, 4, 4, 7, 13, -11, -4, -16, -16, -16,
-10, -10, -13, -13, -7, -7, -7, -7, 3, 3, 8, 8,
};
static const uint8 kGanon_Draw_Char[204] = {
0x16, 0, 0, 2, 2, 8, 0x18, 6, 0x22, 0x22, 0x20, 0x20, 0x46, 0, 0, 2,
2, 8, 0x18, 0x36, 0x22, 0x22, 0x20, 0x20, 0x1a, 0, 0, 4, 4, 0x38, 0x48, 0xa,
0x24, 0x24, 0x20, 0x20, 0x1a, 0x40, 0x42, 4, 4, 0x38, 0x48, 0xa, 0x24, 0x24, 0x20, 0x20,
0x1a, 0x42, 0x40, 4, 4, 0x38, 0x48, 0xa, 0x24, 0x24, 0x20, 0x20, 0x18, 0, 0, 2,
2, 8, 0x18, 8, 0x22, 0x22, 0x20, 0x20, 0x16, 0x6a, 0x6a, 0xe, 0xe, 6, 0x16, 6,
0x22, 0x22, 0x20, 0x20, 0x48, 0, 0, 4, 4, 0x38, 0x48, 0x38, 0x24, 0x24, 0x20, 0x20,
0x4e, 0x4e, 0x6e, 0x6e, 0x6c, 0x6c, 0xa2, 0xa2, 0xc, 0x1c, 0x3c, 0x4c, 0x4e, 0x4e, 0x6e, 0x6e,
0x6c, 0x6c, 0xa2, 0xa2, 0x3a, 0x4a, 0x3c, 0x4c, 0x84, 0x84, 0xa4, 0xa4, 0xa0, 0xa0, 0xa2, 0xa2,
0x3c, 0x4c, 0x3c, 0x4c, 0x84, 0x84, 0xa4, 0xa4, 0x80, 0x82, 0xa2, 0xa2, 0x3c, 0x4c, 0x3c, 0x4c,
0x84, 0x84, 0xa4, 0xa4, 0x82, 0x80, 0xa2, 0xa2, 0x3c, 0x4c, 0x3c, 0x4c, 0x4e, 0x4e, 0x6e, 0x6e,
0x6c, 0x6c, 0xa2, 0xa2, 0x3c, 0x4c, 0x3c, 0x4c, 0x4e, 0x4e, 0x6e, 0x6e, 0x6c, 0x6c, 0xa2, 0xa2,
0xc, 0x1c, 0xc, 0x1c, 0xe0, 0xc6, 0xc8, 0xe6, 0xe8, 0x20, 0x20, 8, 0x18, 0xc0, 0xc2, 0xc2,
0, 0, 0xce, 0xce, 0xec, 0xec, 0xec, 0xec, 0xee, 0xee, 0xc4, 0xc4,
};
static const uint8 kGanon_Draw_Flags[204] = {
0x4c, 0xc, 0x4c, 0xa, 0x4a, 0xc, 0xc, 0x4c, 0xa, 0x4a, 0xc, 0x4c, 0x4c, 0xc, 0x4c, 0xa,
0x4a, 0xc, 0xc, 0x4c, 0xa, 0x4a, 0xc, 0x4c, 0x4c, 0xc, 0x4c, 0xa, 0x4a, 0xc, 0xc, 0x4c,
0xa, 0x4a, 0xc, 0x4c, 0x4c, 0xc, 0xc, 0xa, 0x4a, 0xc, 0xc, 0x4c, 0xa, 0x4a, 0xc, 0x4c,
0x4c, 0x4c, 0x4c, 0xa, 0x4a, 0xc, 0xc, 0x4c, 0xa, 0x4a, 0xc, 0x4c, 0x4c, 0xc, 0x4c, 0xa,
0x4a, 0xc, 0xc, 0x4c, 0xa, 0x4a, 0xc, 0x4c, 0x4c, 0xc, 0x4c, 0xa, 0x4a, 0xc, 0xc, 0x4c,
0xa, 0x4a, 0xc, 0x4c, 0x4c, 0xc, 0x4c, 0xa, 0x4a, 0xc, 0xc, 0x4c, 0xa, 0x4a, 0xc, 0x4c,
0xa, 0x4a, 0xa, 0x4a, 0xc, 0x4c, 0xc, 0x4c, 0xc, 0xc, 0x4c, 0x4c, 0xa, 0x4a, 0xa, 0x4a,
0xc, 0x4c, 0xc, 0x4c, 0xc, 0xc, 0x4c, 0x4c, 0xa, 0x4a, 0xa, 0x4a, 0xc, 0x4c, 0xc, 0x4c,
0xc, 0xc, 0x4c, 0x4c, 0xa, 0x4a, 0xa, 0x4a, 0xc, 0xc, 0xc, 0x4c, 0xc, 0xc, 0x4c, 0x4c,
0xa, 0x4a, 0xa, 0x4a, 0x4c, 0x4c, 0xc, 0x4c, 0xc, 0xc, 0x4c, 0x4c, 0xa, 0x4a, 0xa, 0x4a,
0xc, 0x4c, 0xc, 0x4c, 0xc, 0xc, 0x4c, 0x4c, 0xa, 0x4a, 0xa, 0x4a, 0xc, 0x4c, 0xc, 0x4c,
0xc, 0xc, 0x4c, 0x4c, 0xc, 0xa, 0xa, 0xa, 0xa, 0xc, 0x4c, 0xc, 0xc, 0xc, 0xc, 0xc,
0xc, 0x4c, 0xa, 0x4a, 0xc, 0xc, 0x4c, 0x4c, 0xa, 0x4a, 0xc, 0x4c,
};
static const uint8 kGanon_Draw_Char2[12] = { 0x40, 0x42, 0, 0, 0x42, 0x40, 0x82, 0x80, 0xa0, 0xa0, 0x80, 0x82 };
static const uint8 kGanon_Draw_Flags2[12] = { 0, 0, 0, 0x40, 0x40, 0x40, 0x40, 0x40, 0, 0x40, 0, 0 };
static HandlerFuncK *const kSpriteActiveRoutines[243] = {
&Sprite_Raven,
&Sprite_01_Vulture_bounce,
&Sprite_02_StalfosHead,
NULL,
&Sprite_PullSwitch_bounce,
&Sprite_PullSwitch_bounce,
&Sprite_PullSwitch_bounce,
&Sprite_PullSwitch_bounce,
&Sprite_08_Octorok,
&Sprite_09_Moldorm_bounce,
&Sprite_08_Octorok,
&Sprite_0B_Cucco,
&Sprite_0C_OctorokStone,
&Sprite_0D_Buzzblob,
&Sprite_0E_Snapdragon,
&Sprite_0F_Octoballoon,
&Sprite_10_OctoballoonBaby,
&Sprite_11_Hinox,
&Sprite_12_Moblin,
&Sprite_13_MiniHelmasaur,
&Sprite_14_ThievesTownGrate_bounce,
&Sprite_15_Antifairy,
&Sprite_16_Elder_bounce,
&Sprite_17_Hoarder,
&Sprite_18_MiniMoldorm,
&Sprite_19_Poe,
&Sprite_1A_Smithy,
&Sprite_1B_Arrow,
&Sprite_1C_Statue,
&Sprite_1D_FluteQuest,
&Sprite_1E_CrystalSwitch,
&Sprite_1F_SickKid,
&Sprite_20_Sluggula,
&Sprite_21_WaterSwitch,
&Sprite_22_Ropa,
&Sprite_23_RedBari,
&Sprite_23_RedBari,
&Sprite_25_TalkingTree_bounce,
&Sprite_26_HardhatBeetle,
&Sprite_27_Deadrock,
&Sprite_28_DarkWorldHintNPC,
&Sprite_HumanMulti_1,
&Sprite_SweepingLady,
&Sprite_2B_Hobo,
&Sprite_Lumberjacks,
&Sprite_2D_TelepathicTile_bounce,
&Sprite_2E_FluteKid,
&Sprite_MazeGameLady,
&Sprite_MazeGameGuy,
&Sprite_FortuneTeller,
&Sprite_QuarrelBros,
&Sprite_33_RupeePull_bounce,
&Sprite_YoungSnitchLady,
&Sprite_InnKeeper,
&Sprite_Witch,
&Sprite_37_Waterfall_bounce,
&Sprite_38_EyeStatue_bounce,
&Sprite_39_Locksmith,
&Sprite_3A_MagicBat_bounce,
&Sprite_DashItem,
&Sprite_TroughBoy,
&Sprite_OldSnitchLady,
&Sprite_17_Hoarder,
&Sprite_TutorialGuardOrBarrier_bounce,
&Sprite_TutorialGuardOrBarrier_bounce,
// Trampoline 48 entries
&Sprite_41_BlueGuard,
&Sprite_41_BlueGuard,
&Sprite_41_BlueGuard,
&Sprite_44_BluesainBolt,
&Sprite_45_UsainBolt,
&Sprite_46_BlueArcher,
&Sprite_47_GreenBushGuard,
&Sprite_48_RedJavelinGuard,
&Sprite_49_RedBushGuard,
&Sprite_4A_BombGuard,
&Sprite_4B_GreenKnifeGuard,
&Sprite_4C_Geldman,
&Sprite_4D_Toppo,
&Sprite_4E_Popo,
&Sprite_4E_Popo,
&Sprite_50_Cannonball,
&Sprite_51_ArmosStatue,
&Sprite_52_KingZora,
&Sprite_53_ArmosKnight,
&Sprite_54_Lanmolas,
&Sprite_55_Zora,
&Sprite_56_WalkingZora,
&Sprite_57_DesertStatue,
&Sprite_58_Crab,
&Sprite_59_LostWoodsBird,
&Sprite_5A_LostWoodsSquirrel,
&Sprite_5B_Spark_Clockwise,
&Sprite_5B_Spark_Clockwise,
&Sprite_5D_Roller_VerticalDownFirst,
&Sprite_5D_Roller_VerticalDownFirst,
&Sprite_5D_Roller_VerticalDownFirst,
&Sprite_5D_Roller_VerticalDownFirst,
&Sprite_61_Beamos,
&Sprite_62_MasterSword,
&Sprite_63_DebirandoPit,
&Sprite_64_Debirando,
&Sprite_65_ArcheryGame,
&Sprite_66_WallCannonVerticalLeft,
&Sprite_66_WallCannonVerticalLeft,
&Sprite_66_WallCannonVerticalLeft,
&Sprite_66_WallCannonVerticalLeft,
&Sprite_6A_BallNChain,
&Sprite_CannonTrooper,
&Sprite_6C_MirrorPortal,
&Sprite_6D_Rat,
&Sprite_6E_Rope,
&Sprite_6F_Keese,
&Sprite_70_KingHelmasaurFireball_bounce,
&Sprite_71_Leever,
&Sprite_72_FairyPond,
&Sprite_73_UncleAndPriest_bounce,
&Sprite_RunningMan,
&Sprite_BottleVendor,
&Sprite_76_Zelda,
&Sprite_15_Antifairy,
&Sprite_78_MrsSahasrahla_bounce,
// Trampoline 68 entries
&Sprite_79_Bee,
&Sprite_7A_Agahnim,
&Sprite_7B_AgahnimBalls,
&Sprite_7C_GreenStalfos,
&Sprite_7D_BigSpike,
&Sprite_7E_Firebar_Clockwise,
&Sprite_7E_Firebar_Clockwise,
&Sprite_80_Firesnake,
&Sprite_81_Hover,
&Sprite_82_AntifairyCircle,
&Sprite_83_GreenEyegore,
&Sprite_83_GreenEyegore,
&Sprite_85_YellowStalfos,
&Sprite_86_Kodongo,
&Sprite_87_KodongoFire,
&Sprite_88_Mothula,
&Sprite_89_MothulaBeam,
&Sprite_8A_SpikeBlock,
&Sprite_8B_Gibdo,
&Sprite_8C_Arrghus,
&Sprite_8D_Arrghi,
&Sprite_8E_Terrorpin,
&Sprite_8F_Blob,
&Sprite_90_Wallmaster,
&Sprite_91_StalfosKnight,
&Sprite_92_HelmasaurKing,
&Sprite_93_Bumper,
&Sprite_94_Pirogusu,
&Sprite_95_LaserEyeLeft,
&Sprite_95_LaserEyeLeft,
&Sprite_95_LaserEyeLeft,
&Sprite_95_LaserEyeLeft,
&Sprite_99_Pengator,
&Sprite_9A_Kyameron,
&Sprite_9B_Wizzrobe,
&Sprite_9C_Zoro,
&Sprite_9C_Zoro,
&Sprite_9E_HauntedGroveOstritch,
&Sprite_9F_HauntedGroveRabbit,
&Sprite_A0_HauntedGroveBird,
&Sprite_A1_Freezor,
&Sprite_A2_Kholdstare,
&Sprite_A3_KholdstareShell,
&Sprite_A4_FallingIce,
&Sprite_Zazak_Main,
&Sprite_Zazak_Main,
&Sprite_A7_Stalfos,
&Sprite_A8_GreenZirro,
&Sprite_A8_GreenZirro,
&Sprite_AA_Pikit,
&Sprite_AB_CrystalMaiden,
&Sprite_AC_Apple,
&Sprite_AD_OldMan,
&Sprite_AE_Pipe_Down,
&Sprite_AE_Pipe_Down,
&Sprite_AE_Pipe_Down,
&Sprite_AE_Pipe_Down,
&Sprite_B2_PlayerBee,
&Sprite_B3_PedestalPlaque,
&Sprite_B4_PurpleChest,
&Sprite_B5_BombShop,
&Sprite_B6_Kiki,
&Sprite_B7_BlindMaiden,
&Sprite_B8_DialogueTester,
&Sprite_B9_BullyAndPinkBall,
&Sprite_BA_Whirlpool,
&Sprite_BB_Shopkeeper,
&Sprite_BC_Drunkard,
// Trampoline 4, starts at 187, 27 entries
&Sprite_BD_Vitreous,
&Sprite_BE_VitreousEye,
&Sprite_BF_Lightning,
&Sprite_C0_Catfish,
&Sprite_C1_CutsceneAgahnim,
&Sprite_C2_Boulder,
&Sprite_C3_Gibo,
&Sprite_C4_Thief,
&Sprite_C5_Medusa,
&Sprite_C6_4WayShooter,
&Sprite_C7_Pokey,
&Sprite_C8_BigFairy,
&Sprite_C9_Tektite,
&Sprite_CA_ChainChomp,
&Sprite_CB_TrinexxRockHead,
&Sprite_CC,
&Sprite_CD,
&Sprite_CE_Blind,
&Sprite_CF_Swamola,
&Sprite_D0_Lynel,
&Sprite_D1_BunnyBeam,
&Sprite_D2_FloppingFish,
&Sprite_D3_Stal,
&Sprite_D4_Landmine,
&Sprite_D5_DigGameGuy,
&Sprite_D6_Ganon,
&Sprite_D6_Ganon,
&Sprite_D8_Heart,
&Sprite_D9_GreenRupee,
&Sprite_D9_GreenRupee,
&Sprite_D9_GreenRupee,
&Sprite_D9_GreenRupee,
&Sprite_D9_GreenRupee,
&Sprite_D9_GreenRupee,
&Sprite_D9_GreenRupee,
&Sprite_D9_GreenRupee,
&Sprite_D9_GreenRupee,
&Sprite_D9_GreenRupee,
&Sprite_E3_Fairy,
&Sprite_E4_SmallKey,
&Sprite_E4_SmallKey,
&Sprite_D9_GreenRupee,
&Sprite_Mushroom,
&Sprite_FakeSword,
&Sprite_PotionShop,
&Sprite_HeartContainer,
&Sprite_HeartPiece,
&Sprite_EC_ThrownItem,
&Sprite_SomariaPlatform,
&Sprite_MovableMantleTrampoline,
&Sprite_SomariaPlatform,
&Sprite_SomariaPlatform,
&Sprite_SomariaPlatform,
&Sprite_F2_MedallionTablet_bounce,
};
static HandlerFuncK *const kSpritePrep_Main[243] = {
&SpritePrep_Raven,
&SpritePrep_Vulture,
&SpritePrep_DoNothingA,
NULL,
&SpritePrep_Switch,
&SpritePrep_DoNothingA,
&SpritePrep_Switch,
&SpritePrep_SwitchFacingUp,
&SpritePrep_Octorok,
&SpritePrep_Moldorm_bounce,
&SpritePrep_Octorok,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_Octoballoon,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_MiniHelmasaur,
&SpritePrep_ThievesTownGrate,
&SpritePrep_Antifairy,
&SpritePrep_Sage,
&SpritePrep_DoNothingA,
&SpritePrep_MiniMoldorm_bounce,
&SpritePrep_Poe,
&SpritePrep_Smithy,
&SpritePrep_DoNothingA,
&SpritePrep_Statue,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_CrystalSwitch,
&SpritePrep_SickKid,
&SpritePrep_DoNothingA,
&SpritePrep_WaterLever,
&SpritePrep_DoNothingA,
&SpritePrep_Bari,
&SpritePrep_Bari,
&SpritePrep_TalkingTree,
&SpritePrep_HardhatBeetle,
&SpritePrep_DoNothingA,
&SpritePrep_Storyteller,
&SpritePrep_Adults,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_Hobo,
&SpritePrep_MagicBat,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_FluteKid,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_FortuneTeller,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_RupeePull,
&SpritePrep_Snitch_bounce_2,
&SpritePrep_Snitch_bounce_3,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_DoNothingA,
&SpritePrep_Locksmith,
&SpritePrep_MagicBat,
&SpritePrep_BonkItem,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_Snitch_bounce_1,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_AgahnimsBarrier,
&SpritePrep_StandardGuard,
&SpritePrep_StandardGuard,
&SpritePrep_StandardGuard,
&SpritePrep_TrooperAndArcherSoldier,
&SpritePrep_TrooperAndArcherSoldier,
&SpritePrep_TrooperAndArcherSoldier,
&SpritePrep_TrooperAndArcherSoldier,
&SpritePrep_TrooperAndArcherSoldier,
&SpritePrep_TrooperAndArcherSoldier,
&SpritePrep_TrooperAndArcherSoldier,
&SpritePrep_WeakGuard,
&SpritePrep_Geldman,
&SpritePrep_Kyameron,
&SpritePrep_Popo,
&SpritePrep_Popo2,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingD,
&SpritePrep_KingZora,
&SpritePrep_ArmosKnight,
&SpritePrep_Lanmolas_bounce,
&SpritePrep_SwimmingZora,
&SpritePrep_WalkingZora,
&SpritePrep_DesertStatue,
&SpritePrep_DoNothingA,
&SpritePrep_LostWoodsBird,
&SpritePrep_LostWoodsSquirrel,
&SpritePrep_Spark,
&SpritePrep_Spark,
&SpritePrep_Roller_VerticalDownFirst,
&SpritePrep_RollerUpDown,
&SpritePrep_Roller_HorizontalRightFirst,
&SpritePrep_RollerLeftRight,
&SpritePrep_DoNothingA,
&SpritePrep_MasterSword,
&SpritePrep_DebirandoPit,
&SpritePrep_FireDebirando,
&SpritePrep_ArrowGame_bounce,
&SpritePrep_WallCannon,
&SpritePrep_WallCannon,
&SpritePrep_WallCannon,
&SpritePrep_WallCannon,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_Rat,
&SpritePrep_Rope,
&SpritePrep_Keese,
&SpritePrep_DoNothingG,
&SpritePrep_FairyPond,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_UncleAndPriest_bounce,
&SpritePrep_RunningMan,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_Zelda_bounce,
&SpritePrep_Antifairy,
&SpritePrep_MrsSahasrahla,
&SpritePrep_OverworldBonkItem,
&SpritePrep_Agahnim,
&SpritePrep_DoNothingG,
&SpritePrep_GreenStalfos,
&SpritePrep_BigSpike,
&SpritePrep_FireBar,
&SpritePrep_FireBar,
&SpritePrep_DoNothingG,
&SpritePrep_DoNothingG,
&SpritePrep_AntifairyCircle,
&SpritePrep_Eyegore,
&SpritePrep_Eyegore,
&SpritePrep_DoNothingG,
&SpritePrep_Kodongo,
&SpritePrep_DoNothingG,
&SpritePrep_Mothula,
&SpritePrep_DoNothingG,
&SpritePrep_Spike,
&SpritePrep_DoNothingG,
&SpritePrep_Arrghus,
&SpritePrep_Arrghi,
&SpritePrep_DoNothingG,
&SpritePrep_Blob,
&SpritePrep_DoNothingG,
&SpritePrep_DoNothingG,
&SpritePrep_HelmasaurKing,
&SpritePrep_Bumper,
&SpritePrep_DoNothingA,
&SpritePrep_LaserEye_bounce,
&SpritePrep_LaserEye_bounce,
&SpritePrep_LaserEye_bounce,
&SpritePrep_LaserEye_bounce,
&SpritePrep_DoNothingA,
&SpritePrep_Kyameron,
&SpritePrep_DoNothingA,
&SpritePrep_Zoro,
&SpritePrep_Babasu,
&SpritePrep_HauntedGroveOstritch,
&SpritePrep_HauntedGroveAnimal,
&SpritePrep_HauntedGroveAnimal,
&SpritePrep_MoveDown_8px,
&SpritePrep_Kholdstare,
&SpritePrep_KholdstareShell,
&SpritePrep_FallingIce,
&SpritePrep_Zazakku,
&SpritePrep_Zazakku,
&SpritePrep_Stalfos,
&SpritePrep_Bomber,
&SpritePrep_Bomber,
&SpritePrep_DoNothingC,
&SpritePrep_DoNothingH,
&SpritePrep_OverworldBonkItem,
&SpritePrep_OldMan_bounce,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_NiceBee,
&SpritePrep_PedestalPlaque,
&SpritePrep_PurpleChest,
&SpritePrep_BombShoppe,
&SpritePrep_Kiki,
&SpritePrep_BlindMaiden,
&SpritePrep_DoNothingA,
&SpritePrep_BullyAndVictim,
&SpritePrep_Whirlpool,
&SpritePrep_Shopkeeper,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_Vitreous,
&SpritePrep_MiniVitreous,
&SpritePrep_DoNothingA,
&SpritePrep_Catfish,
&SpritePrep_CutsceneAgahnim,
&SpritePrep_DoNothingA,
&SpritePrep_Gibo,
&SpritePrep_DoNothingA,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_Pokey,
&SpritePrep_BigFairy,
&SpritePrep_Tektite,
&SpritePrep_Chainchomp_bounce,
&SpritePrep_Trinexx,
&SpritePrep_Trinexx,
&SpritePrep_Trinexx,
&SpritePrep_Blind,
&SpritePrep_Swamola,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_RockStal,
&SpritePrep_IgnoreProjectiles,
&SpritePrep_DiggingGameGuy_bounce,
&SpritePrep_Ganon,
&SpritePrep_Ganon,
&SpritePrep_Absorbable,
&SpritePrep_Absorbable,
&SpritePrep_Absorbable,
&SpritePrep_Absorbable,
&SpritePrep_Absorbable,
&SpritePrep_Absorbable,
&SpritePrep_Absorbable,
&SpritePrep_Absorbable,
&SpritePrep_Absorbable,
&SpritePrep_Absorbable,
&SpritePrep_Absorbable,
&SpritePrep_Fairy,
&SpritePrep_SmallKey,
&SpritePrep_BigKey,
&SpritePrep_ShieldPickup,
&SpritePrep_Mushroom,
&SpritePrep_FakeSword,
&SpritePrep_PotionShop,
&SpritePrep_HeartContainer,
&SpritePrep_HeartPiece,
&SpritePrep_ThrowableScenery,
&SpritePrep_DoNothingA,
&SpritePrep_Mantle,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
&SpritePrep_MedallionTable,
};
static inline uint8 ChainBallMult(uint16 a, uint8 b);
static inline uint8 GuruguruBarMult(uint16 a, uint8 b);
static inline int8 GuruguruBarSin(uint16 a, uint8 b);
static inline uint8 ArrgiMult(uint16 a, uint8 b);
static inline int8 ArrgiSin(uint16 a, uint8 b);
static inline uint8 HelmasaurMult(uint16 a, uint8 b);
static inline int8 HelmasaurSin(uint16 a, uint8 b);
static inline uint8 TrinexxMult(uint8 a, uint8 b);
static inline uint8 TrinexxHeadMult(uint16 a, uint8 b);
static inline int8 TrinexxHeadSin(uint16 a, uint8 b);
static inline uint8 GanonMult(uint16 a, uint8 b);
static inline int8 GanonSin(uint16 a, uint8 b);
void Sprite_PullSwitch_bounce(int k) {
if (sprite_type[k] == 5 || sprite_type[k] == 7)
PullSwitch_FacingUp(k);
else
PullSwitch_FacingDown(k);
}
void GiantMoldorm_DrawSegment_AB(int k, int lookback) {
static const DrawMultipleData kGiantMoldorm_SegA_Dmd[8] = {
{-8, -8, 0x0084, 2},
{ 8, -8, 0x0086, 2},
{-8, 8, 0x00a4, 2},
{ 8, 8, 0x00a6, 2},
{-8, -8, 0x4086, 2},
{ 8, -8, 0x4084, 2},
{-8, 8, 0x40a6, 2},
{ 8, 8, 0x40a4, 2},
};
int j = sprite_subtype2[k] - lookback & 0x7f;
cur_sprite_x = moldorm_x_lo[j] | moldorm_x_hi[j] << 8;
cur_sprite_y = moldorm_y_lo[j] | moldorm_y_hi[j] << 8;
oam_cur_ptr += 0x10;
oam_ext_cur_ptr += 4;
Sprite_DrawMultiple(k, &kGiantMoldorm_SegA_Dmd[(sprite_subtype2[k] >> 1 & 1) * 4], 4, NULL);
}
void GiantMoldorm_DrawSegment_C_OrTail(int k, int lookback) {
static const uint8 kGiantMoldorm_OamFlags[4] = {0, 0x40, 0xc0, 0x80};
int j = sprite_subtype2[k] - lookback & 0x7f;
cur_sprite_x = moldorm_x_lo[j] | moldorm_x_hi[j] << 8;
cur_sprite_y = moldorm_y_lo[j] | moldorm_y_hi[j] << 8;
uint8 bak = sprite_oam_flags[k];
sprite_oam_flags[k] = (bak & 0x3f) | kGiantMoldorm_OamFlags[sprite_subtype2[k] >> 1 & 3];
SpriteDraw_SingleLarge(k);
sprite_oam_flags[k] = bak;
}
void Chicken_IncrSubtype2(int k, int j) {
sprite_subtype2[k] += j;
sprite_graphics[k] = (sprite_subtype2[k] >> 4) & 1;
Sprite_ReturnIfLifted(k);
}
bool Octoballoon_Find() {
for (int i = 15; i >= 0; i--) {
if (sprite_state[i] && sprite_type[i] == 0x10)
return true;
}
return false;
}
bool FluteBoy_CheckIfPlayerClose(int k) {
int xx = Sprite_GetX(k);
int yy = Sprite_GetY(k) - 16;
int x = link_x_coord - xx - (yy < 0); // zelda bug: carry
int y = link_y_coord - yy - (x < 0);
if (sign16(x)) x = ~x;
if (sign16(y)) y = ~y;
return (uint16)x < 48 && (uint16)y < 48;
}
void FortuneTeller_LightOrDarkWorld(int k, bool dark_world) {
int j;
static const uint8 kFortuneTeller_Prices[4] = {10, 15, 20, 30};
switch (sprite_ai_state[k]) {
case 0: // WaitForInquiry
sprite_graphics[k] = 0;
sprite_A[k] = (j = (GetRandomNumber() & 3)) << 1;
if (link_rupees_goal < kFortuneTeller_Prices[j])
sprite_ai_state[k] = 1;
else
sprite_ai_state[k] = 2;
break;
case 1: // NotEnoughRupees
Sprite_ShowSolicitedMessage(k, 0xf2);
break;
case 2: // AskIfPlayerWantsReading
if (Sprite_ShowSolicitedMessage(k, 0xf3) & 0x100) {
sprite_delay_main[k] = 255;
flag_is_link_immobilized = 1;
sprite_ai_state[k]=3;
}
break;
case 3: // ReactToPlayerResponse
if (!choice_in_multiselect_box) {
if (!sprite_delay_main[k])
sprite_ai_state[k]++;
sprite_graphics[k] = frame_counter >> 4 & 1;
} else {
Sprite_ShowMessageUnconditional(0xf5);
sprite_ai_state[k] = 2;
flag_is_link_immobilized = 0;
}
break;
case 4: // FortuneTeller_PerformPseudoScience
FortuneTeller_PerformPseudoScience(k);
break;
case 5: // ShowCostMessage
if (!dark_world)
sprite_graphics[k] = 0;
j = kFortuneTeller_Prices[sprite_A[k]>>1];
byte_7E1CF2[0] = (j / 10) | (j % 10)<< 4 ;
byte_7E1CF2[1] = 0;
Sprite_ShowMessageUnconditional(0xf4);
sprite_ai_state[k]++;
break;
case 6: // DeductPayment
link_rupees_goal -= kFortuneTeller_Prices[sprite_A[k]>>1];
sprite_ai_state[k]++;
link_hearts_filler = 160;
flag_is_link_immobilized = 0;
break;
case 7:
break;
}
}
int GarnishAllocForce() {
int k = 29;
while (garnish_type[k--] && k >= 0) {}
return k + 1;
}
int GarnishAlloc() {
int k = 29;
while (garnish_type[k] && k >= 0) k--;
return k;
}
int GarnishAllocLow() {
int k = 14;
while (garnish_type[k] && k >= 0) k--;
return k;
}
int GarnishAllocLimit(int k) {
while (garnish_type[k] && k >= 0) k--;
return k;
}
int GarnishAllocOverwriteOldLow() {
int k = 14;
while (garnish_type[k] && k >= 0) k--;
if (k < 0) {
if (sign8(--byte_7E0FF8))
byte_7E0FF8 = 14;
k = byte_7E0FF8;
}
return k;
}
int GarnishAllocOverwriteOld() {
int k = 29;
while (garnish_type[k] && k >= 0) k--;
if (k < 0) {
if (sign8(--byte_7E0FF8))
byte_7E0FF8 = 29;
k = byte_7E0FF8;
}
return k;
}
void Garnish_SetX(int k, uint16 x) {
garnish_x_lo[k] = x;
garnish_x_hi[k] = x >> 8;
}
void Garnish_SetY(int k, uint16 y) {
garnish_y_lo[k] = y;
garnish_y_hi[k] = y >> 8;
}
void Sprite_WishPond3(int k) {
int j;
switch (sprite_ai_state[k]) {
case 0:
flag_is_link_immobilized = 0;
if (sprite_delay_main[k] || Sprite_CheckIfLinkIsBusy())
return;
if (Sprite_ShowMessageOnContact(k, 0x14a) & 0x100) {
sprite_ai_state[k] = 1;
Link_ResetProperties_A();
link_direction_facing = 0;
sprite_head_dir[k] = 0;
}
break;
case 1:
if (!choice_in_multiselect_box) {
Sprite_ShowMessageUnconditional(0x8a);
sprite_ai_state[k] = 2;
flag_is_link_immobilized = 1;
} else {
Sprite_ShowMessageUnconditional(0x14b);
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 255;
}
break;
case 2: {
sprite_ai_state[k] = 3;
j = choice_in_multiselect_box;
sprite_C[k] = j;
uint8 item = (&link_item_bow)[j];
(&link_item_bow)[j] = 0;
uint8 t = kWishPondItemData[kWishPondItemOffs[j] + ((j == 3 || j == 32) ? 1 : item) - 1];
AncillaAdd_TossedPondItem(0x28, t, 4);
Hud_RefreshIcon();
sprite_graphics[k] = t;
sprite_D[k] = item;
sprite_delay_main[k] = 255;
break;
}
case 3:
if (sprite_delay_main[k] == 0) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x72, &info);
assert(j >= 0);
Sprite_SetX(j, info.r0_x);
Sprite_SetY(j, info.r2_y - 80);
music_control = 0x1b;
last_music_control = 0;
sprite_B[j] = 1;
Palette_AssertTranslucencySwap();
PaletteFilter_WishPonds();
sprite_E[k] = j;
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 255;
}
break;
case 4:
if (!(frame_counter & 7)) {
PaletteFilter_SP5F();
if (!BYTE(palette_filter_countdown)) {
Sprite_ShowMessageUnconditional(0x8b);
Palette_RevertTranslucencySwap();
TS_copy = 0;
CGADSUB_copy = 0x20;
flag_update_cgram_in_nmi++;
sprite_ai_state[k] = 5;
}
}
break;
case 5:
if (!choice_in_multiselect_box) {
sprite_ai_state[k] = 6;
} else {
sprite_ai_state[k] = 11;
}
break;
case 6:
sprite_ai_state[k] = 7;
if (!savegame_is_darkworld) {
if (sprite_graphics[k] == 12) {
sprite_graphics[k] = 42;
sprite_head_dir[k] = 1;
} else if (sprite_graphics[k] == 4) {
sprite_graphics[k] = 5;
sprite_head_dir[k] = 2;
} else if (sprite_graphics[k] == 22) {
sprite_graphics[k] = 44;
sprite_head_dir[k] = 3;
} else {
Sprite_ShowMessageUnconditional(0x14d);
return;
}
} else {
if (sprite_graphics[k] == 58) {
sprite_graphics[k] = 59;
sprite_head_dir[k] = 4;
Sprite_ShowMessageUnconditional(0x14f);
return;
} else if (sprite_graphics[k] == 2) {
sprite_graphics[k] = 3;
sprite_head_dir[k] = 5;
} else if (sprite_graphics[k] == 22) {
sprite_graphics[k] = 44;
sprite_head_dir[k] = 3;
} else {
Sprite_ShowMessageUnconditional(0x14d);
return;
}
}
Sprite_ShowMessageUnconditional(0x8c);
break;
case 7:
if (sprite_C[k] == 3)
(&link_item_bow)[sprite_C[k]] = sprite_D[k];
Palette_AssertTranslucencySwap();
TS_copy = 2;
CGADSUB_copy = 0x30;
flag_update_cgram_in_nmi++;
sprite_ai_state[k] = 8;
break;
case 8:
if (!(frame_counter & 7)) {
PaletteFilter_SP5F();
if (BYTE(palette_filter_countdown) == 30) {
sprite_state[sprite_E[k]] = 0;
} else if (BYTE(palette_filter_countdown) == 0) {
sprite_ai_state[k] = 9;
}
}
break;
case 9:
PaletteFilter_RestoreSP5F();
Palette_RevertTranslucencySwap();
item_receipt_method = 2;
Link_ReceiveItem(sprite_graphics[k], 0);
sprite_ai_state[k] = 10;
break;
case 10: {
static const uint8 kWishPondMsgs[5] = { 0x8f, 0x90, 0x92, 0x91, 0x93 };
if (sprite_head_dir[k])
Sprite_ShowMessageUnconditional(kWishPondMsgs[sprite_head_dir[k] - 1]);
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 255;
break;
}
case 11:
Sprite_ShowMessageUnconditional(0x8d);
sprite_ai_state[k] = 12;
break;
case 12:
if (!choice_in_multiselect_box)
sprite_ai_state[k] = 13;
else
sprite_ai_state[k] = 6;
break;
case 13:
Sprite_ShowMessageUnconditional(0x8e);
sprite_ai_state[k] = 7;
break;
}
}
int Sprite_SpawnSmallSplash(int k) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0xec, &info, 14);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sound_effect_1 = 0;
SpriteSfx_QueueSfx2WithPan(k, 0x28);
sprite_state[j] = 3;
sprite_delay_main[j] = 15;
sprite_ai_state[j] = 0;
sprite_flags2[j] = 3;
}
return j;
}
void HeartUpgrade_CheckIfAlreadyObtained(int k) {
if (!player_is_indoors) {
if (BYTE(overworld_screen_index) == 0x3b && !(save_ow_event_info[0x3b] & 0x20) ||
save_ow_event_info[BYTE(overworld_screen_index)] & 0x40)
sprite_state[k] = 0;
} else {
int j = sprite_x_hi[k] & 1;
if (dung_savegame_state_bits & (j ? 0x2000 : 0x4000))
sprite_state[k] = 0;
}
}
void Sprite_MovableMantleTrampoline(int k) {
MovableMantle_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!Sprite_CheckDamageToLink_same_layer(k))
return;
Sprite_NullifyHookshotDrag();
Sprite_RepelDash();
if (follower_indicator != 1 || !link_item_torch || link_is_running || sprite_G[k] == 0x90 || sign8(link_actual_vel_x - 24))
return;
which_starting_point = 4;
sprite_subtype2[k]++;
if (!(sprite_subtype2[k] & 1))
sprite_G[k]++;
if (sprite_G[k] < 8)
return;
if (sound_effect_1 == 0)
sound_effect_1 = 34;
sprite_x_vel[k] = 2;
Sprite_MoveXY(k);
}
void Sprite_GoodOrBadArcheryTarget(int k) {
static const uint8 kArcheryGame_CashPrize[10] = {4, 8, 16, 32, 64, 99, 99, 99, 99, 99};
if (sprite_A[k] == 1) {
// good target
if (sprite_G[k] >= 5)
sprite_B[k] = 6;
sprite_flags2[k] &= ~0x1f;
int j = sprite_delay_aux2[k] ? sprite_delay_aux2[k] : (sprite_subtype2[k] >> 3);
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | (j & 4) << 4;
BYTE(cur_sprite_y) -= 3;
SpriteDraw_SingleLarge(k);
if (sprite_delay_aux2[k]) {
if (sprite_delay_aux2[k] == 96 && !submodule_index) {
sprite_delay_main[0] = 112;
link_rupees_goal += kArcheryGame_CashPrize[sprite_B[k] - 1];
}
sprite_flags2[k] |= 5;
ArcheryGame_DrawPrize(k);
}
} else {
// bad target
sprite_flags2[k] &= ~0x1f;
BYTE(cur_sprite_y) += 3;
SpriteDraw_SingleLarge(k);
}
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_delay_aux3[k] == 1)
sound_effect_1 = 0x3c;
sprite_subtype2[k]++;
Sprite_MoveX(k);
if (!sprite_delay_aux1[k]) {
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (sprite_delay_main[k] == 0) {
if (Sprite_CheckTileCollision(k)) {
sprite_delay_main[k] = 16;
sprite_delay_aux2[k] = 0;
}
} else if (sprite_delay_main[k] == 1) {
static const int8 kArcheryTarget_X[2] = {-24, 8};
sprite_x_lo[k] = kArcheryTarget_X[sprite_graphics[k]];
sprite_x_hi[k] = link_x_coord >> 8;
sprite_delay_aux1[k] = 32;
sprite_G[k] = 0;
}
}
}
static inline uint8 ChainBallMult(uint16 a, uint8 b) {
if (a >= 256)
return b;
int p = a * b;
return (p >> 8) + (p >> 7 & 1);
}
void ChainBallTrooper_Draw(int k) {
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
SpriteDraw_GuardHead(k, &info, 0x18 / 4);
SpriteDraw_BNCBody(k, &info, 0x14 / 4);
SpriteDraw_BNCFlail(k, &info);
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
if (sprite_flags3[k] & 0x10)
SpriteDraw_Shadow_custom(k, &info, kSoldier_DrawShadow[sprite_D[k]]);
}
void Sprite_CannonTrooper(int k) {
if (sprite_C[k] != 0) {
Sprite_Cannonball(k);
return;
}
assert(0);
}
void Bee_PutInBottle(int k) {
Bee_HandleInteractions(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!choice_in_multiselect_box) {
int j = Sprite_Find_EmptyBottle();
if (j >= 0) {
link_bottle_info[j] = 7 + sprite_head_dir[k];
Hud_RefreshIcon();
sprite_state[k] = 0;
return;
}
Sprite_ShowMessageUnconditional(0xca);
}
sprite_delay_aux4[k] = 64;
sprite_ai_state[k] = 1;
}
static inline uint8 GuruguruBarMult(uint16 a, uint8 b) {
if (a >= 256)
return b;
int p = a * b;
return (p >> 8) + (p >> 7 & 1);
}
static inline int8 GuruguruBarSin(uint16 a, uint8 b) {
uint8 t = GuruguruBarMult(kSinusLookupTable[a & 0xff], b);
return (a & 0x100) ? -t : t;
}
static inline uint8 ArrgiMult(uint16 a, uint8 b) {
if (a >= 256)
return b;
int p = a * b;
return (p >> 8) + (p >> 7 & 1);
}
static inline int8 ArrgiSin(uint16 a, uint8 b) {
uint8 t = ArrgiMult(kSinusLookupTable[a & 0xff], b);
return (a & 0x100) ? -t : t;
}
static inline uint8 HelmasaurMult(uint16 a, uint8 b) {
if (a >= 256)
return b;
int p = a * b;
return (p >> 8) + (p >> 7 & 1);
}
static inline int8 HelmasaurSin(uint16 a, uint8 b) {
uint8 t = HelmasaurMult(kSinusLookupTable[a & 0xff], b);
return (a & 0x100) ? -t : t;
}
void Sprite_Wizzbeam(int k) {
Wizzbeam_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_oam_flags[k] ^= 6;
sprite_subtype2[k]++;
if (!sprite_ai_state[k])
Sprite_CheckDamageToLink(k);
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k))
sprite_state[k] = 0;
}
void Kiki_LyingInwait(int k) {
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
if (link_is_bunny_mirror | link_disable_sprite_damage | countdown_for_blink || follower_indicator == 10)
return;
if (save_ow_event_info[BYTE(overworld_screen_index)] & 0x20)
return;
if (Sprite_CheckDamageToLink_same_layer(k)) {
// Kiki Big Bomb Fix
if (enhanced_features0 & kFeatures0_MiscBugFixes)
follower_dropped = 0; // defuse bomb
follower_indicator = 10;
tagalong_var5 = 0;
LoadFollowerGraphics();
Follower_Initialize();
}
}
int ChainChomp_OneMult(uint8 a, uint8 b) {
uint8 at = sign8(a) ? -a : a;
uint8 prod = at * b >> 8;
return sign8(a) ? ~prod : prod;
}
static inline uint8 TrinexxMult(uint8 a, uint8 b) {
uint8 at = sign8(a) ? -a : a;
int p = at * b;
uint8 res = (p >> 8) + (p >> 7 & 1);
return sign8(a) ? -res : res;
}
static inline uint8 TrinexxHeadMult(uint16 a, uint8 b) {
if (a >= 256)
return b;
int p = a * b;
return (p >> 8) + (p >> 7 & 1);
}
static inline int8 TrinexxHeadSin(uint16 a, uint8 b) {
uint8 t = TrinexxHeadMult(kSinusLookupTable[a & 0xff], b);
return (a & 0x100) ? -t : t;
}
void Sprite_CC(int k) {
if (!sprite_E[k]) {
Sprite_Sidenexx(k);
return;
}
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXY(k);
Sprite_TrinexxFire_AddFireGarnish(k);
Sprite_CC_CD_Common(k);
}
void Sprite_CD(int k) {
if (!sprite_E[k]) {
Sprite_Sidenexx(k);
return;
}
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
uint8 old_xvel = sprite_x_vel[k];
sprite_x_vel[k] += sprite_C[k];
Sprite_MoveXY(k);
sprite_x_vel[k] = old_xvel;
Sprite_CD_SpawnGarnish(k);
Sprite_CC_CD_Common(k);
}
static inline uint8 GanonMult(uint16 a, uint8 b) {
if (a >= 256)
return b;
int p = a * b;
return (p >> 8) + (p >> 7 & 1);
}
static inline int8 GanonSin(uint16 a, uint8 b) {
uint8 t = GanonMult(kSinusLookupTable[a & 0xff], b);
return (a & 0x100) ? -t : t;
}
void SpritePrep_IncrXYLow8(int k) {
sprite_x_lo[k] += 8;
sprite_y_lo[k] += 8;
}
void SpritePrep_FakeSword(int k) {
}
void SpritePrep_MedallionTable(int k) {
sprite_ignore_projectile[k]++;
if (BYTE(overworld_screen_index) != 3) {
sprite_x_lo[k] += 8;
if (link_item_bombos_medallion) {
sprite_graphics[k] = 4;
sprite_ai_state[k] = 3;
}
} else {
if (link_item_ether_medallion) {
sprite_graphics[k] = 4;
sprite_ai_state[k] = 3;
}
}
}
void Hobo_Draw(int k) { // 84ea60
static const DrawMultipleData kHobo_Dmd[12] = {
{-5, 3, 0x00a6, 2},
{ 3, 3, 0x00a7, 2},
{-5, 3, 0x00a6, 2},
{ 3, 3, 0x00a7, 2},
{-5, 3, 0x00ab, 0},
{ 3, 3, 0x00a7, 2},
{-5, 3, 0x00a6, 2},
{ 3, 3, 0x00a7, 2},
{ 5, -11, 0x008a, 2},
{-5, 3, 0x00ab, 0},
{ 3, 3, 0x0088, 2},
{-5, 3, 0x00a6, 2},
};
Sprite_DrawMultiplePlayerDeferred(k, &kHobo_Dmd[sprite_graphics[k] * 4], 4, NULL);
}
bool Landmine_CheckDetonationFromHammer(int k) { // 84ea81
if (!(link_item_in_hand & 10) || player_oam_y_offset == 0x80)
return false;
SpriteHitBox hb;
Player_SetupActionHitBox(&hb);
Sprite_SetupHitBox(k, &hb);
return CheckIfHitBoxesOverlap(&hb);
}
void Sprite_DrawLargeWaterTurbulence(int k) { // 84ebe5
static const DrawMultipleData kWaterTurbulence_Dmd[6] = {
{-10, 14, 0x00c0, 2},
{ -5, 16, 0x40c0, 2},
{ -2, 18, 0x00c0, 2},
{ 2, 18, 0x40c0, 2},
{ 5, 16, 0x00c0, 2},
{ 10, 14, 0x40c0, 2},
};
uint8 bak = sprite_oam_flags[k];
sprite_oam_flags[k] = (sprite_subtype2[k] >> 1 & 1) ? 0x44 : 4;
sprite_obj_prio[k] &= ~0xf;
Oam_AllocateFromRegionC(sprite_obj_prio[k]); // wtf?????
Sprite_DrawMultiple(k, kWaterTurbulence_Dmd, 6, NULL);
sprite_oam_flags[k] = bak;
}
void Sprite_SpawnSparkleGarnish(int k) { // 858008
static const int8 kSparkleGarnish_Coord[4] = {-4, 0, 4, 8};
if (frame_counter & 3)
return;
int j = GarnishAllocForce();
garnish_type[j] = 0x12;
garnish_active = 0x12;
int x = Sprite_GetX(k) + kSparkleGarnish_Coord[GetRandomNumber() & 3];
int y = Sprite_GetY(k) + kSparkleGarnish_Coord[GetRandomNumber() & 3];
garnish_x_lo[j] = x;
garnish_x_hi[j] = x >> 8;
garnish_y_lo[j] = y;
garnish_y_hi[j] = y >> 8;
garnish_sprite[j] = k;
garnish_countdown[j] = 15;
}
void Sprite_70_KingHelmasaurFireball_bounce(int k) { // 85807f
static const uint8 kHelmasaurFireball_Char[3] = {0xcc, 0xcc, 0xca};
static const uint8 kHelmasaurFireball_Flags[2] = {0x33, 0x73};
static const uint8 kHelmasaurFireball_Gfx[4] = {2, 2, 1, 0};
OamEnt *oam = GetOamCurPtr();
uint8 flags = kHelmasaurFireball_Flags[++sprite_subtype2[k] >> 2 & 1];
if ((uint8)((oam->x = sprite_x_lo[k] - BG2HOFS_copy2) + 32) < 64 ||
(uint8)((oam->y = sprite_y_lo[k] - BG2VOFS_copy2) + 16) < 32) {
sprite_state[k] = 0;
return;
}
oam->charnum = kHelmasaurFireball_Char[sprite_graphics[k]];
oam->flags = flags;
bytewise_extended_oam[oam - oam_buf] = 2;
if (Sprite_ReturnIfInactive(k))
return;
if (!((k ^ frame_counter) & 3) &&
(uint16)(link_x_coord - cur_sprite_x + 8) < 16 &&
(uint16)(link_y_coord - cur_sprite_y + 16) < 16) {
Sprite_AttemptDamageToLinkPlusRecoil(k);
}
switch (sprite_ai_state[k]) {
case 0: // pre migrate down
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 18;
sprite_ai_state[k] = 1;
sprite_y_vel[k] = 36;
}
break;
case 1: // migrate down
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 31;
}
sprite_y_vel[k] -= 2;
Sprite_MoveY(k);
break;
case 2: // delay tri split
if (!sprite_delay_main[k])
HelmasaurFireball_TriSplit(k);
else
sprite_graphics[k] = kHelmasaurFireball_Gfx[sprite_delay_main[k] >> 3];
break;
case 3: // delay quad split
if (!sprite_delay_main[k]) {
HelmasaurFireball_QuadSplit(k);
} else if (sprite_head_dir[k] < 20) {
sprite_head_dir[k]++;
Sprite_MoveXY(k);
}
break;
case 4: // move
Sprite_MoveXY(k);
break;
}
}
void Sprite_66_WallCannonVerticalLeft(int k) { // 858090
static const int8 kWallCannon_Xvel[4] = {0, 0, -16, 16};
static const int8 kWallCannon_Yvel[4] = {-16, 16, 0, 0};
static const uint8 kWallCannon_Gfx[4] = {0, 0, 2, 2};
static const uint8 kWallCannon_OamFlags[4] = {0x40, 0, 0, 0x80};
static const int8 kWallCannon_Spawn_X[4] = {8, -8, 0, 0};
static const int8 kWallCannon_Spawn_Y[4] = {0, 0, 8, -8};
static const int8 kWallCannon_Spawn_Xvel[4] = {24, -24, 0, 0};
static const int8 kWallCannon_Spawn_Yvel[4] = {0, 0, 24, -24};
int j = sprite_D[k];
sprite_graphics[k] = kWallCannon_Gfx[j] + (sprite_delay_aux2[k] != 0);
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kWallCannon_OamFlags[j];
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 128;
sprite_A[k] ^= 1;
}
j = sprite_A[k];
sprite_x_vel[k] = kWallCannon_Xvel[j];
sprite_y_vel[k] = kWallCannon_Yvel[j];
Sprite_MoveXY(k);
if (!((k << 2) + frame_counter & 31))
sprite_delay_aux2[k] = 16;
if (sprite_delay_aux2[k] != 1 || sprite_pause[k])
return;
SpriteSpawnInfo info;
j = Sprite_SpawnDynamicallyEx(k, 0x6B, &info, 13);
if (j >= 0) {
SpriteSfx_QueueSfx3WithPan(k, 0x7);
sprite_C[j] = 1;
sprite_graphics[j] = 1;
int i = sprite_D[k];
Sprite_SetX(j, info.r0_x + kWallCannon_Spawn_X[i]);
Sprite_SetY(j, info.r2_y + kWallCannon_Spawn_Y[i]);
sprite_x_vel[j] = kWallCannon_Spawn_Xvel[i];
sprite_y_vel[j] = kWallCannon_Spawn_Yvel[i];
sprite_flags2[j] = sprite_flags2[j] & 0xf0 | 1;
sprite_flags3[j] |= 0x47;
sprite_defl_bits[j] |= 0x44;
sprite_delay_main[j] = 32;
}
}
void Sprite_65_ArcheryGame(int k) { // 8581ff
link_num_arrows = sprite_subtype[k];
if (sprite_A[k] == 0)
ArcheryGame_Host(k);
else
Sprite_GoodOrBadArcheryTarget(k);
}
void ArcheryGame_Host(int k) { // 858217
if (!archery_game_arrows_left)
archery_game_out_of_arrows++;
ArcheryGameGuy_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_flags4[k] = 0;
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Link_CancelDash();
}
if (sprite_delay_main[k]) {
if (!(sprite_delay_main[k] & 7))
SpriteSfx_QueueSfx2WithPan(k, 0x11);
sprite_graphics[k] = (sprite_delay_main[k] & 4) >> 2;
} else {
static const uint8 kArcheryGameGuy_Gfx[4] = {3, 4, 3, 2};
sprite_graphics[k] = kArcheryGameGuy_Gfx[sprite_ai_state[k] ? (frame_counter >> 5 & 3) : 0];
}
switch (sprite_ai_state[k]) {
case 0:
sprite_flags4[k] = 10;
if (Sprite_CheckDamageToLink_same_layer(k) && filtered_joypad_L & 0x80) {
sprite_ai_state[k] = 1;
ArcheryGameGuy_ShowMsg(k, 0x85);
}
break;
case 1:
case 3:
if (!choice_in_multiselect_box && link_rupees_goal >= 20) {
sprite_head_dir[k] = 0;
byte_7E0B88 = 0;
sprite_ai_state[k] = 2;
ArcheryGameGuy_ShowMsg(k, 0x86);
} else {
sprite_ai_state[k] = 0;
ArcheryGameGuy_ShowMsg(k, 0x87);
}
break;
case 2:
ArcheryGame_Host_ProctorGame(k);
break;
}
}
void ArcheryGameGuy_ShowMsg(int k, int msg) { // 8582bf
dialogue_message_index = msg;
Sprite_ShowMessageMinimal();
sprite_delay_main[k] = 0;
}
void ArcheryGame_Host_ProctorGame(int k) { // 8582d4
static const uint8 kArcheryGame_NumSpr[6] = {5, 4, 3, 2, 1, 0};
static const int8 kArcheryGame_X[18] = { 0, 0, 0, 0, 48, 48, 48, 48, 8, 8, 16, 16, 24, 24, 32, 32, 40, 40, };
static const int8 kArcheryGame_Y[18] = {-8, 0, 8, 16, -8, 0, 8, 16, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8 };
static const uint8 kArcheryGame_Char[18] = { 0x2b, 0x3b, 0x3b, 0x2b, 0x2b, 0x3b, 0x3b, 0x2b, 0x63, 0x73, 0x63, 0x73, 0x63, 0x73, 0x63, 0x73, 0x63, 0x73 };
static const uint8 kArcheryGame_Flags[18] = { 0x33, 0x33, 0xb3, 0xb3, 0x73, 0x73, 0xf3, 0xf3, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32 };
if (!sprite_head_dir[k]) {
archery_game_arrows_left = 5;
Sprite_InitializeSecondaryItemMinigame(2);
sprite_delay_aux1[k] = 39;
link_rupees_goal -= 20;
sprite_head_dir[k]++;
}
Oam_AllocateFromRegionA(0x34);
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int i = sprite_delay_aux1[k] ? kArcheryGame_NumSpr[sprite_delay_aux1[k] >> 3] : archery_game_arrows_left;
i = i * 2 + 7;
do {
oam->x = info.x - 20 + kArcheryGame_X[i] + 1;
oam->y = info.y - 48 + kArcheryGame_Y[i] + 1;
oam->charnum = kArcheryGame_Char[i];
oam->flags = kArcheryGame_Flags[i];
bytewise_extended_oam[oam - oam_buf] = 0;
} while (oam++, --i >= 0);
if (archery_game_arrows_left | sprite_delay_aux4[k] |
ancilla_type[0] | ancilla_type[1] | ancilla_type[2] | ancilla_type[3] | ancilla_type[4])
return;
sprite_flags4[k] = 0xA;
if (Sprite_CheckDamageToLink_same_layer(k) && filtered_joypad_L & 0x80) {
ArcheryGameGuy_ShowMsg(k, 0x88);
sprite_ai_state[k] = 3;
}
}
void ArcheryGame_DrawPrize(int k) { // 8584cf
static const int8 kGoodArcheryTarget_X[5] = {-8, -8, 0, 8, 16};
static const int8 kGoodArcheryTarget_Y[5] = {-24, -16, -20, -20, -20};
static const uint8 kGoodArcheryTarget_Draw_Char[3] = {0xb, 0x1b, 0xb6};
static const int8 kGoodArcheryTarget_Draw_Flags[5] = {0x38, 0x38, 0x34, 0x35, 0x35};
static const uint8 kGoodArcheryTarget_Draw_Char3[6] = {0x12, 0x32, 0x31, 3, 0x22, 0x33};
static const uint8 kGoodArcheryTarget_Draw_Char4[6] = {0x7c, 0x7c, 0x22, 2, 0x12, 0x33};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr() + 1;
int b = sprite_B[k];
for (int i = 4; i >= 0; i--, oam++) {
oam->x = info.x + kGoodArcheryTarget_X[i];
oam->y = info.y + kGoodArcheryTarget_Y[i];
oam->charnum = (i == 4) ? kGoodArcheryTarget_Draw_Char4[b - 1] :
(i == 3) ? kGoodArcheryTarget_Draw_Char3[b - 1] : kGoodArcheryTarget_Draw_Char[i];
oam->flags = kGoodArcheryTarget_Draw_Flags[i] & (oam->charnum < 0x7c ? 0xff : 0xfe);
bytewise_extended_oam[oam - oam_buf] = 0;
}
Sprite_DrawDistress_custom(info.x, info.y, frame_counter);
}
void Sprite_63_DebirandoPit(int k) { // 858531
static const uint8 kDebirandoPit_OpeningGfx[4] = {5, 4, 3, 3};
static const uint8 kDebirandoPit_ClosingGfx[4] = {3, 3, 4, 5};
PointU8 pt;
Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.y + 0x20) < 0x40 && (uint8)(pt.x + 0x20) < 0x40)
Oam_AllocateFromRegionB(16);
DebirandoPit_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
int j = sprite_head_dir[k];
if (sprite_state[j] == 6) {
sprite_state[k] = sprite_state[j];
sprite_delay_main[k] = sprite_delay_main[j];
sprite_flags2[k] += 4;
return;
}
if (sprite_graphics[k] < 3 && Sprite_CheckDamageToLink_same_layer(k)) {
Link_CancelDash();
if (!(filtered_joypad_L & 16))
link_prevent_from_moving = 1;
Sprite_ApplySpeedTowardsLink(k, 16);
uint8 v = sprite_y_vel[k];
int t;
sprite_A[k] = (t = (sign8(v) ? (uint8)-v : v) + sprite_A[k]);
if (t >= 256)
drag_player_y = sign8(v) ? 1 : -1;
v = sprite_x_vel[k];
sprite_B[k] = (t = (sign8(v) ? (uint8)-v : v) + sprite_B[k]);
if (t >= 256)
drag_player_x = sign8(v) ? 1 : -1;
}
switch (sprite_ai_state[k]) {
case 0: // closed
sprite_graphics[k] = 6;
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 63;
}
break;
case 1: // opening
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 255;
} else {
sprite_graphics[k] = kDebirandoPit_OpeningGfx[sprite_delay_main[k] >> 4];
}
break;
case 2: // open
if (!(frame_counter & 15) && ++sprite_graphics[k] >= 3)
sprite_graphics[k] = 0;
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 63;
sprite_ai_state[k] = 3;
}
break;
case 3: // closing
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 32;
} else {
sprite_graphics[k] = kDebirandoPit_ClosingGfx[sprite_delay_main[k] >> 4];
}
break;
}
}
void DebirandoPit_Draw(int k) { // 8586e4
static const int16 kDebirandoPit_Draw_X[24] = {
-8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, 0, 8, 0, 8,
0, 8, 0, 8, -8, 8, -8, 8,
};
static const int16 kDebirandoPit_Draw_Y[24] = {
-8, -8, 8, 8, -8, -8, 8, 8, -8, -8, 8, 8, 0, 0, 8, 8,
0, 0, 8, 8, -8, -8, 8, 8,
};
static const uint8 kDebirandoPit_Draw_Char[24] = {
4, 4, 4, 4, 0x22, 0x22, 0x22, 0x22, 2, 2, 2, 2, 0x29, 0x29, 0x29, 0x29,
0x39, 0x39, 0x39, 0x39, 0x2a, 0x2a, 0x2a, 0x2a,
};
static const uint8 kDebirandoPit_Draw_Flags[24] = {
0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0,
0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0,
};
static const uint8 kDebirandoPit_Draw_Ext[6] = {2, 2, 2, 0, 0, 2};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
int g = sprite_graphics[k];
if (g == 6)
return;
OamEnt *oam = GetOamCurPtr();
uint8 ext = kDebirandoPit_Draw_Ext[g];
for (int i = 3; i >= 0; i--, oam++) {
int j = g * 4 + i;
uint16 x = info.x + kDebirandoPit_Draw_X[j];
uint16 y = info.y + kDebirandoPit_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kDebirandoPit_Draw_Char[j];
oam->flags = kDebirandoPit_Draw_Flags[j] | info.flags;
bytewise_extended_oam[oam - oam_buf] = ext | (x >> 8 & 1);
}
}
void Sprite_64_Debirando(int k) { // 85874d
static const uint8 kDebirando_Emerge_Gfx[2] = {1, 0};
static const uint8 kDebirando_Submerge_Gfx[2] = {0, 1};
Debirando_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch (sprite_ai_state[k]) {
case 0: // under sand
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 31;
}
break;
case 1: // emerge
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 128;
} else {
sprite_graphics[k] = kDebirando_Emerge_Gfx[sprite_delay_main[k] >> 4];
}
break;
case 2: // fireball
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 31;
sprite_ai_state[k]++;
} else {
if (!(sprite_delay_main[k] & 31 | sprite_G[k] | submodule_index | sprite_pause[k] | flag_unk1))
Sprite_SpawnFireball(k);
sprite_graphics[k] = (++sprite_subtype2[k] >> 3 & 1) + 2;
}
break;
case 3: // submerge
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 223;
} else {
sprite_graphics[k] = kDebirando_Submerge_Gfx[sprite_delay_main[k] >> 4];
}
break;
}
}
void Debirando_Draw(int k) { // 858857
if (!sprite_ai_state[k])
return;
static const int8 kDebirando_Draw_X[16] = {0, 8, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0};
static const int8 kDebirando_Draw_Y[16] = {2, 2, 6, 6, -2, -2, 6, 6, -4, -4, -4, -4, -4, -4, -4, -4};
static const uint8 kDebirando_Draw_Char[16] = {0, 0, 0xd8, 0xd8, 0, 0, 0xd9, 0xd9, 0, 0, 0, 0, 0x20, 0x20, 0x20, 0x20};
static const uint8 kDebirando_Draw_Flags[16] = {1, 0x41, 0, 0x40, 1, 1, 0, 0x40, 1, 1, 1, 1, 1, 1, 1, 1};
static const uint8 kDebirando_Draw_Ext[16] = {0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int d = sprite_graphics[k] * 4;
for (int i = 3; i >= 0; i--, oam++) {
int j = d + i;
uint16 x = info.x + kDebirando_Draw_X[j];
uint16 y = info.y + kDebirando_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kDebirando_Draw_Char[j];
uint8 f = kDebirando_Draw_Flags[j];
oam->flags = (f ^ info.flags) & ((f & 0xf) == 0 ? 0xf0 : 0xff);
bytewise_extended_oam[oam - oam_buf] = kDebirando_Draw_Ext[j] | (x >> 8 & 1);
}
}
void Sprite_62_MasterSword(int k) { // 8588c5
switch (sprite_subtype2[k]) {
case 0: MasterSword_Main(k); break;
case 1: Sprite_MasterSword_LightFountain(k); break;
case 2: Sprite_MasterSword_LightBeam(k); break;
case 3: Sprite_MasterSword_Prop(k); break;
case 4: Sprite_MasterSword_LightWell(k); break;
}
}
void MasterSword_Main(int k) { // 8588d6
if (main_module_index != 26 && save_ow_event_info[BYTE(overworld_screen_index)] & 0x40) {
sprite_state[k] = 0;
return;
}
if (sprite_ai_state[k] != 5)
MasterSword_Draw(k);
switch (sprite_ai_state[k]) {
case 0: // waiting
if (Sprite_CheckIfLinkIsBusy() || !Sprite_CheckDamageToLink_same_layer(k) || link_direction_facing != 2 ||
!(filtered_joypad_L & 0x80) || (link_which_pendants & 7) != 7)
return;
music_control = 10;
link_disable_sprite_damage = 1;
MasterSword_SpawnPendantProp(k, 9);
MasterSword_SpawnPendantProp(k, 11);
MasterSword_SpawnPendantProp(k, 15);
MasterSword_SpawnLightWell(k);
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 240;
break;
case 1: // pendants transfer
if (!sprite_delay_main[k]) {
MasterSword_SpawnLightFountain(k);
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 192;
}
link_unk_master_sword = 10;
flag_is_link_immobilized = 1;
break;
case 2: // light show
if (!sprite_delay_main[k]) {
MasterSword_SpawnLightBeam(k, 0, 0xff);
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 8;
}
link_unk_master_sword = 10;
flag_is_link_immobilized = 1;
break;
case 3: //
if (!sprite_delay_main[k]) {
MasterSword_SpawnLightBeam(k, 1, 0xff);
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 16;
}
link_unk_master_sword = 11;
flag_is_link_immobilized = 1;
break;
case 4: // give to player
if (!sprite_delay_main[k]) {
save_ow_event_info[BYTE(overworld_screen_index)] |= 0x40;
item_receipt_method = 0;
Link_ReceiveItem(1, 0);
savegame_map_icons_indicator = 5;
link_unk_master_sword = 0;
sprite_ai_state[k] = 5;
}
break;
case 5: // stop
sprite_state[k] = 0;
break;
}
}
void Sprite_MasterSword_LightFountain(int k) { // 8589dc
static const uint8 kMasterSword_Gfx1[9] = {0, 1, 1, 2, 2, 2, 1, 1, 0};
static const uint8 kMasterSword_NumLightBeams[9] = {0, 0, 1, 1, 2, 2, 0, 0, 0};
SpriteDraw_LightFountain(k);
sprite_A[k]++;
if (!sprite_A[k]) {
sprite_C[k]++;
sprite_state[k] = 0;
}
sprite_D[k] = sprite_A[k] >> 2 & 3;
int j = sprite_A[k] >> 5 & 7;
sprite_graphics[k] = kMasterSword_Gfx1[j];
if (kMasterSword_NumLightBeams[j])
MasterSword_SpawnLightBeam(k, sprite_A[k] >> 2 & 1, kMasterSword_NumLightBeams[j]);
}
void Sprite_MasterSword_LightWell(int k) { // 858a16
SpriteDraw_LightFountain(k);
sprite_A[k]++;
if (!sprite_A[k]) {
sprite_C[k]++;
sprite_state[k] = 0;
}
sprite_D[k] = sprite_A[k] >> 2 & 3;
sprite_graphics[k] = 0;
}
void SpriteDraw_LightFountain(int k) { // 858a94
static const DrawMultipleData kMasterSword_LightBall_Dmd[12] = {
{-6, 4, 0x0082, 2},
{-6, 4, 0x4082, 2},
{-6, 4, 0xc082, 2},
{-6, 4, 0x8082, 2},
{-6, 4, 0x00a0, 2},
{-6, 4, 0x40a0, 2},
{-6, 4, 0xc0a0, 2},
{-6, 4, 0x80a0, 2},
{-6, 4, 0x0080, 2},
{-6, 4, 0x4080, 2},
{-6, 4, 0xc080, 2},
{-6, 4, 0x8080, 2},
};
Oam_AllocateFromRegionC(4);
Sprite_DrawMultiple(k, &kMasterSword_LightBall_Dmd[sprite_graphics[k] * 4 + sprite_D[k]], 1, NULL);
}
void MasterSword_SpawnLightWell(int k) { // 858ab6
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x62, &info);
Sprite_SetSpawnedCoordinates(j, &info);
sprite_subtype2[j] = 4;
sprite_oam_flags[j] = 5;
sprite_flags2[j] = 0;
}
void MasterSword_SpawnLightFountain(int k) { // 858ad0
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x62, &info);
Sprite_SetSpawnedCoordinates(j, &info);
sprite_subtype2[j] = 1;
sprite_oam_flags[j] = 5;
sprite_flags2[j] = 0;
}
void Sprite_MasterSword_LightBeam(int k) { // 858aea
SpriteDraw_SingleLarge(k);
if (sprite_A[k]) {
Sprite_MoveXY(k);
if (frame_counter & 3)
return;
MasterSword_SpawnReplacementLightBeam(k);
}
if (!--sprite_B[k])
sprite_state[k] = 0;
}
void MasterSword_SpawnReplacementLightBeam(int k) { // 858b20
SpriteSpawnInfo info;
int j;
if ((j = Sprite_SpawnDynamically(k, 0x62, &info)) < 0)
return;
Sprite_SetX(j, info.r0_x);
Sprite_SetY(j, info.r2_y);
sprite_subtype2[j] = 2;
sprite_B[j] = 3;
sprite_graphics[j] = sprite_graphics[k];
sprite_oam_flags[j] = sprite_oam_flags[k];
sprite_flags2[j] = 0;
}
void MasterSword_SpawnLightBeam(int k, uint8 ain, uint8 yin) { // 858b62
static const int8 kMasterSword_LightBeam_Xv0[2] = {0, -48};
static const int8 kMasterSword_LightBeam_Xv1[2] = {0, 48};
static const int8 kMasterSword_LightBeam_Xv2[2] = {-96, -48};
static const int8 kMasterSword_LightBeam_Xv3[2] = {96, 48};
static const int8 kMasterSword_LightBeam_Yv0[2] = {-96, -48};
static const int8 kMasterSword_LightBeam_Yv1[2] = {96, 48};
static const int8 kMasterSword_LightBeam_Yv2[2] = {0, 48};
static const int8 kMasterSword_LightBeam_Yv3[2] = {0, -48};
static const uint8 kMasterSword_LightBeam_Gfx0[2] = {1, 0};
static const uint8 kMasterSword_LightBeam_Gfx2[2] = {3, 2};
static const uint8 kMasterSword_LightBeam_Flags0[2] = {5, 0x45};
static const uint8 kMasterSword_LightBeam_Flags2[2] = {5, 5};
SpriteSpawnInfo info;
int j;
if ((j = Sprite_SpawnDynamically(k, 0x62, &info)) < 0)
return;
Sprite_SetX(j, info.r0_x - 4);
Sprite_SetY(j, info.r2_y + 4);
sprite_subtype2[j] = 2;
sprite_A[j] = 2;
sprite_flags2[j] = 0;
sprite_x_vel[j] = kMasterSword_LightBeam_Xv0[ain];
sprite_y_vel[j] = kMasterSword_LightBeam_Yv0[ain];
sprite_graphics[j] = kMasterSword_LightBeam_Gfx0[ain];
sprite_oam_flags[j] = kMasterSword_LightBeam_Flags0[ain];
sprite_B[j] = yin;
if ((j = Sprite_SpawnDynamically(k, 0x62, &info)) < 0)
return;
Sprite_SetX(j, info.r0_x - 4);
Sprite_SetY(j, info.r2_y + 4);
sprite_subtype2[j] = 2;
sprite_A[j] = 2;
sprite_flags2[j] = 0;
sprite_x_vel[j] = kMasterSword_LightBeam_Xv1[ain];
sprite_y_vel[j] = kMasterSword_LightBeam_Yv1[ain];
sprite_graphics[j] = kMasterSword_LightBeam_Gfx0[ain];
sprite_oam_flags[j] = kMasterSword_LightBeam_Flags0[ain];
sprite_B[j] = yin;
if ((j = Sprite_SpawnDynamically(k, 0x62, &info)) < 0)
return;
Sprite_SetX(j, info.r0_x - 4);
Sprite_SetY(j, info.r2_y + 4);
sprite_subtype2[j] = 2;
sprite_A[j] = 2;
sprite_flags2[j] = 0;
sprite_x_vel[j] = kMasterSword_LightBeam_Xv2[ain];
sprite_y_vel[j] = kMasterSword_LightBeam_Yv2[ain];
sprite_graphics[j] = kMasterSword_LightBeam_Gfx2[ain];
sprite_oam_flags[j] = kMasterSword_LightBeam_Flags2[ain];
sprite_B[j] = yin;
if ((j = Sprite_SpawnDynamically(k, 0x62, &info)) < 0)
return;
Sprite_SetX(j, info.r0_x - 4);
Sprite_SetY(j, info.r2_y + 4);
sprite_subtype2[j] = 2;
sprite_A[j] = 2;
sprite_flags2[j] = 0;
sprite_x_vel[j] = kMasterSword_LightBeam_Xv3[ain];
sprite_y_vel[j] = kMasterSword_LightBeam_Yv3[ain];
sprite_graphics[j] = kMasterSword_LightBeam_Gfx2[ain];
sprite_oam_flags[j] = kMasterSword_LightBeam_Flags2[ain];
sprite_B[j] = yin;
}
void MasterSword_SpawnPendantProp(int k, uint8 ain) { // 858cd3
static const int8 kMasterSword_Pendant_Xv[4] = {-4, 4, 0, 0};
static const int8 kMasterSword_Pendant_Yv[4] = {-2, -2, -4, -4};
SpriteSpawnInfo info;
int j;
if ((j = Sprite_SpawnDynamically(k, 0x62, &info)) < 0)
return;
sprite_oam_flags[j] = ain;
Sprite_SetX(j, link_x_coord);
Sprite_SetY(j, link_y_coord + 8);
sprite_graphics[j] = 4;
sprite_subtype2[j] = 3;
sprite_flags2[j] = 64;
sprite_delay_main[j] = 228;
int i = ain >> 1 & 3;
sprite_x_vel[j] = kMasterSword_Pendant_Xv[i];
sprite_y_vel[j] = kMasterSword_Pendant_Yv[i];
}
void Sprite_MasterSword_Prop(int k) { // 858d29
Oam_AllocateFromRegionB(4);
SpriteDraw_SingleLarge(k);
switch (sprite_ai_state[k]) {
case 0: // drifting away
Sprite_MoveXY(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 208;
sprite_A[k] = sprite_oam_flags[k];
}
break;
case 1: // flashing
sprite_oam_flags[k] = (sprite_oam_flags[k] & ~0xe) | ((k << 1 ^ frame_counter) & 0xe);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_oam_flags[k] = sprite_A[k];
}
break;
case 2: // fly
Sprite_MoveXY(k);
if (!sprite_delay_main[k]) {
sprite_x_vel[k] <<= 1;
sprite_y_vel[k] <<= 1;
sprite_delay_main[k] = 6;
}
sprite_E[k]++;
if (sprite_E[k] == 0)
sprite_state[k] = 0;
break;
}
}
void MasterSword_Draw(int k) { // 858da8
static const int8 kMasterSword_Draw_X[6] = {-8, 0, -8, 0, -8, 0};
static const int8 kMasterSword_Draw_Y[6] = {-8, -8, 0, 0, 8, 8};
static const uint8 kMasterSword_Draw_Char[6] = {0xc3, 0xc4, 0xd3, 0xd4, 0xe0, 0xf0};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
for (int i = 5; i >= 0; i--, oam++) {
oam->x = kMasterSword_Draw_X[i] + info.x;
oam->y = kMasterSword_Draw_Y[i] + info.y;
oam->charnum = kMasterSword_Draw_Char[i];
oam->flags = info.flags;
}
Sprite_CorrectOamEntries(k, 5, 0);
}
void Sprite_5D_Roller_VerticalDownFirst(int k) { // 858dde
static const int8 kSpikeRoller_XYvel[6] = {-16, 16, 0, 0, -16, 16};
sprite_graphics[k] = sprite_subtype2[k] >> 1 & 1 | sprite_D[k] & 2;
SpikeRoller_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 112;
sprite_D[k] ^= 1;
}
int j = sprite_D[k];
sprite_x_vel[k] = kSpikeRoller_XYvel[j];
sprite_y_vel[k] = kSpikeRoller_XYvel[j + 2];
Sprite_MoveXY(k);
sprite_subtype2[k]++;
}
void SpikeRoller_Draw(int k) { // 858ee3
static const uint8 kSpikeRoller_Draw_X[32] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
};
static const uint8 kSpikeRoller_Draw_Y[32] = {
0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static const uint8 kSpikeRoller_Draw_Char[32] = {
0x8e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x8e, 0x8e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x8e,
0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88,
};
static const uint8 kSpikeRoller_Draw_Flags[32] = {
0, 0, 0, 0x80, 0, 0, 0, 0x80, 0x40, 0x40, 0x40, 0xc0, 0x40, 0x40, 0x40, 0xc0,
0, 0, 0, 0x40, 0, 0, 0, 0x40, 0x80, 0x80, 0x80, 0xc0, 0x80, 0x80, 0x80, 0xc0,
};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
uint8 chr = kSpikeRoller_Draw_Char[g * 8];
for (int i = sprite_ai_state[k] ? 7 : 3; i >= 0; i--, oam++) {
int j = g * 8 + i;
uint16 x = info.x + kSpikeRoller_Draw_X[j];
uint16 y = info.y + kSpikeRoller_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = chr ? chr : kSpikeRoller_Draw_Char[j];
chr = 0;
oam->flags = kSpikeRoller_Draw_Flags[j] | info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
}
void Sprite_61_Beamos(int k) { // 858f54
if (sprite_C[k] == 1) {
Sprite_Beamos_Laser(k);
return;
} else if (sprite_C[k] != 0) {
Sprite_Beamos_LaserHit(k);
return;
}
Beamos_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckTileCollision(k);
Sprite_CheckDamageToLink(k);
switch (sprite_ai_state[k]) {
case 0:
if (!((k ^ frame_counter) & 3)) {
Sprite_SpawnProbeAlways(k, sprite_D[k]);
sprite_D[k]++;
}
sprite_D[k] &= 63;
break;
case 3:
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 80;
SpritePrep_LoadPalette(k);
} else {
if (sprite_delay_main[k] == 15)
Beamos_FireLaser(k);
sprite_oam_flags[k] ^= (sprite_delay_main[k] >> 1 & 0xe);
}
break;
default:
if (!sprite_delay_main[k])
sprite_ai_state[k] = 0;
break;
}
}
void Beamos_FireLaser(int k) { // 858fc2
if (sprite_limit_instance >= 4)
return;
SpriteSpawnInfo info;
int j, t;
if ((j = Sprite_SpawnDynamically(k, 0x61, &info)) < 0)
return;
SpriteSfx_QueueSfx3WithPan(k, 0x19);
Sprite_SetX(j, info.r0_x + (int8)BYTE(dungmap_var7));
Sprite_SetY(j, info.r2_y + (int8)HIBYTE(dungmap_var7));
Sprite_ApplySpeedTowardsLink(j, 0x20);
sprite_flags2[j] = 0x3f;
sprite_flags4[j] = 0x54;
sprite_C[j] = 1;
sprite_defl_bits[j] = 0x48;
sprite_oam_flags[j] = 3;
sprite_bump_damage[j] = 4;
sprite_delay_aux1[j] = 12;
sprite_graphics[j] = t = sprite_limit_instance++;
for (int i = 0; i < 32; i++) {
beamos_x_lo[t * 32 + i] = sprite_x_lo[j];
beamos_x_hi[t * 32 + i] = sprite_x_hi[j];
beamos_y_lo[t * 32 + i] = sprite_y_lo[j];
beamos_y_hi[t * 32 + i] = sprite_y_hi[j];
}
}
void Beamos_Draw(int k) { // 859068
static const int8 kBeamos_Draw_Y[2] = {-16, 0};
static const int8 kBeamos_Draw_Char[2] = {0x48, 0x68};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
int spr_offs = 0;
if (sprite_D[k] < 0x20) {
Oam_AllocateFromRegionB(12);
spr_offs = 1;
} else {
Oam_AllocateFromRegionC(12);
}
OamEnt *oam = GetOamCurPtr() + spr_offs;
for (int i = 1; i >= 0; i--, oam++) {
uint16 x = info.x;
uint16 y = info.y + kBeamos_Draw_Y[i];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kBeamos_Draw_Char[i];
oam->flags = info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
SpriteDraw_Beamos_Eyeball(k, &info);
}
void SpriteDraw_Beamos_Eyeball(int k, PrepOamCoordsRet *info) { // 859151
static const int8 kBeamosEyeball_Draw_X[32] = {
-1, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 12, 13, 14, 15, 16,
17, 15, 14, 13, 12, 11, 10, 8, 7, 5, 4, 3, 2, 1, 0, -2,
};
static const int8 kBeamosEyeball_Draw_Y[32] = {
11, 12, 13, 14, 14, 15, 15, 15, 15, 15, 15, 14, 14, 13, 12, 11,
10, 9, 8, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 8, 9, 10,
};
static const uint8 kBeamosEyeball_Draw_Char[32] = {
0x5b, 0x5b, 0x5a, 0x5a, 0x4b, 0x4b, 0x4a, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x5a, 0x5a, 0x5b, 0x5b,
0x5b, 0x5b, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x5b, 0x5b, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
};
static const uint8 kBeamosEyeball_Draw_Flags[32] = {
0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0, 0, 0, 0, 0, 0, 0, 0,
};
int n = (sprite_D[k] < 0x20) ? 0 : 2;
OamEnt *oam = GetOamCurPtr() + n;
int i = sprite_D[k] >> 1;
BYTE(dungmap_var7) = kBeamosEyeball_Draw_X[i] - 3;
oam->x = BYTE(dungmap_var7) + info->x;
HIBYTE(dungmap_var7) = kBeamosEyeball_Draw_Y[i] - 18;
oam->y = HIBYTE(dungmap_var7) + info->y;
oam->charnum = kBeamosEyeball_Draw_Char[i];
oam->flags = info->flags&0x31|0xA|kBeamosEyeball_Draw_Flags[i];
oam_cur_ptr += n * 4;
oam_ext_cur_ptr += n;
Sprite_CorrectOamEntries(k, 0, 0);
}
void Sprite_Beamos_Laser(int k) { // 8591b5
if (sprite_delay_aux1[k])
return;
BeamosLaser_Draw(k);
if (!sprite_state[k]) {
sprite_limit_instance--;
return;
}
if (Sprite_ReturnIfInactive(k))
return;
for (int i = 3; i >= 0; i--) {
int t = (sprite_subtype2[k]++ & 31) + sprite_graphics[k] * 32;
beamos_y_hi[t] = sprite_y_hi[k];
beamos_y_lo[t] = sprite_y_lo[k];
beamos_x_hi[t] = sprite_x_hi[k];
beamos_x_lo[t] = sprite_x_lo[k];
Sprite_MoveXY(k);
}
if (sprite_delay_main[k]) {
if (sprite_delay_main[k] == 1) {
sprite_state[k] = 0;
sprite_limit_instance--;
}
return;
}
if (!Sprite_CheckDamageToLink_same_layer(k) && !Sprite_CheckTileCollision(k))
return;
SpriteSfx_QueueSfx3WithPan(k, 0x26);
sprite_delay_main[k] = 16;
Sprite_ZeroVelocity_XY(k);
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x61, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_delay_main[j] = 16;
sprite_flags2[j] = 3;
sprite_C[j] = 2;
sprite_flags3[j] = 0x40;
}
sprite_y_hi[k] = 128;
}
void BeamosLaser_Draw(int k) { // 85925b
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
for (int i = 31; i >= 0; i--, oam++) {
int j = g * 32 + i;
uint16 x = (beamos_x_lo[j] | beamos_x_hi[j] << 8) - BG2HOFS_copy2;
uint16 y = (beamos_y_lo[j] | beamos_y_hi[j] << 8) - BG2VOFS_copy2;
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = 0x5c;
oam->flags = info.flags;
bytewise_extended_oam[oam - oam_buf] = (x >> 8 & 1);
}
}
void Sprite_Beamos_LaserHit(int k) { // 8592da
static const int8 kBeamosLaserHit_Draw_X[4] = {-4, 4, -4, 4};
static const int8 kBeamosLaserHit_Draw_Y[4] = {-4, -4, 4, 4};
static const uint8 kBeamosLaserHit_Draw_Flags[4] = {6, 0x46, 0x86, 0xc6};
if (!sprite_delay_main[k])
sprite_state[k] = 0;
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
for (int i = 3; i >= 0; i--, oam++) {
uint16 x = info.x + kBeamosLaserHit_Draw_X[i];
uint16 y = info.y + kBeamosLaserHit_Draw_Y[i];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = 0xd6;
oam->flags = kBeamosLaserHit_Draw_Flags[i] | info.flags & 0x30;
bytewise_extended_oam[oam - oam_buf] = (x >> 8 & 1);
}
}
void Sprite_5B_Spark_Clockwise(int k) { // 85933f
static const uint8 kSpark_OamFlags[4] = {0, 0x40, 0x80, 0xc0};
static const uint8 kSpark_directions[8] = {1, 3, 2, 0, 7, 5, 6, 4};
int j;
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!(frame_counter & 1))
sprite_oam_flags[k] ^= 6;
if (!sprite_ai_state[k]) {
sprite_ai_state[k] = 1;
sprite_x_vel[k] = sprite_y_vel[k] = 1;
uint8 coll = Sprite_CheckTileCollision(k);
sprite_x_vel[k] = sprite_y_vel[k] = -1;
coll |= Sprite_CheckTileCollision(k);
if (coll < 4)
j = (coll & 1) ? 0 : 1;
else
j = (coll & 4) ? 2 : 3;
sprite_D[k] = kSpark_directions[(sprite_type[k] != 0x5c) * 4 + j];
}
sprite_oam_flags[k] = sprite_oam_flags[k] & 0x3f | kSpark_OamFlags[frame_counter >> 2 & 3];
Sprite_MoveXY(k);
Sprite_CheckDamageToLink(k);
j = sprite_D[k];
sprite_x_vel[k] = kSoldierB_Xvel[j];
sprite_y_vel[k] = kSoldierB_Yvel[j];
Sprite_CheckTileCollision(k);
j = sprite_D[k];
if (sprite_delay_aux2[k]) {
if (sprite_delay_aux2[k] == 6)
j = kSoldierB_NextB[j];
} else {
if (!(sprite_wallcoll[k] & kSoldierB_Mask[j]))
sprite_delay_aux2[k] = 10;
}
if (sprite_wallcoll[k] & kSoldierB_Mask2[j])
j = kSoldierB_NextB2[j];
sprite_D[k] = j;
sprite_x_vel[k] = kSoldierB_Xvel2[j] * 2;
sprite_y_vel[k] = kSoldierB_Yvel2[j] * 2;
}
void Sprite_59_LostWoodsBird(int k) { // 85940e
if (sprite_delay_aux1[k])
return;
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | (sign8(sprite_x_vel[k]) ? 0 : 0x40);
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXY(k);
Sprite_MoveZ(k);
switch (sprite_ai_state[k]) {
case 0:
sprite_graphics[k] = 0;
if (sign8(--sprite_z_vel[k] - 0xf1))
sprite_ai_state[k] = 1;
break;
case 1:
sprite_z_vel[k] += 2;
if (!sign8(sprite_z_vel[k] - 0x10))
sprite_ai_state[k] = 0;
sprite_graphics[k] = ++sprite_subtype2[k] >> 1 & 1;
break;
}
}
void Sprite_5A_LostWoodsSquirrel(int k) { // 859468
if (sprite_delay_aux1[k])
return;
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | (sign8(sprite_x_vel[k]) ? 0 : 0x40);
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXY(k);
Sprite_MoveZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 16;
sprite_delay_main[k] = 12;
}
sprite_graphics[k] = sprite_delay_main[k] ? 1 : 0;
}
void Sprite_58_Crab(int k) { // 8594b5
static const int8 kCrab_Xvel[4] = {28, -28, 0, 0};
static const int8 kCrab_Yvel[4] = {0, 0, 12, -12};
Crab_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k) || !sprite_delay_main[k]) {
sprite_delay_main[k] = (GetRandomNumber() & 63) + 32;
sprite_D[k] = sprite_delay_main[k] & 3;
}
int j = sprite_D[k];
sprite_x_vel[k] = kCrab_Xvel[j & 3];
sprite_y_vel[k] = kCrab_Yvel[j & 3];
sprite_graphics[k] = (++sprite_subtype2[k] >> (j < 2 ? 1 : 3)) & 1;
}
void Crab_Draw(int k) { // 859510
static const int16 kCrab_Draw_X[4] = {-8, 8, -8, 8};
static const uint8 kCrab_Draw_Char[4] = {0x8e, 0x8e, 0xae, 0xae};
static const int8 kCrab_Draw_Flags[4] = {0, 0x40, 0, 0x40};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int d = sprite_graphics[k] * 2;
for (int i = 1; i >= 0; i--, oam++) {
int j = d + i;
uint16 x = info.x + kCrab_Draw_X[j];
uint16 y = info.y;
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kCrab_Draw_Char[j];
oam->flags = kCrab_Draw_Flags[j] | info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
SpriteDraw_Shadow(k, &info);
}
void Sprite_57_DesertStatue(int k) { // 85956d
static const uint8 kDesertBarrier_NextD[4] = {3, 2, 0, 1};
DesertBarrier_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
bool dmg = Sprite_CheckDamageToLink_same_layer(k);
if (dmg) {
Sprite_NullifyHookshotDrag();
Sprite_RepelDash();
}
if (sprite_delay_main[k] || sign8(sprite_ai_state[k]))
return;
if (sprite_ai_state[k] == 0) {
if (!byte_7E02F0)
return;
sprite_ai_state[k] = byte_7E02F0;
sprite_delay_main[k] = 128;
sound_effect_ambient = 7;
}
if (dmg && !link_incapacitated_timer) {
link_incapacitated_timer = 16;
Sprite_ApplySpeedTowardsLink(k, 32);
}
int j = sprite_D[k];
sprite_x_vel[k] = kDesertBarrier_Xv[j];
sprite_y_vel[k] = kDesertBarrier_Yv[j];
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k))
sprite_D[k] = kDesertBarrier_NextD[sprite_D[k]];
flag_is_link_immobilized = 1;
if (!(++sprite_subtype2[k] & 1)) {
if (++sprite_G[k] == 130) {
sprite_ai_state[k] = 128;
flag_is_link_immobilized = 0;
}
}
}
void DesertBarrier_Draw(int k) { // 859626
static const DrawMultipleData kDesertBarrier_Dmd[4] = {
{-8, -8, 0x008e, 2},
{ 8, -8, 0x408e, 2},
{-8, 8, 0x00ae, 2},
{ 8, 8, 0x40ae, 2},
};
if (sprite_delay_main[k] == 1) {
sound_effect_2 = 0x1b;
sound_effect_ambient = 5;
}
BYTE(cur_sprite_x) += (sprite_delay_main[k] >> 1) & 1;
PointU8 pt;
Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.x + 0x20) < 0x40 && (uint8)(pt.y + 0x20) < 0x40)
Oam_AllocateFromRegionB(16);
Sprite_DrawMultiple(k, kDesertBarrier_Dmd, 4, NULL);
}
void Sprite_55_Zora(int k) { // 85967b
if (sprite_E[k])
Sprite_Fireball(k);
else
Sprite_Zora_Main(k);
}
void Sprite_Fireball(int k) { // 859683
static const uint8 kSprite_ZoraFireball_Offs[4] = {3, 2, 0, 0};
static const int8 kSprite_ZoraFireball_X[4] = {4, 4, -4, 16};
static const int8 kSprite_ZoraFireball_Y[4] = {0, 16, 8, 8};
static const uint8 kSprite_ZoraFireball_W[4] = {8, 8, 4, 4};
static const uint8 kSprite_ZoraFireball_H[4] = {4, 4, 8, 8};
sprite_ignore_projectile[k] = sprite_E[k];
if (sprite_delay_main[k])
Oam_AllocateFromRegionC(4);
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
Fireball_SpawnTrailGarnish(k);
if (Sprite_CheckDamageToLink(k)) {
sprite_state[k] = 0;
return;
}
Sprite_MoveXY(k);
if (player_is_indoors && !sprite_delay_aux1[k] && !((k ^ frame_counter) & 3) && Sprite_CheckTileCollision(k)) {
sprite_state[k] = 0;
return;
}
if ((link_is_bunny_mirror | link_disable_sprite_damage) || sign8(link_state_bits) || link_shield_type < 2 ||
link_is_on_lower_level != sprite_floor[k])
return;
SpriteHitBox hb;
Sprite_SetupHitBox(k, &hb);
int j = link_direction_facing >> 1;
if (button_b_frames)
j = kSprite_ZoraFireball_Offs[j];
int x = link_x_coord + kSprite_ZoraFireball_X[j], y = link_y_coord + kSprite_ZoraFireball_Y[j];
hb.r0_xlo = x;
hb.r8_xhi = x >> 8;
hb.r2 = kSprite_ZoraFireball_W[j];
hb.r1_ylo = y;
hb.r9_yhi = y >> 8;
hb.r3 = kSprite_ZoraFireball_H[j];
if (CheckIfHitBoxesOverlap(&hb)) {
Sprite_PlaceRupulseSpark_2(k);
sprite_state[k] = 0;
SpriteSfx_QueueSfx2WithPan(k, 0x6);
}
}
void Sprite_Zora_Main(int k) { // 859725
static const int8 kSprite_Zora_Surface_XY[8] = {-32, -24, -16, -8, 8, 16, 24, 32};
static const uint8 kSprite_Zora_AttackGfx[8] = {5, 5, 6, 10, 6, 5, 5, 5};
static const uint8 kSprite_Zora_SubmergeGfx[12] = {12, 11, 9, 8, 7, 0, 0, 0, 0, 0, 0, 0};
PrepOamCoordsRet info;
if (!sprite_ai_state[k])
Sprite_PrepOamCoord(k, &info);
else
Zora_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch (sprite_ai_state[k]) {
case 0: // choose surfacing location
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
Sprite_SetX(k, (sprite_A[k] | sprite_B[k] << 8) + kSprite_Zora_Surface_XY[GetRandomNumber() & 7]);
Sprite_SetY(k, (sprite_C[k] | sprite_head_dir[k] << 8) + kSprite_Zora_Surface_XY[GetRandomNumber() & 7]);
Sprite_Get16BitCoords(k);
Sprite_CheckTileCollision(k);
if (sprite_tiletype == 8) {
sprite_delay_main[k] = 127;
sprite_ai_state[k]++;
sprite_flags3[k] |= 0x40;
}
}
break;
case 1: // surfacing
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 127;
sprite_flags3[k] &= ~0x40;
} else {
sprite_graphics[k] = kSprite_Zora_SurfacingGfx[sprite_delay_main[k] >> 3];
}
break;
case 2: // attack
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 23;
} else {
if (sprite_delay_main[k] == 48)
Sprite_SpawnFireball(k);
sprite_graphics[k] = kSprite_Zora_AttackGfx[sprite_delay_main[k] >> 4];
}
break;
case 3: // submerging
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 128;
sprite_graphics[k] = 0;
sprite_ai_state[k] = 0;
} else {
sprite_graphics[k] = kSprite_Zora_SubmergeGfx[sprite_delay_main[k] >> 2];
}
break;
}
}
void Zora_Draw(int k) { // 8598f5
static const int8 kZora_Draw_X[26] = {
4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, -4, 11, 0, 4, -8, 18, -8, 18,
};
static const int8 kZora_Draw_Y[26] = {
4, 4, 0, 0, 0, 0, 0, -3, 0, -3, -3, -3, -3, -3, -3, -3,
-6, -6, -8, -9, -3, 5, -10, -11, -10, -11,
};
static const uint8 kZora_Draw_Char[26] = {
0xa8, 0xa8, 0x88, 0x88, 0x88, 0x88, 0x88, 0xa4, 0x88, 0xa4, 0xa4, 0xa4, 0xa6, 0xa6, 0xa4, 0xc0,
0x8a, 0x8a, 0xae, 0xaf, 0xa6, 0x8d, 0xcf, 0xcf, 0xdf, 0xdf,
};
static const uint8 kZora_Draw_Flags[26] = {
0x25, 0x25, 0x25, 0x25, 0xe5, 0xe5, 0x25, 0x20, 0xe5, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x24,
0x25, 0x25, 0x24, 0x64, 0x20, 0x26, 0x24, 0x64, 0x24, 0x64,
};
static const uint8 kZora_Draw_Ext[26] = {
0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 0, 0, 2, 0, 0, 0, 0, 0,
};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int d = sprite_graphics[k] * 2;
for (int i = 1; i >= 0; i--, oam++) {
int j = d + i;
uint16 x = info.x + kZora_Draw_X[j];
uint16 y = info.y + kZora_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kZora_Draw_Char[j];
uint8 f = kZora_Draw_Flags[j];
oam->flags = f | (f & 0xf ? 0 : info.flags);
bytewise_extended_oam[oam - oam_buf] = kZora_Draw_Ext[j] | (x >> 8 & 1);
}
}
void Sprite_52_KingZora(int k) { // 85995b
ZoraKing_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch(sprite_ai_state[k]) {
case 0: // WaitingForPlayer
if ((uint16)(link_x_coord - cur_sprite_x + 16) < 32 && (uint16)(link_y_coord - cur_sprite_y + 48) < 96) {
Link_CancelDash();
sprite_delay_main[k] = 127;
sound_effect_1 = 0x35;
sprite_ai_state[k] = 1;
for (int j = 15; j >= 0; j--) {
if (j != k && !(sprite_defl_bits[j] & 0x80)) {
if (sprite_state[j] == 10) {
link_state_bits = 0;
link_picking_throw_state = 0;
}
Sprite_KillSelf(j);
}
}
}
break;
case 1: // RumblingGround
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 127;
bg1_x_offset = 0;
sprite_graphics[k] = 4;
} else {
bg1_x_offset = sprite_delay_main[k] & 1 ? -1 : 1;
flag_is_link_immobilized = 1;
}
break;
case 2: { // Surfacing
static const uint8 kZoraKing_Surfacing_Gfx[16] = {0, 0, 0, 3, 9, 8, 7, 6, 9, 8, 7, 6, 5, 4, 5, 4};
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 127;
} else {
if (sprite_delay_main[k] == 28) {
sprite_delay_aux2[k] = 15;
Sprite_SpawnBigSplash(k);
}
sprite_graphics[k] = kZoraKing_Surfacing_Gfx[sprite_delay_main[k] >> 3];
}
break;
}
case 3: { // Dialogue
static const uint8 kZoraKing_Dialogue_Gfx[8] = {0, 0, 1, 2, 1, 2, 0, 0};
int j = sprite_delay_main[k];
if (!j) {
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 36;
return;
}
sprite_graphics[k] = kZoraKing_Dialogue_Gfx[j >> 4];
if (j == 80) {
dialogue_message_index = 0x142;
Sprite_ShowMessageMinimal();
} else if (j == 79) {
if (choice_in_multiselect_box == 0) {
dialogue_message_index = 0x143;
Sprite_ShowMessageMinimal();
} else {
dialogue_message_index = 0x146;
Sprite_ShowMessageMinimal();
sprite_delay_main[k] = 0x30;
}
} else if (j == 78) {
if (choice_in_multiselect_box == 0 && link_rupees_goal >= 500) {
link_rupees_goal -= 500;
dialogue_message_index = 0x144;
Sprite_ShowMessageMinimal();
sprite_E[k] = 1;
} else {
dialogue_message_index = 0x145;
Sprite_ShowMessageMinimal();
sprite_delay_main[k] = 0x30;
}
} else if (j == 77) {
if (sprite_E[k])
Sprite_Zora_RegurgitateFlippers(k);
}
break;
}
case 4: { // Submerge
static const uint8 kZoraKing_Submerge_Gfx[21] = {
12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 10, 10, 10, 10, 3,
3, 3, 3, 3, 3,
};
int j = sprite_delay_main[k];
if (!j) {
Sprite_KillSelf(k);
flag_is_link_immobilized = 0;
} else {
if (j == 29) {
sprite_delay_aux2[k] = 15;
Sprite_SpawnBigSplash(k);
}
sprite_graphics[k] = kZoraKing_Submerge_Gfx[sprite_delay_main[k] >> 1];
}
break;
}
}
}
void Sprite_SpawnBigSplash(int k) { // 859b40
static const int8 kSpawnSplashRing_X[8] = {-8, -5, 4, 13, 16, 13, 4, -5};
static const int8 kSpawnSplashRing_Y[8] = {4, -5, -8, -5, 4, 13, 16, 13};
static const int8 kSpawnSplashRing_Xvel[8] = {-8, -6, 0, 6, 8, 6, 0, -6};
static const int8 kSpawnSplashRing_Yvel[8] = {0, -6, -8, -6, 0, 6, 8, 6};
SpriteSfx_QueueSfx2WithPan(k, 0x24);
for (int i = 7; i >= 0; i--) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 8, &info);
if (j >= 0) {
sprite_state[j] = 3;
Sprite_SetX(j, info.r0_x + kSpawnSplashRing_X[i] - 4);
Sprite_SetY(j, info.r2_y + kSpawnSplashRing_Y[i] - 4);
sprite_x_vel[j] = kSpawnSplashRing_Xvel[i];
sprite_y_vel[j] = kSpawnSplashRing_Yvel[i];
sprite_A[j] = i;
sprite_z_vel[j] = (GetRandomNumber() & 15) + 24;
sprite_ai_state[j] = 1;
sprite_z[j] = 0;
sprite_flags3[j] |= 0x40;
sprite_ignore_projectile[j] = sprite_flags3[j];
}
}
}
void ZoraKing_Draw(int k) { // 859cab
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
if (sprite_ai_state[k] >= 2) {
static const int8 kZoraKing_Draw_X0[52] = {
-8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8,
0, 0, 0, 0, 0, 0, 0, 0, -8, 8, -8, 8, -8, 8, -8, 8,
-8, 8, -8, 8, -8, 8, -8, 8, -9, 9, -9, 9, -10, 10, -10, 10,
-11, 11, -11, 11,
};
static const int8 kZoraKing_Draw_Y0[52] = {
-18, -18, -2, -2, -18, -18, -2, -2, -18, -18, -2, -2, -12, -12, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, -8, -8, 8, 8, -8, -8, 8, 8,
-8, -8, 8, 8, -8, -8, 8, 8, -5, -5, 5, 5, -5, -5, 5, 5,
-5, -5, 5, 5,
};
static const uint8 kZoraKing_Draw_Char0[52] = {
0xc0, 0xc0, 0xe0, 0xe0, 0xc2, 0xea, 0xe2, 0xe2, 0xea, 0xc2, 0xe2, 0xe2, 0xc0, 0xc0, 0xe4, 0xe6,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xc4, 0xc6, 0xe4, 0xe6, 0xc6, 0xc4, 0xe6, 0xe4,
0xe6, 0xe4, 0xc6, 0xc4, 0xe4, 0xe6, 0xc4, 0xc6, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88,
};
static const uint8 kZoraKing_Draw_Flags0[52] = {
0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40, 5, 5,
5, 5, 5, 5, 0xc5, 0xc5, 0xc5, 0xc5, 5, 5, 5, 5, 0x45, 0x45, 0x45, 0x45,
0xc5, 0xc5, 0xc5, 0xc5, 0x85, 0x85, 0x85, 0x85, 4, 0x44, 0x84, 0xc4, 4, 0x44, 0x84, 0xc4,
4, 0x44, 0x84, 0xc4,
};
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
for (int i = 3; i >= 0; i--, oam++) {
int j = g * 4 + i;
oam->x = kZoraKing_Draw_X0[j] + info.x;
oam->y = kZoraKing_Draw_Y0[j] + info.y;
oam->charnum = kZoraKing_Draw_Char0[j];
uint8 f = kZoraKing_Draw_Flags0[j];
oam->flags = (f & 0xf ? f : f | info.flags) | 0x20;
}
Sprite_CorrectOamEntries(k, 3, 2);
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
}
if (!sprite_delay_aux2[k])
return;
static const int8 kZoraKing_Draw_X1[8] = {-23, 23, 23, 23, -20, -15, 13, 18};
static const int8 kZoraKing_Draw_Y1[8] = {-8, -8, -8, -8, -7, 0, 0, -7};
static const uint8 kZoraKing_Draw_Char1[8] = {0xae, 0xae, 0xae, 0xae, 0xac, 0xac, 0xac, 0xac};
static const uint8 kZoraKing_Draw_Flags1[8] = {0, 0x40, 0x40, 0x40, 0, 0, 0x40, 0x40};
Oam_AllocateFromRegionC(0x10);
OamEnt *oam = GetOamCurPtr();
int g = (sprite_delay_aux2[k] >> 1) & 4;
for (int i = 3; i >= 0; i--, oam++) {
int j = g + i;
oam->x = kZoraKing_Draw_X1[j] + info.x;
oam->y = kZoraKing_Draw_Y1[j] + info.y;
oam->charnum = kZoraKing_Draw_Char1[j];
oam->flags = kZoraKing_Draw_Flags1[j] | 0x24;
bytewise_extended_oam[oam - oam_buf] = 2;
}
}
void Sprite_56_WalkingZora(int k) { // 859d4a
if (sprite_F[k]) {
sprite_F[k] = 0;
sprite_B[k] = 3;
sprite_G[k] = 192;
sprite_x_vel[k] = (int8)sprite_x_recoil[k] >> 1;
sprite_y_vel[k] = (int8)sprite_y_recoil[k] >> 1;
}
PrepOamCoordsRet info;
switch(sprite_B[k]) {
case 0: // Waiting
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 127;
sprite_B[k]++;
sprite_flags3[k] |= 64;
}
break;
case 1: // Surfacing
Zora_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
sprite_flags3[k] &= ~0x40;
SpriteSfx_QueueSfx2WithPan(k, 0x28);
sprite_B[k]++;
sprite_z_vel[k] = 48;
sprite_head_dir[k] = sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
} else {
sprite_graphics[k] = kSprite_Zora_SurfacingGfx[sprite_delay_main[k] >> 3];
}
break;
case 2: // Ambulating
sprite_graphics[k] = kSprite_Recruit_Gfx[(sprite_subtype2[k] >> 1 & 4) + sprite_D[k]];
WalkingZora_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k] - 1)) {
if (sign8(sprite_z_vel[k] + 16))
Sprite_ZeroVelocity_XY(k);
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
if (!((k ^ frame_counter) & 15)) {
int j = Sprite_DirectionToFaceLink(k, NULL);
sprite_head_dir[k] = j;
if (!((k ^ frame_counter) & 31)) {
sprite_D[k] = j;
Sprite_ApplySpeedTowardsLink(k, 8);
}
}
}
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
if (sign8(sprite_z[k] - 1)) {
WalkingZora_AdjustShadow(k);
if (sprite_tiletype == 8) {
Sprite_KillSelf(k);
SpriteSfx_QueueSfx2WithPan(k, 0x28);
sprite_state[k] = 3;
sprite_delay_main[k] = 15;
sprite_ai_state[k] = 0;
sprite_flags2[k] = 3;
}
}
sprite_subtype2[k]++;
break;
case 3: // Depressed
Sprite_CheckDamageFromLink(k);
if (!(frame_counter & 3) && !--sprite_G[k]) {
sprite_B[k] = 2;
if (sprite_state[k] == 10) {
link_state_bits = 0;
link_picking_throw_state = 0;
}
sprite_state[k] = 9;
}
if (sprite_G[k] < 48 && !(frame_counter & 1))
Sprite_SetX(k, Sprite_GetX(k) + (frame_counter & 2 ? -1 : 1));
sprite_graphics[k] = 0;
sprite_wallcoll[k] = 0;
WalkingZora_DrawWaterRipples(k);
sprite_flags2[k] -= 2;
SpriteDraw_SingleLarge(k);
sprite_flags2[k] += 2;
sprite_anim_clock[k] = 0;
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_MoveXY(k);
ThrownSprite_TileAndSpriteInteraction(k);
WalkingZora_AdjustShadow(k);
break;
}
}
void WalkingZora_AdjustShadow(int k) { // 859edb
sprite_anim_clock[k] = (sprite_z[k] == 0 && sprite_tiletype == 9);
}
void WalkingZora_Draw(int k) { // 859f08
static const uint8 kWalkingZora_Draw_Char[4] = {0xce, 0xce, 0xa4, 0xee};
static const uint8 kWalkingZora_Draw_Flags[4] = {0x40, 0, 0, 0};
static const uint8 kWalkingZora_Draw_Char2[8] = {0xcc, 0xec, 0xcc, 0xec, 0xe8, 0xe8, 0xca, 0xca};
static const uint8 kWalkingZora_Draw_Flags2[8] = {0x40, 0x40, 0, 0, 0, 0x40, 0, 0x40};
PrepOamCoordsRet info;
WalkingZora_DrawWaterRipples(k);
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
if (g == 0 || g == 2)
info.y--;
int i = sprite_head_dir[k];
oam->x = info.x;
oam->y = ClampYForOam(info.y - 6);
oam->charnum = kWalkingZora_Draw_Char[i];
oam->flags = info.flags | kWalkingZora_Draw_Flags[i];
bytewise_extended_oam[oam - oam_buf] = 2 | (info.x >> 8 & 1);
oam++;
oam->x = info.x;
oam->y = ClampYForOam(info.y + 2);
oam->charnum = kWalkingZora_Draw_Char2[g];
oam->flags = info.flags | kWalkingZora_Draw_Flags2[g];
bytewise_extended_oam[oam - oam_buf] = 2 | (info.x >> 8 & 1);
if (!sprite_anim_clock[k])
SpriteDraw_Shadow(k, &info);
}
void WalkingZora_DrawWaterRipples(int k) { // 859fe0
if (sprite_anim_clock[k])
SpriteDraw_WaterRipple_WithOamAdjust(k);
}
void SpriteDraw_WaterRipple_WithOamAdjust(int k) { // 859fe5
SpriteDraw_WaterRipple(k);
oam_cur_ptr += 8;
oam_ext_cur_ptr += 2;
}
void SpriteDraw_WaterRipple(int k) { // 859ffa
static const DrawMultipleData kWaterRipple_Dmd[6] = {
{0, 10, 0x01d8, 0},
{8, 10, 0x41d8, 0},
{0, 10, 0x01d9, 0},
{8, 10, 0x41d9, 0},
{0, 10, 0x01da, 0},
{8, 10, 0x41da, 0},
};
static const uint8 kWaterRipple_Idx[4] = {0, 1, 2, 1};
Sprite_DrawMultiple(k, &kWaterRipple_Dmd[kWaterRipple_Idx[frame_counter >> 2 & 3] * 2], 2, NULL);
OamEnt *oam = GetOamCurPtr();
uint8 t = (oam[0].flags & 0x30) | 0x4;
oam[0].flags = t;
oam[1].flags = t | 0x40;
}
void Sprite_53_ArmosKnight(int k) { // 85a036
static const uint8 kArmosKnight_Gfx1[5] = {5, 4, 3, 2, 1};
static const int8 kArmosKnight_Xv[2] = {16, -16};
sprite_obj_prio[k] |= 0x30;
ArmosKnight_Draw(k);
if (Sprite_ReturnIfPaused(k))
return;
if (sprite_state[k] != 9) {
if (sprite_delay_main[k]) {
sprite_graphics[k] = kArmosKnight_Gfx1[sprite_delay_main[k] >> 3];
return;
}
if (--byte_7E0FF8 == 1) {
for (int j = 5; j >= 0; j--) {
sprite_health[j] = 48;
sprite_x_vel[j] = sprite_y_vel[j] = sprite_z_vel[j] = 0;
}
}
sprite_state[k] = 0;
if (Sprite_CheckIfScreenIsClear()) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xea, &info);
assert(j >= 0);
Sprite_SetSpawnedCoordinates(j, &info);
sprite_z_vel[j] = 32;
sprite_A[j] = 1;
}
return;
}
Sprite_MoveXY(k);
Sprite_MoveZ(k);
sprite_z_vel[k] -= 4;
if (sign8(sprite_z[k])) {
sprite_z_vel[k] = 0;
sprite_z[k] = 0;
if (byte_7E0FF8 != 1 && sprite_A[k]) {
sprite_z_vel[k] = 48;
SpriteSfx_QueueSfx3WithPan(k, 0x16);
}
}
if (sprite_F[k]) {
Sprite_ZeroVelocity_XY(k);
sprite_ai_state[k] = 0;
sprite_G[k] = 0;
}
if (Sprite_ReturnIfRecoiling(k))
return;
if (!sprite_A[k]) {
if (!sprite_delay_main[k]) {
sprite_A[k]++;
sprite_flags2[k] = (sprite_flags2[k] & 0x7f) - 2;
sprite_defl_bits[k] &= ~4;
sprite_flags3[k] &= ~0x40;
} else {
if (sprite_delay_main[k] == 64) {
sound_effect_1 = 0x35;
} else if (sprite_delay_main[k] < 64) {
int j = ((sprite_delay_main[k] >> 1) ^ k) & 1;
sprite_x_vel[k] = kArmosKnight_Xv[j];
Sprite_MoveX(k);
sprite_x_vel[k] = 0;
}
Sprite_CheckDamageFromLink(k);
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
Sprite_RepelDash();
}
}
} else if (byte_7E0FF8 == 1) {
Sprite_ArmosCrusher(k);
} else {
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_ai_state[k]) {
uint16 x = overlord_y_hi[k] << 8 | overlord_x_hi[k];
uint16 y = overlord_floor[k] << 8 | overlord_gen2[k];
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 16);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
Sprite_Get16BitCoords(k);
if ((uint16)(x - cur_sprite_x + 2) < 4 && (uint16)(y - cur_sprite_y + 2) < 4)
sprite_ai_state[k] = 1;
} else {
sprite_x_lo[k] = overlord_x_hi[k];
sprite_x_hi[k] = overlord_y_hi[k];
sprite_y_lo[k] = overlord_gen2[k];
sprite_y_hi[k] = overlord_floor[k];
}
}
}
void ArmosKnight_Draw(int k) { // 85a274
static const int8 kArmosKnight_Draw_X[24] = {
-8, 8, -8, 8, -10, 10, -10, 10, -10, 10, -10, 10, -12, 12, -12, 12,
-14, 14, -14, 14, -16, 24, -16, 24,
};
static const int8 kArmosKnight_Draw_Y[24] = {
-8, -8, 8, 8, -10, -10, 10, 10, -10, -10, 10, 10, -12, -12, 12, 12,
-14, -14, 14, 14, -16, -16, 24, 24,
};
static const uint8 kArmosKnight_Draw_Char[24] = {
0xc0, 0xc2, 0xe0, 0xe2, 0xc0, 0xc2, 0xe0, 0xe2, 0xc4, 0xc4, 0xc4, 0xc4, 0xc6, 0xc6, 0xc6, 0xc6,
0xc8, 0xc8, 0xc8, 0xc8, 0xd8, 0xd8, 0xd8, 0xd8,
};
static const uint8 kArmosKnight_Draw_Flags[24] = {
0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0xc0, 0x80, 0x40, 0, 0xc0, 0x80,
0x40, 0, 0xc0, 0x80, 0x40, 0, 0xc0, 0x80,
};
static const uint8 kArmosKnight_Draw_Ext[24] = {
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 0, 0, 0, 0,
};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
if (!sprite_A[k] && submodule_index != 7)
Oam_AllocateDeferToPlayer(k);
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
for (int i = 3; i >= 0; i--, oam++) {
int j = g * 4 + i;
uint16 x = info.x + kArmosKnight_Draw_X[j];
uint16 y = info.y + kArmosKnight_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kArmosKnight_Draw_Char[j];
oam->flags = kArmosKnight_Draw_Flags[j] | info.flags;
bytewise_extended_oam[oam - oam_buf] = kArmosKnight_Draw_Ext[j] | (x >> 8 & 1);
}
if (g != 0)
return;
if (sprite_A[k]) {
int spr_idx = 76 + k * 2;
oam_cur_ptr = 0x800 + spr_idx * 4;
oam_ext_cur_ptr = 0xA20 + spr_idx;
}
oam = GetOamCurPtr();
int z = sprite_z[k];
z = ((z >= 32) ? 32 : z) >> 3;
uint16 y = Sprite_GetY(k) - BG2VOFS_copy2;
oam[4].x = info.x - 8 + z;
oam[5].x = info.x + 8 - z;
if ((uint16)(y + 12 + 16) < 0x100) {
oam[5].y = oam[4].y = y + 12;
} else {
oam[5].y = oam[4].y = 0xf0;
}
oam[5].charnum = oam[4].charnum = 0xe4;
oam[4].flags = 0x25;
oam[5].flags = 0x25 | 0x40;
bytewise_extended_oam[oam + 4 - oam_buf] = 2;
bytewise_extended_oam[oam + 5 - oam_buf] = 2;
}
void Sprite_54_Lanmolas(int k) { // 85a3a2
static const uint8 kLanmola_RandB[8] = {0x58, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0x98};
static const uint8 kLanmola_RandC[8] = {0x68, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xa8, 0x80};
static const int8 kLanmola_ZVel[2] = {2, -2};
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
Lanmola_Draw(k);
if (Sprite_ReturnIfPaused(k))
return;
switch(sprite_ai_state[k]) {
case 0:
if (!(sprite_delay_main[k] | sprite_pause[k])) {
sprite_delay_main[k] = 127;
sprite_ai_state[k] = 1;
SpriteSfx_QueueSfx2WithPan(k, 0x35);
}
break;
case 1:
if (!sprite_delay_main[k]) {
Lanmola_SpawnShrapnel(k);
sound_effect_ambient = 0x13;
sprite_B[k] = kLanmola_RandB[GetRandomNumber() & 7];
sprite_C[k] = kLanmola_RandC[GetRandomNumber() & 7];
sprite_ai_state[k] = 2;
sprite_z_vel[k] = 24;
sprite_anim_clock[k] = 0;
sprite_G[k] = 0;
lbl_a:
sprite_D[k] = sprite_x_lo[k];
sprite_wallcoll[k] = sprite_y_lo[k];
sprite_delay_aux1[k] = 74;
}
break;
case 2: {
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveZ(k);
if (!sprite_anim_clock[k]) {
if (!--sprite_z_vel[k])
sprite_anim_clock[k]++;
} else if ((frame_counter & 1) == 0) {
int j = sprite_G[k] & 1;
if ((sprite_z_vel[k] += kLanmola_ZVel[j]) == (uint8)kDesertBarrier_Xv[j])
sprite_G[k]++;
}
uint16 x = Sprite_GetX(k), y = Sprite_GetY(k);
uint16 x2 = sprite_x_hi[k] << 8 | sprite_B[k];
uint16 y2 = sprite_y_hi[k] << 8 | sprite_C[k];
if ((uint16)(x - x2 + 2) < 4 && (uint16)(y - y2 + 2) < 4)
sprite_ai_state[k] = 3;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x2, y2, 10);
sprite_y_vel[k] = pt.y;
sprite_x_vel[k] = pt.x;
Sprite_MoveXY(k);
break;
}
case 3:
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
Sprite_MoveZ(k);
if (!sign8(sprite_z_vel[k] + 20))
sprite_z_vel[k] -= 1;
if (sign8(sprite_z[k])) {
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 128;
goto lbl_a;
}
break;
case 4:
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_x_lo[k] = kLanmola_RandB[GetRandomNumber() & 7];
sprite_y_lo[k] = kLanmola_RandC[GetRandomNumber() & 7];
}
break;
case 5:
if (!sprite_delay_main[k]) {
sprite_state[k] = 0;
if (Sprite_CheckIfScreenIsClear()) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xEA, &info);
assert(j >= 0);
Sprite_SetSpawnedCoordinates(j, &info);
sprite_z_vel[j] = 32;
sprite_A[j] = 3;
}
}
if (sprite_delay_main[k] >= 32 && sprite_delay_main[k] < 160 && !(sprite_delay_main[k] & 15)) {
int i = ((sprite_subtype2[k] - garnish_y_lo[k] * 8) & 0x3f) + k * 0x40;
uint8 xlo = moldorm_x_lo[i] - BG2HOFS_copy2;
uint8 ylo = moldorm_y_lo[i] - beamos_x_hi[i] - BG2VOFS_copy2;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x00, &info);
if (j >= 0) {
load_chr_halfslot_even_odd = 11;
sprite_state[j] = 4;
sprite_delay_main[j] = 31;
sprite_A[j] = 31;
Sprite_SetX(j, BG2HOFS_copy2 + xlo);
Sprite_SetY(j, BG2VOFS_copy2 + ylo);
sprite_flags2[j] = 3;
sprite_oam_flags[j] = 0xc;
SpriteSfx_QueueSfx2WithPan(k, 0xc);
if (!sign8(garnish_y_lo[k]))
garnish_y_lo[k]--;
}
}
break;
}
}
void Lanmola_Draw(int k) { // 85a64a
static const uint8 kLanmola_SprOffs[4] = {76, 60, 44, 28};
static const uint8 kLanmola_Draw_Char1[16] = {0xc4, 0xe2, 0xc2, 0xe0, 0xc0, 0xe0, 0xc2, 0xe2, 0xc4, 0xe2, 0xc2, 0xe0, 0xc0, 0xe0, 0xc2, 0xe2};
static const uint8 kLanmola_Draw_Char0[16] = {0xcc, 0xe4, 0xca, 0xe6, 0xc8, 0xe6, 0xca, 0xe4, 0xcc, 0xe4, 0xca, 0xe6, 0xc8, 0xe6, 0xca, 0xe4};
static const uint8 kLanmola_Draw_Flags[16] = {0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0, 0, 0, 0, 0x40, 0x40, 0x40, 0x40};
int spr_offs = kLanmola_SprOffs[k];
oam_cur_ptr = 0x800 + spr_offs * 4;
oam_ext_cur_ptr = 0xA20 + spr_offs;
sprite_graphics[k] = Sprite_ConvertVelocityToAngle(sprite_x_vel[k], sprite_y_vel[k] - sprite_z_vel[k]);
uint8 r2 = sprite_subtype2[k], r5 = r2;
int j = k * 64 + r2;
moldorm_x_lo[j] = sprite_x_lo[k];
moldorm_y_lo[j] = sprite_y_lo[k];
beamos_x_hi[j] = sprite_z[k];
beamos_y_hi[j] = sprite_graphics[k];
if (sprite_state[k] == 9 && !(submodule_index | flag_unk1))
sprite_subtype2[k] = sprite_subtype2[k] + 1 & 63;
uint8 r3 = sprite_oam_flags[k] | sprite_obj_prio[k];
uint8 n = garnish_y_lo[k];
if (sign8(n))
return;
j = sign8(sprite_y_vel[k]) ? 1 : 0;
int oam_step = (j ? -1 : 1);
OamEnt *oam = GetOamCurPtr() + (j ? 7 : 0);
uint8 i = n;
do {
int j = r2 + k * 64;
r2 = r2 - 8 & 63;
oam->x = moldorm_x_lo[j] - BG2HOFS_copy2;
if (!sign8(beamos_x_hi[j]))
oam->y = moldorm_y_lo[j] - beamos_x_hi[j] - BG2VOFS_copy2;
j = beamos_y_hi[j];
if (n != 7 || i != 0) {
oam->charnum = (n == i) ? kLanmola_Draw_Char1[j] : 0xc6;
} else {
oam->charnum = kLanmola_Draw_Char0[j];
}
oam->flags = kLanmola_Draw_Flags[j] | r3;
bytewise_extended_oam[oam - oam_buf] = 2;
} while (oam += oam_step, !sign8(--i));
oam = GetOamCurPtr() + 8;
i = n;
do {
int j = r5 + k * 64;
r5 = r5 - 8 & 63;
oam->x = moldorm_x_lo[j] - BG2HOFS_copy2;
if (!sign8(beamos_x_hi[j]))
oam->y = moldorm_y_lo[j] + 10 - BG2VOFS_copy2;
oam->charnum = 0x6c;
oam->flags = 0x34;
bytewise_extended_oam[oam - oam_buf] = 2;
} while (oam++, !sign8(--i));
if (sprite_ai_state[k] == 1) {
static const uint8 kLanmola_Draw_Idx2[16] = {4, 5, 4, 5, 4, 5, 4, 5, 4, 3, 2, 2, 1, 1, 0, 0};
static const uint8 kLanmola_Draw_Char2[6] = {0xee, 0xee, 0xec, 0xec, 0xce, 0xce};
static const uint8 kLanmola_Draw_Flags2[6] = {0, 0x40, 0, 0x40, 0, 0x40};
Oam_AllocateFromRegionB(4);
OamEnt *oam = GetOamCurPtr();
oam->x = sprite_x_lo[k] - BG2HOFS_copy2;
oam->y = sprite_y_lo[k] - BG2VOFS_copy2;
j = kLanmola_Draw_Idx2[sprite_delay_main[k] >> 3];
oam->charnum = kLanmola_Draw_Char2[j];
oam->flags = kLanmola_Draw_Flags2[j] | 0x31;
bytewise_extended_oam[oam - oam_buf] = 2;
} else if (sprite_ai_state[k] != 5 && sprite_delay_aux1[k] != 0) {
static const int8 kLanmola_Draw_X4[8] = {-8, 8, -10, 10, -16, 16, -24, 32};
static const int8 kLanmola_Draw_Y4[8] = {0, 0, -1, -1, -1, -1, 3, 3};
static const uint8 kLanmola_Draw_Char4[8] = {0xe8, 0xe8, 0xe8, 0xe8, 0xea, 0xea, 0xea, 0xea};
static const uint8 kLanmola_Draw_Flags4[8] = {0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40};
static const uint8 kLanmola_Draw_Ext4[8] = {2, 2, 2, 2, 2, 2, 0, 0};
if (((sprite_y_vel[k] >> 6) ^ sprite_ai_state[k]) & 2)
Oam_AllocateFromRegionB(8);
else
Oam_AllocateFromRegionC(8);
OamEnt *oam = GetOamCurPtr();
uint8 r6 = (((sprite_delay_aux1[k] >> 2) & 3) ^ 3) * 2;
uint8 x = sprite_D[k] - BG2HOFS_copy2;
uint8 y = sprite_wallcoll[k] - BG2VOFS_copy2;
for (int i = 1; i >= 0; i--, oam++) {
int j = i + r6;
oam->x = x + kLanmola_Draw_X4[j];
oam->y = y + kLanmola_Draw_Y4[j];
oam->charnum = kLanmola_Draw_Char4[j];
oam->flags = kLanmola_Draw_Flags4[j] | 0x31;
bytewise_extended_oam[oam - oam_buf] = kLanmola_Draw_Ext4[j];
}
}
}
void Sprite_6D_Rat(int k) { // 85a8b0
static const uint8 kSpriteRat_Tab0[16] = {0, 0, 3, 3, 1, 2, 4, 5, 1, 2, 4, 5, 0, 0, 3, 3};
static const uint8 kSpriteRat_Tab1[16] = {0, 0x40, 0, 0x40, 0, 0, 0, 0, 0x40, 0x40, 0x40, 0x40, 0x80, 0xc0, 0x80, 0xc0};
static const uint8 kSpriteRat_Tab2[8] = {10, 11, 6, 7, 2, 3, 14, 15};
static const uint8 kSpriteRat_Tab4[8] = {8, 9, 4, 5, 0, 1, 12, 13};
static const int8 kSpriteRat_Xvel[4] = {24, -24, 0, 0};
static const int8 kSpriteRat_Yvel[4] = {0, 0, 24, -24};
static const uint8 kSpriteRat_Tab3[4] = {2, 3, 1, 0};
int j = sprite_A[k];
sprite_graphics[k] = kSpriteRat_Tab0[j];
sprite_oam_flags[k] = (sprite_oam_flags[k] & 0x3f) | kSpriteRat_Tab1[j];
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
if (sprite_ai_state[k] != 0) {
if (sprite_delay_main[k] == 0) {
if (is_in_dark_world == 0)
SpriteSfx_QueueSfx3WithPan(k, 0x17);
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 80;
}
j = sprite_D[k];
if (sprite_wallcoll[k] != 0)
sprite_D[k] = j = kSpriteRat_Tab3[j];
sprite_x_vel[k] = kSpriteRat_Xvel[j];
sprite_y_vel[k] = kSpriteRat_Yvel[j];
sprite_A[k] = kSpriteRat_Tab4[sprite_D[k] * 2 + (frame_counter >> 2 & 1)];
} else {
Sprite_ZeroVelocity_XY(k);
if (sprite_delay_main[k] == 0) {
uint8 a = GetRandomNumber();
sprite_D[k] = a & 3;
sprite_ai_state[k]++;
sprite_delay_main[k] = (a & 0x7f) + 0x40;
}
sprite_A[k] = kSpriteRat_Tab2[sprite_D[k] * 2 + (frame_counter >> 3 & 1)];
}
}
void Sprite_6E_Rope(int k) { // 85a973
int j;
j = sprite_A[k];
sprite_graphics[k] = kSpriteRope_Gfx[j];
sprite_oam_flags[k] = (sprite_oam_flags[k] & 0x3f) | kSpriteRope_Flags[j];
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_E[k]) {
OamEnt *oam = GetOamCurPtr();
oam[0].flags |= 0x30;
uint8 old_z = sprite_z[k];
Sprite_MoveZ(k);
if (!sign8(sprite_z_vel[k] - 0xc0))
sprite_z_vel[k] -= 2;
if (!sign8(old_z ^ sprite_z[k]) || !sign8(sprite_z[k]))
return;
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
sprite_E[k] = 0;
sprite_flags3[k] &= ~0x10;
} else {
sprite_flags2[k] = 0;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
if (sprite_ai_state[k] != 0) {
if (sprite_delay_main[k] == 0) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 32;
}
j = sprite_D[k];
if (sprite_wallcoll[k] != 0)
sprite_D[k] = j = kSpriteRope_Tab0[j];
j += sprite_G[k];
sprite_x_vel[k] = kSpriteRope_Xvel[j];
sprite_y_vel[k] = kSpriteRope_Yvel[j];
int i = frame_counter;
if (j < 4)
i >>= 1;
sprite_A[k] = kSpriteRope_Tab1[sprite_D[k] * 2 + (i >> 1 & 1)];
} else {
Sprite_ZeroVelocity_XY(k);
if (sprite_delay_main[k] == 0) {
sprite_G[k] = 0;
uint8 a = GetRandomNumber();
sprite_D[k] = a & 3;
sprite_ai_state[k]++;
sprite_delay_main[k] = (a & 0x7f) + 0x40;
PointU8 pt;
uint8 dir = Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.y + 0x10) < 0x20 || (uint8)(pt.x + 0x18) < 0x20) {
sprite_G[k] = 4;
sprite_D[k] = dir;
}
}
sprite_A[k] = kSpriteRope_Tab1[sprite_D[k] * 2 + (frame_counter >> 3 & 1)];
}
}
}
void Sprite_6F_Keese(int k) { // 85aa8b
static const int8 kSpriteKeese_Tab1[2] = {1, -1};
static const int8 kSpriteKeese_Tab0[4] = {2, 10, 6, 14};
sprite_obj_prio[k] |= 0x30;
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
if (sprite_ai_state[k]) {
if (sprite_delay_main[k] == 0) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 64;
sprite_graphics[k] = 0;
Sprite_ZeroVelocity_XY(k);
} else {
if ((sprite_delay_main[k] & 7) == 0) {
sprite_A[k] += kSpriteKeese_Tab1[sprite_B[k] & 1];
if (!(GetRandomNumber() & 3))
sprite_B[k]++;
}
int j = sprite_A[k] & 0xf;
sprite_x_vel[k] = kSpriteKeese_Tab2[j];
sprite_y_vel[k] = kSpriteKeese_Tab3[j];
sprite_graphics[k] = ((frame_counter >> 2) & 1) + 1;
}
} else {
if ((k ^ frame_counter) & 3 | sprite_delay_main[k])
return;
PointU8 pt;
uint8 dir = Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.y + 0x28) >= 0x50 || (uint8)(pt.x + 0x28) >= 0x50)
return;
SpriteSfx_QueueSfx3WithPan(k, 0x1e);
sprite_ai_state[k]++;
sprite_delay_main[k] = 64;
sprite_B[k] = 64;
sprite_A[k] = kSpriteKeese_Tab0[dir];
}
}
void Sprite_Cannonball(int k) { // 85ab54
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXY(k);
if (sprite_delay_main[k] == 30) {
Sprite_SpawnPoofGarnish(k);
} else if (sprite_delay_main[k] == 0 && Sprite_CheckTileCollision(k)) {
sprite_state[k] = 0;
sprite_x_lo[k] += 4;
sprite_y_lo[k] += 4;
Sprite_PlaceRupulseSpark_2(k);
SpriteSfx_QueueSfx2WithPan(k, 0x5);
}
Sprite_CheckDamageToAndFromLink(k);
}
void Sprite_SpawnPoofGarnish(int j) { // 85ab9c
int k = GarnishAllocForce();
garnish_type[k] = 10;
garnish_active = 10;
garnish_x_lo[k] = sprite_x_lo[j];
garnish_x_hi[k] = sprite_x_hi[j];
int y = Sprite_GetY(j) + 16;
garnish_y_lo[k] = y;
garnish_y_hi[k] = y >> 8;
garnish_sprite[k] = sprite_floor[j];
garnish_countdown[k] = 15;
}
void Sprite_6C_MirrorPortal(int k) { // 85af75
if (savegame_is_darkworld) {
sprite_state[k] = 0;
} else {
if (BYTE(overworld_screen_index) >= 0x80)
return;
if (submodule_index != 0x23 && byte_7E0FC6 < 3)
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
int j = frame_counter >> 2 & 3;
sprite_oam_flags[k] = sprite_oam_flags[k] & 0x3f | kSprite_WarpVortex_Flags[j];
if (Sprite_CheckIfLinkIsBusy())
return;
if (Sprite_CheckDamageToLink_same_layer(k)) {
if (sprite_A[k] && (link_disable_sprite_damage | countdown_for_blink) == 0 && !flag_is_link_immobilized) {
submodule_index = 0x23;
link_triggered_by_whirlpool_sprite = 1;
subsubmodule_index = 0;
link_actual_vel_y = 0;
link_actual_vel_x = 0;
link_player_handler_state = kPlayerState_Mirror;
last_light_vs_dark_world = overworld_screen_index & 0x40;
sprite_state[k] = 0;
}
} else {
sprite_A[k] = 1;
}
}
if (++sprite_B[k] == 0)
sprite_A[k] = 1;
sprite_x_lo[k] = bird_travel_x_lo[15];
sprite_x_hi[k] = bird_travel_x_hi[15];
int t = (bird_travel_y_lo[15] | (bird_travel_y_hi[15] << 8)) + 8;
sprite_y_lo[k] = t;
sprite_y_hi[k] = t >> 8;
}
void Sprite_6A_BallNChain(int k) { // 85b01b
ChainBallTrooper_Draw(k);
if (sprite_ai_state[k] < 2)
HIBYTE(dungmap_var8) = 0x80;
if (Sprite_ReturnIfInactive(k))
return;
Guard_ParrySwordAttacks(k);
int t = sprite_B[k] << 8 | sprite_A[k];
t += kChainBallTrooper_Tab1[sprite_ai_state[k]];
sprite_A[k] = t;
sprite_B[k] = t >> 8 & 1;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckTileCollision(k);
Sprite_MoveXY(k);
Sprite_CheckDamageToLink(k);
PointU8 pt = { 0, 0 };
if (((k ^ frame_counter) & 0xf) == 0)
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, &pt);
switch (sprite_ai_state[k]) {
case 0:
if (((k ^ frame_counter) & 0xf) == 0) {
sprite_D[k] = sprite_head_dir[k];
if ((uint8)(pt.y + 0x40) < 0x68 && (uint8)(pt.x + 0x30) < 0x60) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 24;
return;
}
Sprite_ApplySpeedTowardsLink(k, 8);
}
BallNChain_Animate(k);
break;
case 1:
Sprite_ZeroVelocity_XY(k);
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 48;
sprite_ai_state[k]++;
}
break;
case 2:
if (!sprite_delay_main[k] &&
sprite_head_dir[k] == kFlailTrooperAttackDir[(sprite_A[k] >> 7 & 1) + sprite_B[k] * 2]) {
sprite_ai_state[k]++;
sprite_delay_aux2[k] = 31;
}
attack_common:
sprite_subtype2[k]++;
BallNChain_Animate(k);
if (((k ^ frame_counter) & 0xf) == 0)
SpriteSfx_QueueSfx3WithPan(k, 6);
break;
case 3:
Sprite_ZeroVelocity_XY(k);
t = sprite_delay_aux2[k];
if (t == 0)
sprite_ai_state[k] = 0;
else if (t >= 0x10)
goto attack_common;
sprite_subtype2[k]++;
BallNChain_Animate(k);
break;
}
}
void BallNChain_Animate(int k) { // 85b0ab
sprite_graphics[k] = kFlailTrooperGfx[sprite_D[k] * 8 + (++sprite_subtype2[k] >> 2 & 7)];
}
void SpriteDraw_GuardHead(int k, PrepOamCoordsRet *info, int spr_offs) { // 85b160
int j = sprite_head_dir[k];
OamEnt *oam = GetOamCurPtr() + spr_offs;
uint16 x = info->x, y = info->y - 9;
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kChainBallTrooperHead_Char[j];
oam->flags = info->flags | kChainBallTrooperHead_Flags[j];
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
void SpriteDraw_BNCBody(int k, PrepOamCoordsRet *info, int spr_offs) { // 85b3cb
int g = sprite_graphics[k];
spr_offs += kFlailTrooperBody_SprOffs[g] >> 2;
OamEnt *oam = GetOamCurPtr() + spr_offs;
int n = kFlailTrooperBody_Num[g];
do {
int j = g * 3 + n;
uint16 x = info->x + kFlailTrooperBody_X[j];
uint16 y = info->y + kFlailTrooperBody_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kFlailTrooperBody_Char[j];
oam->flags = info->flags | kFlailTrooperBody_Flags[j];
bytewise_extended_oam[oam - oam_buf] = kFlailTrooperBody_Ext[j] | (x >> 8 & 1);
if (n == 2)
oam++;
} while (oam++, --n >= 0);
}
void SpriteDraw_BNCFlail(int k, PrepOamCoordsRet *info) { // 85b468
OamEnt *oam = GetOamCurPtr();
BYTE(dungmap_var7) = info->x;
HIBYTE(dungmap_var7) = info->y;
uint8 t;
uint16 r0 = sprite_A[k] | sprite_B[k] << 8;
uint8 qq = sprite_ai_state[k] < 2 ? 0 : kFlailTrooperWeapon_Tab0[sprite_delay_aux2[k]];
uint8 r12 = kFlailTrooperWeapon_Tab1[sprite_D[k]];
uint8 r13 = kFlailTrooperWeapon_Tab2[sprite_D[k]];
uint16 r10 = (r0 & 0x1ff) >> 6;
uint16 r2 = (r0 + 0x80) & 0x1ff;
uint8 r14 = ChainBallMult(kSinusLookupTable[r0 & 0xff], qq);
uint8 r4 = (r0 & 0x100) ? -r14 : r14;
uint8 r15 = ChainBallMult(kSinusLookupTable[r2 & 0xff], qq);
uint8 r6 = (r2 & 0x100) ? -r15 : r15;
HIBYTE(dungmap_var8) = r4 - 4 + r12;
BYTE(dungmap_var8) = r6 - 4 + r13;
oam[0].x = HIBYTE(dungmap_var8) + BYTE(dungmap_var7);
oam[0].y = BYTE(dungmap_var8) + HIBYTE(dungmap_var7);
oam[0].charnum = 0x2a;
oam[0].flags = 0x2d;
bytewise_extended_oam[oam - oam_buf] = 2;
oam++;
for (int i = 3; i >= 0; i--, oam++) {
t = (kFlailTrooperWeapon_Tab4[i] * r14) >> 8;
t = sign8(r4) ? -t : t;
oam->x = t + BYTE(dungmap_var7) + r12;
t = (kFlailTrooperWeapon_Tab4[i] * r15) >> 8;
t = sign8(r6) ? -t : t;
oam->y = t + HIBYTE(dungmap_var7) + r13;
oam->charnum = 0x3f;
oam->flags = 0x2d;
bytewise_extended_oam[oam - oam_buf] = 0;
}
Sprite_CorrectOamEntries(k, 4, 0xff);
}
void Sprite_50_Cannonball(int k) { // 85b648
if (!sprite_ai_state[k])
SpriteDraw_SingleLarge(k);
else
SpriteDraw_BigCannonball(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_graphics[k] = ++sprite_subtype2[k] >> 2 & 1;
Sprite_MoveXY(k);
if (sprite_delay_main[k]) {
if (sprite_delay_main[k] == 1)
sprite_state[k] = 0;
return;
}
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_aux2[k] && Sprite_CheckTileCollision(k))
sprite_delay_main[k] = 16;
}
void SpriteDraw_BigCannonball(int k) { // 85b6a4
static const int8 kMetalBallLarge_X[4] = {-8, 8, -8, 8};
static const int8 kMetalBallLarge_Y[4] = {-8, -8, 8, 8};
static const uint8 kMetalBallLarge_Char[8] = {0x84, 0x88, 0x88, 0x88, 0x86, 0x88, 0x88, 0x88};
static const uint8 kMetalBallLarge_Flags[4] = {0, 0, 0xc0, 0x80};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
for (int i = 3; i >= 0; i--, oam++) {
uint16 x = info.x + kMetalBallLarge_X[i];
uint16 y = info.y + kMetalBallLarge_Y[i];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kMetalBallLarge_Char[g * 4 + i];
oam->flags = kMetalBallLarge_Flags[i] | info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
}
void Sprite_51_ArmosStatue(int k) { // 85b703
Armos_Draw(k);
if (sprite_F[k])
Sprite_ZeroVelocity_XY(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
Sprite_ZeroVelocity_XY(k);
}
if (!sprite_ai_state[k]) {
sprite_flags3[k] |= 0x40;
if (sprite_delay_main[k] == 1) {
sprite_flags3[k] &= ~0x40;
sprite_ai_state[k]++;
sprite_flags2[k] &= ~0x80;
sprite_flags3[k] &= ~0x40;
sprite_oam_flags[k] = 0xb;
} else {
if (!((k ^ frame_counter) & 3) &&
(uint16)(link_x_coord - cur_sprite_x + 31) < 62 &&
(uint16)(link_y_coord + 8 - cur_sprite_y + 48) < 88 && !sprite_delay_main[k]) {
sprite_delay_main[k] = 48;
SpriteSfx_QueueSfx2WithPan(k, 0x22);
}
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
Sprite_RepelDash();
}
if (sprite_delay_main[k])
sprite_oam_flags[k] ^= (sprite_delay_main[k] >> 1) & 0xe;
}
} else {
Sprite_CheckDamageToAndFromLink(k);
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
if ((sprite_delay_main[k] | sprite_z[k]) == 0) {
sprite_delay_main[k] = 8;
sprite_z_vel[k] = 16;
Sprite_ApplySpeedTowardsLink(k, 12);
}
}
}
void Armos_Draw(int k) { // 85b7ef
static const DrawMultipleData kArmos_Dmd[2] = {
{0, -16, 0x00c0, 2},
{0, 0, 0x00e0, 2},
};
PrepOamCoordsRet info;
if (!sprite_ai_state[k]) {
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
}
Sprite_DrawMultiple(k, &kArmos_Dmd[0], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_4E_Popo(int k) { // 85b80a
Bot_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_subtype2[k]++;
sprite_A[k] = sprite_subtype2[k] >> 4 & 3;
Sprite_CheckDamageToAndFromLink(k);
switch (sprite_ai_state[k]) {
case 0:
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 105;
}
break;
case 1:
sprite_subtype2[k]++;
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = (GetRandomNumber() & 63) + 128;
sprite_ai_state[k]++;
int j = GetRandomNumber() & 15;
sprite_x_vel[k] = kSpriteKeese_Tab2[j] << 2;
sprite_y_vel[k] = kSpriteKeese_Tab3[j] << 2;
}
break;
case 2:
sprite_subtype2[k]++;
if (sprite_delay_main[k]) {
if ((k ^ frame_counter) & sprite_B[k]) {
Sprite_CheckTileCollision(k);
return;
}
Sprite_MoveXY(k);
if (!sprite_wallcoll[k]) {
Sprite_CheckTileCollision(k);
return;
}
}
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 80;
break;
}
}
void Bot_Draw(int k) { // 85b89a
static const uint8 kBot_Gfx[4] = {0, 1, 0, 1};
static const uint8 kBot_OamFlags[4] = {0, 0, 0x40, 0x40};
int j = sprite_A[k];
sprite_graphics[k] = kBot_Gfx[j];
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kBot_OamFlags[j];
SpriteDraw_SingleLarge(k);
}
void Sprite_4C_Geldman(int k) { // 85b8b3
static const uint8 kGerudoMan_EmergeGfx[8] = {3, 2, 0, 0, 0, 0, 0, 0};
static const uint8 kGerudoMan_PursueGfx[2] = {4, 5};
static const uint8 kGerudoMan_SubmergeGfx[5] = {0, 1, 2, 3, 3};
PrepOamCoordsRet info;
if (sprite_ai_state[k] < 2)
Sprite_PrepOamCoord(k, &info);
else
GerudoMan_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_ignore_projectile[k] = 1;
switch (sprite_ai_state[k]) {
case 0: // return
if (!sprite_delay_main[k]) {
sprite_x_lo[k] = sprite_A[k];
sprite_x_hi[k] = sprite_B[k];
sprite_y_lo[k] = sprite_C[k];
sprite_y_hi[k] = sprite_head_dir[k];
sprite_ai_state[k] = 1;
}
break;
case 1: // wait
if (!((k ^ frame_counter) & 7) &&
(uint16)(link_x_coord - cur_sprite_x + 0x30) < 0x60 &&
(uint16)(link_y_coord - cur_sprite_y + 0x30) < 0x60) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 31;
}
break;
case 2: // emerge
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 96;
Sprite_ApplySpeedTowardsLink(k, 16);
} else {
sprite_graphics[k] = kGerudoMan_EmergeGfx[sprite_delay_main[k] >> 2];
}
break;
case 3: // pursue
sprite_ignore_projectile[k] = 0;
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 8;
} else {
sprite_graphics[k] = kGerudoMan_PursueGfx[sprite_delay_main[k] >> 2 & 1];
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
}
break;
case 4: // submerge
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 16;
} else {
sprite_graphics[k] = kGerudoMan_SubmergeGfx[sprite_delay_main[k] >> 1];
}
break;
}
}
void GerudoMan_Draw(int k) { // 85ba24
static const int8 kGerudoMan_Draw_X[18] = { 4, 4, 4, 4, 4, 4, -8, 8, 8, -8, 8, 8, -16, 0, 16, -16, 0, 16 };
static const int8 kGerudoMan_Draw_Y[18] = { 8, 8, 8, 8, 8, 8, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static const uint8 kGerudoMan_Draw_Char[18] = {
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa4, 0xa2, 0xa0, 0xa0, 0xa2, 0xa4,
};
static const uint8 kGerudoMan_Draw_Flags[18] = {
0, 0, 0, 0x40, 0x40, 0x40, 0, 0x40, 0x40, 0, 0x40, 0x40, 0x40, 0x40, 0x40, 0, 0, 0,
};
static const uint8 kGerudoMan_Draw_Ext[18] = { 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
for (int i = 2; i >= 0; i--, oam++) {
int j = g * 3 + i;
uint16 x = info.x + kGerudoMan_Draw_X[j];
uint16 y = info.y + kGerudoMan_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kGerudoMan_Draw_Char[j];
oam->flags = kGerudoMan_Draw_Flags[j] | info.flags;
bytewise_extended_oam[oam - oam_buf] = kGerudoMan_Draw_Ext[j] | (x >> 8 & 1);
}
}
void Sprite_4D_Toppo(int k) { // 85ba85
static const int8 kToppo_XOffs[4] = {-32, 32, 0, 0};
static const int8 kToppo_YOffs[4] = {0, 0, -32, 32};
if (sprite_ai_state[k]) {
sprite_obj_prio[k] |= 0x30;
Toppo_Draw(k);
}
if (Sprite_ReturnIfInactive(k))
return;
switch (sprite_ai_state[k]) {
case 0: // Toppo_Hiding
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 8;
int j = GetRandomNumber() & 3;
uint16 x = sprite_A[k] | sprite_B[k] << 8;
uint16 y = sprite_C[k] | sprite_head_dir[k] << 8;
Sprite_SetX(k, x + kToppo_XOffs[j]);
Sprite_SetY(k, y + kToppo_YOffs[j]);
}
break;
case 1: // Toppo_RustleGrass
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 16;
} else {
sprite_graphics[k] = sprite_delay_main[k] >> 2 & 1;
Toppo_VerifyTile(k);
}
break;
case 2: // Toppo_PokingOut
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 3;
sprite_z_vel[k] = 64;
}
sprite_graphics[k] = 2;
Toppo_VerifyTile(k);
break;
case 3: // Toppo_Leaping
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 16;
Toppo_VerifyTile(k);
}
break;
case 4: // Toppo_Retreat
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 32;
} else {
sprite_graphics[k] = sprite_delay_main[k] >> 2 & 1;
}
Toppo_VerifyTile(k);
break;
case 5: // Toppo_Flustered
Toppo_Flustered(k);
break;
}
}
void Toppo_VerifyTile(int k) { // 85bb72
uint16 x = Sprite_GetX(k);
if (GetTileAttribute(0, &x, Sprite_GetY(k)) != 0x40)
sprite_ai_state[k] = 5;
}
void Toppo_Draw(int k) { // 85bbff
static const int8 kToppo_Draw_X[15] = {0, 8, 8, 0, 8, 8, 0, 0, 8, 0, 0, 0, 0, 0, 0};
static const int8 kToppo_Draw_Y[15] = {8, 8, 8, 8, 8, 8, 0, 8, 8, 0, 0, 0, 0, 0, 0};
static const uint8 kToppo_Draw_Char[15] = {0xc8, 0xc8, 0xc8, 0xca, 0xca, 0xca, 0xc0, 0xc8, 0xc8, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2};
static const uint8 kToppo_Draw_Flags[15] = {0, 0x40, 0x40, 0, 0x40, 0x40, 0, 0, 0x40, 0, 0, 0, 0x40, 0x40, 0x40};
static const uint8 kToppo_Draw_Ext[15] = {0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
uint16 ybase = Sprite_GetY(k) - BG2VOFS_copy2;
for (int i = 2; i >= 0; i--, oam++) {
int j = i + g * 3;
uint8 ext = kToppo_Draw_Ext[j];
uint16 x = info.x + kToppo_Draw_X[j];
uint16 y = (ext ? info.y : ybase) + kToppo_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kToppo_Draw_Char[j];
uint8 flags = kToppo_Draw_Flags[j] | info.flags;
if (ext == 0)
flags = flags & ~0xf | 2;
oam->flags = flags;
bytewise_extended_oam[oam - oam_buf] = ext | (x >> 8 & 1);
}
}
void Sprite_4B_GreenKnifeGuard(int k) { // 85bca2
sprite_graphics[k] = kSprite_Recruit_Gfx[sprite_D[k] + (sprite_subtype2[k] >> 1 & 4) ];
Recruit_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
if (sprite_ai_state[k] != 0) {
GreenKnifeGuard_Moving(k);
return;
}
if (sprite_delay_main[k] != 0)
return;
sprite_delay_main[k] = (GetRandomNumber() & 0x3f) + 0x30;
sprite_ai_state[k]++;
sprite_D[k] = sprite_head_dir[k];
PointU8 out;
int j = sprite_D[k];
if (j == Sprite_DirectionToFaceLink(k, &out) &&
(((uint8)(out.x + 0x10) < 0x20) || ((uint8)(out.y + 0x10) < 0x20))) {
j += 4;
sprite_delay_main[k] = 128;
}
sprite_x_vel[k] = kSprite_Recruit_Xvel[j];
sprite_y_vel[k] = kSprite_Recruit_Yvel[j];
}
void GreenKnifeGuard_Moving(int k) { // 85bd1e
uint8 t = 0x10;
if (sprite_wallcoll[k] == 0) {
if (sprite_delay_main[k] != 0)
goto out;
t = 0x30;
}
sprite_delay_main[k] = t;
Sprite_ZeroVelocity_XY(k);
sprite_head_dir[k] = kRecruit_Moving_HeadDir[sprite_D[k] * 2 | (GetRandomNumber() & 1)];
sprite_ai_state[k] = 0;
out:
sprite_subtype2[k] += (sprite_delay_aux1[k] != 0) ? 2 : 1;
}
void Recruit_Draw(int k) { // 85bd7e
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int r6 = sprite_graphics[k];
int hd = sprite_head_dir[k];
uint16 x = info.x;
uint16 y = info.y - 11;
oam->x = x;
oam->y = (uint16)(y + 0x10) < 0x100 ? y : 0xf0;
oam->charnum = kSoldier_Draw1_Char[hd];
oam->flags = kSoldier_Draw1_Flags[hd] | info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
oam++;
x = info.x + kRecruit_Draw_X[r6];
y = info.y;
oam->x = x;
oam->y = (uint16)(y + 0x10) < 0x100 ? y : 0xf0;
oam->charnum = kRecruit_Draw_Char[r6];
oam->flags = kRecruit_Draw_Flags[r6] | info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
SpriteDraw_Shadow(k, &info);
}
void Sprite_4A_BombGuard(int k) { // 85be0a
if (sprite_C[k] == 0) {
BombGuard(k);
return;
}
if (sprite_C[k] < 2) {
SpriteBomb_ExplosionIncoming(k);
return;
}
if (sprite_C[k] == 2) {
for (int j = 15; j >= 0; j--) {
if (j != cur_object_index && sprite_state[j] >= 9 && !((frame_counter ^ j) & 7 | sprite_hit_timer[j]))
SpriteBomb_CheckDamageToSprite(k, j);
}
Sprite_CheckDamageToLink(k);
}
SpriteDraw_SpriteBombExplosion(k);
if (!sprite_delay_aux1[k])
sprite_state[k] = 0;
}
void SpriteBomb_CheckDamageToSprite(int k, int j) { // 85be49
int x = Sprite_GetX(k) - 16, y = Sprite_GetY(k) - 16;
SpriteHitBox hb;
hb.r0_xlo = x;
hb.r8_xhi = x >> 8;
hb.r3 = hb.r2 = 48;
hb.r1_ylo = y;
hb.r9_yhi = y >> 8;
Sprite_SetupHitBox(j, &hb);
if (!CheckIfHitBoxesOverlap(&hb) || sprite_type[j] == 0x11)
return;
Ancilla_CheckDamageToSprite_preset(j, 8);
x = Sprite_GetX(j);
y = Sprite_GetY(j) - sprite_z[j];
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 32);
sprite_y_recoil[j] = pt.y;
sprite_x_recoil[j] = pt.x;
}
void SpriteBomb_ExplosionIncoming(int k) { // 85bed3
if (sprite_E[k])
sprite_obj_prio[k] |= 48;
SpriteDraw_SingleLarge(k);
if (sprite_hit_timer[k] || sprite_delay_aux1[k] == 1) {
sprite_hit_timer[k] = 0;
if (sprite_state[k] == 10)
link_state_bits = 0, link_picking_throw_state = 0;
SpriteSfx_QueueSfx2WithPan(k, 0xc);
sprite_C[k]++;
sprite_flags4[k] = 9;
sprite_oam_flags[k] = 2;
sprite_delay_aux1[k] = 31;
sprite_state[k] = 6;
sprite_flags2[k] = 3;
return;
}
if (sprite_delay_aux1[k] < 64)
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0xe | (sprite_delay_aux1[k] >> 1) & 0xe;
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_delay_aux3[k])
Sprite_CheckDamageFromLink(k);
Sprite_MoveXY(k);
if (player_is_indoors)
Sprite_CheckTileCollision(k);
ThrownSprite_TileAndSpriteInteraction(k);
}
void BombGuard(int k) { // 85bf51
BombTrooper_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_head_dir[k] = sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
if (sprite_ai_state[k] == 0) {
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 112;
}
} else {
int j = sprite_delay_main[k];
if (!j) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 32;
return;
}
sprite_subtype2[k] = (j >= 80);
if (j == 32)
BombGuard_CreateBomb(k);
sprite_graphics[k] = kJavelinTrooper_Tab2[(sprite_D[k] << 3 | j >> 4) + 32];
}
}
void BombGuard_CreateBomb(int k) { // 85bfc1
static const int8 kBombTrooperBomb_X[4] = {0, 1, 9, -8};
static const int8 kBombTrooperBomb_Y[4] = {-12, -12, -15, -13};
static const int8 kBombTrooperBomb_Zvel[16] = {32, 40, 48, 56, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x4a, &info);
if (j >= 0) {
int i = sprite_D[k];
Sprite_SetX(j, info.r0_x + kBombTrooperBomb_X[i]);
Sprite_SetY(j, info.r2_y + kBombTrooperBomb_Y[i]);
Sprite_ApplySpeedTowardsLink(j, 16);
PointU8 pt;
sprite_C[j] = 1;
Sprite_DirectionToFaceLink(j, &pt);
if (sign8(pt.x))
pt.x = -pt.x;
if (sign8(pt.y))
pt.y = -pt.y;
sprite_z_vel[j] = kBombTrooperBomb_Zvel[(pt.y | pt.x) >> 4];
sprite_flags3[j] = sprite_flags3[k] & 0xee | 0x18;
sprite_oam_flags[j] = 8;
sprite_delay_aux1[j] = 255;
sprite_health[j] = 0;
SpriteSfx_QueueSfx3WithPan(j, 0x13);
}
}
void BombTrooper_Draw(int k) { // 85c04b
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
SpriteDraw_GuardHead(k, &info, 2);
SpriteDraw_BNCBody(k, &info, 1);
if (sprite_graphics[k] < 20)
SpriteDraw_BombGuard_Arm(k, &info);
SpriteDraw_Shadow_custom(k, &info, 10);
}
void SpriteDraw_BombGuard_Arm(int k, PrepOamCoordsRet *info) { // 85c089
static const int8 kBombTrooper_DrawArm_X[8] = {-1, 1, 2, 0, 9, 9, -8, -8};
static const int8 kBombTrooper_DrawArm_Y[8] = {-12, -12, -12, -12, -16, -14, -12, -14};
OamEnt *oam = GetOamCurPtr();
int j = sprite_D[k] * 2 | sprite_subtype2[k];
uint16 x = info->x + kBombTrooper_DrawArm_X[j];
uint16 y = info->y + kBombTrooper_DrawArm_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = 0x6e;
oam->flags = info->flags & 0x30 | 0x8;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
void SpriteDraw_SpriteBombExplosion(int k) { // 85c113
static const int8 kEnemyBombExplosion_X[16] = {-12, 12, -12, 12, -8, 8, -8, 8, -8, 8, -8, 8, 0, 0, 0, 0};
static const int8 kEnemyBombExplosion_Y[16] = {-12, -12, 12, 12, -8, -8, 8, 8, -8, -8, 8, 8, 0, 0, 0, 0};
static const uint8 kEnemyBombExplosion_Char[16] = {0x88, 0x88, 0x88, 0x88, 0x8a, 0x8a, 0x8a, 0x8a, 0x84, 0x84, 0x84, 0x84, 0x86, 0x86, 0x86, 0x86};
static const uint8 kEnemyBombExplosion_Flags[16] = {0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0, 0, 0, 0, 0};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int base = sprite_delay_aux1[k] >> 1 & 0xc;
for (int i = 3; i >= 0; i--, oam++) {
int j = base + i;
oam->x = kEnemyBombExplosion_X[j] + info.x;
oam->y = kEnemyBombExplosion_Y[j] + info.y;
oam->charnum = kEnemyBombExplosion_Char[j];
oam->flags = kEnemyBombExplosion_Flags[j] | info.flags;
}
Sprite_CorrectOamEntries(k, 3, 2);
}
void Sprite_41_BlueGuard(int k) { // 85c155
if (sprite_C[k])
Probe(k);
else
Guard_Main(k);
}
void Probe(int k) { // 85c15d
SpriteAddXY(k, (int8)sprite_x_vel[k], (int8)sprite_y_vel[k]);
bool is_close;
if (sprite_type[sprite_C[k] - 1] == 0xce) {
// parent is blind the thief?
uint16 x = cur_sprite_x - link_x_coord + 16;
uint16 y = link_y_coord - cur_sprite_y + 24;
is_close = (x < 32 && y < 32);
} else {
if (Probe_CheckTileSolidity(k) && sprite_tiletype != 9 || link_cape_mode != 0) {
sprite_state[k] = 0;
return;
}
uint16 x = cur_sprite_x - link_x_coord;
uint16 y = cur_sprite_y - link_y_coord;
is_close = (x < 16 && y < 16 && sprite_floor[k] == link_is_on_lower_level);
}
if (is_close) {
int p = sprite_C[k] - 1;
if (sprite_ai_state[p] != 3) {
sprite_ai_state[p] = 3;
if (sprite_type[p] != 0xce) {
sprite_delay_main[p] = 16;
sprite_subtype2[p] = 0;
}
}
sprite_state[k] = 0;
} else {
PrepOamCoordsRet oam;
if (Sprite_PrepOamCoordOrDoubleRet(k, &oam))
return;
if ((oam.x | oam.y) >= 256)
sprite_state[k] = 0;
}
}
void Guard_Main(int k) { // 85c227
uint8 bak1 = sprite_graphics[k];
uint8 bak2 = sprite_D[k];
if (sprite_delay_aux1[k]) {
sprite_D[k] = kSoldier_DirectionLockSettings[bak2];
sprite_graphics[k] = kSoldier_Gfx[bak2];
}
Guard_HandleAllAnimation(k);
sprite_D[k] = bak2;
sprite_graphics[k] = bak1;
if (sprite_state[k] == 5) {
if (submodule_index == 0) {
sprite_subtype2[k]++;
Guard_TickAndUpdateBody(k);
sprite_subtype2[k]++;
Guard_TickAndUpdateBody(k);
}
return;
}
if (Sprite_ReturnIfInactive(k))
return;
Guard_ParrySwordAttacks(k);
if ((Sprite_CheckDamageToLink(k) || sprite_alert_flag) && sprite_ai_state[k] < 3) {
sprite_ai_state[k] = 3;
Guard_SetTimerAndAssertTileHitBox(k, 0x20);
} else if (sprite_F[k] != 0 && sprite_F[k] >= 4) {
sprite_ai_state[k] = 4;
Guard_SetTimerAndAssertTileHitBox(k, 0x80);
}
if (Sprite_ReturnIfRecoiling(k))
return;
if ((sprite_subtype[k] & 7) < 5) {
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
} else {
Sprite_MoveXY(k);
}
if (sprite_ai_state[k] != 4)
sprite_G[k] = 0;
switch (sprite_ai_state[k]) {
case 0:
Sprite_ZeroVelocity_XY(k);
if (sprite_delay_main[k])
break;
sprite_ai_state[k]++;
if (sprite_subtype[k] && (sprite_subtype[k] & 7) < 5) {
sprite_delay_main[k] = kSoldier_Delay[sprite_subtype[k] >> 3 & 3];
sprite_D[k] ^= 1;
sprite_subtype2[k] = 0;
} else {
sprite_delay_main[k] = (GetRandomNumber() & 0x3f) + 0x28; // note: adc
uint8 t = sprite_D[k], u = GetRandomNumber() & 3;
sprite_D[k] = u;
if (t == u || (t ^ u) & 2)
return;
}
sprite_delay_aux1[k] = 12;
break;
case 1: {
Sprite_Guard_SendOutProbe(k);
if ((sprite_subtype[k] & 7) >= 5) {
Guard_ShootProbeAndStuff(k);
return;
}
if (!sprite_delay_main[k]) {
Sprite_ZeroVelocity_XY(k);
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 160;
return;
}
if (!(sprite_subtype2[k] & 1))
sprite_delay_main[k]++;
if (sprite_wallcoll[k] & 0xf) {
sprite_D[k] ^= 1;
Guard_SetGlanceTo12(k);
}
int dir = sprite_D[k];
sprite_x_vel[k] = kSoldier_Xvel[dir];
sprite_y_vel[k] = kSoldier_Yvel[dir];
sprite_head_dir[k] = dir;
Guard_TickAndUpdateBody(k);
break;
}
case 2: {
Sprite_ZeroVelocity_XY(k);
Sprite_Guard_SendOutProbe(k);
if (sprite_delay_main[k] == 0) {
sprite_delay_main[k] = 0x20;
sprite_ai_state[k] = 0;
} else if (sprite_delay_main[k] < 0x80) {
int t = sprite_D[k] * 8 | (sprite_delay_main[k] >> 3 & 7);
sprite_head_dir[k] = kSoldier_HeadDirs[t];
}
break;
}
case 3:
Sprite_ZeroVelocity_XY(k);
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL);
if (sprite_delay_main[k] == 0) {
sprite_ai_state[k] = 4;
Guard_SetTimerAndAssertTileHitBox(k, 255);
}
break;
case 4:
if (sprite_delay_main[k]) {
Soldier_Func12(k);
} else {
sprite_anim_clock[k] = kSoldier_Tab1[sprite_D[k]];
Sprite_ZeroVelocity_XY(k);
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 160;
}
break;
}
}
void Guard_SetGlanceTo12(int k) { // 85c32b
sprite_delay_aux1[k] = 12;
}
void Guard_ShootProbeAndStuff(int k) { // 85c3a1
int i = sprite_B[k];
sprite_x_vel[k] = kSoldierB_Xvel[i];
sprite_y_vel[k] = kSoldierB_Yvel[i];
Sprite_CheckTileCollision(k);
if (sprite_delay_aux2[k]) {
if (sprite_delay_aux2[k] == 44)
sprite_B[k] = i = kSoldierB_NextB[i];
} else if (!(sprite_wallcoll[k] & kSoldierB_Mask[i])) {
sprite_delay_aux2[k] = 88;
}
if (sprite_wallcoll[k] & kSoldierB_Mask2[i])
sprite_B[k] = i = kSoldierB_NextB2[i];
sprite_x_vel[k] = kSoldierB_Xvel2[i];
sprite_y_vel[k] = kSoldierB_Yvel2[i];
sprite_head_dir[k] = sprite_D[k] = kSoldierB_Dir[i];
Guard_TickAndUpdateBody(k);
}
void Guard_TickAndUpdateBody(int k) { // 85c454
sprite_subtype2[k]++;
int t = sprite_D[k] * 4 + (sprite_subtype2[k] >> 3 & 3);
sprite_graphics[k] = kSoldier_Gfx2[t];
}
void Guard_SetTimerAndAssertTileHitBox(int k, uint8 a) { // 85c4d7
sprite_delay_main[k] = a;
sprite_subtype[k] = 0;
sprite_flags[k] = sprite_flags[k] & 0xf | 0x60;
}
void Soldier_Func12(int k) { // 85c500
if (((k ^ frame_counter) & 0x1f) == 0) {
if (!sprite_G[k]) {
sprite_G[k] = 1;
SpriteSfx_QueueSfx3WithPan(k, 4);
}
Sprite_ApplySpeedTowardsLink(k, 16);
sprite_D[k] = sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL);
}
Guard_ApplySpeedInDirection(k);
sprite_subtype2[k]++;
Guard_TickAndUpdateBody(k);
}
void Guard_ApplySpeedInDirection(int k) { // 85c542
if (!sprite_wallcoll[k])
return;
int i;
if (sprite_wallcoll[k] & 3) {
i = 2 + Sprite_IsBelowLink(k).a;
} else {
i = Sprite_IsRightOfLink(k).a;
}
sprite_x_vel[k] = kSoldier_SetTowardsVel[i];
sprite_y_vel[k] = kSoldier_SetTowardsVel[i + 2];
}
void Sprite_Guard_SendOutProbe(int k) { // 85c5f2
if ((k + frame_counter & 3) | sprite_pause[k])
return;
uint8 a = sprite_anim_clock[k]++;
uint8 r15 = ((a & 0x1f) + kSprite_SpawnProbeStaggered_Tab[sprite_D[k]]) & 0x3f;
Sprite_SpawnProbeAlways(k, r15);
}
void Sprite_SpawnProbeAlways(int k, uint8 r15) { // 85c612
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0x41, &info, 10);
if (j < 0)
return;
int t = info.r0_x + 8;
sprite_x_lo[j] = t;
sprite_x_hi[j] = t >> 8;
t = info.r2_y + 4;
sprite_y_lo[j] = t;
sprite_y_hi[j] = t >> 8;
sprite_D[j] = r15;
sprite_x_vel[j] = kSpawnProbe_Xvel[r15];
sprite_y_vel[j] = kSpawnProbe_Yvel[r15];
sprite_flags2[j] = sprite_flags2[j] & 0xf0 | 0xa0;
sprite_C[j] = k + 1;
sprite_ignore_projectile[j] = k + 1;
sprite_flags4[j] = 0x40;
sprite_flags3[j] = 0x40;
sprite_defl_bits[j] = 2;
}
void Guard_HandleAllAnimation(int k) { // 85c680
PrepOamCoordsRet poc;
if (Sprite_PrepOamCoordOrDoubleRet(k, &poc))
return;
Guard_AnimateHead(k, 0, &poc);
Guard_AnimateBody(k, kSoldier_Draw2_OamIdx[sprite_D[k]] >> 2, &poc);
Guard_AnimateWeapon(k, &poc);
if (sprite_flags3[k] & 0x10)
SpriteDraw_Shadow_custom(k, &poc, kSoldier_DrawShadow[sprite_D[k]]);
}
void Guard_AnimateHead(int k, int oam_offs, const PrepOamCoordsRet *poc) { // 85c6de
OamEnt *oam = GetOamCurPtr() + oam_offs;
oam->x = poc->x;
int dir = sprite_head_dir[k];
uint16 y = poc->y - kSoldier_Draw1_Yd[sprite_graphics[k]];
oam->y = (uint16)(y + 0x10) < 0x100 ? y : 0xf0;
oam->charnum = kSoldier_Draw1_Char[dir];
oam->flags = kSoldier_Draw1_Flags[dir] | poc->flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (poc->x & 0x100) >> 8;
}
void Guard_AnimateBody(int k, int oam_idx, const PrepOamCoordsRet *poc) { // 85ca09
int g = sprite_graphics[k] * 4;
uint8 type = sprite_type[k];
OamEnt *oam = GetOamCurPtr() + oam_idx;
for (int i = 3; i >= 0; i--) {
int j = i + g;
if (type >= 0x46 && (!kSoldier_Draw2_Ext[j] || i == 3 && kSoldier_Draw2_Char[j] == 0x20))
continue;
uint16 x = poc->x + kSoldier_Draw2_Xd[j];
uint16 y = poc->y + kSoldier_Draw2_Yd[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kSoldier_Draw2_Char[j];
bool flag = true;
uint8 p = 8;
if (oam->charnum == 0x20) {
p = 2;
if (type == 0x46)
oam->y = 0xf0;
} else {
flag = kSoldier_Draw2_Ext[j] == 0;
}
uint8 flags = kSoldier_Draw2_Flags[j] | poc->flags;
oam->flags = flag ? (flags & 0xf1 | p) : flags;
bytewise_extended_oam[oam - oam_buf] = kSoldier_Draw2_Ext[j] | (x & 0x100) >> 8;
oam++;
}
}
void Guard_AnimateWeapon(int k, const PrepOamCoordsRet *poc) { // 85cb64
int oam_idx = kSoldier_Draw3_OamIdx[sprite_D[k]] >> 2;
int g = sprite_graphics[k] * 2;
uint8 type = sprite_type[k];
OamEnt *oam = GetOamCurPtr() + oam_idx;
for (int i = 1; i >= 0; i--, oam++) {
int j = i + g;
uint16 x = poc->x + kSoldier_Draw3_Xd[j];
uint16 y = poc->y + kSoldier_Draw3_Yd[j];
oam->x = x;
oam->y = (uint16)(y + 0x10) < 0x100 ? y : 0xf0;
dungmap_var8 = kSoldier_Draw3_Xd[j] << 8 | (uint8)kSoldier_Draw3_Yd[j];
oam->charnum = kSoldier_Draw3_Char[j] + (type < 0x43 ? 3 : 0);
oam->flags = kSoldier_Draw3_Flags[j] | poc->flags;
bytewise_extended_oam[oam - oam_buf] = (x & 0x100) >> 8;
}
}
void Sprite_45_UsainBolt(int k) { // 85cbe0
Guard_HandleAllAnimation(k);
if (Sprite_ReturnIfInactive(k))
return;
BoltGuard_TriggerChaseTheme(k);
Guard_ParrySwordAttacks(k);
if (Sprite_ReturnIfRecoiling(k))
return;
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
Sprite_CheckDamageToLink(k);
if (!((k ^ frame_counter) & 15)) {
sprite_head_dir[k] = sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
Sprite_ApplySpeedTowardsLink(k, 18);
Guard_ApplySpeedInDirection(k);
}
sprite_subtype2[k]++;
Guard_TickAndUpdateBody(k);
}
void BoltGuard_TriggerChaseTheme(int k) { // 85cc3c
if (sprite_G[k] != 16 && sprite_G[k]++ == 15) {
SpriteSfx_QueueSfx3WithPan(k, 0x4);
if (sram_progress_indicator == 2 && BYTE(overworld_area_index) == 24)
music_control = 12;
}
}
void Sprite_44_BluesainBolt(int k) { // 85cc65
PsychoTrooper_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
BoltGuard_TriggerChaseTheme(k);
Guard_ParrySwordAttacks(k);
if (Sprite_ReturnIfRecoiling(k))
return;
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
Sprite_CheckDamageToLink(k);
if (!((k ^ frame_counter) & 15)) {
sprite_D[k] = sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL);
Sprite_ApplySpeedTowardsLink(k, 18);
Guard_ApplySpeedInDirection(k);
}
sprite_graphics[k] = kFlailTrooperGfx[++sprite_subtype2[k] >> 1 & 7 | sprite_D[k] << 3];
}
void PsychoTrooper_Draw(int k) { // 85ccd5
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
SpriteDraw_GuardHead(k, &info, 3);
SpriteDraw_BNCBody(k, &info, 2);
SpriteDraw_GuardSpear(k, &info, 0);
if (sprite_flags3[k] & 0x10)
SpriteDraw_Shadow_custom(k, &info, kSoldier_DrawShadow[sprite_D[k]]);
}
void SpriteDraw_GuardSpear(int k, PrepOamCoordsRet *info, int spr_offs) { // 85cd54
static const int8 kSolderThrowing_Draw_X[16] = {15, 7, 17, 9, -8, 0, -10, -2, 13, 13, 13, 13, -4, -4, -4, -4};
static const int8 kSolderThrowing_Draw_Y[16] = {-2, -2, -2, -2, -2, -2, -2, -2, 8, 0, 10, 2, -14, -6, -16, -8};
static const uint8 kSolderThrowing_Draw_Char[16] = {0x6f, 0x7f, 0x6f, 0x7f, 0x6f, 0x7f, 0x6f, 0x7f, 0x6e, 0x7e, 0x6e, 0x7e, 0x6e, 0x7e, 0x6e, 0x7e};
static const uint8 kSolderThrowing_Draw_Flags[16] = {0x40, 0x40, 0x40, 0x40, 0, 0, 0, 0, 0x80, 0x80, 0x80, 0x80, 0, 0, 0, 0};
OamEnt *oam = GetOamCurPtr() + spr_offs;
uint8 r6 = sprite_D[k] * 4 + (((sprite_A[k] ^ 1) << 1) & 2);
for (int i = 1; i >= 0; i--, oam++) {
int j = r6 + i;
uint16 x = info->x + kSolderThrowing_Draw_X[j];
uint16 y = info->y + kSolderThrowing_Draw_Y[j];
HIBYTE(dungmap_var8) = kSolderThrowing_Draw_X[j];
BYTE(dungmap_var8) = kSolderThrowing_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kSolderThrowing_Draw_Char[j] - (sprite_type[k] >= 0x48 ? 3 : 0);
oam->flags = (kSolderThrowing_Draw_Flags[j] | info->flags) & 0xf1 | 8;
bytewise_extended_oam[oam - oam_buf] = (x >> 8 & 1);
}
}
void Sprite_48_RedJavelinGuard(int k) { // 85cde1
static const uint8 kJavelinTrooper_Gfx[4] = {12, 0, 18, 8};
uint8 bak0 = sprite_graphics[k];
int j = sprite_D[k];
if (sprite_delay_aux1[k] != 0) {
sprite_D[k] = kSoldier_DirectionLockSettings[j];
sprite_graphics[k] = kJavelinTrooper_Gfx[j];
}
JavelinTrooper_Draw(k);
sprite_D[k] = j;
sprite_graphics[k] = bak0;
SoldierThrowing_Common(k);
}
void Sprite_46_BlueArcher(int k) { // 85cdff
uint8 bak0 = sprite_graphics[k];
int j = sprite_D[k];
if (sprite_delay_aux1[k] != 0) {
sprite_D[k] = kSoldier_DirectionLockSettings[j];
sprite_graphics[k] = kSoldier_Gfx[j];
}
ArcherSoldier_Draw(k);
sprite_D[k] = j;
sprite_graphics[k] = bak0;
SoldierThrowing_Common(k);
}
void SoldierThrowing_Common(int k) { // 85ce23
int j;
static const uint8 kSolderThrowing_DirFlags[4] = {3, 3, 12, 12};
static const int8 kSolderThrowing_Xd[8] = {-80, 80, 0, -8, -80, 80, -8, 8};
static const int8 kSolderThrowing_Yd[8] = {8, 8, -80, 80, 8, 8, -80, 80};
if (Sprite_ReturnIfInactive(k))
return;
if ((Sprite_CheckDamageToAndFromLink(k) || sprite_alert_flag) && sprite_ai_state[k] < 3) {
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 32;
}
if (sprite_F[k] >= 4) {
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 60;
sprite_subtype2[k] = 0;
}
if (Sprite_ReturnIfRecoiling(k))
return;
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
switch (sprite_ai_state[k]) {
case 0: // resting
Sprite_ZeroVelocity_XY(k);
if (sprite_delay_main[k] == 0) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 0x50 + (GetRandomNumber() & 0x7f);
uint8 jbak = sprite_D[k];
sprite_D[k] = GetRandomNumber() & 3;
if (sprite_D[k] != jbak && !((sprite_D[k] ^ jbak) & 2))
sprite_delay_aux1[k] = 12;
}
break;
case 1: // walking
if (sprite_delay_main[k] == 0) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 160;
return;
}
Sprite_Guard_SendOutProbe(k);
if (sprite_wallcoll[k] & 0xf) {
sprite_D[k] ^= 1;
Guard_SetGlanceTo12(k);
}
j = sprite_D[k];
sprite_x_vel[k] = kSoldier_Xvel[j];
sprite_y_vel[k] = kSoldier_Yvel[j];
sprite_head_dir[k] = j;
agitated_jump_to:
sprite_subtype2[k]++;
if (!(sprite_subtype2[k] & 0xf) && ++sprite_A[k] == 2)
sprite_A[k] = 0;
sprite_graphics[k] = kSoldier_Gfx2[sprite_D[k] * 4 + sprite_A[k] + (sprite_type[k] == 0x48 ? 16 : 0)];
break;
case 2: // looking
Sprite_ZeroVelocity_XY(k);
Sprite_Guard_SendOutProbe(k);
if (sprite_delay_main[k] == 0) {
sprite_delay_main[k] = 32;
sprite_ai_state[k] = 0;
} else if (sprite_delay_main[k] < 0x80) {
int t = sprite_D[k] * 8 | (sprite_delay_main[k] >> 3 & 7);
sprite_head_dir[k] = kSoldier_HeadDirs[t];
}
break;
case 3: // noticed player
Sprite_ZeroVelocity_XY(k);
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL);
if (sprite_delay_main[k] == 0) {
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 60;
sprite_subtype2[k] = 0;
}
break;
case 4: // agitated
j = sprite_D[k];
if (sprite_wallcoll[k] & kSolderThrowing_DirFlags[j] || !sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 24;
return;
}
if (!((frame_counter ^ k) & 7)) {
sprite_D[k] = sprite_head_dir[k] = j = Sprite_DirectionToFaceLink(k, NULL);
if (sprite_type[k] == 0x48)
j += 4;
uint16 x = link_x_coord + kSolderThrowing_Xd[j];
uint16 y = link_y_coord + kSolderThrowing_Yd[j];
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 24);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
if ((uint8)(pt.xdiff + 6) < 12 && (uint8)(pt.ydiff + 6) < 12) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 24;
return;
}
}
sprite_subtype2[k]++;
goto agitated_jump_to;
case 5: // attack
sprite_anim_clock[k] = kSoldier_Tab1[sprite_D[k]];
Sprite_ZeroVelocity_XY(k);
if ((j = sprite_delay_main[k]) == 0) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 160;
return;
}
sprite_subtype2[k] = (j >= 40) ? 255 : 0;
if (j == 12)
Guard_LaunchProjectile(k);
sprite_graphics[k] = kJavelinTrooper_Tab2[sprite_D[k] * 8 + (j >> 3) + (sprite_type[k] == 0x48 ? 32 : 0)];
break;
}
}
void Guard_LaunchProjectile(int k) { // 85d0c5
static const int8 kJavelinProjectile_X[8] = {16, -8, 3, 11, 12, -4, 12, -4};
static const int8 kJavelinProjectile_Y[8] = {2, 2, 16, -8, -2, -2, 2, -8};
static const int8 kJavelinProjectile_Xvel[8] = {48, -48, 0, 0, 32, -32, 0, 0};
static const int8 kJavelinProjectile_Yvel[8] = {0, 0, 48, -48, 0, 0, 32, -32};
static const uint8 kJavelinProjectile_Flags4[4] = {5, 5, 6, 6};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x1b, &info);
if (j < 0)
return;
SpriteSfx_QueueSfx3WithPan(k, 0x5);
int i = sprite_D[k] + (sprite_type[k] >= 0x48 ? 4 : 0);
Sprite_SetX(j, info.r0_x + kJavelinProjectile_X[i]);
Sprite_SetY(j, info.r2_y + kJavelinProjectile_Y[i]);
sprite_x_vel[j] = kJavelinProjectile_Xvel[i];
sprite_y_vel[j] = kJavelinProjectile_Yvel[i];
i &= 3;
sprite_D[j] = i;
sprite_flags4[j] = kJavelinProjectile_Flags4[i];
sprite_z[j] = 0;
sprite_A[j] = (sprite_type[k] >= 0x48);
if (sprite_A[j] && link_shield_type == 0)
sprite_flags5[j] &= ~0x20;
}
void BushJavelinSoldier_Draw(int k) { // 85d141
uint8 bak0 = sprite_graphics[k];
sprite_graphics[k] = 0;
uint8 bak1 = sprite_oam_flags[k];
sprite_oam_flags[k] = sprite_oam_flags[k] & 0xf1 | 2;
uint16 bak2 = cur_sprite_y;
cur_sprite_y += 8;
SpriteDraw_SingleLarge(k);
cur_sprite_y = bak2;
sprite_oam_flags[k] = bak1;
sprite_graphics[k] = bak0;
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
Guard_AnimateHead(k, 0x10 / 4, &info);
SpriteDraw_BNCBody(k, &info, 0xC / 4);
if (sprite_graphics[k] < 20)
SpriteDraw_GuardSpear(k, &info, 4 / 4);
if (sprite_flags3[k] & 0x10)
SpriteDraw_Shadow_custom(k, &info, kSoldier_DrawShadow[sprite_D[k]]);
}
void JavelinTrooper_Draw(int k) { // 85d192
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
SpriteDraw_GuardHead(k, &info, 3);
SpriteDraw_BNCBody(k, &info, 2);
if (sprite_graphics[k] < 20)
SpriteDraw_GuardSpear(k, &info, 0);
if (sprite_flags3[k] & 0x10)
SpriteDraw_Shadow_custom(k, &info, kSoldier_DrawShadow[sprite_D[k]]);
}
void Sprite_49_RedBushGuard(int k) { // 85d1ac
if (sprite_ai_state[k]) {
if (sprite_ai_state[k] == 2)
BushJavelinSoldier_Draw(k);
else
BushSoldierCommon_Draw(k);
}
Sprite_BushGuard_Main(k);
}
void Sprite_47_GreenBushGuard(int k) { // 85d1bf
if (sprite_ai_state[k]) {
if (sprite_graphics[k] >= 14)
ArcherSoldier_Draw(k);
else
BushSoldierCommon_Draw(k);
}
Sprite_BushGuard_Main(k);
}
void Sprite_BushGuard_Main(int k) { // 85d1d3
int j;
static const uint8 kBushSoldier_Gfx[32] = {
4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
};
static const uint8 kBushSoldier_Gfx2[16] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 3, 4, 4, 4, 4, 4};
if (Sprite_ReturnIfInactive(k))
return;
sprite_ignore_projectile[k] = 1;
switch (sprite_ai_state[k]) {
case 0:
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 64;
}
break;
case 1:
Sprite_CheckDamageFromLink(k);
if (sprite_delay_main[k] == 0) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 48;
sprite_head_dir[k] = sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);;
} else {
if (sprite_delay_main[k] == 0x20)
BushGuard_SpawnFoliage(k);
sprite_graphics[k] = kBushSoldier_Gfx[sprite_delay_main[k] >> 2];
}
break;
case 2:
sprite_ignore_projectile[k] = 0;
Sprite_CheckDamageToAndFromLink(k);
j = sprite_delay_main[k];
if (!j) {
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 48;
goto case_3;
}
sprite_A[k] = j < 40 ? 0xff : 0x00;
if (j == 16)
Guard_LaunchProjectile(k);
sprite_graphics[k] = kJavelinTrooper_Tab2[sprite_D[k] * 8 + (j >> 3) + (sprite_type[k] == 0x49 ? 32 : 0)];
break;
case 3:
case_3:
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 64;
} else {
sprite_graphics[k] = kBushSoldier_Gfx2[sprite_delay_main[k] >> 2];
}
break;
}
}
void BushGuard_SpawnFoliage(int k) { // 85d252
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xec, &info);
if (j < 0)
return;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_state[j] = 6;
sprite_delay_main[j] = 32;
sprite_flags2[j] += 3;
sprite_C[j] = 2;
}
void BushSoldierCommon_Draw(int k) { // 85d321
static const int8 kBushSoldierCommon_Y[14] = {8, 8, 8, 8, 2, 8, 0, 8, -3, 8, -3, 8, -3, 8};
static const uint8 kBushSoldierCommon_Char[14] = {0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x42, 0x20, 0x42, 0x20};
static const uint8 kBushSoldierCommon_Flags[14] = {9, 3, 0x49, 0x43, 9, 3, 0x49, 0x43, 9, 3, 0x49, 0x43, 9, 3};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k] * 2;
for (int i = 1; i >= 0; i--, oam++) {
int j = g + i;
uint16 x = info.x;
uint16 y = info.y + kBushSoldierCommon_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kBushSoldierCommon_Char[j];
uint8 flags = kBushSoldierCommon_Flags[j] | 0x20;
if (i == 0)
flags = flags & ~0xe | info.flags;
oam->flags = flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
}
void ArcherSoldier_Draw(int k) { // 85d38c
static const uint8 kArcherSoldier_WeaponOamOffs[4] = {0, 0, 0, 16};
static const uint8 kArcherSoldier_HeadOamOffs[4] = {16, 16, 16, 0};
static const uint8 kArcherSoldier_BodyOamOffs[4] = {20, 20, 20, 4};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
Guard_AnimateHead(k, kArcherSoldier_HeadOamOffs[sprite_D[k]] >> 2, &info);
Guard_AnimateBody(k, kArcherSoldier_BodyOamOffs[sprite_D[k]] >> 2, &info);
SpriteDraw_Archer_Weapon(k, kArcherSoldier_WeaponOamOffs[sprite_D[k]] >> 2, &info);
if (sprite_flags3[k] & 0x10)
SpriteDraw_Shadow_custom(k, &info, kSoldier_DrawShadow[sprite_D[k]]);
}
void SpriteDraw_Archer_Weapon(int k, int spr_offs, PrepOamCoordsRet *info) { // 85d4d4
static const uint8 kArcherSoldier_Tab1[4] = {9, 3, 0, 6};
static const int8 kArcherSoldier_Draw_X[48] = {
-1, 7, 3, 3, -1, 7, 3, 3, -1, 7, 7, 7, -5, -5, -10, -2,
-4, -4, -6, 2, -5, -5, -5, -5, 6, 14, 11, 11, 6, 14, 11, 11,
6, 14, 14, 14, 11, 11, 18, 10, 12, 12, 14, 6, 11, 11, 11, 11,
};
static const int8 kArcherSoldier_Draw_Y[48] = {
7, 7, 3, 11, 6, 6, 1, 9, 7, 7, 7, 7, -2, 6, 2, 2,
-2, 6, 2, 2, -2, 6, 6, 6, -6, -6, -12, -4, -6, -6, -9, -1,
-6, -6, -6, -6, -2, 6, 2, 2, -2, 6, 2, 2, -2, 6, 6, 6,
};
static const uint8 kArcherSoldier_Draw_Char[48] = {
0xa, 0xa, 0x2a, 0x2b, 0x1a, 0x1a, 0x2a, 0x2b, 0xa, 0xa, 0xa, 0xa, 0xb, 0xb, 0x3d, 0x3a,
0x1b, 0x1b, 0x3d, 0x3a, 0xb, 0xb, 0xb, 0xb, 0xa, 0xa, 0x2b, 0x2a, 0xa, 0xa, 0x2b, 0x2a,
0xa, 0xa, 0xa, 0xa, 0xb, 0xb, 0x3d, 0x3a, 0x1b, 0x1b, 0x3d, 0x3a, 0xb, 0xb, 0xb, 0xb,
};
static const uint8 kArcherSoldier_Draw_Flags[48] = {
0xd, 0x4d, 8, 8, 0xd, 0x4d, 8, 8, 0xd, 0x4d, 0x4d, 0x4d, 0xd, 0x8d, 0x48, 0x48,
0xd, 0x8d, 0x48, 0x48, 0xd, 0x8d, 0x8d, 0x8d, 0x8d, 0xcd, 0x88, 0x88, 0x8d, 0xcd, 0x88, 0x88,
0x8d, 0xcd, 0xcd, 0xcd, 0x4d, 0xcd, 8, 8, 0x4d, 0xcd, 8, 8, 0x4d, 0xcd, 0xcd, 0xcd,
};
OamEnt *oam = GetOamCurPtr() + spr_offs;
int base = sprite_graphics[k] - 14;
if (base < 0)
base = kArcherSoldier_Tab1[sprite_D[k]];
for (int i = 3; i >= 0; i--, oam++) {
int j = base * 4 + i;
uint16 x = info->x + kArcherSoldier_Draw_X[j];
uint16 y = info->y + kArcherSoldier_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kArcherSoldier_Draw_Char[j];
oam->flags = kArcherSoldier_Draw_Flags[j] | 0x20;
bytewise_extended_oam[oam - oam_buf] = (x >> 8 & 1);
}
}
void TutorialSoldier_Draw(int k) { // 85d64b
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int d = sprite_graphics[k] * 5;
for (int i = 4; i >= 0; i--, oam++) {
int j = d + i;
uint16 x = info.x + kTutorialSoldier_X[j];
uint16 y = info.y + kTutorialSoldier_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kTutorialSoldier_Char[j];
uint8 flags = kTutorialSoldier_Flags[j] | info.flags;
if (oam->charnum < 0x40)
flags = (flags & 0xf1) | 8;
oam->flags = flags;
bytewise_extended_oam[oam - oam_buf] = kTutorialSoldier_Ext[j] | (x >> 8 & 1);
}
SpriteDraw_Shadow_custom(k, &info, 12);
}
void PullSwitch_FacingUp(int k) { // 85d6d4
static const uint8 kBadPullSwitch_Tab1[10] = {8, 24, 4, 4, 4, 4, 4, 4, 2, 10};
static const uint8 kBadPullSwitch_Tab0[10] = {6, 7, 8, 8, 8, 8, 8, 9, 9, 9};
PullSwitch_HandleUpPulling(k);
int j = sprite_graphics[k];
if (j != 0 && j != 11) {
link_unk_master_sword = kBadPullSwitch_Tab0[j - 1];
link_y_coord = Sprite_GetY(k) - 19;
link_x_coord = Sprite_GetX(k);
if (sprite_delay_main[k] == 0) {
sprite_graphics[k] = ++j;
if (j == 11) {
sound_effect_2 = 0x1b;
dung_flag_statechange_waterpuzzle = 1;
}
sprite_delay_main[k] = kBadPullSwitch_Tab1[j - 2];
}
}
if (sprite_type[k] != 7)
BadPullDownSwitch_Draw(k);
else
BadPullUpSwitch_Draw(k);
}
void PullSwitch_HandleUpPulling(int k) { // 85d743
if (!Sprite_CheckDamageToLink_same_layer(k))
return;
link_actual_vel_y = 0;
link_actual_vel_x = 0;
Sprite_RepelDash();
bitmask_of_dragstate = 0;
uint8 y = link_y_coord - sprite_y_lo[k];
if (!sign8(y - 2)) {
link_y_coord = Sprite_GetY(k) + 9;
} else if (sign8(y - 244)) {
byte_7E0379++;
if (joypad1L_last & 0x80 && !(joypad1H_last & 3) && sprite_graphics[k] == 0) {
sprite_graphics[k] = 1;
sprite_delay_main[k] = 8;
SpriteSfx_QueueSfx2WithPan(k, 0x22);
}
link_y_coord = Sprite_GetY(k) - 21;
} else {
if (sign8(link_x_coord - sprite_x_lo[k]))
link_x_coord = Sprite_GetX(k) - 16;
else
link_x_coord = Sprite_GetX(k) + 14;
}
}
void BadPullDownSwitch_Draw(int k) { // 85d7f9
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
Oam_AllocateDeferToPlayer(k);
OamEnt *oam = GetOamCurPtr();
uint8 yoff = kBadPullSwitch_Tab5[kBadPullSwitch_Tab4[sprite_graphics[k]]];
for (int i = 4; i >= 0; i--, oam++) {
oam->x = info.x + kBadPullDownSwitch_X[i];
oam->y = info.y + kBadPullDownSwitch_Y[i] - (i == 2 ? yoff : 0);
oam->charnum = kBadPullDownSwitch_Char[i];
oam->flags = kBadPullDownSwitch_Flags[i] | 0x21;
bytewise_extended_oam[oam - oam_buf] = kBadPullDownSwitch_Ext[i];
}
Sprite_CorrectOamEntries(k, 4, 0xff);
}
void BadPullUpSwitch_Draw(int k) { // 85d858
static const uint8 kBadPullUpSwitch_Tab2[2] = {0xa2, 0xa4};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
Oam_AllocateDeferToPlayer(k);
OamEnt *oam = GetOamCurPtr();
uint8 yoff = kBadPullSwitch_Tab5[kBadPullSwitch_Tab4[sprite_graphics[k]]];
for (int i = 1; i >= 0; i--, oam++) {
uint16 x = info.x;
uint16 y = info.y - ((i == 0) ? yoff : 0);
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kBadPullUpSwitch_Tab2[i];
oam->flags = info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
}
void PullSwitch_FacingDown(int k) { // 85d8b5
static const uint8 kGoodPullSwitch_Tab1[12] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
static const uint8 kGoodPullSwitch_Tab0[12] = {1, 1, 2, 2, 3, 3, 1, 1, 4, 4, 5, 5};
static const uint8 kGoodPullSwitch_YOffs[12] = {9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14};
PullSwitch_HandleDownPulling(k);
int j = sprite_graphics[k];
if (j != 0 && j != 13) {
link_unk_master_sword = kGoodPullSwitch_Tab0[j - 1];
link_y_coord = Sprite_GetY(k) + kGoodPullSwitch_YOffs[j - 1];
link_x_coord = Sprite_GetX(k);
if (sprite_delay_main[k] == 0) {
sprite_graphics[k] = ++j;
if (j == 13) {
if (sprite_type[k] == 6) {
activate_bomb_trap_overlord = 1;
sound_effect_1 = 0x3c;
} else {
dung_flag_statechange_waterpuzzle = 1;
sound_effect_2 = 0x1b;
}
}
sprite_delay_main[k] = kGoodPullSwitch_Tab1[j - 2];
}
}
GoodPullSwitch_Draw(k);
if (sprite_pause[k])
sprite_graphics[k] = 0;
}
void GoodPullSwitch_Draw(int k) { // 85d953
static const uint8 kGoodPullSwitch_Tab2[14] = {1, 1, 2, 3, 2, 3, 4, 5, 6, 7, 6, 7, 7, 7};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
Oam_AllocateDeferToPlayer(k);
OamEnt *oam = GetOamCurPtr();
uint8 t = kGoodPullSwitch_Tab2[sprite_graphics[k]];
oam[0].x = oam[1].x = info.x;
oam[0].y = info.y - 1;
oam[1].y = info.y - 1 + t;
oam[0].charnum = 0xee;
oam[1].charnum = 0xce;
oam[0].flags = oam[1].flags = info.flags;
Sprite_CorrectOamEntries(k, 1, 2);
}
void PullSwitch_HandleDownPulling(int k) { // 85d999
if (!Sprite_CheckDamageToLink_same_layer(k))
return;
link_actual_vel_y = 0;
link_actual_vel_x = 0;
Sprite_RepelDash();
bitmask_of_dragstate = 0;
uint8 y = link_y_coord - sprite_y_lo[k];
if (!sign8(y - 2)) {
byte_7E0379++;
if (joypad1L_last & 0x80 && !(joypad1H_last & 3)) {
link_unk_master_sword++;
if ((joypad1H_last & 4) && sprite_graphics[k] == 0) {
sprite_graphics[k] = 1;
sprite_delay_main[k] = 12;
SpriteSfx_QueueSfx2WithPan(k, 0x22);
}
}
link_y_coord = Sprite_GetY(k) + 9;
} else if (sign8(y - 244)) {
link_y_coord = Sprite_GetY(k) - 21;
} else {
if (sign8(link_x_coord - sprite_x_lo[k]))
link_x_coord = Sprite_GetX(k) - 16;
else
link_x_coord = Sprite_GetX(k) + 14;
}
}
void Priest_SpawnMantle(int k) { // 85db27
sprite_state[15]++;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x73, &info);
sprite_state[15] = 0;
sprite_flags2[j] = sprite_flags2[j] & 0xf0 | 0x3;
sprite_x_lo[j] = 0xF0;
sprite_x_hi[j] = 4;
sprite_y_lo[j] = 0x37;
sprite_y_hi[j] = 2;
sprite_E[j] = 2;
sprite_flags4[j] = 11;
sprite_defl_bits[j] |= 0x20;
sprite_subtype2[j] = 1;
if (link_y_coord < Sprite_GetY(j))
sprite_C[j] = 1;
}
void Sprite_SanctuaryMantle(int k) { // 85db9b
SageMantle_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_C[k]) {
sprite_A[k] = 0x40;
goto lbl2;
}
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Sprite_RepelDash();
sprite_delay_aux1[k] = 7;
lbl:
sprite_subtype2[k] = 0;
bitmask_of_dragstate = 0x81;
link_speed_setting = 8;
lbl2:
switch (sprite_ai_state[k]) {
case 0: {
uint16 x = Sprite_GetX(k);
Sprite_SetX(k, x + 19);
uint8 dir = Sprite_DirectionToFaceLink(k, NULL);
Sprite_SetX(k, x);
if (dir == 1 || dir == 3) {
sprite_A[k]++;
if (sprite_A[k] >= 64) {
sprite_ai_state[k]++;
flag_is_link_immobilized = 1;
}
}
break;
}
case 1:
SpriteSfx_QueueSfx3WithPan(k, 24);
sprite_ai_state[k]++;
sprite_delay_main[k] = 168;
sprite_x_vel[k] = 3;
sprite_delay_aux1[k] = 2;
break;
case 2:
Sprite_MoveXY(k);
if (sprite_delay_main[k] == 0) {
flag_is_link_immobilized = 0;
sprite_x_vel[k] = 0;
sprite_C[k] = 0;
} else {
sprite_delay_aux1[k] = 2;
}
break;
}
} else { // no collision
if (sprite_delay_aux1[k])
goto lbl;
switch (sprite_subtype2[k]) {
case 0:
sprite_A[k] = 0;
bitmask_of_dragstate = 0;
link_speed_setting = 0;
sprite_subtype2[k]++;
break;
case 1:
break;
}
}
}
void SageMantle_Draw(int k) { // 85dc8a
if (sprite_C[k] == 0)
Oam_AllocateFromRegionB(0x10);
Sprite_DrawMultiple(k, kSageMantle_Dmd, 4, NULL);
}
void Sprite_Priest(int k) { // 85dce6
if (sprite_A[k] == 0)
Priest_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (Sprite_TrackBodyToHead(k))
Sprite_MoveXY(k);
switch (sprite_subtype2[k]) {
case 0: Priest_Dying(k); break;
case 1: Priest_RunRescueCutscene(k); break;
case 2: Priest_Chillin(k); break;
}
}
void Priest_Dying(int k) { // 85dd0a
sprite_head_dir[k] = 4;
sprite_D[k] = 4;
switch (sprite_ai_state[k]) {
case 0: // Priest_LyingOnGround
if (Sprite_ShowSolicitedMessage(k, 0x1b) & 0x100) {
sprite_ai_state[k]++;
sprite_graphics[k]++;
sram_progress_flags |= 0x2;
sprite_delay_aux2[k] = 128;
}
break;
case 1: // Priest_FinalWords
sprite_graphics[k] = 0;
if (sprite_delay_aux2[k] == 0)
sprite_ai_state[k]++;
sprite_A[k] = frame_counter & 2;
if (!(sprite_delay_aux2[k] & 7))
SpriteSfx_QueueSfx2WithPan(k, 0x33);
break;
case 2: // Priest_Die
sprite_state[k] = 0;
break;
}
}
void Priest_RunRescueCutscene(int k) { // 85dd63
int j;
switch (sprite_ai_state[k]) {
case 0:
sprite_head_dir[k] = 0;
sprite_D[k] = 0;
if (sprite_delay_main[k] == 0) {
Sprite_ShowMessageUnconditional(0x17);
sprite_ai_state[k]++;
byte_7FFE01 = 1;
Priest_SpawnRescuedPrincess();
flag_is_link_immobilized = 1;
savegame_map_icons_indicator = 1;
}
break;
case 1:
if (byte_7FFE01 == 2) {
Sprite_ShowMessageUnconditional(0x18);
sprite_ai_state[k]++;
}
break;
case 2:
if (choice_in_multiselect_box == 0) {
sprite_ai_state[k]++;
flag_is_link_immobilized = 0;
} else {
sprite_ai_state[k] = 1;
}
break;
case 3:
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
j = Sprite_ShowSolicitedMessage(k, 0x16);
if (j & 0x100)
sprite_D[k] = sprite_head_dir[k] = (uint8)j;
break;
}
}
void Priest_Chillin(int k) { // 85dde5
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
int m = (link_which_pendants & 7) == 7 ? 0x1a :
savegame_map_icons_indicator >= 3 ? 0x19 : 0x16;
int j = Sprite_ShowSolicitedMessage(k, m);
if (j & 0x100) {
sprite_D[k] = sprite_head_dir[k] = (uint8)j;
link_hearts_filler = 0xa0;
}
}
void Sprite_Uncle(int k) { // 85de2c
Uncle_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_subtype2[k] == 0)
Uncle_AtHouse(k);
else
Uncle_InPassage(k);
}
void Uncle_AtHouse(int k) { // 85de3e
Sprite_MoveXY(k);
switch (sprite_ai_state[k]) {
case 0: // Uncle_TriggerTelepathy
link_x_coord_prev = 0x940;
link_y_coord_prev = 0x215a;
Sprite_ShowMessageUnconditional(0x1f);
sprite_ai_state[k]++;
break;
case 1: // Uncle_AwakenLink
if (frame_counter & 3)
break;
if (COLDATA_copy0 != 32) {
COLDATA_copy0--;
COLDATA_copy1--;
break;
}
link_pose_during_opening++;
player_sleep_in_bed_state++;
link_y_coord = 0x2157;
flag_is_link_immobilized = 1;
sprite_ai_state[k]++;
break;
case 2: // Uncle_DeclareCurfew
Sprite_ShowMessageUnconditional(0x0d);
music_control = 3;
sprite_graphics[k] = 1;
sprite_ai_state[k]++;
break;
case 3: // Uncle_Embark
sprite_graphics[k] = frame_counter >> 3 & 1;
if (!sprite_delay_main[k]) {
int j = sprite_A[k];
if (j == 2) {
sprite_ai_state[k]++;
} else {
sprite_A[k]++;
if (!j)
sprite_y_lo[k] -= 2;
sprite_delay_main[k] = kUncle_LeaveHouse_Delay[j];
sprite_D[k] = j = kUncle_LeaveHouse_Dir[j];
sprite_x_vel[k] = kUncle_LeaveHouse_Xvel[j];
sprite_y_vel[k] = kUncle_LeaveHouse_Yvel[j];
}
}
break;
case 4: // Uncle_ApplyTelepathyFollower
follower_indicator = 5;
word_7E02CD = 0xdf3;
sram_progress_flags |= 0x10;
sprite_state[k] = 0;
flag_is_link_immobilized = 0;
break;
}
}
void Uncle_InPassage(int k) { // 85df19
switch (sprite_ai_state[k]) {
case 0: // RemoveZeldaTelepathTagalong
if (Sprite_CheckDamageToLink_same_layer(k))
Link_CancelDash();
if (Sprite_ShowMessageOnContact(k, 0xe) & 0x100) {
follower_indicator = 0;
sprite_ai_state[k]++;
}
break;
case 1: // GiveSwordAndShield
item_receipt_method = 0;
Link_ReceiveItem(0, 0);
sprite_ai_state[k]++;
sprite_graphics[k] = 1;
which_starting_point = 3;
sram_progress_flags |= 1;
sram_progress_indicator = 1;
break;
}
}
void Sprite_QuarrelBros(int k) { // 85e013
QuarrelBros_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_TrackBodyToHead(k);
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
if (!(dungeon_room_index & 1)) {
Sprite_ShowSolicitedMessage(k, 0x131);
} else if (!(dung_door_opened & 0xff00)) {
Sprite_ShowSolicitedMessage(k, 0x12f);
} else {
Sprite_ShowSolicitedMessage(k, 0x130);
}
Sprite_BehaveAsBarrier(k);
}
void QuarrelBros_Draw(int k) { // 85e17f
static const DrawMultipleData kQuarrelBros_Dmd[16] = {
{0, -12, 0x0004, 2},
{0, 0, 0x000a, 2},
{0, -11, 0x0004, 2},
{0, 1, 0x400a, 2},
{0, -12, 0x0004, 2},
{0, 0, 0x000a, 2},
{0, -11, 0x0004, 2},
{0, 1, 0x400a, 2},
{0, -12, 0x0008, 2},
{0, 0, 0x000a, 2},
{0, -11, 0x0008, 2},
{0, 1, 0x400a, 2},
{0, -12, 0x4008, 2},
{0, 0, 0x000a, 2},
{0, -11, 0x4008, 2},
{0, 1, 0x400a, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kQuarrelBros_Dmd[sprite_graphics[k] * 2 + sprite_D[k] * 4], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_YoungSnitchLady(int k) { // 85e2f2
Sprite_OldSnitchLady(k);
}
void YoungSnitchLady_Draw(int k) { // 85e37f
static const DrawMultipleData kYoungSnitchLady_Dmd[16] = {
{0, -8, 0x0026, 2},
{0, 0, 0x00e8, 2},
{0, -7, 0x0026, 2},
{0, 1, 0x40e8, 2},
{0, -8, 0x0024, 2},
{0, 0, 0x00c2, 2},
{0, -7, 0x0024, 2},
{0, 1, 0x40c2, 2},
{0, -8, 0x0028, 2},
{0, 0, 0x00e4, 2},
{0, -7, 0x0028, 2},
{0, 1, 0x00e6, 2},
{0, -8, 0x4028, 2},
{0, 0, 0x40e4, 2},
{0, -7, 0x4028, 2},
{0, 1, 0x40e6, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kYoungSnitchLady_Dmd[sprite_graphics[k] * 2 + sprite_D[k] * 4], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_InnKeeper(int k) { // 85e3af
InnKeeper_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
Sprite_ShowSolicitedMessage(k, link_item_flippers ? 0x183 : 0x182);
}
void InnKeeper_Draw(int k) { // 85e3dc
static const DrawMultipleData kInnKeeper_Dmd[2] = {
{0, -8, 0x00c4, 2},
{0, 0, 0x00ca, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, kInnKeeper_Dmd, 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_Witch(int k) { // 85e3fb
Witch_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
uint8 bak0 = sprite_flags4[k];
sprite_flags4[k] = 2;
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Link_CancelDash();
}
sprite_flags4[k] = bak0;
if (!frame_counter)
sprite_A[k] = (GetRandomNumber() & 1) + 2;
int shift = sprite_A[k] + 1;
sprite_graphics[k] = (frame_counter >> shift) & 7;
if (Sprite_CheckIfLinkIsBusy())
return;
switch (sprite_ai_state[k]) {
case 0: // main
if (link_item_mushroom == 0) {
if (save_dung_info[0x109] & 0x80)
Sprite_ShowSolicitedMessage(k, 0x4b);
else
Sprite_ShowSolicitedMessage(k, 0x4a);
} else if (link_item_mushroom == 1) {
if (!(joypad1H_last & 0x40)) {
Sprite_ShowSolicitedMessage(k, 0x4c);
} else if (Sprite_CheckDamageToLink_same_layer(k) && hud_cur_item == kHudItem_Mushroom) {
Witch_AcceptShroom(k);
}
} else {
Sprite_ShowSolicitedMessage(k, 0x4a);
}
break;
case 1: // grant cane of byrna
sprite_ai_state[k] = 0;
item_receipt_method = 0;
Link_ReceiveItem(0x18, 0);
break;
}
}
void Witch_AcceptShroom(int k) { // 85e4cf
link_item_mushroom = 0;
save_dung_info[0x109] |= 0x80;
sound_effect_1 = 0;
Hud_RefreshIcon();
Sprite_ShowMessageUnconditional(0x4b);
SpriteSfx_QueueSfx1WithPan(k, 0xd);
flag_overworld_area_did_change = 0;
}
void Witch_Draw(int k) { // 85e55d
static const OamEntSigned kWitch_DrawDataA[16] = {
{-3, 8, 0xae, 0x00},
{-3, 16, 0xbe, 0x00},
{-2, 8, 0xae, 0x00},
{-2, 16, 0xbe, 0x00},
{-1, 8, 0xaf, 0x00},
{-1, 16, 0xbf, 0x00},
{ 0, 9, 0xaf, 0x00},
{ 0, 17, 0xbf, 0x00},
{ 1, 10, 0xaf, 0x00},
{ 1, 18, 0xbf, 0x00},
{ 0, 11, 0xaf, 0x00},
{ 0, 18, 0xbf, 0x00},
{-1, 10, 0xae, 0x00},
{-1, 18, 0xbe, 0x00},
{-3, 9, 0xae, 0x00},
{-3, 17, 0xbe, 0x00},
};
static const OamEntSigned kWitch_DrawDataB[3] = {
{ 0, -4, 0x80, 0x00},
{-11, 15, 0x86, 0x04},
{ -3, 15, 0x86, 0x44},
};
static const OamEntSigned kWitch_DrawDataC[2] = {
{0, 4, 0x84, 0x00},
{0, 4, 0x82, 0x00},
};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
Oam_AllocateDeferToPlayer(k);
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
oam[0].x = BYTE(dungmap_var7) + kWitch_DrawDataA[g * 2].x;
oam[0].y = HIBYTE(dungmap_var7) + kWitch_DrawDataA[g * 2].y;
WORD(oam[0].charnum) = WORD(info.r4) | WORD(kWitch_DrawDataA[g * 2].charnum);
oam[1].x = BYTE(dungmap_var7) + kWitch_DrawDataA[g * 2 + 1].x;
oam[1].y = HIBYTE(dungmap_var7) + kWitch_DrawDataA[g * 2 + 1].y;
WORD(oam[1].charnum) = WORD(info.r4) | WORD(kWitch_DrawDataA[g * 2+1].charnum);
for (int i = 0; i < 3; i++) {
oam[i+2].x = BYTE(dungmap_var7) + kWitch_DrawDataB[i].x;
oam[i+2].y = HIBYTE(dungmap_var7) + kWitch_DrawDataB[i].y;
WORD(oam[i+2].charnum) = WORD(info.r4) ^ WORD(kWitch_DrawDataB[i].charnum);
}
int i = (uint16)(g - 3) < 3;
oam[5].x = BYTE(dungmap_var7) + kWitch_DrawDataC[i].x;
oam[5].y = HIBYTE(dungmap_var7) + kWitch_DrawDataC[i].y;
WORD(oam[5].charnum) = WORD(info.r4) | WORD(kWitch_DrawDataC[i].charnum);
int e = oam - oam_buf;
WORD(bytewise_extended_oam[e]) = 0;
WORD(bytewise_extended_oam[e+2]) = 0x202;
WORD(bytewise_extended_oam[e+4]) = 0x202;
Sprite_CorrectOamEntries(k, 5, 0xff);
}
void SpritePrep_Snitches(int k) { // 85e67d
sprite_D[k] = 2;
sprite_head_dir[k] = 2;
sprite_ignore_projectile[k]++;
sprite_A[k] = sprite_x_lo[k];
sprite_B[k] = sprite_x_hi[k];
sprite_x_vel[k] = -9;
}
void Sprite_OldSnitchLady(int k) { // 85e6aa
static const int8 kOldSnitchLady_Xd[2] = {-32, 32};
static const int8 kOldSnitchLady_Xvel[4] = {0, 0, -9, 9};
static const int8 kOldSnitchLady_Yvel[4] = {-9, 9, 0, 0};
int j;
if (sprite_type[k] == 0x34) {
if (sprite_ai_state[k] < 2)
YoungSnitchLady_Draw(k);
} else {
if (sprite_subtype[k]) {
Sprite_ChickenLady(k);
return;
}
if (sprite_ai_state[k] < 3)
Lady_Draw(k);
}
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_ai_state[k] < 3) {
if (player_is_indoors) {
Sprite_TrackBodyToHead(k);
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
Sprite_ShowSolicitedMessage(k, 0xad);
return;
}
if (!sprite_ai_state[k] && Sprite_CheckDamageToLink_same_layer(k)) {
sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
sprite_delay_main[k] = 1;
} else {
if (Sprite_TrackBodyToHead(k))
Sprite_MoveXY(k);
else
sprite_delay_main[k] = 1;
}
}
switch (sprite_ai_state[k]) {
case 0: {
if (sprite_delay_main[k] == 0) {
uint16 t = (sprite_A[k] | sprite_B[k] << 8) + kOldSnitchLady_Xd[sprite_C[k]];
if (t == Sprite_GetX(k)) {
sprite_head_dir[k] = (j = sprite_D[k] ^ 1);
sprite_x_vel[k] = kOldSnitchLady_Xvel[j];
sprite_y_vel[k] = kOldSnitchLady_Yvel[j];
sprite_C[k] ^= 1;
}
}
sprite_graphics[k] = (k ^ frame_counter) >> 4 & 1;
uint8 bak0 = sprite_flags4[k];
sprite_flags4[k] = 3;
j = Sprite_ShowMessageOnContact(k, 0x2f);
sprite_flags4[k] = bak0;
if (j & 0x100) {
sprite_D[k] = j;
Snitch_SpawnGuard(k);
sprite_ai_state[k] = 1;
}
break;
}
case 1: {
uint16 ovx = overlord_x_lo[byte_7E0FDE] | overlord_x_hi[byte_7E0FDE] << 8;
uint16 ovy = overlord_y_lo[byte_7E0FDE] | overlord_y_hi[byte_7E0FDE] << 8;
if (ovy >= Sprite_GetY(k)) {
sprite_ai_state[k] = 2;
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
sprite_flags4[k] = 2;
uint16 pos = ((ovy - overworld_offset_base_y) & overworld_offset_mask_y) * 8;
pos += (((ovx >> 3) - overworld_offset_base_x) & overworld_offset_mask_x);
Overworld_DrawWoodenDoor(pos, false);
sprite_delay_main[k] = 16;
} else {
flag_is_link_immobilized = 1;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, ovx, ovy, 64);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
sprite_D[k] = 0;
sprite_head_dir[k] = 0;
sprite_graphics[k] = (k ^ frame_counter) >> 3 & 1;
}
break;
}
case 2:
if (sprite_delay_main[k] == 0) {
uint16 ovx = overlord_x_lo[byte_7E0FDE] | overlord_x_hi[byte_7E0FDE] << 8;
uint16 ovy = overlord_y_lo[byte_7E0FDE] | overlord_y_hi[byte_7E0FDE] << 8;
Sprite_SetX(k, ovx);
Sprite_SetY(k, ovy);
uint16 pos = ((ovy - overworld_offset_base_y) & overworld_offset_mask_y) * 8;
pos += (((ovx >> 3) - overworld_offset_base_x) & overworld_offset_mask_x);
Overworld_DrawWoodenDoor(pos, true);
sprite_ai_state[k] = 3;
}
Sprite_MoveXY(k);
break;
case 3:
sprite_state[k] = 0;
flag_is_link_immobilized = 0;
break;
}
}
void SpritePrep_RunningMan(int k) { // 85e896
sprite_head_dir[k] = 2;
sprite_D[k] = 2;
sprite_ignore_projectile[k]++;
}
void Sprite_RunningMan(int k) { // 85e8b2
static const int8 kRunningMan_Xvel2[2] = {-24, 24};
static const int8 kRunningMan_Xvel[4] = {0, 0, -54, 54};
static const int8 kRunningMan_Yvel[4] = {-54, 54, 0, 0};
static const int8 kRunningMan_Dir[4] = {3, 1, 3, -1};
static const uint8 kRunningMan_A[4] = {120, 24, 128, 3};
int j;
RunningMan_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_TrackBodyToHead(k);
Sprite_BehaveAsBarrier(k);
sprite_subtype[k] = 255;
Sprite_CheckTileCollision(k);
uint8 bak0 = sprite_flags4[k];
sprite_flags4[k] = 7;
if (Sprite_CheckDamageToLink_same_layer(k)) {
sprite_C[k] = sprite_ai_state[k];
sprite_ai_state[k] = 3;
}
sprite_flags4[k] = bak0;
switch (sprite_ai_state[k]) {
case 0: // chill
Sprite_TrackBodyToHead(k);
j = Sprite_DirectionToFaceLink(k, NULL);
sprite_head_dir[k] = j ^ 3;
if (Sprite_CheckDamageToLink_same_layer(k)) {
Link_CancelDash();
sprite_D[k] = j ^ 3;
sprite_head_dir[k] = j | 2;
sprite_ai_state[k] = (j & 1) + 1;
sprite_x_vel[k] = kRunningMan_Xvel2[j & 1];
sprite_delay_main[k] = 32;
} else {
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
}
break;
case 1: // run left
case 2: // run right
if (sprite_delay_main[k] != 0) {
sprite_graphics[k] = frame_counter >> 3 & 1;
Sprite_MoveXY(k);
} else {
RunningBoy_SpawnDustGarnish(k);
sprite_graphics[k] = frame_counter >> 2 & 1;
j = sprite_head_dir[k];
sprite_x_vel[k] = kRunningMan_Xvel[j];
sprite_y_vel[k] = kRunningMan_Yvel[j];
Sprite_MoveXY(k);
if (sprite_A[k]) {
sprite_A[k]--;
break;
}
if (sprite_ai_state[k] == 1) { // left
sprite_A[k] = 255;
sprite_head_dir[k] = 2;
} else {
j = sprite_B[k]++;
sprite_A[k] = kRunningMan_A[j];
if (kRunningMan_Dir[j] < 0) {
sprite_ai_state[k] = 0;
sprite_subtype2[k] = 0;
} else {
sprite_head_dir[k] = kRunningMan_Dir[j];
}
}
}
break;
case 3: // caught
Sprite_ShowMessageUnconditional(0xa6);
if (link_player_handler_state >= kPlayerState_RecoilWall) // wtf
sprite_D[k] = link_player_handler_state;
sprite_ai_state[k] = sprite_C[k];
break;
}
}
void RunningMan_Draw(int k) { // 85ea4d
static const DrawMultipleData kRunningMan_Dmd[16] = {
{0, -8, 0x002c, 2},
{0, 0, 0x08ee, 2},
{0, -7, 0x002c, 2},
{0, 1, 0x48ee, 2},
{0, -8, 0x002a, 2},
{0, 0, 0x08ca, 2},
{0, -7, 0x002a, 2},
{0, 1, 0x48ca, 2},
{0, -8, 0x002e, 2},
{0, 0, 0x08cc, 2},
{0, -7, 0x002e, 2},
{0, 1, 0x08ce, 2},
{0, -8, 0x402e, 2},
{0, 0, 0x48cc, 2},
{0, -7, 0x402e, 2},
{0, 1, 0x48ce, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kRunningMan_Dmd[(sprite_D[k] * 4 + sprite_graphics[k] * 2) & 0xf], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_BottleVendor(int k) { // 85ea79
int j;
sprite_A[k] = BottleVendor_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
BottleMerchant_DetectFish(k);
Sprite_BehaveAsBarrier(k);
if (Sprite_CheckIfLinkIsBusy())
return;
if (GetRandomNumber() == 0) {
sprite_delay_main[k] = 20;
sprite_graphics[k] = 1;
} else if (!sprite_delay_main[k]) {
sprite_graphics[k] = 0;
}
switch (sprite_ai_state[k]) {
case 0: // base
if (!sprite_A[k] && sprite_E[k])
sprite_ai_state[k] = 3;
else if (sram_progress_indicator_3 & 2)
Sprite_ShowSolicitedMessage(k, 0xd4);
else if (Sprite_ShowSolicitedMessage(k, 0xd1) & 0x100)
sprite_ai_state[k] = 1;
break;
case 1: // selling
if (choice_in_multiselect_box == 0 && link_rupees_goal >= 100) {
Sprite_ShowMessageUnconditional(0xd2);
sprite_ai_state[k] = 2;
} else {
Sprite_ShowMessageUnconditional(0xd3);
sprite_ai_state[k] = 0;
}
break;
case 2: // giving
item_receipt_method = 0;
Link_ReceiveItem(0x16, 0);
sram_progress_indicator_3 |= 2;
link_rupees_goal -= 100;
sprite_ai_state[k] = 0;
break;
case 3: // buying
if (!sign8(sprite_E[k]))
Sprite_ShowMessageUnconditional(0xd5);
else
Sprite_ShowMessageUnconditional(0xd6);
sprite_ai_state[k] = 4;
break;
case 4: // reward
j = sprite_E[k];
if (!sign8(j)) {
sprite_state[j - 1] = 0;
BottleMerchant_BuyBee(k);
} else {
sprite_state[j & 0xf] = 0;
BottleMerchant_BuyFish(k);
}
sprite_E[k] = 0;
sprite_ai_state[k] = 0;
break;
}
}
uint8 BottleVendor_Draw(int k) { // 85eba7
PrepOamCoordsRet info;
static const DrawMultipleData kBottleVendor_Dmd[4] = {
{0, -7, 0x00ac, 2},
{0, 0, 0x0088, 2},
{0, -6, 0x00ac, 2},
{0, 0, 0x00a2, 2},
};
Sprite_DrawMultiplePlayerDeferred(k, &kBottleVendor_Dmd[sprite_graphics[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
return (info.x | info.y) >> 8;
}
void Priest_SpawnRescuedPrincess() { // 85ec4c
SpriteSpawnInfo info;
int k = Sprite_SpawnDynamically(0, 0x76, &info);
if (k < 0)
return;
sprite_D[k] = sprite_head_dir[k] = tagalong_layerbits[tagalong_var2] & 3;
Sprite_SetX(k, link_x_coord);
Sprite_SetY(k, link_y_coord);
sprite_subtype2[k] = 1;
follower_indicator = 0;
sprite_ignore_projectile[k]++;
sprite_flags4[k] = 3;
}
void Sprite_76_Zelda(int k) { // 85ec9e
CrystalMaiden_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (Sprite_TrackBodyToHead(k))
Sprite_MoveXY(k);
switch (sprite_subtype2[k]) {
case 0: Zelda_InCell(k); break;
case 1: Zelda_EnteringSanctuary(k); break;
case 2: Zelda_AtSanctuary(k); break;
}
}
void Zelda_InCell(int k) { // 85ecbf
int j;
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
switch (sprite_ai_state[k]) {
case 0: // AwaitingRescue
if (!Sprite_CheckDamageToLink_same_layer(k))
return;
sprite_ai_state[k]++;
flag_is_link_immobilized++;
j = sprite_head_dir[k];
sprite_x_vel[k] = kZelda_Xvel[j];
sprite_y_vel[k] = kZelda_Yvel[j];
sprite_delay_main[k] = 16;
break;
case 1: // ApproachingPlayer
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
Sprite_ShowMessageUnconditional(0x1c);
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
music_control = 25;
}
sprite_graphics[k] = frame_counter >> 3 & 1;
break;
case 2: // TheWizardIsBadMkay
sprite_ai_state[k]++;
Sprite_ShowMessageUnconditional(0x25);
break;
case 3: // WaitUntilPlayerPaysAttention
if (choice_in_multiselect_box) {
sprite_ai_state[k] = 2;
} else {
sprite_ai_state[k]++;
Sprite_ShowMessageUnconditional(0x24);
}
break;
case 4: // TransitionToTagalong
flag_is_link_immobilized = 0;
which_starting_point = 2;
SavePalaceDeaths();
follower_indicator = 1;
Dungeon_FlagRoomData_Quadrants();
Sprite_BecomeFollower(k);
sprite_state[k] = 0;
music_control = 16;
break;
}
}
void Zelda_EnteringSanctuary(int k) { // 85ed69
static const uint8 kZelda_Delay0[4] = {38, 26, 44, 1};
static const uint8 kZelda_Dir0[4] = {1, 3, 1, 2};
int j;
switch (sprite_ai_state[k]) {
case 0: // walk to priest
if (sprite_delay_main[k] == 0) {
j = sprite_A[k];
if (j >= 4) {
sprite_ai_state[k]++;
sprite_head_dir[k] = sprite_D[k] = 0;
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
return;
}
sprite_delay_main[k] = kZelda_Delay0[j];
sprite_D[k] = sprite_head_dir[k] = j = kZelda_Dir0[j];
sprite_A[k]++;
sprite_x_vel[k] = kZelda_Xvel[j];
sprite_y_vel[k] = kZelda_Yvel[j];
}
sprite_graphics[k] = (frame_counter >> 3) & 1;
break;
case 1: // respond to priest
Sprite_ShowMessageUnconditional(0x1d);
sprite_ai_state[k]++;
byte_7FFE01 = 2;
which_starting_point = 1;
SavePalaceDeaths();
sram_progress_indicator = 2;
Sprite_LoadGraphicsProperties_light_world_only();
break;
case 2: // be careful
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
j = Sprite_ShowSolicitedMessage(k, 0x1e);
if (j & 0x100)
sprite_D[k] = sprite_head_dir[k] = (uint8)j;
break;
}
}
void Zelda_AtSanctuary(int k) { // 85ee0c
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
int m = (link_which_pendants & 7) == 7 ? 0x27 :
savegame_map_icons_indicator >= 3 ? 0x26 : 0x1e;
int j = Sprite_ShowSolicitedMessage(k, m);
if (j & 0x100) {
sprite_D[k] = sprite_head_dir[k] = (uint8)j;
link_hearts_filler = 0xa0;
}
}
void SpritePrep_Mushroom(int k) { // 85ee53
if (link_item_mushroom >= 2) {
sprite_state[k] = 0;
} else {
sprite_graphics[k] = 0;
sprite_oam_flags[k] |= 8;
sprite_ignore_projectile[k]++;
}
}
void Sprite_Mushroom(int k) { // 85ee78
SpriteDraw_SingleLarge(k);
if (Sprite_CheckIfLinkIsBusy())
return;
// If we're in the middle of a mirror warp, don't get the mushroom yet
if (enhanced_features0 & kFeatures0_MiscBugFixes && submodule_index != 0)
return;
if (Sprite_CheckDamageToLink_same_layer(k)) {
sprite_state[k] = 0;
item_receipt_method = 0;
Link_ReceiveItem(0x29, 0);
} else if ((frame_counter & 0x1f) == 0) {
sprite_oam_flags[k] ^= 0x40;
}
}
void Sprite_FakeSword(int k) { // 85eeaf
FakeSword_Draw(k);
if (Sprite_ReturnIfPaused(k))
return;
if (sprite_unk3[k] == 3) {
if (!sprite_C[k]) {
sprite_C[k] = 1;
Sprite_ShowMessageUnconditional(0x6f);
}
} else {
Sprite_MoveXY(k);
ThrownSprite_TileAndSpriteInteraction(k);
}
}
void FakeSword_Draw(int k) { // 85eee6
Sprite_DrawMultiplePlayerDeferred(k, kFakeSword_Dmd, 2, NULL);
}
void SpritePrep_HeartContainer(int k) { // 85ef01
HeartUpgrade_CheckIfAlreadyObtained(k);
}
void Sprite_HeartContainer(int k) { // 85ef47
if (BYTE(cur_palace_index_x2) == 26) {
sprite_state[k] = 0;
return;
}
sprite_ignore_projectile[k] = sprite_G[k];
if (!sprite_G[k]) {
DecodeAnimatedSpriteTile_variable(3);
Sprite_Get16BitCoords(k);
sprite_G[k] = 1;
}
if (BYTE(dungeon_room_index2) == 6 && !sprite_z[k])
SpriteDraw_WaterRipple_WithOamAdjust(k);
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_z_vel[k] -= 2;
Sprite_MoveZ(k);
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = (uint8)-sprite_z_vel[k] >> 2;
if (BYTE(dungeon_room_index2) == 6 && !sprite_subtype[k]) {
sprite_flags2[k] += 2;
sprite_subtype[k] = 1;
Sprite_SpawnWaterSplash(k);
}
}
if (Sprite_CheckIfLinkIsBusy())
return;
if (!Sprite_CheckDamageToLink_same_layer(k))
return;
sprite_state[k] = 0;
if (sprite_A[k]) {
item_receipt_method = 2;
Link_ReceiveItem(0x3e, 0);
dung_savegame_state_bits |= 0x8000;
return;
}
Link_CancelDash();
item_receipt_method = 0;
Link_ReceiveItem(0x26, 0);
if (!player_is_indoors)
save_ow_event_info[BYTE(overworld_screen_index)] |= 0x40;
else
dung_savegame_state_bits |= (sprite_x_hi[k] & 1) ? 0x2000 : 0x4000;
}
void Sprite_HeartPiece(int k) { // 85f020
static const uint16 kHeartPieceMsg[4] = {0x158, 0x155, 0x156, 0x157};
if (!sprite_ai_state[k]) {
sprite_ai_state[k]++;
HeartUpgrade_CheckIfAlreadyObtained(k);
if (!sprite_state[k])
return;
}
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckIfLinkIsBusy())
return;
if (Sprite_CheckTileCollision(k) & 3)
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_z_vel[k]--;
Sprite_MoveZ(k);
Sprite_MoveXY(k);
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = ((sprite_z_vel[k] ^ 255) & 248) >> 1;
sprite_x_vel[k] = (int8)sprite_x_vel[k] >> 1;
}
if (sprite_delay_aux4[k] || !Sprite_CheckDamageToLink_same_layer(k))
return;
link_heart_pieces = link_heart_pieces + 1 & 3;
if (link_heart_pieces == 0) {
Link_CancelDash();
item_receipt_method = 0;
Link_ReceiveItem(0x26, 0);
} else {
SpriteSfx_QueueSfx3WithPan(k, 0x2d);
Sprite_ShowMessageUnconditional(kHeartPieceMsg[link_heart_pieces]);
}
sprite_state[k] = 0;
HeartUpgrade_SetObtainedFlag(k);
}
void HeartUpgrade_SetObtainedFlag(int k) { // 85f0c3
if (!player_is_indoors) {
save_ow_event_info[BYTE(overworld_screen_index)] |= 0x40;
} else {
int j = sprite_x_hi[k] & 1;
dung_savegame_state_bits |= (j ? 0x2000 : 0x4000);
}
}
void Sprite_Aginah(int k) { // 85f0ea
if (!(sram_progress_flags & 0x20))
goto default_msg;
if (link_sword_type >= 2) {
Sprite_ShowSolicitedMessage(k, 0x128);
} else if ((link_which_pendants & 7) == 7) {
Sprite_ShowSolicitedMessage(k, 0x126);
} else if ((link_which_pendants & 2) != 0) {
Sprite_ShowSolicitedMessage(k, 0x129);
} else if (link_item_book_of_mudora) {
Sprite_ShowSolicitedMessage(k, 0x127);
} else {
default_msg:
sram_progress_flags |= 0x20;
Sprite_ShowSolicitedMessage(k, 0x125);
}
sprite_graphics[k] = frame_counter >> 5 & 1;
}
void Sprite_Sahasrahla(int k) { // 85f14d
switch (sprite_ai_state[k]) {
case 0: // dialogue
Sasha_Idle(k);
break;
case 1: // mark map
Sprite_ShowMessageUnconditional(0x33);
sprite_ai_state[k] = 0;
savegame_map_icons_indicator = 3;
break;
case 2: // grant boots
item_receipt_method = 0;
Link_ReceiveItem(0x4b, 0);
sprite_ai_state[k] = 3;
savegame_map_icons_indicator = 3;
break;
case 3: // shamelessly promote ice rod
Sprite_ShowMessageUnconditional(0x37);
sprite_ai_state[k] = 0;
break;
}
}
void Sasha_Idle(int k) { // 85f160
if (!(link_which_pendants & 4)) {
if (Sprite_ShowSolicitedMessage(k, 0x32) & 0x100)
sprite_ai_state[k] = 1;
} else if (!link_item_boots) {
int m = (savegame_map_icons_indicator >= 3) ? 0x38 : 0x39;
if (Sprite_ShowSolicitedMessage(k, m) & 0x100)
sprite_ai_state[k] = 2;
} else if (!link_item_ice_rod) {
Sprite_ShowSolicitedMessage(k, 0x37);
} else if ((link_which_pendants & 7) != 7) {
Sprite_ShowSolicitedMessage(k, 0x34);
} else if (link_sword_type < 2) {
Sprite_ShowSolicitedMessage(k, 0x30);
} else {
Sprite_ShowSolicitedMessage(k, 0x31);
}
sprite_graphics[k] = frame_counter >> 5 & 1;
}
void Elder_Draw(int k) { // 85f23a
static const DrawMultipleData kElder_Dmd[4] = {
{0, -9, 0x00a0, 2},
{0, 0, 0x00a2, 2},
{0, -8, 0x00a0, 2},
{0, 0, 0x40a4, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kElder_Dmd[sprite_graphics[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_DustCloud(int k) { // 85f2b2
static const uint8 kDustCloud_Gfx[9] = {0, 1, 2, 3, 4, 5, 1, 0, 0xff};
DustCloud_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_delay_main[k])
return;
sprite_delay_main[k] = 5;
if (!sign8(kDustCloud_Gfx[sprite_A[k]])) {
sprite_graphics[k] = kDustCloud_Gfx[sprite_A[k]];
sprite_A[k]++;
} else {
sprite_state[k] = 0;
}
}
int Sprite_SpawnDustCloud(int k) { // 85f2d6
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xF2, &info);
if (j >= 0) {
info.r2_y += (GetRandomNumber() & 15);
info.r0_x += (GetRandomNumber() & 15) - 8;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_subtype2[j] = 1;
}
return j;
}
void MedallionTablet_Main(int k) { // 85f30c
MedallionTablet_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
link_position_mode &= ~0x20;
sprite_A[k] = 0;
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Sprite_RepelDash();
sprite_A[k]++;
}
if (Sprite_CheckIfLinkIsBusy())
return;
switch (sprite_ai_state[k]) {
case 0: // wait for mudora
if (BYTE(overworld_screen_index) != 3)
BombosTablet(k);
else
EtherTablet(k);
break;
case 1: // delay
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 128;
}
break;
case 2: // crumbling
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 240;
} else {
if (sprite_delay_main[k] == 0x20 || sprite_delay_main[k] == 0x40 || sprite_delay_main[k] == 0x60)
sprite_graphics[k]++;
if (!(frame_counter & 7))
Sprite_SpawnDustCloud(k);
}
break;
case 3: // final animstate
sprite_graphics[k] = 4;
break;
}
}
void BombosTablet(int k) { // 85f355
static const uint16 kMedallionTabletMsg[2] = {0x10d, 0x10f};
if (link_direction_facing || Sprite_DirectionToFaceLink(k, NULL) != 2)
return;
if ((uint16)(cur_sprite_y + 16) < link_y_coord)
return;
if (filtered_joypad_H & 0x80 && link_sword_type == 2)
return;
int j = 1;
if (!(hud_cur_item == kHudItem_BookMudora && (filtered_joypad_H & 0x40)) && (j = 0, !(filtered_joypad_L & 0x80)))
return;
if (j) {
player_handler_timer = 0;
link_position_mode = 32;
sound_effect_1 = 0;
if (!sign8(link_sword_type) && link_sword_type >= 2) {
sprite_ai_state[k]++;
BombosTablet_StartCutscene();
sprite_delay_main[k] = 64;
}
}
Sprite_ShowMessageUnconditional(kMedallionTabletMsg[j]);
}
void EtherTablet(int k) { // 85f3c4
static const uint16 kMedallionTabletEtherMsg[2] = {0x10d, 0x10e};
if (link_direction_facing || Sprite_DirectionToFaceLink(k, NULL) != 2)
return;
if ((uint8)(sprite_y_lo[k] + 16) < BYTE(link_y_coord))
return;
if (filtered_joypad_H & 0x80 && link_sword_type == 2)
return;
int j = 1;
if (!(hud_cur_item == kHudItem_BookMudora && (filtered_joypad_H & 0x40)) && (j = 0, !(filtered_joypad_L & 0x80)))
return;
if (j) {
player_handler_timer = 0;
link_position_mode = 32;
sound_effect_1 = 0;
if (!sign8(link_sword_type) && link_sword_type >= 2) {
sprite_ai_state[k]++;
EtherTablet_StartCutscene();
sprite_delay_main[k] = 64;
}
}
Sprite_ShowMessageUnconditional(kMedallionTabletEtherMsg[j]);
}
void ElderWife_Draw(int k) { // 85f505
static const DrawMultipleData kElderWife_Dmd[4] = {
{0, -5, 0x008e, 2},
{0, 5, 0x0028, 2},
{0, -4, 0x008e, 2},
{0, 5, 0x4028, 2},
};
Sprite_DrawMultiplePlayerDeferred(k, &kElderWife_Dmd[sprite_graphics[k] * 2], 2, NULL);
}
void SpritePrep_PotionShop(int k) { // 85f529
MagicShopAssistant_SpawnPowder(k);
MagicShopAssistant_SpawnGreenCauldron(k);
MagicShopAssistant_SpawnBlueCauldron(k);
MagicShopAssistant_SpawnRedCauldron(k);
sprite_ignore_projectile[k]++;
}
void MagicShopAssistant_SpawnPowder(int k) { // 85f539
if (!flag_overworld_area_did_change || link_item_mushroom == 2)
return;
if (save_dung_info[0x109] & 0x80) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xe9, &info);
sprite_subtype2[j] = 1;
Sprite_SetX(j, info.r0_x - 16);
Sprite_SetY(j, info.r2_y);
sprite_flags4[j] = 3;
sprite_defl_bits[j] |= 0x20;
}
}
void MagicShopAssistant_SpawnGreenCauldron(int k) { // 85f58e
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xe9, &info);
sprite_subtype2[j] = 2;
Sprite_SetX(j, info.r0_x - 40);
Sprite_SetY(j, info.r2_y - 72);
sprite_flags4[j] = 3;
sprite_defl_bits[j] |= 0x20;
}
void MagicShopAssistant_SpawnBlueCauldron(int k) { // 85f5bf
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xe9, &info);
sprite_subtype2[j] = 3;
Sprite_SetX(j, info.r0_x + 8);
Sprite_SetY(j, info.r2_y - 72);
sprite_flags4[j] = 3;
sprite_defl_bits[j] |= 0x20;
}
void MagicShopAssistant_SpawnRedCauldron(int k) { // 85f5f0
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xe9, &info);
sprite_subtype2[j] = 4;
Sprite_SetX(j, info.r0_x - 88);
Sprite_SetY(j, info.r2_y - 72);
sprite_flags4[j] = 3;
sprite_defl_bits[j] |= 0x20;
}
void Sprite_PotionShop(int k) { // 85f633
switch(sprite_subtype2[k]) {
case 0: Sprite_MagicShopAssistant_Main(k); return;
case 1: Sprite_BagOfPowder(k); return;
case 2: Sprite_GreenCauldron(k); return;
case 3: Sprite_BlueCauldron(k); return;
case 4: Sprite_RedCauldron(k); return;
}
}
void Sprite_BagOfPowder(int k) { // 85f644
MagicPowderItem_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (!Sprite_CheckDamageToLink_same_layer(k) || !(filtered_joypad_L & 0x80))
return;
Link_CancelDash();
item_receipt_method = 0;
Link_ReceiveItem(0xd, 0);
sprite_state[k] = 0;
}
void MagicPowderItem_Draw(int k) { // 85f67b
static const DrawMultipleData kMagicPowder_Dmd[2] = {
{0, 0, 0x04e6, 2},
{0, 0, 0x04e6, 2},
};
Sprite_DrawMultiplePlayerDeferred(k, kMagicPowder_Dmd, 2, NULL);
}
void Sprite_GreenCauldron(int k) { // 85f68e
GreenPotionItem_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (sprite_delay_main[k])
return;
if (!PotionCauldron_CheckBottles()) {
if (Sprite_ShowMessageOnContact(k, 0x4f) & 0x100)
PotionCauldron_GoBeep(k);
return;
}
if (!Sprite_CheckDamageToLink_same_layer(k) || !(filtered_joypad_L & 0x80))
return;
if (link_rupees_goal < 60) {
Sprite_ShowMessageUnconditional(0x17c);
PotionCauldron_GoBeep(k);
return;
}
if (Sprite_Find_EmptyBottle() < 0) {
Sprite_ShowMessageUnconditional(0x50);
PotionCauldron_GoBeep(k);
return;
}
SpriteSfx_QueueSfx3WithPan(k, 0x1d);
sprite_delay_main[k] = 64;
link_rupees_goal -= 60;
item_receipt_method = 0;
Link_ReceiveItem(0x2f, 0);
}
void GreenPotionItem_Draw(int k) { // 85f718
static const DrawMultipleData kGreenPotionItem_Dmd[3] = {
{ 0, 0, 0x08c0, 2},
{ 8, 18, 0x0a30, 0},
{-1, 18, 0x0a22, 0},
};
Sprite_DrawMultiplePlayerDeferred(k, kGreenPotionItem_Dmd, 3, NULL);
}
void Sprite_BlueCauldron(int k) { // 85f72b
BluePotionItem_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (sprite_delay_main[k])
return;
if (!PotionCauldron_CheckBottles()) {
if (Sprite_ShowMessageOnContact(k, 0x4f) & 0x100)
PotionCauldron_GoBeep(k);
return;
}
if (!Sprite_CheckDamageToLink_same_layer(k) || !(filtered_joypad_L & 0x80))
return;
if (link_rupees_goal < 160) {
Sprite_ShowMessageUnconditional(0x17c);
PotionCauldron_GoBeep(k);
return;
}
if (Sprite_Find_EmptyBottle() < 0) {
Sprite_ShowMessageUnconditional(0x50);
PotionCauldron_GoBeep(k);
return;
}
SpriteSfx_QueueSfx3WithPan(k, 0x1d);
sprite_delay_main[k] = 64;
link_rupees_goal -= 160;
item_receipt_method = 0;
Link_ReceiveItem(0x30, 0);
}
void BluePotionItem_Draw(int k) { // 85f7bd
static const DrawMultipleData kBluePotionItem_Dmd[4] = {
{ 0, 0, 0x04c0, 2},
{13, 18, 0x0a30, 0},
{ 5, 18, 0x0a22, 0},
{-3, 18, 0x0a31, 0},
};
Sprite_DrawMultiplePlayerDeferred(k, kBluePotionItem_Dmd, 4, NULL);
}
void Sprite_RedCauldron(int k) { // 85f7d0
RedPotionItem_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (sprite_delay_main[k])
return;
if (!PotionCauldron_CheckBottles()) {
if (Sprite_ShowMessageOnContact(k, 0x4f) & 0x100)
PotionCauldron_GoBeep(k);
return;
}
if (!Sprite_CheckDamageToLink_same_layer(k) || !(filtered_joypad_L & 0x80))
return;
if (link_rupees_goal < 120) {
Sprite_ShowMessageUnconditional(0x17c);
PotionCauldron_GoBeep(k);
return;
}
if (Sprite_Find_EmptyBottle() < 0) {
Sprite_ShowMessageUnconditional(0x50);
PotionCauldron_GoBeep(k);
return;
}
SpriteSfx_QueueSfx3WithPan(k, 0x1d);
sprite_delay_main[k] = 64;
link_rupees_goal -= 120;
item_receipt_method = 0;
Link_ReceiveItem(0x2e, 0);
}
void PotionCauldron_GoBeep(int k) { // 85f846
SpriteSfx_QueueSfx2WithPan(k, 0x3c);
}
void RedPotionItem_Draw(int k) { // 85f86d
static const DrawMultipleData kRedPotionItem_Dmd[4] = {
{ 0, 0, 0x02c0, 2},
{13, 18, 0x0a30, 0},
{ 5, 18, 0x0a02, 0},
{-3, 18, 0x0a31, 0},
};
Sprite_DrawMultiplePlayerDeferred(k, kRedPotionItem_Dmd, 4, NULL);
}
bool PotionCauldron_CheckBottles() { // 85f880
return (link_bottle_info[0] | link_bottle_info[1] | link_bottle_info[2] | link_bottle_info[3]) >= 2;
}
void Sprite_MagicShopAssistant_Main(int k) { // 85f893
Shopkeeper_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (Sprite_CheckIfLinkIsBusy())
return;
if (sprite_ai_state[k]) {
link_hearts_filler = 160;
sprite_ai_state[k] = 0;
}
sprite_graphics[k] = frame_counter >> 5 & 1;
int msg;
if (link_bottle_info[0] >= 2 || link_bottle_info[1] >= 2 || link_bottle_info[2] >= 2 || link_bottle_info[3] >= 2 || !flag_overworld_area_did_change)
msg = 0x4e;
else
msg = 0x4d;
if (Sprite_ShowSolicitedMessage(k, msg) & 0x100)
sprite_ai_state[k] = 1;
}
void Shopkeeper_Draw(int k) { // 85f91b
static const DrawMultipleData kShopkeeper_Dmd[4] = {
{0, -8, 0x0c00, 2},
{0, 0, 0x0c10, 2},
{0, -8, 0x0c00, 2},
{0, 0, 0x4c10, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kShopkeeper_Dmd[sprite_graphics[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_DashItem(int k) { // 85fbf7
switch (sprite_graphics[k]) {
case 0: Sprite_BookOfMudora(k); break;
case 1: Sprite_BonkKey(k); break;
case 2: Sprite_LumberjackTree(k); break;
}
}
void Sprite_BonkKey(int k) { // 85fc04
Sprite_DrawThinAndTall(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckDamageToLink_same_layer(k))
sprite_ai_state[k] = 3;
Sprite_MoveXY(k);
sprite_z_vel[k]--;
Sprite_MoveZ(k);
if (sign8(sprite_z[k])) {
sprite_y_vel[k] = 0;
sprite_z[k] = 0;
sprite_z_vel[k] = (uint8)-sprite_z_vel[k] >> 2;
if (sprite_z_vel[k] & 254)
SpriteSfx_QueueSfx3WithPan(k, 0x14);
}
switch (sprite_ai_state[k]) {
case 0: // wait for dash
if ((uint16)(cur_sprite_x - link_x_coord + 16) < 33 &&
(uint16)(cur_sprite_y - link_y_coord + 24) < 41 && (bg1_x_offset | bg1_y_offset))
sprite_ai_state[k] = 1;
break;
case 1: // being falling
sprite_z_vel[k] = 32;
sprite_y_vel[k] = -5;
sound_effect_2 = 27;
sprite_ai_state[k] = 2;
break;
case 2: // falling
if (!sprite_z[k])
sprite_floor[k] = link_is_on_lower_level;
break;
case 3: // give to player
link_num_keys++;
sprite_state[k] = 0;
dung_savegame_state_bits |= (sprite_die_action[k] ? 0x2000 : 0x4000);
SpriteSfx_QueueSfx3WithPan(k, 0x2f);
break;
}
}
void Sprite_BookOfMudora(int k) { // 85fc9e
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckDamageToLink_same_layer(k))
sprite_ai_state[k] = 3;
Sprite_MoveXY(k);
sprite_z_vel[k]--;
Sprite_MoveZ(k);
if (sign8(sprite_z[k])) {
sprite_y_vel[k] = 0;
sprite_z[k] = 0;
sprite_z_vel[k] = (uint8)-sprite_z_vel[k] >> 2;
if (sprite_z_vel[k] & 254)
SpriteSfx_QueueSfx2WithPan(k, 0x21);
}
switch (sprite_ai_state[k]) {
case 0: // wait for dash
if (link_direction_facing == 0 &&
(uint16)(cur_sprite_x - link_x_coord + 39) < 47 &&
(uint16)(cur_sprite_y - link_y_coord + 40) < 46 && (bg1_x_offset | bg1_y_offset))
sprite_ai_state[k] = 1;
break;
case 1: // being falling
sprite_z_vel[k] = 32;
sprite_y_vel[k] = -5;
sound_effect_2 = 27;
sprite_ai_state[k] = 2;
break;
case 2: // falling
if (!sprite_z[k])
sprite_floor[k] = link_is_on_lower_level;
break;
case 3: // give to player
Link_CancelDash();
item_receipt_method = 0;
Link_ReceiveItem(0x1d, 0);
sprite_state[k] = 0;
break;
}
}
void Sprite_LumberjackTree(int k) { // 85fd4d
sprite_flags2[k] = 0x8f;
sprite_flags4[k] = 0x47;
DashTreeTop_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Sprite_RepelDash();
}
Sprite_MoveXY(k);
sprite_z_vel[k]--;
Sprite_MoveZ(k);
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = (uint8)-sprite_z_vel[k] >> 2;
}
switch (sprite_ai_state[k]) {
case 0: // wait for dash
sprite_subtype2[k] = 0;
if ((uint16)(cur_sprite_x - link_x_coord + 24) < 65 &&
(uint16)(cur_sprite_y - link_y_coord + 32) < 81 && (bg1_x_offset | bg1_y_offset) & 0xff) {
sprite_z_vel[k] = 20;
sprite_ai_state[k] = 1;
}
break;
case 1: // spawn leaves
if (!sprite_z[k]) {
sprite_ai_state[k]++;
sound_effect_2 = 0x1b;
sprite_x_vel[k] = -4;
sprite_y_vel[k] = -4;
int j = LumberjackTree_SpawnLeaves(k);
sprite_x_vel[j] = 5;
sprite_y_vel[j] = 5;
j = LumberjackTree_SpawnLeaves(k);
sprite_x_vel[j] = 5;
sprite_y_vel[j] = -4;
j = LumberjackTree_SpawnLeaves(k);
sprite_x_vel[j] = -4;
sprite_y_vel[j] = 4;
}
break;
case 2: // dancing leaves
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 8;
if (sprite_subtype2[k] == 6)
sprite_state[k] = 0;
sprite_subtype2[k]++;
}
break;
}
}
void DashTreeTop_Draw(int k) { // 85fe6f
static const uint16 kDashTreeTop_CharFlags[16] = {0x3100, 0x3102, 0x7102, 0x7100, 0x3120, 0x3122, 0x7122, 0x7120, 0x3104, 0x3106, 0x7106, 0x7104, 0x3124, 0x3126, 0x7126, 0x7124};
static const int8 kDashTreeTop_X[16] = {10, 22, 30, 1, 34, 5, 13, 29, 0, 17, 27, 44, 15, 33, 18, 26};
static const int8 kDashTreeTop_Y[16] = {0, 4, 2, 7, 10, 16, 24, 23, 34, 35, 30, 31, 46, 42, 10, 11};
static const int8 kDashTreeTop_Char[6] = {8, 8, 0x28, 0x28, 0x2a, 0x2a};
static const int8 kDashTreeTop_Flags[6] = {0x31, 0x71, 0x31, 0x71, 0x31, 0x71};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
BYTE(dungmap_var7) -= 0x20;
HIBYTE(dungmap_var7) -= 0x20;
if (!sprite_subtype2[k]) {
uint8 x = BYTE(dungmap_var7);
uint8 y = HIBYTE(dungmap_var7);
for (int i = 0; i < 16; i++) {
oam[i].x = x + (i & 3) * 0x10;
oam[i].y = y + (i >> 2) * 0x10;
WORD(oam[i].charnum) = kDashTreeTop_CharFlags[i];
}
Sprite_CorrectOamEntries(k, 15, 2);
} else {
int j = sprite_subtype2[k] - 1;
for (int i = 15; i >= 0; i--, oam++) {
oam->x = BYTE(dungmap_var7) + kDashTreeTop_X[i];
oam->y = HIBYTE(dungmap_var7) + kDashTreeTop_Y[i];
oam->charnum = kDashTreeTop_Char[j];
oam->flags = kDashTreeTop_Flags[j];
}
Sprite_CorrectOamEntries(k, 15, 2);
}
}
int LumberjackTree_SpawnLeaves(int k) { // 85ff39
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x3B, &info);
assert(j >= 0);
sprite_graphics[j] = 2;
sprite_z_vel[j] = sprite_z_vel[k];
sprite_subtype2[j] = 1;
sprite_ai_state[j] = 2;
sprite_delay_main[j] = 8;
Sprite_SetSpawnedCoordinates(j, &info);
return j;
}
void Sprite_TroughBoy(int k) { // 85ff66
TroughBoy_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
Sprite_TrackBodyToHead(k);
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
if (savegame_map_icons_indicator < 3) {
if (Sprite_ShowSolicitedMessage(k, 0x147) & 0x100)
savegame_map_icons_indicator = 2;
} else {
Sprite_ShowSolicitedMessage(k, 0x148);
}
}
void TroughBoy_Draw(int k) { // 85ffdf
static const DrawMultipleData kTroughBoy_Dmd[8] = {
{0, -8, 0x0882, 2},
{0, 0, 0x0aaa, 2},
{0, -8, 0x0882, 2},
{0, 0, 0x0aaa, 2},
{0, -8, 0x4880, 2},
{0, 0, 0x0aaa, 2},
{0, -8, 0x0880, 2},
{0, 0, 0x0aaa, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kTroughBoy_Dmd[sprite_D[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void BottleMerchant_DetectFish(int k) { // 868000
for (int i = 15; i >= 0; i--) {
if (sprite_state[i] && sprite_type[i] == 0xd2) {
SpriteHitBox hb;
hb.r0_xlo = sprite_x_lo[k];
hb.r8_xhi = sprite_x_hi[k];
hb.r2 = 16;
hb.r1_ylo = sprite_y_lo[k];
hb.r9_yhi = sprite_y_hi[k];
hb.r3 = 16;
Sprite_SetupHitBox(i, &hb);
if (CheckIfHitBoxesOverlap(&hb))
sprite_E[k] = 0x80 | i;
return;
}
}
}
void BottleMerchant_BuyFish(int k) { // 868054
static const uint8 kBottleVendor_FishRewardType[5] = {0xdb, 0xe0, 0xde, 0xe2, 0xd9};
static const int8 kBottleVendor_FishRewardXv[5] = {-6, -3, 0, 4, 7};
static const int8 kBottleVendor_FishRewardYv[5] = {11, 14, 16, 14, 11};
SpriteSpawnInfo info;
SpriteSfx_QueueSfx3WithPan(k, 0x13);
tmp_counter = 4;
do {
int j = Sprite_SpawnDynamically(k, kBottleVendor_FishRewardType[tmp_counter], &info);
if (j < 0)
return;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_x_lo[j] = info.r0_x + 4;
sprite_stunned[j] = 0xff;
sprite_x_vel[j] = kBottleVendor_FishRewardXv[tmp_counter];
sprite_y_vel[j] = kBottleVendor_FishRewardYv[tmp_counter];
sprite_z_vel[j] = 32;
sprite_delay_aux4[j] = 32;
} while (!sign8(--tmp_counter));
}
void SpritePrep_ThrowableScenery(int k) { // 86850f
}
void SpriteModule_Initialize(int k) { // 86864d
SpritePrep_LoadProperties(k);
sprite_state[k]++;
kSpritePrep_Main[sprite_type[k]](k);
}
void SpritePrep_Mantle(int k) { // 868841
sprite_y_lo[k] += 3;
sprite_x_lo[k] += 8;
}
void SpritePrep_Switch(int k) { // 868859
int j = BYTE(dungeon_room_index2);
if (j == 0xce || j == 4 || j == 0x3f)
sprite_oam_flags[k] = 0xD;
}
void SpritePrep_SwitchFacingUp(int k) { // 86886d
}
void SpritePrep_Snitch_bounce_1(int k) { // 86886e
SpritePrep_Snitches(k);
}
void SpritePrep_DoNothingA(int k) { // 868873
}
void SpritePrep_Rat(int k) { // 868878
static const uint8 kSpriteRat_BumpDamage[2] = {0, 5};
static const uint8 kSpriteRat_Health[2] = {2, 8};
int j = is_in_dark_world;
sprite_bump_damage[k] = kSpriteRat_BumpDamage[j];
sprite_health[k] = kSpriteRat_Health[j];
}
void SpritePrep_Keese(int k) { // 86888e
static const uint8 kSpriteKeese_BumpDamage[2] = {0x80, 0x85};
static const uint8 kSpriteKeese_Health[2] = {1, 4};
static const uint8 kSpriteKeese_Flags5[2] = {0, 7};
int j = is_in_dark_world;
sprite_bump_damage[k] = kSpriteKeese_BumpDamage[j];
sprite_health[k] = kSpriteKeese_Health[j];
sprite_flags5[k] = kSpriteKeese_Flags5[j];
}
void SpritePrep_Rope(int k) { // 8688aa
static const uint8 kSpriteRope_BumpDamage[2] = {1, 5};
static const uint8 kSpriteRope_Health[2] = {4, 8};
static const uint8 kSpriteRope_Flags5[2] = {1, 7};
int j = is_in_dark_world;
sprite_bump_damage[k] = kSpriteRope_BumpDamage[j];
sprite_health[k] = kSpriteRope_Health[j];
sprite_flags5[k] = kSpriteRope_Flags5[j];
}
void SpritePrep_Swamola(int k) { // 8688c0
SpritePrep_Swamola_InitializeSegments(k);
SpritePrep_Kyameron(k);
}
void SpritePrep_Blind(int k) { // 8688c7
if (Sprite_ReturnIfBossFinished(k))
return;
SpritePrep_Blind_PrepareBattle(k);
}
void SpritePrep_Ganon(int k) { // 8688cf
if (Sprite_ReturnIfBossFinished(k))
return;
Ganon_HandleAnimation_Idle(k);
sprite_delay_main[k] = 128;
sprite_room[k] = 2;
music_control = 0x1e;
}
void SpritePrep_Pokey(int k) { // 8688df
static const int8 kHokbok_InitXvel[4] = {16, -16, 16, -16};
static const int8 kHokbok_InitYvel[4] = {16, 16, -16, -16};
sprite_A[k] = 3;
sprite_B[k] = 8;
int j = GetRandomNumber() & 3;
sprite_x_vel[k] = kHokbok_InitXvel[j];
sprite_y_vel[k] = kHokbok_InitYvel[j];
}
void SpritePrep_MiniVitreous(int k) { // 8688fd
Sprite_ReturnIfBossFinished(k);
}
void SpritePrep_Gibo(int k) { // 868901
sprite_z[k] = 16;
sprite_G[k] = 8;
}
void SpritePrep_Octoballoon(int k) { // 868910
static const uint8 kSprite_Octoballoon_Delay[4] = {192, 208, 224, 240};
sprite_delay_main[k] = kSprite_Octoballoon_Delay[k & 3];
}
void SpritePrep_AgahnimsBarrier(int k) { // 86891b
if (save_ow_event_info[BYTE(overworld_screen_index)] & 0x40)
sprite_graphics[k] = 4;
SpritePrep_MoveDown_8px_Right8px(k);
sprite_y_lo[k] -= 12;
sprite_ignore_projectile[k]++;
}
void SpritePrep_Catfish(int k) { // 86892c
SpritePrep_MoveDown_8px_Right8px(k);
sprite_y_lo[k] -= 12;
SpritePrep_IgnoreProjectiles(k);
}
void SpritePrep_CutsceneAgahnim(int k) { // 86893b
if (dung_savegame_state_bits & 0x4000) {
sprite_state[k] = 0;
} else {
CutsceneAgahnim_SpawnZeldaOnAltar(k);
sprite_ignore_projectile[k]++;
}
}
void SpritePrep_Vitreous(int k) { // 86894d
if (Sprite_ReturnIfBossFinished(k))
return;
SpritePrep_MoveDown_8px_Right8px(k);
sprite_y_lo[k] -= 16;
Vitreous_SpawnSmallerEyes(k);
sprite_ignore_projectile[k]++;
}
void SpritePrep_Raven(int k) { // 868969
static const uint8 kSpriteRaven_BumpDamage[2] = {0x81, 0x88};
static const uint8 kSpriteRaven_Health[2] = {4, 8};
static const uint8 kSpriteRaven_Flags5[2] = {6, 2};
int j = is_in_dark_world;
sprite_bump_damage[k] = kSpriteRaven_BumpDamage[j];
sprite_health[k] = kSpriteRaven_Health[j];
sprite_flags5[k] = kSpriteRaven_Flags5[j];
sprite_z[k] = 0;
sprite_A[k] = (sprite_x_lo[k] & 16) >> 4;
sprite_subtype[k] = 254;
}
void SpritePrep_Vulture(int k) { // 86897e
sprite_z[k] = 0;
sprite_A[k] = (sprite_x_lo[k] & 16) >> 4;
sprite_subtype[k] = 254;
}
void SpritePrep_Poe(int k) { // 868991
sprite_z[k] = 12;
sprite_subtype[k] = 254;
}
void SpritePrep_DoNothingC(int k) { // 86899b
// empty
}
void SpritePrep_BlindMaiden(int k) { // 86899c
if (!(save_dung_info[0xac] & 0x800)) {
sprite_ignore_projectile[k]++;
if (follower_indicator != 6) {
follower_indicator = 6;
follower_dropped = 0;
tagalong_var5 = 0;
LoadFollowerGraphics();
Follower_Initialize();
follower_indicator = 0;
return;
}
}
sprite_state[k] = 0;
}
void SpritePrep_MiniMoldorm_bounce(int k) { // 8689d3
int j = 32 * k;
for (int i = 0; i < 32; i++, j++) {
moldorm_x_lo[j] = sprite_x_lo[k];
moldorm_x_hi[j] = sprite_x_hi[k];
moldorm_y_lo[j] = sprite_y_lo[k];
moldorm_y_hi[j] = sprite_y_hi[k];
}
}
void SpritePrep_Bomber(int k) { // 8689d8
sprite_z[k] = 16;
sprite_subtype[k] = 254;
}
void SpritePrep_BombShoppe(int k) { // 8689df
sprite_ignore_projectile[k]++;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xb5, &info);
if (j >= 0) {
Sprite_SetX(j, info.r0_x - 24);
Sprite_SetY(j, info.r2_y - 24);
sprite_subtype2[j] = 1;
sprite_ignore_projectile[j] = 1;
}
if ((link_has_crystals & 5) == 5 && sram_progress_indicator_3 & 32) {
int j = Sprite_SpawnDynamically(k, 0xb5, &info);
if (j >= 0) {
Sprite_SetX(j, info.r0_x - 56);
Sprite_SetY(j, info.r2_y - 24);
sprite_subtype2[j] = 2;
sprite_ignore_projectile[j] = 2;
}
}
}
void SpritePrep_BullyAndVictim(int k) { // 868a51
SpawnBully(k);
sprite_ignore_projectile[k]++;
}
void SpritePrep_PurpleChest(int k) { // 868a59
if (follower_indicator != 12 && !(sram_progress_indicator_3 & 16) && sram_progress_indicator_3 & 32)
sprite_ignore_projectile[k]++;
else
sprite_state[k] = 0;
}
void SpritePrep_Smithy(int k) { // 868a79
sprite_ignore_projectile[k]++;
if (savegame_is_darkworld & 64) {
if (sram_progress_indicator_3 & 32 || follower_indicator != 0)
sprite_state[k] = 0;
else
sprite_subtype2[k] = 2;
return;
}
Smithy_SpawnDumbBarrierSprite(k);
if (!(sram_progress_indicator_3 & 32)) {
sprite_x_lo[k] += 2;
sprite_y_lo[k] -= 3;
return;
}
sprite_x_lo[k] += 2;
sprite_y_lo[k] -= 3;
int j = Smithy_SpawnDwarfPal(k);
Smithy_SpawnDumbBarrierSprite(j);
sprite_E[j] = k;
sprite_E[k] = j;
if (sram_progress_indicator_3 & 0x80) {
sprite_ai_state[k] = 5;
sprite_ai_state[j] = 5;
}
}
void SpritePrep_Babasu(int k) { // 868af0
SpritePrep_MoveDown_8px(k);
SpritePrep_Zoro(k);
}
void SpritePrep_Zoro(int k) { // 868af3
sprite_D[k] = (sprite_type[k] - 0x9c) << 1;
sprite_graphics[k]--;
}
void SpritePrep_LaserEye_bounce(int k) { // 868b03
int t = sprite_type[k];
sprite_D[k] = t - 0x95;
if (t >= 0x97) {
sprite_x_lo[k] += 8;
sprite_head_dir[k] = sprite_x_lo[k] & 16 ^ 16;
if (!sprite_head_dir[k])
sprite_y_lo[k] += (t & 1) ? -8 : 8;
} else {
sprite_head_dir[k] = sprite_y_lo[k] & 16;
if (!sprite_head_dir[k])
sprite_x_lo[k] += (t & 1) ? -8 : 8;
}
}
void SpritePrep_Popo(int k) { // 868b08
sprite_B[k] = 7;
}
void SpritePrep_Popo2(int k) { // 868b0c
sprite_B[k] = 15;
}
void SpritePrep_Statue(int k) { // 868b12
sprite_y_lo[k] += 7;
}
void SpritePrep_Bari(int k) { // 868b1c
sprite_z[k] = 6;
if (BYTE(dungeon_room_index2) == 206)
sprite_C[k]--;
sprite_delay_aux1[k] = (GetRandomNumber() & 63) + 128;
}
void SpritePrep_GreenStalfos(int k) { // 868b2e
sprite_z[k] = 9;
}
void SpritePrep_WaterLever(int k) { // 868b34
sprite_y_lo[k] += 5;
}
void SpritePrep_FireDebirando(int k) { // 868b3e
sprite_type[k] = 0x63;
SpritePrep_LoadProperties(k);
sprite_G[k]--;
SpritePrep_DebirandoPit(k);
}
void SpritePrep_DebirandoPit(int k) { // 868b4a
static const uint8 kDebirando_OamFlags[2] = {6, 8};
sprite_G[k]++;
sprite_delay_main[k] = 0;
sprite_graphics[k] = 6;
SpritePrep_IgnoreProjectiles(k);
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x64, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_delay_main[j] = 96;
sprite_head_dir[k] = j;
sprite_G[j] = sprite_G[k];
sprite_oam_flags[j] = kDebirando_OamFlags[sprite_G[j]];
}
}
void SpritePrep_WeakGuard(int k) { // 868b81
sprite_D[k] = sprite_head_dir[k] = GetRandomNumber() & 3;
sprite_delay_main[k] = 16;
}
void SpritePrep_WallCannon(int k) { // 868b93
sprite_D[k] = sprite_type[k] - 0x66;
sprite_A[k] = sprite_D[k] & 2;
}
void SpritePrep_ArrowGame_bounce(int k) { // 868ba2
static const uint8 kArcheryGameGuy_X[8] = {0, 0x40, 0x80, 0xc0, 0x30, 0x60, 0x90, 0xc0};
static const uint8 kArcheryGameGuy_Y[8] = {0, 0x4f, 0x4f, 0x4f, 0x5a, 0x5a, 0x5a, 0x5a};
static const uint8 kArcheryGameGuy_A[8] = {0, 1, 1, 1, 2, 2, 2, 2};
static const int8 kArcheryGameGuy_Xvel[2] = {-8, 12};
static const uint8 kArcheryGameGuy_Flags4[2] = {0x1c, 0x15};
byte_7E0B88 = 0;
sprite_y_lo[k] -= 9;
for (int i = 7; i != 0; i--) {
sprite_type[i] = 0x65;
sprite_state[i] = 9;
SpritePrep_LoadProperties(i);
sprite_x_hi[i] = (link_x_coord >> 8);
sprite_x_lo[i] = kArcheryGameGuy_X[i];
sprite_y_hi[i] = (link_y_coord >> 8);
sprite_y_lo[i] = kArcheryGameGuy_Y[i];
sprite_A[i] = kArcheryGameGuy_A[i];
int j = kArcheryGameGuy_A[i] - 1;
sprite_graphics[i] = j;
sprite_x_vel[i] = kArcheryGameGuy_Xvel[j];
sprite_flags4[i] = kArcheryGameGuy_Flags4[j];
sprite_oam_flags[i] = 13;
sprite_floor[i] = link_is_on_lower_level;
sprite_subtype2[i] = GetRandomNumber();
}
sprite_ignore_projectile[k]++;
sprite_subtype[k] = link_num_arrows;
}
void SpritePrep_IgnoreProjectiles(int k) { // 868ba7
sprite_ignore_projectile[k]++;
}
void SpritePrep_HauntedGroveAnimal(int k) { // 868bab
sprite_D[k] = Sprite_IsRightOfLink(k).a;
SpritePrep_HauntedGroveOstritch(k);
}
void SpritePrep_HauntedGroveOstritch(int k) { // 868bb2
if (link_item_flute >= 2)
sprite_state[k] = 0;
sprite_ignore_projectile[k]++;
}
void SpritePrep_DiggingGameGuy_bounce(int k) { // 868bbf
if (link_y_coord < Sprite_GetY(k)) {
sprite_ai_state[k] = 5;
sprite_x_lo[k] -= 9;
sprite_graphics[k] = 1;
}
sprite_ignore_projectile[k]++;
}
void SpritePrep_ThievesTownGrate(int k) { // 868bc4
if (save_ow_event_info[0x58] & 0x20)
sprite_state[k] = 0;
sprite_ignore_projectile[k]++;
Sprite_SetX(k, Sprite_GetX(k) - 8);
}
void SpritePrep_RupeePull(int k) { // 868bcf
sprite_ignore_projectile[k]++;
Sprite_SetX(k, Sprite_GetX(k) - 8);
}
void SpritePrep_Shopkeeper(int k) { // 868bf1
sprite_ignore_projectile[k]++;
sprite_flags2[k] |= 2;
sprite_oam_flags[k] |= 12;
sprite_flags3[k] |= 16;
static const uint8 kShopKeeperWhere[13] = {0xf, 0x10, 0, 6, 0x18, 0x12, 0x1e, 0xff, 0x1f, 0x23, 0x24, 0x25, 0x27};
uint8 room = BYTE(dungeon_room_index);
int j = FindInByteArray(kShopKeeperWhere, room, 13);
switch (j) {
case 0:
ShopKeeper_SpawnShopItem(k, 0, 7);
ShopKeeper_SpawnShopItem(k, 1, 8);
ShopKeeper_SpawnShopItem(k, 2, 12);
break;
case 1:
ShopKeeper_SpawnShopItem(k, 0, 9);
ShopKeeper_SpawnShopItem(k, 1, 13);
ShopKeeper_SpawnShopItem(k, 2, 11);
break;
case 2:
sprite_subtype2[k] = 4;
minigame_credits = 0xff;
break;
case 3:
sprite_subtype2[k] = sprite_graphics[k] = 1;
minigame_credits = 0xff;
break;
case 4:
sprite_subtype2[k] = 3;
minigame_credits = 0xff;
break;
case 5: case 7: case 8:
ShopKeeper_SpawnShopItem(k, 0, 7);
ShopKeeper_SpawnShopItem(k, 1, 10);
ShopKeeper_SpawnShopItem(k, 2, 12);
break;
case 6: case 9: case 12:
sprite_subtype2[k] = 2;
break;
case 10:
sprite_subtype2[k] = 5;
break;
case 11:
sprite_subtype2[k] = 6;
break;
default:
assert(0);
}
}
void SpritePrep_Storyteller(int k) { // 868c9e
static const uint8 kStoryTellerRooms[5] = {0xe, 0xe, 0x12, 0x1a, 0x14};
int r = FindInByteArray(kStoryTellerRooms, BYTE(dungeon_room_index), 5);
if (r == 0 && sprite_x_hi[k] & 1)
r = 1;
sprite_subtype2[k] = r;
sprite_ignore_projectile[k]++;
}
void SpritePrep_Adults(int k) { // 868cc1
static const uint8 kHumanMultiTypes[3] = {3, 0xe1, 0x19};
sprite_ignore_projectile[k]++;
sprite_subtype2[k] = FindInByteArray(kHumanMultiTypes, BYTE(dungeon_room_index), 3);
}
void SpritePrep_Whirlpool(int k) { // 868cd5
sprite_ignore_projectile[k]++;
sprite_A[k] = 1;
}
void SpritePrep_Sage(int k) { // 868cde
sprite_ignore_projectile[k]++;
if (BYTE(dungeon_room_index) == 10) {
sprite_subtype2[k]++;
sprite_oam_flags[k] = 11;
}
}
void SpritePrep_BonkItem(int k) { // 868cf2
static const uint16 kDashItemMask[2] = {0x4000, 0x2000};
if (!player_is_indoors) {
sprite_graphics[k] = 2;
return;
}
sprite_floor[k] = 2;
if (dungeon_room_index == 0x107) {
if (link_item_book_of_mudora)
sprite_state[k] = 0;
else
DecodeAnimatedSpriteTile_variable(0xe);
} else {
int j = byte_7E0B9B++;
sprite_die_action[k] = j;
if (dung_savegame_state_bits & kDashItemMask[j])
sprite_state[k] = 0;
sprite_graphics[k]++;
sprite_oam_flags[k] = 8;
sprite_flags3[k] |= 0x20;
}
}
void SpritePrep_Kiki(int k) { // 868d46
sprite_ignore_projectile[k]++;
if (save_ow_event_info[BYTE(overworld_screen_index)] & 0x20)
sprite_state[k] = 0;
}
void SpritePrep_Locksmith(int k) { // 868d59
sprite_ignore_projectile[k]++;
if (follower_indicator == 9) {
sprite_state[k] = 0;
return;
}
if (follower_indicator == 12) {
sprite_ai_state[k] = 2;
}
if (sram_progress_indicator_3 & 0x10)
sprite_ai_state[k] = 4;
}
void SpritePrep_SickKid(int k) { // 868d7f
if (link_item_bug_net)
sprite_ai_state[k] = 3;
sprite_ignore_projectile[k]++;
}
void SpritePrep_Tektite(int k) { // 868d94
static const uint8 kGanonHelpers_OamFlags[2] = {9, 7};
static const uint8 kGanonHelpers_Health[2] = {8, 12};
static const uint8 kGanonHelpers_BumpDamage[2] = {3, 5};
int j;
sprite_A[k] = j = sprite_x_lo[k] >> 4 & 1;
sprite_oam_flags[k] = kGanonHelpers_OamFlags[j];
sprite_health[k] = kGanonHelpers_Health[j];
sprite_bump_damage[k] = kGanonHelpers_BumpDamage[j];
Sprite_ApplySpeedTowardsLink(k, 16);
sprite_z_vel[k] = 32;
sprite_ai_state[k]++;
}
void SpritePrep_Chainchomp_bounce(int k) { // 868dc1
int i = k * 8;
for (int j = 5; j >= 0; j--, i++) {
chainchomp_x_hist[i] = cur_sprite_x;
chainchomp_y_hist[i] = cur_sprite_y;
}
sprite_A[k] = sprite_x_lo[k];
sprite_B[k] = sprite_x_hi[k];
sprite_C[k] = sprite_y_lo[k];
sprite_G[k] = sprite_y_hi[k];
}
void SpritePrep_BigFairy(int k) { // 868dc6
sprite_z[k] = 24;
SpritePrep_MoveDown_8px_Right8px(k);
sprite_ignore_projectile[k]++;
}
void SpritePrep_MrsSahasrahla(int k) { // 868dd1
sprite_y_lo[k] += 8;
SpritePrep_MagicBat(k);
}
void SpritePrep_MagicBat(int k) { // 868dda
sprite_x_lo[k] += 8;
sprite_ignore_projectile[k]++;
}
void SpritePrep_FortuneTeller(int k) { // 868de0
SpritePrep_IncrXYLow8(k);
sprite_ignore_projectile[k]++;
}
void SpritePrep_FairyPond(int k) { // 868de9
static const uint8 kLeever_OamFlags[2] = {10, 2};
int j = sprite_x_lo[k] >> 4 & 1;
sprite_A[k] = j;
sprite_oam_flags[k] = kLeever_OamFlags[j];
}
void SpritePrep_Hobo(int k) { // 868dfd
for (int i = 15; i; i--)
SpritePrep_Hobo_SpawnSmoke(k);
for (int i = 15; i; i--) {
if (sprite_type[i] == 0x2b)
sprite_state[i] = 0;
}
SpritePrep_Hobo_SpawnFire(k);
if (sram_progress_indicator_3 & 1)
sprite_ai_state[0] = 3;
sprite_ignore_projectile[0] = 1;
}
void SpritePrep_MasterSword(int k) { // 868e30
sprite_x_lo[k] += 6;
sprite_y_lo[k] += 6;
}
void SpritePrep_Roller_HorizontalRightFirst(int k) { // 868e42
sprite_ai_state[k] = (~sprite_x_lo[k] & 16) >> 4;
if (sprite_ai_state[k])
sprite_flags4[k]++;
sprite_D[k] = 0;
}
void SpritePrep_RollerLeftRight(int k) { // 868e46
sprite_ai_state[k] = (~sprite_x_lo[k] & 16) >> 4;
if (sprite_ai_state[k])
sprite_flags4[k]++;
sprite_D[k] = 1;
}
void SpritePrep_Roller_VerticalDownFirst(int k) { // 868e4f
sprite_ai_state[k] = (sprite_y_lo[k] & 16) >> 4;
if (sprite_ai_state[k])
sprite_flags4[k]++;
sprite_D[k] = 2;
}
void SpritePrep_RollerUpDown(int k) { // 868e53
sprite_ai_state[k] = (sprite_y_lo[k] & 16) >> 4;
if (sprite_ai_state[k])
sprite_flags4[k]++;
sprite_D[k] = 3;
}
void SpritePrep_Kodongo(int k) { // 868e6b
sprite_x_lo[k] += 4;
Sprite_SetY(k, Sprite_GetY(k) - 5);
sprite_subtype[k]--;
}
void SpritePrep_Spark(int k) { // 868e85
sprite_subtype[k]--;
}
void SpritePrep_LostWoodsBird(int k) { // 868ec1
sprite_z_vel[k] = (GetRandomNumber() & 0x1f) - 0x10;
sprite_z[k] = 64;
SpritePrep_LostWoodsSquirrel(k);
}
void SpritePrep_LostWoodsSquirrel(int k) { // 868ed2
sprite_x_vel[k] = Sprite_IsRightOfLink(k).a ? -16 : 16;
sprite_ignore_projectile[k] = sprite_y_vel[k] = sign8(byte_7E069E[0]) ? 4 : -4;
}
void SpritePrep_Antifairy(int k) { // 868ef2
static const int8 kBubble_Xvel[2] = {16, -16};
sprite_x_vel[k] = kBubble_Xvel[sprite_x_lo[k] >> 4 & 1];
sprite_y_vel[k] = -16;
}
void SpritePrep_FallingIce(int k) { // 868f08
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_ignore_projectile[k]++;
}
void SpritePrep_KingZora(int k) { // 868f0f
if (link_item_flippers)
sprite_state[k] = 0;
else
sprite_ignore_projectile[k]++;
}
bool Sprite_ReturnIfBossFinished(int k) { // 868f1c
if (dung_savegame_state_bits & 0x8000) {
sprite_state[k] = 0;
return true;
}
for (int j = 15; j >= 0; j--) {
if (!(kSpriteInit_BumpDamage[sprite_type[j]] & 0x10))
sprite_state[j] = 0;
}
return false;
}
void SpritePrep_ArmosKnight(int k) { // 868f3f
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_delay_main[k] = 255;
byte_7E0FF8++;
SpritePrep_MoveDown_8px_Right8px(k);
}
void SpritePrep_DesertStatue(int k) { // 868f4d
sprite_A[k] = sprite_limit_instance;
sprite_limit_instance++;
SpritePrep_MoveDown_8px_Right8px(k);
sprite_D[k] = (sprite_x_lo[k] < 0x30) ? 1 : (sprite_x_lo[k] < 0xe0) ? 3 : 2;
}
void SpritePrep_DoNothingD(int k) { // 868f6c
// empty
}
void SpritePrep_Octorok(int k) { // 868f71
static const uint8 kOctorock_BumpDamage[2] = {3, 5};
static const uint8 kOctorock_Health[2] = {2, 4};
int j = is_in_dark_world;
sprite_health[k] = kOctorock_Health[j];
sprite_bump_damage[k] = kOctorock_BumpDamage[j];
sprite_delay_main[k] = GetRandomNumber() & 127;
}
void SpritePrep_Moldorm_bounce(int k) { // 868f8a
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_ignore_projectile[k]++;
Sprite_InitializedSegmented(k);
}
void SpritePrep_Lanmolas_bounce(int k) { // 868f95
static const uint8 kLanmola_InitDelay[3] = {128, 192, 255};
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_delay_main[k] = kLanmola_InitDelay[k];
sprite_z[k] = -1;
for (int i = 0; i < 64; i++)
beamos_x_hi[k * 0x40 + i] = 0xff;
garnish_y_lo[k] = 7;
}
void SpritePrep_BigSpike(int k) { // 868f9d
SpritePrep_MoveDown_8px_Right8px(k);
SpritePrep_Kyameron(k);
}
void SpritePrep_SwimmingZora(int k) { // 868fa2
sprite_delay_main[k] = 64;
SpritePrep_Geldman(k);
}
void SpritePrep_Geldman(int k) { // 868fa7
sprite_x_lo[k] += 8;
SpritePrep_Kyameron(k);
}
void SpritePrep_Kyameron(int k) { // 868fb0
sprite_A[k] = sprite_x_lo[k];
sprite_B[k] = sprite_x_hi[k];
sprite_C[k] = sprite_y_lo[k];
sprite_head_dir[k] = sprite_y_hi[k];
}
void SpritePrep_WalkingZora(int k) { // 868fc9
sprite_delay_main[k] = 96;
}
void SpritePrep_StandardGuard(int k) { // 868fd6
static const uint8 kSpriteSoldier_Tab0[8] = {0, 2, 1, 3, 6, 4, 5, 7};
uint8 subtype = sprite_subtype[k];
if (subtype != 0) {
if ((subtype & 7) >= 5) {
int j = ((subtype & 7) != 5) * 4 + (subtype >> 3 & 3);
sprite_B[k] = kSpriteSoldier_Tab0[j];
sprite_flags[k] = sprite_flags[k] & 0xf | 0x50;
SpritePrep_TrooperAndArcherSoldier(k);
return;
}
sprite_D[k] = ((subtype & 7) - 1) ^ 1;
}
if (player_is_indoors) {
sprite_flags5[k] &= ~0x80;
return;
}
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 112;
sprite_D[k] = sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL);
SpritePrep_TrooperAndArcherSoldier(k);
}
void SpritePrep_TrooperAndArcherSoldier(int k) { // 869001
uint8 bak0 = submodule_index;
submodule_index = 0;
sprite_defl_bits[k] = (sprite_defl_bits[k] >> 1) | 0x80;
SpriteActive_Main(k);
SpriteActive_Main(k);
sprite_defl_bits[k] <<= 1;
submodule_index = bak0;
}
void SpritePrep_TalkingTree(int k) { // 869043
sprite_ignore_projectile[k]++;
Sprite_SetX(k, Sprite_GetX(k) - 8);
SpritePrep_TalkingTree_SpawnEyeball(k, 0);
SpritePrep_TalkingTree_SpawnEyeball(k, 1);
}
void SpritePrep_CrystalSwitch(int k) { // 869064
sprite_oam_flags[k] |= kCrystalSwitchPal[orange_blue_barrier_state & 1];
}
void SpritePrep_FluteKid(int k) { // 869075
sprite_ignore_projectile[k]++;
sprite_subtype2[k] = savegame_is_darkworld >> 6 & 1;
if (sprite_subtype2[k]) {
if (sram_progress_indicator_3 & 8 || link_item_flute > 2) {
sprite_graphics[k] = 3;
sprite_ai_state[k] = 5;
} else if (link_item_flute == 2) {
sprite_graphics[k] = 1;
}
sprite_x_lo[k] += 8;
sprite_y_lo[k] -= 8;
} else {
if (link_item_flute >= 2)
sprite_state[k] = 0;
else
sprite_x_lo[k] += 7;
}
}
void SpritePrep_MoveDown_8px(int k) { // 8690cc
sprite_y_lo[k] += 8;
}
void SpritePrep_Zazakku(int k) { // 8690d5
// empty
}
void SpritePrep_PedestalPlaque(int k) { // 8690d6
sprite_ignore_projectile[k]++;
if (BYTE(overworld_screen_index) == 48)
sprite_x_lo[k] += 7;
}
void SpritePrep_Stalfos(int k) { // 8690e0
sprite_subtype[k] = sprite_x_lo[k] & 16;
if (sprite_subtype[k])
sprite_oam_flags[k] = 7;
}
void SpritePrep_KholdstareShell(int k) { // 8690f0
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_delay_aux1[k] = 192;
SpritePrep_MoveDown_8px_Right8px(k);
}
void SpritePrep_Kholdstare(int k) { // 8690fa
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_ai_state[k] = 3;
SpritePrep_IgnoreProjectiles(k);
SpritePrep_MoveDown_8px_Right8px(k);
}
void SpritePrep_Bumper(int k) { // 869107
sprite_ignore_projectile[k]++;
SpritePrep_MoveDown_8px_Right8px(k);
}
void SpritePrep_MoveDown_8px_Right8px(int k) { // 86910a
sprite_x_lo[k] += 8;
sprite_y_lo[k] += 8;
}
void SpritePrep_HardhatBeetle(int k) { // 869122
static const uint8 kHardHatBeetle_OamFlags[2] = {6, 8};
static const uint8 kHardHatBeetle_Health[2] = {32, 6};
static const uint8 kHardHatBeetle_A[2] = {16, 12};
static const uint8 kHardHatBeetle_State[2] = {1, 3};
static const uint8 kHardHatBeetle_Flags5[2] = {2, 6};
static const uint8 kHardHatBeetle_BumpDamage[2] = {5, 3};
int j = (sprite_x_lo[k] & 0x10) != 0;
sprite_oam_flags[k] = kHardHatBeetle_OamFlags[j];
sprite_health[k] = kHardHatBeetle_Health[j];
sprite_A[k] = kHardHatBeetle_A[j];
sprite_ai_state[k] = kHardHatBeetle_State[j];
sprite_flags5[k] = kHardHatBeetle_Flags5[j];
sprite_bump_damage[k] = kHardHatBeetle_BumpDamage[j];
}
void SpritePrep_MiniHelmasaur(int k) { // 869151
sprite_A[k] = 16;
sprite_ai_state[k] = 1;
}
void SpritePrep_Fairy(int k) { // 86915c
sprite_A[k] = GetRandomNumber() & 1;
sprite_D[k] = sprite_A[k] ^ 1;
SpritePrep_Absorbable(k);
}
void SpritePrep_Absorbable(int k) { // 86916a
if (!player_is_indoors) {
sprite_E[k]++;
sprite_ignore_projectile[k]++;
}
}
void SpritePrep_OverworldBonkItem(int k) { // 86916e
sprite_E[k]++;
sprite_ignore_projectile[k]++;
}
void SpritePrep_ShieldPickup(int k) { // 869174
}
void SpritePrep_NiceBee(int k) { // 869175
uint8 or_bottle = link_bottle_info[0] | link_bottle_info[1] | link_bottle_info[2] | link_bottle_info[3];
if (or_bottle & 8)
sprite_state[k] = 0;
sprite_E[k]++;
sprite_ignore_projectile[k]++;
}
void SpritePrep_Agahnim(int k) { // 869195
static const uint8 kAgahnim_OamFlags[2] = {11, 7};
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_graphics[k] = 0;
sprite_D[k] = 3;
SpritePrep_MoveDown_8px_Right8px(k);
sprite_oam_flags[k] = kAgahnim_OamFlags[is_in_dark_world];
}
void SpritePrep_DoNothingG(int k) { // 8691ae
// empty
}
void SpritePrep_FireBar(int k) { // 8691b4
sprite_B[k]++;
sprite_ignore_projectile[k]++;
}
void SpritePrep_Trinexx(int k) { // 8691ba
if (Sprite_ReturnIfBossFinished(k))
return;
TrinexxComponents_Initialize(k);
for (int i = 15; i >= 0; i--)
alt_sprite_state[i] = 0;
}
void SpritePrep_HelmasaurKing(int k) { // 8691c5
if (Sprite_ReturnIfBossFinished(k))
return;
HelmasaurKing_Initialize(k);
memset(alt_sprite_state, 0, 16);
}
void SpritePrep_Spike(int k) { // 8691d7
sprite_x_vel[k] = 32;
sprite_y_vel[k] = -16;
Sprite_MoveY(k);
sprite_y_vel[k] = 0;
}
void SpritePrep_RockStal(int k) { // 8691dc
sprite_y_vel[k] = -16;
Sprite_MoveY(k);
sprite_y_vel[k] = 0;
}
void SpritePrep_Blob(int k) { // 8691e8
sprite_graphics[k] = 4;
SpritePrep_IgnoreProjectiles(k);
}
void SpritePrep_Arrghus(int k) { // 8691f1
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_z[k] = 24;
}
void SpritePrep_Arrghi(int k) { // 8691fa
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_subtype2[k] = GetRandomNumber();
if (k == 13) {
overlord_x_lo[2] = 0;
overlord_x_lo[3] = 0;
Arrghus_HandlePuffs(0);
}
sprite_x_lo[k] = overlord_x_lo[k + 7];
sprite_x_hi[k] = overlord_y_lo[k + 7];
sprite_y_lo[k] = overlord_gen1[k + 7];
sprite_y_hi[k] = overlord_gen3[k + 7];
}
void SpritePrep_Mothula(int k) { // 86922f
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_delay_main[k] = 80;
sprite_ignore_projectile[k]++;
sprite_graphics[k] = 2;
BYTE(dung_floor_move_flags)++;
sprite_C[k] = 112;
}
void SpritePrep_DoNothingH(int k) { // 86924d
// empty
}
void SpritePrep_BigKey(int k) { // 86924e
sprite_x_lo[k] += 8;
sprite_subtype[k] = 0xff;
SpritePrep_BigKey_load_graphics(k);
}
void SpritePrep_BigKey_load_graphics(int k) { // 869256
DecodeAnimatedSpriteTile_variable(0x22);
SpritePrep_KeySetItemDrop(k);
}
void SpritePrep_SmallKey(int k) { // 869262
sprite_subtype[k] = 255;
sprite_die_action[k] = byte_7E0B9B++;
}
void SpritePrep_KeySetItemDrop(int k) { // 869267
sprite_die_action[k] = byte_7E0B9B;
byte_7E0B9B++;
}
void SpriteActive_Main(int k) { // 869271
uint8 type = sprite_type[k];
kSpriteActiveRoutines[type](k);
}
void Sprite_09_Moldorm_bounce(int k) { // 869469
static const int8 kGiantMoldorm_Xvel[32] = {
24, 22, 17, 9, 0, -9, -17, -22, -24, -22, -17, -9, 0, 9, 17, 22,
36, 33, 25, 13, 0, -13, -25, -33, -36, -33, -25, -13, 0, 13, 25, 33,
};
static const int8 kGiantMoldorm_Yvel[32] = {
0, 9, 17, 22, 24, 22, 17, 9, 0, -9, -17, -22, -24, -22, -17, -9,
0, 13, 25, 33, 36, 33, 25, 13, 0, -13, -25, -33, -36, -33, -25, -13,
};
static const uint8 kGiantMoldorm_NextDir[16] = {8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7};
GiantMoldorm_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_ai_state[k] == 3) {
// await death
if (!sprite_delay_aux4[k]) {
sprite_state[k] = 4;
sprite_A[k] = 0;
sprite_delay_main[k] = 224;
} else {
sprite_hit_timer[k] = sprite_delay_aux4[k] | 224;
}
return;
}
Sprite_CheckDamageFromLink(k);
bool low_health = (sprite_health[k] < 3);
sprite_subtype2[k] += low_health ? 2 : 1;
if (!(frame_counter & (low_health ? 3 : 7)))
SpriteSfx_QueueSfx3WithPan(k, 0x31);
if (sprite_F[k]) {
sprite_delay_aux2[k] = 64;
if (!(frame_counter & 3))
sprite_F[k]--;
return;
}
if (!link_incapacitated_timer && Sprite_CheckDamageToLink(k)) {
Link_CancelDash();
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 0x28);
link_actual_vel_y = pt.y;
link_actual_vel_x = pt.x;
link_incapacitated_timer = 24;
sprite_delay_aux1[k] = 48;
sound_effect_2 = Sprite_CalculateSfxPan(k);
}
int j = sprite_D[k] + low_health * 16;
sprite_x_vel[k] = kGiantMoldorm_Xvel[j];
sprite_y_vel[k] = kGiantMoldorm_Yvel[j];
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k)) {
sprite_D[k] = kGiantMoldorm_NextDir[sprite_D[k]];
SpriteSfx_QueueSfx2WithPan(k, 0x21);
}
switch(sprite_ai_state[k]) {
case 0: // straight path
if (!sprite_delay_main[k]) {
j = 1;
if (++sprite_G[k] == 3)
sprite_G[k] = 0, j = 2;
sprite_ai_state[k] = j;
sprite_head_dir[k] = (GetRandomNumber() & 2) - 1;
sprite_delay_main[k] = (GetRandomNumber() & 31) + 32;
}
break;
case 1: // spinning meander
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = (GetRandomNumber() & 15) + 8;
sprite_ai_state[k] = 0;
} else if (!(sprite_delay_main[k] & 3)) {
sprite_D[k] = (sprite_D[k] + sprite_head_dir[k]) & 0xf;
}
break;
case 2: // lunge at player
if (!((k ^ frame_counter) & 3)) {
Sprite_ApplySpeedTowardsLink(k, 0x1f);
uint8 dir = Sprite_ConvertVelocityToAngle(sprite_x_vel[k], sprite_y_vel[k]) - sprite_D[k];
if (dir == 0) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 48;
} else {
sprite_D[k] += sign8(dir) ? -1 : 1;
}
}
break;
}
}
void Sprite_01_Vulture_bounce(int k) { // 869473
static const uint8 kVulture_Gfx[4] = {1, 2, 3, 2};
sprite_obj_prio[k] |= 0x30;
Vulture_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
switch (sprite_ai_state[k]) {
case 0: // dormant
if (++sprite_subtype2[k] == 160) {
sprite_ai_state[k] = 1;
SpriteSfx_QueueSfx3WithPan(k, 0x1e);
sprite_delay_main[k] = 16;
}
break;
case 1: { // circling
sprite_graphics[k] = kVulture_Gfx[frame_counter >> 1 & 3];
if (sprite_delay_main[k]) {
sprite_z[k]++;
return;
}
if ((k ^ frame_counter) & 1)
return;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, (k & 0xf) + 24);
sprite_x_vel[k] = -pt.y;
sprite_y_vel[k] = pt.x;
if ((uint8)(pt.xdiff + 0x28) < 0x50 && (uint8)(pt.ydiff + 0x28) < 0x50)
return;
sprite_y_vel[k] += (int8)pt.y >> 2;
sprite_x_vel[k] += (int8)pt.x >> 2;
break;
}
}
}
void Sprite_27_Deadrock(int k) { // 86948a
static const uint8 kDeadRock_Gfx[9] = {0, 1, 0, 1, 2, 2, 3, 3, 4};
static const uint8 kDeadRock_OamFlags[9] = {0x40, 0x40, 0, 0, 0, 0x40, 0, 0x40, 0};
static const int8 kDeadRock_Xvel[4] = {32, -32, 0, 0};
static const int8 kDeadRock_Yvel[4] = {0, 0, 32, -32};
int j = (sprite_delay_aux2[k] ? (sprite_delay_aux2[k] & 4) : (sprite_ai_state[k] != 2)) ? sprite_A[k] : 8;
sprite_graphics[k] = kDeadRock_Gfx[j];
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kDeadRock_OamFlags[j];
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_F[k] && (Sprite_CheckDamageFromLink(k) & kCheckDamageFromPlayer_Carry) && !sound_effect_1)
SpriteSfx_QueueSfx2WithPan(k, 0xb);
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
Sprite_RepelDash();
}
if (sprite_F[k] == 14) {
sprite_ai_state[k] = 2;
sprite_delay_aux1[k] = 255;
sprite_delay_aux2[k] = 64;
}
if (Sprite_ReturnIfRecoiling(k))
return;
switch(sprite_ai_state[k]) {
case 0: // pick dir
if (!sprite_delay_main[k]) {
sprite_flags2[k] &= ~0x80;
sprite_defl_bits[k] &= ~4;
sprite_flags3[k] &= ~0x40;
sprite_ai_state[k]++;
sprite_delay_main[k] = (GetRandomNumber() & 31) + 32;
if (++sprite_B[k] == 4) {
sprite_B[k] = 0;
j = Sprite_DirectionToFaceLink(k, NULL);
} else {
j = GetRandomNumber() & 3;
}
set_dir:
sprite_D[k] = j;
sprite_x_vel[k] = kDeadRock_Xvel[j];
sprite_y_vel[k] = kDeadRock_Yvel[j];
}
break;
case 1: // walk
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 32;
} else {
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k)) {
j = sprite_D[k] ^ 1;
goto set_dir;
}
sprite_A[k] = sprite_D[k] << 1 | ++sprite_subtype2[k] >> 2 & 1;
}
break;
case 2: // petrified
sprite_flags2[k] |= 0x80;
sprite_defl_bits[k] |= 4;
sprite_flags3[k] |= 0x40;
if (!(frame_counter & 1)) {
if (sprite_delay_aux1[k] == 0) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 16;
} else if (sprite_delay_aux1[k] == 0x20) {
sprite_delay_aux2[k] = 0x40;
}
} else {
sprite_delay_aux1[k]++;
}
break;
}
}
void Sprite_20_Sluggula(int k) { // 8695d9
static const uint8 kSluggula_Gfx[8] = {0, 1, 0, 1, 2, 3, 4, 5};
static const uint8 kSluggula_OamFlags[8] = {0x40, 0x40, 0, 0, 0, 0, 0, 0};
static const int8 kSluggula_XYvel[6] = {16, -16, 0, 0, 16, -16};
int j = sprite_D[k] << 1 | (sprite_subtype2[k] & 8) >> 3;
sprite_graphics[k] = kSluggula_Gfx[j];
sprite_oam_flags[k] = sprite_oam_flags[k] & 191 | kSluggula_OamFlags[j];
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_subtype2[k]++;
switch(sprite_ai_state[k]) {
case 0: // normal
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = (GetRandomNumber() & 31) + 32;
sprite_D[k] = j = sprite_delay_main[k] & 3;
set_vel:
sprite_x_vel[k] = kSluggula_XYvel[j];
sprite_y_vel[k] = kSluggula_XYvel[j + 2];
} else if (sprite_delay_main[k] == 16 && !(GetRandomNumber() & 1)) {
Sluggula_DropBomb(k);
}
break;
case 1: // break from bombing
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 32;
}
Sprite_MoveXY(k);
if (!Sprite_CheckTileCollision(k))
return;
j = (sprite_D[k] ^= 1);
goto set_vel;
}
}
void Sluggula_DropBomb(int k) { // 869673
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0x4a, &info, 11);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
Sprite_TransmuteToBomb(j);
}
}
void Sprite_19_Poe(int k) { // 869688
static const int8 kPoe_Accel[4] = {1, -1, 2, -2};
static const int8 kPoe_ZvelTarget[2] = {8, -8};
static const int8 kPoe_XvelTarget[4] = {16, -16, 28, -28};
static const uint8 kPoe_OamFlags[2] = {0x40, 0};
static const int8 kPoe_Yvel[2] = {8, -8};
int j;
sprite_D[k] = j = sprite_x_vel[k] >> 7;
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kPoe_OamFlags[j];
if (!sprite_E[k])
sprite_obj_prio[k] |= 0x30;
Poe_Draw(k);
oam_cur_ptr += 4;
oam_ext_cur_ptr++;
sprite_flags2[k]--;
SpriteDraw_SingleLarge(k);
sprite_flags2[k]++;
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
if (sprite_E[k]) {
if (++sprite_z[k] == 12)
sprite_E[k] = 0;
return;
}
Sprite_CheckDamageToAndFromLink(k);
sprite_subtype2[k]++;
Sprite_MoveXY(k);
if (!(frame_counter & 1)) {
j = sprite_G[k] & 1;
sprite_z_vel[k] += kPoe_Accel[j];
if (sprite_z_vel[k] == (uint8)kPoe_ZvelTarget[j])
sprite_G[k]++;
}
Sprite_MoveZ(k);
sprite_y_vel[k] = 0;
switch(sprite_ai_state[k]) {
case 0: // select vertical dir
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
if (!(GetRandomNumber() & 12))
sprite_head_dir[k] = Sprite_IsBelowLink(k).a;
else
sprite_head_dir[k] = GetRandomNumber() & 1;
}
break;
case 1: // roaming
if (!(frame_counter & 1)) {
int j = (sprite_anim_clock[k] & 1) + is_in_dark_world * 2;
sprite_x_vel[k] += kPoe_Accel[j];
if (sprite_x_vel[k] == (uint8)kPoe_XvelTarget[j]) {
sprite_anim_clock[k]++;
sprite_ai_state[k] = 0;
sprite_delay_main[k] = (GetRandomNumber() & 31) + 16;
}
}
sprite_y_vel[k] = kPoe_Yvel[sprite_head_dir[k]];
break;
}
}
void Poe_Draw(int k) { // 869786
static const int8 kPoe_Draw_X[2] = {9, -1};
static const uint8 kPoe_Draw_Char[4] = {0x7c, 0x80, 0xb7, 0x80};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
uint16 x = info.x + kPoe_Draw_X[sprite_D[k]];
uint16 y = info.y + 9;
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kPoe_Draw_Char[sprite_subtype2[k] >> 3 & 3];
oam->flags = info.flags & 0xf0 | 2;
bytewise_extended_oam[oam - oam_buf] = (x >> 8 & 1);
}
void Sprite_18_MiniMoldorm(int k) { // 869808
static const int8 kMoldorm_Xvel[16] = {24, 22, 17, 9, 0, -9, -17, -22, -24, -22, -17, -9, 0, 9, 17, 22};
static const int8 kMoldorm_Yvel[16] = {0, 9, 17, 22, 24, 22, 17, 9, 0, -9, -17, -22, -24, -22, -17, -9};
static const uint8 kMoldorm_NextDir[16] = {8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7};
Moldorm_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_F[k])
SpritePrep_MiniMoldorm_bounce(k);
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_subtype2[k]++;
int j = sprite_D[k];
sprite_x_vel[k] = kMoldorm_Xvel[j];
sprite_y_vel[k] = kMoldorm_Yvel[j];
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k)) {
if (GetRandomNumber() & 1)
sprite_head_dir[k] = -sprite_head_dir[k];
sprite_D[k] = kMoldorm_NextDir[sprite_D[k]];
}
switch (sprite_ai_state[k]) {
case 0: // configure
if (!sprite_delay_main[k]) {
if (++sprite_G[k] == 6)
sprite_G[k] = 0, sprite_ai_state[k] = 2;
else
sprite_ai_state[k] = 1;
sprite_head_dir[k] = (GetRandomNumber() & 2) - 1;
sprite_delay_main[k] = (GetRandomNumber() & 0x1f) + 0x20;
}
break;
case 1: // meander
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = (GetRandomNumber() & 15) + 8;
sprite_ai_state[k] = 0;
} else if ((sprite_delay_main[k] & 3) == 0) {
sprite_D[k] = (sprite_D[k] + sprite_head_dir[k]) & 0xf;
}
break;
case 2: // seek player
if (!((k ^ frame_counter) & 3)) {
Sprite_ApplySpeedTowardsLink(k, 31);
uint8 d = Sprite_ConvertVelocityToAngle(sprite_x_vel[k], sprite_y_vel[k]) - sprite_D[k];
if (d == 0) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 48;
} else {
sprite_D[k] = (sprite_D[k] + (sign8(d) ? -1 : 1)) & 0xf;
}
}
break;
}
}
void Sprite_12_Moblin(int k) { // 8698e4
static const int8 kMoblin_Xvel[4] = {16, -16, 0, 0};
static const int8 kMoblin_Yvel[4] = {0, 0, 16, -16};
static const uint8 kMoblin_Delay[4] = {0x10, 0x20, 0x30, 0x40};
static const uint8 kMoblin_Gfx2[8] = {11, 10, 8, 9, 7, 5, 0, 2};
static const uint8 kMoblin_Dirs[8] = {2, 3, 2, 3, 0, 1, 0, 1};
static const uint8 kMoblin_Gfx[4] = {6, 4, 0, 2};
int j;
Moblin_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
Sprite_CheckTileCollision2(k);
switch(sprite_ai_state[k]) {
case 0: // select dir
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = kMoblin_Delay[GetRandomNumber() & 3];
sprite_ai_state[k]++;
sprite_D[k] = sprite_head_dir[k];
j = sprite_head_dir[k];
sprite_x_vel[k] = kMoblin_Xvel[j];
sprite_y_vel[k] = kMoblin_Yvel[j];
}
break;
case 1: // walk
sprite_graphics[k] = (sprite_subtype2[k] & 1) + kMoblin_Gfx[sprite_D[k]];
if (!sprite_wallcoll[k]) {
if (sprite_delay_main[k]) {
if (sign8(--sprite_E[k])) {
sprite_E[k] = 11;
sprite_subtype2[k]++;
}
return;
}
if (sprite_D[k] == Sprite_DirectionToFaceLink(k, NULL)) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 32;
Sprite_ZeroVelocity_XY(k);
sprite_z_vel[k] = 0;
return;
}
sprite_delay_main[k] = 0x10;
} else {
sprite_delay_main[k] = 0xc;
}
sprite_head_dir[k] = kMoblin_Dirs[sprite_D[k] << 1 | GetRandomNumber() & 1];
sprite_ai_state[k] = 0;
if (++sprite_C[k] == 4) {
sprite_C[k] = 0;
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL);
}
Sprite_ZeroVelocity_XY(k);
sprite_z_vel[k] = 0;
break;
case 2: // throw spear
j = sprite_D[k];
if (!sprite_delay_main[k])
sprite_ai_state[k] = 0;
if (sprite_delay_main[k] < 16) {
if (sprite_delay_main[k] == 15) {
Moblin_MaterializeSpear(k);
sprite_delay_aux1[k] = 32;
}
j += 4;
}
sprite_graphics[k] = kMoblin_Gfx2[j];
break;
}
}
void Moblin_MaterializeSpear(int k) { // 8699eb
static const int8 kMoblinSpear_X[4] = {11, -2, -3, 11};
static const int8 kMoblinSpear_Y[4] = {-3, -3, 3, -11};
static const int8 kMoblinSpear_Xvel[4] = {32, -32, 0, 0};
static const int8 kMoblinSpear_Yvel[4] = {0, 0, 32, -32};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x1b, &info), i;
if (j >= 0) {
sprite_A[j] = 3;
sprite_D[j] = i = sprite_D[k];
Sprite_SetX(j, info.r0_x + kMoblinSpear_X[i]);
Sprite_SetY(j, info.r2_y + kMoblinSpear_Y[i]);
sprite_x_vel[j] = kMoblinSpear_Xvel[i];
sprite_y_vel[j] = kMoblinSpear_Yvel[i];
}
}
void Moblin_Draw(int k) { // 869bc4
static const DrawMultipleData kMoblin_Dmd[48] = {
{-2, 3, 0x8091, 0},
{-2, 11, 0x8090, 0},
{ 0, -10, 0x0086, 2},
{ 0, 0, 0x008a, 2},
{-2, 7, 0x8091, 0},
{-2, 15, 0x8090, 0},
{ 0, -10, 0x0086, 2},
{ 0, 0, 0x408a, 2},
{ 0, -9, 0x0084, 2},
{ 0, 0, 0x00a0, 2},
{11, -5, 0x0090, 0},
{11, 3, 0x0091, 0},
{ 0, -9, 0x0084, 2},
{ 0, 0, 0x40a0, 2},
{11, -8, 0x0090, 0},
{11, 0, 0x0091, 0},
{-4, 8, 0x0080, 0},
{ 4, 8, 0x0081, 0},
{ 0, -9, 0x0088, 2},
{ 0, 0, 0x00a6, 2},
{-9, 6, 0x0080, 0},
{-1, 6, 0x0081, 0},
{ 0, -8, 0x0088, 2},
{ 0, 0, 0x00a4, 2},
{12, 8, 0x4080, 0},
{ 4, 8, 0x4081, 0},
{ 0, -9, 0x4088, 2},
{ 0, 0, 0x40a6, 2},
{17, 6, 0x4080, 0},
{ 9, 6, 0x4081, 0},
{ 0, -8, 0x4088, 2},
{ 0, 0, 0x40a4, 2},
{-3, -5, 0x8091, 0},
{-3, 3, 0x8090, 0},
{ 0, -10, 0x0086, 2},
{ 0, 0, 0x00a8, 2},
{11, -11, 0x0090, 0},
{11, -3, 0x0091, 0},
{ 0, -9, 0x0084, 2},
{ 0, 0, 0x4082, 2},
{-2, -3, 0x0080, 0},
{ 6, -3, 0x0081, 0},
{ 0, -9, 0x0088, 2},
{ 0, 0, 0x00a2, 2},
{10, -3, 0x4080, 0},
{ 2, -3, 0x4081, 0},
{ 0, -9, 0x4088, 2},
{ 0, 0, 0x40a2, 2},
};
static const uint8 kMoblin_ObjOffs[12] = {2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2};
static const uint8 kMoblin_HeadChar[4] = {0x88, 0x88, 0x86, 0x84};
static const uint8 kMoblin_HeadFlags[4] = {0x40, 0, 0, 0};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kMoblin_Dmd[sprite_graphics[k] * 4], 4, &info);
if (sprite_pause[k])
return;
OamEnt *oam = GetOamCurPtr();
if (sprite_delay_aux1[k]) {
for (int i = 0; i < 4; i++, oam++) {
if (!(bytewise_extended_oam[oam - oam_buf] & 2))
oam->y = 0xf0;
}
}
oam = GetOamCurPtr() + kMoblin_ObjOffs[sprite_graphics[k]];
int j = sprite_head_dir[k];
oam->charnum = kMoblin_HeadChar[j];
oam->flags = oam->flags &~0x40 | kMoblin_HeadFlags[j];
SpriteDraw_Shadow(k, &info);
}
void Sprite_0E_Snapdragon(int k) { // 869c24
static const uint8 kSnapDragon_Delay[4] = {0x20, 0x30, 0x40, 0x50};
static const uint8 kSnapDragon_Gfx[4] = {4, 0, 6, 2};
static const int8 kSnapDragon_Xvel[8] = {8, -8, 8, -8, 16, -16, 16, -16};
static const int8 kSnapDragon_Yvel[8] = {8, 8, -8, -8, 16, 16, -16, -16};
int j;
sprite_graphics[k] = sprite_B[k] + kSnapDragon_Gfx[sprite_D[k]];
SnapDragon_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_B[k] = 0;
switch(sprite_ai_state[k]) {
case 0: // resting
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = kSnapDragon_Delay[(GetRandomNumber() & 12) >> 2];
if (sign8(--sprite_A[k])) {
sprite_A[k] = 3;
sprite_delay_main[k] = 96;
sprite_C[k]++;
sprite_D[k] = Sprite_IsBelowLink(k).a * 2 + Sprite_IsRightOfLink(k).a;
} else {
sprite_D[k] = GetRandomNumber() & 3;
}
} else if (sprite_delay_main[k] & 0x18) {
sprite_B[k]++;
}
break;
case 1: // attack
sprite_B[k]++;
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k))
sprite_D[k] ^= 3;
j = sprite_D[k] + (sprite_C[k] ? 4 : 0);
sprite_x_vel[k] = kSnapDragon_Xvel[j];
sprite_y_vel[k] = kSnapDragon_Yvel[j];
Sprite_MoveZ(k);
sprite_z_vel[k] -= 4;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_C[k] = 0;
sprite_delay_main[k] = 63;
} else {
sprite_z_vel[k] = 20;
}
}
break;
}
}
void SnapDragon_Draw(int k) { // 869e02
static const DrawMultipleData kSnapDragon_Dmd[32] = {
{ 4, -8, 0x008f, 0},
{12, -8, 0x009f, 0},
{-4, 0, 0x008c, 2},
{ 4, 0, 0x008d, 2},
{ 4, -8, 0x002b, 0},
{12, -8, 0x003b, 0},
{-4, 0, 0x0028, 2},
{ 4, 0, 0x0029, 2},
{-4, -8, 0x003c, 0},
{ 4, -8, 0x003d, 0},
{-4, 0, 0x00aa, 2},
{ 4, 0, 0x00ab, 2},
{-4, -8, 0x003e, 0},
{ 4, -8, 0x003f, 0},
{-4, 0, 0x00ad, 2},
{ 4, 0, 0x00ae, 2},
{-4, -8, 0x409f, 0},
{ 4, -8, 0x408f, 0},
{-4, 0, 0x408d, 2},
{ 4, 0, 0x408c, 2},
{-4, -8, 0x403b, 0},
{ 4, -8, 0x402b, 0},
{-4, 0, 0x4029, 2},
{ 4, 0, 0x4028, 2},
{ 4, -8, 0x403d, 0},
{12, -8, 0x403c, 0},
{-4, 0, 0x40ab, 2},
{ 4, 0, 0x40aa, 2},
{ 4, -8, 0x403f, 0},
{12, -8, 0x403e, 0},
{-4, 0, 0x40ae, 2},
{ 4, 0, 0x40ad, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kSnapDragon_Dmd[sprite_graphics[k] * 4], 4, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_22_Ropa(int k) { // 869e1f
Ropa_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_subtype2[k]++;
sprite_graphics[k] = sprite_subtype2[k] >> 3 & 3;
switch(sprite_ai_state[k]) {
case 0: // stationary
if (!sprite_delay_main[k]) {
Sprite_ApplySpeedTowardsLink(k, 16);
sprite_z_vel[k] = (GetRandomNumber() & 15) + 20;
sprite_ai_state[k]++;
}
break;
case 1: // pounce
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k))
Sprite_ZeroVelocity_XY(k);
Sprite_MoveZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_delay_main[k] = 48;
sprite_ai_state[k] = 0;
}
break;
}
}
void Ropa_Draw(int k) { // 869ee5
static const DrawMultipleData kRopa_Dmd[12] = {
{0, -8, 0x0026, 0},
{8, -8, 0x0027, 0},
{0, 0, 0x0008, 2},
{0, -8, 0x0036, 0},
{8, -8, 0x0037, 0},
{0, 0, 0x000a, 2},
{0, -8, 0x4027, 0},
{8, -8, 0x4026, 0},
{0, 0, 0x4008, 2},
{0, -8, 0x4037, 0},
{8, -8, 0x4036, 0},
{0, 0, 0x4008, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kRopa_Dmd[sprite_graphics[k] * 3], 3, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_11_Hinox(int k) { // 869f05
Hinox_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_F[k]) {
Hinox_FaceLink(k);
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 48;
}
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
switch(sprite_ai_state[k]) {
case 0: // select dir
if (!sprite_delay_main[k]) {
if (!(GetRandomNumber() & 3)) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 64;
} else {
if (++sprite_C[k] == 4) {
sprite_C[k] = 0;
Hinox_FaceLink(k);
} else {
static const uint8 kHinox_RandomDirs[8] = {2, 3, 3, 2, 0, 1, 1, 0};
Hinox_SetDirection(k, kHinox_RandomDirs[sprite_D[k] * 2 + (GetRandomNumber() & 1)]);
}
}
}
break;
case 1: // walk
if (sprite_delay_main[k]) {
if (sign8(--sprite_A[k])) {
sprite_A[k] = 11;
sprite_subtype2[k]++;
}
Sprite_MoveXY(k);
if (!Sprite_CheckTileCollision(k)) {
static const uint8 kHinox_WalkGfx[4] = {6, 4, 0, 2};
sprite_graphics[k] = kHinox_WalkGfx[sprite_D[k]] + (sprite_subtype2[k] & 1);
return;
}
}
sprite_delay_main[k] = 16;
sprite_ai_state[k] = 0;
break;
case 2: // throw bomb
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 2;
return;
}
if (sprite_delay_main[k] == 32) {
static const int8 kHinox_BombX[4] = {8, -8, -13, 13};
static const int8 kHinox_BombY[4] = {-11, -11, -16, -16};
static const int8 kHinox_BombXvel[4] = {24, -24, 0, 0};
static const int8 kHinox_BombYvel[4] = {0, 0, 24, -24};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x4a, &info);
if (j >= 0) {
Sprite_TransmuteToBomb(j);
sprite_delay_aux1[j] = 64;
int i = sprite_D[k];
Sprite_SetX(j, info.r0_x + kHinox_BombX[i]);
Sprite_SetY(j, info.r2_y + kHinox_BombY[i]);
sprite_x_vel[j] = kHinox_BombXvel[i];
sprite_y_vel[j] = kHinox_BombYvel[i];
sprite_z_vel[j] = 40;
}
} else {
static const uint8 kHinox_Gfx[8] = {11, 10, 8, 9, 7, 5, 1, 3};
sprite_graphics[k] = kHinox_Gfx[sprite_D[k] + (sprite_delay_main[k] < 32 ? 4 : 0)];
}
break;
}
}
void Hinox_ThrowBomb(int k) { // 869f4a
}
void Hinox_FaceLink(int k) { // 869fe1
Hinox_SetDirection(k, Sprite_DirectionToFaceLink(k, NULL));
sprite_x_vel[k] <<= 1;
sprite_y_vel[k] <<= 1;
}
void Hinox_SetDirection(int k, uint8 dir) { // 86a004
static const int8 kHinox_Xvel[4] = {8, -8, 0, 0};
static const int8 kHinox_Yvel[4] = {0, 0, 8, -8};
sprite_D[k] = dir;
sprite_delay_main[k] = (GetRandomNumber() & 63) + 96;
sprite_ai_state[k]++;
sprite_x_vel[k] = kHinox_Xvel[dir];
sprite_y_vel[k] = kHinox_Yvel[dir];
}
void Hinox_Draw(int k) { // 86a1f9
static const DrawMultipleData kHinox_Dmd[46] = {
{ 0, -13, 0x0600, 2},
{ -8, -5, 0x0624, 2},
{ 8, -5, 0x4624, 2},
{ 0, 1, 0x0606, 2},
{ 0, -13, 0x0600, 2},
{ -8, -5, 0x0624, 2},
{ 8, -5, 0x4624, 2},
{ 0, 1, 0x4606, 2},
{ -8, -6, 0x0624, 2},
{ 8, -6, 0x4624, 2},
{ 0, 0, 0x0606, 2},
{ 0, -13, 0x0604, 2},
{ -8, -6, 0x0624, 2},
{ 8, -6, 0x4624, 2},
{ 0, 0, 0x4606, 2},
{ 0, -13, 0x0604, 2},
{ -3, -13, 0x0602, 2},
{ 0, -8, 0x060c, 2},
{ 0, 0, 0x061c, 2},
{ -3, -12, 0x0602, 2},
{ 0, -8, 0x060e, 2},
{ 0, 0, 0x061e, 2},
{ 3, -13, 0x4602, 2},
{ 0, -8, 0x460c, 2},
{ 0, 0, 0x461c, 2},
{ 3, -12, 0x4602, 2},
{ 0, -8, 0x460e, 2},
{ 0, 0, 0x461e, 2},
{-13, -16, 0x056e, 2},
{ 0, -13, 0x0600, 2},
{ -8, -5, 0x0620, 2},
{ 8, -5, 0x4624, 2},
{ 0, 1, 0x0606, 2},
{ -8, -5, 0x0624, 2},
{ 8, -5, 0x4620, 2},
{ 0, 1, 0x0606, 2},
{ 0, -13, 0x0604, 2},
{ 13, -16, 0x056e, 2},
{ -8, -11, 0x056e, 2},
{ -3, -13, 0x0602, 2},
{ 0, 0, 0x0622, 2},
{ 0, -8, 0x060c, 2},
{ 8, -11, 0x056e, 2},
{ 3, -13, 0x4602, 2},
{ 0, 0, 0x4622, 2},
{ 0, -8, 0x460c, 2},
};
PrepOamCoordsRet info;
static const uint8 kHinoxNum[12] = { 4, 4, 4, 4, 3, 3, 3, 3, 5, 5, 4, 4 };
static const uint8 kHinoxOffs[12] = { 0, 4, 8, 12, 16, 19, 22, 25, 28, 33, 38, 42 };
int j = sprite_graphics[k];
Sprite_DrawMultiple(k, &kHinox_Dmd[kHinoxOffs[j]], kHinoxNum[j], &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_23_RedBari(int k) { // 86a23d
static const int8 kBari_Xvel2[16] = {0, 8, 11, 14, 16, 14, 11, 8, 0, -8, -11, -14, -16, -14, -11, -8};
static const int8 kBari_Yvel2[16] = {-16, -14, -11, -8, 0, 8, 11, 14, 16, 14, 11, 8, 0, -9, -11, -14};
static const uint8 kBari_Gfx[2] = {0, 3};
int j;
if (sign8(sprite_C[k])) {
if (sprite_head_dir[k] != 16) {
sprite_head_dir[k]++;
} else {
sprite_x_vel[k] = 255;
sprite_subtype[k] = 255;
Sprite_CheckTileCollision2(k);
sprite_subtype[k] = 0;
if (!sprite_tiletype) {
sprite_C[k] = 0;
sprite_ignore_projectile[k] = 0;
goto set_electrocute_delay;
}
sprite_ignore_projectile[k] = sprite_tiletype;
}
return;
}
if (sprite_C[k] != 0) {
SpriteDraw_SingleSmall(k);
} else if (sprite_graphics[k] >= 2) {
SpriteDraw_SingleLarge(k);
} else {
RedBari_Draw(k);
}
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
if (sprite_delay_aux2[k])
goto recoil_from_split;
if (sprite_ai_state[k] == 2) {
static const int8 kBari_Xvel[2] = {8, -8};
sprite_ignore_projectile[k] = sprite_ai_state[k];
sprite_x_vel[k] = kBari_Xvel[frame_counter >> 1 & 1];
Sprite_MoveX(k);
if (!sprite_delay_main[k]) {
RedBari_Split(k);
sprite_state[k] = 0;
}
return;
}
Sprite_CheckDamageToAndFromLink(k);
if (!((k ^ frame_counter) & 15)) {
sprite_A[k] += (sprite_B[k] & 1) ? -1 : 1;
if (!(GetRandomNumber() & 3))
sprite_B[k]++;
}
j = sprite_A[k] & 15;
sprite_x_vel[k] = kBari_Xvel2[j];
sprite_y_vel[k] = kBari_Yvel2[j];
if (!((k ^ frame_counter) & 3 | sprite_delay_main[k])) {
recoil_from_split:
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision2(k);
}
j = sprite_C[k];
sprite_graphics[k] = (frame_counter >> 3 & 1) + kBari_Gfx[j];
if (sprite_ai_state[k]) {
if (sprite_delay_main[k]) {
sprite_graphics[k] = (frame_counter >> 1 & 2) + kBari_Gfx[j];
return;
}
sprite_ai_state[k] = 0;
} else if (sprite_delay_aux1[k]) {
return;
} else if (!(GetRandomNumber() & 1)) {
sprite_delay_main[k] = 128;
sprite_ai_state[k]++;
return;
}
set_electrocute_delay:
sprite_delay_aux1[k] = (GetRandomNumber() & 63) + 128;
}
void RedBari_Split(int k) { // 86a34e
static const int8 kRedBari_SplitX[2] = {0, 8};
static const int8 kRedBari_SplitXvel[2] = {-32, 32};
tmp_counter = 1;
do {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x23, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_flags3[j] = 0x33;
sprite_oam_flags[j] = 3;
sprite_flags4[j] = 1;
sprite_C[j] = 1;
Sprite_SetX(j, info.r0_x + kRedBari_SplitX[tmp_counter]);
sprite_x_vel[j] = kRedBari_SplitXvel[tmp_counter];
sprite_delay_aux2[j] = 8;
sprite_delay_aux1[j] = 64;
}
} while (!sign8(--tmp_counter));
}
void RedBari_Draw(int k) { // 86a3dc
static const DrawMultipleData kRedBari_Dmd[8] = {
{0, 0, 0x0022, 0},
{8, 0, 0x4022, 0},
{0, 8, 0x0032, 0},
{8, 8, 0x4032, 0},
{0, 0, 0x0023, 0},
{8, 0, 0x4023, 0},
{0, 8, 0x0033, 0},
{8, 8, 0x4033, 0},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kRedBari_Dmd[sprite_graphics[k] * 4], 4, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_13_MiniHelmasaur(int k) { // 86a409
static const uint8 kHelmasaur_Gfx[8] = {3, 4, 3, 4, 2, 2, 5, 5};
static const uint8 kHelmasaur_OamFlags[8] = {0x40, 0x40, 0, 0, 0, 0x40, 0x40, 0};
int j = sprite_subtype2[k] >> 2 & 1 | sprite_D[k] << 1;
sprite_graphics[k] = kHelmasaur_Gfx[j];
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kHelmasaur_OamFlags[j];
if (!((k ^ frame_counter) & 15)) {
uint8 x = sprite_x_vel[k];
if (sign8(x)) x = -x;
uint8 y = sprite_y_vel[k];
if (sign8(y)) y = -y;
sprite_D[k] = (x >= y) ? (sprite_x_vel[k] >> 7) : (sprite_y_vel[k] >> 7) + 2;
}
SpriteDraw_SingleLarge(k);
HelmasaurHardHatBeetleCommon(k);
}
void Sprite_26_HardhatBeetle(int k) { // 86a460
sprite_graphics[k] = sprite_subtype2[k] >> 2 & 1;
HardHatBeetle_Draw(k);
HelmasaurHardHatBeetleCommon(k);
}
void HelmasaurHardHatBeetleCommon(int k) { // 86a46d
if (Sprite_ReturnIfInactive(k))
return;
sprite_subtype2[k]++;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
if (sprite_wallcoll[k] & 15) {
if (sprite_wallcoll[k] & 3)
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
} else {
Sprite_MoveXY(k);
}
Sprite_CheckTileCollision(k);
if (!((k ^ frame_counter) & 31)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, sprite_A[k]);
sprite_B[k] = pt.y;
sprite_C[k] = pt.x;
}
if ((k ^ frame_counter) & sprite_ai_state[k])
return;
sprite_y_vel[k] += sign8(sprite_y_vel[k] - sprite_B[k]) ? 1 : -1;
sprite_x_vel[k] += sign8(sprite_x_vel[k] - sprite_C[k]) ? 1 : -1;
}
void HardHatBeetle_Draw(int k) { // 86a4f2
static const DrawMultipleData kHardHatBeetle_Dmd[4] = {
{0, -4, 0x0140, 2},
{0, 2, 0x0142, 2},
{0, -5, 0x0140, 2},
{0, 2, 0x0144, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kHardHatBeetle_Dmd[sprite_graphics[k] * 2], 2, &info);
if (sprite_flags3[k] & 0x10)
SpriteDraw_Shadow(k, &info);
}
void Sprite_15_Antifairy(int k) { // 86a50c
SpriteDraw_Antfairy(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckDamageToLink(k) && sprite_delay_main[k] == 0) {
sprite_delay_main[k] = 16;
int t = link_magic_power - 8;
if (t < 0)
t = 0;
else
sound_effect_2 = 0x1d;
link_magic_power = t;
}
Sprite_MoveXY(k);
Sprite_BounceFromTileCollision(k);
}
void Sprite_0B_Cucco(int k) { // 86a5c2
if (sprite_x_vel[k] != 0)
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | (sign8(sprite_x_vel[k]) ? 0 : 0x40);
SpriteDraw_SingleLarge(k);
if (sprite_head_dir[k] != 0) {
sprite_type[k] = 0x3d;
SpritePrep_LoadProperties(k);
sprite_subtype[k]++;
sprite_delay_main[k] = 48;
sound_effect_1 = 21;
sprite_ignore_projectile[k] = 21;
return;
}
if (sprite_state[k] == 10) {
sprite_ai_state[k] = 3;
if (submodule_index == 0) {
Chicken_IncrSubtype2(k, 3);
Cucco_DrawPANIC(k);
if (!(frame_counter & 0xf))
BawkBawk(k);
}
}
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_C[k] != 0) {
sprite_oam_flags[k] |= 0x10;
Sprite_MoveXY(k);
sprite_z[k] = 12;
sprite_ignore_projectile[k] = 12;
if (((k ^ frame_counter) & 7) == 0)
Sprite_CheckDamageToLink(k);
Chicken_IncrSubtype2(k, 4);
} else {
sprite_health[k] = 255;
if (sprite_B[k] >= 35)
Cucco_SummonAvenger(k);
if (sprite_F[k] != 0) {
sprite_F[k] = 0;
if (sprite_B[k] < 35) {
sprite_B[k]++;
BawkBawk(k);
}
sprite_ai_state[k] = 2;
}
Sprite_CheckDamageFromLink(k);
switch (sprite_ai_state[k]) {
case 0: Cucco_Calm(k); break;
case 1: Chicken_Hopping(k); break;
case 2: Cucco_Flee(k); break;
case 3: Cucco_Carried(k); break;
}
}
}
void Cucco_Calm(int k) { // 86a67f
if (sprite_delay_main[k] == 0) {
int j = GetRandomNumber() & 0xf;
sprite_x_vel[k] = kSpriteKeese_Tab2[j];
sprite_y_vel[k] = kSpriteKeese_Tab3[j];
sprite_delay_main[k] = (GetRandomNumber() & 0x1f) + 0x10;
sprite_ai_state[k]++;
}
sprite_graphics[k] = 0;
Sprite_ReturnIfLifted(k);
}
void Chicken_Hopping(int k) { // 86a6b1
if ((k ^ frame_counter) & 1 && Cucco_DoMovement_XY(k))
sprite_ai_state[k] = 0;
Sprite_MoveZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
if (sprite_delay_main[k] == 0) {
sprite_delay_main[k] = 32;
sprite_ai_state[k] = 0;
}
sprite_z_vel[k] = 10;
}
Chicken_IncrSubtype2(k, 4);
}
void Cucco_Flee(int k) { // 86a6fc
Sprite_ReturnIfLifted(k);
Cucco_DoMovement_XY(k);
sprite_z[k] = 0;
if (!((k ^ frame_counter) & 0x1f)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 16);
sprite_x_vel[k] = -pt.x;
sprite_y_vel[k] = -pt.y;
}
Chicken_IncrSubtype2(k, 5);
Cucco_DrawPANIC(k);
}
void Cucco_DrawPANIC(int k) { // 86a727
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
Sprite_DrawDistress_custom(info.x, info.y, frame_counter);
}
void Cucco_Carried(int k) { // 86a78e
Sprite_MoveZ(k);
if (Cucco_DoMovement_XY(k)) {
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_y_vel[k] = -sprite_y_vel[k];
Sprite_MoveXY(k);
Sprite_HalveSpeed_XY(k);
Sprite_HalveSpeed_XY(k);
BawkBawk(k);
}
sprite_z_vel[k]--;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_ai_state[k] = 2;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 16);
sprite_x_vel[k] = -pt.x;
sprite_y_vel[k] = -pt.y;
Chicken_IncrSubtype2(k, 5);
Cucco_DrawPANIC(k);
} else {
Chicken_IncrSubtype2(k, 4);
}
}
uint8 Cucco_DoMovement_XY(int k) { // 86a7bb
Sprite_MoveXY(k);
return Sprite_CheckTileCollision(k);
}
void Cucco_SummonAvenger(int k) { // 86a7d3
static const uint8 kChicken_Avenger[2] = {0, 0xff};
if ((k ^ frame_counter) & 0xf | player_is_indoors)
return;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0xB, &info, 10);
if (j < 0)
return;
SpriteSfx_QueueSfx3WithPan(j, 0x1e);
sprite_C[j] = 1;
uint8 t = GetRandomNumber();
uint16 x = BG2HOFS_copy2, y = BG2VOFS_copy2;
if (t & 2)
x += t, y += kChicken_Avenger[t & 1];
else
y += t, x += kChicken_Avenger[t & 1];
Sprite_SetX(j, x);
Sprite_SetY(j, y);
Sprite_ApplySpeedTowardsLink(j, 32);
BawkBawk(k);
}
void BawkBawk(int k) { // 86a84c
SpriteSfx_QueueSfx2WithPan(k, 0x30);
}
void Sprite_17_Hoarder(int k) { // 86a86c
if (sprite_ai_state[k])
Sprite_Hoarder_Frantic(k);
else
Sprite_Hoarder_Covered(k);
}
void Sprite_Hoarder_Covered(int k) { // 86a874
static const uint8 kRupeeCoveredGrab_Gfx[4] = {3, 4, 5, 4};
static const int8 kRupeeCoveredGrab_Xvel[4] = {-12, 12, 0, 0};
static const int8 kRupeeCoveredGrab_Yvel[4] = {0, 0, -12, 12};
CoveredRupeeCrab_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_graphics[k] = 0;
PointU8 pt;
uint8 dir = Sprite_DirectionToFaceLink(k, &pt);
if (sprite_delay_main[k])
goto lbl;
if ((uint8)(pt.y + 0x30) < 0x60 && (uint8)(pt.x + 0x20) < 0x40) {
sprite_delay_main[k] = 32;
lbl:sprite_x_vel[k] = kRupeeCoveredGrab_Xvel[dir];
sprite_y_vel[k] = kRupeeCoveredGrab_Yvel[dir];
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision2(k);
Sprite_CheckDamageFromLink(k);
sprite_graphics[k] = kRupeeCoveredGrab_Gfx[++sprite_subtype2[k] >> 1 & 3];
}
if (sprite_type[k] != 0x3e || link_item_gloves >= 1)
Sprite_ReturnIfLiftedPermissive(k); // note, dont ret
if (sprite_state[k] != 9) {
sprite_C[k] = (sprite_type[k] == 0x17) ? 2 : 1;
sprite_type[k] = 0xec;
sprite_oam_flags[k] &= ~1;
sprite_graphics[k] = 0;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x3e, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_flags2[j] &= ~0x80;
sprite_delay_aux2[j] = 128;
sprite_oam_flags[j] = 9;
sprite_ai_state[j] = 9;
}
}
}
void Sprite_Hoarder_Frantic(int k) { // 86a91d
static const uint8 kRupeeCrab_Gfx[4] = {0, 1, 0, 1};
static const uint8 kRupeeCrab_OamFlags[4] = {0, 0, 0x40, 0};
static const int8 kRupeeCrab_Xvel[4] = {-16, 16, -16, 16};
static const int8 kRupeeCrab_Yvel[4] = {-16, -16, 16, 16};
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageFromLink(k);
if (!sprite_delay_aux2[k])
Sprite_CheckDamageToLink(k);
int j = ++sprite_subtype2[k] >> 1 & 3;
sprite_graphics[k] = kRupeeCrab_Gfx[j];
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kRupeeCrab_OamFlags[j];
if (sprite_wallcoll[k]) {
sprite_delay_aux4[k] = 16;
j = GetRandomNumber() & 3;
sprite_x_vel[k] = kRupeeCrab_Xvel[j];
sprite_y_vel[k] = kRupeeCrab_Yvel[j];
} else {
Sprite_MoveXY(k);
}
Sprite_CheckTileCollision2(k);
if (!sprite_delay_aux4[k] && !((k ^ frame_counter) & 31)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 16);
sprite_y_vel[k] = -pt.y;
sprite_x_vel[k] = -pt.x;
}
if (frame_counter & 1)
return;
int end;
uint8 type;
if (++sprite_G[k] == 192) {
sprite_delay_main[k] = 15;
sprite_state[k] = 6;
sprite_flags2[k] += 4;
end = 1;
type = 0xd9;
} else {
if (sprite_G[k] & 15)
return;
end = 0;
type = sprite_head_dir[k] == 6 ? 0xdb : 0xd9;
}
SpriteSpawnInfo info;
j = Sprite_SpawnDynamicallyEx(k, type, &info, end);
if (j >= 0) {
sprite_head_dir[k]++;
Sprite_SetSpawnedCoordinates(j, &info);
Sprite_SetX(j, info.r0_x + 8);
sprite_z_vel[j] = 32;
sprite_delay_aux4[j] = 16;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(j, 16);
sprite_y_vel[j] = ~pt.y;
sprite_x_vel[j] = ~pt.x;
SpriteSfx_QueueSfx3WithPan(k, 0x30);
}
}
void CoveredRupeeCrab_Draw(int k) { // 86aa48
static const int8 kCoveredRupeeCrab_DrawY[12] = {0, 0, 0, -3, 0, -5, 0, -6, 0, -6, 0, -6};
static const uint8 kCoveredRupeeCrab_DrawChar[12] = {0x44, 0x44, 0xe8, 0x44, 0xe8, 0x44, 0xe6, 0x44, 0xe8, 0x44, 0xe6, 0x44};
static const uint8 kCoveredRupeeCrab_DrawFlags[12] = {0, 0xc, 3, 0xc, 3, 0xc, 3, 0xc, 3, 0xc, 0x43, 0xc};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
if (byte_7E0FC6 >= 3)
return;
OamEnt *oam = GetOamCurPtr();
uint8 r7 = (sprite_type[k] == 0x17) ? 2 : 0;
uint8 r6 = sprite_graphics[k] * 2;
for (int i = 1; i >= 0; i--, oam++) {
int j = i + r6;
uint16 x = info.x;
uint16 y = info.y + kCoveredRupeeCrab_DrawY[j];
oam->x = x;
oam->y = ClampYForOam(y);
uint8 ch = kCoveredRupeeCrab_DrawChar[j];
oam->charnum = ch + (ch == 0x44 ? r7 : 0);
oam->flags = (info.flags & ~1) | kCoveredRupeeCrab_DrawFlags[j];
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
}
void Sprite_EC_ThrownItem(int k) { // 86aae0
if (byte_7E0FC6 < 3) {
if (sort_sprites_setting && sprite_floor[k]) {
int spr_slot = 0x2c + (k & 3);
oam_cur_ptr = 0x0800 + spr_slot * 4;
oam_ext_cur_ptr = 0x0A20 + spr_slot;
}
sprite_ignore_projectile[k] = sprite_state[k];
if (sprite_C[k] >= 6) {
SpriteDraw_ThrownItem_Gigantic(k);
} else {
SpriteDraw_SingleLarge(k);
OamEnt *oam = GetOamCurPtr();
uint8 t = player_is_indoors + is_in_dark_world;
int j = sprite_C[k];
oam->charnum = kThrowableScenery_Char[j + ((t >= 2) ? 6 : 0)];
oam->flags = (oam->flags & 0xf0) | kThrowableScenery_Flags[j];
sprite_oam_flags[k] = (sprite_oam_flags[k] & 0xc0) | (oam->flags & 0xf);
}
}
if (sprite_state[k] == 9) {
if (Sprite_ReturnIfInactive(k))
return;
ThrowableScenery_InteractWithSpritesAndTiles(k);
}
}
void SpriteDraw_ThrownItem_Gigantic(int k) { // 86ab76
PrepOamCoordsRet info;
sprite_oam_flags[k] = kThrowableScenery_DrawLarge_OamFlags[sprite_C[k] - 6];
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
for (int i = 3; i >= 0; i--, oam++) {
uint16 x = info.x + kThrowableScenery_DrawLarge_X[i];
uint16 y = info.y + kThrowableScenery_DrawLarge_Y[i];
oam->x = x;
oam->y = (uint16)(y + 0x10) < 0x100 ? y : 0xf0;
oam->charnum = 0x4a;
oam->flags = kThrowableScenery_DrawLarge_Flags[i] | info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
Oam_AllocateFromRegionB(12);
oam = GetOamCurPtr();
info.y = Sprite_GetY(k) - BG2VOFS_copy2;
for (int i = 2; i >= 0; i--, oam++) {
uint16 x = info.x + kThrowableScenery_DrawLarge_X2[i];
uint16 y = info.y + 12;
oam->x = x;
oam->y = (uint16)(y + 0x10) < 0x100 ? y : 0xf0;
oam->charnum = 0x6c;
oam->flags = 0x24;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
}
void ThrowableScenery_ScatterIntoDebris(int k) { // 86ac41
if (!sign8(sprite_C[k]) && sprite_C[k] >= 6) {
for (int i = 3; i >= 0; i--) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xec, &info);
if (j >= 0) {
sprite_z[j] = sprite_z[k];
Sprite_SetX(j, info.r0_x + kScatterDebris_X[i]);
Sprite_SetY(j, info.r2_y + kScatterDebris_Y[i]);
sprite_C[j] = 1;
Sprite_ScheduleForBreakage(j);
sprite_oam_flags[j] = (sprite_C[k] < 7) ? 12 : 0;
}
}
sprite_state[k] = 0;
} else {
sprite_state[k] = 0;
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
int j = 29;
while (garnish_type[j--] && j >= 0) {}
j++;
garnish_type[j] = 22;
garnish_active = 22;
garnish_x_lo[j] = sprite_x_lo[k];
garnish_x_hi[j] = sprite_x_hi[k];
uint16 y = Sprite_GetY(k) - sprite_z[k] + 0x10;
garnish_y_lo[j] = (uint8)y;
garnish_y_hi[j] = (uint8)(y >> 8);
garnish_oam_flags[j] = info.flags;
garnish_floor[j] = sprite_floor[k];
garnish_countdown[j] = 31;
garnish_sprite[j] = sprite_C[k];
}
}
void Sprite_TransmuteToBomb(int k) { // 86ad50
sprite_type[k] = 0x4a;
sprite_C[k] = 1;
sprite_delay_aux1[k] = 255;
sprite_flags3[k] = 0x18;
sprite_oam_flags[k] = 8;
sprite_health[k] = 0;
}
void Sprite_28_DarkWorldHintNPC(int k) { // 86ad6f
StoryTeller_1_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (!sprite_delay_main[k])
sprite_graphics[k] = frame_counter >> 4 & 1;
int type = sprite_subtype2[k];
switch(sprite_subtype2[k]) {
case 0:
switch (sprite_ai_state[k]) {
case 0: DarkWorldHintNPC_Idle(k); break;
case 1:
if (choice_in_multiselect_box == 0 && DarkWorldHintNPC_HandlePayment()) {
Sprite_ShowMessageUnconditional(0xff);
sprite_ai_state[k] = 2;
} else {
Sprite_ShowMessageUnconditional(0x100);
sprite_ai_state[k] = 0;
}
break;
case 2: DarkWorldHintNPC_RestoreHealth(k); break;
}
break;
case 1:
switch (sprite_ai_state[k]) {
case 0: DarkWorldHintNPC_Idle(k); break;
case 1:
if (choice_in_multiselect_box == 0 && DarkWorldHintNPC_HandlePayment()) {
Sprite_ShowMessageUnconditional(0x101);
sprite_ai_state[k] = 2;
} else {
Sprite_ShowMessageUnconditional(0x100);
sprite_ai_state[k] = 0;
}
break;
case 2: DarkWorldHintNPC_RestoreHealth(k); break;
}
break;
case 2:
switch (sprite_ai_state[k]) {
case 0: DarkWorldHintNPC_Idle(k); break;
case 1:
if (choice_in_multiselect_box == 0 && DarkWorldHintNPC_HandlePayment()) {
Sprite_ShowMessageUnconditional(0x102);
sprite_ai_state[k] = 2;
} else {
Sprite_ShowMessageUnconditional(0x100);
sprite_ai_state[k] = 0;
}
break;
case 2: DarkWorldHintNPC_RestoreHealth(k); break;
}
break;
case 3:
if (sprite_delay_main[k] == 0) {
if ((frame_counter & 0x3f) == 0)
sprite_oam_flags[k] ^= 0x40;
if (GetRandomNumber() == 0)
sprite_delay_main[k] = 32;
}
Sprite_ShowSolicitedMessage(k, 0x149);
break;
case 4:
sprite_graphics[k] = frame_counter >> 1 & 1;
Sprite_MoveZ(k);
if (sign8(sprite_z[k]))
sprite_z[k] = 0;
sprite_z_vel[k] += (sprite_z[k] >= 4) ? -1 : 1;
switch (sprite_ai_state[k]) {
case 0: DarkWorldHintNPC_Idle(k); break;
case 1:
if (choice_in_multiselect_box == 0 && DarkWorldHintNPC_HandlePayment()) {
Sprite_ShowMessageUnconditional(0x103);
sprite_ai_state[k] = 2;
} else {
Sprite_ShowMessageUnconditional(0x100);
sprite_ai_state[k] = 0;
}
break;
case 2: DarkWorldHintNPC_RestoreHealth(k); break;
}
break;
}
}
void DarkWorldHintNPC_Idle(int k) { // 86ada7
if (Sprite_ShowSolicitedMessage(k, 0xfe) & 0x100)
sprite_ai_state[k] = 1;
}
void DarkWorldHintNPC_RestoreHealth(int k) { // 86adb5
link_hearts_filler = 0xa0;
sprite_ai_state[k] = 0;
}
bool DarkWorldHintNPC_HandlePayment() { // 86aeab
if (link_rupees_goal < 20)
return false;
link_rupees_goal -= 20;
return true;
}
void StoryTeller_1_Draw(int k) { // 86af1a
static const DrawMultipleData kStoryTeller_Dmd[10] = {
{0, 0, 0x0a4a, 2},
{0, 0, 0x4a6e, 2},
{0, 0, 0x0a24, 2},
{0, 0, 0x4a24, 2},
{0, 0, 0x0804, 2},
{0, 0, 0x4804, 2},
{0, 0, 0x0a6a, 2},
{0, 0, 0x0a6c, 2},
{0, 0, 0x0a0e, 2},
{0, 0, 0x0a2e, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kStoryTeller_Dmd[sprite_subtype2[k] * 2 + sprite_graphics[k]], 1, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_2E_FluteKid(int k) { // 86af3b
switch (sprite_head_dir[k]) {
case 0:
switch (sprite_subtype2[k]) {
case 0: FluteKid_Human(k); break;
case 1: Sprite_FluteKid_Stumpy(k); break;
}
break;
case 1: Sprite_FluteKid_Quaver(k); break;
}
}
void FluteKid_Human(int k) { // 86af51
if (sprite_ai_state[k] != 3)
sprite_C[k] = FluteBoy_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_C[k] && !sprite_B[k]) {
sound_effect_ambient = 11;
sprite_B[k] = 11;
}
sprite_graphics[k] = frame_counter >> 5 & 1;
switch (sprite_ai_state[k]) {
case 0: // wait
if (link_item_flute >= 2 || FluteBoy_CheckIfPlayerClose(k)) {
sprite_ai_state[k] = 1;
sprite_D[k]++;
byte_7E0FDD++;
sprite_delay_main[k] = 176;
flag_is_link_immobilized = 1;
}
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 25;
FluteKid_SpawnQuaver(k);
}
break;
case 1: // prep phase out
flag_is_link_immobilized = 1;
if (!sprite_delay_main[k]) {
TS_copy = 2;
CGADSUB_copy = 48;
BYTE(palette_filter_countdown) = 0;
BYTE(darkening_or_lightening_screen) = 0;
Palette_AssertTranslucencySwap();
sprite_ai_state[k] = 2;
sound_effect_ambient = 128;
SpriteSfx_QueueSfx2WithPan(k, 0x33);
}
break;
case 2: // phase out
if (!(frame_counter & 15)) {
PaletteFilter_SP5F();
if (!BYTE(palette_filter_countdown))
sprite_ai_state[k] = 3;
}
break;
case 3: // phased out
PaletteFilter_RestoreSP5F();
Palette_RevertTranslucencySwap();
sprite_state[k] = 0;
flag_is_link_immobilized = 0;
break;
}
}
void Sprite_FluteKid_Stumpy(int k) { // 86b040
static const int8 kFluteAardvark_Gfx[20] = {
1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, -1,
};
static const int8 kFluteAardvark_Delay[19] = {
-1, -1, -1, 16, 2, 12, 6, 8, 10, 4, 14, 2, 10, 6, 6, 10, 2, 14, 2,
};
FluteAardvark_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch (sprite_ai_state[k]) {
case 0: //
switch (link_item_flute & 3) {
case 0: // supplicate
if (Sprite_ShowSolicitedMessage(k, 0xe5) & 0x100)
sprite_ai_state[k] = 1;
break;
case 1: // give me flute
Sprite_ShowSolicitedMessage(k, 0xe8);
break;
case 2: // thanks
sprite_graphics[k] = 1;
if (Sprite_ShowSolicitedMessage(k, 0xe9) & 0x100)
sprite_ai_state[k] = 3;
break;
case 3: // already did
sprite_graphics[k] = 3;
break;
}
break;
case 1: //
if (!choice_in_multiselect_box) {
Sprite_ShowMessageUnconditional(0xe6);
sprite_ai_state[k] = 2;
} else {
Sprite_ShowMessageUnconditional(0xe7);
sprite_ai_state[k] = 0;
}
break;
case 2: // grant shovel
item_receipt_method = 0;
Link_ReceiveItem(0x13, 0);
sprite_ai_state[k] = 0;
break;
case 3: // wait for music
if (hud_cur_item == kHudItem_Flute && joypad1H_last & 0x40) {
sprite_ai_state[k] = 4;
music_control = 0xf2;
sound_effect_1 = 0;
sound_effect_ambient = 23;
flag_is_link_immobilized++;
}
break;
case 4: //
if (!sprite_delay_main[k]) {
if (sprite_A[k] >= 3)
SpriteSfx_QueueSfx2WithPan(k, 0x33);
int j = sprite_A[k]++;
if (kFluteAardvark_Gfx[j] >= 0) {
sprite_graphics[k] = kFluteAardvark_Gfx[j];
sprite_delay_main[k] = kFluteAardvark_Delay[j];
} else {
music_control = 0xf3;
sprite_ai_state[k] = 5;
flag_is_link_immobilized = 0;
}
}
break;
case 5: // done
sprite_graphics[k] = 3;
sram_progress_indicator_3 |= 8;
break;
}
}
void Sprite_FluteKid_Quaver(int k) { // 86b173
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXY(k);
Sprite_MoveZ(k);
if (!sprite_delay_main[k])
sprite_state[k] = 0;
if (!(frame_counter & 1))
sprite_x_vel[k] += (frame_counter >> 5 ^ cur_object_index) & 1 ? -1 : 1;
}
void FluteKid_SpawnQuaver(int k) { // 86b1a5
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x2e, &info);
if (j >= 0) {
Sprite_SetX(j, info.r0_x + 4);
Sprite_SetY(j, info.r2_y - 4);
sprite_head_dir[j] = 1;
sprite_z_vel[j] = 8;
sprite_delay_main[j] = 96;
sprite_ignore_projectile[j] = 96;
}
}
void Sprite_1A_Smithy(int k) { // 86b1ee
switch (sprite_subtype2[k]) {
case 0: Smithy_Main(k); break;
case 1: Smithy_Spark(k); break;
case 2: Smithy_Frog(k); break;
case 3: Smithy_Homecoming(k); break;
}
}
void Smithy_Homecoming(int k) { // 86b1fd
ReturningSmithy_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch(sprite_ai_state[k]) {
case 0: { // ApproachTheBench
static const int8 kReturningSmithy_Delay[3] = {104, 12, 0};
static const int8 kReturningSmithy_Dir[3] = {0, 2, -1};
static const int8 kReturningSmithy_Xvel[4] = {0, 0, -13, 13};
static const int8 kReturningSmithy_Yvel[4] = {-13, 13, 0, 0};
Sprite_MoveXY(k);
sprite_graphics[k] = frame_counter >> 3 & 1;
if (sprite_delay_main[k])
return;
int j = sprite_A[k]++;
sprite_delay_main[k] = kReturningSmithy_Delay[j];
if ((j = kReturningSmithy_Dir[j]) >= 0) {
sprite_D[k] = j;
sprite_x_vel[k] = kReturningSmithy_Xvel[j];
sprite_y_vel[k] = kReturningSmithy_Yvel[j];
} else {
sprite_ai_state[k] = 1;
}
break;
}
case 1: // Thankful
Sprite_BehaveAsBarrier(k);
Sprite_ShowSolicitedMessage(k, 0xe3);
flag_is_link_immobilized = 0;
sprite_D[k] = 1;
sram_progress_indicator_3 |= 32;
break;
}
}
void Smithy_Frog(int k) { // 86b274
SmithyFrog_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
sprite_z_vel[k] -= 2;
Sprite_MoveZ(k);
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 16;
}
if (!sprite_ai_state[k]) {
sprite_D[k] = 1;
if (Sprite_ShowSolicitedMessage(k, 0xe1) & 0x100)
sprite_ai_state[k] = 1;
} else {
follower_indicator = 7;
LoadFollowerGraphics();
Sprite_BecomeFollower(k); // zelda bug: doesn't save X
sprite_state[k] = 0;
}
}
void ReturningSmithy_Draw(int k) { // 86b308
static const DrawMultipleData kReturningSmithy_Dmd[8] = {
{0, 0, 0x4122, 2},
{0, 0, 0x0122, 2},
{0, 0, 0x4122, 2},
{0, 0, 0x0122, 2},
{0, 0, 0x0122, 2},
{0, 0, 0x0122, 2},
{0, 0, 0x4122, 2},
{0, 0, 0x4122, 2},
};
static const uint8 kReturningSmithy_Dma[8] = {0xc0, 0xc0, 0xa0, 0xa0, 0x80, 0x60, 0x80, 0x60};
int j = sprite_D[k] * 2 + sprite_graphics[k];
PrepOamCoordsRet info;
BYTE(dma_var7) = kReturningSmithy_Dma[j];
Sprite_DrawMultiplePlayerDeferred(k, &kReturningSmithy_Dmd[j], 1, &info);
SpriteDraw_Shadow(k, &info);
}
void SmithyFrog_Draw(int k) { // 86b339
static const DrawMultipleData kSmithyFrog_Dmd[1] = {
{0, 0, 0x00c8, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, kSmithyFrog_Dmd, 1, &info);
SpriteDraw_Shadow(k, &info);
}
void Smithy_Main(int k) { // 86b34e
Smithy_Draw(k);
sprite_z_vel[k] -= 2;
Sprite_MoveZ(k);
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
}
if (Sprite_ReturnIfInactive(k))
return;
int j = sprite_ai_state[sprite_E[k]];
int i = sprite_ai_state[k];
if ((j == 5 || j == 7 || j == 9 || i == 5 || i == 7 || i == 9 || (i | j) == 0) && sprite_B[k]-- == 0) {
static const uint8 kSmithy_Gfx[8] = {0, 1, 2, 3, 3, 2, 1, 0};
static const uint8 kSmithy_B[8] = {24, 4, 1, 16, 16, 5, 10, 16};
j = sprite_A[k];
sprite_A[k] = j + 1 & 7;
sprite_graphics[k] = kSmithy_Gfx[j];
sprite_B[k] = kSmithy_B[j];
if (j == 1)
sprite_z_vel[k] = 16;
if (j == 3) {
Smithy_SpawnSpark(k);
SpriteSfx_QueueSfx2WithPan(k, 0x5);
}
}
switch(sprite_ai_state[k]) {
case 0: // ConversationStart
sprite_C[k] = 0;
if (follower_indicator != 8) {
if (Smithy_ListenForHammer(k)) {
Sprite_ShowMessageUnconditional(0xe4);
sprite_delay_aux1[k] = 96;
sprite_C[k]++;
} else if (sram_progress_indicator_3 & 0x20) {
if (Sprite_ShowSolicitedMessage(k, 0xd8) & 0x100) {
sprite_ai_state[k]++;
sprite_C[k]++;
}
} else {
Sprite_ShowSolicitedMessage(k, 0xdf);
}
} else {
if (BYTE(link_y_coord) < 0xc2) {
Sprite_ShowMessageUnconditional(0xe0);
sprite_ai_state[k] = 10;
flag_is_link_immobilized++;
}
}
break;
case 1: // ProvideTemperingChoice
if (!choice_in_multiselect_box) {
Sprite_ShowMessageUnconditional(0xd9);
sprite_ai_state[k] = 2;
} else {
Sprite_ShowMessageUnconditional(0xdc);
sprite_ai_state[k] = 0;
}
break;
case 2: // HandleTemperingChoice
if (choice_in_multiselect_box == 0) {
if (link_sword_type < 3) {
Sprite_ShowMessageUnconditional(0xda);
sprite_ai_state[k] = 3;
} else {
Sprite_ShowMessageUnconditional(0xdb);
sprite_ai_state[k] = 0;
}
} else {
Sprite_ShowMessageUnconditional(0xdc);
sprite_ai_state[k] = 0;
}
break;
case 3: // HandleTemperingCost
if (choice_in_multiselect_box || link_rupees_goal < 10) {
Sprite_ShowMessageUnconditional(0xdc);
sprite_ai_state[k] = 0;
} else {
link_rupees_goal -= 10;
Sprite_ShowMessageUnconditional(0xdd);
sprite_ai_state[sprite_E[k]] = 5;
sprite_ai_state[k] = 5;
flag_overworld_area_did_change = 0;
link_sword_type = 255;
sram_progress_indicator_3 |= 128;
}
break;
case 4: // TemperingSword
case 5: //
sprite_C[k] = 0;
if (Smithy_ListenForHammer(k)) {
Sprite_ShowMessageUnconditional(0xe4);
sprite_delay_aux1[k] = 96;
sprite_C[k]++;
} else if (flag_overworld_area_did_change) {
if (Sprite_ShowSolicitedMessage(k, 0xde) & 0x100) {
sprite_ai_state[k]++;
sprite_graphics[k] = 4;
}
} else {
Sprite_ShowSolicitedMessage(k, 0xe2);
}
break;
case 6: // Smithy_GiveTemperedSword
sprite_ai_state[k] = 0;
sprite_ai_state[sprite_E[k]] = 0;
item_receipt_method = 0;
Link_ReceiveItem(2, 0);
sram_progress_indicator_3 &= ~0x80;
break;
case 7: //
case 8: //
case 9: //
break;
case 10: { // Smithy_SpawnFriend
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x1a, &info);
if (j >= 0) {
Sprite_SetX(j, link_x_coord);
Sprite_SetY(j, link_y_coord);
sprite_subtype2[j] = 3;
sprite_ignore_projectile[j] = 3;
}
sprite_ai_state[k] = 11;
follower_indicator = 0;
sprite_graphics[k] = 4;
break;
}
case 11: // Smithy_CopiouslyThankful
Sprite_ShowSolicitedMessage(k, 0xe3);
break;
}
}
bool Smithy_ListenForHammer(int k) { // 86b43d
return sprite_delay_aux1[k] == 0 && hud_cur_item == kHudItem_Hammer && (link_item_in_hand & 2) && player_handler_timer == 2 && Sprite_CheckDamageToLink_same_layer(k);
}
int Smithy_SpawnDwarfPal(int k) { // 86b5a6
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x1a, &info);
if (j < 0)
return j;
Sprite_SetX(j, info.r0_x);
Sprite_SetY(j, info.r2_y);
sprite_x_lo[j] += 0x2C;
sprite_D[j] = 1;
sprite_A[j] = 4;
sprite_ignore_projectile[j] = 4;
return j;
}
void Smithy_Draw(int k) { // 86b673
static const DrawMultipleData kSmithy_Dmd[20] = {
{ 1, 0, 0x4040, 2},
{-11, -10, 0x4060, 2},
{ -1, 0, 0x0040, 2},
{ 11, -10, 0x0060, 2},
{ 1, 0, 0x4040, 2},
{ -3, -14, 0x4044, 2},
{ -1, 0, 0x0040, 2},
{ 3, -14, 0x0044, 2},
{ 1, 0, 0x4042, 2},
{ 11, -10, 0x0060, 2},
{ -1, 0, 0x0042, 2},
{-11, -10, 0x4060, 2},
{ 1, 0, 0x4042, 2},
{ 13, 2, 0x4062, 2},
{ -1, 0, 0x0042, 2},
{-13, 2, 0x0062, 2},
{ 0, 0, 0x4064, 2},
{ 0, 0, 0x4062, 2},
{ 0, 0, 0x0064, 2},
{ 0, 0, 0x0064, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kSmithy_Dmd[sprite_graphics[k] * 4 + sprite_D[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Smithy_Spark(int k) { // 86b6a3
static const int8 kSmithySpark_Gfx[7] = {0, 1, 2, 1, 2, 1, -1};
static const int8 kSmithySpark_Delay[6] = {4, 1, 3, 2, 1, 1};
SmithySpark_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_delay_main[k]) {
int j = sprite_A[k];
sprite_A[k] = j + 1 & 7;
if (sign8(kSmithySpark_Gfx[j])) {
sprite_state[k] = 0;
return;
}
sprite_graphics[k] = kSmithySpark_Gfx[j];
sprite_delay_main[k] = kSmithySpark_Delay[j];
}
}
void Smithy_SpawnSpark(int k) { // 86b6cd
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x1a, &info);
if (j >= 0) {
Sprite_SetX(j, info.r0_x);
Sprite_SetY(j, info.r2_y);
sprite_x_lo[j] += sprite_D[k] ? -15 : 15;
sprite_y_lo[j] += 2;
sprite_subtype2[j] = 1;
}
}
void SmithySpark_Draw(int k) { // 86b72c
Oam_AllocateFromRegionB(8);
static const DrawMultipleData kSmithySpark_Dmd[6] = {
{ 0, 3, 0x41aa, 2},
{ 0, -1, 0x41aa, 2},
{-4, 0, 0x0190, 0},
{12, 0, 0x4190, 0},
{-5, -2, 0x0191, 0},
{13, -2, 0x0191, 0},
};
Sprite_DrawMultiple(k, &kSmithySpark_Dmd[sprite_graphics[k] * 2], 2, NULL);
}
void Sprite_1B_Arrow(int k) { // 86b754
int j;
static const int8 kEnemyArrow_Xvel[8] = {0, 0, 16, 16, 0, 0, -16, -16};
static const int8 kEnemyArrow_Yvel[8] = {16, 16, 0, 0, -16, -16, 0, 0};
static const uint8 kEnemyArrow_Dirs[4] = {0, 2, 1, 3};
EnemyArrow_Draw(k);
if (Sprite_ReturnIfPaused(k))
return;
if (sprite_state[k] == 9) {
j = sprite_delay_main[k];
if (j != 0) {
if (--j == 0) {
sprite_state[k] = 0;
} else if (j >= 32 && !(j & 1)) {
j = (frame_counter << 1 & 4) | sprite_D[k];
sprite_x_vel[k] = kEnemyArrow_Xvel[j];
sprite_y_vel[k] = kEnemyArrow_Yvel[j];
Sprite_MoveXY(k);
}
return;
}
Sprite_CheckDamageToLink_same_layer(k);
if (sprite_E[k] == 0 && Sprite_CheckTileCollision(k)) {
if (sprite_A[k]) {
SpriteSfx_QueueSfx2WithPan(k, 0x5);
Sprite_ScheduleForBreakage(k);
Sprite_PlaceWeaponTink(k);
} else {
sprite_delay_main[k] = 48;
sprite_A[k] = 2;
SpriteSfx_QueueSfx2WithPan(k, 0x8);
}
} else {
Sprite_MoveXY(k);
}
} else {
if (sprite_ai_state[k] == 0) {
Sprite_ApplyRicochet(k);
sprite_z_vel[k] = 24;
sprite_delay_main[k] = 255;
sprite_ai_state[k]++;
sprite_hit_timer[k] = 0;
}
sprite_D[k] = kEnemyArrow_Dirs[sprite_delay_main[k] >> 3 & 3];
Sprite_MoveZ(k);
Sprite_MoveXY(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k]))
sprite_state[k] = 0;
}
}
void EnemyArrow_Draw(int k) { // 86b867
static const int16 kEnemyArrow_Draw_X[8] = {-8, 0, 0, 8, 0, 0, 0, 0};
static const int16 kEnemyArrow_Draw_Y[8] = {0, 0, 0, 0, -8, 0, 0, 8};
static const uint8 kEnemyArrow_Draw_Char[32] = {
0x3a, 0x3d, 0x3d, 0x3a, 0x2a, 0x2b, 0x2b, 0x2a, 0x7c, 0x6c, 0x6c, 0x7c, 0x7b, 0x6b, 0x6b, 0x7b,
0x3a, 0x3b, 0x3b, 0x3a, 0x2a, 0x3c, 0x3c, 0x2a, 0x81, 0x80, 0x80, 0x81, 0x91, 0x90, 0x90, 0x91,
};
static const uint8 kEnemyArrow_Draw_Flags[32] = {
8, 8, 0x48, 0x48, 8, 8, 0x88, 0x88, 9, 0x49, 9, 0x49, 9, 0x89, 9, 0x89,
8, 0x88, 0xc8, 0x48, 8, 8, 0x88, 0x88, 0x49, 0x49, 9, 9, 0x89, 0x89, 9, 9,
};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
uint8 r6 = sprite_D[k] * 2, r7 = sprite_A[k] * 8;
for (int i = 1; i >= 0; i--, oam++) {
int j = r6 + i;
uint16 x = info.x + kEnemyArrow_Draw_X[j];
uint16 y = info.y + kEnemyArrow_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kEnemyArrow_Draw_Char[j + r7];
oam->flags = kEnemyArrow_Draw_Flags[j + r7] | info.flags;
bytewise_extended_oam[oam - oam_buf] = (x >> 8 & 1);
}
}
void Sprite_1E_CrystalSwitch(int k) { // 86b8d0
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0xe | kCrystalSwitchPal[orange_blue_barrier_state & 1];
Oam_AllocateDeferToPlayer(k);
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Sprite_RepelDash();
}
if (sprite_delay_main[k] == 0) {
Sprite_GarnishSpawn_Sparkle(k, frame_counter & 7, GetRandomNumber() & 7);
sprite_delay_main[k] = 31;
}
if (sprite_F[k] == 0) {
if (sign8(button_b_frames - 9))
Sprite_CheckDamageFromLink(k);
} else if (sprite_F[k]-- == 11) {
orange_blue_barrier_state ^= 1;
submodule_index = 22;
SpriteSfx_QueueSfx3WithPan(k, 0x25);
}
}
void Sprite_1F_SickKid(int k) { // 86b94c
static const int8 kBugNetKid_Gfx[8] = {0, 1, 0, 1, 0, 1, 2, -1};
static const uint8 kBugNetKid_Delay[7] = {8, 12, 8, 12, 8, 96, 16};
int j;
BugNetKid_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch (sprite_ai_state[k]) {
case 0: // resting
if (Sprite_CheckIfLinkIsBusy() || !Sprite_CheckDamageToLink_same_layer(k))
return;
if ((link_bottle_info[0] | link_bottle_info[1] | link_bottle_info[2] | link_bottle_info[3]) < 2) {
Sprite_ShowSolicitedMessage(k, 0x104);
} else {
flag_is_link_immobilized++;
sprite_ai_state[k] = 1;
}
break;
case 1: // perk
if (sprite_delay_main[k])
return;
j = sprite_A[k];
if (kBugNetKid_Gfx[j] >= 0) {
sprite_graphics[k] = kBugNetKid_Gfx[j];
sprite_delay_main[k] = kBugNetKid_Delay[j];
sprite_A[k] = j + 1;
} else {
Sprite_ShowMessageUnconditional(0x105);
sprite_ai_state[k] = 2;
}
break;
case 2: // grant
item_receipt_method = 0;
Link_ReceiveItem(0x21, 0);
flag_is_link_immobilized = 0;
sprite_ai_state[k] = 3;
break;
case 3: // back to rest
sprite_graphics[k] = 1;
Sprite_ShowSolicitedMessage(k, 0x106);
break;
}
}
void Sprite_21_WaterSwitch(int k) { // 86b9fa
PushSwitch_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch(sprite_ai_state[k]) {
case 0:
if (sprite_C[k]) {
if (!--sprite_B[k])
sprite_ai_state[k] = 1;
if (!(frame_counter & 3))
SpriteSfx_QueueSfx2WithPan(k, 0x22);
} else {
sprite_B[k] = 48;
}
break;
case 1:
if (!sprite_delay_main[k]) {
static const uint8 kPushSwitch_Delay[10] = {40, 6, 3, 3, 3, 5, 1, 1, 3, 12};
static const uint8 kPushSwitch_Dir[10] = {0, 1, 2, 3, 4, 5, 5, 6, 7, 6};
int j = ++sprite_A[k];
if (j == 10) {
sprite_ai_state[k] = 2;
dung_flag_statechange_waterpuzzle++;
SpriteSfx_QueueSfx3WithPan(k, 0x25);
} else {
sprite_delay_main[k] = kPushSwitch_Delay[j];
sprite_D[k] = kPushSwitch_Dir[j];
SpriteSfx_QueueSfx2WithPan(k, 0x22);
}
}
break;
case 2:
break;
}
}
void PushSwitch_Draw(int k) { // 86bb22
static const OamEntSigned kPushSwitch_Oam[40] = {
{ 4, 20, 0xdc, 0x20},
{ 4, 12, 0xdd, 0x20},
{ 4, 12, 0xdd, 0x20},
{ 4, 12, 0xdd, 0x20},
{ 0, 0, 0xca, 0x20},
{ 3, 12, 0xdd, 0x20},
{ 3, 20, 0xdc, 0x20},
{ 3, 20, 0xdc, 0x20},
{ 3, 20, 0xdc, 0x20},
{ 0, 0, 0xca, 0x20},
{ -8, 8, 0xea, 0x20},
{ 0, 8, 0xeb, 0x20},
{ -8, 16, 0xfa, 0x20},
{ 0, 16, 0xfb, 0x20},
{ 0, 0, 0xca, 0x20},
{-12, 4, 0xcc, 0x20},
{ -4, 4, 0xcd, 0x20},
{ -4, 4, 0xcd, 0x20},
{ -4, 4, 0xcd, 0x20},
{ 0, 0, 0xca, 0x20},
{-10, 4, 0xcc, 0x20},
{ -4, 4, 0xcd, 0x20},
{ -4, 4, 0xcd, 0x20},
{ -4, 4, 0xcd, 0x20},
{ 0, 0, 0xca, 0x20},
{ -8, 4, 0xcc, 0x20},
{ -4, 4, 0xcd, 0x20},
{ -4, 4, 0xcd, 0x20},
{ -4, 4, 0xcd, 0x20},
{ 0, 0, 0xca, 0x20},
{ 4, 3, 0xe2, 0x20},
{ -6, 4, 0xcc, 0x20},
{ -4, 4, 0xcd, 0x20},
{ -4, 4, 0xcd, 0x20},
{ 0, 0, 0xca, 0x20},
{ 4, 3, 0xf1, 0x20},
{ -6, 4, 0xcc, 0x20},
{ -4, 4, 0xcd, 0x20},
{ -4, 4, 0xcd, 0x20},
{ 0, 0, 0xca, 0x20},
};
static const uint8 kPushSwitch_WH[16] = {8, 6, 0x10, 0x10, 0x10, 8, 0x10, 8, 0x10, 8, 0x10, 8, 0x10, 3, 0x10, 8};
Oam_AllocateDeferToPlayer(k);
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
uint8 flags;
sprite_oam_flags[k] = flags = overworld_palette_swap_flag ? sprite_oam_flags[k] | 0xe : sprite_oam_flags[k] & ~0xe;
uint8 r1 = sprite_B[k] >> 2 & 3;
oam_cur_ptr += 4, oam_ext_cur_ptr += 1;
OamEnt *oam = GetOamCurPtr();
memcpy(oam, &kPushSwitch_Oam[sprite_D[k] * 5], 20);
uint8 xv = -r1 + BYTE(dungmap_var7);
uint8 yv = HIBYTE(dungmap_var7) - (r1 >> 1);
oam[0].x += xv;
oam[1].x += xv;
oam[2].x += xv;
oam[3].x += xv;
oam[4].x += BYTE(dungmap_var7);
oam[0].y += yv;
oam[1].y += yv;
oam[2].y += yv;
oam[3].y += yv;
oam[4].y += HIBYTE(dungmap_var7);
oam[0].flags |= flags;
oam[1].flags |= flags;
oam[2].flags |= flags;
oam[3].flags |= flags;
oam[4].flags |= flags;
uint8 *ext = &g_ram[oam_ext_cur_ptr];
ext[0] = ext[1] = ext[2] = ext[3] = 0;
ext[4] = 2;
Sprite_CorrectOamEntries(k, 4, 0xff);
if (sprite_floor[k] == link_is_on_lower_level) {
sprite_C[k] = 0;
int d = sprite_D[k];
int x = Sprite_GetX(k) + (int8)kPushSwitch_Oam[d * 4].x;
int y = Sprite_GetY(k) + (int8)kPushSwitch_Oam[d * 4].y;
SpriteHitBox hb;
hb.r4_spr_xlo = x;
hb.r10_spr_xhi = x >> 8;
hb.r5_spr_ylo = y;
hb.r11_spr_yhi = y >> 8;
hb.r6_spr_xsize = kPushSwitch_WH[d * 2 + 0];
hb.r7_spr_ysize = kPushSwitch_WH[d * 2 + 1];
Link_SetupHitBox(&hb);
if (CheckIfHitBoxesOverlap(&hb)) {
uint16 oldy = Sprite_GetY(k);
Sprite_SetY(k, oldy + 19);
uint8 new_dir = Sprite_DirectionToFaceLink(k, NULL);
Sprite_SetY(k, oldy);
if (new_dir == 0 && link_direction_facing == 4)
sprite_C[k]++;
} else {
if (!Sprite_CheckDamageToLink_same_layer(k))
return;
}
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Sprite_RepelDash();
}
}
void Sprite_39_Locksmith(int k) { // 86bcac
uint8 bak;
int j;
MiddleAgedMan_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
switch (sprite_ai_state[k]) {
case 0: // chilling
Sprite_ShowSolicitedMessage(k, 0x107);
bak = sprite_x_lo[k];
sprite_x_lo[k] -= 16;
Sprite_Get16BitCoords(k);
sprite_x_vel[k] = 1;
sprite_y_vel[k] = 1;
if (!Sprite_CheckTileCollision(k)) {
sprite_ai_state[k]++;
if (follower_indicator != 0)
sprite_ai_state[k] = 5;
}
sprite_x_lo[k] = bak;
break;
case 1: // transition to tagalong
follower_indicator = 9;
tagalong_var5 = 0;
LoadFollowerGraphics();
Follower_Initialize();
word_7E02CD = 0x40;
sprite_state[k] = 0;
break;
case 2: // offer chest
if (Sprite_CheckIfLinkIsBusy())
return;
if (follower_dropped) {
j = Sprite_ShowSolicitedMessage(k, 0x109);
} else {
j = Sprite_ShowMessageOnContact(k, 0x109);
}
if (j & 0x100)
sprite_ai_state[k] = 3;
break;
case 3: // react to secret keeping
if (!choice_in_multiselect_box) {
if (follower_dropped) {
Sprite_ShowMessageUnconditional(0x10c);
sprite_ai_state[k] = 2;
} else {
item_receipt_method = 0;
Link_ReceiveItem(0x16, 0);
sram_progress_indicator_3 |= 0x10;
sprite_ai_state[k] = 4;
follower_indicator = 0;
}
} else {
Sprite_ShowMessageUnconditional(0x10a);
sprite_ai_state[k] = 2;
}
break;
case 4: // promise reminder
Sprite_ShowSolicitedMessage(k, 0x10b);
break;
case 5: // silence other tagalong
Sprite_ShowSolicitedMessage(k, 0x107);
break;
}
}
void MiddleAgedMan_Draw(int k) { // 86bdac
static const DrawMultipleData kMiddleAgedMan_Dmd[2] = {
{0, -8, 0x00ea, 2},
{0, 0, 0x00ec, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kMiddleAgedMan_Dmd[0], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_2B_Hobo(int k) { // 86bdc1
switch (sprite_subtype2[k]) {
case 0:
Sprite_Hobo_Bum(k);
break;
case 1:
Sprite_Hobo_Bubble(k);
break;
case 2:
Sprite_Hobo_Fire(k);
break;
case 3:
Sprite_Hobo_Smoke(k);
break;
}
}
void Sprite_Hobo_Bum(int k) { // 86bdd0
Hobo_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_flags4[k] = 3;
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Link_CancelDash();
}
switch(sprite_ai_state[k]) {
case 0: // sleeping
sprite_flags4[k] = 7;
if (Sprite_CheckDamageToLink_same_layer(k) && (filtered_joypad_L & 0x80)) {
sprite_ai_state[k] = 1;
int j = sprite_E[k];
sprite_delay_main[j] = 4;
flag_is_link_immobilized = 1;
}
if (!sprite_delay_aux2[k]) {
sprite_delay_aux2[k] = 160;
sprite_E[k] = Hobo_SpawnBubble(k);
}
break;
case 1: // wake up
if (!sprite_delay_main[k]) {
static const int8 kHobo_Gfx[7] = {0, 1, 0, 1, 0, 1, 2};
static const int8 kHobo_Delay[7] = {6, 2, 6, 6, 2, 100, 30};
int j = sprite_A[k];
if (j != 7) {
sprite_graphics[k] = kHobo_Gfx[j];
sprite_delay_main[k] = kHobo_Delay[j];
sprite_A[k]++;
} else {
Sprite_ShowMessageUnconditional(0xd7);
sprite_ai_state[k] = 2;
}
}
break;
case 2: // grant bottle
sprite_ai_state[k] = 3;
sprite_graphics[k] = 1;
save_ow_event_info[BYTE(overworld_screen_index)] |= 0x20;
item_receipt_method = 0;
Link_ReceiveItem(0x16, 0);
sram_progress_indicator_3 |= 1;
break;
case 3: // back to sleep
flag_is_link_immobilized = 0;
sprite_graphics[k] = 0;
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 160;
Hobo_SpawnBubble(k);
}
break;
}
}
void SpritePrep_Hobo_SpawnSmoke(int k) { // 86be9d
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x2b, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_subtype2[j] = 0;
sprite_ignore_projectile[j] = 0;
}
}
void Sprite_Hobo_Bubble(int k) { // 86beb4
Oam_AllocateFromRegionC(4);
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_graphics[k] = (frame_counter >> 4 & 1) + 2;
if (!sprite_delay_aux1[k]) {
sprite_graphics[k]++;
Sprite_MoveZ(k);
if (!sprite_delay_main[k])
sprite_state[k] = 0;
}
if (sprite_delay_main[k] < 4)
sprite_graphics[k] = 3;
}
int Hobo_SpawnBubble(int k) { // 86beed
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x2b, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_subtype2[j] = 1;
sprite_z_vel[j] = 2;
sprite_delay_main[j] = 96;
sprite_delay_aux1[j] = 96 >> 1;
sprite_ignore_projectile[j] = 96 >> 1;
sprite_flags2[j] = 0;
}
return j;
}
void Sprite_Hobo_Fire(int k) { // 86bf15
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_graphics[k] = frame_counter >> 3 & 1;
sprite_oam_flags[k] &= ~0x40;
if (!sprite_delay_main[k]) {
Hobo_SpawnSmoke(k);
sprite_delay_main[k] = 47;
}
}
void SpritePrep_Hobo_SpawnFire(int k) { // 86bf4b
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x2b, &info);
if (j >= 0) {
Sprite_SetX(j, 0x194);
Sprite_SetY(j, 0x03f);
sprite_subtype2[j] = 2;
sprite_ignore_projectile[j] = 2;
sprite_flags2[j] = 0;
sprite_oam_flags[j] = sprite_oam_flags[j] & ~0xE | 2;
}
}
void Sprite_Hobo_Smoke(int k) { // 86bf81
static const uint8 kHoboSmoke_OamFlags[4] = {0, 64, 128, 192};
sprite_graphics[k] = 6;
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXY(k);
Sprite_MoveZ(k);
sprite_oam_flags[k] = sprite_oam_flags[k] & 0x3f | kHoboSmoke_OamFlags[frame_counter >> 4 & 3];
if (!sprite_delay_main[k])
sprite_state[k] = 0;
}
void Hobo_SpawnSmoke(int k) { // 86bfaf
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x2b, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
Sprite_SetY(j, info.r2_y - 4);
sprite_subtype2[j] = 3;
sprite_z_vel[j] = 7;
sprite_delay_main[j] = 96;
sprite_ignore_projectile[j] = 96;
sprite_flags2[j] = 0;
}
}
void Sprite_73_UncleAndPriest_bounce(int k) { // 86bfe0
switch (sprite_E[k]) {
case 0:
Sprite_Uncle(k);
break;
case 1:
Sprite_Priest(k);
break;
case 2:
Sprite_SanctuaryMantle(k);
break;
}
}
void SpritePrep_UncleAndPriest_bounce(int k) { // 86bfe5
if (BYTE(dungeon_room_index) == 18) {
Priest_SpawnMantle(k);
if (sram_progress_indicator >= 3)
sram_progress_flags |= 2;
if (sram_progress_flags & 2) {
sprite_state[k] = 0;
return;
}
sprite_E[k] = 1;
sprite_flags2[k] = sprite_flags2[k] & 0xf0 | 0x2;
sprite_flags4[k] = 3;
int j;
if (link_sword_type >= 2) {
sprite_D[k] = 4;
sprite_graphics[k] = 0;
j = 0;
} else {
sprite_D[k] = sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
if (follower_indicator == 1) {
sram_progress_flags |= 0x4;
save_ow_event_info[0x1b] |= 0x20;
sprite_delay_main[k] = 170;
j = 1;
} else {
j = 2;
}
}
sprite_subtype2[k] = j;
static const int16 kUncleAndSage_Y[3] = {0, -9, 0};
Sprite_SetX(k, Sprite_GetX(k) - 6);
Sprite_SetY(k, Sprite_GetY(k) + kUncleAndSage_Y[j]);
sprite_ignore_projectile[k]++;
byte_7FFE01 = 0;
} else if (BYTE(dungeon_room_index) == 4) {
if (!(sram_progress_flags & 0x10))
sprite_x_lo[k] += 8;
else
sprite_state[k] = 0;
} else {
if (!(sram_progress_flags & 1)) {
sprite_D[k] = 3;
sprite_subtype2[k] = 1;
} else {
sprite_state[k] = 0;
}
}
}
void SpritePrep_OldMan_bounce(int k) { // 86bff9
sprite_ignore_projectile[k]++;
if (BYTE(dungeon_room_index) == 0xe4) {
sprite_subtype2[k] = 2;
return;
}
if (follower_indicator == 0) {
if (link_item_mirror == 2)
sprite_state[k] = 0;
follower_indicator = 4;
LoadFollowerGraphics();
follower_indicator = 0;
} else {
sprite_state[k] = 0;
LoadFollowerGraphics();
}
}
void Sprite_TutorialGuardOrBarrier_bounce(int k) { // 86bffe
if (sprite_type[k] == 0x40) {
Sprite_EvilBarrier(k);
return;
}
int jbak = sprite_D[k];
if (sprite_delay_aux1[k])
sprite_D[k] = kSoldier_DirectionLockSettings[jbak];
sprite_graphics[k] = kSprite_TutorialEntities_Tab[sprite_D[k]];
TutorialSoldier_Draw(k);
sprite_D[k] = jbak;
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageFromLink(k);
if (BYTE(overworld_area_index) == 0x1b && (sprite_y_lo[k] == 0x50 || sprite_y_lo[k] == 0x90)) {
Sprite_TutorialGuard_ShowMessageOnContact(k, sprite_y_lo[k] == 0x50 ? 0xB2 : 0xB3);
} else {
if (Sprite_TutorialGuard_ShowMessageOnContact(k, byte_7E0B69 + 0xf)) {
byte_7E0B69 = byte_7E0B69 != 6 ? byte_7E0B69 + 1 : 0;
}
}
Sprite_CheckDamageToAndFromLink(k);
if (((k ^ frame_counter) & 0x1f) == 0) {
uint8 jbak = sprite_D[k];
sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
if (sprite_D[k] != jbak && !((sprite_D[k] ^ jbak) & 2))
sprite_delay_aux1[k] = 12;
}
}
void Sprite_F2_MedallionTablet_bounce(int k) { // 86c00d
switch (sprite_subtype2[k]) {
case 0:
MedallionTablet_Main(k);
break;
case 1:
Sprite_DustCloud(k);
break;
}
}
void Sprite_33_RupeePull_bounce(int k) { // 86c017
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckIfLinkIsBusy())
return;
if (Sprite_CheckDamageToLink_same_layer(k)) {
link_need_for_pullforrupees_sprite = 1;
sprite_A[k] = 1;
} else {
if (sprite_A[k]) {
link_need_for_pullforrupees_sprite = 0;
if (link_state_bits & 1) {
sprite_state[k] = 0;
RupeePull_SpawnPrize(k);
Sprite_SpawnPoofGarnish(k);
}
}
}
}
void Sprite_14_ThievesTownGrate_bounce(int k) { // 86c01c
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckIfLinkIsBusy())
return;
if (Sprite_CheckDamageToLink_same_layer(k)) {
link_need_for_pullforrupees_sprite = 1;
sprite_A[k] = 1;
} else {
if (!sprite_A[k])
return;
link_need_for_pullforrupees_sprite = 0;
if (!(link_state_bits & 1))
return;
SpriteSfx_QueueSfx2WithPan(k, 0x1f);
OpenGargoylesDomain();
int j = Sprite_SpawnDustCloud(k);
Sprite_SetX(j, Sprite_GetX(k));
Sprite_SetY(j, Sprite_GetY(k));
sprite_state[k] = 0;
}
}
void SpritePrep_Snitch_bounce_2(int k) { // 86c026
SpritePrep_Snitches(k);
}
void SpritePrep_Snitch_bounce_3(int k) { // 86c030
SpritePrep_Snitches(k);
}
void Sprite_37_Waterfall_bounce(int k) { // 86c03a
switch (sprite_subtype2[k]) {
case 0: Waterfall(k); break;
case 1: Sprite_BatCrash(k); break;
}
}
void Sprite_38_EyeStatue_bounce(int k) { // 86c03f
if (!sprite_B[k]) {
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_DirectionToFaceLink(k, NULL) == 2 && sprite_unk2[k] == 9) {
dung_flag_statechange_waterpuzzle++;
sprite_B[k] = 1;
}
}
}
void Sprite_3A_MagicBat_bounce(int k) { // 86c044
if (sprite_head_dir[k]) {
Sprite_MadBatterBolt(k);
return;
}
if (sprite_ai_state[k])
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXY(k);
Sprite_MoveZ(k);
switch(sprite_ai_state[k]) {
case 0: // wait for summon
if (link_magic_consumption >= 2)
return;
if (!Sprite_CheckDamageToLink_same_layer(k))
return;
for (int i = 4; i >= 0; i--) {
if (ancilla_type[i] == 0x1a) {
Sprite_SpawnSuperficialBombBlast(k);
SpriteSfx_QueueSfx1WithPan(k, 0xd);
sprite_ai_state[k]++;
sprite_A[k] = 20;
flag_is_link_immobilized = 1;
sprite_oam_flags[k] |= 32;
return;
}
}
break;
case 1: // RisingUp
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = --sprite_A[k];
if (sprite_delay_main[k] != 1) {
static const int8 kMadBatter_RisingUp_XAccel[2] = {-8, 7};
sprite_z_vel[k] = sprite_delay_main[k] >> 2;
sprite_x_vel[k] += kMadBatter_RisingUp_XAccel[sprite_A[k] & 1];
sprite_graphics[k] ^= 1;
} else {
Sprite_ShowMessageUnconditional(0x110);
sprite_ai_state[k]++;
sprite_graphics[k] = 0;
sprite_z_vel[k] = 0;
sprite_x_vel[k] = 0;
sprite_delay_main[k] = 255;
}
}
break;
case 2: { // PseudoAttackPlayer
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_aux1[k] = 64;
}
static const int8 kMadBatter_PseudoAttack_OamFlags[8] = {0xa, 4, 2, 4, 2, 0xa, 4, 2};
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0xE | kMadBatter_PseudoAttack_OamFlags[sprite_delay_main[k] >> 1 & 7];
if (sprite_delay_main[k] == 240)
Sprite_MagicBat_SpawnLightning(k);
break;
}
case 3: // DoublePlayerMagicPower
if (!sprite_delay_aux1[k]) {
Sprite_ShowMessageUnconditional(0x111);
Palette_Restore_BG_And_HUD();
flag_update_cgram_in_nmi++;
sprite_ai_state[k]++;
link_magic_consumption = 1;
Hud_RefreshIcon();
} else if (sprite_delay_aux1[k] == 0x10) {
intro_times_pal_flash = 0x10;
}
break;
case 4: // LaterBitches
Sprite_SpawnDummyDeathAnimation(k);
sprite_state[k] = 0;
flag_is_link_immobilized = 0;
break;
}
}
void SpritePrep_Zelda_bounce(int k) { // 86c06c
if (link_sword_type >= 2) {
sprite_state[k] = 0;
return;
}
sprite_ignore_projectile[k]++;
sprite_D[k] = sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
uint8 bak0 = follower_indicator;
follower_indicator = 1;
LoadFollowerGraphics();
follower_indicator = bak0;
if (BYTE(dungeon_room_index) == 0x12) {
sprite_subtype2[k] = 2;
if (!(sram_progress_flags & 4)) {
sprite_state[k] = 0;
} else {
Sprite_SetX(k, Sprite_GetX(k) + 6);
Sprite_SetY(k, Sprite_GetY(k) + 15);
sprite_flags4[k] = 3;
}
} else {
sprite_subtype2[k] = 0;
if (follower_indicator == 1 || (sram_progress_flags & 4))
sprite_state[k] = 0;
}
}
void Sprite_78_MrsSahasrahla_bounce(int k) { // 86c071
ElderWife_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
switch (sprite_ai_state[k]) {
case 0: // initial
if (link_sword_type < 2) {
if (Sprite_ShowSolicitedMessage(k, 0x2b) & 0x100)
sprite_ai_state[k] = 1;
} else {
Sprite_ShowSolicitedMessage(k, 0x2e);
}
sprite_graphics[k] = frame_counter >> 4 & 1;
break;
case 1: // tell legend
Sprite_ShowMessageUnconditional(0x2c);
sprite_ai_state[k] = 2;
break;
case 2: // loop until player not dumb
if (choice_in_multiselect_box == 0) {
sprite_ai_state[k] = 3;
Sprite_ShowMessageUnconditional(0x2d);
} else {
Sprite_ShowMessageUnconditional(0x2c);
}
break;
case 3: // go away find old man
Sprite_ShowSolicitedMessage(k, 0x2d);
sprite_graphics[k] = frame_counter >> 4 & 1;
break;
}
}
void Sprite_16_Elder_bounce(int k) { // 86c08a
Elder_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
switch (sprite_subtype2[k]) {
case 0:
Sprite_Sahasrahla(k);
break;
case 1:
Sprite_Aginah(k);
break;
}
}
void SpritePrep_HeartPiece(int k) { // 86c0a8
HeartUpgrade_CheckIfAlreadyObtained(k);
}
void Sprite_2D_TelepathicTile_bounce(int k) { // 86c0b2
assert(0);
}
void Sprite_25_TalkingTree_bounce(int k) { // 86c0d5
switch (sprite_subtype2[k]) {
case 0: TalkingTree_Mouth(k); break;
case 1: TalkingTree_Eye(k); break;
}
}
void Sprite_1C_Statue(int k) { // 86c0e8
static const uint8 kMovableStatue_Dir[4] = {4, 6, 0, 2};
static const uint8 kMovableStatue_Joypad[4] = {1, 2, 4, 8};
static const int8 kMovableStatue_Xvel[4] = {-16, 16, 0, 0};
static const int8 kMovableStatue_Yvel[4] = {0, 0, -16, 16};
int j;
if (sprite_D[k]) {
sprite_D[k] = 0;
link_speed_setting = 0;
bitmask_of_dragstate = 0;
}
if (sprite_delay_main[k]) {
sprite_D[k] = 1;
bitmask_of_dragstate = 129;
link_speed_setting = 8;
}
MovableStatue_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Statue_BlockSprites(k);
dung_flag_statechange_waterpuzzle = 0;
if (Statue_CheckForSwitch(k))
dung_flag_statechange_waterpuzzle = 1;
Sprite_MoveXY(k);
Sprite_Get16BitCoords(k);
Sprite_CheckTileCollision2(k);
Sprite_ZeroVelocity_XY(k);
if (Sprite_CheckDamageToLink_same_layer(k)) {
sprite_delay_main[k] = 7;
Sprite_RepelDash();
if (sprite_delay_aux1[k]) {
Sprite_NullifyHookshotDrag();
return;
}
j = Sprite_DirectionToFaceLink(k, NULL);
sprite_x_vel[k] = kMovableStatue_Xvel[j];
sprite_y_vel[k] = kMovableStatue_Yvel[j];
} else {
if (!sprite_delay_main[k])
sprite_delay_aux1[k] = 13;
if ((uint16)(cur_sprite_x - link_x_coord + 16) < 35 &&
(uint16)(cur_sprite_y - link_y_coord + 12) < 36 &&
link_direction_facing == kMovableStatue_Dir[j = Sprite_DirectionToFaceLink(k, NULL)] &&
!link_is_running) {
link_is_near_moveable_statue = 1;
sprite_A[k] = 1;
if (!(link_grabbing_wall & 2) || !(kMovableStatue_Joypad[j] & joypad1H_last) || (link_x_vel | link_y_vel) == 0)
return;
j ^= 1;
sprite_x_vel[k] = kMovableStatue_Xvel[j];
sprite_y_vel[k] = kMovableStatue_Yvel[j];
} else {
if (sprite_A[k]) {
sprite_A[k] = 0;
link_speed_setting = 0;
link_grabbing_wall = 0;
link_is_near_moveable_statue = 0;
link_cant_change_direction &= ~1;
}
return;
}
}
if (!(link_grabbing_wall & 2))
Sprite_NullifyHookshotDrag();
if (!(sprite_wallcoll[k] & 15) && !sprite_delay_aux4[k]) {
SpriteSfx_QueueSfx2WithPan(k, 0x22);
sprite_delay_aux4[k] = 8;
}
}
bool Statue_CheckForSwitch(int k) { // 86c203
static const int8 kMovableStatue_SwitchX[4] = {3, 12, 3, 12};
static const int8 kMovableStatue_SwitchY[4] = {3, 3, 12, 12};
for (int j = 3; j >= 0; j--) {
uint16 x = Sprite_GetX(k) + kMovableStatue_SwitchX[j];
uint16 y = Sprite_GetY(k) + kMovableStatue_SwitchY[j];
uint8 t = GetTileAttribute(sprite_floor[k], &x, y);
if (t != 0x23 && t != 0x24 && t != 0x25 && t != 0x3b)
return false;
}
return true;
}
void MovableStatue_Draw(int k) { // 86c264
static const DrawMultipleData kMovableStatue_Dmd[3] = {
{0, -8, 0x00c2, 0},
{8, -8, 0x40c2, 0},
{0, 0, 0x00c0, 2},
};
Sprite_DrawMultiplePlayerDeferred(k, &kMovableStatue_Dmd[0], 3, NULL);
}
void Statue_BlockSprites(int k) { // 86c277
for (int j = 15; j >= 0; j--) {
if (sprite_type[j] == 0x1c || j == k || (j ^ frame_counter) & 1 || sprite_state[j] < 9)
continue;
int x = Sprite_GetX(j), y = Sprite_GetY(j);
if ((uint16)(cur_sprite_x - x + 12) < 24 &&
(uint16)(cur_sprite_y - y + 12) < 36) {
sprite_F[j] = 4;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 32);
sprite_y_recoil[j] = pt.y;
sprite_x_recoil[j] = pt.x;
}
}
}
void Sprite_1D_FluteQuest(int k) { // 86c2e5
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
if (BYTE(overworld_screen_index) == 0x18) {
if (link_item_flute == 3)
sprite_state[k] = 0;
} else {
if (link_item_flute & 2)
sprite_state[k] = 0;
}
}
void Sprite_72_FairyPond(int k) { // 86c319
if (sprite_A[k]) {
if (!--sprite_C[k])
sprite_state[k] = 0;
sprite_graphics[k] = sprite_C[k] >> 3;
Oam_AllocateFromRegionC(4);
SpriteDraw_SingleSmall(k);
return;
}
if (sprite_B[k]) {
FaerieQueen_Draw(k);
sprite_graphics[k] = frame_counter >> 4 & 1;
if (frame_counter & 15)
return;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x72, &info);
if (j >= 0) {
Sprite_SetX(j, info.r0_x + kWishPond_X[GetRandomNumber() & 7]);
Sprite_SetY(j, info.r2_y + kWishPond_Y[GetRandomNumber() & 7]);
sprite_C[j] = 31;
sprite_A[j] = 31;
sprite_flags2[j] = 0;
sprite_flags3[j] = 0x48;
sprite_oam_flags[j] = 0x48 & 0xf;
sprite_B[j] = 1;
}
return;
}
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
Sprite_WishPond2(k);
}
void Sprite_WishPond2(int k) { // 86c41d
WishPond2_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (BYTE(dungeon_room_index) != 21)
Sprite_WishPond3(k);
else
Sprite_HappinessPond(k);
}
void Sprite_HappinessPond(int k) { // 86c44c
static const uint8 kHappinessPondCost[4] = {5, 20, 25, 50};
static const uint8 kHappinessPondCostHex[4] = {5, 0x20, 0x25, 0x50};
switch (sprite_ai_state[k]) {
case 0:
flag_is_link_immobilized = 0;
if (sprite_delay_main[k] || Sprite_CheckIfLinkIsBusy())
return;
if (Sprite_ShowMessageOnContact(k, 0x89) & 0x100) {
sprite_ai_state[k] = 1;
Link_ResetProperties_A();
Ancilla_TerminateSparkleObjects();
link_direction_facing = 0;
}
break;
case 1:
if (choice_in_multiselect_box == 0) {
int i = (link_bomb_upgrades | link_arrow_upgrades) != 0;
sprite_graphics[k] = i * 2;
WORD(byte_7E1CF2[0]) = WORD(kHappinessPondCostHex[i * 2]);
Sprite_ShowMessageUnconditional(0x14e);
sprite_ai_state[k] = 2;
flag_is_link_immobilized = 1;
} else {
show_later_msg:
Sprite_ShowMessageUnconditional(0x14c);
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 255;
}
break;
case 2: {
int i = sprite_graphics[k] + choice_in_multiselect_box;
byte_7E1CF2[1] = kHappinessPondCostHex[i];
if (link_rupees_goal < kHappinessPondCost[i]) {
goto show_later_msg;
} else {
sprite_D[k] = kHappinessPondCost[i];
sprite_head_dir[k] = i;
sprite_ai_state[k] = 3;
}
break;
}
case 3: {
sprite_delay_main[k] = 80;
int i = sprite_D[k];
link_rupees_goal -= i;
link_rupees_in_pond += i;
AddHappinessPondRupees(sprite_head_dir[k]);
if (link_rupees_in_pond >= 100) {
link_rupees_in_pond -= 100;
sprite_ai_state[k] = 5;
return;
}
byte_7E1CF2[0] = (link_rupees_in_pond / 10) * 16 + (link_rupees_in_pond % 10);
sprite_ai_state[k] = 4;
break;
}
case 4:
if (sprite_delay_main[k] == 0) {
Sprite_ShowMessageUnconditional(0x94);
sprite_ai_state[k] = 13;
}
break;
case 5:
if (sprite_delay_main[k] == 0) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x72, &info);
assert(j >= 0);
Sprite_SetX(j, info.r0_x);
Sprite_SetY(j, info.r2_y - 80);
music_control = 0x1b;
last_music_control = 0;
sprite_B[j] = 1;
Palette_AssertTranslucencySwap();
PaletteFilter_WishPonds();
sprite_E[k] = j;
sprite_ai_state[k] = 6;
sprite_delay_main[k] = 255;
}
break;
case 6:
if (!(frame_counter & 7)) {
PaletteFilter_SP5F();
if (!BYTE(palette_filter_countdown)) {
Sprite_ShowMessageUnconditional(0x95);
Palette_RevertTranslucencySwap();
TS_copy = 0;
CGADSUB_copy = 0x20;
flag_update_cgram_in_nmi++;
sprite_ai_state[k] = 7;
}
}
break;
case 7:
if (!choice_in_multiselect_box)
sprite_ai_state[k] = 8;
else
sprite_ai_state[k] = 12;
break;
case 8: {
static const uint8 kMaxBombsForLevelHex[8] = {0x10, 0x15, 0x20, 0x25, 0x30, 0x35, 0x40, 0x50};
int i = link_bomb_upgrades + 1;
if (i != 8) {
link_bomb_upgrades = i;
byte_7E1CF2[0] = link_bomb_filler = kMaxBombsForLevelHex[i];
Sprite_ShowMessageUnconditional(0x96);
} else {
link_rupees_goal += 100;
Sprite_ShowMessageUnconditional(0x98);
}
sprite_ai_state[k] = 9;
break;
}
case 9:
Palette_AssertTranslucencySwap();
TS_copy = 2;
CGADSUB_copy = 0x30;
flag_update_cgram_in_nmi++;
sprite_ai_state[k] = 10;
break;
case 10:
if (!(frame_counter & 7)) {
PaletteFilter_SP5F();
if (BYTE(palette_filter_countdown) == 30) {
sprite_state[sprite_E[k]] = 0;
} else if (BYTE(palette_filter_countdown) == 0) {
sprite_ai_state[k] = 11;
}
}
break;
case 11:
PaletteFilter_RestoreSP5F();
Palette_RevertTranslucencySwap();
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 255;
break;
case 12: {
static const uint8 kMaxArrowsForLevelHex[8] = {0x30, 0x35, 0x40, 0x45, 0x50, 0x55, 0x60, 0x70};
int i = link_arrow_upgrades + 1;
if (i != 8) {
link_arrow_upgrades = i;
byte_7E1CF2[0] = link_arrow_filler = kMaxArrowsForLevelHex[i];
Sprite_ShowMessageUnconditional(0x97);
} else {
link_rupees_goal += 100;
Sprite_ShowMessageUnconditional(0x98);
}
sprite_ai_state[k] = 9;
break;
}
case 13:
Sprite_ShowMessageUnconditional(0x154);
sprite_ai_state[k] = 14;
break;
case 14: {
static const uint16 kHappinessPondLuckMsg[4] = {0x150, 0x151, 0x152, 0x153};
static const uint8 kHappinessPondLuck[4] = {1, 0, 0, 2};
int i = GetRandomNumber() & 3;
item_drop_luck = kHappinessPondLuck[i];
luck_kill_counter = 0;
Sprite_ShowMessageUnconditional(kHappinessPondLuckMsg[i]);
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 255;
break;
}
}
}
void WishPond2_Draw(int k) { // 86c4b5
static const DrawMultipleData kWishPond2_Dmd[8] = {
{32, -64, 0x0024, 0},
{32, -56, 0x0034, 0},
{32, -64, 0x0024, 0},
{32, -56, 0x0034, 0},
{32, -64, 0x0024, 2},
{32, -64, 0x0024, 2},
{32, -64, 0x0024, 2},
{32, -64, 0x0024, 2},
};
if (BYTE(dungeon_room_index) == 21)
return;
uint8 t = sprite_ai_state[k];
if (t != 5 && t != 6 && t != 11 && t != 12)
return;
int g = sprite_graphics[k];
uint8 f = kWishPond2_OamFlags[g];
if (f == 0xff)
f = 5;
sprite_oam_flags[k] = (f & 7) * 2;
Sprite_DrawMultiple(k, &kWishPond2_Dmd[(kReceiveItem_Tab1[g] >> 1) * 4], 4, NULL);
}
void FaerieQueen_Draw(int k) { // 86cb26
static const uint8 kFaerieQueen_Draw_X[24] = {
0, 16, 0, 8, 16, 24, 0, 8, 16, 24, 0, 16, 0, 16, 0, 8, 16, 24, 0, 8, 16, 24, 0, 16,
};
static const uint8 kFaerieQueen_Draw_Y[24] = {
0, 0, 16, 16, 16, 16, 24, 24, 24, 24, 32, 32, 0, 0, 16, 16, 16, 16, 24, 24, 24, 24, 32, 32,
};
static const uint8 kFaerieQueen_Draw_Char[24] = {
0xc7, 0xc7, 0xcf, 0xca, 0xca, 0xcf, 0xdf, 0xda, 0xda, 0xdf, 0xcb, 0xcb, 0xcd, 0xcd, 0xc9, 0xca,
0xca, 0xc9, 0xd9, 0xda, 0xda, 0xd9, 0xcb, 0xcb,
};
static const uint8 kFaerieQueen_Draw_Flags[24] = {
0, 0x40, 0, 0, 0x40, 0x40, 0, 0, 0x40, 0x40, 0, 0x40, 0, 0x40, 0, 0, 0x40, 0x40, 0, 0, 0x40, 0x40, 0, 0x40,
};
static const uint8 kFaerieQueen_Draw_Ext[24] = {
2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
};
static const DrawMultipleData kFaerieQueen_Dmd[20] = {
{ 0, 0, 0x00e9, 2},
{16, 0, 0x40e9, 2},
{ 0, 0, 0x00e9, 2},
{16, 0, 0x40e9, 2},
{ 0, 0, 0x00e9, 2},
{16, 0, 0x40e9, 2},
{ 0, 16, 0x00eb, 2},
{16, 16, 0x40eb, 2},
{ 0, 32, 0x00ed, 2},
{16, 32, 0x40ed, 2},
{ 0, 0, 0x00ef, 0},
{24, 0, 0x40ef, 0},
{ 0, 8, 0x00ff, 0},
{24, 8, 0x40ff, 0},
{ 0, 0, 0x00e9, 2},
{16, 0, 0x40e9, 2},
{ 0, 16, 0x00eb, 2},
{16, 16, 0x40eb, 2},
{ 0, 32, 0x00ed, 2},
{16, 32, 0x40ed, 2},
};
if (!savegame_is_darkworld) {
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
for (int i = 11; i >= 0; i--, oam++) {
int j = g * 12 + i;
oam->x = kFaerieQueen_Draw_X[j] + info.x;
oam->y = kFaerieQueen_Draw_Y[j] + info.y;
oam->charnum = kFaerieQueen_Draw_Char[j];
oam->flags = info.flags | kFaerieQueen_Draw_Flags[j];
bytewise_extended_oam[oam - oam_buf] = kFaerieQueen_Draw_Ext[j];
}
Sprite_CorrectOamEntries(k, 11, 0xff);
} else {
Sprite_DrawMultiple(k, &kFaerieQueen_Dmd[sprite_graphics[k] * 10], 10, NULL);
}
}
void Sprite_71_Leever(int k) { // 86cba2
static const uint8 kLeever_EmergeGfx[16] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, 1, 2, 1, 0, 0};
static const uint8 kLeever_AttackGfx[4] = {9, 10, 11, 12};
static const uint8 kLeever_AttackSpd[2] = {12, 8};
static const uint8 kLeever_SubmergeGfx[16] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, 1, 2, 1, 0, 0};
if (sprite_ai_state[k])
Leever_Draw(k);
else {
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
}
if (sprite_pause[k])
sprite_state[k] = 8;
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
switch(sprite_ai_state[k]) {
case 0: // under sand
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 127;
} else {
Sprite_ApplySpeedTowardsLink(k, 16);
Sprite_MoveXY(k);
Sprite_CheckTileCollision2(k);
}
break;
case 1: // emerge
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = (GetRandomNumber() & 63) + 160;
Sprite_ZeroVelocity_XY(k);
} else {
sprite_graphics[k] = kLeever_EmergeGfx[sprite_delay_main[k] >> 3];
}
break;
case 2: // attack
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
stop_attack:
sprite_ai_state[k]++;
sprite_delay_main[k] = 127;
} else {
if (!(sprite_subtype2[k] & 7))
Sprite_ApplySpeedTowardsLink(k, kLeever_AttackSpd[sprite_A[k]]);
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k))
goto stop_attack;
sprite_graphics[k] = kLeever_AttackGfx[++sprite_subtype2[k] >> 2 & 3];
}
break;
case 3: // submerge
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = (GetRandomNumber() & 31) + 64;
} else {
sprite_graphics[k] = kLeever_SubmergeGfx[sprite_delay_main[k] >> 3 ^ 15];
}
break;
}
}
void Leever_Draw(int k) { // 86ce45
static const uint8 kLeever_Draw_Num[14] = {1, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1};
static const int8 kLeever_Draw_X[56] = {
2, 6, 6, 6, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 0, 8,
0, 8, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8,
0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
static const int8 kLeever_Draw_Y[56] = {
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 5, 8, 8,
5, 5, 8, 8, 2, 2, 8, 8, 1, 1, 8, 8, 0, 0, 8, 8,
-1, -1, 8, 8, 8, -2, -2, 0, 8, -2, -2, 0, 8, -2, -2, 0,
8, -2, -2, 0, 8, -2, -2, 0,
};
static const uint8 kLeever_Draw_Char[56] = {
0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x38, 0x38, 0x38, 0x38, 8, 9, 0x28, 0x28,
8, 9, 0xd9, 0xd9, 8, 8, 0xd8, 0xd8, 8, 8, 0xda, 0xda, 6, 6, 0xd9, 0xd9,
0x26, 0x26, 0xd8, 0xd8, 0x6c, 6, 6, 0, 0x6c, 0x26, 0x26, 0, 0x6c, 6, 6, 0,
0x6c, 0x26, 0x26, 0, 0x6c, 8, 8, 0,
};
static const uint8 kLeever_Draw_Flags[56] = {
1, 0x41, 0x41, 0x41, 1, 0x41, 0x41, 0x41, 1, 0x41, 0x41, 0x41, 1, 1, 1, 0x41,
1, 1, 0, 0x40, 1, 1, 0, 0x40, 1, 1, 0, 0x40, 1, 1, 0, 0x40,
0, 1, 0, 0x40, 6, 0x41, 0x41, 0, 6, 0x41, 0x41, 0, 6, 1, 1, 0,
6, 1, 1, 0, 6, 1, 1, 0,
};
static const uint8 kLeever_Draw_Ext[56] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0,
2, 2, 0, 0, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 0,
2, 2, 2, 0, 2, 2, 2, 0,
};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int d = sprite_graphics[k];
for (int i = kLeever_Draw_Num[d]; i >= 0; i--, oam++) {
int j = d * 4 + i;
uint16 x = info.x + kLeever_Draw_X[j];
uint16 y = info.y + kLeever_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kLeever_Draw_Char[j];
uint8 f = info.flags;
if (oam->charnum >= 0x60 || oam->charnum == 0x28 || oam->charnum == 0x38)
f &= 0xf0;
oam->flags = kLeever_Draw_Flags[j] | f;
bytewise_extended_oam[oam - oam_buf] = kLeever_Draw_Ext[j] | (x >> 8 & 1);
}
}
void Sprite_D8_Heart(int k) { // 86cec0
if (SpriteDraw_AbsorbableTransient(k, true))
return;
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckAbsorptionByPlayer(k);
if (Sprite_HandleDraggingByAncilla(k))
return;
Sprite_MoveXY(k);
Sprite_MoveZ(k);
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_ai_state[k]++;
sprite_graphics[k] = 0;
}
sprite_oam_flags[k] &= ~0x40;
if (!sign8(sprite_x_vel[k]))
sprite_oam_flags[k] |= 0x40;
switch (sprite_ai_state[k] >= 3 ? 3 : sprite_ai_state[k]) {
case 0: // InitializeAscent
sprite_ai_state[k]++;
sprite_delay_main[k] = 18;
sprite_z_vel[k] = 20;
sprite_graphics[k] = 1;
sprite_D[k] = 0;
break;
case 1: // BeginDescending
if (sprite_delay_main[k] != 0) {
sprite_z_vel[k]--;
} else {
sprite_ai_state[k]++;
sprite_z_vel[k] = 253;
sprite_x_vel[k] = 0;
}
break;
case 2: // GlideGroundward
if (sprite_delay_main[k] == 0) {
int j = sprite_D[k] & 1;
sprite_x_vel[k] += kHeartRefill_AccelX[j];
if (sprite_x_vel[k] == (uint8)kHeartRefill_VelTarget[j]) {
sprite_D[k]++;
sprite_delay_main[k] = 8;
}
}
break;
case 3: // Grounded
sprite_z_vel[k] = sprite_x_vel[k] = sprite_y_vel[k] = 0;
break;
}
}
void Sprite_E3_Fairy(int k) { // 86cf94
sprite_ignore_projectile[k] = 1;
if (!sprite_ai_state[k]) {
if (!player_is_indoors)
sprite_obj_prio[k] = 48;
if (SpriteDraw_AbsorbableTransient(k, true))
return;
}
Fairy_CheckIfTouchable(k);
if (Sprite_ReturnIfInactive(k))
return;
switch (sprite_ai_state[k]) {
case 0: // normal
if (!sprite_delay_aux4[k]) {
if (Sprite_CheckDamageToLink(k)) {
Sprite_HandleAbsorptionByPlayer(k);
} else if (Sprite_CheckDamageFromLink(k) & kCheckDamageFromPlayer_Ne) {
sprite_ai_state[k]++;
Sprite_ShowMessageUnconditional(0xc9);
return;
}
}
if (Sprite_HandleDraggingByAncilla(k))
return;
Faerie_HandleMovement(k);
break;
case 1: // capture
if (choice_in_multiselect_box == 0) {
int j = Sprite_Find_EmptyBottle();
if (j >= 0) {
link_bottle_info[j] = 6;
Hud_RefreshIcon();
sprite_state[k] = 0;
return;
}
Sprite_ShowMessageUnconditional(0xca);
}
sprite_delay_aux4[k] = 48;
sprite_ai_state[k] = 0;
break;
}
}
void Fairy_CheckIfTouchable(int k) { // 86d011
if (submodule_index == 2 && (dialogue_message_index == 0xc9 || dialogue_message_index == 0xca))
sprite_delay_aux4[k] = 40;
}
void Sprite_E4_SmallKey(int k) { // 86d032
if (dung_savegame_state_bits & (kAbsorbBigKey[sprite_die_action[k]] << 8)) {
sprite_state[k] = 0;
return;
}
Sprite_DrawRippleIfInWater(k);
if (SpriteDraw_AbsorbableTransient(k, false))
return;
Sprite_Absorbable_Main(k);
}
void Sprite_D9_GreenRupee(int k) { // 86d04a
Sprite_DrawRippleIfInWater(k);
if (SpriteDraw_AbsorbableTransient(k, true))
return;
Sprite_Absorbable_Main(k);
}
void Sprite_Absorbable_Main(int k) { // 86d051
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveZ(k);
Sprite_MoveXY(k);
if (sprite_delay_aux3[k] == 0) {
Sprite_CheckTileCollision2(k);
Sprite_BounceOffWall(k);
}
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_x_vel[k] = (int8)sprite_x_vel[k] >> 1;
sprite_y_vel[k] = (int8)sprite_y_vel[k] >> 1;
uint8 t = -sprite_z_vel[k];
t >>= 1;
if (t < 9) {
sprite_z_vel[k] = sprite_x_vel[k] = sprite_y_vel[k] = 0;
} else {
sprite_z_vel[k] = t;
if (sprite_I[k] == 8 || sprite_I[k] == 9) {
sprite_z_vel[k] = 0;
int j = Sprite_SpawnSmallSplash(k);
if (j >= 0 && sprite_flags3[k] & 0x20) {
// wtf carry propagation
Sprite_SetX(j, Sprite_GetX(j) - 4);
Sprite_SetY(j, Sprite_GetY(j) - 4);
}
} else {
if (sprite_type[k] >= 0xe4 && player_is_indoors)
SpriteSfx_QueueSfx2WithPan(k, 5);
}
}
}
if (Sprite_HandleDraggingByAncilla(k))
return;
Sprite_CheckAbsorptionByPlayer(k);
}
void Sprite_08_Octorok(int k) { // 86d377
static const uint8 kOctorock_Tab0[20] = {
0, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 0,
};
static const uint8 kOctorock_Tab1[10] = {2, 2, 2, 2, 2, 2, 2, 2, 1, 0};
static const uint8 kOctorock_NextDir[4] = {2, 3, 1, 0};
static const uint8 kOctorock_Dir[4] = {3, 2, 0, 1};
static const int8 kOctorock_Xvel[4] = {24, -24, 0, 0};
static const int8 kOctorock_Yvel[4] = {0, 0, 24, -24};
static const uint8 kOctorock_OamFlags[4] = {0x40, 0, 0, 0};
int j = sprite_D[k];
if (sprite_delay_aux1[k])
sprite_D[k] = kOctorock_Dir[j];
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kOctorock_OamFlags[j] | (sprite_graphics[k] == 7 ? 0x40 : 0);
Octorock_Draw(k);
sprite_D[k] = j;
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_MoveXY(k);
Sprite_CheckDamageToAndFromLink(k);
if (!(sprite_ai_state[k] & 1)) {
sprite_graphics[k] = ++sprite_subtype2[k] >> 3 & 3 | (sprite_D[k] & 2) << 1;
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = sprite_type[k] == 8 ? 60 : 160;
} else {
j = sprite_D[k];
sprite_x_vel[k] = kOctorock_Xvel[j];
sprite_y_vel[k] = kOctorock_Yvel[j];
if (Sprite_CheckTileCollision(k))
sprite_D[k] ^= 1;
}
return;
} else {
Sprite_ZeroVelocity_XY(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = (GetRandomNumber() & 0x3f) + 48;
sprite_D[k] = sprite_delay_main[k] & 3;
} else {
switch (sprite_type[k]) {
case 8: // normal
j = sprite_delay_main[k];
if (j == 28)
Octorok_FireLoogie(k);
sprite_C[k] = kOctorock_Tab0[j >> 3];
break;
case 10: // four shooter
j = sprite_delay_main[k];
if (j < 128) {
if (!(j & 15))
sprite_D[k] = kOctorock_NextDir[sprite_D[k]];
if ((j & 15) == 8)
Octorok_FireLoogie(k);
}
sprite_C[k] = kOctorock_Tab1[j >> 4];
break;
}
}
}
}
void Octorok_FireLoogie(int k) { // 86d4cd
static const int8 kOctorock_Spit_X[4] = {12, -12, 0, 0};
static const int8 kOctorock_Spit_Y[4] = {4, 4, 12, -12};
static const int8 kOctorock_Spit_Xvel[4] = {44, -44, 0, 0};
static const int8 kOctorock_Spit_Yvel[4] = {0, 0, 44, -44};
SpriteSpawnInfo info;
SpriteSfx_QueueSfx2WithPan(k, 0x7);
int j = Sprite_SpawnDynamically(k, 0xc, &info);
if (j >= 0) {
int i = sprite_D[k];
Sprite_SetX(j, info.r0_x + kOctorock_Spit_X[i]);
Sprite_SetY(j, info.r2_y + kOctorock_Spit_Y[i]);
sprite_x_vel[j] = kOctorock_Spit_Xvel[i];
sprite_y_vel[j] = kOctorock_Spit_Yvel[i];
}
}
void Octorock_Draw(int k) { // 86d54a
static const int8 kOctorock_Draw_X[9] = {8, 0, 4, 8, 0, 4, 9, -1, 4};
static const int8 kOctorock_Draw_Y[9] = {6, 6, 9, 6, 6, 9, 6, 6, 9};
static const uint8 kOctorock_Draw_Char[9] = {0xbb, 0xbb, 0xba, 0xab, 0xab, 0xaa, 0xa9, 0xa9, 0xb9};
static const uint8 kOctorock_Draw_Flags[9] = {0x65, 0x25, 0x25, 0x65, 0x25, 0x25, 0x65, 0x25, 0x25};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
if (sprite_D[k] != 3) {
OamEnt *oam = GetOamCurPtr();
int j = sprite_C[k] * 3 + sprite_D[k];
uint16 x = info.x + kOctorock_Draw_X[j];
uint16 y = info.y + kOctorock_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kOctorock_Draw_Char[j];
oam->flags = kOctorock_Draw_Flags[j] | info.flags;
bytewise_extended_oam[oam - oam_buf] = (x >> 8 & 1);
}
oam_cur_ptr += 4;
oam_ext_cur_ptr++;
sprite_flags2[k]--;
Sprite_PrepAndDrawSingleLargeNoPrep(k, &info);
sprite_flags2[k]++;
}
void Sprite_0C_OctorokStone(int k) { // 86d5b9
if (sprite_state[k] == 6) {
SpriteDraw_OctorokStoneCrumbling(k);
if (Sprite_ReturnIfPaused(k))
return;
if (sprite_delay_main[k] == 30)
SpriteSfx_QueueSfx2WithPan(k, 0x1f);
} else {
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToLink(k);
Sprite_MoveXY(k);
if (!((k ^ frame_counter) & 3) && Sprite_CheckTileCollision(k))
Sprite_Func3(k);
}
}
void SpriteDraw_OctorokStoneCrumbling(int k) { // 86d643
static const int8 kOctostone_Draw_X[16] = {0, 8, 0, 8, -8, 16, -8, 16, -12, 20, -12, 20, -14, 22, -14, 22};
static const int8 kOctostone_Draw_Y[16] = {0, 0, 8, 8, -8, -8, 16, 16, -12, -12, 20, 20, -14, -14, 22, 22};
static const uint8 kOctostone_Draw_Flags[16] = {0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = ((sprite_delay_main[k] >> 1 & 0xc) ^ 0xc);
for (int i = 3; i >= 0; i--, oam++) {
int j = g + i;
uint16 x = info.x + kOctostone_Draw_X[j];
uint16 y = info.y + kOctostone_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = 0xbc;
oam->flags = kOctostone_Draw_Flags[j] | 0x2d;
bytewise_extended_oam[oam - oam_buf] = (x >> 8 & 1);
}
}
void Sprite_0F_Octoballoon(int k) { // 86d6aa
static const uint8 kSprite_Octoballoon_Z[8] = {16, 17, 18, 19, 20, 19, 18, 17};
sprite_z[k] = kSprite_Octoballoon_Z[sprite_subtype2[k] >> 3 & 7];
Octoballoon_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 3;
if (!Octoballoon_Find()) {
sprite_state[k] = 6;
sprite_hit_timer[k] = 0;
sprite_delay_main[k] = 15;
return;
}
}
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_subtype2[k]++;
if (!((k ^ frame_counter) & 15)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 4);
if (sprite_x_vel[k] - pt.x)
sprite_x_vel[k] += sign8(sprite_x_vel[k] - pt.x) ? 1 : -1;
if (sprite_y_vel[k] - pt.y)
sprite_y_vel[k] += sign8(sprite_y_vel[k] - pt.y) ? 1 : -1;
}
Sprite_MoveXY(k);
if (Sprite_CheckDamageToLink(k))
Octoballoon_RecoilLink(k);
Sprite_CheckDamageFromLink(k);
Sprite_CheckTileCollision2(k);
Sprite_BounceOffWall(k);
}
void Octoballoon_RecoilLink(int k) { // 86d72b
if (!link_incapacitated_timer) {
link_incapacitated_timer = 4;
Sprite_ApplyRecoilToLink(k, 16);
Sprite_InvertSpeed_XY(k);
}
}
void Octoballoon_Draw(int k) { // 86d784
static const int8 kOctoballoon_Draw_X[12] = {-4, 4, -4, 4, -8, 8, -8, 8, -4, 4, -4, 4};
static const int8 kOctoballoon_Draw_Y[12] = {-4, -4, 4, 4, -8, -8, 8, 8, -4, -4, 4, 4};
static const uint8 kOctoballoon_Draw_Char[12] = {0x8c, 0x8c, 0x9c, 0x9c, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86};
static const uint8 kOctoballoon_Draw_Flags[12] = {0, 0x40, 0, 0x40, 0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0};
int d = 0;
if (sprite_state[k] == 6) {
if (sprite_delay_main[k] == 6 && !submodule_index)
Octoballoon_FormBabby(k);
d = (sprite_delay_main[k] >> 1 & 4) + 4;
}
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
for (int i = 3; i >= 0; i--, oam++) {
int j = d + i;
uint16 x = info.x + kOctoballoon_Draw_X[j];
uint16 y = info.y + kOctoballoon_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kOctoballoon_Draw_Char[j];
oam->flags = kOctoballoon_Draw_Flags[j] | info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
SpriteDraw_Shadow(k, &info);
}
void Octoballoon_FormBabby(int k) { // 86d80e
static const int8 kOctoballoon_Spawn_Xv[6] = {16, 11, -11, -16, -11, 11};
static const int8 kOctoballoon_Spawn_Yv[6] = {0, 11, 11, 0, -11, -11};
SpriteSfx_QueueSfx2WithPan(k, 0xc);
for (int i = 5; i >= 0; i--) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x10, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_x_vel[j] = kOctoballoon_Spawn_Xv[i];
sprite_y_vel[j] = kOctoballoon_Spawn_Yv[i];
sprite_z_vel[j] = 48;
sprite_subtype2[j] = 255;
}
}
}
void Sprite_10_OctoballoonBaby(int k) { // 86d853
if (!sprite_subtype2[k])
sprite_state[k] = 0;
if (sprite_subtype2[k] >= 64 || !(sprite_subtype2[k] & 1))
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_subtype2[k]--;
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_z_vel[k]--;
Sprite_MoveZ(k);
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 16;
}
Sprite_MoveXY(k);
Sprite_CheckTileCollision2(k);
Sprite_BounceOffWall(k);
Sprite_CheckDamageToAndFromLink(k);
}
void Sprite_0D_Buzzblob(int k) { // 86d89a
static const uint8 kBuzzBlob_Gfx[4] = {0, 1, 0, 2};
static const uint8 kBuzzBlob_ObjPrio[4] = {10, 2, 8, 2};
if (sprite_delay_aux1[k])
sprite_obj_prio[k] = sprite_obj_prio[k] & 0xf1 | kBuzzBlob_ObjPrio[sprite_delay_aux1[k] >> 1 & 3];
Sprite_Cukeman(k);
BuzzBlob_Draw(k);
sprite_graphics[k] = kBuzzBlob_Gfx[sprite_subtype2[k] >> 3 & 3] + (sprite_delay_aux1[k] ? 3 : 0);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_subtype2[k]++;
if (!sprite_delay_main[k])
Buzzblob_SelectNewDirection(k);
if (!sprite_delay_aux1[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision2(k);
Sprite_BounceOffWall(k);
Sprite_CheckDamageToAndFromLink(k);
}
void Buzzblob_SelectNewDirection(int k) { // 86d906
static const int8 kBuzzBlob_Xvel[8] = {3, 2, -2, -3, -2, 2, 0, 0};
static const int8 kBuzzBlob_Yvel[8] = {0, 2, 2, 0, -2, -2, 0, 0};
static const uint8 kBuzzBlob_Delay[8] = {48, 48, 48, 48, 48, 48, 64, 64};
int j = GetRandomNumber() & 7;
sprite_x_vel[k] = kBuzzBlob_Xvel[j];
sprite_y_vel[k] = kBuzzBlob_Yvel[j];
sprite_delay_main[k] = kBuzzBlob_Delay[j];
}
void BuzzBlob_Draw(int k) { // 86d953
static const uint16 kBuzzBlob_DrawX[3] = {0, 8, 0};
static const int16 kBuzzBlob_DrawY[3] = {-8, -8, 0};
static const uint8 kBuzzBlob_DrawChar[18] = { 0xf0, 0xf0, 0xe1, 0, 0, 0xce, 0, 0, 0xce, 0xe3, 0xe3, 0xca, 0xe4, 0xe5, 0xcc, 0xe5, 0xe4, 0xcc };
static const uint8 kBuzzBlob_DrawFlags[18] = { 0, 0x40, 0, 0, 0, 0, 0, 0, 0x40, 0, 0x40, 0, 0, 0, 0, 0x40, 0x40, 0x40 };
static const uint8 kBuzzBlob_DrawExt[3] = {0, 0, 2};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
for (int i = 2; i >= 0; i--, oam++) {
uint16 x = info.x + kBuzzBlob_DrawX[i];
uint16 y = info.y + kBuzzBlob_DrawY[i];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kBuzzBlob_DrawChar[g * 3 + i];
if (oam->charnum == 0)
oam->y = 240;
oam->flags = kBuzzBlob_DrawFlags[g * 3 + i] | info.flags;
bytewise_extended_oam[oam - oam_buf] = kBuzzBlob_DrawExt[i] | (x >> 8 & 1);
}
SpriteDraw_Shadow(k, &info);
}
void Sprite_02_StalfosHead(int k) { // 86ddb7
static const uint8 kStalfosHead_OamFlags[4] = {0, 0, 0, 0x40};
static const uint8 kStalfosHead_Gfx[4] = {0, 1, 2, 1};
sprite_floor[k] = link_is_on_lower_level;
if (sprite_delay_aux1[k])
Oam_AllocateFromRegionC(8);
int j = sprite_subtype2[k] >> 3 & 3;
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kStalfosHead_OamFlags[j];
sprite_graphics[k] = kStalfosHead_Gfx[j];
sprite_obj_prio[k] = 0x30;
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
if (sprite_F[k])
Sprite_ZeroVelocity_XY(k);
Sprite_MoveXY(k);
sprite_subtype2[k]++;
ProjectSpeedRet pt;
if (sprite_delay_main[k]) {
if (sprite_delay_main[k] & 1)
return;
pt = Sprite_ProjectSpeedTowardsLink(k, 16);
} else {
if ((k ^ frame_counter) & 3)
return;
pt = Sprite_ProjectSpeedTowardsLink(k, 16);
pt.x = -pt.x;
pt.y = -pt.y;
}
if (sprite_x_vel[k] - pt.x != 0)
sprite_x_vel[k] += sign8(sprite_x_vel[k] - pt.x) ? 1 : -1;
if (sprite_y_vel[k] - pt.y != 0)
sprite_y_vel[k] += sign8(sprite_y_vel[k] - pt.y) ? 1 : -1;
}
bool Pipe_ValidateEntry() { // 87f4f1
for (int k = 4; k >= 0; k--) {
if (ancilla_type[k] == 0x31) {
link_position_mode = 0;
link_cant_change_direction = 0;
ancilla_type[k] = 0;
break;
}
}
return ((link_state_bits & 0x80) | link_auxiliary_state) != 0;
}
void Ancilla_TerminateSparkleObjects() { // 89adc7
for (int i = 4; i >= 0; i--) {
uint8 t = ancilla_type[i];
if (t == 0x2a || t == 0x2b || t == 0x30 || t == 0x31 || t == 0x18 || t == 0x19 || t == 0xc)
ancilla_type[i] = 0;
}
}
int Sprite_SpawnSuperficialBombBlast(int k) { // 89ae40
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x4a, &info);
if (j >= 0) {
sprite_state[j] = 6;
sprite_delay_aux1[j] = 31;
sprite_C[j] = 3;
sprite_flags2[j] = 3;
sprite_oam_flags[j] = 4;
SpriteSfx_QueueSfx2WithPan(k, 0x15);
Sprite_SetSpawnedCoordinates(j, &info);
}
return j;
}
void Sprite_SpawnDummyDeathAnimation(int k) { // 89ae7e
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xb, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_state[j] = 6;
sprite_delay_main[j] = 15;
SpriteSfx_QueueSfx2WithPan(k, 0x14);
sprite_floor[j] = 2;
}
}
void Sprite_MagicBat_SpawnLightning(int k) { // 89aea8
static const int8 kSpawnMadderBolts_Xvel[4] = {-8, -4, 4, 8};
static const int8 kSpawnMadderBolts_St2[4] = {0, 0x11, 0x22, 0x33};
for (int i = 0; i < 4; i++) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x3a, &info);
if (j >= 0) {
SpriteSfx_QueueSfx3WithPan(k, 0x1);
Sprite_SetSpawnedCoordinates(j, &info);
Sprite_SetX(j, info.r0_x + 4);
Sprite_SetY(j, info.r2_y + 12 - sprite_z[k]);
sprite_z[j] = 0;
sprite_y_vel[j] = 24;
sprite_head_dir[j] = 24;
sprite_ignore_projectile[j] = 24;
sprite_flags2[j] = 0x80;
sprite_flags3[j] = 3;
sprite_oam_flags[j] = 3;
sprite_delay_main[j] = 32;
sprite_graphics[j] = 2;
int i = sprite_G[k];
sprite_x_vel[j] = kSpawnMadderBolts_Xvel[i];
sprite_subtype2[j] = kSpawnMadderBolts_St2[i];
sprite_floor[j] = 2;
sprite_G[k]++;
}
}
}
void Fireball_SpawnTrailGarnish(int k) { // 89b020
if ((k ^ frame_counter) & 3)
return;
int j = GarnishAlloc();
garnish_type[j] = 8;
garnish_active = 8;
garnish_countdown[j] = 11;
garnish_x_lo[j] = cur_sprite_x;
garnish_x_hi[j] = cur_sprite_x >> 8;
garnish_y_lo[j] = cur_sprite_y + 16;
garnish_y_hi[j] = (cur_sprite_y + 16) >> 8;
garnish_sprite[j] = k;
}
void GarnishSpawn_PyramidDebris(int8 x, int8 y, int8 xvel, int8 yvel) { // 89b1bd
int k = GarnishAllocForce();
sound_effect_2 = 3;
sound_effect_1 = 31;
sound_effect_ambient = 5;
garnish_type[k] = 19;
garnish_active = 19;
garnish_x_lo[k] = 232 + x;
garnish_y_lo[k] = 96 + y;
garnish_x_vel[k] = xvel;
garnish_y_vel[k] = yvel;
garnish_countdown[k] = (GetRandomNumber() & 31) + 48;
}
void Snitch_SpawnGuard(int k) { // 89c02f
static const uint16 kCrazyVillageSoldier_X[3] = {0x120, 0x340, 0x2e0};
static const uint16 kCrazyVillageSoldier_Y[3] = {0x100, 0x3b0, 0x160};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0x45, &info, 0);
if (j < 0)
return;
int i = sprite_type[k] == 0x3d ? 0 :
sprite_type[k] == 0x35 ? 1 : 2;
Sprite_SetX(j, kCrazyVillageSoldier_X[i] + (sprcoll_x_base & 0xff00));
Sprite_SetY(j, kCrazyVillageSoldier_Y[i] + (sprcoll_y_base & 0xff00));
sprite_floor[j] = 0;
sprite_health[j] = 4;
sprite_defl_bits[j] = 0x80;
sprite_flags5[j] = 0x90;
sprite_oam_flags[j] = 0xb;
}
void Babusu_Draw(int k) { // 8dbd20
static const DrawMultipleData kBabusu_Dmd[40] = {
{ 0, 4, 0x4380, 0},
{ 0, 4, 0x4380, 0},
{ 0, 4, 0x43b6, 0},
{ 0, 4, 0x43b6, 0},
{ 0, 4, 0x43b7, 0},
{ 8, 4, 0x0380, 0},
{ 0, 4, 0x4380, 0},
{ 8, 4, 0x03b6, 0},
{ 8, 4, 0x03b7, 0},
{ 8, 4, 0x03b7, 0},
{ 8, 4, 0x0380, 0},
{ 8, 4, 0x0380, 0},
{ 4, 0, 0x8380, 0},
{ 4, 0, 0x8380, 0},
{ 4, 0, 0x83b6, 0},
{ 4, 0, 0x83b6, 0},
{ 4, 0, 0x83b7, 0},
{ 4, 8, 0x0380, 0},
{ 4, 0, 0x8380, 0},
{ 4, 8, 0x03b6, 0},
{ 4, 8, 0x03b7, 0},
{ 4, 8, 0x03b7, 0},
{ 4, 8, 0x0380, 0},
{ 4, 8, 0x0380, 0},
{ 0, -8, 0x0a4e, 2},
{ 0, 0, 0x0a5e, 2},
{ 0, -8, 0x4a4e, 2},
{ 0, 0, 0x4a5e, 2},
{ 8, 0, 0x0a6c, 2},
{ 0, 0, 0x0a6b, 2},
{ 8, 0, 0x8a6c, 2},
{ 0, 0, 0x8a6b, 2},
{ 0, 8, 0x8a4e, 2},
{ 0, 0, 0x8a5e, 2},
{ 0, 8, 0xca4e, 2},
{ 0, 0, 0xca5e, 2},
{-8, 0, 0x4a6c, 2},
{ 0, 0, 0x4a6b, 2},
{-8, 0, 0xca6c, 2},
{ 0, 0, 0xca6b, 2},
};
if (sprite_graphics[k] != 0xff) {
Sprite_DrawMultiple(k, &kBabusu_Dmd[sprite_graphics[k] * 2], 2, NULL);
} else {
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
}
}
void Wizzrobe_Draw(int k) { // 8dbe06
static const DrawMultipleData kWizzrobe_Dmd[24] = {
{0, -8, 0x00b2, 0},
{8, -8, 0x00b3, 0},
{0, 0, 0x0088, 2},
{0, -8, 0x00b2, 0},
{8, -8, 0x00b3, 0},
{0, 0, 0x0086, 2},
{0, -8, 0x00b2, 0},
{8, -8, 0x00b3, 0},
{0, 0, 0x008c, 2},
{0, -8, 0x00b2, 0},
{8, -8, 0x00b3, 0},
{0, 0, 0x008a, 2},
{0, -8, 0x00b2, 0},
{8, -8, 0x00b3, 0},
{0, 0, 0x408c, 2},
{0, -8, 0x00b2, 0},
{8, -8, 0x00b3, 0},
{0, 0, 0x408a, 2},
{0, -8, 0x00b2, 0},
{8, -8, 0x00b3, 0},
{0, 0, 0x00a4, 2},
{0, -8, 0x00b2, 0},
{8, -8, 0x00b3, 0},
{0, 0, 0x008e, 2},
};
Sprite_DrawMultiple(k, &kWizzrobe_Dmd[sprite_graphics[k] * 3], 3, NULL);
}
void Wizzbeam_Draw(int k) { // 8dbe68
static const DrawMultipleData kWizzbeam_Dmd[8] = {
{ 0, -4, 0x00c5, 0},
{ 0, 4, 0x80c5, 0},
{ 0, -4, 0x40c5, 0},
{ 0, 4, 0xc0c5, 0},
{-4, 0, 0x40d2, 0},
{ 4, 0, 0x00d2, 0},
{-4, 0, 0xc0d2, 0},
{ 4, 0, 0x80d2, 0},
};
Sprite_DrawMultiple(k, &kWizzbeam_Dmd[sprite_D[k] * 2], 2, NULL);
}
void Freezor_Draw(int k) { // 8dbfa6
static const DrawMultipleData kFreezor_Dmd0[28] = {
{-8, 0, 0x00a6, 2},
{ 8, 0, 0x40a6, 2},
{-8, 0, 0x00a6, 2},
{ 8, 0, 0x40a6, 2},
{-8, 0, 0x00a6, 2},
{ 8, 0, 0x40a6, 2},
{ 0, 11, 0x00ab, 0},
{ 8, 11, 0x40ab, 0},
{-8, 0, 0x00ac, 2},
{ 8, 0, 0x40a8, 2},
{ 0, 11, 0x00ba, 0},
{ 8, 11, 0x00bb, 0},
{-8, 0, 0x00a8, 2},
{ 8, 0, 0x40ac, 2},
{ 0, 11, 0x40bb, 0},
{ 8, 11, 0x40ba, 0},
{ 0, 2, 0x00ae, 0},
{ 8, 2, 0x40ae, 0},
{ 0, 10, 0x00be, 0},
{ 8, 10, 0x40be, 0},
{ 0, 4, 0x00af, 0},
{ 8, 4, 0x40af, 0},
{ 0, 12, 0x00bf, 0},
{ 8, 12, 0x40bf, 0},
{ 0, 8, 0x00aa, 0},
{ 8, 8, 0x40aa, 0},
{ 0, 8, 0x00aa, 0},
{ 8, 8, 0x40aa, 0},
};
static const DrawMultipleData kFreezor_Dmd1[8] = {
{ 0, 0, 0x00ae, 0},
{ 8, 0, 0x40ae, 0},
{ 0, 8, 0x00be, 0},
{ 8, 8, 0x40be, 0},
{-2, 0, 0x00ae, 0},
{10, 0, 0x40ae, 0},
{-2, 8, 0x00be, 0},
{10, 8, 0x40be, 0},
};
if (sprite_graphics[k] != 7) {
Sprite_DrawMultiple(k, &kFreezor_Dmd0[sprite_graphics[k] * 4], 4, NULL);
} else {
Sprite_DrawMultiple(k, kFreezor_Dmd1, 8, NULL);
}
}
void Zazak_Draw(int k) { // 8dc0a6
static const uint8 kZazak_Char[8] = {0x82, 0x82, 0x80, 0x84, 0x88, 0x88, 0x86, 0x84};
static const uint8 kZazak_Flags[8] = {0x40, 0, 0, 0, 0x40, 0, 0, 0};
static const DrawMultipleData kZazak_Dmd[24] = {
{ 0, -8, 0x0008, 2},
{-4, 0, 0x00a0, 2},
{ 4, 0, 0x00a1, 2},
{ 0, -7, 0x0008, 2},
{-4, 1, 0x40a1, 2},
{ 4, 1, 0x40a0, 2},
{ 0, -8, 0x000e, 2},
{-4, 0, 0x00a3, 2},
{ 4, 0, 0x00a4, 2},
{ 0, -7, 0x000e, 2},
{-4, 1, 0x40a4, 2},
{ 4, 1, 0x40a3, 2},
{ 0, -9, 0x000c, 2},
{ 0, 0, 0x00a6, 2},
{ 0, 0, 0x00a6, 2},
{ 0, -8, 0x000c, 2},
{ 0, 0, 0x00a8, 2},
{ 0, 0, 0x00a8, 2},
{ 0, -9, 0x400c, 2},
{ 0, 0, 0x40a6, 2},
{ 0, 0, 0x40a6, 2},
{ 0, -8, 0x400c, 2},
{ 0, 0, 0x40a8, 2},
{ 0, 0, 0x40a8, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kZazak_Dmd[sprite_graphics[k] * 3], 3, &info);
if (sprite_pause[k])
return;
int i = sprite_head_dir[k] + (sprite_delay_aux1[k] == 0 ? 0 : 4);
OamEnt *oam = GetOamCurPtr();
oam->charnum = kZazak_Char[i];
oam->flags = (oam->flags & ~0x40) | kZazak_Flags[i];
SpriteDraw_Shadow(k, &info);
}
void Stalfos_Draw(int k) { // 8dc21c
static const uint8 kStalfos_Char[4] = {2, 2, 0, 4};
static const uint8 kStalfos_Flags[4] = {0x70, 0x30, 0x30, 0x30};
static const DrawMultipleData kStalfos_Dmd[36] = {
{ 0, -10, 0x0000, 2},
{ 0, 0, 0x0006, 2},
{ 0, 0, 0x0006, 2},
{ 0, -9, 0x0000, 2},
{ 0, 1, 0x4006, 2},
{ 0, 1, 0x4006, 2},
{ 0, -10, 0x0004, 2},
{ 0, 0, 0x0006, 2},
{ 0, 0, 0x0006, 2},
{ 0, -9, 0x0004, 2},
{ 0, 1, 0x4006, 2},
{ 0, 1, 0x4006, 2},
{ 0, -10, 0x0002, 2},
{ 5, 5, 0x002e, 0},
{ 0, 0, 0x0024, 2},
{ 0, -10, 0x0002, 2},
{ 0, 0, 0x000e, 2},
{ 0, 0, 0x000e, 2},
{ 0, -10, 0x4002, 2},
{ 3, 5, 0x402e, 0},
{ 0, 0, 0x4024, 2},
{ 0, -10, 0x4002, 2},
{ 0, 0, 0x400e, 2},
{ 0, 0, 0x000e, 2},
{ 2, -8, 0x4002, 2},
{ 0, 0, 0x4008, 2},
{ 0, 0, 0x4008, 2},
{-2, -8, 0x0002, 2},
{ 0, 0, 0x0008, 2},
{ 0, 0, 0x0008, 2},
{ 0, -6, 0x0000, 2},
{ 0, 0, 0x000a, 2},
{ 0, 0, 0x000a, 2},
{ 0, 0, 0x000a, 2},
{ 0, -6, 0x0004, 2},
{ 0, -6, 0x0004, 2},
};
PrepOamCoordsRet info;
if (sprite_delay_aux2[k]) {
Sprite_PrepOamCoord(k, &info);
return;
}
Sprite_DrawMultiple(k, &kStalfos_Dmd[sprite_graphics[k] * 3], 3, &info);
if (sprite_graphics[k] < 8 && !sprite_pause[k]) {
OamEnt *oam = GetOamCurPtr();
int i = sprite_head_dir[k];
oam->charnum = kStalfos_Char[i];
oam->flags = (oam->flags & ~0x70) | kStalfos_Flags[i];
}
SpriteDraw_Shadow(k, &info);
}
bool Probe_CheckTileSolidity(int k) { // 8dc26e
uint8 tiletype;
if (player_is_indoors) {
int t = (sprite_floor[k] >= 1) ? 0x1000 : 0;
t += (cur_sprite_x & 0x1f8) >> 3;
t += (cur_sprite_y & 0x1f8) << 3;
tiletype = dung_bg2_attr_table[t];
} else {
tiletype = Overworld_ReadTileAttribute(cur_sprite_x >> 3, cur_sprite_y);
}
sprite_tiletype = tiletype;
return kSprite_SimplifiedTileAttr[tiletype] >= 1;
}
void Sprite_HumanMulti_1(int k) { // 8dc2d9
switch (sprite_subtype2[k]) {
case 0: Sprite_FluteDad(k); break;
case 1: Sprite_ThiefHideoutGuy(k); break;
case 2: Sprite_BlindsHutGuy(k); break;
}
}
void Sprite_BlindsHutGuy(int k) { // 8dc2e6
BlindHideoutGuy_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
Sprite_TrackBodyToHead(k);
sprite_head_dir[k] = 0;
int j = Sprite_ShowSolicitedMessage(k, 0x172);
if (j & 0x100)
sprite_D[k] = sprite_head_dir[k] = j;
}
void Sprite_ThiefHideoutGuy(int k) { // 8dc308
if (!(frame_counter & 3)) {
sprite_graphics[k] = 2;
uint8 dir = Sprite_DirectionToFaceLink(k, NULL);
sprite_head_dir[k] = dir == 3 ? 2 : dir;
}
sprite_oam_flags[k] = 15;
Oam_AllocateDeferToPlayer(k);
Thief_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
Sprite_ShowSolicitedMessage(k, 0x171);
sprite_graphics[k] = 2;
}
void Sprite_FluteDad(int k) { // 8dc343
FluteBoyFather_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
sprite_graphics[k] = (frame_counter < 48) ? 2 : (frame_counter >> 7) & 1;
if (sprite_ai_state[k]) {
Sprite_ShowSolicitedMessage(k, 0xa3);
sprite_graphics[k] = 2;
} else if (link_item_flute < 2) {
Sprite_ShowSolicitedMessage(k, 0xa1);
} else if (!(Sprite_ShowSolicitedMessage(k, 0xa4) & 0x100) &&
hud_cur_item == kHudItem_Flute && (joypad1H_last&0x40) && Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_ShowMessageUnconditional(0xa2);
sprite_ai_state[k]++;
sprite_graphics[k] = 2;
}
}
void FluteBoyFather_Draw(int k) { // 8dc3e1
static const DrawMultipleData kFluteBoyFather_Dmd[6] = {
{0, -7, 0x0086, 2},
{0, 0, 0x0088, 2},
{0, -6, 0x0086, 2},
{0, 0, 0x0088, 2},
{0, -8, 0x0084, 2},
{0, 0, 0x0088, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kFluteBoyFather_Dmd[sprite_graphics[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void BlindHideoutGuy_Draw(int k) { // 8dc481
static const DrawMultipleData kBlindHideoutGuy_Dmd[16] = {
{0, -8, 0x000c, 2},
{0, 0, 0x00ca, 2},
{0, -8, 0x000c, 2},
{0, 0, 0x40ca, 2},
{0, -8, 0x000c, 2},
{0, 0, 0x00ca, 2},
{0, -8, 0x000c, 2},
{0, 0, 0x40ca, 2},
{0, -8, 0x000e, 2},
{0, 0, 0x00ca, 2},
{0, -8, 0x000e, 2},
{0, 0, 0x40ca, 2},
{0, -8, 0x400e, 2},
{0, 0, 0x00ca, 2},
{0, -8, 0x400e, 2},
{0, 0, 0x40ca, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kBlindHideoutGuy_Dmd[sprite_graphics[k] * 2 + sprite_D[k] * 4], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_SweepingLady(int k) { // 8dc4ad
SweepingLady_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_ShowSolicitedMessage(k, 0xa5);
Sprite_BehaveAsBarrier(k);
sprite_graphics[k] = frame_counter >> 4 & 1;
}
void SweepingLady_Draw(int k) { // 8dc4eb
static const DrawMultipleData kSweepingLadyDmd[4] = {
{0, -7, 0x008e, 2},
{0, 5, 0x008a, 2},
{0, -8, 0x008e, 2},
{0, 4, 0x008c, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kSweepingLadyDmd[sprite_graphics[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_Lumberjacks(int k) { // 8dc51b
static const uint16 kLumberJackMsg[4] = {0x12c, 0x12d, 0x12e, 0x12d};
Lumberjacks_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Lumberjack_CheckProximity(k, 0)) {
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Link_CancelDash();
}
if (!Sprite_CheckIfLinkIsBusy() && Lumberjack_CheckProximity(k, 1) && (filtered_joypad_L & 0x80)) {
int msg = (BYTE(link_x_coord) >= sprite_x_lo[k]) + (link_sword_type >= 2) * 2;
Sprite_ShowMessageUnconditional(kLumberJackMsg[msg]);
}
sprite_graphics[k] = frame_counter >> 5 & 1;
}
bool Lumberjack_CheckProximity(int k, int j) { // 8dc58f
static const uint8 kLumberJacks_X[2] = {48, 52};
static const uint8 kLumberJacks_Y[2] = {19, 20};
static const uint8 kLumberJacks_W[2] = {98, 106};
static const uint8 kLumberJacks_H[2] = {37, 40};
return (uint16)(cur_sprite_x - link_x_coord + kLumberJacks_X[j]) < kLumberJacks_W[j] &&
(uint16)(cur_sprite_y - link_y_coord + kLumberJacks_Y[j]) < kLumberJacks_H[j];
}
void Lumberjacks_Draw(int k) { // 8dc6ba
static const DrawMultipleData kLumberJacks_Dmd[33] = {
{-23, 5, 0x02be, 0},
{-15, 5, 0x02bf, 0},
{ -7, 5, 0x02bf, 0},
{ 1, 5, 0x02bf, 0},
{ 9, 5, 0x02bf, 0},
{ 17, 5, 0x02bf, 0},
{ 25, 5, 0x42be, 0},
{-32, -8, 0x40a8, 2},
{-32, 4, 0x40a6, 2},
{ 30, -8, 0x00a8, 2},
{ 31, 4, 0x00a4, 2},
{-19, 5, 0x02be, 0},
{-11, 5, 0x02bf, 0},
{ -3, 5, 0x02bf, 0},
{ 5, 5, 0x02bf, 0},
{ 13, 5, 0x02bf, 0},
{ 21, 5, 0x02bf, 0},
{ 29, 5, 0x42be, 0},
{-31, -8, 0x40a8, 2},
{-32, 4, 0x40a4, 2},
{ 31, -8, 0x00a8, 2},
{ 31, 4, 0x00a6, 2},
{-19, 5, 0x02be, 0},
{-11, 5, 0x02bf, 0},
{ -3, 5, 0x02bf, 0},
{ 5, 5, 0x02bf, 0},
{ 13, 5, 0x02bf, 0},
{ 21, 5, 0x02bf, 0},
{ 29, 5, 0x42be, 0},
{-32, -8, 0x400e, 2},
{-32, 4, 0x40a4, 2},
{ 32, -8, 0x000e, 2},
{ 31, 4, 0x00a6, 2},
};
Sprite_DrawMultiple(k, &kLumberJacks_Dmd[sprite_graphics[k] * 11], 11, NULL);
}
void Sprite_FortuneTeller(int k) { // 8dc762
switch (sprite_subtype2[k]) {
case 0: // fortuneteller main
FortuneTeller_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
FortuneTeller_LightOrDarkWorld(k, savegame_is_darkworld >> 6 & 1);
break;
case 1: // dwarf solidity
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Link_CancelDash();
}
break;
}
}
void FortuneTeller_PerformPseudoScience(int k) { // 8dc849
sprite_graphics[k] = 0;
sprite_ai_state[k]++;
static const uint8 kFortuneTeller_Readings[16] = {0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd};
uint8 slots[2] = { 0, 0 };
int n = 0;
#define ADD_MSG(q) { slots[n++]=(q); if (n==2) goto done; }
if (savegame_map_icons_indicator < 3)
goto done;
if (!link_item_book_of_mudora) ADD_MSG(2);
if (!(link_which_pendants & 2)) ADD_MSG(1);
if (link_item_mushroom < 2) ADD_MSG(3);
if (!link_item_flippers) ADD_MSG(4);
if (!link_item_moon_pearl) ADD_MSG(5);
if (sram_progress_indicator < 3) ADD_MSG(6);
if (!link_magic_consumption) ADD_MSG(7);
if (!link_item_bombos_medallion) ADD_MSG(8);
if (!(sram_progress_indicator_3 & 0x10)) ADD_MSG(9);
if (!(sram_progress_indicator_3 & 0x20)) ADD_MSG(10);
if (!link_item_cape) ADD_MSG(11);
if (!(save_ow_event_info[0x5b] & 2)) ADD_MSG(12);
if (link_sword_type < 4) ADD_MSG(13);
ADD_MSG(14);
ADD_MSG(15);
int j;
done:
j = ((sram_progress_flags ^= 0x40) & 0x40) != 0;
Sprite_ShowMessageUnconditional(kFortuneTeller_Readings[slots[j]]);
}
void FortuneTeller_Draw(int k) { // 8dcb01
static const DrawMultipleData kFortuneTeller_Dmd[12] = {
{ 0, -48, 0x000c, 2},
{ 0, -32, 0x002c, 0},
{ 8, -32, 0x402c, 0},
{ 0, -48, 0x000a, 2},
{ 0, -32, 0x002a, 0},
{ 8, -32, 0x402a, 0},
{-4, -40, 0x0066, 2},
{ 4, -40, 0x4066, 2},
{-4, -40, 0x0066, 2},
{-4, -40, 0x0068, 2},
{ 4, -40, 0x4068, 2},
{-4, -40, 0x0068, 2},
};
int j = (savegame_is_darkworld >> 6 & 1) * 2 + sprite_graphics[k];
Sprite_DrawMultiple(k, &kFortuneTeller_Dmd[j * 3], 3, NULL);
}
void Smithy_SpawnDumbBarrierSprite(int k) { // 8dcb2a
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x31, &info);
if (j < 0)
return;
Sprite_SetX(j, info.r0_x);
Sprite_SetY(j, info.r2_y);
sprite_subtype2[j] = 1;
sprite_flags4[j] = 0;
sprite_ignore_projectile[j] = 1;
}
void Sprite_MazeGameLady(int k) { // 8dcb5c
Lady_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_TrackBodyToHead(k);
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
switch (sprite_ai_state[k]) {
case 0: // startup
if (sprite_x_lo[k] < BYTE(link_x_coord)) {
int j = Sprite_ShowMessageOnContact(k, 0xcc);
if (j & 0x100) {
sprite_D[k] = sprite_head_dir[k] = (uint8)j;
sprite_ai_state[k] = 1;
word_7FFE00 = 0;
word_7FFE02 = 0;
sprite_A[k] = 0;
flag_overworld_area_did_change = 0;
}
} else {
Sprite_ShowMessageOnContact(k, 0xd0);
}
break;
case 1: // sound
SpriteSfx_QueueSfx3WithPan(k, 0x7);
sprite_ai_state[k] = 2;
break;
case 2: // accumulate time
if (++sprite_A[k] == 63) {
sprite_A[k] = 0;
word_7FFE00 += 1;
if (word_7FFE00 == 0)
word_7FFE02++;
}
break;
}
}
void Sprite_MazeGameGuy(int k) { // 8dcbf2
int j;
MazeGameGuy_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_TrackBodyToHead(k);
sprite_head_dir[k] = 0;
Sprite_BehaveAsBarrier(k);
sprite_graphics[k] = frame_counter >> 3 & 1;
if (flag_overworld_area_did_change) {
Sprite_ShowMessageOnContact(k, 0xd0);
return;
}
switch (sprite_ai_state[k]) {
case 0: { // parse time
word_7FFE04 = word_7FFE00;
word_7FFE06 = word_7FFE02;
int t = word_7FFE04 % 6000;
int a = t / 600;
t %= 600;
int b = t / 60;
t %= 60;
int c = t / 10;
t %= 10;
byte_7E1CF2[0] = t | c << 4;
byte_7E1CF2[1] = b | a << 4;
t = Sprite_ShowMessageOnContact(k, 0xcb);
if (t & 0x100) {
sprite_D[k] = sprite_head_dir[k] = (uint8)t;
sprite_ai_state[k] = 1;
}
break;
}
case 1: // check qualify
if (save_ow_event_info[BYTE(overworld_screen_index)] & 0x40) {
Sprite_ShowMessageUnconditional(0xcf);
sprite_ai_state[k] = 4;
} else if (word_7FFE04 < 16) {
Sprite_ShowMessageUnconditional(0xcd);
sprite_D[k] = sprite_head_dir[k] = (uint8)link_player_handler_state; // wtf
sprite_ai_state[k] = 3;
} else {
Sprite_ShowMessageUnconditional(0xce);
sprite_D[k] = sprite_head_dir[k] = (uint8)link_player_handler_state; // wtf
sprite_ai_state[k] = 2;
}
break;
case 2: // sorry
j = Sprite_ShowMessageOnContact(k, 0xce);
if (j & 0x100)
sprite_D[k] = sprite_head_dir[k] = (uint8)j;
break;
case 3: // can have it
j = Sprite_ShowSolicitedMessage(k, 0xcd);
if (j & 0x100)
sprite_D[k] = sprite_head_dir[k] = (uint8)j;
break;
case 4: // nothing more
j = Sprite_ShowSolicitedMessage(k, 0xcf);
if (j & 0x100)
sprite_D[k] = sprite_head_dir[k] = (uint8)j;
break;
}
}
void MazeGameGuy_Draw(int k) { // 8dcda7
static const DrawMultipleData kMazeGameGuy_Dmd[16] = {
{0, -10, 0x0000, 2},
{0, 0, 0x0020, 2},
{0, -10, 0x0000, 2},
{0, 0, 0x0020, 2},
{0, -10, 0x0000, 2},
{0, 0, 0x0020, 2},
{0, -10, 0x0000, 2},
{0, 0, 0x0020, 2},
{0, -10, 0x4002, 2},
{0, 0, 0x0020, 2},
{0, -10, 0x4002, 2},
{0, 0, 0x0020, 2},
{0, -10, 0x0002, 2},
{0, 0, 0x0020, 2},
{0, -10, 0x0002, 2},
{0, 0, 0x0020, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kMazeGameGuy_Dmd[sprite_graphics[k] * 2 + sprite_D[k] * 4], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void CrystalMaiden_Draw(int k) { // 8dce5f
int j = sprite_D[k] * 2 + sprite_graphics[k];
BYTE(dma_var6) = kCrystalMaiden_Dma[j * 2 + 0];
BYTE(dma_var7) = kCrystalMaiden_Dma[j * 2 + 1];
Sprite_DrawMultiplePlayerDeferred(k, kCrystalMaiden_SpriteData + j * 2, 2, NULL);
}
void Priest_Draw(int k) { // 8dcf31
int j = sprite_D[k] * 2 + sprite_graphics[k];
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, kPriest_Dmd + j * 2, 2, &info);
SpriteDraw_Shadow(k, &info);
}
uint8 FluteBoy_Draw(int k) { // 8dcfd9
static const DrawMultipleData kFluteBoy_Dmd[16] = {
{-1, -1, 0x0abe, 0},
{ 0, 0, 0x0aaa, 2},
{ 0, -10, 0x0aa8, 2},
{ 0, 0, 0x0aaa, 2},
{-1, -1, 0x0abe, 0},
{ 0, 8, 0x0abf, 0},
{ 0, -10, 0x0aa8, 2},
{ 0, 0, 0x0aaa, 2},
{-1, -1, 0x0abe, 0},
{ 0, 0, 0x0aaa, 2},
{ 0, -10, 0x0aa8, 2},
{ 0, 0, 0x0aaa, 2},
{-1, -1, 0x0abe, 0},
{ 0, 8, 0x0abf, 0},
{ 0, -10, 0x0aa8, 2},
{ 0, 0, 0x0aaa, 2},
};
Oam_AllocateFromRegionB(0x10);
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kFluteBoy_Dmd[sprite_D[k] * 8 + sprite_graphics[k] * 4], 4, &info);
return (info.x | info.y) >> 8;
}
void FluteAardvark_Draw(int k) { // 8dd040
static const DrawMultipleData kFluteAardvark_Dmd[8] = {
{0, -16, 0x06e6, 2},
{0, -8, 0x06c8, 2},
{0, -16, 0x06e6, 2},
{0, -8, 0x06ca, 2},
{0, -16, 0x06e8, 2},
{0, -8, 0x06ca, 2},
{0, -16, 0x00cc, 2},
{0, -8, 0x00dc, 2},
};
Sprite_DrawMultiplePlayerDeferred(k, &kFluteAardvark_Dmd[sprite_graphics[k] * 2], 2, NULL);
}
void DustCloud_Draw(int k) { // 8dd120
static const DrawMultipleData kDustCloud_Dmd[24] = {
{ 0, -3, 0x008b, 0},
{ 3, 0, 0x009b, 0},
{-3, 0, 0xc08b, 0},
{ 0, 3, 0xc09b, 0},
{ 0, -5, 0x008a, 2},
{ 5, 0, 0x008a, 2},
{-5, 0, 0x008a, 2},
{ 0, 5, 0x008a, 2},
{ 0, -7, 0x0086, 2},
{ 7, 0, 0x0086, 2},
{-7, 0, 0x0086, 2},
{ 0, 7, 0x0086, 2},
{ 0, -9, 0x8086, 2},
{ 9, 0, 0x8086, 2},
{-9, 0, 0x8086, 2},
{ 0, 9, 0x8086, 2},
{ 0, -9, 0xc086, 2},
{ 9, 0, 0xc086, 2},
{-9, 0, 0xc086, 2},
{ 0, 9, 0xc086, 2},
{ 0, -7, 0x4086, 2},
{ 7, 0, 0x4086, 2},
{-7, 0, 0x4086, 2},
{ 0, 7, 0x4086, 2},
};
sprite_oam_flags[k] = 0x14;
Sprite_DrawMultiple(k, &kDustCloud_Dmd[sprite_graphics[k] * 4], 4, NULL);
}
void MedallionTablet_Draw(int k) { // 8dd1e2
static const DrawMultipleData kMedallionTablet_Dmd[20] = {
{-8, -16, 0x008c, 2},
{ 8, -16, 0x408c, 2},
{-8, 0, 0x00ac, 2},
{ 8, 0, 0x40ac, 2},
{-8, -13, 0x008a, 2},
{ 8, -13, 0x408a, 2},
{-8, 0, 0x00ac, 2},
{ 8, 0, 0x40ac, 2},
{-8, -8, 0x008a, 2},
{ 8, -8, 0x408a, 2},
{-8, 0, 0x00ac, 2},
{ 8, 0, 0x40ac, 2},
{-8, -4, 0x008a, 2},
{ 8, -4, 0x408a, 2},
{-8, 0, 0x00aa, 2},
{ 8, 0, 0x40aa, 2},
{-8, 0, 0x00aa, 2},
{ 8, 0, 0x40aa, 2},
{-8, 0, 0x00aa, 2},
{ 8, 0, 0x40aa, 2},
};
Sprite_DrawMultiplePlayerDeferred(k, &kMedallionTablet_Dmd[sprite_graphics[k] * 4], 4, NULL);
}
void Uncle_Draw(int k) { // 8dd391
Oam_AllocateFromRegionB(0x18);
const DrawMultipleData *src = &kUncleDraw_Table[sprite_D[k] * 12 + sprite_graphics[k] * 6];
int j = sprite_D[k] * 2 + sprite_graphics[k];
link_dma_var3 = kUncleDraw_Dma3[j];
link_dma_var4 = kUncleDraw_Dma4[j];
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, src, 6, &info);
if (sprite_D[k] != 0 && sprite_D[k] != 3)
SpriteDraw_Shadow(k, &info);
}
void BugNetKid_Draw(int k) { // 8dd47b
static const DrawMultipleData kBugNetKid_Dmd[18] = {
{ 4, 0, 0x0027, 0},
{ 0, -5, 0x000e, 2},
{-8, 6, 0x040a, 2},
{ 8, 6, 0x440a, 2},
{-8, 14, 0x840a, 2},
{ 8, 14, 0xc40a, 2},
{ 0, -5, 0x000e, 2},
{ 0, -5, 0x000e, 2},
{-8, 6, 0x040a, 2},
{ 8, 6, 0x440a, 2},
{-8, 14, 0x840a, 2},
{ 8, 14, 0xc40a, 2},
{ 0, -5, 0x002e, 2},
{ 0, -5, 0x002e, 2},
{-8, 7, 0x040a, 2},
{ 8, 7, 0x440a, 2},
{-8, 14, 0x840a, 2},
{ 8, 14, 0xc40a, 2},
};
Sprite_DrawMultiplePlayerDeferred(k, &kBugNetKid_Dmd[sprite_graphics[k] * 6], 6, NULL);
}
void Bomber_Draw(int k) { // 8dd56c
static const DrawMultipleData kBomber_Dmd[22] = {
{ 0, 0, 0x40c6, 2},
{ 0, 0, 0x40c6, 2},
{ 0, 0, 0x40c4, 2},
{ 0, 0, 0x40c4, 2},
{ 0, 0, 0x00c6, 2},
{ 0, 0, 0x00c6, 2},
{ 0, 0, 0x00c4, 2},
{ 0, 0, 0x00c4, 2},
{-8, 0, 0x00c0, 2},
{ 8, 0, 0x40c0, 2},
{-8, 0, 0x00c2, 2},
{ 8, 0, 0x40c2, 2},
{-8, 0, 0x00e0, 2},
{ 8, 0, 0x40e0, 2},
{-8, 0, 0x00e2, 2},
{ 8, 0, 0x40e2, 2},
{-8, 0, 0x00e4, 2},
{ 8, 0, 0x40e4, 2},
{ 0, 0, 0x40e6, 2},
{ 0, 0, 0x40e6, 2},
{ 0, 0, 0x00e6, 2},
{ 0, 0, 0x00e6, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kBomber_Dmd[sprite_graphics[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void SpriteDraw_ZirroBomb(int k) { // 8dd606
static const DrawMultipleData kBomberPellet_Dmd[15] = {
{-11, 0, 0x019b, 0},
{ 0, -8, 0xc19b, 0},
{ 6, 6, 0x419b, 0},
{-15, -6, 0x018a, 2},
{ -4, -14, 0x018a, 2},
{ 2, 0, 0x018a, 2},
{-15, -6, 0x0186, 2},
{ -4, -14, 0x0186, 2},
{ 2, 0, 0x0186, 2},
{ -4, -4, 0x0186, 2},
{ -4, -4, 0x0186, 2},
{ -4, -4, 0x0186, 2},
{ -4, -4, 0x01aa, 2},
{ -4, -4, 0x01aa, 2},
{ -4, -4, 0x01aa, 2},
};
if (!sprite_delay_main[k])
sprite_state[k] = 0;
Sprite_DrawMultiple(k, &kBomberPellet_Dmd[(sprite_delay_main[k] >> 2) * 3], 3, NULL);
}
void PlayerBee_HoneInOnTarget(int j, int k) { // 8dd631
if (sprite_type[j] != 0x88 && (sprite_flags[j] & 2))
return;
uint16 x = Sprite_GetX(j);
uint16 y = Sprite_GetY(j);
if ((uint16)(cur_sprite_x - x + 16) >= 24 ||
(uint16)(cur_sprite_y - y - 8) >= 24)
return;
if (sprite_type[j] == 0x75) {
sprite_E[j] = k + 1;
return;
}
Ancilla_CheckDamageToSprite_preset(j, 1);
sprite_F[j] = 15;
sprite_x_recoil[j] = sprite_x_vel[k] << 1;
sprite_y_recoil[j] = sprite_y_vel[k] << 1;
sprite_B[k]++;
}
void Pikit_Draw(int k) { // 8dd6e6
static const DrawMultipleData kPikit_Dmd[8] = {
{ 0, 0, 0x00c8, 2},
{ 0, 0, 0x00c8, 2},
{ 0, 0, 0x00ca, 2},
{ 0, 0, 0x00ca, 2},
{-8, 0, 0x00cc, 2},
{ 8, 0, 0x40cc, 2},
{-8, 0, 0x00ce, 2},
{ 8, 0, 0x40ce, 2},
};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
SpriteDraw_Pikit_Tongue(k, &info);
OamEnt *oam = GetOamCurPtr();
tmp_counter = oam->x;
byte_7E0FB6 = oam->y;
oam_cur_ptr += 24;
oam_ext_cur_ptr += 6;
Sprite_DrawMultiple(k, &kPikit_Dmd[sprite_graphics[k] * 2], 2, &info);
uint8 bak = sprite_flags2[k];
sprite_flags2[k] -= 6;
SpriteDraw_Shadow(k, &info);
sprite_flags2[k] = bak;
SpriteDraw_Pikit_Loot(k, &info);
}
void SpriteDraw_Pikit_Tongue(int k, PrepOamCoordsRet *info) { // 8dd74a
static const uint8 kPikit_TongueMult[4] = {0x33, 0x66, 0x99, 0xcc};
static const uint8 kPikit_Draw_Char[8] = {0xee, 0xfd, 0xed, 0xfd, 0xee, 0xfd, 0xed, 0xfd};
static const uint8 kPikit_Draw_Flags[8] = {0, 0, 0, 0x40, 0x40, 0xc0, 0x80, 0x80};
if (sprite_ai_state[k] != 2 || sprite_pause[k])
return;
OamEnt *oam = GetOamCurPtr();
int x = info->x + 4, y = info->y + 3;
oam[5].x = x;
oam[5].y = y;
oam[0].x = x + sprite_A[k];
oam[0].y = y + sprite_B[k];
oam[0].charnum = oam[5].charnum = 0xfe;
oam[0].flags = oam[5].flags = info->flags;
oam++;
int g = sprite_D[k];
for (int i = 3; i >= 0; i--, oam++) {
oam->x = x + (int8)sprite_A[k] * kPikit_TongueMult[i] / 256;
oam->y = y + (int8)sprite_B[k] * kPikit_TongueMult[i] / 256;
oam->charnum = kPikit_Draw_Char[g];
oam->flags = kPikit_Draw_Flags[g] | info->flags;
}
Sprite_CorrectOamEntries(k, 5, 0);
}
void SpriteDraw_Pikit_Loot(int k, PrepOamCoordsRet *info) { // 8dd858
static const int8 kPikit_DrawGrabbedItem_X[20] = {
-4, 4, -4, 4, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, -4, 4, -4, 4,
};
static const int8 kPikit_DrawGrabbedItem_Y[20] = {
-4, -4, 4, 4, -4, -4, 4, 4, -4, -4, 4, 4, -4, -4, 4, 4, -4, -4, 4, 4,
};
static const uint8 kPikit_DrawGrabbedItem_Char[20] = {
0x6e, 0x6f, 0x7e, 0x7f, 0x63, 0x7c, 0x73, 0x7c, 0xb, 0x7c, 0x1b, 0x7c, 0xec, 0xf9, 0xfc, 0xf9,
0xea, 0xeb, 0xfa, 0xfb,
};
static const uint8 kPikit_DrawGrabbedItem_Flags[5] = {0x24, 0x24, 0x28, 0x29, 0x2f};
if (!sprite_G[k])
return;
int g = sprite_G[k] - 1;
if (g == 3)
g = sprite_subtype[k] + 2;
Oam_AllocateFromRegionC(0x10);
OamEnt *oam = GetOamCurPtr();
for (int i = 3; i >= 0; i--, oam++) {
int j = g * 4 + i;
oam->x = tmp_counter + kPikit_DrawGrabbedItem_X[j];
oam->y = byte_7E0FB6 + kPikit_DrawGrabbedItem_Y[j];
oam->charnum = kPikit_DrawGrabbedItem_Char[j];
oam->flags = kPikit_DrawGrabbedItem_Flags[g];
}
Sprite_CorrectOamEntries(k, 3, 0);
}
void Kholdstare_Draw(int k) { // 8dd98f
static const DrawMultipleData kKholdstare_Dmd[16] = {
{-8, -8, 0x0080, 2},
{ 8, -8, 0x0082, 2},
{-8, 8, 0x00a0, 2},
{ 8, 8, 0x00a2, 2},
{-7, -7, 0x0080, 2},
{ 7, -7, 0x0082, 2},
{-7, 7, 0x00a0, 2},
{ 7, 7, 0x00a2, 2},
{-7, -7, 0x0084, 2},
{ 7, -7, 0x0086, 2},
{-7, 7, 0x00a4, 2},
{ 7, 7, 0x00a6, 2},
{-8, -8, 0x0084, 2},
{ 8, -8, 0x0086, 2},
{-8, 8, 0x00a4, 2},
{ 8, 8, 0x00a6, 2},
};
static const int8 kKholdstare_Draw_X[16] = {8, 7, 4, 2, 0, -2, -4, -7, -8, -7, -4, -2, 0, 2, 4, 7};
static const int8 kKholdstare_Draw_Y[16] = {0, 2, 4, 7, 8, 7, 4, 2, 0, -2, -4, -7, -8, -7, -4, -2};
static const uint8 kKholdstare_Draw_Char[16] = {0xac, 0xac, 0xaa, 0x8c, 0x8c, 0x8c, 0xaa, 0xac, 0xac, 0xaa, 0xaa, 0x8c, 0x8c, 0x8c, 0xaa, 0xac};
static const uint8 kKholdstare_Draw_Flags[16] = {0x40, 0x40, 0x40, 0, 0, 0, 0, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int j = sprite_A[k];
uint16 x = info.x + kKholdstare_Draw_X[j];
uint16 y = info.y + kKholdstare_Draw_Y[j];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kKholdstare_Draw_Char[j];
oam->flags = kKholdstare_Draw_Flags[j] | info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
oam_cur_ptr += 4, oam_ext_cur_ptr += 1;
Sprite_DrawMultiple(k, &kKholdstare_Dmd[sprite_graphics[k] * 4], 4, &info);
}
int Sprite_SpawnFireball(int k) { // 8dda06
SpriteSpawnInfo info;
SpriteSfx_QueueSfx3WithPan(k, 0x19);
int j = Sprite_SpawnDynamicallyEx(k, 0x55, &info, 13);
if (j < 0)
return j;
Sprite_SetX(j, info.r0_x + 4);
Sprite_SetY(j, info.r2_y + 4 - info.r4_z);
sprite_flags3[j] = sprite_flags3[j] & 0xfe | 0x40;
sprite_oam_flags[j] = 6;
sprite_flags4[j] = 0x54;
sprite_E[j] = 0x54;
sprite_flags2[j] = 0x20;
Sprite_ApplySpeedTowardsLink(j, 0x20);
sprite_delay_main[j] = 20;
sprite_delay_aux1[j] = 16;
sprite_flags5[j] = 0;
sprite_defl_bits[j] = 0x48;
return j;
}
void ArcheryGameGuy_Draw(int k) { // 8ddac4
static const int8 kArcheryGameGuy_Draw_X[15] = {0, 0, 0, 0, 0, -5, 0, -1, -1, 0, 0, 0, 0, 1, 1};
static const int8 kArcheryGameGuy_Draw_Y[15] = {0, -10, -10, 0, -10, -3, 0, -10, -10, 0, -10, -10, 0, -10, -10};
static const uint8 kArcheryGameGuy_Draw_Char[15] = {0x26, 6, 6, 8, 6, 0x3a, 0x26, 6, 6, 0x26, 6, 6, 0x26, 6, 6};
static const uint8 kArcheryGameGuy_Draw_Flags[15] = {8, 6, 6, 8, 6, 8, 8, 6, 6, 8, 6, 6, 8, 6, 6};
static const uint8 kArcheryGameGuy_Draw_Ext[15] = {2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2};
Oam_AllocateDeferToPlayer(k);
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
for (int i = 2; i >= 0; i--, oam++) {
int j = g * 3 + i;
oam->x = info.x + kArcheryGameGuy_Draw_X[j];
oam->y = info.y + kArcheryGameGuy_Draw_Y[j];
oam->charnum = kArcheryGameGuy_Draw_Char[j];
oam->flags = kArcheryGameGuy_Draw_Flags[j] | info.flags;
bytewise_extended_oam[oam - oam_buf] = kArcheryGameGuy_Draw_Ext[j];
}
SpriteDraw_Shadow(k, &info);
}
void ShopKeeper_RapidTerminateReceiveItem() { // 8ffaea
for (int i = 4; i >= 0; i--) {
if (ancilla_type[i] == 0x22)
ancilla_aux_timer[i] = 1;
}
}
void Sprite_InitializeSecondaryItemMinigame(int what) { // 8ffd86
is_archer_or_shovel_game = what;
Link_ResetProperties_C();
for (int k = 4; k >= 0; k--) {
if (ancilla_type[k] == 0x30 || ancilla_type[k] == 0x31) {
ancilla_type[k] = 0;
} else if (ancilla_type[k] == 5) {
flag_for_boomerang_in_place = 0;
ancilla_type[k] = 0;
}
}
}
void Waterfall(int k) { // 9af5b8
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckDamageToLink_same_layer(k)) {
if (BYTE(overworld_screen_index) == 0x43)
AncillaAdd_GTCutscene();
else
AncillaAdd_WaterfallSplash();
}
}
void Sprite_BatCrash(int k) { // 9af5d9
static const uint16 kRetreatBat_Xpos[4] = {0x7dc, 0x7f0, 0x820, 0x818};
static const uint16 kRetreatBat_Ypos[4] = {0x62e, 0x636, 0x630, 0x5e0};
static const uint8 kRetreatBat_Delay[5] = {4, 3, 4, 6, 0};
int j;
RetreatBat_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXY(k);
BatCrash_DrawHardcodedGarbage(k);
bg1_y_offset = 0;
if (sprite_delay_aux3[k]) {
if (sprite_delay_aux3[k] == 1)
sound_effect_ambient = 5;
bg1_y_offset = sprite_delay_aux3[k] & 1 ? 1 : -1;
}
if (!sprite_delay_main[k]) {
sprite_graphics[k] = sprite_graphics[k] + 1 & 3;
if (sprite_graphics[k] == 0 && sprite_ai_state[k] < 2)
SpriteSfx_QueueSfx2WithPan(k, 0x3);
sprite_delay_main[k] = kRetreatBat_Delay[sprite_D[k]];
}
switch(sprite_ai_state[k]) {
case 0: {
j = sprite_A[k];
if (kRetreatBat_Xpos[j] < cur_sprite_x) {
if (j >= 2) {
sprite_ai_state[k]++;
sprite_delay_aux1[k] = 208;
}
sprite_A[k]++;
sprite_D[k]++;
}
update_pos:
if (!(frame_counter & 7))
sprite_y_vel[k] += (kRetreatBat_Ypos[j] >= cur_sprite_y) ? 1 : -1;
if (!(frame_counter & 15))
sprite_x_vel[k]++;
break;
}
case 1:
if (!sprite_delay_aux1[k]) {
sprite_ai_state[k]++;
SpriteSfx_QueueSfx3WithPan(k, 0x26);
sprite_D[k]++;
sprite_x_lo[k] = 232;
sprite_x_hi[k] = 7;
sprite_y_lo[k] = 224;
sprite_y_hi[k] = 5;
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 64;
sprite_delay_aux1[k] = 45;
} else {
if (!(frame_counter & 3))
sprite_x_vel[k]--;
j = sprite_A[k];
goto update_pos;
}
break;
case 2:
if (!sprite_delay_aux1[k]) {
sprite_y_vel[k] = 0;
sprite_delay_aux1[k] = 96;
sprite_ai_state[k]++;
}
if (sprite_delay_aux1[k] == 9) {
BatCrash_SpawnDebris(k);
CreatePyramidHole();
}
break;
case 3: // Finishing Up
if (!sprite_delay_aux1[k]) {
sprite_state[k] = 0;
overworld_map_state++;
}
break;
}
}
void Sprite_SpawnBatCrashCutscene() { // 9af6f5
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(0, 0x37, &info);
if (j >= 0) {
sprite_y_vel[j] = 0;
sprite_B[j] = 0;
sprite_D[j] = 0;
sprite_floor[j] = 0;
sprite_subtype2[j] = 1;
sprite_flags2[j] = 1;
sprite_flags3[j] = 1;
sprite_oam_flags[j] = 1;
sprite_x_lo[j] = 204;
sprite_x_hi[j] = 7;
sprite_y_lo[j] = 50;
sprite_y_hi[j] = 6;
sprite_defl_bits[j] = 128;
}
}
void BatCrash_DrawHardcodedGarbage(int k) { // 9af750
static const OamEntSigned kRetreatBat_Oams[8] = {
{ 104, -105, 0x57, 0x01},
{ 120, -105, 0x57, 0x01},
{-120, -105, 0x57, 0x01},
{ 104, -89, 0x57, 0x01},
{ 120, -89, 0x57, 0x01},
{-120, -89, 0x57, 0x01},
{ 101, -112, 0x57, 0x01},
{-117, -112, 0x57, 0x01},
};
memcpy(oam_buf + 76, kRetreatBat_Oams, 32);
for (int i = 0; i < 9; i++) // wtf 9
bytewise_extended_oam[i + 76] = 2;
}
void BatCrash_SpawnDebris(int k) { // 9af7e5
static const int8 kPyramidDebris_X[30] = {
-8, 0, 8, 16, 24, 32, -8, 0, 8, 16, 24, 32, -8, 0, 8, 16,
24, 32, -8, 0, 8, 16, 24, 32, -8, 0, 8, 16, 24, 32,
};
static const int8 kPyramidDebris_Y[30] = {
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
};
static const int8 kPyramidDebris_Xvel[30] = {
-30, -25, -8, 8, 25, 30, -50, -45, -20, 20, 45, 50, -50, -35, -25, 25,
35, 50, -45, -50, -60, 60, 50, 45, -30, -35, -40, 40, 35, 30,
};
static const int8 kPyramidDebris_Yvel[30] = {
2, 5, 10, 10, 5, 2, 5, 20, 30, 30, 20, 5, 10, 30, 40, 40,
30, 10, -20, -40, -60, -60, -40, -20, -10, -20, -40, -40, -20, -10,
};
for (int j = 29; j >= 0; j--) {
GarnishSpawn_PyramidDebris(kPyramidDebris_X[j], kPyramidDebris_Y[j], kPyramidDebris_Xvel[j], kPyramidDebris_Yvel[j]);
}
sprite_delay_aux3[k] = 32;
}
void RetreatBat_Draw(int k) { // 9af833
static const DrawMultipleData kRetreatBat_Dmds[18] = {
{ 0, 0, 0x044b, 0},
{ 5, -4, 0x045b, 0},
{-2, -4, 0x0464, 2},
{-2, -4, 0x0449, 2},
{-8, -9, 0x046c, 2},
{ 8, -9, 0x446c, 2},
{-8, -7, 0x044c, 2},
{ 8, -7, 0x444c, 2},
{-8, -9, 0x0444, 2},
{ 8, -9, 0x4444, 2},
{-8, -8, 0x0462, 2},
{ 8, -8, 0x4462, 2},
{-8, -7, 0x0460, 2},
{ 8, -7, 0x4460, 2},
{ 0, 0, 0x044e, 2},
{16, 0, 0x444e, 2},
{ 0, 16, 0x046e, 2},
{16, 16, 0x446e, 2},
};
static const uint8 kOffs[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 6, 6, 8, 10, 12, 10, 14, 14, 14, 14};
static const uint8 kCount[20] = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, };
oam_cur_ptr = 0x960;
oam_ext_cur_ptr = 0xa78;
int j = sprite_D[k] * 4 + sprite_graphics[k];
Sprite_DrawMultiple(k, &kRetreatBat_Dmds[kOffs[j]], kCount[j], NULL);
}
void DrinkingGuy_Draw(int k) { // 9af88c
static const DrawMultipleData kDrinkingGuy_Dmd[6] = {
{8, 2, 0x00ae, 0},
{0, -9, 0x0822, 2},
{0, 0, 0x0006, 2},
{7, 0, 0x00af, 0},
{0, -9, 0x0822, 2},
{0, 0, 0x0006, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kDrinkingGuy_Dmd[sprite_graphics[k] * 3], 3, &info);
SpriteDraw_Shadow(k, &info);
}
void Lady_Draw(int k) { // 9af92c
static const DrawMultipleData kLadyDmd[16] = {
{0, -8, 0x00e0, 2},
{0, 0, 0x00e8, 2},
{0, -7, 0x00e0, 2},
{0, 1, 0x40e8, 2},
{0, -8, 0x00c0, 2},
{0, 0, 0x00c2, 2},
{0, -7, 0x00c0, 2},
{0, 1, 0x40c2, 2},
{0, -8, 0x00e2, 2},
{0, 0, 0x00e4, 2},
{0, -7, 0x00e2, 2},
{0, 1, 0x00e6, 2},
{0, -8, 0x40e2, 2},
{0, 0, 0x40e4, 2},
{0, -7, 0x40e2, 2},
{0, 1, 0x40e6, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kLadyDmd[sprite_graphics[k] * 2 + sprite_D[k] * 4], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Lanmola_SpawnShrapnel(int k) { // 9af981
static const int8 kLanmolaShrapnel_Yvel[8] = {28, -28, 28, -28, 0, 36, 0, -36};
static const int8 kLanmolaShrapnel_Xvel[8] = {-28, -28, 28, 28, -36, 0, 36, 0};
tmp_counter = (sprite_state[0] + sprite_state[1] + sprite_state[2]) < 10 ? 7 : 3;
do {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xC2, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_x_lo[j] = info.r0_x + 4;
sprite_y_lo[j] = info.r2_y + 4;
sprite_ignore_projectile[j] = 1;
sprite_bump_damage[j] = 1;
sprite_flags4[j] = 1;
sprite_z[j] = 0;
sprite_flags2[j] = 0x20;
sprite_x_vel[j] = kLanmolaShrapnel_Xvel[tmp_counter];
sprite_y_vel[j] = kLanmolaShrapnel_Yvel[tmp_counter];
sprite_graphics[j] = GetRandomNumber() & 1;
}
} while (!sign8(--tmp_counter));
}
void Sprite_Cukeman(int k) { // 9afa0c
if (sprite_head_dir[k] == 0)
return;
if (sprite_state[k] == 9 && !(submodule_index | flag_unk1) &&
(uint16)(cur_sprite_x - link_x_coord + 0x18) < 0x30 &&
(uint16)(link_y_coord - cur_sprite_y + 0x20) < 0x30 &&
(filtered_joypad_L & 0x80)) {
dialogue_message_index = 0x17a + (sprite_subtype[k]++ & 1);
Sprite_ShowMessageMinimal();
}
uint8 old = sprite_oam_flags[k] & 0xf0;
sprite_oam_flags[k] = old | 8;
Cukeman_Draw(k);
sprite_oam_flags[k] = old | 0xd;
Oam_AllocateFromRegionA(0x10);
}
void Cukeman_Draw(int k) { // 9afb0e
static const DrawMultipleData kCukeman_Dmd[18] = {
{ 0, 0, 0x01f3, 0},
{ 7, 0, 0x41f3, 0},
{ 4, 7, 0x07e0, 0},
{-1, 2, 0x01f3, 0},
{ 6, 1, 0x41f3, 0},
{ 4, 8, 0x07e0, 0},
{ 1, 1, 0x01f3, 0},
{ 8, 2, 0x41f3, 0},
{ 4, 8, 0x07e0, 0},
{-2, 0, 0x01f3, 0},
{10, 0, 0x41f3, 0},
{ 4, 7, 0x07e0, 0},
{ 0, 0, 0x01f3, 0},
{ 8, 0, 0x41f3, 0},
{ 4, 6, 0x07e0, 0},
{-5, 0, 0x01f3, 0},
{16, 0, 0x41f3, 0},
{ 4, 8, 0x07e0, 0},
};
Sprite_DrawMultiple(k, &kCukeman_Dmd[sprite_graphics[k] * 3], 3, NULL);
}
void RunningBoy_SpawnDustGarnish(int k) { // 9afb2c
if (++sprite_die_action[k] & 0xf)
return;
int j = GarnishAllocForce();
garnish_type[j] = 20;
garnish_active = 20;
Garnish_SetX(j, Sprite_GetX(k) + 4);
Garnish_SetY(j, Sprite_GetY(k) + 28);
garnish_countdown[j] = 10;
}
void MovableMantle_Draw(int k) { // 9afcb3
Oam_AllocateFromRegionB(0x20);
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
for (int i = 5; i >= 0; i--, oam++) {
oam->x = kMovableMantle_X[i] + info.x;
oam->y = kMovableMantle_Y[i] + info.y;
oam->charnum = kMovableMantle_Char[i];
oam->flags = kMovableMantle_Flags[i];
}
Sprite_CorrectOamEntries(k, 5, 2);
}
void Mothula_Draw(int k) { // 9afdb5
static const DrawMultipleData kMothula_Dmd[24] = {
{-24, -8, 0x0080, 2},
{ -8, -8, 0x0082, 2},
{ 8, -8, 0x4082, 2},
{ 24, -8, 0x4080, 2},
{-24, 8, 0x00a0, 2},
{ -8, 8, 0x00a2, 2},
{ 8, 8, 0x40a2, 2},
{ 24, 8, 0x40a0, 2},
{-24, -8, 0x0084, 2},
{ -8, -8, 0x0086, 2},
{ 8, -8, 0x4086, 2},
{ 24, -8, 0x4084, 2},
{-24, 8, 0x00a4, 2},
{ -8, 8, 0x00a6, 2},
{ 8, 8, 0x40a6, 2},
{ 24, 8, 0x40a4, 2},
{ -8, -8, 0x0088, 2},
{ -8, -8, 0x0088, 2},
{ 8, -8, 0x4088, 2},
{ 8, -8, 0x4088, 2},
{ -8, 8, 0x00a8, 2},
{ -8, 8, 0x00a8, 2},
{ 8, 8, 0x40a8, 2},
{ 8, 8, 0x40a8, 2},
};
oam_cur_ptr = 0x920;
oam_ext_cur_ptr = 0xa68;
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kMothula_Dmd[sprite_graphics[k] * 8], 8, &info);
if (sprite_pause[k])
return;
info.y += sprite_z[k];
static const int8 kMothula_Draw_X[27] = {
0, 3, 6, 9, 12, -3, -6, -9, -12, 0, 2, 4, 6, 8, -2, -4,
-6, -8, 0, 1, 2, 3, 4, -1, -2, -3, -4,
};
OamEnt *oam = GetOamCurPtr() + 10;
int g = sprite_graphics[k];
for (int i = 8; i >= 0; i--, oam++) {
uint16 x = info.x + kMothula_Draw_X[g * 9 + i];
uint16 y = info.y + 16;
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = 0x6c;
oam->flags = 0x24;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
}
void BottleMerchant_BuyBee(int k) { // 9afe88
static const int8 kBottleVendor_GoodBeeX[5] = {-6, -3, 0, 4, 7};
static const int8 kBottleVendor_GoodBeeY[5] = {11, 14, 16, 14, 11};
SpriteSpawnInfo info;
SpriteSfx_QueueSfx3WithPan(k, 0x13);
tmp_counter = 4;
do {
int j = Sprite_SpawnDynamically(k, 0xd8, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_x_lo[j] = info.r0_x + 4;
sprite_stunned[j] = 0xff;
sprite_x_vel[j] = kBottleVendor_GoodBeeX[tmp_counter];
sprite_y_vel[j] = kBottleVendor_GoodBeeY[tmp_counter];
sprite_z_vel[j] = 32;
sprite_delay_aux4[j] = 32;
}
} while (!sign8(--tmp_counter));
}
void Sprite_ChickenLady(int k) { // 9afed3
sprite_D[k] = 1;
Lady_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_delay_main[k] == 1) {
dialogue_message_index = 0x17d;
Sprite_ShowMessageMinimal();
}
sprite_graphics[k] = frame_counter >> 4 & 1;
}
void Overworld_DrawWoodenDoor(uint16 pos, bool unlocked) { // 9bc952
Overworld_DrawMap16_Persist(pos, unlocked ? 0xda5 : 0xda4);
Overworld_DrawMap16_Persist(pos+2, unlocked ? 0xda7 : 0xda6);
nmi_load_bg_from_vram = 1;
}
void Sprite_D4_Landmine(int k) { // 9d8099
static const uint8 kLandMine_OamFlags[4] = {4, 2, 8, 2};
Landmine_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!Landmine_CheckDetonationFromHammer(k)) {
if (!sprite_delay_main[k]) {
sprite_oam_flags[k] = 4;
if (Sprite_CheckDamageToLink(k))
sprite_delay_main[k] = 8;
return;
}
if (sprite_delay_main[k] != 1) {
sprite_oam_flags[k] = kLandMine_OamFlags[sprite_delay_main[k] >> 1 & 3];
return;
}
}
sprite_state[k] = 0;
int j = Sprite_SpawnBomb(k);
if (j >= 0) {
sprite_state[j] = 6;
sprite_C[j] = 2;
sprite_oam_flags[j] = 2;
sprite_flags4[j] = 9;
sprite_delay_aux1[j] = 31;
sprite_flags2[j] = 3;
sound_effect_1 = Sprite_CalculateSfxPan(k) | 12;
}
}
void Landmine_Draw(int k) { // 9d810c
static const DrawMultipleData kLandmine_Dmd[2] = {
{0, 4, 0x0070, 0},
{8, 4, 0x4070, 0},
};
Oam_AllocateFromRegionB(8);
if (byte_7E0FC6 >= 3)
return;
Sprite_DrawMultiple(k, kLandmine_Dmd, 2, NULL);
}
void Sprite_D3_Stal(int k) { // 9d8129
static const uint8 kStal_Gfx[5] = {2, 2, 1, 0, 1};
if (byte_7E0FC6 < 3) {
if (!sprite_ai_state[k])
Oam_AllocateFromRegionB(4);
Stal_Draw(k);
}
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
switch(sprite_ai_state[k]) {
case 0: // dormant
sprite_ignore_projectile[k] = 1;
if (Sprite_CheckDamageToLink_same_layer(k)) {
Sprite_NullifyHookshotDrag();
Sprite_RepelDash();
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 64;
SpriteSfx_QueueSfx2WithPan(k, 0x22);
}
}
if (sprite_delay_main[k] != 0) {
if (sprite_delay_main[k] - 1) {
sprite_hit_timer[k] = (sprite_delay_main[k] - 1) | 64;
} else {
sprite_ignore_projectile[k] = 0;
sprite_ai_state[k]++;
sprite_hit_timer[k] = 0;
sprite_flags3[k] &= ~0x40;
sprite_flags2[k] &= ~0x80;
}
}
break;
case 1: // active
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXYZ(k);
Sprite_CheckTileCollision(k);
sprite_z_vel[k]-=2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 16;
Sprite_ApplySpeedTowardsLink(k, 12);
}
if (!(frame_counter & 3) && ++sprite_subtype2[k] == 5)
sprite_subtype2[k] = 0;
sprite_graphics[k] = kStal_Gfx[sprite_subtype2[k]];
break;
}
}
void Stal_Draw(int k) { // 9d820c
static const DrawMultipleData kStal_Dmd[6] = {
{0, 0, 0x0044, 2},
{4, 11, 0x0070, 0},
{0, 0, 0x0044, 2},
{4, 12, 0x0070, 0},
{0, 0, 0x0044, 2},
{4, 13, 0x0070, 0},
};
PrepOamCoordsRet info;
int n = sprite_ai_state[k] ? 2 : 1;
Sprite_DrawMultiple(k, &kStal_Dmd[sprite_graphics[k] * 2], n, &info);
if (sprite_ai_state[k])
SpriteDraw_Shadow(k, &info);
}
void Sprite_D2_FloppingFish(int k) { // 9d8235
static const int8 kFish_Xvel[8] = {0, 12, 16, 12, 0, -12, -16, -12};
static const int8 kFish_Yvel[8] = {-16, -12, 0, 12, 16, 12, 0, -12};
static const uint8 kFish_Tab1[2] = {2, 0};
static const uint8 kFish_Gfx[3] = {1, 5, 3};
static const uint8 kFish_Gfx2[17] = {5, 5, 6, 6, 5, 5, 4, 4, 3, 7, 7, 8, 8, 7, 7, 8, 8 };
if (byte_7E0FC6 < 3)
Fish_Draw(k);
if (sprite_state[k] == 10) {
sprite_ai_state[k] = 4;
sprite_graphics[k] = (frame_counter >> 4 & 1) + 3;
}
if (Sprite_ReturnIfInactive(k))
return;
switch (sprite_ai_state[k]) {
case 0: // check deep water
Sprite_CheckTileCollision(k);
if (sprite_tiletype == 8)
sprite_state[k] = 0;
else
sprite_ai_state[k] = 1;
break;
case 1: // flop around
Sprite_CheckIfLifted_permissive(k);
Sprite_BounceFromTileCollision(k);
Sprite_MoveXYZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
if (sprite_tiletype == 9) {
Sprite_SpawnSmallSplash(k);
} else if (sprite_tiletype == 8) {
sprite_state[k] = 0;
Sprite_SpawnSmallSplash(k);
}
sprite_z_vel[k] = (GetRandomNumber() & 15) + 16;
int j = GetRandomNumber() & 7;
sprite_x_vel[k] = kFish_Xvel[j];
sprite_y_vel[k] = kFish_Yvel[j];
sprite_D[k]++;
sprite_subtype2[k] = 3;
}
sprite_subtype2[k]++;
if (!(sprite_subtype2[k] & 7)) {
int j = sprite_D[k] & 1;
if (sprite_A[k] != kFish_Tab1[j])
sprite_A[k] += j ? -1 : 1;
}
sprite_graphics[k] = kFish_Gfx[sprite_A[k]] + (frame_counter >> 3 & 1);
break;
case 2: // pause before leap
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 3;
sprite_z_vel[k] = 48;
Sprite_SpawnSmallSplash(k);
}
break;
case 3: // leaping
Sprite_MoveZ(k);
sprite_z_vel[k] -= 2;
if (sprite_z_vel[k] == 0 && sprite_A[k] != 0) {
dialogue_message_index = 0x176;
Sprite_ShowMessageMinimal();
}
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
Sprite_SpawnSmallSplash(k);
if (sprite_A[k]) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xdb, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
Sprite_SetX(j, info.r0_x + 4);
sprite_stunned[j] = 255;
sprite_z_vel[j] = 48;
sprite_delay_aux3[j] = 48;
Sprite_ApplySpeedTowardsLink(j, 16);
}
}
sprite_state[k] = 0;
}
sprite_graphics[k] = kFish_Gfx2[++sprite_subtype2[k] >> 2];
break;
case 4: // wiggle
if (!sprite_z[k])
sprite_ai_state[k] = 1;
Sprite_MoveXY(k);
ThrownSprite_TileAndSpriteInteraction(k);
break;
}
}
void Fish_Draw(int k) { // 9d8483
static const DrawMultipleData kFish_Dmd[16] = {
{-4, 8, 0x045e, 0},
{ 4, 8, 0x045f, 0},
{-4, 8, 0x845e, 0},
{ 4, 8, 0x845f, 0},
{-4, 8, 0x445f, 0},
{ 4, 8, 0x445e, 0},
{-4, 8, 0xc45f, 0},
{ 4, 8, 0xc45e, 0},
{ 0, 0, 0x0461, 0},
{ 0, 8, 0x0471, 0},
{ 0, 0, 0x4461, 0},
{ 0, 8, 0x4471, 0},
{ 0, 0, 0x8471, 0},
{ 0, 8, 0x8461, 0},
{ 0, 0, 0xc471, 0},
{ 0, 8, 0xc461, 0},
};
static const DrawMultipleData kFish_Dmd2[9] = {
{-2, 11, 0x0438, 0},
{ 0, 11, 0x0438, 0},
{ 2, 11, 0x0438, 0},
{-1, 11, 0x0438, 0},
{ 0, 11, 0x0438, 0},
{ 1, 11, 0x0438, 0},
{ 0, 11, 0x0438, 0},
{ 0, 11, 0x0438, 0},
{ 0, 11, 0x0438, 0},
};
PrepOamCoordsRet info;
if (sprite_graphics[k] == 0) {
Sprite_PrepOamCoord(k, &info);
return;
}
cur_sprite_x += 4;
Sprite_DrawMultiple(k, &kFish_Dmd[(sprite_graphics[k] - 1) * 2], 2, &info);
cur_sprite_y += sprite_z[k];
int j = sprite_z[k] >> 2;
oam_cur_ptr += 8, oam_ext_cur_ptr += 2;
Sprite_DrawMultiple(k, &kFish_Dmd2[((j >= 2) ? 2 : j) * 3], 3, &info);
Sprite_Get16BitCoords(k);
}
void ChimneySmoke_Draw(int k) { // 9d8531
static const DrawMultipleData kChimneySmoke_Dmd[8] = {
{0, 0, 0x0086, 0},
{8, 0, 0x0087, 0},
{0, 8, 0x0096, 0},
{8, 8, 0x0097, 0},
{1, 1, 0x0086, 0},
{7, 1, 0x0087, 0},
{1, 7, 0x0096, 0},
{7, 7, 0x0097, 0},
};
Sprite_DrawMultiple(k, &kChimneySmoke_Dmd[(sprite_graphics[k] & 1) * 4], 4, NULL);
}
void Sprite_D1_BunnyBeam(int k) { // 9d858b
if (player_is_indoors)
Sprite_BunnyBeam(k);
else
Sprite_Chimney(k);
}
void Sprite_Chimney(int k) { // 9d858f
sprite_flags3[k] = 64;
sprite_ignore_projectile[k] = 64;
if (!sprite_ai_state[k]) {
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_delay_main[k])
return;
sprite_delay_main[k] = 67;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xd1, &info);
if (j < 0)
return;
Sprite_SetSpawnedCoordinates(j, &info);
int t = (uint8)info.r0_x + 8;
sprite_x_lo[j] = t;
sprite_y_lo[j] = info.r2_y + 4 + (t >> 8);
sprite_oam_flags[j] = 4;
sprite_ai_state[j] = 4;
sprite_flags2[j] = 67;
sprite_flags3[j] = 67;
sprite_x_vel[j] = -4;
sprite_y_vel[j] = -6;
} else {
sprite_obj_prio[k] = 0x30;
ChimneySmoke_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXY(k);
if (!(++sprite_subtype2[k] & 7)) {
int j = sprite_D[k] & 1;
sprite_x_vel[k] += j ? -1 : 1;
if (sprite_x_vel[k] == (uint8)(j ? -4 : 4))
sprite_D[k]++;
}
if (!(sprite_subtype2[k] & 31))
sprite_graphics[k]++;
}
}
void Sprite_BunnyBeam(int k) { // 9d85e0
static const uint8 kRabbitBeam_Gfx[6] = {0xd7, 0xd7, 0xd7, 0x91, 0x91, 0x91};
PrepOamCoordsRet info;
if (!sprite_ai_state[k]) {
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
if (!Sprite_CheckTileCollision(k)) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 128;
}
return;
}
SpriteDraw_Antfairy(k);
if (!sprite_pause[k]) {
OamEnt *oam = GetOamCurPtr();
uint8 charnum = kRabbitBeam_Gfx[sprite_graphics[k]];
for (int i = 0; i < 5; i++) {
oam[i].charnum = charnum;
oam[i].flags = oam[i].flags & 0xf0 | 2;
}
}
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_delay_main[k]) {
sprite_bump_damage[k] = 0x30;
if (Sprite_CheckDamageToLink(k)) {
sprite_state[k] = 0;
link_timer_tempbunny = 256;
}
if (link_is_on_lower_level == sprite_floor[k])
Sprite_ApplySpeedTowardsLink(k, 16);
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k)) {
sprite_state[k] = 0;
Sprite_SpawnPoofGarnish(k);
SpriteSfx_QueueSfx2WithPan(k, 0x15);
}
}
}
void Sprite_D0_Lynel(int k) { // 9d866a
static const int8 kLynel_AttackGfx[4] = {5, 2, 8, 10};
static const int8 kLynel_Gfx[8] = {3, 0, 6, 9, 4, 1, 7, 10};
Lynel_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
Sprite_CheckDamageToAndFromLink(k);
switch(sprite_ai_state[k]) {
case 0: // target
if (!sprite_delay_main[k]) {
static const int8 kLynel_Xtarget[4] = {-96, 96, 0, 0};
static const int8 kLynel_Ytarget[4] = {8, 8, -96, 112};
int j = sprite_D[k];
int x = link_x_coord + kLynel_Xtarget[j];
sprite_A[k] = x, sprite_B[k] = x >> 8;
int y = link_y_coord + kLynel_Ytarget[j];
sprite_C[k] = y, sprite_E[k] = y >> 8;
sprite_ai_state[k]++;
sprite_delay_main[k] = 80;
}
sprite_graphics[k] = kLynel_Gfx[sprite_subtype2[k] & 4 | sprite_D[k]];
break;
case 1: // approach
if (sprite_delay_main[k]) {
if (!((k ^ frame_counter) & 3)) {
uint16 x = sprite_A[k] | sprite_B[k] << 8;
uint16 y = sprite_C[k] | sprite_E[k] << 8;
if ((uint16)(x - cur_sprite_x + 5) < 10 && (uint16)(y - cur_sprite_y + 5) < 10)
goto incr_state;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 24);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
}
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k))
goto incr_state;
sprite_graphics[k] = kLynel_Gfx[++sprite_subtype2[k] & 4 | sprite_D[k]];
} else {
incr_state:
sprite_ai_state[k]++;
sprite_delay_main[k] = 32;
}
break;
case 2: // attack
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = (GetRandomNumber() & 15) + 16;
sprite_ai_state[k] = 0;
return;
}
if (sprite_delay_main[k] == 16) {
int j = Sprite_SpawnFirePhlegm(k);
if (j >= 0 && link_shield_type != 3)
sprite_flags5[j] = 0;
}
sprite_graphics[k] = kLynel_AttackGfx[sprite_D[k]];
Sprite_CheckTileCollision(k);
break;
}
}
void Lynel_Draw(int k) { // 9d8880
static const DrawMultipleData kLynel_Dmd[33] = {
{-5, -11, 0x00cc, 2},
{-4, 0, 0x00e4, 2},
{ 4, 0, 0x00e5, 2},
{-5, -10, 0x00cc, 2},
{-4, 0, 0x00e7, 2},
{ 4, 0, 0x00e8, 2},
{-5, -11, 0x00c8, 2},
{-4, 0, 0x00e4, 2},
{ 4, 0, 0x00e5, 2},
{ 5, -11, 0x40cc, 2},
{-4, 0, 0x40e5, 2},
{ 4, 0, 0x40e4, 2},
{ 5, -10, 0x40cc, 2},
{-4, 0, 0x40e8, 2},
{ 4, 0, 0x40e7, 2},
{ 5, -11, 0x40c8, 2},
{-4, 0, 0x40e8, 2},
{ 4, 0, 0x40e7, 2},
{ 0, -9, 0x00ce, 2},
{-4, 0, 0x00ea, 2},
{ 4, 0, 0x00eb, 2},
{ 0, -9, 0x00ce, 2},
{-4, 0, 0x40eb, 2},
{ 4, 0, 0x40ea, 2},
{ 0, -9, 0x00ca, 2},
{-4, 0, 0x40eb, 2},
{ 4, 0, 0x00eb, 2},
{ 0, -14, 0x00c6, 2},
{-4, 0, 0x00ed, 2},
{ 4, 0, 0x00ee, 2},
{ 0, -14, 0x00c6, 2},
{-4, 0, 0x40ee, 2},
{ 4, 0, 0x40ed, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kLynel_Dmd[sprite_graphics[k] * 3], 3, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_SpawnPhantomGanon(int k) { // 9d88a1
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xc9, &info);
Sprite_SetSpawnedCoordinates(j, &info);
sprite_flags2[j] = 2;
sprite_ignore_projectile[j] = 2;
sprite_anim_clock[j] = 1;
sprite_oam_flags[j] = 0;
}
void Sprite_PhantomGanon(int k) { // 9d88bc
static const uint8 kGanonBat_Gfx[4] = {0, 1, 2, 1};
static const int8 kGanonBat_TargetXvel[2] = {32, -32};
static const int8 kGanonBat_TargetYvel[2] = {16, -16};
if (!sprite_ai_state[k]) {
PhantomGanon_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveY(k);
if (!(++sprite_subtype2[k] & 31)) {
if (--sprite_y_vel[k] == 252) {
int j = SpawnBossPoof(k);
Sprite_SetY(j, Sprite_GetY(j) - 20);
} else if (sprite_y_vel[k] == 251) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 255;
sprite_y_vel[k] = -4;
}
}
} else {
GanonBat_Draw(k);
if (sprite_pause[k]) {
sprite_state[k] = 0;
dung_savegame_state_bits |= 0x8000;
}
if (Sprite_ReturnIfInactive(k))
return;
sprite_graphics[k] = kGanonBat_Gfx[frame_counter >> 2 & 3];
if (sprite_delay_main[k]) {
if (sprite_delay_main[k] < 208) {
int j = sprite_head_dir[k] & 1;
sprite_y_vel[k] += j ? -1 : 1;
if (sprite_y_vel[k] == (uint8)kGanonBat_TargetYvel[j])
sprite_head_dir[k]++;
j = sprite_D[k] & 1;
sprite_x_vel[k] += j ? -1 : 1;
if (sprite_x_vel[k] == (uint8)kGanonBat_TargetXvel[j])
sprite_D[k]++;
if (sprite_x_vel[k] == 0)
SpriteSfx_QueueSfx3WithPan(k, 0x1e);
}
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, link_x_coord & 0xff00 | 0x78, link_y_coord & 0xff00 | 0x50, 5);
uint8 xvel = sprite_x_vel[k], yvel = sprite_y_vel[k];
sprite_x_vel[k] = xvel + pt.x, sprite_y_vel[k] = yvel + pt.y;
Sprite_MoveXY(k);
sprite_x_vel[k] = xvel, sprite_y_vel[k] = yvel;
} else {
Sprite_MoveXY(k);
if (sprite_x_vel[k] != 64) {
sprite_x_vel[k]++;
sprite_y_vel[k]--;
}
}
}
}
void GanonBat_Draw(int k) { // 9d89eb
static const DrawMultipleData kGanonBat_Dmd[6] = {
{-8, 0, 0x0560, 2},
{ 8, 0, 0x4560, 2},
{-8, 0, 0x0562, 2},
{ 8, 0, 0x4562, 2},
{-8, 0, 0x0544, 2},
{ 8, 0, 0x4544, 2},
};
Sprite_DrawMultiple(k, &kGanonBat_Dmd[sprite_graphics[k] * 2], 2, NULL);
}
void PhantomGanon_Draw(int k) { // 9d8a84
static const DrawMultipleData kPhantomGanon_Dmd[16] = {
{-16, -8, 0x0d46, 2},
{ -8, -8, 0x0d47, 2},
{ 8, -8, 0x4d47, 2},
{ 16, -8, 0x4d46, 2},
{-16, 8, 0x0d69, 2},
{ -8, 8, 0x0d6a, 2},
{ 8, 8, 0x4d6a, 2},
{ 16, 8, 0x4d69, 2},
{-16, -8, 0x0d46, 2},
{ -8, -8, 0x0d47, 2},
{ 8, -8, 0x4d47, 2},
{ 16, -8, 0x4d46, 2},
{-16, 8, 0x0d66, 2},
{ -8, 8, 0x0d67, 2},
{ 8, 8, 0x4d67, 2},
{ 16, 8, 0x4d66, 2},
};
oam_cur_ptr = 0x950;
oam_ext_cur_ptr = 0xa74;
Sprite_DrawMultiple(k, &kPhantomGanon_Dmd[sprite_graphics[k] * 8], 8, NULL);
}
void SwishEvery16Frames(int k) { // 9d8aa9
if (!(frame_counter & 15))
SpriteSfx_QueueSfx3WithPan(k, 0x6);
}
void Sprite_GanonTrident(int k) { // 9d8ab6
Trident_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
SwishEvery16Frames(k);
Sprite_MoveXY(k);
sprite_G[k] = kGanon_G_Func2[--sprite_subtype2[k] >> 2 & 7];
if (sprite_delay_main[k]) {
if (sprite_delay_main[k] & 1)
return;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 32);
Sprite_ApproachTargetSpeed(k, pt.x, pt.y);
} else {
int x = Sprite_GetX(0) + (sprite_D[0] ? -16 : 24);
int y = Sprite_GetY(0) - 16;
if (Ganon_AttemptTridentCatch(x, y)) {
sprite_state[k] = 0;
sprite_ai_state[0] = 3;
sprite_delay_main[0] = 16;
}
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 32);
Sprite_ApproachTargetSpeed(k, pt.x, pt.y);
}
}
void Sprite_FireBat_Trailer(int k) { // 9d8b49
FireBat_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
FireBat_Move(k);
}
void Sprite_SpiralFireBat(int k) { // 9d8b52
FireBat_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
{
uint16 x = sprite_A[k] | sprite_B[k] << 8;
uint16 y = sprite_C[k] | sprite_E[k] << 8;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 2);
ProjectSpeedRet pt2 = Sprite_ProjectSpeedTowardsLocation(k, x, y, 80);
sprite_x_vel[k] = pt2.y - pt.x;
sprite_y_vel[k] = -pt2.x - pt.y;
}
FireBat_Move(k);
}
void FireBat_Move(int k) { // 9d8b90
FireBat_Animate(k);
Sprite_MoveXY(k);
if (sprite_subtype2[k] & 7)
return;
int j = Garnish_FlameTrail(k, true);
// garnish_type[j] = 0x10;
garnish_countdown[j] = (sprite_anim_clock[k] == 5) ? 0x2f : 0x4f;
}
void Sprite_FireBat_Launched(int k) { // 9d8bd7
FireBat_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToLink(k);
switch (sprite_ai_state[k]) {
case 0:
GetPositionRelativeToTheGreatOverlordGanon(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
} else {
sprite_graphics[k] = sprite_delay_main[k] >> 2 & 1;
}
break;
case 1:
GetPositionRelativeToTheGreatOverlordGanon(k);
sprite_graphics[k] = ++sprite_subtype2[k] >> 2 & 1;
break;
case 2:
Sprite_MoveXY(k);
sprite_defl_bits[k] = 64;
if (sprite_delay_aux1[k] == 0) {
if (sprite_delay_main[k] == 0) {
FireBat_Animate(k);
FireBat_Animate(k);
} else {
uint8 t = sprite_delay_main[k] - 1;
if (t == 0)
sprite_delay_aux1[k] = t = 35;
sprite_graphics[k] = t >> 2 & 1;
}
} else if (sprite_delay_aux1[k] == 1) {
Sprite_ApplySpeedTowardsLink(k, 48);
SpriteSfx_QueueSfx3WithPan(k, 0x1e);
FireBat_Animate(k);
FireBat_Animate(k);
} else {
static const uint8 kFirebat_Gfx2[9] = { 4, 4, 4, 3, 3, 3, 2, 2, 2 };
sprite_graphics[k] = kFirebat_Gfx2[sprite_delay_aux1[k] >> 2];
}
break;
}
}
void GetPositionRelativeToTheGreatOverlordGanon(int k) { // 9d8bee
static const int8 kFirebat_X[2] = { 20, -18 };
static const int8 kFirebat_Y[2] = { -20, -20 };
int j = sprite_D[0];
Sprite_SetX(k, (overlord_x_hi[k] | overlord_y_hi[k] << 8) + kFirebat_X[j]);
Sprite_SetY(k, (overlord_gen2[k] | overlord_floor[k] << 8) + kFirebat_Y[j]);
}
void FireBat_Animate(int k) { // 9d8c43
static const uint8 kFirebat_Gfx[4] = { 4, 5, 6, 5 };
sprite_graphics[k] = kFirebat_Gfx[++sprite_subtype2[k] >> 2 & 3];
}
void FireBat_Draw(int k) { // 9d8ca9
static const int8 kFirebat_Draw_X[2] = { -8, 8 };
static const uint8 kFirebat_Draw_Char[7] = { 0x88, 0x88, 0x8a, 0x8c, 0x68, 0xaa, 0xa8 };
static const uint8 kFirebat_Draw_Flags[14] = { 0, 0xc0, 0x80, 0x40, 0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40 };
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
for (int i = 1; i >= 0; i--, oam++) {
uint16 x = info.x + kFirebat_Draw_X[i];
uint16 y = info.y;
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kFirebat_Draw_Char[g];
oam->flags = kFirebat_Draw_Flags[g * 2 + i] | info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
}
bool Ganon_AttemptTridentCatch(uint16 x, uint16 y) { // 9d8d06
return (uint16)(cur_sprite_x - x + 4) < 8 && (uint16)(cur_sprite_y - y + 4) < 8;
}
void Ganon_HandleFireBatCircle(int k) { // 9d8d70
static const int8 kGanonMath_X[16] = { 0, 16, 24, 28, 32, 28, 24, 16, 0, -16, -24, -28, -32, -28, -24, -16 };
static const int8 kGanonMath_Y[16] = { 32, 28, 24, 16, 0, -16, -24, -28, -32, -28, -24, -16, 0, 16, 24, 28 };
WORD(overlord_x_lo[0]) -= 4;
for (int i = 0; i != 8; i++) {
int t = WORD(overlord_x_lo[0]) + i * 64 & 0x1ff;
if (sprite_ai_state[i + 1] != 2) {
int j = (t >> 5) - 4 & 0xf;
sprite_x_vel[i + 1] = (int8)kGanonMath_X[j] >> 2;
sprite_y_vel[i + 1] = (int8)kGanonMath_Y[j] >> 2;
}
int x = Sprite_GetX(0) + GanonSin(t, overlord_x_lo[2]);
overlord_x_hi[i + 1] = x;
overlord_y_hi[i + 1] = x >> 8;
int y = Sprite_GetY(0) + GanonSin(t + 0x80, overlord_x_lo[2]);
overlord_gen2[i + 1] = y;
overlord_floor[i + 1] = y >> 8;
}
tmp_counter = 8;
}
void Ganon_SpawnSpiralBat(int k) { // 9d8e7c
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0xc9, &info, 8);
if (j < 0)
return;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_anim_clock[j] = 4;
sprite_oam_flags[j] = 3;
sprite_flags3[j] = 0x40;
sprite_flags2[j] = 1;
sprite_defl_bits[j] = 0x80;
sprite_y_hi[j] = 128;
sprite_delay_main[j] = 48;
sprite_bump_damage[j] = 7;
sprite_ignore_projectile[j] = 7;
}
void Sprite_D6_Ganon(int k) { // 9d8eb4
int j;
if (sign8(sprite_ai_state[k])) {
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_delay_main[k])
sprite_state[k] = 0;
if (!(sprite_delay_main[k] & 1))
Ganon_Draw(k);
return;
}
if (sprite_delay_aux4[k]) {
static const uint8 kGanon_GfxB[2] = { 16, 10 };
sprite_graphics[k] = kGanon_GfxB[sprite_D[k]];
}
if (byte_7E04C5 == 2 && byte_7E04C5 != sprite_room[k])
sprite_delay_aux1[k] = 64;
sprite_room[k] = byte_7E04C5;
Ganon_Draw(k);
if (sprite_delay_aux1[k]) {
sprite_graphics[k] = 15;
Ganon_EnableInvincibility(k);
Sprite_CheckDamageToAndFromLink(k);
return;
}
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_delay_aux2[k] == 1)
Ganon_ExtinguishTorch();
else if (sprite_delay_aux2[k] == 16)
Ganon_ExtinguishTorch_adjust_translucency();
PairU8 pair = Sprite_IsRightOfLink(k);
static const uint8 kGanon_HeadDir0[2] = { 2, 0 };
sprite_head_dir[k] = (uint8)(pair.b + 32) < 64 ? 1 : kGanon_HeadDir0[pair.a];
if (sprite_delay_aux4[k]) {
sprite_ignore_projectile[k] = sprite_delay_aux4[k];
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_delay_main[k] = 0;
return;
}
if (!(sprite_ignore_projectile[k] | flag_is_link_immobilized) && byte_7E04C5 == 2)
Sprite_CheckDamageToAndFromLink(k);
sprite_ignore_projectile[k] = 0;
switch (sprite_ai_state[k]) {
case 0: //
if (sprite_delay_main[k] == 0) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 128;
} else if (sprite_delay_main[k] == 32) {
music_control = 0x1f;
} else if (sprite_delay_main[k] == 64) {
dialogue_message_index = 0x16f;
Sprite_ShowMessageMinimal();
}
break;
case 1: //
if (sprite_health[k] < 209)
sprite_health[k] = 208;
if (sprite_delay_main[k] < 64) {
static const uint8 kGanon_Gfx1[2] = { 2, 10 };
if (sprite_delay_main[k] == 0) {
Ganon_SelectWarpLocation(k, 5);
} else {
sprite_graphics[k] = kGanon_Gfx1[sprite_D[k]];
}
} else if (sprite_delay_main[k] != 64) {
Ganon_Phase1_AnimateTridentSpin(k);
} else {
static const int8 kGanon_X1[2] = { 24, -16 };
static const int8 kGanon_Y1[2] = { 4, 4 };
static const int8 kGanon_Xvel1[16] = { 32, 28, 24, 16, 0, -16, -24, -28, -32, -28, -24, -16, 0, 16, 24, 28 };
static const int8 kGanon_Yvel1[16] = { 0, 16, 24, 28, 32, 28, 24, 16, 0, -16, -24, -28, -32, -28, -24, -16 };
sprite_G[k] = 0;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xc9, &info);
int i = sprite_D[k];
Sprite_SetX(j, info.r0_x + kGanon_X1[i]);
Sprite_SetY(j, info.r2_y + kGanon_Y1[i]);
Sprite_ApplySpeedTowardsLink(k, 31);
uint8 angle = Sprite_ConvertVelocityToAngle(sprite_x_vel[k], sprite_y_vel[k]);
sprite_x_vel[j] = kGanon_Xvel1[angle - 2 & 0xf];
sprite_y_vel[j] = kGanon_Yvel1[angle - 2 & 0xf];
sprite_delay_main[j] = 112;
sprite_anim_clock[j] = 2;
sprite_oam_flags[j] = 1;
sprite_flags2[j] = 4;
sprite_defl_bits[j] = 0x84;
sprite_D[j] = 2;
sprite_bump_damage[j] = 7;
sprite_ignore_projectile[j] = 7;
}
break;
case 2: { //
static const uint8 kGanon_Gfx2_0[2] = { 0, 8 };
if (sprite_health[k] < 209)
sprite_health[k] = 208;
sprite_graphics[k] = kGanon_Gfx2_0[sprite_D[k]];
if (sprite_delay_main[k]) {
sprite_ignore_projectile[k]++;
if (sprite_delay_main[k] & 1)
sprite_graphics[k] = 255;
}
break;
}
case 3: //
if (sprite_health[k] < 209)
sprite_health[k] = 208;
if (sprite_delay_main[k] != 0) {
Ganon_Phase1_AnimateTridentSpin(k);
} else {
sprite_ai_state[k] = 6;
sprite_delay_main[k] = 127;
Ganon_HandleAnimation_Idle(k);
}
break;
case 4: //
if (sprite_health[k] < 209)
sprite_health[k] = 208;
if (sprite_delay_main[k] != 0)
Ganon_ShakeHead(k);
else
Ganon_SelectWarpLocation(k, 5);
break;
case 13: //
sprite_health[k] = 100;
// fall through
case 5: //
case 10: //
case 18: { //
sprite_ignore_projectile[k]++;
uint16 x = sprite_x_hi[k] << 8 | swamola_target_x_lo[0];
uint16 y = sprite_y_hi[k] << 8 | swamola_target_y_lo[0];
if (Ganon_AttemptTridentCatch(x, y)) {
sprite_D[k] = sprite_subtype[k] >> 2;
if (sprite_ai_state[k] == 5) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 32;
} else if (sprite_health[k] >= 161) {
sprite_ai_state[k] = 11;
sprite_delay_main[k] = 40;
} else if (sprite_health[k] >= 97) {
sprite_ai_state[k] = 14;
sprite_delay_main[k] = 40;
} else {
sprite_ai_state[k] = 17;
sprite_delay_main[k] = 104;
}
} else {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 32);
Sprite_ApproachTargetSpeed(k, pt.x, pt.y);
Sprite_MoveXY(k);
if (sprite_delay_main[k] == 0 || frame_counter & 1) {
sprite_graphics[k] = 255;
return;
}
static const uint8 kGanon_Gfx5[2] = { 2, 10 };
sprite_graphics[k] = kGanon_Gfx5[sprite_D[k]];
if (!(frame_counter & 7)) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xd6, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_ignore_projectile[j] = 24;
sprite_delay_main[j] = 24;
sprite_ai_state[j] = 255;
sprite_graphics[j] = sprite_graphics[k];
sprite_head_dir[j] = sprite_head_dir[k];
}
}
}
break;
}
case 6: //
if (sprite_health[k] < 209)
sprite_health[k] = 208;
if (!sprite_delay_main[k]) {
if (sprite_health[k] >= 209) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 128;
} else {
sprite_delay_main[k] = 255;
sprite_ai_state[k] = 7;
}
} else {
Ganon_ShakeHead(k);
}
break;
case 7: //
if (sprite_health[k] < 161)
sprite_health[k] = 160;
overlord_x_lo[2] = 40;
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 8;
sprite_delay_main[k] = 255;
} else {
if (sprite_delay_main[k] < 0xc0 && (sprite_delay_main[k] & 0xf) == 0)
Ganon_SpawnSpiralBat(k);
Ganon_Phase1_AnimateTridentSpin(k);
Ganon_HandleFireBatCircle(k);
}
break;
case 8: { //
static const int8 kGanon_Tab2[16] = { 0, 0, 0, 0, -1, -1, -2, -1, 0, 0, 0, 0, 1, 2, 1, 1 };
static const uint8 kGanon_Delay8[8] = { 0x10, 0x30, 0x50, 0x70, 0x90, 0xb0, 0xd0, 0xbd };
if (sprite_health[k] < 161)
sprite_health[k] = 160;
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 9;
sprite_delay_main[k] = 127;
Ganon_HandleAnimation_Idle(k);
for (int j = 8; j != 0; j--) {
sprite_ai_state[j] = 2;
sprite_delay_main[j] = kGanon_Delay8[j - 1];
}
} else {
overlord_x_lo[2] += kGanon_Tab2[sprite_delay_main[k] >> 4 & 15];
Ganon_Phase1_AnimateTridentSpin(k);
Ganon_HandleFireBatCircle(k);
}
break;
}
case 9: //
if (sprite_health[k] < 161)
sprite_health[k] = 160;
if (!sprite_delay_main[k]) {
Ganon_SelectWarpLocation(k, 10);
} else {
Ganon_ShakeHead(k);
}
break;
case 11: //
sprite_ignore_projectile[k]++;
Ganon_HandleAnimation_Idle(k);
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 255;
sprite_ai_state[k] = 7;
} else if (sprite_delay_main[k] & 1) {
sprite_graphics[k] = 255;
}
break;
case 12: { //
j = sprite_delay_main[k];
if (j == 0) {
Ganon_SelectWarpLocation(k, 13);
return;
}
int t = 0;
if (j < 96) {
t = 1;
if (j < 72) {
if (j == 66)
Ganon_Func1(k, 3);
t = 2;
}
}
if (sprite_D[k])
t += 3;
static const uint8 kGanon_Gfx12[6] = { 5, 6, 7, 13, 14, 10 };
sprite_graphics[k] = kGanon_Gfx12[t];
if ((sprite_hit_timer[k] & 127) == 1) {
sprite_ai_state[k] = 15;
sprite_z_vel[k] = 24;
sprite_delay_main[k] = 0;
}
break;
}
case 14: //
sprite_ignore_projectile[k]++;
Ganon_HandleAnimation_Idle(k);
sprite_G[k] = 0;
if (!sprite_delay_main[k]) {
if (GetRandomNumber() & 1) {
Ganon_SelectWarpLocation(k, 13);
} else {
sprite_delay_main[k] = 127;
sprite_ai_state[k] = 12;
}
} else if (sprite_delay_main[k] & 1) {
sprite_graphics[k] = 255;
}
break;
case 15: { //
static const uint8 kGanon_Gfx15[2] = { 6, 14 };
if (sprite_delay_main[k]) {
if (sprite_delay_main[k] == 1) {
sprite_ai_state[k] = 16;
sprite_z_vel[k] = 160;
return;
}
} else {
Sprite_MoveZ(k);
if (--sprite_z_vel[k] == 0)
sprite_delay_main[k] = 32;
}
sprite_graphics[k] = kGanon_Gfx15[sprite_D[k]];
break;
}
case 16: { //
bg1_y_offset = 0;
if (sprite_delay_main[k]) {
if (sprite_delay_main[k] == 1) {
sound_effect_ambient = 5;
Ganon_SelectWarpLocation(k, 13);
flag_is_link_immobilized = 0;
Ganon_SpawnFallingTilesOverlord(k);
if (sprite_anim_clock[k] >= 4) {
Ganon_SelectWarpLocation(k, 10);
sprite_health[k] = 96;
sprite_delay_aux2[k] = 224;
dialogue_message_index = 0x170;
Sprite_ShowMessageMinimal();
}
} else {
bg1_y_offset = (sprite_delay_main[k] - 1) & 1 ? -1 : 1;
flag_is_link_immobilized = 1;
}
} else {
static const uint8 kGanon_Gfx16[2] = { 2, 10 };
Sprite_MoveZ(k);
if (sign8(sprite_z[k])) {
sprite_z_vel[k] = 0;
sprite_z[k] = 0;
sprite_delay_main[k] = 96;
sound_effect_ambient = 7;
SpriteSfx_QueueSfx2WithPan(k, 0xc);
}
sprite_graphics[k] = kGanon_Gfx16[sprite_D[k]];
}
break;
}
case 17: { //
static const uint8 kGanon_Gfx17b[2] = { 6, 14 };
static const uint8 kGanon_Gfx17[2] = { 7, 10 };
sprite_graphics[k] = kGanon_Gfx17b[sprite_D[k]];
if (!sprite_delay_main[k]) {
Ganon_SelectWarpLocation(k, 0x12);
return;
} else if (sprite_delay_main[k] == 52) {
Ganon_Func1(k, 5);
} else if (sprite_delay_main[k] < 52) {
sprite_graphics[k] = kGanon_Gfx17[sprite_D[k]];
}
if (sprite_delay_main[k] >= 72 || sprite_delay_main[k] < 40) {
sprite_ignore_projectile[k]++;
if (sprite_delay_main[k] & 1)
sprite_graphics[k] = 0xff;
}
Ganon_EnableInvincibility(k);
break;
}
case 19: //
sprite_oam_flags[k] = 5;
sprite_flags[k] = 2;
if (!sprite_delay_main[k]) {
sprite_oam_flags[k] = 1;
Ganon_SelectWarpLocation(k, 18);
sprite_type[k] = 0xd6;
sprite_hit_timer[k] = 0;
} else {
static const uint8 kGanon_Gfx19[2] = { 5, 13 };
sprite_graphics[k] = kGanon_Gfx19[sprite_D[k]];
}
break;
}
}
void Ganon_EnableInvincibility(int k) { // 9d8ffa
if ((sprite_hit_timer[k] & 127) == 26) {
sprite_hit_timer[k] = 0;
sprite_ai_state[k] = 19;
sprite_delay_main[k] = 127;
sprite_type[k] = 215;
}
}
void Ganon_SpawnFallingTilesOverlord(int k) { // 9d90d0
static const uint8 kGanon_Ov_Type[4] = { 12, 13, 14, 15 };
static const uint8 kGanon_Ov_X[4] = { 0x18, 0xd8, 0xd8, 0x18 };
static const uint8 kGanon_Ov_Y[4] = { 0x28, 0x28, 0xd8, 0xd8 };
int j;
for (j = 7; j >= 0 && overlord_type[j] != 0; j--);
int t = sprite_anim_clock[k];
if (t >= 4)
return;
sprite_anim_clock[k] = t + 1;
overlord_type[j] = kGanon_Ov_Type[t];
overlord_x_lo[j] = kGanon_Ov_X[t];
overlord_x_hi[j] = link_x_coord >> 8;
overlord_y_lo[j] = kGanon_Ov_Y[t];
overlord_y_hi[j] = link_y_coord >> 8;
overlord_gen1[j] = 0;
overlord_gen2[j] = 0;
}
void Ganon_Func1(int k, int t) { // 9d9162
tmp_counter = t;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0xC9, &info, 8);
if (j < 0)
return;
SpriteSfx_QueueSfx2WithPan(k, 0x2a);
Sprite_SetSpawnedCoordinates(j, &info);
sprite_ignore_projectile[j] = sprite_anim_clock[j] = t;
sprite_oam_flags[j] = 3;
sprite_flags3[j] = 0x40;
sprite_flags2[j] = 0x21;
sprite_defl_bits[j] = 0x40;
static const int8 kGanon_Gfx16_Y[2] = { 0, -16 };
Sprite_SetY(j, info.r2_y + kGanon_Gfx16_Y[sprite_D[k]]);
Sprite_ApplySpeedTowardsLink(j, 32);
sprite_delay_main[j] = 16;
sprite_A[j] = sprite_x_lo[0];
sprite_B[j] = sprite_x_hi[0];
sprite_C[j] = sprite_y_lo[0];
sprite_E[j] = sprite_y_hi[0];
sprite_bump_damage[j] = 7;
sprite_ignore_projectile[j] = 7;
}
void Ganon_Phase1_AnimateTridentSpin(int k) { // 9d93db
static const uint8 kGanon_GfxFunc2[16] = { 0, 0, 1, 1, 0, 0, 1, 1, 8, 8, 9, 9, 8, 8, 9, 9 };
int j = (sprite_delay_main[k] >> 2 & 7) + (sprite_D[k] ? 8 : 0);
sprite_G[k] = kGanon_G_Func2[j];
sprite_graphics[k] = kGanon_GfxFunc2[j];
SwishEvery16Frames(k);
}
void Ganon_HandleAnimation_Idle(int k) { // 9d9443
static const uint8 kGanon_G[2] = { 9, 10 };
static const uint8 kGanon_Gfx[2] = { 2, 10 };
sprite_G[k] = kGanon_G[sprite_D[k]];
sprite_graphics[k] = kGanon_Gfx[sprite_D[k]];
}
void Ganon_SelectWarpLocation(int k, int a) { // 9d947f
int j;
static const uint8 kGanon_NextSubtype[32] = {
4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7,
0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
};
static const uint8 kGanon_NextY[8] = { 0x40, 0x30, 0x30, 0x40, 0xb0, 0xc0, 0xc0, 0xb0 };
static const uint8 kGanon_NextX[8] = { 0x30, 0x50, 0xa0, 0xc0, 0x40, 0x60, 0x90, 0xb0 };
sprite_subtype[k] = j = kGanon_NextSubtype[GetRandomNumber() & 3 | sprite_subtype[k] << 2];
swamola_target_x_lo[0] = kGanon_NextX[j];
swamola_target_y_lo[0] = kGanon_NextY[j];
sprite_ai_state[k] = a;
sprite_x_vel[k] = sprite_y_vel[k] = 0;
sprite_delay_main[k] = 48;
SpriteSfx_QueueSfx3WithPan(k, 0x28);
}
void Ganon_ShakeHead(int k) { // 9d94ba
static const uint8 kGanon_HeadDir[18] = {
0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 1, 1, 1, 1, 1,
0, 16,
};
sprite_head_dir[k] = kGanon_HeadDir[sprite_delay_main[k] >> 3];
}
void Ganon_Draw(int k) { // 9d9adf
PrepOamCoordsRet info;
if (sign8(sprite_graphics[k]) ||
sprite_ai_state[k] != 19 && sprite_delay_aux4[k] == 0 && byte_7E04C5 == 0) {
Sprite_PrepOamCoordOrDoubleRet(k, &info);
return;
}
Trident_Draw(k);
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr() + 5;
int g = sprite_graphics[k];
for (int i = 0; i < 12; i++, oam++) {
int j = g * 12 + i;
oam->x = info.x + kGanon_Draw_X[j];
oam->y = info.y + kGanon_Draw_Y[j];
oam->charnum = kGanon_Draw_Char[j];
oam->flags = info.flags | (kGanon_Draw_Flags[j] & ((info.flags & 0xf) >= 5 ? 0xf0 : 0xff));
bytewise_extended_oam[oam - oam_buf] = 2;
}
static const uint8 kGanon_SprOffs[17] = {
1, 1, 1, 1, 1, 1, 15, 1, 4, 4, 4, 4, 4, 4, 4, 15, 15,
};
if (kGanon_SprOffs[g] != 15) {
oam = oam - 12 + kGanon_SprOffs[g];
int j = sprite_head_dir[k] * 2 + (sprite_D[k] ? 6 : 0);
oam[0].charnum = kGanon_Draw_Char2[j];
oam[0].flags = (oam[0].flags & 0x3f) | kGanon_Draw_Flags2[j];
oam[1].charnum = kGanon_Draw_Char2[j + 1];
oam[1].flags = (oam[1].flags & 0x3f) | kGanon_Draw_Flags2[j + 1];
}
if (submodule_index)
Sprite_CorrectOamEntries(k, 9, 0xff);
if (sprite_G[k] == 9) {
static const DrawMultipleData kGanon_Dmd[2] = {
{16, -3, 0x4c0a, 2},
{16, 5, 0x4c1a, 2},
};
oam_cur_ptr = 0x828, oam_ext_cur_ptr = 0xa2a;
Sprite_DrawMultiple(k, kGanon_Dmd, 2, NULL);
}
uint16 z = sprite_z[k] - 1;
int frame = (z >> 11) > 4 ? 4 : (z >> 11);
cur_sprite_y += z;
oam_cur_ptr = 0x9f4;
oam_ext_cur_ptr = 0xa9d;
uint8 bak = sprite_oam_flags[k];
sprite_oam_flags[k] = 0;
sprite_obj_prio[k] = 48;
Sprite_DrawMultiple(k, &kLargeShadow_Dmd[frame * 3], 3, NULL);
sprite_oam_flags[k] = bak;
Sprite_Get16BitCoords(k);
}
void Trident_Draw(int k) { // 9d9c1c
static const DrawMultipleData kTrident_Dmd[50] = {
{ 10, -10, 0x0864, 0},
{ 5, -15, 0x0864, 0},
{ 0, -20, 0x0864, 0},
{ -5, -25, 0x0864, 0},
{-18, -38, 0x0844, 2},
{ 1, -4, 0x0865, 0},
{ 1, -11, 0x0865, 0},
{ 1, -18, 0x0865, 0},
{ 1, -25, 0x0865, 0},
{ -3, -40, 0x0862, 2},
{ -8, -9, 0x4864, 0},
{ -3, -14, 0x4864, 0},
{ 3, -20, 0x4864, 0},
{ 9, -26, 0x4864, 0},
{ 12, -37, 0x4844, 2},
{-10, -20, 0x4874, 0},
{ -3, -20, 0x4874, 0},
{ 4, -20, 0x4874, 0},
{ 11, -20, 0x4874, 0},
{ 18, -23, 0x4860, 2},
{-10, -30, 0xc864, 0},
{ -4, -24, 0xc864, 0},
{ 2, -18, 0xc864, 0},
{ 8, -12, 0xc864, 0},
{ 12, -8, 0xc844, 2},
{ 1, -32, 0x8865, 0},
{ 1, -25, 0x8865, 0},
{ 1, -18, 0x8865, 0},
{ 1, -11, 0x8865, 0},
{ -3, -5, 0x8862, 2},
{ 13, -30, 0x8864, 0},
{ 8, -25, 0x8864, 0},
{ 2, -19, 0x8864, 0},
{ -4, -13, 0x8864, 0},
{-16, -9, 0x8844, 2},
{ 14, -20, 0x0874, 0},
{ 7, -20, 0x0874, 0},
{ 0, -20, 0x0874, 0},
{ -7, -20, 0x0874, 0},
{-21, -23, 0x0860, 2},
{ 13, -30, 0x8864, 0},
{ 8, -25, 0x8864, 0},
{ 2, -19, 0x8864, 0},
{ -4, -13, 0x8864, 0},
{-16, -9, 0x8844, 2},
{-10, -30, 0xc864, 0},
{ -4, -24, 0xc864, 0},
{ -4, -24, 0xc864, 0},
{ -4, -24, 0xc864, 0},
{ -4, -24, 0xc864, 0},
};
int g = sprite_G[k];
if (g == 0)
return;
static const int8 kTrident_Draw_X[5] = { 24, -16, 0, 16, -8 };
static const int8 kTrident_Draw_Y[5] = { 4, 4, 16, 21, 19 };
int j = sprite_G[k] == 9 ? 3 :
sprite_G[k] >= 9 ? 4 : sprite_D[k];
cur_sprite_x += kTrident_Draw_X[j];
cur_sprite_y += kTrident_Draw_Y[j];
uint8 bak = sprite_obj_prio[k];
sprite_obj_prio[k] &= ~0xf;
Sprite_DrawMultiple(k, &kTrident_Dmd[(g - 1) * 5], 5, NULL);
sprite_obj_prio[k] = bak;
Sprite_Get16BitCoords(k);
}
void SpritePrep_Swamola_InitializeSegments(int k) { // 9d9c80
int j;
// The snes code uses the wrong bank.. Causes glitches with lanmolas in misery mire
if (enhanced_features0 & kFeatures0_MiscBugFixes) {
j = k * 32;
} else {
static const uint8 kBuggySwamolaLookup[6] = { 0x1c, 0xa9, 0x03, 0x9d, 0x90, 0x0d }; // wrong bank
j = kBuggySwamolaLookup[k];
}
for (int i = 0; i < 32; i++, j++) {
swamola_x_lo[j] = sprite_x_lo[k];
swamola_x_hi[j] = sprite_x_hi[k];
swamola_y_lo[j] = sprite_y_lo[k];
swamola_y_hi[j] = sprite_y_hi[k];
}
}
void Sprite_CF_Swamola(int k) { // 9d9cb0
static const uint8 kSwamola_Target_Dir[8] = {1, 2, 3, 4, 5, 6, 7, 8};
static const int8 kSwamola_Target_X[9] = {0, 0, 32, 32, 32, 0, -32, -32, -32};
static const int8 kSwamola_Target_Y[9] = {0, -32, -32, 0, 32, 32, 32, 0, -32};
int j;
if (sprite_ai_state[k]) {
if (sign8(sprite_ai_state[k])) {
Sprite_Swamola_Ripples(k);
return;
}
Swamola_Draw(k);
}
Sprite_Get16BitCoords(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_subtype2[k]++;
Sprite_CheckDamageToAndFromLink(k);
uint8 old_vel = sprite_y_vel[k];
sprite_y_vel[k] += sprite_z_vel[k];
Sprite_MoveXY(k);
sprite_y_vel[k] = old_vel;
switch(sprite_ai_state[k]) {
case 0: { // emerge
if (!sprite_delay_main[k] && (j = kSwamola_Target_Dir[GetRandomNumber() & 7]) != sprite_D[k]) {
int t = (sprite_B[k] << 8 | sprite_A[k]) + kSwamola_Target_X[j];
swamola_target_x_lo[k] = t, swamola_target_x_hi[k] = t >> 8;
t = (sprite_head_dir[k] << 8 | sprite_C[k]) + kSwamola_Target_Y[j];
swamola_target_y_lo[k] = t, swamola_target_y_hi[k] = t >> 8;
sprite_ai_state[k] = 1;
sprite_x_vel[k] = sprite_y_vel[k] = 0;
sprite_z_vel[k] = -15;
Swamola_SpawnRipples(k);
}
break;
}
case 1: // ascending
if (!(sprite_subtype2[k] & 3)) {
if (!++sprite_z_vel[k])
sprite_ai_state[k] = 2;
ProjectSpeedRet pt = Swamola_ProjectVelocityTowardsTarget(k);
Sprite_ApproachTargetSpeed(k, pt.x, pt.y);
}
break;
case 2: { // wiggle
static const int8 kSwamola_Z_Accel[2] = {2, -2};
static const int8 kSwamola_Z_Vel_Target[2] = {12, -12};
int j = sprite_G[k] & 1;
sprite_z_vel[k] += kSwamola_Z_Accel[j];
if (sprite_z_vel[k] == (uint8)kSwamola_Z_Vel_Target[j])
sprite_G[k]++;
uint16 x = swamola_target_x_hi[k] << 8 | swamola_target_x_lo[k];
uint16 y = swamola_target_y_hi[k] << 8 | swamola_target_y_lo[k];
if ((uint16)(cur_sprite_x - x + 8) < 16 && (uint16)(cur_sprite_y - y + 8) < 16)
sprite_ai_state[k] = 3;
ProjectSpeedRet pt = Swamola_ProjectVelocityTowardsTarget(k);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
break;
}
case 3: // descending
if (!(sprite_subtype2[k] & 3) && ++sprite_z_vel[k] == 16) {
sprite_ai_state[k] = 4;
Swamola_SpawnRipples(k);
sprite_y_hi[k] = 128;
sprite_delay_main[k] = 80;
}
if (!(sprite_subtype2[k] & 3))
Sprite_ApproachTargetSpeed(k, 0, 0);
break;
case 4: // submerge
if (!sprite_delay_main[k]) {
sprite_D[k] = j = kSwamola_Target_Dir[GetRandomNumber() & 7];
Sprite_SetX(k, (sprite_B[k] << 8 | sprite_A[k]) + kSwamola_Target_X[j]);
Sprite_SetY(k, (sprite_head_dir[k] << 8 | sprite_C[k]) + kSwamola_Target_Y[j]);
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 48;
sprite_x_vel[k] = sprite_y_vel[k] = 0;
sprite_z_vel[k] = 0;
}
break;
}
}
ProjectSpeedRet Swamola_ProjectVelocityTowardsTarget(int k) { // 9d9e13
uint16 x = swamola_target_x_hi[k] << 8 | swamola_target_x_lo[k];
uint16 y = swamola_target_y_hi[k] << 8 | swamola_target_y_lo[k];
return Sprite_ProjectSpeedTowardsLocation(k, x, y, 15);
}
void Swamola_SpawnRipples(int k) { // 9d9eaa
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xcf, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_ai_state[j] = 128;
sprite_delay_main[j] = 32;
sprite_oam_flags[j] = 4;
sprite_ignore_projectile[j] = 4;
sprite_flags2[j] = 0;
}
}
void Sprite_Swamola_Ripples(int k) { // 9d9ece
SwamolaRipples_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_delay_main[k])
sprite_state[k] = 0;
}
void SwamolaRipples_Draw(int k) { // 9d9f1d
static const DrawMultipleData kSwamolaRipples_Dmd[8] = {
{0, 4, 0x00d8, 0},
{8, 4, 0x40d8, 0},
{0, 4, 0x00d9, 0},
{8, 4, 0x40d9, 0},
{0, 4, 0x00da, 0},
{8, 4, 0x40da, 0},
{0, 4, 0x00d9, 0},
{8, 4, 0x40d9, 0},
};
Oam_AllocateFromRegionB(8);
Sprite_DrawMultiple(k, &kSwamolaRipples_Dmd[(sprite_delay_main[k] >> 2 & 3) * 2], 2, NULL);
}
void Swamola_Draw(int k) { // 9d9f64
static const uint8 kSwamola_Gfx[16] = {7, 6, 5, 4, 3, 4, 5, 6, 7, 6, 5, 4, 3, 4, 5, 6};
static const uint8 kSwamola_Gfx2[4] = {0, 0, 1, 2};
static const uint8 kSwamola_Draw_OamFlags[16] = {0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0, 0, 0, 0, 0, 0x40, 0x40, 0x40};
static const uint8 kSwamola_HistOffs[4] = {8, 16, 22, 26};
int j = Sprite_ConvertVelocityToAngle(sprite_x_vel[k], sprite_y_vel[k] + sprite_z_vel[k]);
sprite_graphics[k] = kSwamola_Gfx[j];
sprite_oam_flags[k] = sprite_oam_flags[k] & 63 | kSwamola_Draw_OamFlags[j];
SpriteDraw_SingleLarge(k);
j = (sprite_subtype2[k] & 0x1f) + k * 32;
swamola_x_lo[j] = sprite_x_lo[k];
swamola_x_hi[j] = sprite_x_hi[k];
swamola_y_lo[j] = sprite_y_lo[k];
swamola_y_hi[j] = sprite_y_hi[k];
j = sign8(sprite_y_vel[k]) ? 5 : 0;
int delta = sign8(sprite_y_vel[k]) ? -1 : 1;
oam_cur_ptr += j * 4, oam_ext_cur_ptr += j;
for (int i = 0; i < 4; i++) {
sprite_graphics[k] = kSwamola_Gfx2[i];
j = (sprite_subtype2[k] - kSwamola_HistOffs[i] & 31) + k * 32;
cur_sprite_x = swamola_x_hi[j] << 8 | swamola_x_lo[j];
cur_sprite_y = swamola_y_hi[j] << 8 | swamola_y_lo[j];
oam_cur_ptr += delta * 4, oam_ext_cur_ptr += delta;
SpriteDraw_SingleLarge(k);
}
byte_7E0FB6 = 4;
}
void SpritePrep_Blind_PrepareBattle(int k) { // 9da081
if (follower_indicator != 6 && dung_savegame_state_bits & 0x2000) {
sprite_delay_aux2[k] = 96;
sprite_C[k] = 1;
sprite_D[k] = 2;
sprite_head_dir[k] = 4;
sprite_graphics[k] = 7;
byte_7E0B69 = 0;
} else {
sprite_state[k] = 0;
}
}
void BlindLaser_SpawnTrailGarnish(int j) { // 9da0b1
int k = GarnishAllocOverwriteOld();
garnish_type[k] = 15;
garnish_active = 15;
garnish_oam_flags[k] = sprite_graphics[j];
garnish_sprite[k] = j;
garnish_x_lo[k] = sprite_x_lo[j];
garnish_x_hi[k] = sprite_x_hi[j];
uint16 y = Sprite_GetY(j) + 16;
garnish_y_lo[k] = y;
garnish_y_hi[k] = y >> 8;
garnish_countdown[k] = 10;
}
void Sprite_Blind_Head(int k) { // 9da118
static const uint8 kBlindHead_XposLimit[2] = {0x98, 0x58};
static const uint8 kBlindHead_YposLimit[2] = {0xb0, 0x50};
static const int8 kBlindHead_YvelLimit[2] = {24, -24};
static const int8 kBlindHead_XvelLimit[2] = {32, -32};
sprite_obj_prio[k] |= 48;
SpriteDraw_SingleLarge(k);
OamEnt *oam = GetOamCurPtr();
int j = sprite_head_dir[k];
oam->charnum = kBlindHead_Draw_Char[j];
oam->flags = oam->flags & 0x3f | kBlindHead_Draw_Flags[j];
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_F[k] == 14)
sprite_F[k] = 8;
if (Sprite_ReturnIfRecoiling(k))
return;
if (sign8(--sprite_subtype[k])) {
sprite_subtype[k] = 2;
sprite_head_dir[k] = sprite_head_dir[k] + 1 & 15;
}
if (sprite_delay_main[k])
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_subtype2[k]++;
j = Blind_SpitFireball(k, 0x1f);
if (j >= 0 && sign8(--sprite_z_subpos[k])) {
sprite_z_subpos[k] = 4;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 32);
sprite_x_vel[j] = pt.x;
sprite_y_vel[j] = pt.y;
}
j = sprite_G[k] & 1;
if (sprite_x_vel[k] != (uint8)kBlindHead_XvelLimit[j])
sprite_x_vel[k] += j ? -1 : 1;
if ((sprite_x_lo[k] & ~1) == kBlindHead_XposLimit[j])
sprite_G[k]++;
j = sprite_anim_clock[k] & 1;
if (sprite_y_vel[k] != (uint8)kBlindHead_YvelLimit[j])
sprite_y_vel[k] += j ? -1 : 1;
if ((sprite_y_lo[k] & ~1) == kBlindHead_YposLimit[j])
sprite_anim_clock[k]++;
if (!sprite_F[k])
Sprite_MoveXY(k);
}
void Blind_SpawnHead(int k) { // 9da1ed
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xce, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_flags3[j] = 0x5b;
sprite_oam_flags[j] = 0x5b & 15;
sprite_defl_bits[j] = 4;
sprite_A[j] = 2;
sprite_flags2[j] = 1;
sprite_flags4[j] = 0;
sprite_flags[j] = 0;
sprite_z[j] = 23;
sprite_y_lo[j] = 23 + info.r2_y;
sprite_G[j] = (info.r0_x >> 7) & 1;
sprite_anim_clock[j] = (info.r2_y >> 7) & 1;
sprite_delay_main[j] = 48;
}
}
void Sprite_CE_Blind(int k) { // 9da263
if (sign8(sprite_A[k]))
Sprite_BlindLaser(k);
else if (sprite_A[k] == 2)
Sprite_Blind_Head(k);
else
Sprite_Blind_Blind_Blind(k);
}
void Sprite_BlindLaser(int k) { // 9da268
static const uint8 kBlindLaser_Gfx[16] = {7, 7, 8, 9, 10, 9, 8, 7, 7, 7, 8, 9, 10, 9, 8, 7};
static const uint8 kBlindLaser_OamFlags[16] = {0, 0, 0, 0, 0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80};
int j = sprite_head_dir[k];
sprite_graphics[k] = kBlindLaser_Gfx[j];
sprite_oam_flags[k] = kBlindLaser_OamFlags[j] | 3;
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_delay_main[k]) {
if (sprite_delay_main[k] == 1)
sprite_state[k] = 0;
return;
}
Sprite_CheckDamageToLink_same_layer(k);
Sprite_SetX(k, Sprite_GetX(k) + (int8)sprite_x_vel[k]);
Sprite_SetY(k, Sprite_GetY(k) + (int8)sprite_y_vel[k]);
if (Sprite_CheckTileCollision(k))
sprite_delay_main[k] = 12;
BlindLaser_SpawnTrailGarnish(k);
}
void Sprite_Blind_Blind_Blind(int k) { // 9da2d2
int j;
sprite_obj_prio[k] |= 0x30;
Blind_Draw(k);
sprite_oam_flags[k] = 1;
if (Sprite_ReturnIfInactive(k))
return;
uint8 a = sprite_F[k];
if (a)
sprite_F[k]--;
if (a == 11) {
sprite_hit_timer[k] = 0;
sprite_wallcoll[k] = 0;
if (!sprite_delay_aux4[k]) {
sprite_health[k] = 128;
sprite_delay_aux4[k] = 48;
sprite_oam_flags[k] &= 1;
if (++sprite_z_subpos[k] < 3) {
sprite_wallcoll[k] = 96;
sprite_subtype[k] = 1;
} else {
sprite_z_subpos[k] = 0;
if (++sprite_limit_instance == 3) {
Sprite_KillFriends();
sprite_state[k] = 4;
sprite_A[k] = 0;
sprite_delay_main[k] = 255;
sprite_hit_timer[k] = 255;
flag_block_link_menu++;
SpriteSfx_QueueSfx3WithPan(k, 0x22);
return;
}
sprite_y_vel[k] = sprite_x_vel[k] = 0;
sprite_C[k] = 6;
sprite_delay_aux2[k] = 255;
sprite_ignore_projectile[k] = 255;
Blind_SpawnHead(k);
}
}
}
if (sprite_A[k]) {
static const uint8 kBlind_Gfx0[7] = {20, 19, 18, 17, 16, 15, 15};
if (!sprite_delay_main[k])
sprite_state[k] = 0;
sprite_graphics[k] = kBlind_Gfx0[sprite_delay_main[k] >> 3];
return;
}
if (!(++sprite_subtype2[k] & 1))
sprite_delay_main[k]++;
if (sprite_delay_aux1[k]) {
sprite_ai_state[k] = 0;
if (sprite_delay_aux1[k] == 8)
Blind_SpawnLaser(k);
Blind_CheckBumpDamage(k);
return;
}
byte_7E0B69++;
if (!sprite_stunned[k]) {
if (sprite_ai_state[k]) {
sprite_delay_aux1[k] = 16;
sprite_stunned[k] = 128;
sprite_ai_state[k] = 0;
}
} else {
sprite_stunned[k]--;
sprite_ai_state[k] = 0;
}
sprite_x_hi[k] = HIBYTE(link_x_coord);
sprite_y_hi[k] = HIBYTE(link_y_coord);
switch(sprite_C[k]) {
case 0: // blinded
BYTE(dma_var6) = 0;
BYTE(dma_var7) = 0xA0;
if (sprite_delay_aux2[k] == 0) {
sprite_C[k]++;
sprite_delay_aux2[k] = 96;
} else if (sprite_delay_aux2[k] == 80) {
dialogue_message_index = 0x123;
Sprite_ShowMessageMinimal();
} else if (sprite_delay_aux2[k] == 24) {
SpawnBossPoof(k);
}
break;
case 1: // retreat to back wall
Blind_CheckBumpDamage(k);
sprite_graphics[k] = 9;
if (sprite_delay_aux2[k] == 0) {
sprite_C[k]++;
sprite_delay_main[k] = 255;
sprite_ignore_projectile[k] = 0;
} else if (sprite_delay_aux2[k] < 64) {
sprite_y_vel[k] = -8;
Sprite_MoveY(k);
}
Blind_Animate(k);
sprite_head_dir[k] = 4;
break;
case 2: { // oscillate
static const int8 kBlind_Oscillate_YVelTarget[2] = {18, -18};
static const int8 kBlind_Oscillate_XVelTarget[2] = {24, -24};
static const uint8 kBlind_Oscillate_XPosTarget[2] = {164, 76};
Blind_CheckBumpDamage(k);
Blind_Animate(k);
if ((!(sprite_subtype2[k] & 127) && Sprite_IsBelowLink(k).a + 2 != sprite_D[k] || sprite_delay_main[k] == 0) && sprite_x_lo[k] < 0x78) {
sprite_C[k]++;
sprite_y_vel[k] &= ~1;
sprite_x_vel[k] &= ~1;
sprite_delay_aux2[k] = 0x30;
return;
}
j = sprite_B[k] & 1;
sprite_y_vel[k] += j ? -1 : 1;
if (sprite_y_vel[k] == (uint8)kBlind_Oscillate_YVelTarget[j])
sprite_B[k]++;
j = sprite_G[k] & 1;
if (sprite_x_vel[k] != (uint8)kBlind_Oscillate_XVelTarget[j])
sprite_x_vel[k] += j ? -1 : 1;
if ((sprite_x_lo[k] & ~1) == kBlind_Oscillate_XPosTarget[j])
sprite_G[k]++;
Sprite_MoveXY(k);
if (sprite_wallcoll[k]) {
Blind_FireballFlurry(k, sprite_wallcoll[k]);
} else if (!(sprite_subtype2[k] & 7)) {
Sprite_SpawnProbeAlways(k, sprite_head_dir[k] << 2);
}
break;
}
case 3: // switch walls
Blind_CheckBumpDamage(k);
if (sprite_delay_aux2[k]) {
Blind_Decelerate_X(k);
Sprite_MoveX(k);
Blind_Decelerate_Y(k);
} else {
static const int8 kBlind_SwitchWall_YVelTarget[2] = {64, -64};
static const uint8 kBlind_SwitchWall_YPosTarget[2] = {0x90, 0x50};
j = sprite_D[k] - 2;
if (sprite_y_vel[k] != (uint8)kBlind_SwitchWall_YVelTarget[j])
sprite_y_vel[k] += j ? -2 : 2;
if ((sprite_y_lo[k] & ~3) == kBlind_SwitchWall_YPosTarget[j]) {
sprite_C[k]++;
sprite_B[k] = sprite_D[k] - 1;
}
Sprite_MoveXY(k);
Blind_Decelerate_X(k);
}
break;
case 4: { // whirl around
Blind_CheckBumpDamage(k);
if (!(sprite_subtype2[k] & 7)) {
static const uint8 kBlind_WhirlAround_Gfx[2] = {0, 9};
j = sprite_D[k] - 2;
if (sprite_graphics[k] == kBlind_WhirlAround_Gfx[j]) {
sprite_delay_main[k] = 254;
sprite_C[k] = 2;
sprite_D[k] ^= 1;
sprite_G[k] = sprite_x_lo[k] >> 7;
} else {
sprite_graphics[k] += j ? 1 : -1;
}
}
Blind_Decelerate_Y(k);
break;
}
case 5: // fireball reprisal
Blind_FireballFlurry(k, 0x65); // wtf: argument
break;
case 6: // behind the curtain
sprite_hit_timer[k] = 0;
sprite_head_dir[k] = 12;
if (sprite_delay_aux2[k] == 0) {
sprite_C[k]++;
sprite_delay_aux2[k] = 39;
SpriteSfx_QueueSfx1WithPan(k, 0x13);
} else if (sprite_delay_aux2[k] >= 224) {
static const uint8 kBlind_Gfx_BehindCurtain[4] = {14, 13, 12, 10};
sprite_graphics[k] = kBlind_Gfx_BehindCurtain[(sprite_delay_aux2[k] - 224) >> 3];
} else {
sprite_graphics[k] = 14;
}
break;
case 7: // rerobe
if (sprite_delay_aux2[k] == 0) {
sprite_C[k] = 2;
sprite_delay_main[k] = 128;
sprite_D[k] = (sprite_y_lo[k] >> 7) + 2;
sprite_G[k] = (sprite_x_lo[k] << 2) | (sprite_x_lo[k] >> 7);
sprite_x_vel[k] = sprite_y_vel[k] = 0;
sprite_ignore_projectile[k] = 0;
} else {
static const uint8 kBlind_Gfx_Rerobe[5] = {10, 11, 12, 13, 14};
sprite_graphics[k] = kBlind_Gfx_Rerobe[sprite_delay_aux2[k] >> 3];
}
break;
}
}
void Blind_FireballFlurry(int k, uint8 a) { // 9da465
sprite_wallcoll[k]--;
sprite_oam_flags[k] = (a & 7) * 2 + 1;
if (sign8(--sprite_E[k])) {
sprite_E[k] = sprite_subtype[k];
sprite_head_dir[k] = sprite_head_dir[k] + 1 & 15;
}
if (!(sprite_subtype2[k] & 31) && sprite_subtype[k] != 5)
sprite_subtype[k]++;
Blind_AnimateRobes(k);
Blind_SpitFireball(k, 0xf);
}
int Blind_SpitFireball(int k, uint8 a) { // 9da49d
static const int8 kBlindHead_SpawnFireball_Xvel[16] = {-32, -28, -24, -16, 0, 16, 24, 28, 32, 28, 24, 16, 0, -16, -24, -28};
static const int8 kBlindHead_SpawnFireball_Yvel[16] = {0, 16, 24, 28, 32, 28, 24, 16, 0, -16, -24, -28, -32, -28, -24, -16};
if (sprite_subtype2[k] & a)
return -1;
int j = Sprite_SpawnFireball(k);
if (j >= 0) {
SpriteSfx_QueueSfx3WithPan(k, 0x19);
int i = sprite_head_dir[k];
sprite_x_vel[j] = kBlindHead_SpawnFireball_Xvel[i];
sprite_y_vel[j] = kBlindHead_SpawnFireball_Yvel[i];
sprite_defl_bits[j] |= 8;
sprite_bump_damage[j] = 4;
}
return j;
}
int SpawnBossPoof(int k) { // 9da4f9
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xce, &info);
Sprite_SetX(j, info.r0_x + 16);
Sprite_SetY(j, info.r2_y + 40);
sprite_graphics[j] = 0xf;
sprite_A[j] = 1;
sprite_delay_main[j] = 47;
sprite_flags2[j] = 9;
sprite_ignore_projectile[j] = 9;
sound_effect_1 = 12;
return j;
}
void Blind_Decelerate_X(int k) { // 9da647
if (sprite_x_vel[k] != 0)
sprite_x_vel[k] += sign8(sprite_x_vel[k]) ? 2 : -2;
Blind_AnimateRobes(k);
if (sprite_wallcoll[k])
Blind_FireballFlurry(k, sprite_wallcoll[k]);
}
void Blind_Decelerate_Y(int k) { // 9da6a4
if (sprite_y_vel[k] != 0)
sprite_y_vel[k] += sign8(sprite_y_vel[k]) ? 4 : -4;
Sprite_MoveY(k);
if (sprite_wallcoll[k])
Blind_FireballFlurry(k, sprite_wallcoll[k]);
}
void Blind_CheckBumpDamage(int k) { // 9da6c0
if (!(sprite_delay_aux4[k] | sprite_F[k]))
Sprite_CheckDamageToAndFromLink(k);
if ((uint16)(link_x_coord - cur_sprite_x + 14) < 28 &&
(uint16)(link_y_coord - cur_sprite_y) < 28 &&
!(countdown_for_blink | link_disable_sprite_damage)) {
link_auxiliary_state = 1;
link_give_damage = 8;
link_incapacitated_timer = 16;
link_actual_vel_x ^= 255;
link_actual_vel_y ^= 255;
}
}
void Blind_Animate(int k) { // 9da6ef
static const uint8 kBlind_HeadDir[17] = {0, 1, 2, 3, 4, 3, 2, 1, 0, 15, 14, 13, 12, 13, 14, 15, 0};
static const uint8 kBlind_Animate_Tab[8] = {0, 1, 1, 2, 2, 3, 3, 4};
if (!sprite_wallcoll[k]) {
int t1 = kBlind_Animate_Tab[BYTE(link_x_coord) >> 5];
t1 = (sprite_D[k] == 3) ? -t1 : t1;
int t0 = (sprite_D[k] - 2) * 8;
int idx = (byte_7E0B69 >> 3 & 7) + (byte_7E0B69 >> 2 & 1) + t0;
sprite_head_dir[k] = (kBlind_HeadDir[idx] + t1) & 15;
}
Blind_AnimateRobes(k);
}
void Blind_AnimateRobes(int k) { // 9da729
static const uint8 kBlind_Gfx_Animate[8] = {7, 8, 9, 8, 0, 1, 2, 1};
sprite_graphics[k] = kBlind_Gfx_Animate[(sprite_subtype2[k] >> 3 & 3) + ((sprite_D[k] - 2) << 2)];
}
void Blind_SpawnLaser(int k) { // 9da765
static const int8 kBlind_Laser_Xvel[16] = {-8, -8, -8, -4, 0, 4, 8, 8, 8, 8, 8, 4, 0, -4, -8, -8};
static const int8 kBlind_Laser_Yvel[16] = {0, 0, 4, 8, 8, 8, 4, 0, 0, 0, -4, -8, -8, -8, -4, 0};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xce, &info), i;
if (j >= 0) {
sound_effect_2 = Sprite_CalculateSfxPan(k) | 0x26;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_x_lo[j] = info.r0_x + 4;
sprite_head_dir[j] = i = sprite_head_dir[k];
sprite_x_vel[j] = kBlind_Laser_Xvel[i];
sprite_y_vel[j] = kBlind_Laser_Yvel[i];
sprite_A[j] = 128;
sprite_ignore_projectile[j] = 128;
sprite_flags2[j] = 0x40;
sprite_flags4[j] = 0x14;
}
}
void Blind_Draw(int k) { // 9dac6c
if (sprite_graphics[k] >= 15) {
static const DrawMultipleData kBlindPoof_Dmd[37] = {
{-16, -20, 0x0586, 2},
{-11, -28, 0x0586, 2},
{-23, -26, 0x0586, 2},
{ -8, -17, 0x0586, 2},
{-20, -13, 0x0586, 2},
{-16, -37, 0x0586, 2},
{-27, -31, 0x0586, 2},
{-10, -28, 0x0586, 2},
{ -5, -28, 0x0586, 2},
{-20, -27, 0x0586, 2},
{-27, -17, 0x0586, 2},
{ -4, -17, 0x0586, 2},
{-16, -13, 0x0586, 2},
{-18, -37, 0x458a, 2},
{ -5, -33, 0x458a, 2},
{-32, -32, 0x058a, 2},
{-23, -31, 0x458a, 2},
{-15, -24, 0x458a, 2},
{-23, -31, 0x458a, 2},
{-15, -24, 0x458a, 2},
{-29, -22, 0x058a, 2},
{ -5, -22, 0x058a, 2},
{-16, -14, 0x058a, 2},
{-12, -32, 0x458a, 2},
{-26, -29, 0x458a, 2},
{ -6, -22, 0x458a, 2},
{-19, -20, 0x058a, 2},
{-26, -29, 0x458a, 2},
{ -6, -22, 0x458a, 2},
{-19, -20, 0x058a, 2},
{-17, -27, 0x059b, 0},
{-10, -26, 0x059b, 0},
{ 0, -22, 0x459b, 0},
{-19, -16, 0x459b, 0},
{ -6, -12, 0x059b, 0},
{ 0, 13, 0x0b20, 2},
{ 0, 23, 0x0b22, 2},
};
static const uint8 kOffs[] = { 0, 1, 5, 13, 23, 30, 35, 37 };
int j = sprite_graphics[k] - 15;
Sprite_DrawMultiple(k, &kBlindPoof_Dmd[kOffs[j]], kOffs[j + 1] - kOffs[j], NULL);
return;
}
static const DrawMultipleData kBlind_Dmd[105] = {
{ -8, 7, 0x0c8e, 2},
{ 8, 7, 0x4c8e, 2},
{ -8, 23, 0x0ca0, 2},
{ 8, 23, 0x4ca4, 2},
{ 0, 0, 0x0a8c, 2},
{-19, 3, 0x0aa6, 2},
{ 19, 3, 0x4aa6, 2},
{ -8, 7, 0x0c8e, 2},
{ 8, 7, 0x4c8e, 2},
{ -8, 23, 0x0ca2, 2},
{ 8, 23, 0x4ca0, 2},
{ 0, 0, 0x0a8c, 2},
{-19, 3, 0x0aa8, 2},
{ 19, 3, 0x4aa8, 2},
{ -8, 7, 0x0c8e, 2},
{ 8, 7, 0x4c8e, 2},
{ -8, 23, 0x0ca4, 2},
{ 8, 23, 0x4ca2, 2},
{ 0, 0, 0x0a8c, 2},
{-19, 3, 0x0aaa, 2},
{ 19, 3, 0x4aaa, 2},
{-15, 5, 0x0aa6, 2},
{ -6, 7, 0x0c8e, 2},
{ 6, 7, 0x4c8e, 2},
{ -6, 23, 0x0ca4, 2},
{ 6, 23, 0x4ca0, 2},
{ 0, 0, 0x0a8a, 2},
{ 16, -1, 0x4aa6, 2},
{-11, 9, 0x0aa6, 2},
{ -4, 7, 0x0c8e, 2},
{ 5, 7, 0x4c8e, 2},
{ -4, 23, 0x0ca4, 2},
{ 5, 23, 0x4ca0, 2},
{ 0, 0, 0x0a88, 2},
{ 10, -2, 0x4aa6, 2},
{ 0, 0, 0x0a84, 2},
{ 13, 8, 0x4aa6, 2},
{-10, -2, 0x0aa6, 2},
{ -5, 7, 0x0c8e, 2},
{ 5, 7, 0x4c8e, 2},
{ -5, 23, 0x0ca0, 2},
{ 5, 23, 0x4ca4, 2},
{ 0, 0, 0x0a82, 2},
{ 18, 4, 0x4aa6, 2},
{-15, -1, 0x0aa6, 2},
{ -6, 7, 0x0c8e, 2},
{ 6, 7, 0x4c8e, 2},
{ -6, 23, 0x0ca0, 2},
{ 6, 23, 0x4ca4, 2},
{ 0, 0, 0x0a80, 2},
{-19, 3, 0x0aa6, 2},
{ 19, 3, 0x4aa6, 2},
{ -8, 7, 0x0c8e, 2},
{ 8, 7, 0x4c8e, 2},
{ -8, 23, 0x0ca0, 2},
{ 8, 23, 0x4ca4, 2},
{ 0, 0, 0x0a80, 2},
{-19, 3, 0x0aa8, 2},
{ 19, 3, 0x4aa8, 2},
{ -8, 7, 0x0c8e, 2},
{ 8, 7, 0x4c8e, 2},
{ -8, 23, 0x0ca2, 2},
{ 8, 23, 0x4ca0, 2},
{ 0, 0, 0x0a80, 2},
{-19, 3, 0x0aaa, 2},
{ 19, 3, 0x4aaa, 2},
{ -8, 7, 0x0c8e, 2},
{ 8, 7, 0x4c8e, 2},
{ -8, 23, 0x0ca0, 2},
{ 8, 23, 0x4ca4, 2},
{ -8, 9, 0x0c8e, 2},
{ 8, 9, 0x4c8e, 2},
{ -8, 23, 0x0cae, 2},
{ 8, 23, 0x4cae, 2},
{ 8, 23, 0x4cae, 2},
{ 8, 23, 0x4cae, 2},
{ 0, 2, 0x0a8c, 2},
{ -8, 16, 0x0c8e, 2},
{ 8, 16, 0x4c8e, 2},
{ -8, 23, 0x0cae, 2},
{ 8, 23, 0x4cae, 2},
{ 8, 23, 0x4cae, 2},
{ 8, 23, 0x4cae, 2},
{ 0, 9, 0x0a8c, 2},
{ -8, 23, 0x0cae, 2},
{ 8, 23, 0x4cae, 2},
{ 8, 23, 0x4cae, 2},
{ 8, 23, 0x4cae, 2},
{ 8, 23, 0x4cae, 2},
{ 8, 23, 0x4cae, 2},
{ 0, 16, 0x0a8c, 2},
{ -8, 23, 0x0cac, 2},
{ 8, 23, 0x4cac, 2},
{ 8, 23, 0x4cac, 2},
{ 8, 23, 0x4cac, 2},
{ 8, 23, 0x4cac, 2},
{ 8, 23, 0x4cac, 2},
{ 0, 20, 0x0a8c, 2},
{ -8, 23, 0x0cac, 2},
{ 8, 23, 0x4cac, 2},
{ 8, 23, 0x4cac, 2},
{ 8, 23, 0x4cac, 2},
{ 8, 23, 0x4cac, 2},
{ 8, 23, 0x4cac, 2},
{ 0, 23, 0x0a8c, 2},
};
Sprite_DrawMultiple(k, &kBlind_Dmd[sprite_graphics[k] * 7], 7, NULL);
OamEnt *oam = GetOamCurPtr();
if (sprite_wallcoll[k] == 0) {
if (sprite_C[k] == 6) {
oam[6].y = 0xf0;
return;
}
if (sprite_C[k] == 4)
return;
}
if (sprite_graphics[k] >= 10)
return;
static const uint8 kBlind_OamIdx[10] = {4, 4, 4, 5, 5, 0, 0, 0, 0, 0};
oam += kBlind_OamIdx[sprite_graphics[k]];
int j = sprite_head_dir[k];
oam->charnum = kBlindHead_Draw_Char[j];
oam->flags = oam->flags & 0x3f | kBlindHead_Draw_Flags[j];
}
void TrinexxComponents_Initialize(int k) { // 9dad16
switch (sprite_type[k]) {
case 0xcb: {
sprite_x_lo[k] += 8;
sprite_y_lo[k] += 16;
Trinexx_CachePosition(k);
overlord_x_lo[2] = 0;
overlord_x_lo[3] = 0;
overlord_x_lo[5] = 0;
overlord_x_lo[7] = 0;
overlord_x_hi[0] = 0;
overlord_x_lo[6] = 255;
Trinexx_RestoreXY(k);
break;
}
case 0xcc:
sprite_graphics[k] = 3;
sprite_delay_main[k] = 128;
common:
for (int j = 0x1a; j >= 0; j--) {
alt_sprite_type[j] = 0x40;
alt_sprite_x_hi[j] = 0;
alt_sprite_y_hi[j] = 0;
}
sprite_subtype2[k] = 1;
Trinexx_CachePosition(k);
break;
case 0xcd:
sprite_delay_main[k] = 255;
goto common;
}
}
void Trinexx_RestoreXY(int k) { // 9dad4f
sprite_x_lo[k] = sprite_A[k];
Sprite_SetY(k, (sprite_G[k] << 8) + sprite_C[k] + 12);
}
void Trinexx_CachePosition(int k) { // 9dad8c
sprite_A[k] = sprite_x_lo[k];
sprite_B[k] = sprite_x_hi[k];
sprite_C[k] = sprite_y_lo[k];
sprite_G[k] = sprite_y_hi[k];
}
void Sprite_Trinexx_FinalPhase(int k) { // 9dadb5
static const uint8 kSprite_TrinexxD_Gfx3[8] = {6, 7, 0, 1, 2, 3, 4, 5};
static const uint8 kSprite_TrinexxD_Gfx[8] = {7, 7, 1, 1, 3, 3, 5, 5};
static const int8 kSprite_TrinexxD_Xvel[4] = {0, -31, 0, 31};
static const int8 kSprite_TrinexxD_Yvel[4] = {31, 0, -31, 0};
int j = Sprite_ConvertVelocityToAngle(sprite_x_vel[k], sprite_y_vel[k]) >> 1;
uint8 gfx = kSprite_TrinexxD_Gfx3[j];
sprite_graphics[k] = sprite_delay_aux1[k] ? kSprite_TrinexxD_Gfx[gfx] : gfx;
Sprite_TrinexxD_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sign8(sprite_ai_state[k])) {
uint8 t = sprite_delay_main[k];
sprite_hit_timer[k] = t | 0xe0;
if (t == 0) {
sprite_delay_main[k] = 12;
if (sprite_anim_clock[k] == 0) {
sprite_hit_timer[k] = 255;
Sprite_ScheduleBossForDeath(k);
} else {
sprite_anim_clock[k]--;
Sprite_MakeBossExplosion(k);
}
}
return;
}
if (!(frame_counter & 7))
SpriteSfx_QueueSfx3WithPan(k, 0x31);
j = ++sprite_subtype2[k] & 0x7f;
moldorm_x_lo[j] = sprite_x_lo[k];
moldorm_y_lo[j] = sprite_y_lo[k];
moldorm_x_hi[j] = sprite_x_hi[k];
moldorm_y_hi[j] = sprite_y_hi[k];
if (sprite_F[k] == 14) {
sprite_F[k] = 8;
if (sprite_ai_state[k] == 0)
sprite_ai_state[k] = 2;
}
Sprite_MoveXY(k);
Sprite_CheckDamageToAndFromLink(k);
switch(sprite_ai_state[k]) {
case 0:
if (!--sprite_A[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 192;
}
Sprite_Get16BitCoords(k);
if (Sprite_CheckTileCollision(k)) {
sprite_D[k] = sprite_D[k] + 1 & 3;
sprite_delay_aux1[k] = 8;
}
j = sprite_D[k];
sprite_x_vel[k] = kSprite_TrinexxD_Xvel[j];
sprite_y_vel[k] = kSprite_TrinexxD_Yvel[j];
break;
case 1:
if (!(frame_counter & 1)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 31);
Sprite_ApproachTargetSpeed(k, pt.x, pt.y);
}
break;
}
}
void Sprite_TrinexxD_Draw(int k) { // 9daf84
static const int8 kTrinexxD_HistPos[24] = {
8, 0xc, 0x10, 0x18, 0x20, 0x28, 0x30, 0x34, 0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x50, 0x54,
0x58, 0x5c, 0x60, 0x64, 0x68, 0x6c, 0x70, 0x74,
};
static const int8 kSprite_TrinexxD_Gfx2[24] = {
2, 2, 2, 3, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
static const int16 kTrinexxD_OamOffs[24] = {
0x10, 4, 4, 4, 0x10, 0x10, 0x10, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
};
sprite_obj_prio[k] |= 0x30;
PrepOamCoordsRet info;
SpriteDraw_TrinexxRockHead(k, &info);
for (int i = 0; i != sprite_anim_clock[k]; i++) {
int j = sprite_subtype2[k] - kTrinexxD_HistPos[i] & 0x7f;
cur_sprite_x = moldorm_x_hi[j] << 8 | moldorm_x_lo[j];
cur_sprite_y = moldorm_y_hi[j] << 8 | moldorm_y_lo[j];
if ((uint16)(link_x_coord - cur_sprite_x + 8) < 16 &&
(uint16)(link_y_coord - cur_sprite_y + 16) < 16 &&
!sign8(sprite_ai_state[k]) &&
!(countdown_for_blink | link_disable_sprite_damage | submodule_index | flag_unk1)) {
link_auxiliary_state = 1;
link_give_damage = 8;
link_incapacitated_timer = 16;
link_actual_vel_x ^= 255;
link_actual_vel_y ^= 255;
}
oam_cur_ptr += kTrinexxD_OamOffs[i];
oam_ext_cur_ptr += (kTrinexxD_OamOffs[i] >> 2);
sprite_oam_flags[k] = 1;
if (i == 4 && sprite_ai_state[k] != 0) {
Sprite_Trinexx_CheckDamageToFlashingSegment(k);
sprite_oam_flags[k] = (sprite_subtype2[k] & 6) ^ sprite_oam_flags[k];
}
sprite_graphics[k] = kSprite_TrinexxD_Gfx2[i];
if (sprite_graphics[k] != 3) {
SpriteDraw_SingleLarge(k);
} else {
sprite_graphics[k] = 8;
SpriteDraw_TrinexxRockHead(k, &info);
}
}
byte_7E0FB6 = sprite_anim_clock[k];
}
void Sprite_Trinexx_CheckDamageToFlashingSegment(int k) { // 9db079
uint16 old_x = Sprite_GetX(k);
uint16 old_y = Sprite_GetY(k);
Sprite_SetX(k, cur_sprite_x);
Sprite_SetY(k, cur_sprite_y);
sprite_defl_bits[k] = 0x80;
sprite_flags3[k] = 0;
Sprite_CheckDamageFromLink(k);
sprite_defl_bits[k] = 0x84;
sprite_flags3[k] = 0x40;
Sprite_SetX(k, old_x);
Sprite_SetY(k, old_y);
}
void Sprite_CB_TrinexxRockHead(int k) { // 9db0ca
if (overlord_x_hi[0]) {
Sprite_Trinexx_FinalPhase(k);
return;
}
TM_copy = 0x17;
TS_copy = 0;
SpriteDraw_TrinexxRockHeadAndBody(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sign8(sprite_ai_state[k])) {
flag_block_link_menu = sprite_ai_state[k];
if (!sprite_delay_main[k]) {
overlord_x_hi[0]++;
Sprite_InitializedSegmented(k);
sprite_subtype2[k] = 0;
sprite_head_dir[k] = 0;
sprite_flags3[k] &= ~0x40;
sprite_defl_bits[k] = 0x80;
sprite_ai_state[k] = 0;
sprite_D[k] = 0;
sprite_A[k] = 0;
sprite_anim_clock[k] = 16;
sprite_x_vel[k] = sprite_y_vel[k] = 0;
sprite_A[k] = 128;
HIBYTE(dung_floor_y_vel) = 255;
} else if (sprite_delay_main[k] >= 0xff) {
} else if (sprite_delay_main[k] >= 0xe0) {
if (!(sprite_delay_main[k] & 3)) {
dung_floor_y_vel = -1;
dung_hdr_collision_2_mirror = 1;
}
sprite_y_vel[k] = -8;
Sprite_MoveY(k);
Trinexx_CachePosition(k);
sprite_C[k] = sprite_y_lo[k] - 12;
overlord_x_lo[7] += 2;
} else {
if (!(sprite_delay_main[k] & 3))
SpriteSfx_QueueSfx2WithPan(k, 0xc);
if (!(sprite_delay_main[k] & 1)) {
static const int8 kTrinexx_X0[8] = {0, 8, 16, 24, -24, -16, -8, 0};
static const int8 kTrinexx_Y0[8] = {0, 8, 16, 24, -24, -16, -8, 0};
cur_sprite_x = Sprite_GetX(k) + kTrinexx_X0[GetRandomNumber() & 7];
cur_sprite_y = Sprite_GetY(k) + kTrinexx_Y0[GetRandomNumber() & 7] - 8;
Sprite_MakeBossDeathExplosion_NoSound(k);
}
sprite_head_dir[k] = 255;
}
return;
}
if ((sprite_state[1] | sprite_state[2]) == 0 && sprite_ai_state[k] < 2) {
sprite_delay_main[k] = 255;
sprite_ai_state[k] = 255;
sound_effect_2 = 0x22;
return;
}
Trinexx_WagTail(k);
Trinexx_HandleShellCollision(k);
Sprite_CheckDamageToAndFromLink(k);
if (!(frame_counter & 63)) {
PairU8 pair = Sprite_IsRightOfLink(k);
sprite_graphics[k] = (uint8)(pair.b + 24) < 48 ? 0 : pair.a ? 1 : 7;
}
if (overlord_x_lo[6]) {
if (!(frame_counter & 1))
overlord_x_lo[6]--;
return;
}
if (sprite_state[1] && sprite_ai_state[1] == 3)
return;
if (sprite_state[2] && sprite_ai_state[2] == 3)
return;
switch (sprite_ai_state[k]) {
case 0:
if (!sprite_delay_main[k]) {
int j = GetRandomNumber() & 3;
if ((sprite_subtype[k] & 0x7f) == j)
return;
if (++sprite_anim_clock[k] == 2) {
sprite_anim_clock[k] = 0;
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 80;
return;
}
static const uint8 kTrinexx_Tab0[4] = {0x60, 0x78, 0x78, 0x90};
static const uint8 kTrinexx_Tab1[4] = {0x80, 0x70, 0x60, 0x80};
overlord_x_lo[0] = kTrinexx_Tab0[j];
overlord_x_lo[1] = kTrinexx_Tab1[j];
sprite_subtype[k] = j + ((GetRandomNumber() & 3) == 0) * 0x80;
sprite_ai_state[k] = 1;
}
break;
case 1: {
if (sprite_subtype[k] == 0xff && (sprite_delay_main[k] == 0 || Sprite_IsBelowLink(k).a == 0)) {
sprite_subtype[k] = 0;
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 48;
} else {
uint16 x = sprite_x_hi[k] << 8 | overlord_x_lo[0];
uint16 y = sprite_y_hi[k] << 8 | overlord_x_lo[1];
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, sign8(sprite_subtype[k]) ? 16 : 8);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
uint8 bakx = sprite_x_lo[k];
uint8 baky = sprite_y_lo[k];
Sprite_MoveXY(k);
dung_floor_y_vel = (int8)(baky - sprite_y_lo[k]);
dung_floor_x_vel = (int8)(bakx - sprite_x_lo[k]);
dung_hdr_collision_2_mirror = 1;
Trinexx_CachePosition(k);
sprite_C[k] = sprite_y_lo[k] - 12;
if ((uint8)(overlord_x_lo[0] - sprite_x_lo[k] + 2) < 4 &&
(uint8)(overlord_x_lo[1] - sprite_y_lo[k] + 2) < 4) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 48;
}
}
int i = sign8(sprite_subtype[k]) ? 2 : 1;
do {
sprite_subtype2[k] += sign8(sprite_x_vel[k]) ? 1 : -1;
if (!(sprite_subtype2[k] & 0xf))
SpriteSfx_QueueSfx2WithPan(k, 0x21);
} while (--i);
break;
}
case 2:
Trinexx_WagTail(k);
Trinexx_WagTail(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 3;
Sprite_ApplySpeedTowardsLink(k, 48);
sprite_delay_main[k] = 64;
sound_effect_2 = 0x26;
}
break;
case 3:
Sprite_MoveXY(k);
if (!sprite_delay_main[k]) {
Trinexx_RestoreXY(k);
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 48;
} else if (sprite_delay_main[k] == 0x20) {
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_y_vel[k] = -sprite_y_vel[k];
}
break;
}
}
void Trinexx_WagTail(int k) { // 9db3b5
if (!overlord_x_lo[5]) {
if (!(++overlord_x_lo[4] & 3)) {
int j = overlord_x_lo[3] & 1;
overlord_x_lo[2] += j ? -1 : 1;
if (overlord_x_lo[2] == (j ? 0 : 6)) {
overlord_x_lo[3] += 1;
overlord_x_lo[5] = 8;
}
}
} else {
--overlord_x_lo[5];
}
}
void Trinexx_HandleShellCollision(int k) { // 9db3e6
uint16 x = sprite_A[k] | sprite_B[k] << 8;
uint16 y = sprite_C[k] | sprite_G[k] << 8;
if ((uint16)(x - link_x_coord + 40) < 80 && (uint16)(y - link_y_coord + 16) < 64 && !(countdown_for_blink | link_disable_sprite_damage)) {
link_auxiliary_state = 1;
link_give_damage = 8;
link_incapacitated_timer = 16;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 32);
link_actual_vel_x = pt.x;
link_actual_vel_y = pt.y;
}
}
void SpriteDraw_TrinexxRockHead(int k, PrepOamCoordsRet *info) { // 9db560
static const DrawMultipleData kTrinexx_Draw1_Dmd[36] = {
{-8, -8, 0x40c0, 2},
{ 8, -8, 0x00c0, 2},
{-8, 8, 0x40e0, 2},
{ 8, 8, 0x00e0, 2},
{-8, -8, 0x0000, 2},
{ 8, -8, 0x0002, 2},
{-8, 8, 0x0020, 2},
{ 8, 8, 0x0022, 2},
{-8, -8, 0x00c2, 2},
{ 8, -8, 0x00c4, 2},
{-8, 8, 0x80c2, 2},
{ 8, 8, 0x80c4, 2},
{-8, -8, 0x8020, 2},
{ 8, -8, 0x8022, 2},
{-8, 8, 0x8000, 2},
{ 8, 8, 0x8002, 2},
{-8, -8, 0xc0e0, 2},
{ 8, -8, 0x80e0, 2},
{-8, 8, 0xc0c0, 2},
{ 8, 8, 0x80c0, 2},
{-8, -8, 0xc022, 2},
{ 8, -8, 0xc020, 2},
{-8, 8, 0xc002, 2},
{ 8, 8, 0xc000, 2},
{-8, -8, 0x40c4, 2},
{ 8, -8, 0x40c2, 2},
{-8, 8, 0xc0c4, 2},
{ 8, 8, 0xc0c2, 2},
{-8, -8, 0x4002, 2},
{ 8, -8, 0x4000, 2},
{-8, 8, 0x4022, 2},
{ 8, 8, 0x4020, 2},
{-8, -8, 0x0026, 2},
{ 8, -8, 0x4026, 2},
{-8, 8, 0x8026, 2},
{ 8, 8, 0xc026, 2},
};
if (!sign8(sprite_ai_state[k]))
sprite_obj_prio[k] |= 0x30;
Sprite_DrawMultiple(k, &kTrinexx_Draw1_Dmd[sprite_graphics[k] * 4], 4, info);
}
void SpriteDraw_TrinexxRockHeadAndBody(int k) { // 9db587
static const int8 kTrinexx_Draw_X[35] = {
0, 3, 9, 16, 24, 0, 2, 7, 13, 20, 0, 1, 4, 9, 15, 0,
0, 0, 0, 0, 0, -1, -4, -9, -15, 0, -2, -7, -13, -20, 0, -3,
-9, -16, -24,
};
static const int8 kTrinexx_Draw_Y[35] = {
0x18, 0x20, 0x25, 0x25, 0x21, 0x18, 0x20, 0x27, 0x2a, 0x2c, 0x18, 0x20, 0x28, 0x2f, 0x34, 0x18,
0x21, 0x2a, 0x34, 0x3d, 0x18, 0x20, 0x28, 0x2f, 0x34, 0x18, 0x20, 0x27, 0x2a, 0x2c, 0x18, 0x20,
0x25, 0x25, 0x21,
};
static const uint8 kTrinexx_Draw_Char[5] = {6, 0x28, 0x28, 0x2c, 0x2c};
static const uint8 kTrinexx_Mults[8] = {0xfc, 0xe0, 0xc0, 0xa0, 0x80, 0x60, 0x40, 0x20};
static const int8 kTrinexx_Draw_Xoffs[16] = {0, 2, 3, 4, 4, 4, 3, 2, 0, -2, -3, -4, -4, -4, -3, -2};
static const int8 kTrinexx_Draw_Yoffs[16] = {-4, -4, -3, -2, 0, 2, 3, 4, 4, 4, 3, 2, 0, -2, -3, -4};
if (sign8(sprite_head_dir[k]))
return;
PrepOamCoordsRet info;
SpriteDraw_TrinexxRockHead(k, &info);
info.flags &= ~0x10;
if (sprite_ai_state[k] == 3) {
OamEnt *oam = GetOamCurPtr() + 4;
uint8 xb = sprite_A[k] - sprite_x_lo[k];
uint8 yb = sprite_C[k] - sprite_y_lo[k];
for (int i = 7; i >= 0; i--, oam++) {
oam->x = info.x + TrinexxMult(xb, kTrinexx_Mults[i]);
oam->y = info.y + TrinexxMult(yb, kTrinexx_Mults[i]);
oam->charnum = 0x28;
oam->flags = info.flags;
bytewise_extended_oam[oam - oam_buf] = 2;
}
byte_7E0FB6 = 0x30;
}
oam_cur_ptr = 0x9f0;
oam_ext_cur_ptr = 0xa9c;
OamEnt *oam = GetOamCurPtr();
uint8 xb = sprite_A[k] - BG2HOFS_copy2;
uint16 yb = (sprite_C[k] | sprite_y_hi[k] << 8) - BG2VOFS_copy2;
uint8 xidx = (uint8)(sprite_x_vel[k] + 3) < 7 ? 0 : (sprite_subtype2[k] >> 2);
uint8 yidx = sprite_subtype2[k] >> 2;
for (int i = 1; i >= 0; i--, oam += 2) {
oam[0].x = oam[1].x = xb + (i ? -28 : 28) + kTrinexx_Draw_Xoffs[xidx + (1-i) * 8 & 0xf];
oam[0].y = yb - 8 + kTrinexx_Draw_Yoffs[yidx + i * 8 & 0xf];
oam[1].y = oam[0].y + 16;
oam[0].charnum = 0xc;
oam[1].charnum = 0x2a;
oam[0].flags = oam[1].flags = info.flags | (i ? 0 : 0x40);
WORD(bytewise_extended_oam[oam - oam_buf]) = 0x202;
}
oam = (OamEnt *)&g_ram[0x800] + 91;
int g = overlord_x_lo[2];
for (int i = 0; i < 5; i++, oam++) {
int j = g * 5 + i;
oam->x = xb + kTrinexx_Draw_X[j];
uint16 y = yb - kTrinexx_Draw_Y[j] - 0x20 + WORD(overlord_x_lo[7]);
oam->y = ClampYForOam(y);
oam->charnum = kTrinexx_Draw_Char[i];
oam->flags = info.flags;
bytewise_extended_oam[oam - oam_buf] = 2;
}
tmp_counter = 0xff;
if (submodule_index)
Sprite_CorrectOamEntries(k, 3, 2);
}
void Sprite_Sidenexx(int k) { // 9db8a7
static const int8 kTrinexxHead_Xoffs[2] = {-14, 13};
int xx = (sprite_B[0] << 8 | sprite_A[0]) + kTrinexxHead_Xoffs[sprite_type[k] - 0xcc];
sprite_A[k] = xx, sprite_B[k] = xx >> 8;
int yy = (sprite_G[0] << 8 | sprite_C[0]) - 0x20;
sprite_C[k] = yy, sprite_G[k] = yy >> 8;
sprite_obj_prio[k] |= 0x30;
TrinexxHead_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sign8(sprite_ai_state[k])) {
sprite_ignore_projectile[k] = sprite_ai_state[k];
Sidenexx_Explode(k);
return;
}
if (sprite_hit_timer[k] && sprite_ai_state[k] != 4) {
sprite_hit_timer[k] = 0;
sprite_delay_main[k] = 128;
sprite_ai_state[k] = 4;
sprite_z_vel[k] = sprite_oam_flags[k];
sprite_oam_flags[k] = 3;
}
Sprite_CheckDamageToAndFromLink(k);
sprite_defl_bits[k] |= 4;
switch(sprite_ai_state[k]) {
case 0:
sprite_flags3[k] |= 0x40;
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_subtype2[k] = 9;
sprite_flags3[k] &= ~0x40;
}
break;
case 1:
if (!sprite_delay_main[k]) {
int i = (GetRandomNumber() & 7) + 1;
int j = sprite_D[k];
if (i < 5 && sprite_D[k] != i) {
sprite_D[k] = i;
sprite_ai_state[k] = 2;
if (j == 1 && !(GetRandomNumber() & 1) && sprite_ai_state[0] < 2) {
sprite_graphics[k] = 0;
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 127;
}
}
}
break;
case 2: {
static const uint8 kTrinexxHead_Target0[45] = {
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x58, 0x64, 0x6a, 0x6f, 0x74, 0x7a, 0x7e,
0x80, 0x80, 0x39, 0x48, 0x52, 0x5c, 0x65, 0x73, 0x77, 0x7a, 0x80, 0x1e, 0x24, 0x29, 0x2e, 0x34,
0x3a, 0x44, 0x4d, 0x80, 0xa, 0x11, 0x17, 0x1c, 0x22, 0x2a, 0x36, 0x3a, 0x80,
};
static const uint8 kTrinexxHead_Target1[45] = {
0x30, 0x28, 0x23, 0x1e, 0x19, 0x13, 0xc, 6, 0, 0x2f, 0x26, 0x21, 0x1d, 0x18, 0x12, 0xc,
6, 0, 0x2f, 0x27, 0x22, 0x1d, 0x18, 0x12, 0xc, 6, 0, 0x2f, 0x27, 0x22, 0x1d, 0x18,
0x12, 0xc, 6, 0, 0x48, 0x3a, 0x32, 0x29, 0x22, 0x19, 0x10, 7, 0,
};
int j = sprite_D[k] * 9, f = k * 9;
int n = 0;
for (int i = 8; i >= 0; i--, j++, f++) {
if (alt_sprite_type[f] - kTrinexxHead_Target0[j]) {
alt_sprite_type[f] += sign8(alt_sprite_type[f] - kTrinexxHead_Target0[j]) ? 1 : -1;
n++;
}
if (alt_sprite_type[f] - kTrinexxHead_Target0[j]) {
alt_sprite_type[f] += sign8(alt_sprite_type[f] - kTrinexxHead_Target0[j]) ? 1 : -1;
n++;
}
if (alt_sprite_y_hi[f] - kTrinexxHead_Target1[j]) {
alt_sprite_y_hi[f] += sign8(alt_sprite_y_hi[f] - kTrinexxHead_Target1[j]) ? 1 : -1;
n++;
}
}
if (n == 0) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = GetRandomNumber() & 15;
}
break;
}
case 3: {
static const uint8 kTrinexxHead_FrameMask[8] = {1, 1, 3, 3, 7, 0xf, 0x1f, 0x1f};
int j = sprite_delay_main[k];
if (!j) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 32;
return;
}
if (j == 64)
Sidenexx_ExhaleDanger(k);
sprite_subtype[k] = (j < 8) ? j : (j < 121) ? 8 : ~(sprite_delay_main[k] + 0x80);
if (j >= 64 && !(frame_counter & kTrinexxHead_FrameMask[(j - 64) >> 3])) {
int x = (GetRandomNumber() & 0xf) - 3;
int y = (GetRandomNumber() & 0xf) + 12;
int j = Sprite_GarnishSpawn_Sparkle(k, x, y);
if (sprite_type[k] == 0xcc)
garnish_type[j] = 0xe;
}
break;
}
case 4: {
sprite_defl_bits[k] &= ~4;
sprite_subtype[k] = 0;
int j = sprite_delay_main[k];
if (!j) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 32;
sprite_oam_flags[k] = sprite_z_vel[k];
sprite_hit_timer[k] = 0;
}
if (j >= 15) {
if (j >= 63 && j < 78) {
if (sprite_type[k] == 0xcd)
Trinexx_FlashShellPalette_Blue();
else
Trinexx_FlashShellPalette_Red();
}
} else {
if (sprite_type[k] == 0xcd)
Trinexx_UnflashShellPalette_Blue();
else
Trinexx_UnflashShellPalette_Red();
}
}
}
}
void Sidenexx_ExhaleDanger(int k) { // 9dbae8
SpriteSpawnInfo info;
if (sprite_type[k] == 0xcd) {
for (int i = 0; i < 2; i++) {
int j = Sprite_SpawnDynamically(k, 0xcd, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_C[j] = i ? 1 : -2;
SpriteSfx_QueueSfx3WithPan(k, 0x19);
sprite_ignore_projectile[j] = sprite_E[j] = 1;
sprite_y_vel[j] = 24;
sprite_flags2[j] = 0;
sprite_flags3[j] = 0x40;
}
}
byte_7E0FB6 = 1;
} else {
int j = Sprite_SpawnDynamically(k, sprite_type[k], &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
SpriteSfx_QueueSfx2WithPan(k, 0x2a);
sprite_ignore_projectile[j] = sprite_E[j] = 1;
sprite_y_vel[j] = 24;
sprite_flags2[j] = 0;
sprite_flags3[j] = 0x40;
}
}
}
void Sidenexx_Explode(int k) { // 9dbb3f
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 12;
if (sprite_subtype2[k] == 1)
sprite_state[k] = 0;
sprite_subtype2[k]--;
BYTE(cur_sprite_x) += BG2HOFS_copy2;
BYTE(cur_sprite_y) += BG2VOFS_copy2;
Sprite_MakeBossExplosion(k);
}
}
void TrinexxHead_Draw(int k) { // 9dbb70
sprite_x_lo[k] = sprite_A[k];
sprite_x_hi[k] = sprite_B[k];
sprite_y_lo[k] = sprite_C[k];
sprite_y_hi[k] = sprite_G[k];
Sprite_Get16BitCoords(k);
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int i = 0;
do {
int j = i + k * 9;
uint16 r6 = (k != 2) ? 0x100 + (uint8)(-alt_sprite_type[j]) : alt_sprite_type[j];
uint8 r15 = alt_sprite_y_hi[j];
BYTE(dungmap_var7) = TrinexxHeadSin(r6, r15);
HIBYTE(dungmap_var7) = TrinexxHeadSin(r6 + 0x80, r15);
if (i == 0) {
static const int8 kTrinexxHead_FirstPart_X[5] = {-8, 8, -8, 8, 0};
static const int8 kTrinexxHead_FirstPart_Y[5] = {-8, -8, 8, 8, 2};
static const uint8 kTrinexxHead_FirstPart_Char[5] = {4, 4, 0x24, 0x24, 0xa};
static const uint8 kTrinexxHead_FirstPart_Flags[5] = {0x40, 0, 0x40, 0, 0};
for (int m = 0; m < 5; m++) {
BYTE(cur_sprite_x) = info.x + BYTE(dungmap_var7);
oam->x = BYTE(cur_sprite_x) + kTrinexxHead_FirstPart_X[m];
BYTE(cur_sprite_y) = info.y + HIBYTE(dungmap_var7);
oam->y = BYTE(cur_sprite_y) + kTrinexxHead_FirstPart_Y[m] + (m == 4 ? sprite_subtype[k] : 0);
oam->charnum = kTrinexxHead_FirstPart_Char[m];
oam->flags = info.flags | kTrinexxHead_FirstPart_Flags[m];
bytewise_extended_oam[oam - oam_buf] = 2;
oam++;
}
Sprite_SetX(k, (sprite_B[k] << 8 | sprite_A[k]) + (int8)BYTE(dungmap_var7));
Sprite_SetY(k, (sprite_G[k] << 8 | sprite_C[k]) + (int8)HIBYTE(dungmap_var7));
} else {
BYTE(cur_sprite_x) = oam->x = info.x + BYTE(dungmap_var7);
BYTE(cur_sprite_y) = oam->y = info.y + HIBYTE(dungmap_var7);
oam->charnum = 8;
oam->flags = info.flags;
bytewise_extended_oam[oam - oam_buf] = 2;
oam++;
}
} while (++i != sprite_subtype2[k]);
tmp_counter = i;
byte_7E0FB6 = i * 4 + 16;
if (submodule_index)
Sprite_CorrectOamEntries(k, 4, 2);
}
void Sprite_CC_CD_Common(int k) { // 9dbd44
if (!(frame_counter & 3)) {
int m = Sprite_IsRightOfLink(k).a ? -1 : 1;
if (sprite_x_vel[k] != (uint8)(m * 16))
sprite_x_vel[k] += m;
}
if (Sprite_CheckTileCollision(k))
sprite_state[k] = 0;
}
void Sprite_CD_SpawnGarnish(int k) { // 9dbd65
if (++sprite_subtype2[k] & 7)
return;
SpriteSfx_QueueSfx3WithPan(k, 0x14);
int j = GarnishAllocOverwriteOld();
garnish_active = garnish_type[j] = 0xc;
garnish_sprite[j] = k;
Garnish_SetX(j, Sprite_GetX(k));
Garnish_SetY(j, Sprite_GetY(k) + 16);
garnish_countdown[j] = 127;
}
void Sprite_TrinexxFire_AddFireGarnish(int k) { // 9dbdd6
if (++sprite_subtype2[k] & 7)
return;
SpriteSfx_QueueSfx2WithPan(k, 0x2a);
Garnish_FlameTrail(k, false);
}
int Garnish_FlameTrail(int k, bool is_low) { // 9dbde8
int j = is_low ? GarnishAllocOverwriteOldLow() : GarnishAllocOverwriteOld();
garnish_active = garnish_type[j] = 0x10;
garnish_sprite[j] = k;
Garnish_SetX(j, Sprite_GetX(k));
Garnish_SetY(j, Sprite_GetY(k) + 16);
garnish_countdown[j] = 127;
return j;
}
void Sprite_CA_ChainChomp(int k) { // 9dbe7d
ChainChomp_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
ChainChomp_HandleLeash(k);
if (!((k ^ frame_counter) & 3) && (sprite_x_vel[k] | sprite_y_vel[k]))
sprite_D[k] = Sprite_ConvertVelocityToAngle(sprite_x_vel[k], sprite_y_vel[k]) & 0xf;
Sprite_MoveXYZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
}
Sprite_Get16BitCoords(k);
uint16 x = sprite_A[k] | sprite_B[k] << 8;
uint16 y = sprite_C[k] | sprite_G[k] << 8;
sprite_anim_clock[k] = (uint16)(cur_sprite_x - x + 48) < 96 && (uint16)(cur_sprite_y - y + 48) < 96;
switch(sprite_ai_state[k]) {
case 0: //
if (!sprite_delay_main[k]) {
static const int8 kChainChomp_Xvel[16] = {0, 8, 11, 14, 16, 14, 11, 8, 0, -8, -11, -14, -16, -14, -11, -8};
static const int8 kChainChomp_Yvel[16] = {-16, -14, -11, -8, 0, 8, 11, 14, 16, 14, 11, 8, 0, -9, -11, -14};
if (++sprite_subtype2[k] == 4) {
sprite_subtype2[k] = 0;
sprite_ai_state[k] = 2;
int j = GetRandomNumber() & 15;
sprite_x_vel[k] = kChainChomp_Xvel[j] << 2;
sprite_y_vel[k] = kChainChomp_Yvel[j] << 2;
GetRandomNumber();
Sprite_ApplySpeedTowardsLink(k, 64);
SpriteSfx_QueueSfx3WithPan(k, 0x4);
} else {
sprite_delay_main[k] = (GetRandomNumber() & 31) + 16;
int j = GetRandomNumber() & 15;
sprite_x_vel[k] = kChainChomp_Xvel[j];
sprite_y_vel[k] = kChainChomp_Yvel[j];
sprite_ai_state[k] = 1;
}
} else {
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
}
break;
case 1: //
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 32;
sprite_ai_state[k] = 0;
}
if (!(sprite_delay_main[k] & 15))
ChainChomp_MoveChain(k);
if (!sprite_z[k])
sprite_z_vel[k] = 16;
if (!sprite_anim_clock[k]) {
uint16 x = sprite_A[k] | sprite_B[k] << 8;
uint16 y = sprite_C[k] | sprite_G[k] << 8;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 16);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
Sprite_MoveXY(k);
sprite_delay_main[k] = 12;
}
break;
case 2: //
if (!sprite_anim_clock[k]) {
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_y_vel[k] = -sprite_y_vel[k];
Sprite_MoveXY(k);
sprite_x_vel[k] = sprite_y_vel[k] = 0;
sprite_ai_state[k] = 3;
sprite_delay_aux1[k] = 48;
}
ChainChomp_MoveChain(k);
ChainChomp_MoveChain(k);
break;
case 3: //
if (!sprite_delay_aux1[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 48;
}
ChainChomp_MoveChain(k);
ChainChomp_MoveChain(k);
break;
}
}
void ChainChomp_MoveChain(int k) { // 9dc02a
static const uint8 kChainChomp_Muls[6] = {205, 154, 102, 51, 8, 0xbd}; // wtf
uint16 x = sprite_A[k] | sprite_B[k] << 8;
uint16 y = sprite_C[k] | sprite_G[k] << 8;
int pos = k * 8;
uint16 x2 = chainchomp_x_hist[pos] - x;
uint16 y2 = chainchomp_y_hist[pos] - y;
pos++;
for (int i = 5; i >= 0; i--) {
uint16 x3 = x + ChainChomp_OneMult(x2, kChainChomp_Muls[(pos & 7) - 1]);
uint16 y3 = y + ChainChomp_OneMult(y2, kChainChomp_Muls[(pos & 7) - 1]);
if (chainchomp_x_hist[pos] - x3)
chainchomp_x_hist[pos] += sign16(chainchomp_x_hist[pos] - x3) ? 1 : -1;
if (chainchomp_y_hist[pos] - y3)
chainchomp_y_hist[pos] += sign16(chainchomp_y_hist[pos] - y3) ? 1 : -1;
pos++;
}
}
void ChainChomp_HandleLeash(int k) { // 9dc0f2
int pos = k * 8;
chainchomp_x_hist[pos] = cur_sprite_x;
chainchomp_y_hist[pos] = cur_sprite_y;
for (int i = 0; i < 6; i++, pos++) {
uint16 x = chainchomp_x_hist[pos] - chainchomp_x_hist[pos + 1];
if (!sign16(x - 8))
chainchomp_x_hist[pos + 1] = chainchomp_x_hist[pos] - 8;
else if (sign16(x + 8))
chainchomp_x_hist[pos + 1] = chainchomp_x_hist[pos] + 8;
uint16 y = chainchomp_y_hist[pos] - chainchomp_y_hist[pos + 1];
if (!sign16(y - 8))
chainchomp_y_hist[pos + 1] = chainchomp_y_hist[pos] - 8;
else if (sign16(y + 8))
chainchomp_y_hist[pos + 1] = chainchomp_y_hist[pos] + 8;
}
}
void ChainChomp_Draw(int k) { // 9dc192
static const uint8 kChainChomp_Gfx[16] = {0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0, 4, 4, 4, 0, 0};
static const uint8 kChainChomp_OamFlags[16] = {0x40, 0x40, 0x40, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0x40, 0x40, 0x40};
int j = sprite_D[k];
sprite_graphics[k] = kChainChomp_Gfx[j];
sprite_oam_flags[k] = sprite_oam_flags[k] & 0x3f | kChainChomp_OamFlags[j];
SpriteDraw_SingleLarge(k);
OamEnt *oam = GetOamCurPtr() + 1;
uint8 flags = sprite_oam_flags[k] ^ sprite_obj_prio[k];
int r8 = (sprite_delay_aux1[k] & 1) + 4;
int pos = k * 8;
for (int i = 5; i >= 0; i--, pos++, oam++) {
uint16 x = chainchomp_x_hist[pos] + r8 - BG2HOFS_copy2;
uint16 y = chainchomp_y_hist[pos] + r8 - BG2VOFS_copy2;
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = 0x8b;
oam->flags = flags & 0xf0 | 0xd;
bytewise_extended_oam[oam - oam_buf] = (x >> 8 & 1);
}
}
void Sprite_C9_Tektite(int k) { // 9dc275
int j = sprite_anim_clock[k];
if (j) {
sprite_ignore_projectile[k] = j;
sprite_obj_prio[k] = 0x30;
}
switch (j) {
case 0: Sprite_Tektite(k); break;
case 1: Sprite_PhantomGanon(k); break;
case 2: Sprite_GanonTrident(k); break;
case 3: Sprite_SpiralFireBat(k); break;
case 4: Sprite_FireBat_Launched(k); break;
case 5: Sprite_FireBat_Trailer(k); break;
}
}
void Sprite_Tektite(int k) { // 9dc293
int j;
if (sprite_delay_aux1[k])
sprite_graphics[k] = 0;
Tektite_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXYZ(k);
Sprite_BounceFromTileCollision(k);
sprite_z_vel[k] -= 1;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
}
switch(sprite_ai_state[k]) {
case 0: { // Stationary
static const uint8 kTektite_Dir[4] = {3, 2, 1, 0};
static const int8 kTektite_Xvel[4] = {16, -16, 16, -16};
static const int8 kTektite_Yvel[4] = {16, 16, -16, -16};
PointU8 pt;
j = Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.x + 40) < 80 && (uint8)(pt.y + 40) < 80 && player_oam_y_offset != 0x80 &&
!(sprite_z[k] | sprite_pause[k]) && link_is_on_lower_level == sprite_floor[k] && j != kTektite_Dir[link_direction_facing >> 1]) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 32);
sprite_x_vel[k] = -pt.x;
sprite_y_vel[k] = -pt.y;
sprite_z_vel[k] = 16;
sprite_ai_state[k] = 1;
return;
}
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_B[k]++;
if (sprite_B[k] == 4) {
sprite_B[k] = 0;
sprite_ai_state[k]++;
sprite_delay_main[k] = (GetRandomNumber() & 63) + 48;
sprite_z_vel[k] = 12;
j = Sprite_IsBelowLink(k).a * 2 + Sprite_IsRightOfLink(k).a;
} else {
sprite_z_vel[k] = (GetRandomNumber() & 7) + 24;
j = GetRandomNumber() & 3;
}
sprite_x_vel[k] = kTektite_Xvel[j];
sprite_y_vel[k] = kTektite_Yvel[j];
} else {
sprite_graphics[k] = sprite_delay_main[k] >> 4 & 1;
}
break;
}
case 1: // Aloft
if (!sprite_z[k]) {
reset_state:
sprite_ai_state[k] = 0;
sprite_delay_main[k] = (GetRandomNumber() & 63) + 72;
sprite_y_vel[k] = 0;
sprite_x_vel[k] = 0;
} else {
sprite_graphics[k] = 2;
}
break;
case 2: // RepeatingHop
if (!sprite_delay_main[k])
goto reset_state;
if (!sprite_z[k]) {
sprite_z_vel[k] = 12;
sprite_z[k]++;
sprite_delay_aux1[k] = 8;
}
sprite_graphics[k] = 2;
break;
}
}
void Tektite_Draw(int k) { // 9dc3f5
static const DrawMultipleData kTektite_Dmd[6] = {
{-8, 0, 0x00c8, 2},
{ 8, 0, 0x40c8, 2},
{-8, 0, 0x00ca, 2},
{ 8, 0, 0x40ca, 2},
{-8, 0, 0x00ea, 2},
{ 8, 0, 0x40ea, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kTektite_Dmd[sprite_graphics[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_C8_BigFairy(int k) { // 9dc414
if (sprite_head_dir[k])
Sprite_FairyCloud(k);
else
Sprite_BigFairy(k);
}
void Sprite_FairyCloud(int k) { // 9dc41c
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
sprite_subtype2[k]++;
FaerieCloud_Draw(k);
if (!(sprite_subtype2[k] & 31))
SpriteSfx_QueueSfx2WithPan(k, 0x31);
switch (sprite_ai_state[k]) {
case 0:
sprite_A[k] = 0;
Sprite_ApplySpeedTowardsLink(k, 8);
Sprite_MoveXY(k);
Sprite_Get16BitCoords(k);
if ((uint16)(link_x_coord - cur_sprite_x + 3) < 6 &&
(uint16)(link_y_coord - cur_sprite_y + 11) < 6) {
WORD(link_hearts_filler) += 0xa0;
sprite_ai_state[k] = 1;
}
break;
case 1:
if (link_health_current == link_health_capacity) {
sprite_ai_state[k]++;
sprite_delay_aux2[0] = 112; // zelda bug
}
break;
case 2:
if ((sprite_subtype2[k] & 15) || sign8(sprite_A[k]))
return;
sprite_A[k] = sprite_A[k] * 2 + 1;
if (sprite_A[k] >= 0x80) {
sprite_A[k] = 255;
flag_is_link_immobilized = 0;
sprite_state[k] = 0;
}
break;
}
}
void Sprite_BigFairy(int k) { // 9dc4bf
PointU8 pt;
int i = sprite_delay_aux2[k];
if (i != 0 && i < 0x40) {
if (--i == 0)
sprite_state[k] = 0;
if (i & 1)
return;
}
BigFaerie_Draw(k);
if (sign8(--sprite_G[k])) {
sprite_G[k] = 5;
sprite_graphics[k] = sprite_graphics[k] + 1 & 3;
}
if (Sprite_ReturnIfInactive(k))
return;
sprite_subtype2[k]++;
switch (sprite_ai_state[k]) {
case 0: // await close player
FaerieCloud_Draw(k);
sprite_A[k] = 1;
Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.x + 0x30) < 0x60 && (uint8)(pt.y + 0x30) < 0x60) {
Link_CancelDash();
sprite_ai_state[k] = 1;
dialogue_message_index = 0x15a;
Sprite_ShowMessageMinimal();
flag_is_link_immobilized = 1;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xC8, &info);
Sprite_SetSpawnedCoordinates(j, &info);
sprite_head_dir[j] = 1;
sprite_y_lo[j] -= sprite_z[k];
sprite_z[j] = 0;
}
break;
case 1: // dormant
break;
}
}
void BigFaerie_Draw(int k) { // 9dc5d0
static const DrawMultipleData kBigFaerie_Dmd[16] = {
{-4, -8, 0x008e, 2},
{ 4, -8, 0x408e, 2},
{-4, 8, 0x00ae, 2},
{ 4, 8, 0x40ae, 2},
{-4, -8, 0x008c, 2},
{ 4, -8, 0x408c, 2},
{-4, 8, 0x00ac, 2},
{ 4, 8, 0x40ac, 2},
{-4, -8, 0x008a, 2},
{ 4, -8, 0x408a, 2},
{-4, 8, 0x00aa, 2},
{ 4, 8, 0x40aa, 2},
{-4, -8, 0x008c, 2},
{ 4, -8, 0x408c, 2},
{-4, 8, 0x00ac, 2},
{ 4, 8, 0x40ac, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kBigFaerie_Dmd[sprite_graphics[k] * 4], 4, &info);
SpriteDraw_Shadow(k, &info);
}
void FaerieCloud_Draw(int k) { // 9dc616
static const int8 kFaerieCloud_Draw_XY[8] = {-12, -6, 0, 6, 12, 18, 0, 6};
if (!sign8(sprite_A[k]) && !(sprite_A[k] & sprite_subtype2[k])) {
int x = kFaerieCloud_Draw_XY[GetRandomNumber() & 7];
int y = kFaerieCloud_Draw_XY[GetRandomNumber() & 7];
Sprite_GarnishSpawn_Sparkle(k, x, y);
}
}
void Sprite_C7_Pokey(int k) { // 9dc64f
if (sprite_C[k]) {
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXYZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z_vel[k] = 16;
sprite_z[k] = 0;
}
if (Sprite_BounceFromTileCollision(k))
SpriteSfx_QueueSfx2WithPan(k, 0x21);
if (sprite_G[k] >= 3) {
sprite_state[k] = 6;
sprite_delay_main[k] = 10;
sprite_flags5[k] = 0;
SpriteSfx_QueueSfx2WithPan(k, 0x1e);
}
return;
}
Hokbok_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_A[k] && sprite_F[k] == 15) {
sprite_F[k] = 6;
sprite_z[k] += sprite_B[k];
if (!--sprite_A[k])
sprite_health[k] = 17;
sprite_x_vel[k] += sign8(sprite_x_vel[k]) ? -4 : 4;
sprite_y_vel[k] += sign8(sprite_y_vel[k]) ? -4 : 4;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xc7, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_C[j] = 1;
sprite_health[j] = 1;
sprite_x_vel[j] = sprite_x_recoil[k];
sprite_y_vel[j] = sprite_y_recoil[k];
sprite_defl_bits[j] = 64;
}
}
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
switch(sprite_ai_state[k]) {
case 0:
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_z_vel[k] = 16;
} else {
static const uint8 kHokbok_B[8] = {8, 7, 6, 5, 4, 5, 6, 7};
sprite_B[k] = kHokbok_B[sprite_delay_main[k] >> 1];
}
break;
case 1:
Sprite_MoveXYZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 15;
}
Sprite_BounceFromTileCollision(k);
break;
}
}
void Hokbok_Draw(int k) { // 9dc77d
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr() + 3;
int d = sprite_B[k];
uint16 x = info.x, y = info.y;
for (int i = sprite_A[k]; i >= 0; i--, oam--) {
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = ((i == 0) ? 0xa2 : 0xa0) - ((d < 7) ? 0x20 : 0);
oam->flags = info.flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
y -= d;
}
SpriteDraw_Shadow(k, &info);
}
void Sprite_C5_Medusa(int k) { // 9dc7eb
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (!player_is_indoors) {
sprite_x_vel[k] = 255;
sprite_subtype[k] = 255;
if (!Sprite_CheckTileCollision(k))
return;
if (Sprite_ReturnIfInactive(k))
return;
sprite_type[k] = 0x19;
SpritePrep_LoadProperties(k);
sprite_E[k]++;
sprite_x_lo[k] += 8;
sprite_y_lo[k] -= 8;
SpriteSfx_QueueSfx3WithPan(k, 0x19);
sprite_defl_bits[k] = 0x80;
} else {
if (Sprite_ReturnIfInactive(k))
return;
sprite_subtype2[k]++;
if (!(sprite_subtype2[k] & 0x7f) && sprite_floor[k] == link_is_on_lower_level) {
int j = Sprite_SpawnFireball(k);
if (j >= 0) {
sprite_defl_bits[j] = sprite_defl_bits[j] | 8;
sprite_bump_damage[j] = 4;
}
}
}
}
void Sprite_C6_4WayShooter(int k) { // 9dc869
static const int8 kFireballJunction_X[4] = {12, -12, 0, 0};
static const int8 kFireballJunction_Y[4] = {0, 0, 12, -12};
static const int8 kFireballJunction_XYvel[6] = {0, 0, 40, -40, 0, 0};
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_delay_main[k] == 24) {
int j = Sprite_SpawnFireball(k);
if (j >= 0) {
sprite_defl_bits[j] |= 8;
sprite_bump_damage[j] = 4;
int i = Sprite_DirectionToFaceLink(j, NULL);
sprite_x_vel[j] = kFireballJunction_XYvel[i + 2];
sprite_y_vel[j] = kFireballJunction_XYvel[i];
Sprite_SetX(j, Sprite_GetX(j) + kFireballJunction_X[i]);
Sprite_SetY(j, Sprite_GetY(j) + kFireballJunction_Y[i]);
}
} else if (sprite_delay_main[k] == 0) {
if (button_b_frames && sprite_floor[k] == link_is_on_lower_level)
sprite_delay_main[k] = 32;
}
}
void Sprite_C4_Thief(int k) { // 9dc8d8
int j;
Thief_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageFromLink(k);
if (sprite_ai_state[k] != 3) {
j = Sprite_DirectionToFaceLink(k, NULL);
sprite_head_dir[k] = j;
if ((j ^ sprite_D[k]) == 1)
sprite_D[k] = j;
}
switch (sprite_ai_state[k]) {
case 0: // loitering
Thief_CheckCollisionWithLink(k);
if (!sprite_delay_main[k]) {
if ((uint16)(link_x_coord - cur_sprite_x + 0x50) < 0xa0 &&
(uint16)(link_y_coord - cur_sprite_y + 0x50) < 0xa0) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 16;
}
}
sprite_graphics[k] = kThief_Gfx[sprite_D[k]];
break;
case 1: // watch player
Thief_CheckCollisionWithLink(k);
sprite_D[k] = sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 32;
}
thief_common:
if (!(frame_counter & 31))
sprite_D[k] = sprite_head_dir[k];
sprite_graphics[k] = kThief_Gfx[4 + sprite_D[k] + (++sprite_subtype2[k] & 4)];
break;
case 2: // chase player
Sprite_ApplySpeedTowardsLink(k, 18);
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
if (!sprite_delay_main[k]) {
if ((uint16)(link_x_coord - cur_sprite_x + 0x50) >= 0xa0 ||
(uint16)(link_y_coord - cur_sprite_y + 0x50) >= 0xa0) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 128;
}
}
if (Sprite_CheckDamageToLink(k)) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 32;
Thief_SpillItems(k);
SpriteSfx_QueueSfx2WithPan(k, 0xb);
}
goto thief_common;
case 3: // steal
Thief_CheckCollisionWithLink(k);
j = Thief_ScanForBooty(k);
if (!sprite_delay_main[k]) {
sprite_graphics[k] = kThief_Gfx[4 + sprite_D[k] + (++sprite_subtype2[k] & 4)];
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
sprite_D[k] = sprite_head_dir[k];
}
if (!((k ^ frame_counter) & 3))
sprite_head_dir[k] = Sprite_DirectionToFaceLocation(k, Sprite_GetX(j), Sprite_GetY(j));
break;
}
}
uint8 Thief_ScanForBooty(int k) { // 9dca24
for (int j = 15; j >= 0; j--) {
if (sprite_state[j] && (sprite_type[j] == 0xdc || sprite_type[j] == 0xe1 || sprite_type[j] == 0xd9)) {
Thief_TargetBooty(k, j);
return j;
}
}
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 64;
return 0xff;
}
void Thief_TargetBooty(int k, int j) { // 9dca4c
if (!((k ^ frame_counter) & 3)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, Sprite_GetX(j), Sprite_GetY(j), 19);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
}
for (j = 15; j >= 0; j--) {
if (!((j ^ frame_counter) & 3 | sprite_delay_aux4[j]) && sprite_state[j] &&
(sprite_type[j] == 0xdc || sprite_type[j] == 0xe1 || sprite_type[j] == 0xd9)) {
Thief_GrabBooty(k, j);
}
}
}
void Thief_GrabBooty(int k, int j) { // 9dca9e
if ((uint16)(Sprite_GetX(j) - cur_sprite_x + 8) < 16 &&
(uint16)(Sprite_GetY(j) - cur_sprite_y + 12) < 24) {
sprite_state[j] = 0;
int t = sprite_type[j] - 0xd8;
SpriteSfx_QueueSfx3WithPan(t, kAbsorptionSfx[t]);
sprite_delay_main[k] = 14;
}
}
void Thief_CheckCollisionWithLink(int k) { // 9dcaf2
if (Sprite_CheckDamageToLink_same_layer(k)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 32);
link_actual_vel_y = pt.y;
sprite_y_recoil[k] = pt.y ^ 0xff;
link_actual_vel_x = pt.x;
sprite_x_recoil[k] = pt.x ^ 0xff;
link_incapacitated_timer = 4;
sprite_F[k] = 12;
SpriteSfx_QueueSfx2WithPan(k, 0xb);
}
}
void Thief_SpillItems(int k) { // 9dcb30
static const uint8 kThiefSpawn_Items[4] = {0xd9, 0xe1, 0xdc, 0xd9};
static const int8 kThiefSpawn_Xvel[6] = {0, 24, 24, 0, -24, -24};
static const int8 kThiefSpawn_Yvel[6] = {-32, -16, 16, 32, 16, -16};
tmp_counter = 5;
do {
byte_7E0FB6 = GetRandomNumber() & 3;
int j;
if (byte_7E0FB6 == 1) {
j = link_num_arrows;
} else if (byte_7E0FB6 == 2) {
j = link_item_bombs;
} else {
j = link_rupees_goal;
}
if (!j)
return;
SpriteSpawnInfo info;
j = Sprite_SpawnDynamicallyEx(k, kThiefSpawn_Items[byte_7E0FB6], &info, 7);
if (j < 0)
return;
if (byte_7E0FB6 == 1)
link_num_arrows--;
else if (byte_7E0FB6 == 2)
link_item_bombs--;
else
link_rupees_goal--;
Sprite_SetX(j, link_x_coord);
Sprite_SetY(j, link_y_coord);
sprite_z_vel[j] = 0x18;
sprite_x_vel[j] = kThiefSpawn_Xvel[tmp_counter];
sprite_y_vel[j] = kThiefSpawn_Yvel[tmp_counter];
sprite_delay_aux4[j] = 32;
sprite_head_dir[j] = 1;
sprite_stunned[j] = 255;
} while (!sign8(--tmp_counter));
}
void Thief_Draw(int k) { // 9dcc9e
static const DrawMultipleData kThief_Dmd[24] = {
{0, -6, 0x0000, 2},
{0, 0, 0x0006, 2},
{0, -6, 0x0000, 2},
{0, 0, 0x4006, 2},
{0, -6, 0x0000, 2},
{0, 0, 0x0020, 2},
{0, -7, 0x0004, 2},
{0, 0, 0x0022, 2},
{0, -7, 0x0004, 2},
{0, 0, 0x4022, 2},
{0, -7, 0x0004, 2},
{0, 0, 0x0024, 2},
{0, -8, 0x0002, 2},
{0, 0, 0x000a, 2},
{0, -7, 0x0002, 2},
{0, 0, 0x000e, 2},
{0, -7, 0x0002, 2},
{0, 0, 0x000a, 2},
{0, -8, 0x4002, 2},
{0, 0, 0x400a, 2},
{0, -7, 0x4002, 2},
{0, 0, 0x400e, 2},
{0, -7, 0x4002, 2},
{0, 0, 0x400a, 2},
};
static const uint8 kThief_DrawChar[4] = {2, 2, 0, 4};
static const uint8 kThief_DrawFlags[4] = {0x40, 0, 0, 0};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kThief_Dmd[sprite_graphics[k] * 2], 2, &info);
if (!sprite_pause[k]) {
OamEnt *oam = GetOamCurPtr();
int j = sprite_head_dir[k];
oam->charnum = kThief_DrawChar[j];
oam->flags = (oam->flags & ~0x40) | kThief_DrawFlags[j];
SpriteDraw_Shadow(k, &info);
}
}
void Sprite_C3_Gibo(int k) { // 9dcce1
if (sprite_B[k]) {
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_oam_flags[k] = sprite_oam_flags[k] & 0x3f | kGibo_OamFlags[++sprite_subtype2[k] >> 2 & 3];
if (sprite_delay_main[k]) {
Sprite_MoveXY(k);
Sprite_BounceFromTileCollision(k);
}
return;
}
Gibo_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_anim_clock[k]++;
int j = sprite_head_dir[k], i;
if (sprite_state[j] == 6) {
sprite_state[k] = sprite_state[j];
sprite_delay_main[k] = sprite_delay_main[j];
sprite_flags2[k] += 4;
return;
}
sprite_subtype2[k] = frame_counter >> 3 & 3;
if (!(frame_counter & 63))
sprite_D[k] = Sprite_IsRightOfLink(k).a << 2;
Sprite_CheckDamageToLink(k); // original destroys y which is a bug
switch(sprite_ai_state[k]) {
case 0: // expel nucleus
if (sprite_delay_main[k] == 0) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 48;
sprite_A[k]++;
SpriteSpawnInfo info;
j = Sprite_SpawnDynamically(k, 0xc3, &info);
if (j >= 0) {
static const int8 kGibo_Xvel[8] = {16, 16, 0, -16, -16, -16, 0, 16};
static const int8 kGibo_Yvel[8] = {0, 0, 16, -16, 16, 16, -16, -16};
Sprite_SetSpawnedCoordinates(j, &info);
sprite_head_dir[k] = j;
sprite_flags2[j] = 1;
sprite_B[j] = 1;
sprite_flags3[j] = 16;
sprite_health[j] = sprite_G[k];
sprite_oam_flags[j] = 7;
sprite_delay_main[j] = 48;
if (++sprite_C[k] == 3) {
sprite_C[k] = 0;
i = Sprite_DirectionToFaceLink(k, NULL);
} else {
i = GetRandomNumber() & 7;
}
sprite_x_vel[j] = kGibo_Xvel[i];
sprite_y_vel[j] = kGibo_Yvel[i];
}
} else if (sprite_delay_main[k] == 32) {
sprite_delay_aux1[k] = 32;
}
break;
case 1: // delay pursuit
if (!sprite_delay_main[k])
sprite_ai_state[k]++;
break;
case 2: // pursue nucleus
if (!((k ^ frame_counter) & 3)) {
uint16 x = Sprite_GetX(j), y = Sprite_GetY(j);
if ((uint16)(cur_sprite_x - x + 2) < 4 &&
(uint16)(cur_sprite_y - y + 2) < 4) {
j = sprite_head_dir[k];
sprite_state[j] = 0;
sprite_A[k] = 0;
sprite_ai_state[k] = 0;
sprite_G[k] = sprite_health[j];
sprite_delay_main[k] = (GetRandomNumber() & 31) + 32;
return;
}
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 16);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
}
Sprite_MoveXY(k);
break;
}
}
void Gibo_Draw(int k) { // 9dcf5e
static const DrawMultipleData kGibo_Dmd[32] = {
{ 4, -4, 0x408a, 2},
{-4, -4, 0x408f, 0},
{12, 12, 0x408e, 0},
{-4, 4, 0x408c, 2},
{ 4, -4, 0x40aa, 2},
{-4, -4, 0x409f, 0},
{12, 12, 0x409e, 0},
{-4, 4, 0x40ac, 2},
{ 3, -3, 0x40aa, 2},
{-3, -3, 0x409f, 0},
{11, 11, 0x409e, 0},
{-3, 3, 0x40ac, 2},
{ 3, -3, 0x408a, 2},
{-3, -3, 0x408f, 0},
{11, 11, 0x408e, 0},
{-3, 3, 0x408c, 2},
{-3, -4, 0x008a, 2},
{13, -4, 0x008f, 0},
{-3, 12, 0x008e, 0},
{ 5, 4, 0x008c, 2},
{-3, -4, 0x00aa, 2},
{13, -4, 0x009f, 0},
{-3, 12, 0x009e, 0},
{ 5, 4, 0x00ac, 2},
{-2, -3, 0x00aa, 2},
{12, -3, 0x009f, 0},
{-2, 11, 0x009e, 0},
{ 4, 3, 0x00ac, 2},
{-2, -3, 0x008a, 2},
{12, -3, 0x008f, 0},
{-2, 11, 0x008e, 0},
{ 4, 3, 0x008c, 2},
};
if (!sprite_A[k]) {
uint8 bak0 = sprite_flags2[k];
sprite_flags2[k] = 1;
uint8 bak1 = sprite_oam_flags[k];
sprite_oam_flags[k] = kGibo_OamFlags[sprite_anim_clock[k] >> 2 & 3] |
kGibo_OamFlags2[sprite_delay_aux1[k] >> 2 & 1];
SpriteDraw_SingleLarge(k);
sprite_oam_flags[k] = bak1;
sprite_flags2[k] = bak0;
}
oam_cur_ptr += 8;
oam_ext_cur_ptr += 2;
Sprite_DrawMultiple(k, &kGibo_Dmd[(sprite_subtype2[k] + sprite_D[k]) * 4], 4, NULL);
}
void Sprite_C2_Boulder(int k) { // 9dcfcb
if (!player_is_indoors) {
Boulder_OutdoorsMain(k);
return;
}
if (byte_7E0FC6 < 3)
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_oam_flags[k] = frame_counter << 2 & 0xc0;
Sprite_MoveXYZ(k);
if ((k ^ frame_counter) & 3)
return;
if ((uint16)(cur_sprite_x - link_x_coord + 4) < 16 && (uint16)(cur_sprite_y - link_y_coord - 4) < 12)
Sprite_AttemptDamageToLinkPlusRecoil(k);
if (!((k ^ frame_counter) & 3) && Sprite_CheckTileCollision(k))
sprite_state[k] = 0;
}
void Boulder_OutdoorsMain(int k) { // 9dd02a
static const int8 kBoulder_Zvel[2] = {32, 48};
static const int8 kBoulder_Yvel[2] = {8, 32};
static const int8 kBoulder_Xvel[4] = {24, 16, -24, -16};
sprite_obj_prio[k] = 0x30;
Boulder_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_subtype2[k] -= sprite_D[k];
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXYZ(k);
sprite_z_vel[k]-=2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
int j = Sprite_CheckTileCollision(k) != 0;
sprite_z_vel[k] = kBoulder_Zvel[j];
sprite_y_vel[k] = kBoulder_Yvel[j];
j += (GetRandomNumber() & 1) * 2;
sprite_x_vel[k] = kBoulder_Xvel[j];
sprite_D[k] = (j & 2) - 1;
SpriteSfx_QueueSfx2WithPan(k, 0xb);
}
}
void Boulder_Draw(int k) { // 9dd185
static const DrawMultipleData kBoulder_Dmd[16] = {
{-8, -8, 0x01cc, 2},
{ 8, -8, 0x01ce, 2},
{-8, 8, 0x01ec, 2},
{ 8, 8, 0x01ee, 2},
{-8, -8, 0x41ce, 2},
{ 8, -8, 0x41cc, 2},
{-8, 8, 0x41ee, 2},
{ 8, 8, 0x41ec, 2},
{-8, -8, 0xc1ee, 2},
{ 8, -8, 0xc1ec, 2},
{-8, 8, 0xc1ce, 2},
{ 8, 8, 0xc1cc, 2},
{-8, -8, 0x81ec, 2},
{ 8, -8, 0x81ee, 2},
{-8, 8, 0x81cc, 2},
{ 8, 8, 0x81ce, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kBoulder_Dmd[(sprite_subtype2[k] >> 3 & 3) * 4], 4, &info);
Sprite_DrawLargeShadow2(k);
}
void SpriteDraw_BigShadow(int k, int anim) { // 9dd1a8
cur_sprite_y += sprite_z[k];
oam_cur_ptr += 16;
oam_ext_cur_ptr += 4;
Sprite_DrawMultiple(k, &kLargeShadow_Dmd[anim * 3], 3, NULL);
Sprite_Get16BitCoords(k);
}
void Sprite_DrawLargeShadow2(int k) { // 9dd1af
int z = sprite_z[k] >> 3;
SpriteDraw_BigShadow(k, (z > 4) ? 4 : z);
}
void CutsceneAgahnim_SpawnZeldaOnAltar(int k) { // 9dd1fd
sprite_x_lo[k] += 8;
sprite_y_lo[k] += 6;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xc1, &info);
sprite_A[j] = 1;
sprite_ignore_projectile[j] = 1;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_y_lo[j] = info.r2_y + 40;
sprite_flags2[j] = 0;
sprite_oam_flags[j] = 12;
}
void Sprite_C1_CutsceneAgahnim(int k) { // 9dd234
switch (sprite_A[k]) {
case 0: CutsceneAgahnim_Agahnim(k); break;
case 1: Sprite_CutsceneAgahnim_Zelda(k); break;
}
}
void CutsceneAgahnim_Agahnim(int k) { // 9dd23f
static const uint8 kChattyAgahnim_LevitateGfx[4] = {2, 0, 3, 0};
int j;
PrepOamCoordsRet info;
if (sprite_C[k]) {
if (!sprite_delay_main[k])
sprite_state[k] = 0;
if (!(sprite_delay_main[k] & 1))
ChattyAgahnim_Draw(k, &info);
return;
}
ChattyAgahnim_Draw(k, &info);
SpriteDraw_CutsceneAgahnimSpell(k, &info);
if (sprite_pause[k]) {
sprite_ai_state[k] = 0;
sprite_B[k] = 0;
sprite_graphics[k] = 0;
sprite_delay_main[k] = 64;
}
if (Sprite_ReturnIfInactive(k))
return;
switch(sprite_ai_state[k]) {
case 0: // problab
if (!sprite_delay_main[k]) {
flag_is_link_immobilized = 1;
dialogue_message_index = 0x13d;
Sprite_ShowMessageMinimal();
sprite_ai_state[k]++;
}
break;
case 1: // levitate zelda
j = ++sprite_B[k];
sprite_graphics[k] = sprite_z[15] < 16 ? kChattyAgahnim_LevitateGfx[j >> 5 & 3] : 1;
if ((j & 15) == 0) {
sprite_graphics[15] = 1;
if (++sprite_z[15] == 22) {
sound_effect_2 = 0x27;
sprite_ai_state[k]++;
sprite_delay_main[k] = 255;
sprite_subtype2[k] = 2;
sprite_subtype[k] = 255;
}
}
break;
case 2: // do telewarp
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 80;
} else if (sprite_delay_main[k] == 120) {
intro_times_pal_flash = 120;
} else if (sprite_delay_main[k] < 128 && (sprite_delay_main[k] & 3) == 0) {
sound_effect_2 = 0x2b;
if (sprite_subtype2[k] != 14)
sprite_subtype2[k] += 4;
}
break;
case 3: // complete telewarp
if (sprite_delay_main[k]) {
if (!(sprite_delay_main[k] & 3) && sprite_subtype[k] != 9)
sprite_subtype[k] += 2;
} else {
sprite_delay_main[15] = 19;
sprite_ai_state[k]++;
sprite_delay_main[k] = 80;
sprite_subtype2[k] = 0;
sound_effect_1 = 0x33;
}
break;
case 4: // epiblab
if (!sprite_delay_main[k]) {
dialogue_message_index = 0x13e;
Sprite_ShowMessageMinimal();
sprite_ai_state[k]++;
sprite_delay_main[k] = 2;
}
break;
case 5: // teleport to curtains
if (sprite_delay_main[k] == 1)
sound_effect_2 = 0x28;
sprite_y_vel[k] = -32;
Sprite_MoveY(k);
if (sprite_y_lo[k] < 48) {
sprite_delay_aux4[k] = 66;
sprite_ai_state[k]++;
}
Sprite_Agahnim_ApplyMotionBlur(k);
break;
case 6: // linger then terminate
if (!sprite_delay_aux4[k]) {
flag_is_link_immobilized = 0;
sprite_state[k] = 0;
Sprite_ManuallySetDeathFlagUW(k);
dung_savegame_state_bits |= 0x4000;
}
break;
}
}
int Sprite_Agahnim_ApplyMotionBlur(int k) { // 9dd392
if (frame_counter & 3)
return -1;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xc1, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_graphics[j] = sprite_graphics[k];
sprite_delay_main[j] = 32;
sprite_ignore_projectile[j] = 32;
sprite_C[j] = 32;
}
return j;
}
void ChattyAgahnim_Draw(int k, PrepOamCoordsRet *info) { // 9dd451
static const DrawMultipleData kChattyAgahnim_Dmd[16] = {
{-8, -8, 0x0b82, 2},
{ 8, -8, 0x4b82, 2},
{-8, 8, 0x0ba2, 2},
{ 8, 8, 0x4ba2, 2},
{-8, -8, 0x0b80, 2},
{ 8, -8, 0x4b80, 2},
{-8, 8, 0x0ba0, 2},
{ 8, 8, 0x4ba0, 2},
{-8, -8, 0x0b80, 2},
{ 8, -8, 0x4b82, 2},
{-8, 8, 0x0ba0, 2},
{ 8, 8, 0x4ba2, 2},
{-8, -8, 0x0b82, 2},
{ 8, -8, 0x4b80, 2},
{-8, 8, 0x0ba2, 2},
{ 8, 8, 0x4ba0, 2},
};
if (sprite_delay_aux4[k] & 1)
return;
if (sprite_C[k] == 0) {
oam_cur_ptr = 0x900;
oam_ext_cur_ptr = 0xa60;
}
Sprite_DrawMultiple(k, &kChattyAgahnim_Dmd[sprite_graphics[k] * 4], 4, info);
SpriteDraw_Shadow_custom(k, info, 18);
}
void SpriteDraw_CutsceneAgahnimSpell(int k, PrepOamCoordsRet *info) { // 9dd516
static const OamEntSigned kChattyAgahnim_Telewarp_Data[28] = {
{-10, -16, 0xce, 0x06},
{ 18, -16, 0xce, 0x06},
{ 20, -13, 0x26, 0x06},
{ 20, -5, 0x36, 0x06},
{-12, -13, 0x26, 0x46},
{-12, -5, 0x36, 0x46},
{ 18, 0, 0x26, 0x06},
{ 18, 8, 0x36, 0x06},
{-10, 0, 0x26, 0x46},
{-10, 8, 0x36, 0x46},
{ -8, 0, 0x22, 0x06},
{ 8, 0, 0x22, 0x46},
{ -8, 16, 0x22, 0x86},
{ 8, 16, 0x22, 0xc6},
{-10, -16, 0xce, 0x04},
{ 18, -16, 0xce, 0x04},
{ 20, -13, 0x26, 0x44},
{ 20, -5, 0x36, 0x44},
{-12, -13, 0x26, 0x04},
{-12, -5, 0x36, 0x04},
{ 18, 0, 0x26, 0x44},
{ 18, 8, 0x36, 0x44},
{-10, 0, 0x26, 0x04},
{-10, 8, 0x36, 0x04},
{ -8, 0, 0x20, 0x04},
{ 8, 0, 0x20, 0x44},
{ -8, 16, 0x20, 0x84},
{ 8, 16, 0x20, 0xc4},
};
static const uint8 kChattyAgahnim_Telewarp_Data_Ext[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2};
Oam_AllocateFromRegionA(0x38);
const OamEntSigned *data = kChattyAgahnim_Telewarp_Data;
if (!(frame_counter & 2))
data += 14;
const uint8 *ext_data = kChattyAgahnim_Telewarp_Data_Ext;
if (!sprite_subtype2[k])
return;
OamEnt *oam = GetOamCurPtr();
uint8 kn = sprite_subtype2[k] - 1;
uint8 end = sprite_subtype[k];
uint8 t = end + 1;
oam += t;
ext_data += t;
data += t;
do {
oam->x = info->x + data->x;
oam->y = info->y + data->y - 8;
oam->charnum = data->charnum;
oam->flags = data->flags | 0x31;
bytewise_extended_oam[oam - oam_buf] = *ext_data;
} while (data++, ext_data++, oam++, --kn != end);
}
void Sprite_CutsceneAgahnim_Zelda(int k) { // 9dd57d
static const DrawMultipleData kAltarZelda_Dmd[4] = {
{-4, 0, 0x0103, 2},
{ 4, 0, 0x0104, 2},
{-4, 0, 0x0100, 2},
{ 4, 0, 0x0101, 2},
};
int j = sprite_delay_main[k];
if (j != 0) {
SpriteDraw_AltarZeldaWarp(k);
if (j == 1)
sprite_state[k] = 0;
if (j < 12)
return;
}
Oam_AllocateFromRegionA(8);
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kAltarZelda_Dmd[sprite_graphics[k] * 2], 2, &info);
AltarZelda_DrawBody(k, &info);
}
void AltarZelda_DrawBody(int k, PrepOamCoordsRet *info) { // 9dd5e9
static const uint8 kAltarZelda_XOffs[16] = {4, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
Oam_AllocateFromRegionA(8);
int z = sprite_z[k] < 31 ? sprite_z[k] : 31;
uint8 xoffs = kAltarZelda_XOffs[z >> 1];
int y = Sprite_GetY(k) - BG2VOFS_copy2;
OamEnt *oam = GetOamCurPtr();
oam[0].x = info->x + xoffs;
oam[1].x = info->x - xoffs;
oam[0].y = oam[1].y = ClampYForOam(y + 7);
oam[0].charnum = oam[1].charnum = 0x6c;
oam[0].flags = oam[1].flags = 0x24;
bytewise_extended_oam[oam - oam_buf] = 2;
bytewise_extended_oam[oam - oam_buf + 1] = 2;
}
void SpriteDraw_AltarZeldaWarp(int k) { // 9dd6b1
static const DrawMultipleData kAltarZelda_Warp_Dmd[10] = {
{ 4, 4, 0x0480, 0},
{ 4, 4, 0x0480, 0},
{ 4, 4, 0x04b7, 0},
{ 4, 4, 0x04b7, 0},
{-6, 0, 0x0524, 2},
{ 6, 0, 0x4524, 2},
{-8, 0, 0x0524, 2},
{ 8, 0, 0x4524, 2},
{ 0, 0, 0x05c6, 2},
{ 0, 0, 0x05c6, 2},
};
Oam_AllocateFromRegionA(8);
Sprite_DrawMultiple(k, &kAltarZelda_Warp_Dmd[(sprite_delay_main[k] >> 2) * 2], 2, NULL);
}
void Sprite_InitializedSegmented(int k) { // 9dd6d1
for (int i = 0; i < 128; i++) {
moldorm_x_lo[i] = sprite_x_lo[k];
moldorm_x_hi[i] = sprite_x_hi[k];
moldorm_y_lo[i] = sprite_y_lo[k];
moldorm_y_hi[i] = sprite_y_hi[k];
}
}
void GiantMoldorm_Draw(int k) { // 9dd881
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
sprite_oam_flags[k] = 11;
SpriteDraw_Moldorm_Eyeballs(k, &info);
oam_cur_ptr += 8, oam_ext_cur_ptr += 2;
int j = sprite_subtype2[k] & 0x7f;
moldorm_x_lo[j] = sprite_x_lo[k];
moldorm_x_hi[j] = sprite_x_hi[k];
moldorm_y_lo[j] = sprite_y_lo[k];
moldorm_y_hi[j] = sprite_y_hi[k];
SpriteDraw_Moldorm_Head(k);
if (sprite_B[k] < 4) {
GiantMoldorm_DrawSegment_AB(k, 16);
if (sprite_B[k] < 3) {
GiantMoldorm_DrawSegment_AB(k, 28);
if (sprite_B[k] < 2) {
SpriteDraw_Moldorm_SegmentC(k);
if (sprite_B[k] == 0)
Moldorm_HandleTail(k);
}
}
}
GiantMoldorm_IncrementalSegmentExplosion(k);
Sprite_Get16BitCoords(k);
}
void GiantMoldorm_IncrementalSegmentExplosion(int k) { // 9dd8f2
if (sprite_state[k] == 9 && sprite_delay_aux4[k] && sprite_delay_aux4[k] < 80 &&
!(sprite_delay_aux4[k] & 15 | submodule_index | flag_unk1)) {
sprite_B[k]++;
Sprite_MakeBossExplosion(k);
}
}
void SpriteDraw_Moldorm_Head(int k) { // 9dd993
static const DrawMultipleData kGiantMoldorm_Head_Dmd[16] = {
{-8, -8, 0x0080, 2},
{ 8, -8, 0x0082, 2},
{-8, 8, 0x00a0, 2},
{ 8, 8, 0x00a2, 2},
{-8, -8, 0x4082, 2},
{ 8, -8, 0x4080, 2},
{-8, 8, 0x40a2, 2},
{ 8, 8, 0x40a0, 2},
{-6, -6, 0x0080, 2},
{ 6, -6, 0x0082, 2},
{-6, 6, 0x00a0, 2},
{ 6, 6, 0x00a2, 2},
{-6, -6, 0x4082, 2},
{ 6, -6, 0x4080, 2},
{-6, 6, 0x40a2, 2},
{ 6, 6, 0x40a0, 2},
};
int t = (sprite_subtype2[k] >> 1 & 1) + (sprite_delay_aux1[k] & 2);
Sprite_DrawMultiple(k, &kGiantMoldorm_Head_Dmd[t * 4], 4, NULL);
}
void SpriteDraw_Moldorm_SegmentC(int k) { // 9dda5f
sprite_graphics[k] = 0;
oam_cur_ptr += 0x10;
oam_ext_cur_ptr += 4;
GiantMoldorm_DrawSegment_C_OrTail(k, 0x28);
}
void Moldorm_HandleTail(int k) { // 9ddaba
SpriteDraw_Moldorm_Tail(k);
if (!sprite_delay_aux2[k]) {
sprite_A[k] = 1;
sprite_flags4[k] = 0;
sprite_defl_bits[k] = 0;
uint16 oldx = Sprite_GetX(k);
uint16 oldy = Sprite_GetY(k);
Sprite_SetX(k, cur_sprite_x);
Sprite_SetY(k, cur_sprite_y);
Sprite_CheckDamageFromLink(k);
sprite_A[k] = 0;
sprite_flags4[k] = 9;
sprite_defl_bits[k] = 4;
Sprite_SetX(k, oldx);
Sprite_SetY(k, oldy);
}
}
void SpriteDraw_Moldorm_Tail(int k) { // 9ddb17
oam_cur_ptr += 4;
oam_ext_cur_ptr += 1;
sprite_graphics[k]++;
sprite_oam_flags[k] = 13;
GiantMoldorm_DrawSegment_C_OrTail(k, 0x30);
}
void SpriteDraw_Moldorm_Eyeballs(int k, PrepOamCoordsRet *info) { // 9ddb9e
static const int16 kGiantMoldorm_Eye_X[16] = {16, 15, 12, 6, 0, -6, -12, -13, -16, -13, -12, -6, 0, 6, 12, 15};
static const int16 kGiantMoldorm_Eye_Y[16] = {0, 6, 12, 15, 16, 15, 12, 6, 0, -6, -12, -13, -16, -13, -12, -6};
static const uint8 kGiantMoldorm_Eye_Char[16] = {0xaa, 0xaa, 0xa8, 0xa8, 0x8a, 0x8a, 0xa8, 0xa8, 0xaa, 0xaa, 0xa8, 0xa8, 0x8a, 0x8a, 0xa8, 0xa8};
static const uint8 kGiantMoldorm_Eye_Flags[16] = {0, 0, 0, 0, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0xc0, 0xc0, 0, 0, 0x80, 0x80};
OamEnt *oam = GetOamCurPtr();
uint8 yoff = kBadPullSwitch_Tab5[kBadPullSwitch_Tab4[sprite_graphics[k]]];
int r7 = sprite_F[k] ? frame_counter : 0;
int r6 = sprite_D[k] - 1;
for (int i = 1; i >= 0; i--, oam++, r6 += 2) {
uint16 x = info->x + kGiantMoldorm_Eye_X[r6 & 0xf];
int y = info->y + (uint16)kGiantMoldorm_Eye_Y[r6 & 0xf];
oam->x = x;
oam->y = (uint16)(y + 0x10 + ((y >> 16) & 1)) < 0x100 ? y : 0xf0;
oam->charnum = kGiantMoldorm_Eye_Char[(r6 + r7) & 0xf];
oam->flags = info->flags | kGiantMoldorm_Eye_Flags[(r6 + r7) & 0xf];
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
}
void Sprite_ScheduleBossForDeath(int k) { // 9ddc16
sprite_state[k] = 4;
sprite_A[k] = 0;
sprite_delay_main[k] = 224;
}
void Sprite_MakeBossExplosion(int k) { // 9ddc2a
SpriteSfx_QueueSfx2WithPan(k, 0xc);
Sprite_MakeBossDeathExplosion_NoSound(k);
}
void Sprite_MakeBossDeathExplosion_NoSound(int k) { // 9ddc30
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x00, &info);
if (j >= 0) {
load_chr_halfslot_even_odd = 11;
sprite_state[j] = 4;
sprite_flags2[j] = 3;
sprite_oam_flags[j] = 12;
Sprite_SetX(j, cur_sprite_x);
Sprite_SetY(j, cur_sprite_y);
sprite_delay_main[j] = 31;
sprite_A[j] = 31;
sprite_floor[j] = 2;
}
}
void Vulture_Draw(int k) { // 9ddd5e
static const DrawMultipleData kVulture_Dmd[8] = {
{-8, 0, 0x0086, 2},
{ 8, 0, 0x4086, 2},
{-8, 0, 0x0080, 2},
{ 8, 0, 0x4080, 2},
{-8, 0, 0x0082, 2},
{ 8, 0, 0x4082, 2},
{-8, 0, 0x0084, 2},
{ 8, 0, 0x4084, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kVulture_Dmd[sprite_graphics[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_Raven(int k) { // 9ddd85
static const uint8 kRaven_AscendTime[2] = {16, 248};
int j;
bool fleeing = false;
sprite_obj_prio[k] |= 0x30;
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
switch (sprite_ai_state[k]) {
case 0: { // inwait
PairU8 r = Sprite_IsRightOfLink(k);
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | r.a * 0x40;
int x = link_x_coord - cur_sprite_x;
int y = link_y_coord - cur_sprite_y;
if ((uint16)(x + 0x50 + (x >= 0)) < 0xa0 && (uint16)(y + 0x58 + (y >= 0)) < 0xa0) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 24;
SpriteSfx_QueueSfx3WithPan(k, 0x1e);
}
break;
}
case 1: // ascend
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
int j = sprite_A[k];
sprite_delay_main[k] = kRaven_AscendTime[j];
Sprite_ApplySpeedTowardsLink(k, 32);
}
sprite_z[k]++;
sprite_graphics[k] = (frame_counter >> 1 & 1) + 1;
break;
case 2: // attack
if (!sprite_delay_main[k] && !(is_in_dark_world && sprite_A[k]) )
sprite_ai_state[k]++;
fly:
if (!((k ^ frame_counter) & 1)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, fleeing ? 48 : 32);
if (fleeing)
pt.x = -pt.x, pt.y = -pt.y;
if (sprite_x_vel[k] - pt.x)
sprite_x_vel[k] += sign8(sprite_x_vel[k] - pt.x) ? 1 : -1;
if (sprite_y_vel[k] - pt.y)
sprite_y_vel[k] += sign8(sprite_y_vel[k] - pt.y) ? 1 : -1;
}
sprite_graphics[k] = (frame_counter >> 1 & 1) + 1;
j = (sprite_x_vel[k] >> 7) & 1;
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | j * 0x40;
break;
case 3: // flee
fleeing = true;
goto fly;
}
}
void Vitreous_SpawnSmallerEyes(int k) { // 9ddecb
sprite_G[k] = 9;
sprite_graphics[k] = 4;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0x4, &info, 13);
static const int8 kVitreous_SpawnSmallerEyes_X[13] = {8, 22, -8, -22, 0, 14, 19, 33, 26, -14, -19, -33, -26};
static const int8 kVitreous_SpawnSmallerEyes_Y[13] = {-8, -12, -8, -12, 0, -20, -1, -12, -24, -20, -1, -12, -24};
static const int8 kVitreous_SpawnSmallerEyes_Gfx[13] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
for (j = 13; j != 0; j--) {
sprite_state[j] = 9;
sprite_type[j] = 0xbe;
SpritePrep_LoadProperties(j);
sprite_floor[j] = 0;
Sprite_SetX(j, info.r0_x + kVitreous_SpawnSmallerEyes_X[j - 1]);
Sprite_SetY(j, info.r2_y + kVitreous_SpawnSmallerEyes_Y[j - 1] + 32);
sprite_A[j] = sprite_x_lo[j];
sprite_B[j] = sprite_x_hi[j];
sprite_C[j] = sprite_y_lo[j];
sprite_D[j] = sprite_y_hi[j];
sprite_ignore_projectile[j] = sprite_graphics[j] = kVitreous_SpawnSmallerEyes_Gfx[j - 1];
sprite_subtype2[j] = (j - 1) * 8 + GetRandomNumber();
}
}
void Sprite_C0_Catfish(int k) { // 9ddf49
if (sprite_A[k] & 0x80)
Sprite_Catfish_SplashOfWater(k);
else if (sprite_A[k] == 0)
Catfish_BigFish(k);
else
Sprite_Catfish_QuakeMedallion(k);
}
void Sprite_Catfish_QuakeMedallion(int k) { // 9ddf54
if (!sprite_z[k]) {
SpriteDraw_WaterRipple_WithOamAdjust(k);
if (!submodule_index && Sprite_CheckDamageToLink_same_layer(k)) {
sprite_state[k] = 0;
item_receipt_method = 0;
Link_ReceiveItem(sprite_A[k], 0);
}
}
if (sprite_delay_aux3[k])
Oam_AllocateFromRegionC(8);
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXYZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_x_vel[k] = (int8)sprite_x_vel[k] >> 1;
sprite_y_vel[k] = (int8)sprite_y_vel[k] >> 1;
int j = sprite_ai_state[k];
if (j == 4) {
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
sprite_z_vel[k] = 0;
} else {
sprite_ai_state[k]++;
static const uint8 kStandaloneItem_Zvel[4] = {0x20, 0x10, 8, 0};
sprite_z_vel[k] = kStandaloneItem_Zvel[j];
if (j < 2 && (j = Sprite_SpawnWaterSplash(k)) >= 0)
sprite_delay_main[j] = 16;
}
}
}
void Catfish_BigFish(int k) { // 9ddfd1
GreatCatfish_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch(sprite_ai_state[k]) {
case 0: // AwaitSpriteThrownInCircle
for (int j = 15; j >= 0; j--) {
if (j == k || sprite_state[j] != 3)
continue;
if ((uint16)(cur_sprite_x - Sprite_GetX(j) + 32) < 64 && (uint16)(cur_sprite_y - Sprite_GetY(j) + 32) < 64) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 255;
return;
}
}
break;
case 1: { // RumbleBeforeEmergence
int j = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 255;
bg1_x_offset = 0;
sound_effect_ambient = 5;
sprite_z_vel[k] = 48;
sprite_x_vel[k] = 0;
Catfish_SpawnPlop(k);
} else if (sprite_delay_main[k] < 0xc0) {
if (sprite_delay_main[k] == 0xbf)
sound_effect_ambient = 7;
bg1_x_offset = (j & 1) ? -1 : 1;
flag_is_link_immobilized = 1;
}
break;
}
case 2: { // Emerge
static const uint8 kGreatCatfish_Emerge_Gfx[16] = {1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 0, 0, 0, 0};
sprite_subtype2[k]++;
Sprite_MoveXYZ(k);
sprite_z_vel[k] -= 2;
if (sprite_z_vel[k] == (uint8)(-48))
Catfish_SpawnPlop(k);
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_ai_state[k]++;
sprite_delay_main[k] = 255;
}
sprite_graphics[k] = kGreatCatfish_Emerge_Gfx[sprite_subtype2[k] >> 2];
break;
}
case 3: { // ConversateThenSubmerge
int j = sprite_delay_main[k];
static const uint8 kGreatCatfish_Conversate_Gfx[20] = { 0, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6 };
if (j == 0) {
sprite_state[k] = 0;
} else {
if (j == 160 || j == 252 || j == 4) {
Sprite_SpawnWaterSplash(k);
} else if (j == 10) {
Catfish_SpawnPlop(k);
} else if (j == 96) {
flag_is_link_immobilized = 0;
dialogue_message_index = link_item_quake_medallion ? 0x12b : 0x12a;
Sprite_ShowMessageMinimal();
return;
} else if (j == 80) {
if (link_item_quake_medallion) {
if (GetRandomNumber() & 1)
Sprite_SpawnBomb(k);
else
Sprite_SpawnFireball(k);
} else {
Catfish_RegurgitateMedallion(k);
}
}
if (j < 160)
sprite_graphics[k] = kGreatCatfish_Conversate_Gfx[j >> 3];
}
break;
}
}
}
int Sprite_SpawnBomb(int k) { // 9de144
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x4a, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
Sprite_TransmuteToBomb(j);
sprite_delay_aux1[j] = 80;
sprite_x_vel[j] = 24;
sprite_z_vel[j] = 48;
}
return j;
}
void Catfish_RegurgitateMedallion(int k) { // 9de16c
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xc0, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_x_vel[j] = 24;
sprite_z_vel[j] = 48;
sprite_A[j] = 17;
SpriteSfx_QueueSfx2WithPan(j, 0x20);
sprite_flags2[j] = 0x83;
sprite_flags3[j] = 0x58;
sprite_oam_flags[j] = 0x58 & 0xf;
DecodeAnimatedSpriteTile_variable(0x1c);
}
}
void Sprite_Zora_RegurgitateFlippers(int k) { // 9de1aa
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xc0, &info);
if (j < 0)
return;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_z_vel[j] = 32;
sprite_y_vel[j] = 16;
sprite_A[j] = 30;
SpriteSfx_QueueSfx2WithPan(j, 0x20);
sprite_flags2[j] = 0x83;
sprite_flags3[j] = 0x54;
sprite_oam_flags[j] = 0x54 & 15;
sprite_delay_aux3[j] = 0x30;
DecodeAnimatedSpriteTile_variable(0x11);
}
void Catfish_SpawnPlop(int k) { // 9de1ed
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xec, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_state[j] = 3;
sprite_delay_main[j] = 15;
sprite_ai_state[j] = 0;
sprite_flags2[j] = 3;
SpriteSfx_QueueSfx2WithPan(k, 0x28);
}
}
int Sprite_SpawnWaterSplash(int k) { // 9de21c
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xc0, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_A[j] = 0x80;
sprite_flags2[j] = 2;
sprite_ignore_projectile[j] = 2;
sprite_oam_flags[j] = 4;
sprite_delay_main[j] = 31;
}
return j;
}
void GreatCatfish_Draw(int k) { // 9de320
static const DrawMultipleData kGreatCatfish_Dmd[28] = {
{-4, 4, 0x008c, 2},
{ 4, 4, 0x008d, 2},
{-4, 4, 0x008c, 2},
{ 4, 4, 0x008d, 2},
{-4, -4, 0x008c, 2},
{ 4, -4, 0x008d, 2},
{-4, 4, 0x009c, 2},
{ 4, 4, 0x009d, 2},
{-4, -4, 0x408d, 2},
{ 4, -4, 0x408c, 2},
{-4, 4, 0x409d, 2},
{ 4, 4, 0x409c, 2},
{-4, -4, 0xc09d, 2},
{ 4, -4, 0xc09c, 2},
{-4, 4, 0xc08d, 2},
{ 4, 4, 0xc08c, 2},
{-4, 4, 0xc09d, 2},
{ 4, 4, 0xc09c, 2},
{-4, 4, 0xc09d, 2},
{ 4, 4, 0xc09c, 2},
{ 0, 8, 0x00bd, 0},
{ 8, 8, 0x40bd, 0},
{ 8, 8, 0x40bd, 0},
{ 8, 8, 0x40bd, 0},
{-8, 0, 0x0086, 2},
{ 8, 0, 0x4086, 2},
{ 8, 0, 0x4086, 2},
{ 8, 0, 0x4086, 2},
};
if (sprite_graphics[k])
Sprite_DrawMultiple(k, &kGreatCatfish_Dmd[(sprite_graphics[k] - 1) * 4], 4, NULL);
}
void Sprite_Catfish_SplashOfWater(int k) { // 9de37d
static const DrawMultipleData kWaterSplash_Dmd[8] = {
{-8, -4, 0x0080, 0},
{18, -7, 0x0080, 0},
{-5, -2, 0x00bf, 0},
{15, -4, 0x40af, 0},
{ 0, -4, 0x00e7, 2},
{ 0, -4, 0x00e7, 2},
{ 0, -4, 0x00c0, 2},
{ 0, -4, 0x00c0, 2},
};
if (!sprite_delay_main[k])
sprite_state[k] = 0;
Sprite_DrawMultiple(k, &kWaterSplash_Dmd[(sprite_delay_main[k] >> 3) * 2], 2, NULL);
}
void Sprite_BF_Lightning(int k) { // 9de3ed
static const uint8 kSpriteLightning_Gfx[8] = {0, 1, 2, 3, 0, 1, 2, 3};
static const uint8 kSpriteLightning_OamFlags[8] = {0, 0, 0, 0, 0x40, 0x40, 0x40, 0x40};
static const int8 kSpriteLightning_Xoff[64] = {
-15, 0, 0, -15, 0, -15, -15, 0, -15, 0, 0, -15, 0, -15, -15, 0,
0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 15, 0, 15, 0, 0, 15,
0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 15, 0, 15, 0, 0, 15,
-15, 0, 0, -15, 0, -15, -15, 0, -15, 0, 0, -15, 0, -15, -15, 0,
};
int j = sprite_A[k];
sprite_oam_flags[k] = sprite_oam_flags[k] & 0xb1 | kSpriteLightning_OamFlags[j] | frame_counter << 1 & 14;
sprite_graphics[k] = kSpriteLightning_Gfx[j] + (BYTE(dungeon_room_index2) == 0x20 ? 4 : 0);
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_delay_main[k])
return;
Lightning_SpawnGarnish(k);
sprite_delay_main[k] = 2;
Sprite_SetY(k, Sprite_GetY(k) + 16);
if ((uint8)(sprite_y_lo[k] - BG2VOFS_copy2) >= 0xd0) {
sprite_state[k] = 0;
return;
}
int rr = GetRandomNumber() & 7;
Sprite_SetX(k, Sprite_GetX(k) + kSpriteLightning_Xoff[sprite_A[k] << 3 | rr]);
sprite_A[k] = rr;
}
void Lightning_SpawnGarnish(int k) { // 9de475
int j = GarnishAllocOverwriteOld();
garnish_type[j] = 9;
garnish_active = 9;
garnish_sprite[j] = sprite_A[k];
garnish_x_lo[j] = sprite_x_lo[k];
garnish_x_hi[j] = sprite_x_hi[k];
int y = Sprite_GetY(k) + 16;
garnish_y_lo[j] = y;
garnish_y_hi[j] = y >> 8;
garnish_countdown[j] = 32;
}
void Sprite_BD_Vitreous(int k) { // 9de4c8
if (sprite_delay_aux4[k])
sprite_graphics[k] = 3;
Vitreous_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Vitreous_SetMinionsForth(k);
Sprite_CheckDamageToAndFromLink(k);
switch(sprite_ai_state[k]) {
case 0: // dormant
byte_7E0FF8 = 0;
sprite_F[k] = 0;
sprite_flags3[k] |= 64;
if (!(frame_counter & 1) && !--sprite_A[k]) {
sprite_flags3[k] &= ~0x40;
sprite_delay_aux4[k] = 16;
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 128;
if (!sprite_G[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 64;
sprite_ignore_projectile[k] = 0;
sound_effect_1 = 0x35;
return;
}
}
sprite_graphics[k] = frame_counter & 0x30 ? 4 : 5;
break;
case 1: // spew lighting
sprite_F[k] = 0;
if (!sprite_delay_main[k]) {
static const uint8 kVitreous_AfromG[10] = {0x20, 0x20, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0};
sprite_delay_aux4[k] = 16;
sprite_ai_state[k] = 0;
sprite_A[k] = kVitreous_AfromG[sprite_G[k]];
} else {
Vitreous_Animate(k, sprite_delay_main[k]);
}
break;
case 2: // pursue player
Vitreous_Animate(k, 0x8B);
if (Sprite_ReturnIfRecoiling(k))
return;
if (sprite_delay_main[k]) {
static const int8 kVitreous_Xvel[2] = {8, -8};
sprite_x_vel[k] = kVitreous_Xvel[(sprite_delay_main[k] & 2) >> 1];
Sprite_MoveX(k);
} else {
Sprite_MoveXYZ(k);
Sprite_CheckTileCollision(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 32;
Sprite_ApplySpeedTowardsLink(k, 16);
SpriteSfx_QueueSfx2WithPan(k, 0x21);
}
}
break;
}
}
void Vitreous_Animate(int k, uint8 a) { // 9de563
static const int8 kVitreous_Animate_Gfx[2] = {2, 1};
if (a == 0x40 || a == 0x41 || a == 0x42)
Sprite_SpawnLightning(k);
sprite_graphics[k] = 0;
PairU8 pair = Sprite_IsRightOfLink(k);
if ((uint8)(pair.b + 16) >= 32)
sprite_graphics[k] = kVitreous_Animate_Gfx[pair.a];
}
void Vitreous_SetMinionsForth(int k) { // 9de5da
static const uint8 kVitreous_WhichToActivate[16] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 5, 6, 7, 8, 9, 10, 11};
if (!(++sprite_subtype2[k] & 63)) {
int j = kVitreous_WhichToActivate[GetRandomNumber() & 15];
if (sprite_ai_state[j] == 0) {
sprite_ai_state[j] = 1;
sound_effect_1 = 0x15;
} else {
sprite_subtype2[k]--;
}
}
}
void Sprite_SpawnLightning(int k) { // 9de612
static const int8 kAgahnim_Lighting_X[8] = {-8, 8, 8, -8, 8, -8, -8, 8};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xBF, &info), i;
if (j >= 0) {
sound_effect_2 = 0x26;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_A[j] = i = GetRandomNumber() & 7;
int t = info.r0_x + (uint16)kAgahnim_Lighting_X[i];
Sprite_SetX(j, info.r0_x + kAgahnim_Lighting_X[i]);
sprite_y_lo[j] = info.r2_y + 12 + (t >> 16);
sprite_delay_main[j] = 2;
intro_times_pal_flash = 32;
}
}
void Vitreous_Draw(int k) { // 9de716
static const DrawMultipleData kVitreous_Dmd[24] = {
{-8, -8, 0x01c0, 2},
{ 8, -8, 0x41c0, 2},
{-8, 8, 0x01e0, 2},
{ 8, 8, 0x41e0, 2},
{-8, -8, 0x01c8, 2},
{ 8, -8, 0x01ca, 2},
{-8, 8, 0x01e8, 2},
{ 8, 8, 0x01ea, 2},
{-8, -8, 0x41ca, 2},
{ 8, -8, 0x41c8, 2},
{-8, 8, 0x41ea, 2},
{ 8, 8, 0x41e8, 2},
{-8, -8, 0x01c2, 2},
{ 8, -8, 0x41c2, 2},
{-8, 8, 0x01e2, 2},
{ 8, 8, 0x41e2, 2},
{-8, -8, 0x01c4, 2},
{ 8, -8, 0x41c4, 2},
{-8, 8, 0x01e4, 2},
{ 8, 8, 0x41e4, 2},
{-7, -7, 0x01c4, 2},
{ 7, -7, 0x41c4, 2},
{-7, 7, 0x01e4, 2},
{ 7, 7, 0x41e4, 2},
};
if (sprite_ai_state[k] == 2 && sprite_state[k] == 9)
oam_cur_ptr = 0x800, oam_ext_cur_ptr = 0xa20;
Sprite_DrawMultiple(k, &kVitreous_Dmd[sprite_graphics[k] * 4], 4, NULL);
if (sprite_ai_state[k] == 2) {
sprite_obj_prio[k] &= ~0xe;
Sprite_DrawLargeShadow2(k);
}
}
void Sprite_BE_VitreousEye(int k) { // 9de773
static const int8 kSprite_Vitreolus_Dx[4] = {1, 0, -1, 0};
static const int8 kSprite_Vitreolus_Dy[4] = {0, 1, 0, -1};
int j = sprite_subtype2[k] >> 4 & 3;
cur_sprite_x += kSprite_Vitreolus_Dx[j];
cur_sprite_y += kSprite_Vitreolus_Dy[j];
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_subtype2[k]++;
if (sprite_graphics[k])
return;
Sprite_CheckDamageFromLink(k);
Sprite_CheckDamageToLink(k);
if (sprite_F[k] == 14)
sprite_F[k] = 5;
switch (sprite_ai_state[k]) {
case 0: // target player
sprite_G[k] = link_x_coord;
sprite_head_dir[k] = link_x_coord >> 8;
sprite_anim_clock[k] = link_y_coord;
sprite_subtype[k] = link_y_coord >> 8;
break;
case 1: // pursue player
if (Sprite_ReturnIfRecoiling(k))
return;
if (!((k ^ frame_counter) & 1)) {
uint16 x = sprite_head_dir[k] << 8 | sprite_G[k];
uint16 y = sprite_subtype[k] << 8 | sprite_anim_clock[k];
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 16);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
}
Sprite_MoveXY(k);
if ((uint8)(sprite_G[k] - sprite_x_lo[k] + 4) < 8 && (uint8)(sprite_anim_clock[k] - sprite_y_lo[k] + 4) < 8)
sprite_ai_state[k] = 2;
break;
case 2: // return
if (Sprite_ReturnIfRecoiling(k))
return;
if (!((k ^ frame_counter) & 1)) {
uint16 x = sprite_A[k] | sprite_B[k] << 8;
uint16 y = sprite_C[k] | sprite_D[k] << 8;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 16);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
}
Sprite_MoveXY(k);
if ((uint8)(sprite_A[k] - sprite_x_lo[k] + 4) < 8 && (uint8)(sprite_C[k] - sprite_y_lo[k] + 4) < 8) {
sprite_x_lo[k] = sprite_A[k];
sprite_x_hi[k] = sprite_B[k];
sprite_y_lo[k] = sprite_C[k];
sprite_y_hi[k] = sprite_D[k];
sprite_ai_state[k] = 0;
}
break;
}
}
void HelmasaurFireball_TriSplit(int k) { // 9deed3
static const int8 kHelmasaurFireball_TriSplit_Xvel[3] = {0, 28, -28};
static const int8 kHelmasaurFireball_TriSplit_Yvel[3] = {-32, 24, 24};
static const uint8 kHelmasaurFireball_TriSplit_Delay[6] = {32, 80, 128, 32, 80, 128};
SpriteSfx_QueueSfx3WithPan(k, 0x36);
sprite_state[k] = 0;
byte_7E0FB6 = GetRandomNumber();
for (int i = 2; i >= 0; i--) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x70, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_x_vel[j] = kHelmasaurFireball_TriSplit_Xvel[i];
sprite_y_vel[j] = kHelmasaurFireball_TriSplit_Yvel[i];
sprite_ai_state[j] = 3;
sprite_ignore_projectile[j] = 3;
sprite_delay_main[j] = kHelmasaurFireball_TriSplit_Delay[(byte_7E0FB6 & 3) + i];
sprite_head_dir[j] = 0;
sprite_graphics[j] = 1;
}
}
tmp_counter = -1;
}
void HelmasaurFireball_QuadSplit(int k) { // 9def3d
static const int8 kHelmasaurFireball_QuadSplit_Xvel[4] = {32, 32, -32, -32};
static const int8 kHelmasaurFireball_QuadSplit_Yvel[4] = {-32, 32, -32, 32};
SpriteSfx_QueueSfx3WithPan(k, 0x36);
sprite_state[k] = 0;
for (int i = 3; i >= 0; i--) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x70, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_x_vel[j] = kHelmasaurFireball_QuadSplit_Xvel[i];
sprite_y_vel[j] = kHelmasaurFireball_QuadSplit_Yvel[i];
sprite_ai_state[j] = 4;
sprite_ignore_projectile[j] = 4;
}
}
tmp_counter = -1;
}
void Sprite_ArmosCrusher(int k) { // 9def7e
sprite_oam_flags[k] = 7;
bg1_y_offset = sprite_delay_aux4[k] ? (sprite_delay_aux4[k] & 1 ? -1 : 1) : 0;
switch (sprite_G[k]) {
case 0: // retarget
Sprite_CheckDamageToAndFromLink(k);
if (!(sprite_delay_main[k] | sprite_z[k])) {
Sprite_ApplySpeedTowardsLink(k, 32);
sprite_z_vel[k] = 32;
sprite_G[k]++;
sprite_B[k] = link_x_coord;
sprite_C[k] = link_x_coord >> 8;
sprite_E[k] = link_y_coord;
sprite_head_dir[k] = link_y_coord >> 8;
SpriteSfx_QueueSfx2WithPan(k, 0x20);
}
break;
case 1: // approach target
sprite_z_vel[k] += 3;
if (Sprite_CheckTileCollision(k))
goto advance;
Sprite_Get16BitCoords(k);
uint16 x, y;
x = sprite_B[k] | sprite_C[k] << 8;
y = sprite_E[k] | sprite_head_dir[k] << 8;
if ((uint16)(x - cur_sprite_x + 16) < 32 && (uint16)(y - cur_sprite_y + 16) < 32) {
advance:
sprite_G[k]++;
sprite_delay_main[k] = 16;
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
}
break;
case 2: // hover
sprite_z_vel[k] = 0;
if (!sprite_delay_main[k])
sprite_G[k]++;
break;
case 3: // crush
sprite_z_vel[k] = -104;
if (!sign8(sprite_z[k])) {
sprite_delay_main[k] = 32;
sprite_delay_aux4[k] = 32;
sprite_G[k] = 0;
SpriteSfx_QueueSfx2WithPan(k, 0xc);
}
break;
}
}
void Sprite_EvilBarrier(int k) { // 9df06b
EvilBarrier_Draw(k);
if (sprite_graphics[k] == 4)
return;
sprite_graphics[k] = frame_counter >> 1 & 3;
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckDamageFromLink(k) && link_sword_type < 2) {
sprite_hit_timer[k] = 0;
Sprite_AttemptDamageToLinkPlusRecoil(k);
if (!countdown_for_blink)
link_electrocute_on_touch = 64;
}
if ((uint16)(link_y_coord - cur_sprite_y + 8) < 24 &&
(uint16)(link_x_coord - cur_sprite_x + 32) < 64 &&
sign8(link_actual_vel_y - 1)) {
link_electrocute_on_touch = 64;
link_incapacitated_timer = 12;
link_auxiliary_state = 1;
link_give_damage = 2;
link_actual_vel_x = 0;
link_actual_vel_y = 48;
}
}
void EvilBarrier_Draw(int k) { // 9df249
static const DrawMultipleData kEvilBarrier_Dmd[45] = {
{ 0, 0, 0x00e8, 2},
{-29, 3, 0x00ca, 0},
{-29, 11, 0x00da, 0},
{ 37, 3, 0x40ca, 0},
{ 37, 11, 0x40da, 0},
{-24, -2, 0x00e6, 2},
{ -8, -2, 0x00e6, 2},
{ 8, -2, 0x40e6, 2},
{ 24, -2, 0x40e6, 2},
{ 0, 0, 0x00cc, 2},
{-29, 3, 0x00cb, 0},
{-29, 11, 0x00db, 0},
{ 37, 3, 0x40cb, 0},
{ 37, 11, 0x40db, 0},
{ 0, 0, 0x00cc, 2},
{ 0, 0, 0x00cc, 2},
{ 0, 0, 0x00cc, 2},
{ 0, 0, 0x00cc, 2},
{ 0, 0, 0x00cc, 2},
{-29, 3, 0x00cb, 0},
{-29, 11, 0x00db, 0},
{ 37, 3, 0x40cb, 0},
{ 37, 11, 0x40db, 0},
{-24, -2, 0x80e6, 2},
{ -8, -2, 0x80e6, 2},
{ 8, -2, 0xc0e6, 2},
{ 24, -2, 0xc0e6, 2},
{ 0, 0, 0x00e8, 2},
{-29, 3, 0x00ca, 0},
{-29, 11, 0x00da, 0},
{ 37, 3, 0x40ca, 0},
{ 37, 11, 0x40da, 0},
{ 0, 0, 0x00e8, 2},
{ 0, 0, 0x00e8, 2},
{ 0, 0, 0x00e8, 2},
{ 0, 0, 0x00e8, 2},
{-29, 3, 0x00cb, 0},
{-29, 11, 0x00db, 0},
{ 37, 3, 0x40cb, 0},
{ 37, 11, 0x40db, 0},
{ 37, 11, 0x40db, 0},
{ 37, 11, 0x40db, 0},
{ 37, 11, 0x40db, 0},
{ 37, 11, 0x40db, 0},
{ 37, 11, 0x40db, 0},
};
cur_sprite_y += 8;
Sprite_DrawMultiple(k, &kEvilBarrier_Dmd[sprite_graphics[k] * 9], 9, NULL);
Sprite_Get16BitCoords(k);
}
void SpriteDraw_Antfairy(int k) { // 9df395
static const DrawMultipleData kDrawFourAroundOne_Dmd[30] = {
{ 4, 2, 0x02e1, 0},
{ 4, -3, 0x02e3, 0},
{-1, 2, 0x02e3, 0},
{ 9, 2, 0x02e3, 0},
{ 4, 7, 0x02e3, 0},
{ 4, 2, 0x02e1, 0},
{ 3, -3, 0x02e3, 0},
{ 9, 1, 0x02e3, 0},
{-1, 3, 0x02e3, 0},
{ 5, 7, 0x02e3, 0},
{ 4, 2, 0x02e1, 0},
{ 1, -3, 0x02e3, 0},
{ 9, -1, 0x02e3, 0},
{-1, 5, 0x02e3, 0},
{ 7, 7, 0x02e3, 0},
{ 4, 2, 0x02e1, 0},
{ 0, -2, 0x02e3, 0},
{ 8, -2, 0x02e3, 0},
{ 0, 6, 0x02e3, 0},
{ 8, 6, 0x02e3, 0},
{ 4, 2, 0x02e1, 0},
{ 7, -3, 0x02e3, 0},
{-1, -1, 0x02e3, 0},
{ 9, 5, 0x02e3, 0},
{ 1, 7, 0x02e3, 0},
{ 4, 2, 0x02e1, 0},
{ 5, -3, 0x02e3, 0},
{-1, 1, 0x02e3, 0},
{ 9, 3, 0x02e3, 0},
{ 3, 7, 0x02e3, 0},
};
if (!(++sprite_subtype2[k] & 1 | submodule_index | flag_unk1)) {
if (++sprite_graphics[k] == 6)
sprite_graphics[k] = 0;
}
Sprite_DrawMultiple(k, &kDrawFourAroundOne_Dmd[sprite_graphics[k] * 5], 5, NULL);
}
void Toppo_Flustered(int k) { // 9df3d4
sprite_flags2[k] = 130;
sprite_ignore_projectile[k] = 130;
sprite_flags3[k] = 73;
if (!sprite_subtype[k]) {
if (Sprite_CheckDamageToLink(k)) {
dialogue_message_index = 0x174;
Sprite_ShowMessageMinimal();
sprite_subtype[k] = 1;
}
} else if (sprite_subtype[k] < 16) {
sprite_subtype[k]++;
} else if (sprite_subtype[k] == 16) {
sprite_flags5[k] = 0;
sprite_state[k] = 6;
sprite_delay_main[k] = 15;
sprite_flags2[k] += 4;
SpriteSfx_QueueSfx2WithPan(k, 0x15);
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x4d, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
ForcePrizeDrop(j, 6, 6);
}
sprite_subtype[k]++;
}
sprite_graphics[k] = ((++sprite_subtype2[k] & 4) >> 2) + 3;
}
void Goriya_Draw(int k) { // 9df589
static const DrawMultipleData kGoriya_Dmd2[3] = {
{10, 4, 0x4077, 0},
{-2, 4, 0x0077, 0},
{ 4, 4, 0x0076, 0},
};
static const DrawMultipleData kGoriya_Dmd[32] = {
{-4, -8, 0x0044, 2},
{12, -8, 0x4044, 0},
{-4, 8, 0x0064, 0},
{ 4, 0, 0x4054, 2},
{-4, -8, 0x0044, 2},
{12, -8, 0x4044, 0},
{-4, 8, 0x4074, 0},
{ 4, 0, 0x4062, 2},
{-4, -8, 0x0044, 0},
{ 4, -8, 0x4044, 2},
{-4, 0, 0x0062, 2},
{12, 8, 0x4064, 0},
{-4, -8, 0x0046, 2},
{12, -8, 0x4046, 0},
{-4, 8, 0x0066, 0},
{ 4, 0, 0x4056, 2},
{-4, -8, 0x0046, 2},
{12, -8, 0x4046, 0},
{-4, 8, 0x4075, 0},
{ 4, 0, 0x406a, 2},
{-4, -8, 0x0046, 0},
{ 4, -8, 0x4046, 2},
{-4, 0, 0x006a, 2},
{12, 8, 0x0075, 0},
{-2, -8, 0x004e, 2},
{ 0, 0, 0x006c, 2},
{-2, -7, 0x004e, 2},
{ 0, 0, 0x006e, 2},
{ 2, -8, 0x404e, 2},
{ 0, 0, 0x406c, 2},
{ 2, -7, 0x404e, 2},
{ 0, 0, 0x406e, 2},
};
static const uint8 kGoriyaDmdOffs[] = { 0, 4, 8, 12, 16, 20, 24, 26, 28, 30, 32 };
if (sprite_delay_aux1[k] && sprite_D[k] != 3)
Sprite_DrawMultiple(k, &kGoriya_Dmd2[sprite_D[k]], 1, NULL);
PrepOamCoordsRet info;
oam_cur_ptr += 4, oam_ext_cur_ptr++;
int g = sprite_graphics[k];
Sprite_DrawMultiple(k, &kGoriya_Dmd[kGoriyaDmdOffs[g]], kGoriyaDmdOffs[g + 1] - kGoriyaDmdOffs[g], &info);
sprite_flags2[k]--;
SpriteDraw_Shadow(k, &info);
sprite_flags2[k]++;
}
void Moldorm_Draw(int k) { // 9df822
static const int8 kMoldorm_Draw_X[16] = {11, 10, 9, 6, 3, 0, -2, -3, -4, -3, -2, 1, 4, 7, 9, 10};
static const int8 kMoldorm_Draw_Y[16] = {4, 6, 9, 10, 11, 10, 9, 6, 3, 0, -2, -3, -4, -3, -2, 1};
static const uint8 kMoldorm_Draw_Char[3] = {0x5d, 0x62, 0x60};
static const int8 kMoldorm_Draw_XY[3] = {4, 0, 0};
static const uint8 kMoldorm_Draw_Ext[3] = {0, 2, 2};
static const uint8 kMoldorm_Draw_GetOffs[3] = {21, 26, 0};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
uint8 base = sprite_D[k] - 1;
for (int i = 1; i >= 0; i--, oam++, base += 2) {
uint16 x = info.x + kMoldorm_Draw_X[base & 0xf];
int y = info.y + (uint16)kMoldorm_Draw_Y[base & 0xf];
oam->x = x;
oam->y = (uint16)(y + 0x10 + ((y >> 16) & 1)) < 0x100 ? y : 0xf0;
oam->charnum = 0x4D;
oam->flags = info.flags;
bytewise_extended_oam[oam - oam_buf] = (x >> 8 & 1);
}
oam_cur_ptr += 8;
oam_ext_cur_ptr += 2;
int j = (sprite_subtype2[k] & 0x1f) + k * 32;
moldorm_x_lo[j] = sprite_x_lo[k];
moldorm_x_hi[j] = sprite_x_hi[k];
moldorm_y_lo[j] = sprite_y_lo[k];
moldorm_y_hi[j] = sprite_y_hi[k];
for (int i = 2; i >= 0; i--, oam++) {
j = ((sprite_subtype2[k] + kMoldorm_Draw_GetOffs[i]) & 0x1f) + k * 32;
uint16 x = (moldorm_x_lo[j] | moldorm_x_hi[j] << 8) - BG2HOFS_copy2 + kMoldorm_Draw_XY[i];
uint16 y = (moldorm_y_lo[j] | moldorm_y_hi[j] << 8) - BG2VOFS_copy2 + kMoldorm_Draw_XY[i];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kMoldorm_Draw_Char[i];
oam->flags = info.flags;
bytewise_extended_oam[oam - oam_buf] = kMoldorm_Draw_Ext[i] | (x >> 8 & 1);
}
}
void TalkingTree_Mouth(int k) { // 9df956
static const int8 kTalkingTree_Gfx2[4] = {0, 2, 3, 1};
int j;
TalkingTree_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_flags4[k] = 0;
switch(sprite_ai_state[k]) {
case 0:
sprite_graphics[k] = 0;
if (Sprite_CheckDamageToLink_same_layer(k)) {
Link_CancelDash();
link_incapacitated_timer = 16;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 48);
link_actual_vel_y = pt.y;
link_actual_vel_x = pt.x;
SpriteSfx_QueueSfx3WithPan(k, 0x32);
sprite_ai_state[k]++;
sprite_delay_main[k] = 48;
}
break;
case 1:
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 8;
}
sprite_graphics[k] = sprite_delay_main[k] >> 1 & 3;
break;
case 2:
sprite_graphics[k] = kTalkingTree_Gfx2[sprite_delay_main[k] >> 1]; // zelda bug wtf
if (sprite_delay_main[k] == 7)
TalkingTree_SpawnBomb(k);
if (!sprite_delay_main[k])
sprite_ai_state[k]++;
break;
case 3:
sprite_flags4[k] = 7;
if (!sprite_A[k]) {
static const uint8 kTalkingTree_Msgs2[2] = { 0x82, 0x7d };
j = sprite_x_lo[k] >> 4 & 1 ^ 1;
sprite_A[k] = j;
if (!(Sprite_ShowSolicitedMessage(k, kTalkingTree_Msgs2[j]) & 0x100))
sprite_A[k] = 0;
} else {
static const uint8 kTalkingTree_Msgs[4] = {0x7e, 0x7f, 0x80, 0x81};
static const uint8 kTalkingTree_Screens[4] = {0x58, 0x5d, 0x72, 0x6b};
j = FindInByteArray(kTalkingTree_Screens, BYTE(overworld_screen_index), 4);
Sprite_ShowMessageUnconditional(kTalkingTree_Msgs[j]);
sprite_A[k] = 0;
}
if (!sprite_delay_main[k]) {
static const uint8 kTalkingTree_Gfx[8] = { 1, 2, 3, 1, 3, 1, 2, 3 };
static const uint8 kTalkingTree_Delay[8] = { 13, 13, 13, 11, 11, 6, 16, 8 };
sprite_B[k] = j = sprite_B[k] + 1 & 7;
sprite_graphics[k] = kTalkingTree_Gfx[j];
sprite_delay_main[k] = kTalkingTree_Delay[j];
}
break;
}
}
void TalkingTree_SpawnBomb(int k) { // 9dfa4e
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x4a, &info);
if (j >= 0) {
Sprite_TransmuteToBomb(j);
Sprite_SetSpawnedCoordinates(j, &info);
sprite_delay_aux1[j] = 64;
sprite_y_vel[j] = 24;
sprite_z_vel[j] = 18;
}
}
void TalkingTree_Draw(int k) { // 9dfadb
static const DrawMultipleData kTalkingTree_Dmd[12] = {
{1, -1, 0x00e8, 0},
{1, 7, 0x00f8, 0},
{7, -1, 0x40e8, 0},
{7, 7, 0x40f8, 0},
{0, -1, 0x00e8, 0},
{0, 7, 0x00f8, 0},
{8, -1, 0x40e8, 0},
{8, 7, 0x40f8, 0},
{0, 0, 0x00e8, 0},
{0, 7, 0x00f8, 0},
{8, 0, 0x40e8, 0},
{8, 7, 0x40f8, 0},
};
int g = sprite_graphics[k] - 1;
if (g < 0)
return;
Sprite_DrawMultiplePlayerDeferred(k, &kTalkingTree_Dmd[g * 4], 4, NULL);
}
void TalkingTree_Eye(int k) { // 9dfb0a
static const int8 kTalkingTree_Type1_X[2] = {9, -9};
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
int j = sprite_head_dir[k];
Sprite_SetX(k, (sprite_A[k] | sprite_B[k] << 8) + kTalkingTree_Type1_X[j]);
Sprite_SetY(k, (sprite_C[k] | sprite_E[k] << 8));
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 2);
if (!sign8(pt.y)) {
sprite_D[k] = pt.x + 2;
} else if (sprite_D[k] != 2) {
sprite_D[k] += (sprite_D[k] >= 2) ? -1 : 1;
}
static const int8 kTalkingTree_X1[5] = {-2, -1, 0, 1, 2};
static const int8 kTalkingTree_Y1[5] = {-1, 0, 0, 0, -1};
j = sprite_D[k];
Sprite_SetX(k, (sprite_A[k] | sprite_B[k] << 8) + kTalkingTree_X1[j]);
Sprite_SetY(k, (sprite_C[k] | sprite_E[k] << 8) + kTalkingTree_Y1[j]);
}
void SpritePrep_TalkingTree_SpawnEyeball(int k, int dir) { // 9dfb8a
static const int8 kTalkingTree_SpawnX[2] = {-4, 14};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x25, &info);
if (j >= 0) {
sprite_head_dir[j] = dir;
int x = info.r0_x + kTalkingTree_SpawnX[dir];
int y = info.r2_y - 11;
Sprite_SetX(j, x);
Sprite_SetY(j, y);
sprite_A[j] = x;
sprite_B[j] = x >> 8;
sprite_C[j] = y;
sprite_E[j] = y >> 8;
sprite_subtype2[j] = 1;
}
}
void RupeePull_SpawnPrize(int k) { // 9dfbd7
static const int8 kSpawnRupees_Xvel[4] = {-18, -12, 12, 18};
static const int8 kSpawnRupees_Yvel[4] = {16, 24, 24, 16};
static const uint8 kSpawnRupees_Type[3] = {0xd9, 0xda, 0xdb};
if (num_sprites_killed) {
byte_7E0FB6 = num_sprites_killed < 4 ? 0 :
number_of_times_hurt_by_sprites ? 1 : 2;
tmp_counter = 3;
do {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, kSpawnRupees_Type[byte_7E0FB6], &info);
if (j < 0)
break;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_x_vel[j] = kSpawnRupees_Xvel[tmp_counter];
sprite_y_vel[j] = kSpawnRupees_Yvel[tmp_counter];
sprite_stunned[j] = 255;
sprite_delay_aux4[j] = 32;
sprite_delay_aux3[j] = 32;
sprite_z_vel[j] = 32;
} while (!sign8(--tmp_counter));
}
num_sprites_killed = 0;
number_of_times_hurt_by_sprites = 0;
}
void Sprite_D5_DigGameGuy(int k) { // 9dfc38
DiggingGameGuy_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
Sprite_MoveXY(k);
sprite_x_vel[k] = 0;
switch(sprite_ai_state[k]) {
case 0: // intro
if ((uint8)(sprite_y_lo[k] + 7) < BYTE(link_y_coord) && Sprite_DirectionToFaceLink(k, NULL) == 2) {
if (follower_indicator == 0) {
if (Sprite_ShowSolicitedMessage(k, 0x187) & 0x100)
sprite_ai_state[k]++;
} else {
Sprite_ShowSolicitedMessage(k, 0x18c);
}
}
break;
case 1: // do you want to play
if (choice_in_multiselect_box == 0 && link_rupees_goal >= 80) {
link_rupees_goal -= 80;
Sprite_ShowMessageUnconditional(0x188);
sprite_ai_state[k] = 2;
sprite_graphics[k] = 1;
sprite_delay_main[k] = 80;
beamos_x_hi[0] = 0;
beamos_x_hi[1] = 0;
sprite_delay_aux1[k] = 5;
Sprite_InitializeSecondaryItemMinigame(1);
music_control = 14;
} else {
Sprite_ShowMessageUnconditional(0x189);
sprite_ai_state[k] = 0;
}
break;
case 2: // move out of the way
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_graphics[k] = 1;
} else if (!sprite_delay_aux1[k]) {
sprite_graphics[k] ^= 3;
if (sprite_graphics[k] & 1)
sprite_x_vel[k] = -16;
sprite_delay_aux1[k] = 5;
}
break;
case 3: // start timer
sprite_ai_state[k]++;
super_bomb_indicator_unk1 = 0;
super_bomb_indicator_unk2 = 30;
break;
case 4: // terminate
if ((int8)super_bomb_indicator_unk2 > 0 || link_position_mode & 1)
return;
music_control = 9;
sprite_ai_state[k]++;
is_archer_or_shovel_game = 0;
dialogue_message_index = 0x18a;
Sprite_ShowMessageMinimal();
super_bomb_indicator_unk2 = 254;
break;
case 5: // come back later
Sprite_ShowSolicitedMessage(k, 0x18b);
break;
}
}
void DiggingGameGuy_Draw(int k) { // 9dfe4b
static const DrawMultipleData kDiggingGameGuy_Dmd[9] = {
{ 0, -8, 0x0a40, 2},
{ 4, 9, 0x0c56, 0},
{ 0, 0, 0x0a42, 2},
{ 0, -8, 0x0a40, 2},
{ 0, 0, 0x0a42, 2},
{ 0, 0, 0x0a42, 2},
{-1, -7, 0x0a40, 2},
{-1, 0, 0x0a44, 2},
{-1, 0, 0x0a44, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kDiggingGameGuy_Dmd[sprite_graphics[k] * 3], 3, &info);
SpriteDraw_Shadow(k, &info);
}
void OldMountainMan_Draw(int k) { // 9dff0e
static const DrawMultipleData kOldMountainMan_Dmd0[2] = {
{0, 0, 0x00ac, 2},
{0, 8, 0x00ae, 2},
};
static const DrawMultipleData kOldMountainMan_Dmd1[16] = {
{ 0, 0, 0x0120, 2},
{ 0, 8, 0x0122, 2},
{ 0, 1, 0x0120, 2},
{ 0, 9, 0x4122, 2},
{ 0, 0, 0x0120, 2},
{ 0, 8, 0x0122, 2},
{ 0, 1, 0x0120, 2},
{ 0, 9, 0x4122, 2},
{-2, 0, 0x0120, 2},
{ 0, 8, 0x0122, 2},
{-2, 1, 0x0120, 2},
{ 0, 9, 0x0122, 2},
{ 2, 0, 0x4120, 2},
{ 0, 8, 0x4122, 2},
{ 2, 1, 0x4120, 2},
{ 0, 9, 0x4122, 2},
};
static const uint8 kOldMountainMan_Dma[16] = {0x20, 0xc0, 0x20, 0xc0, 0, 0xa0, 0, 0xa0, 0x40, 0x80, 0x40, 0x60, 0x40, 0x80, 0x40, 0x60};
if (sprite_subtype2[k] != 2) {
int j = sprite_D[k] * 4 + sprite_graphics[k] * 2;
BYTE(dma_var6) = kOldMountainMan_Dma[j + 0];
BYTE(dma_var7) = kOldMountainMan_Dma[j + 1];
Sprite_DrawMultiplePlayerDeferred(k, &kOldMountainMan_Dmd1[j], 2, NULL);
} else {
Sprite_DrawMultiplePlayerDeferred(k, kOldMountainMan_Dmd0, 2, NULL);
}
}
void HelmasaurKing_Initialize(int k) { // 9e8000
overlord_gen1[7] = 0x30;
overlord_gen1[5] = 0x80;
overlord_gen1[6] = 0;
overlord_gen2[0] = 0;
overlord_gen2[3] = 0;
overlord_gen2[1] = 0;
overlord_gen2[2] = 0;
HelmasaurKing_Reinitialize(k);
}
void HelmasaurKing_Reinitialize(int k) { // 9e8019
uint8 t = sprite_subtype2[k];
for (int i = 3; i >= 0; i--) {
overlord_x_lo[i] = kHelmasaur_Tab0[t + i * 8 & 0x1f];
}
}
void Sprite_92_HelmasaurKing(int k) { // 9e8039
int t, j;
if (sign8(sprite_C[k])) {
if (sprite_delay_main[k] == 1)
sprite_state[k] = 0;
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!(frame_counter & 7 | sprite_delay_aux1[k]))
sprite_oam_flags[k] ^= 0x40;
Sprite_MoveXYZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_delay_main[k] = 12;
sprite_z_vel[k] = 24;
sprite_graphics[k] = 6;
}
return;
}
if (sprite_C[k] < 3) {
sprite_obj_prio[k] &= ~0xE;
sprite_flags[k] = 0xA;
} else {
sprite_flags4[k] = 0x1F;
sprite_flags[k] = 2;
}
HelmasaurKing_Draw(k);
if (sprite_state[k] == 6) {
t = sprite_delay_main[k];
if (!t) {
sprite_state[k] = 4;
sprite_A[k] = 0;
sprite_delay_main[k] = 224;
return;
}
sprite_hit_timer[k] = t | 240;
if (t < 128 && (t & 7) == 0 && (j = overlord_gen2[3]) != 0x10) {
overlord_gen2[3]++;
cur_sprite_x = Sprite_GetX(k) + (int8)overlord_x_lo[5 + j];
cur_sprite_y = Sprite_GetY(k) + (int8)overlord_y_lo[5 + j];
Sprite_MakeBossExplosion(k);
}
return;
}
if (Sprite_ReturnIfInactive(k))
return;
static const uint8 kHelmasaurKing_Tab1[13] = {3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 0};
t = kHelmasaurKing_Tab1[sprite_health[k] >> 2];
sprite_C[k] = t;
if (t == 3) {
if (t != sprite_E[k]) {
sprite_hit_timer[k] = 0;
HelmasaurKing_ExplodeMask(k);
}
} else {
if (t != sprite_E[k])
HelmasaurKing_ChipAwayAtMask(k);
}
sprite_E[k] = sprite_C[k];
Sprite_CheckDamageFromLink(k);
HelmasaurKing_SwingTail(k);
HelmasaurKing_AttemptDamage(k);
HelmasaurKing_CheckMaskDamageFromHammer(k);
if (sprite_delay_aux1[k] == 0) {
if (sprite_delay_aux2[k] != 0) {
if (sprite_delay_aux2[k] == 0x40) {
HelmasaurKing_SpitFireball(k);
if (sprite_C[k] >= 3) {
anim_clk:
if (!sprite_anim_clock[k]) {
sprite_anim_clock[k]++;
sprite_delay_aux3[k] = 32;
}
}
}
return;
}
} else {
if (sprite_delay_aux1[k] == 96)
goto anim_clk;
return;
}
static const int8 kHelmasaurKing_Xvel0[8] = {-12, -12, -4, 0, 4, 12, 12, 0};
static const int8 kHelmasaurKing_Yvel0[8] = {0, 4, 12, 12, 12, 4, 0, 12};
switch (sprite_ai_state[k]) {
case 0:
if ((sprite_hit_timer[k] || !sprite_delay_main[k]) && !HelmasaurKing_MaybeFireball(k)) {
j = GetRandomNumber() & 7;
sprite_x_vel[k] = kHelmasaurKing_Xvel0[j];
sprite_y_vel[k] = kHelmasaurKing_Yvel0[j];
sprite_delay_main[k] = 64;
if (sprite_C[k] >= 3) {
sprite_x_vel[k] <<= 1;
sprite_y_vel[k] <<= 1;
sprite_delay_main[k] >>= 1;
}
sprite_ai_state[k]++;
}
break;
case 1:
HelmasaurKing_HandleMovement(k);
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 32;
sprite_ai_state[k]++;
}
break;
case 2:
if ((sprite_hit_timer[k] || !sprite_delay_main[k]) && !HelmasaurKing_MaybeFireball(k)) {
sprite_delay_main[k] = 64;
if (sprite_E[k] >= 3)
sprite_delay_main[k] >>= 1;
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_y_vel[k] = -sprite_y_vel[k];
sprite_ai_state[k]++;
}
break;
case 3:
HelmasaurKing_HandleMovement(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 64;
}
break;
}
}
void HelmasaurKing_HandleMovement(int k) { // 9e81e6
int n = 1 + ((frame_counter & 3) == 0) + (sprite_C[k] >= 3);
do {
if (!(++sprite_subtype2[k] & 15))
sound_effect_1 = 0x21;
} while (--n);
Sprite_MoveXY(k);
}
bool HelmasaurKing_MaybeFireball(int k) { // 9e8253
if (++sprite_subtype[k] != 4)
return false;
sprite_subtype[k] = 0;
if (GetRandomNumber() & 1) {
sprite_delay_aux2[k] = 127;
SpriteSfx_QueueSfx3WithPan(k, 0x2a);
} else {
sprite_delay_aux1[k] = 160;
}
return true;
}
void HelmasaurKing_SwingTail(int k) { // 9e82a0
overlord_x_lo[4]++;
HelmasaurKing_Reinitialize(k);
uint8 mask = sprite_anim_clock[k] ? 0 : 1;
if (!(frame_counter & mask)) {
int j = sprite_D[k] & 1;
overlord_gen2[0] += j ? -1 : 1;
if (overlord_gen2[0] == (uint8)kFluteBoyAnimal_Xvel[j])
sprite_D[k]++;
WORD(overlord_gen1[5]) += (int8)overlord_gen2[0];
}
if (!sprite_anim_clock[k])
return;
if (!overlord_gen2[0])
SpriteSfx_QueueSfx3WithPan(k, 0x6);
if (sprite_anim_clock[k] == 2) {
int j = sprite_head_dir[k];
WORD(overlord_gen2[1]) += j ? -4 : 4;
if (overlord_gen2[1] == (uint8)(j ? -124 : 124))
sprite_anim_clock[k] = 3;
overlord_gen1[7] += 3;
} else if (sprite_anim_clock[k] == 3) {
int j = sprite_head_dir[k] ^ 1;
WORD(overlord_gen2[1]) += j ? -4 : 4;
if (overlord_gen2[1] == 0)
sprite_anim_clock[k] = 0;
overlord_gen1[7] -= 3;
} else {
if (!(overlord_gen2[0] | sprite_delay_aux3[k])) {
sprite_head_dir[k] = overlord_gen1[6] & 1;
uint8 dir = Sprite_IsRightOfLink(k).a ^ 1;
if (dir == sprite_head_dir[k]) {
sprite_anim_clock[k] = 2;
sound_effect_2 = Sprite_CalculateSfxPan(k) | 0x26;
}
}
}
}
void HelmasaurKing_CheckMaskDamageFromHammer(int k) { // 9e8385
if (sprite_C[k] >= 3 || !(link_item_in_hand & 10) || (player_oam_y_offset == 0x80))
return;
SpriteHitBox hb;
Player_SetupActionHitBox(&hb);
uint8 bak = sprite_y_lo[k];
sprite_y_lo[k] += 8;
Sprite_SetupHitBox(k, &hb);
sprite_y_lo[k] = bak;
if (CheckIfHitBoxesOverlap(&hb)) {
sprite_health[k]--;
sound_effect_2 = 0x21;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 0x30);
link_actual_vel_y = pt.y;
link_actual_vel_x = pt.x;
link_incapacitated_timer = 8;
if (!repulsespark_timer) {
repulsespark_x_lo = pt.y;
repulsespark_y_lo = pt.x;
repulsespark_timer = 5;
}
SpriteSfx_QueueSfx2WithPan(k, 0x5);
}
}
void HelmasaurKing_AttemptDamage(int k) { // 9e83eb
if (!(frame_counter & 7) &&
(uint16)(link_x_coord - cur_sprite_x + 36) < 72 &&
(uint16)(link_y_coord - cur_sprite_y + 40) < 64)
Sprite_AttemptDamageToLinkPlusRecoil(k);
}
void HelmasaurKing_ChipAwayAtMask(int k) { // 9e847e
tmp_counter = sprite_C[k] + 7;
HelmasaurKing_SpawnMaskDebris(k);
SpriteSfx_QueueSfx2WithPan(k, 0x1f);
}
void HelmasaurKing_ExplodeMask(int k) { // 9e848c
for (int j = 1; j < 16; j++)
sprite_state[j] = 0;
tmp_counter = 7;
do {
HelmasaurKing_SpawnMaskDebris(k);
} while (!sign8(--tmp_counter));
SpriteSfx_QueueSfx2WithPan(k, 0x1f);
}
void HelmasaurKing_SpawnMaskDebris(int k) { // 9e84aa
static const int8 kHelmasaurKing_Mask_X[10] = {-16, 0, 16, -16, 0, 16, -8, 8, -16, 16};
static const int8 kHelmasaurKing_Mask_Y[10] = {24, 27, 24, 24, 27, 24, 27, 27, 24, 24};
static const int8 kHelmasaurKing_Mask_Z[10] = {29, 32, 29, 13, 16, 13, 0, 0, 13, 13};
static const int8 kHelmasaurKing_Mask_Xvel[10] = {-16, -4, 14, -12, 4, 18, -2, 2, -12, 18};
static const int8 kHelmasaurKing_Mask_Yvel[10] = {-8, -4, -6, 4, 2, 7, 6, 8, 4, 7};
static const int8 kHelmasaurKing_Mask_Zvel[10] = {32, 40, 36, 37, 39, 34, 30, 33, 37, 34};
static const uint8 kHelmasaurKing_Mask_OamFlags[10] = {0, 0, 0x40, 0, 0, 0x40, 0, 0x40, 0, 0x40};
static const uint8 kHelmasaurKing_Mask_Gfx[10] = {0, 1, 0, 2, 3, 2, 4, 4, 5, 5};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x92, &info);
if (j >= 0) {
int i = tmp_counter;
Sprite_SetX(j, info.r0_x + kHelmasaurKing_Mask_X[i]);
Sprite_SetY(j, info.r2_y + kHelmasaurKing_Mask_Y[i]);
sprite_z[j] = kHelmasaurKing_Mask_Z[i];
sprite_x_vel[j] = kHelmasaurKing_Mask_Xvel[i];
sprite_y_vel[j] = kHelmasaurKing_Mask_Yvel[i];
sprite_z_vel[j] = kHelmasaurKing_Mask_Zvel[i];
sprite_oam_flags[j] = kHelmasaurKing_Mask_OamFlags[i] | 13;
sprite_graphics[j] = kHelmasaurKing_Mask_Gfx[i];
sprite_C[j] = 128;
sprite_flags2[j] = 0;
sprite_delay_aux1[j] = 12;
sprite_ignore_projectile[j] = 12;
sprite_subtype[j] = tmp_counter;
}
}
void HelmasaurKing_SpitFireball(int k) { // 9e8517
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x70, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
Sprite_SetY(j, info.r2_y + 28);
sprite_delay_main[j] = 32;
sprite_ignore_projectile[j] = 32;
}
}
void HelmasaurKing_Draw(int k) { // 9e853b
oam_cur_ptr = 0x89c;
oam_ext_cur_ptr = 0xa47;
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
KingHelmasaur_OperateTail(k, &info);
SpriteDraw_KingHelmasaur_Eyes(k, &info);
KingHelmasaurMask(k, &info);
SpriteDraw_KingHelmasaur_Body(k, &info);
SpriteDraw_KingHelmasaur_Legs(k, &info);
SpriteDraw_KingHelmasaur_Mouth(k, &info);
}
void SpriteDraw_KingHelmasaur_Eyes(int k, PrepOamCoordsRet *info) { // 9e856b
static const int8 kHelmasaurKing_DrawB_X[2] = {-3, 11};
static const uint8 kHelmasaurKing_DrawB_Char[8] = {0xce, 0xcf, 0xde, 0xde, 0xde, 0xde, 0xcf, 0xce};
static const uint8 kHelmasaurKing_DrawB_Flags[2] = {0x3b, 0x7b};
oam_cur_ptr += 0x40, oam_ext_cur_ptr += 0x10;
OamEnt *oam = GetOamCurPtr();
for (int i = 1; i >= 0; i--, oam++) {
oam->x = info->x + kHelmasaurKing_DrawB_X[i];
oam->y = info->y + 0x14;
int j = overlord_x_lo[4] >> 2 & 7;
oam->charnum = kHelmasaurKing_DrawB_Char[j];
oam->flags = kHelmasaurKing_DrawB_Flags[i];
bytewise_extended_oam[oam - oam_buf] = 0;
}
if (submodule_index)
Sprite_CorrectOamEntries(k, 1, 0);
}
void KingHelmasaurMask(int k, PrepOamCoordsRet *info) { // 9e8686
static const DrawMultipleData kHelmasaurKing_DrawC_Dmd[24] = {
{-16, -5, 0x0dae, 2},
{ 0, -5, 0x0dc0, 2},
{ 16, -5, 0x4dae, 2},
{-16, 11, 0x0dc2, 2},
{ 0, 11, 0x0dc4, 2},
{ 16, 11, 0x4dc2, 2},
{ -8, 27, 0x0dc6, 2},
{ 8, 27, 0x4dc6, 2},
{-16, -5, 0x0dae, 2},
{ 0, -5, 0x0dc0, 2},
{ 16, -5, 0x4dae, 2},
{-16, 11, 0x0dc8, 2},
{ 0, 11, 0x0dc4, 2},
{ 16, 11, 0x4dc2, 2},
{ -8, 27, 0x0dc6, 2},
{ 8, 27, 0x4dc6, 2},
{-16, -5, 0x0dae, 2},
{ 0, -5, 0x0dc0, 2},
{ 16, -5, 0x4dae, 2},
{-16, 11, 0x0dc8, 2},
{ 0, 11, 0x0dc4, 2},
{ 16, 11, 0x4dc8, 2},
{ -8, 27, 0x0dc6, 2},
{ 8, 27, 0x4dc6, 2},
};
oam_cur_ptr += 8, oam_ext_cur_ptr += 2;
if (sprite_C[k] >= 3)
return;
Sprite_DrawMultiple(k, &kHelmasaurKing_DrawC_Dmd[sprite_C[k] * 8], 8, info);
oam_cur_ptr += 0x20, oam_ext_cur_ptr += 8;
if (sprite_delay_aux4[k])
return;
for (int i = 1; i >= 0; i--) {
if (ancilla_type[i] == 7 && (ancilla_x_vel[i] | ancilla_y_vel[i])) {
KingHelmasaur_CheckBombDamage(k, i);
}
}
}
void KingHelmasaur_CheckBombDamage(int k, int j) { // 9e86e5
SpriteHitBox hb;
Sprite_SetupHitBox(k, &hb);
int x = (ancilla_x_lo[j] | ancilla_x_hi[j] << 8) - 6;
int y = (ancilla_y_lo[j] | ancilla_y_hi[j] << 8) - ancilla_z[j];
hb.r0_xlo = x, hb.r8_xhi = x >> 8;
hb.r1_ylo = y, hb.r9_yhi = y >> 8;
hb.r2 = 2;
hb.r3 = 15;
if (CheckIfHitBoxesOverlap(&hb)) {
ancilla_x_vel[j] = -ancilla_x_vel[j];
ancilla_y_vel[j] = (int8)-ancilla_y_vel[j] >> 1;
sprite_delay_aux4[k] = 32;
repulsespark_timer = 5;
repulsespark_x_lo = ancilla_x_lo[j];
repulsespark_y_lo = ancilla_y_lo[j] - ancilla_z[j];
sound_effect_1 = 5;
}
}
void SpriteDraw_KingHelmasaur_Body(int k, PrepOamCoordsRet *info) { // 9e87e5
static const DrawMultipleData kHelmasaurKing_DrawD_Dmd[19] = {
{-24, -32, 0x0b80, 2},
{ -8, -32, 0x0b82, 2},
{ 8, -32, 0x4b82, 2},
{ 24, -32, 0x4b80, 2},
{-24, -16, 0x0b84, 2},
{ -8, -16, 0x0b86, 2},
{ 8, -16, 0x4b86, 2},
{ 24, -16, 0x4b84, 2},
{-24, 0, 0x0b88, 2},
{ -8, 0, 0x0b8a, 2},
{ 8, 0, 0x4b8a, 2},
{ 24, 0, 0x4b88, 2},
{-24, 16, 0x0b8c, 2},
{ -8, 16, 0x0b8e, 2},
{ 8, 16, 0x4b8e, 2},
{ 24, 16, 0x4b8c, 2},
{ -8, 32, 0x0ba0, 2},
{ 8, 32, 0x4ba0, 2},
{ 0, -40, 0x0bac, 2},
};
Sprite_DrawMultiple(k, kHelmasaurKing_DrawD_Dmd, 19, info);
}
void SpriteDraw_KingHelmasaur_Legs(int k, PrepOamCoordsRet *info) { // 9e8805
static const int8 kHelmasaurKing_DrawE_X[4] = {-28, -28, 28, 28};
static const int8 kHelmasaurKing_DrawE_Y[4] = {-28, 4, -28, 4};
static const uint8 kHelmasaurKing_DrawE_Char[4] = {0xa2, 0xa6, 0xa2, 0xa6};
static const uint8 kHelmasaurKing_DrawE_Flags[4] = {0xb, 0xb, 0x4b, 0x4b};
oam_cur_ptr += 19 * 4;
oam_ext_cur_ptr += 19;
OamEnt *oam = GetOamCurPtr();
for (int i = 3; i >= 0; i--, oam += 2) {
oam[1].x = oam[0].x = info->x + kHelmasaurKing_DrawE_X[i];
oam[0].y = info->y + kHelmasaurKing_DrawE_Y[i] + overlord_x_lo[i];
oam[1].y = oam[0].y + 0x10;
oam[0].charnum = kHelmasaurKing_DrawE_Char[i];
oam[1].charnum = oam[0].charnum + 2;
oam[1].flags = oam[0].flags = kHelmasaurKing_DrawE_Flags[i] ^ info->flags;
bytewise_extended_oam[oam - oam_buf] = 2;
bytewise_extended_oam[oam - oam_buf + 1] = 2;
}
tmp_counter = 0xff;
if (submodule_index) {
Sprite_CorrectOamEntries(k, 7, 2);
Sprite_PrepOamCoordOrDoubleRet(k, info);
}
}
void SpriteDraw_KingHelmasaur_Mouth(int k, PrepOamCoordsRet *info) { // 9e88bc
static const uint8 kHelmasaurKing_DrawF_Y[32] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
};
if (!sprite_delay_aux2[k])
return;
uint8 yd = kHelmasaurKing_DrawF_Y[sprite_delay_aux2[k] >> 2];
Oam_AllocateFromRegionB(4);
OamEnt *oam = GetOamCurPtr();
oam->x = info->x;
int t = (uint8)info->y + 0x13;
oam->y = t + (t >> 8) + yd;
oam->charnum = 0xaa;
oam->flags = info->flags ^ 0xb;
bytewise_extended_oam[oam - oam_buf] = 2;
}
void KingHelmasaur_OperateTail(int k, PrepOamCoordsRet *info) { // 9e8920
static const uint8 kHelmasaurKing_DrawA_Mult[32] = {
0xff, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10,
0xff, 0xf8, 0xf0, 0xe8, 0xe0, 0xd8, 0xd0, 0xc8, 0xbc, 0xb0, 0xa0, 0x90, 0x70, 0x40, 0x20, 0x10,
};
static const uint8 kHelmasaurKing_DrawA_MultB[16] = {
0xff, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10
};
for (int i = 0; i < 16; i++) {
int j = i + (sprite_anim_clock[k] ? 16 : 0);
uint16 rs = WORD(overlord_gen1[5]) + WORD(overlord_gen2[1]);
uint8 f = (rs >> 8) - 1;
uint8 r6 = (uint8)(sign8(f) ? -rs : rs) * kHelmasaurKing_DrawA_Mult[j] >> 8;
uint16 angle = (rs & 0xff00) | (sign8(f) ? r6 ^ 0xff : r6);
uint8 r15 = overlord_gen1[7] * kHelmasaurKing_DrawA_MultB[i] >> 8;
overlord_x_lo[i+5] = HelmasaurSin(angle, r15);
overlord_y_lo[i+5] = HelmasaurSin(angle + 0x80, r15) - 40;
}
OamEnt *oam = GetOamCurPtr();
bool is_hit = false;
for (int i = overlord_gen2[3]; i != 16; i++, oam++) {
uint8 x = overlord_x_lo[i + 5] + info->x;
uint8 y = overlord_y_lo[i + 5] + info->y;
oam->x = x;
oam->y = y;
oam->charnum = (i == overlord_gen2[3]) ? 0xe4 : 0xac;
oam->flags = info->flags ^ 0x1b;
if (!countdown_for_blink && sprite_anim_clock[k]) {
if ((uint8)(link_x_coord - BG2HOFS_copy2 - x + 12) < 24 &&
(uint8)(link_y_coord - BG2VOFS_copy2 + 8 - y + 8) < 16) {
is_hit = true;
link_actual_vel_x = 0;
link_actual_vel_y = 56;
}
}
}
if (is_hit && !flag_block_link_menu)
Sprite_AttemptDamageToLinkPlusRecoil(k);
Sprite_CorrectOamEntries(k, 16, 2);
Sprite_PrepOamCoordOrDoubleRet(k, info);
tmp_counter = 16;
}
void Sprite_MadBatterBolt(int k) { // 9e8a96
static const int8 kMadderBolt_X[8] = {0, 4, 8, 12, 12, 4, 8, 0};
static const int8 kMadderBolt_Y[8] = {0, 4, 8, 12, 12, 4, 8, 0};
if (sprite_subtype2[k] & 16)
Oam_AllocateFromRegionB(4);
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_ai_state[k]) {
Sprite_MoveXY(k);
if (!sprite_delay_main[k])
sprite_ai_state[k] = 1;
} else {
if (++sprite_ai_state[k] == 0)
sprite_state[k] = 0;
int j = ++sprite_subtype2[k];
if (!(j & 7))
sound_effect_2 = 48;
Sprite_SetX(k, link_x_coord + kMadderBolt_X[j >> 2 & 7]);
Sprite_SetY(k, link_y_coord + kMadderBolt_Y[j >> 4 & 7]);
}
}
void Sprite_AA_Pikit(int k) { // 9e8bbf
static const uint8 kPikit_Gfx[24] = {
2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 2, 2, 2, 2,
};
static const int8 kPikit_XyOffs[72] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12, 16, 24, 32, 32, 24, 16, 12, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -12, -16, -24, -32, -32, -24, -16, -12,
0, 0, 0, 0, 0, 0, 0, 0,
};
static const uint8 kPikit_Tab0[8] = {24, 24, 0, 48, 48, 48, 0, 24};
static const uint8 kPikit_Tab1[8] = {0, 24, 24, 24, 0, 48, 48, 48};
int j;
Pikit_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
switch(sprite_ai_state[k]) {
case 0: // set next vel
if (!sprite_delay_main[k]) {
int j;
sprite_ai_state[k]++;
if (++sprite_C[k] == 4) {
sprite_C[k] = 0;
j = Sprite_DirectionToFaceLink(k, NULL);
} else {
j = GetRandomNumber() & 3;
}
sprite_x_vel[k] = kFluteBoyAnimal_Xvel[j];
sprite_y_vel[k] = kZazak_Yvel[j];
sprite_z_vel[k] = (GetRandomNumber() & 7) + 19;
}
sprite_graphics[k] = ++sprite_subtype2[k] >> 3 & 1;
break;
case 1: // finish jump then attack
Sprite_MoveXYZ(k);
Sprite_CheckTileCollision(k);
sprite_z_vel[k]--;
sprite_z_vel[k]--;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
PointU8 pt;
Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.x + 48) < 96 && (uint8)(pt.y + 48) < 96) {
sprite_ai_state[k]++;
ProjectSpeedRet pp = Sprite_ProjectSpeedTowardsLink(k, 31);
sprite_D[k] = Sprite_ConvertVelocityToAngle(pp.x, pp.y) >> 1;
sprite_delay_main[k] = 95;
return;
}
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 16;
}
sprite_graphics[k] = ++sprite_subtype2[k] >> 3 & 1;
break;
case 2: { // attempt item grab
j = sprite_delay_main[k];
if (!j) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 16;
sprite_A[k] = 0;
sprite_B[k] = 0;
sprite_G[k] = 0;
return;
}
j >>= 2;
sprite_graphics[k] = kPikit_Gfx[j];
int8 xo = kPikit_XyOffs[j + kPikit_Tab0[sprite_D[k]]];
int8 yo = kPikit_XyOffs[j + kPikit_Tab1[sprite_D[k]]];
sprite_A[k] = xo;
sprite_B[k] = yo;
if (!sprite_G[k] &&
(uint16)(cur_sprite_x + xo - link_x_coord + 12) < 24 &&
(uint16)(cur_sprite_y + yo - link_y_coord + 12) < 32 &&
sprite_delay_main[k] < 46) {
sound_effect_1 = Link_CalculateSfxPan() | 0x26;
j = (GetRandomNumber() & 3) + 1;
sprite_E[k] = sprite_G[k] = j;
if (j == 1) {
if (link_item_bombs)
link_item_bombs--;
else
sprite_G[k] = 0;
} else if (j == 2) {
if (link_num_arrows)
link_num_arrows--;
else
sprite_G[k] = 0;
} else if (j == 3) {
if (link_rupees_goal)
link_rupees_goal--;
else
sprite_G[k] = 0;
} else {
sprite_subtype[k] = link_shield_type;
if (link_shield_type != 0 && link_shield_type != 3)
link_shield_type = 0;
else
sprite_G[k] = 0;
}
}
break;
}
}
}
void Sprite_A8_GreenZirro(int k) { // 9e8dd2
static const uint8 kBomber_Gfx[4] = {9, 10, 8, 7};
sprite_obj_prio[k] = 0x30;
if (sprite_A[k]) {
switch (sprite_ai_state[k]) {
case 0: // bomberpellet falling
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXY(k);
Sprite_MoveZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_ai_state[k]++;
sprite_delay_main[k] = 19;
sprite_flags2[k]++;
SpriteSfx_QueueSfx2WithPan(k, 0xc);
}
break;
case 1: // bomberpellet exploding
SpriteDraw_ZirroBomb(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!(frame_counter & 3))
sprite_delay_main[k]++;
Sprite_CheckDamageToLink(k);
break;
}
return;
}
if (sprite_delay_aux1[k])
sprite_graphics[k] = kBomber_Gfx[sprite_D[k]];
sprite_obj_prio[k] |= 0x30;
Bomber_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
if (sprite_delay_aux1[k] == 8)
Zirro_DropBomb(k);
Sprite_CheckDamageToAndFromLink(k);
if (!(frame_counter & 1)) {
int j = sprite_G[k] & 1;
sprite_z_vel[k] += j ? -1 : 1;
if (sprite_z_vel[k] == (uint8)(j ? -8 : 8))
sprite_G[k]++;
}
Sprite_MoveZ(k);
PointU8 pt;
Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.x + 40) < 80 && (uint8)(pt.y + 40) < 80 && player_oam_y_offset != 0x80 &&
(link_is_running || sign8(button_b_frames - 9))) {
ProjectSpeedRet pp = Sprite_ProjectSpeedTowardsLink(k, 0x30);
sprite_x_vel[k] = -pp.x;
sprite_y_vel[k] = -pp.y;
sprite_delay_main[k] = 8;
sprite_ai_state[k] = 2;
}
switch(sprite_ai_state[k]) {
case 0:
if (!sprite_delay_main[k]) {
static const int8 kBomber_Xvel[8] = {16, 12, 0, -12, -16, -12, 0, 12};
static const int8 kBomber_Yvel[8] = {0, 12, 16, 12, 0, -12, -16, -12};
static const uint8 kBomber_Tab0[4] = {0, 4, 2, 6};
int j;
sprite_ai_state[k]++;
sprite_B[k]++;
if (sprite_B[k] == 3) {
sprite_B[k] = 0;
sprite_delay_main[k] = 48;
j = kBomber_Tab0[Sprite_DirectionToFaceLink(k, NULL)];
} else {
j = GetRandomNumber();
sprite_delay_main[k] = j & 0x1f | 0x20;
j &= 7;
}
sprite_x_vel[k] = kBomber_Xvel[j];
sprite_y_vel[k] = kBomber_Yvel[j];
}
goto set_dir;
case 1:
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 10;
if (sprite_type[k] == 0xa8)
sprite_delay_aux1[k] = 16;
} else {
Sprite_MoveXY(k);
set_dir:
sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
sprite_graphics[k] = sprite_D[k] << 1 | ++sprite_subtype2[k] >> 3 & 1;
}
break;
case 2:
if (!sprite_delay_main[k])
sprite_ai_state[k] = 0;
sprite_subtype2[k] += 2;
Sprite_MoveXY(k);
goto set_dir;
}
}
void Zirro_DropBomb(int k) { // 9e8f81
static const int8 kBomber_SpawnPellet_X[4] = {14, -6, 4, 4};
static const int8 kBomber_SpawnPellet_Y[4] = {7, 7, 12, -4};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xa8, &info);
if (j >= 0) {
SpriteSfx_QueueSfx2WithPan(k, 0x20);
sprite_z[j] = info.r4_z;
int i = sprite_D[j];
Sprite_SetX(j, info.r0_x + kBomber_SpawnPellet_X[i]);
Sprite_SetY(j, info.r2_y + kBomber_SpawnPellet_Y[i]);
sprite_x_vel[j] = kFluteBoyAnimal_Xvel[i];
sprite_y_vel[j] = kZazak_Yvel[i];
sprite_A[j] = 1;
sprite_ignore_projectile[j] = 1;
sprite_flags4[j] = 9;
sprite_flags3[j] = 0x33;
sprite_oam_flags[j] = 0x33 & 15;
}
}
void Sprite_StalfosBone(int k) { // 9e8fdf
StalfosBone_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToLink(k);
sprite_subtype2[k]++;
Sprite_MoveXY(k);
if (!sprite_delay_main[k] && Sprite_CheckTileCollision(k)) {
sprite_state[k] = 0;
Sprite_PlaceWeaponTink(k);
}
}
void StalfosBone_Draw(int k) { // 9e9040
static const DrawMultipleData kStalfosBone_Dmd[8] = {
{-4, -2, 0x802f, 0},
{ 4, 2, 0x402f, 0},
{-4, 2, 0x002f, 0},
{ 4, -2, 0xc02f, 0},
{ 2, -4, 0x403f, 0},
{-2, 4, 0x803f, 0},
{-2, -4, 0x003f, 0},
{ 2, 4, 0xc03f, 0},
};
Sprite_DrawMultiple(k, &kStalfosBone_Dmd[(sprite_subtype2[k] >> 2 & 3) * 2], 2, NULL);
}
void Sprite_A7_Stalfos(int k) { // 9e906c
if (sprite_A[k]) {
Sprite_StalfosBone(k);
return;
}
if (!sprite_E[k]) {
Stalfos_Skellington(k);
return;
}
if (!sprite_delay_main[k]) {
sprite_x_vel[k] = 1;
sprite_y_vel[k] = 1;
if (Sprite_CheckTileCollision(k)) {
sprite_state[k] = 0;
return;
}
sprite_E[k] = 0;
SpriteSfx_QueueSfx2WithPan(k, 0x15);
Sprite_SpawnPoofGarnish(k);
sprite_delay_aux2[k] = 8;
sprite_delay_main[k] = 64;
sprite_y_vel[k] = 0;
sprite_x_vel[k] = 0;
}
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
}
void Stalfos_Skellington(int k) { // 9e90b5
static const uint8 kStalfos_AnimState2[4] = {8, 9, 10, 11};
static const uint8 kStalfos_CheckDir[4] = {3, 2, 1, 0};
if (sprite_state[k] == 9 &&
(uint16)(link_x_coord - cur_sprite_x + 40) < 80 &&
(uint16)(link_y_coord - cur_sprite_y + 48) < 80 &&
player_oam_y_offset != 0x80 &&
!(sprite_z[k] | sprite_pause[k]) &&
sprite_floor[k] == link_is_on_lower_level) {
uint8 dir = Sprite_DirectionToFaceLink(k, NULL);
if (!link_is_running) {
if (button_b_frames >= 0x90)
goto if_1;
if (!sign8(button_b_frames - 9))
goto endif_1;
}
if (dir != kStalfos_CheckDir[link_direction_facing >> 1]) {
if_1:
sprite_D[k] = dir;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 32);
sprite_x_vel[k] = -pt.x;
sprite_y_vel[k] = -pt.y;
sprite_z_vel[k] = 32;
SpriteSfx_QueueSfx3WithPan(k, 0x13);
sprite_z[k]++;
}
}
endif_1:
if (sprite_z[k] == 0) {
Sprite_Zazak_Main(k);
return;
}
sprite_graphics[k] = kStalfos_AnimState2[sprite_D[k]];
Stalfos_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_F[k])
sprite_z_vel[k] = 0;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
uint8 t = Sprite_CheckTileCollision(k);
if (t & 3)
sprite_x_vel[k] = 0;
if (t & 12)
sprite_y_vel[k] = 0;
Sprite_MoveXYZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k] - 1)) {
sprite_z[k] = 0;
Sprite_ZeroVelocity_XY(k);
SpriteSfx_QueueSfx2WithPan(k, 0x21);
if (sprite_subtype[k]) {
sprite_delay_aux3[k] = 16;
sprite_subtype2[k] = 0;
}
}
}
void Sprite_Zazak_Main(int k) { // 9e919f
static const uint8 kStalfos_AnimState1[8] = {6, 4, 0, 2, 7, 5, 1, 3};
static const uint8 kStalfos_Delay[4] = {16, 32, 64, 32};
static const int8 kZazak_Yvel[4] = {0, 0, 16, -16};
if (sprite_B[k]) {
FirePhlegm_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_graphics[k] = frame_counter >> 1 & 1;
Sprite_CheckDamageToLink(k);
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k)) {
sprite_state[k] = 0;
Sprite_PlaceRupulseSpark_2(k);
}
return;
}
int t = sprite_delay_aux3[k];
if (t != 0) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 32;
Sprite_ZeroVelocity_XY(k);
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL);
}
if (t == 1) {
Stalfos_ThrowBone(k);
sprite_subtype2[k] = 1;
}
sprite_graphics[k] = kStalfos_AnimState1[(sprite_subtype2[k] & 1) * 4 + sprite_D[k]];
if (sprite_type[k] == 0xa7)
Stalfos_Draw(k);
else
Zazak_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
switch (sprite_ai_state[k]) {
case 0: // walk then track head
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = kStalfos_Delay[GetRandomNumber() & 3];
sprite_ai_state[k] = 1;
int j = sprite_head_dir[k];
sprite_D[k] = j;
sprite_x_vel[k] = kFluteBoyAnimal_Xvel[j];
sprite_y_vel[k] = kZazak_Yvel[j];
}
break;
case 1: // halt and change dir
if (sprite_wallcoll[k] != 0) {
sprite_delay_main[k] = 16;
} else {
if (sprite_delay_main[k] != 0) {
if (sign8(--sprite_G[k])) {
sprite_G[k] = 11;
sprite_subtype2[k]++;
}
return;
} else if (sprite_type[k] == 0xa6 &&
sprite_D[k] == Sprite_DirectionToFaceLink(k, NULL) &&
sprite_floor[k] == link_is_on_lower_level) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 48;
sprite_delay_aux1[k] = 48;
sprite_y_vel[k] = sprite_x_vel[k] = 0;
return;
}
sprite_delay_main[k] = 32;
}
sprite_head_dir[k] = kZazak_Dir2[sprite_D[k] * 2 + (GetRandomNumber() & 1)];
sprite_ai_state[k] = 0;
if (++sprite_C[k] == 4) {
sprite_C[k] = 0;
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL);
sprite_delay_main[k] = 24;
}
sprite_y_vel[k] = sprite_x_vel[k] = 0;
break;
case 2: // shoot
if (!sprite_delay_main[k])
sprite_ai_state[k] = 0;
else if (sprite_delay_main[k] == 24)
Sprite_SpawnFirePhlegm(k);
break;
}
}
int Sprite_SpawnFirePhlegm(int k) { // 9e92e4
static const int8 kSpawnFirePhlegm_X[4] = {16, -8, 4, 4};
static const int8 kSpawnFirePhlegm_Y[4] = {-2, -2, 8, -20};
static const int8 kSpawnFirePhlegm_Xvel[4] = {48, -48, 0, 0};
static const int8 kSpawnFirePhlegm_Yvel[4] = {0, 0, 48, -48};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xa5, &info);
if (j >= 0) {
SpriteSfx_QueueSfx3WithPan(k, 0x5);
Sprite_SetSpawnedCoordinates(j, &info);
int i = sprite_D[k];
Sprite_SetX(j, info.r0_x + kSpawnFirePhlegm_X[i]);
Sprite_SetY(j, info.r2_y + kSpawnFirePhlegm_Y[i]);
sprite_x_vel[j] = kSpawnFirePhlegm_Xvel[i];
sprite_y_vel[j] = kSpawnFirePhlegm_Yvel[i];
sprite_flags3[j] |= 0x40;
sprite_defl_bits[j] = 0x40;
sprite_flags2[j] = 0x21;
sprite_B[j] = 0x21;
sprite_oam_flags[j] = 2;
sprite_flags4[j] = 0x14;
sprite_ignore_projectile[j] = 20;
sprite_bump_damage[j] = 37;
if (link_shield_type >= 3)
sprite_flags5[j] = 0x20;
}
return j;
}
void Stalfos_ThrowBone(int k) { // 9e9379
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xa7, &info);
if (j >= 0) {
sprite_A[j] = 1;
Sprite_SetSpawnedCoordinates(j, &info);
Sprite_ApplySpeedTowardsLink(j, 32);
sprite_flags2[j] = 0x21;
sprite_ignore_projectile[j] = 33;
sprite_flags3[j] |= 0x40;
sprite_defl_bits[j] = 0x48;
sprite_delay_main[j] = 16;
sprite_flags4[j] = 0x14;
sprite_oam_flags[j] = 7;
sprite_bump_damage[j] = 32;
SpriteSfx_QueueSfx2WithPan(k, 0x2);
}
}
void FirePhlegm_Draw(int k) { // 9e9443
static const DrawMultipleData kFirePhlegm_Dmd[16] = {
{ 0, 0, 0x00c3, 0},
{-8, 0, 0x00c2, 0},
{ 0, 0, 0x80c3, 0},
{-8, 0, 0x80c2, 0},
{ 0, 0, 0x40c3, 0},
{ 8, 0, 0x40c2, 0},
{ 0, 0, 0xc0c3, 0},
{ 8, 0, 0xc0c2, 0},
{ 0, 0, 0x00d4, 0},
{ 0, -8, 0x00d3, 0},
{ 0, 0, 0x40d4, 0},
{ 0, -8, 0x40d3, 0},
{ 0, 0, 0x80d4, 0},
{ 0, 8, 0x80d3, 0},
{ 0, 0, 0xc0d4, 0},
{ 0, 8, 0xc0d3, 0},
};
Sprite_DrawMultiple(k, &kFirePhlegm_Dmd[sprite_D[k] * 4 + sprite_graphics[k] * 2], 2, NULL);
}
void Sprite_A3_KholdstareShell(int k) { // 9e9460
if (Sprite_ReturnIfPaused(k))
return;
PointU8 pt;
Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.x + 32) < 64 && (uint8)(pt.y + 32) < 64) {
Sprite_NullifyHookshotDrag();
Sprite_RepelDash();
}
Sprite_CheckDamageFromLink(k);
if (sprite_ai_state[k] == 0) {
if (sprite_state[k] == 6) {
sprite_flags3[k] = 0xc0;
sprite_ai_state[k] = 1;
sprite_state[k] = 9;
} else if (sprite_hit_timer[k] != 0) {
dung_floor_x_offs = (sprite_hit_timer[k] & 2) ? -1 : 1;
dung_hdr_collision_2_mirror = 1;
} else {
dung_hdr_collision_2_mirror = 0;
}
} else if (sprite_ai_state[k]++ != 18) {
KholdstareShell_PaletteFiltering();
} else {
sprite_state[k] = 0;
sprite_ai_state[2] = 2;
sprite_delay_main[2] = 128;
}
}
void GenerateIceball(int k) { // 9e94dd
if (++sprite_subtype2[k] & 127 | sprite_delay_aux1[k])
return;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xa4, &info);
if (j >= 0) {
Sprite_SetX(j, link_x_coord);
Sprite_SetY(j, link_y_coord);
sprite_z[j] = -32;
sprite_C[j] = -32;
SpriteSfx_QueueSfx2WithPan(j, 0x20);
}
}
void Sprite_A2_Kholdstare(int k) { // 9e9518
int j;
Kholdstare_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_ai_state[k] < 2) {
Kholdstare_SpawnPuffCloudGarnish(k);
if (!(frame_counter & 7))
sound_effect_1 = 2;
}
if (Sprite_ReturnIfRecoiling(k))
return;
if (sign8(--sprite_subtype2[k])) {
sprite_subtype2[k] = 10;
sprite_graphics[k] = sprite_graphics[k] + 1 & 3;
}
if (!(frame_counter & 3)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 31);
sprite_A[k] = Sprite_ConvertVelocityToAngle(pt.x, pt.y);
}
Sprite_MoveXY(k);
switch(sprite_ai_state[k]) {
case 0: // Accelerate
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = (GetRandomNumber() & 63) + 32;
return;
}
if (sprite_x_vel[k] - sprite_z_vel[k])
sprite_x_vel[k] += sign8(sprite_x_vel[k] - sprite_z_vel[k]) ? 1 : -1;
if (sprite_y_vel[k] - sprite_z_subpos[k])
sprite_y_vel[k] += sign8(sprite_y_vel[k] - sprite_z_subpos[k]) ? 1 : -1;
check_coll:
j = Sprite_CheckTileCollision(k);
if (j & 3) {
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_z_vel[k] = -sprite_z_vel[k];
}
if (j & 12) {
sprite_y_vel[k] = -sprite_y_vel[k];
sprite_z_subpos[k] = -sprite_z_subpos[k];
}
break;
case 1: // Decelerate
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = (GetRandomNumber() & 63) + 96;
j = GetRandomNumber();
if (!(j & 0x1c)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 24);
sprite_z_vel[k] = pt.x;
sprite_z_subpos[k] = pt.y;
} else {
static const int8 kKholdstare_Target_Xvel[4] = {16, 16, -16, -16};
static const int8 kKholdstare_Target_Yvel[4] = {-16, 16, 16, -16};
sprite_z_vel[k] = kKholdstare_Target_Xvel[j & 3];
sprite_z_subpos[k] = kKholdstare_Target_Yvel[j & 3];
}
} else {
if (sprite_x_vel[k])
sprite_x_vel[k] += sign8(sprite_x_vel[k]) ? 1 : -1;
if (sprite_y_vel[k])
sprite_y_vel[k] += sign8(sprite_y_vel[k]) ? 1 : -1;
goto check_coll;
}
break;
case 2: // Triplicate
if (sprite_delay_main[k] == 1) {
sprite_state[k] = 0;
sprite_state[k + 1] = 0;
sprite_state[k + 2] = 0;
for (int i = 2; i >= 0; i--) {
static const int8 kKholdstare_Triplicate_Tab0[3] = {32, -32, 0};
static const int8 kKholdstare_Triplicate_Tab1[3] = {-32, -32, 48};
SpriteSpawnInfo info;
j = Sprite_SpawnDynamicallyEx(k, 0xa2, &info, 4);
assert(j >= 0);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_z_vel[j] = kKholdstare_Triplicate_Tab0[i];
sprite_z_subpos[j] = kKholdstare_Triplicate_Tab1[i];
sprite_delay_main[j] = 32;
}
}
tmp_counter = 0xff;
} else {
sprite_hit_timer[k] |= 0xe0;
}
break;
}
}
void Kholdstare_SpawnPuffCloudGarnish(int k) { // 9e96a5
static const int8 kNebuleGarnish_XY[8] = {-8, -6, -4, -2, 0, 2, 4, 6};
if ((k ^ frame_counter) & 3)
return;
int j = GarnishAllocLow();
if (j < 0)
return;
garnish_type[j] = 7;
garnish_active = 7;
garnish_countdown[j] = 31;
Garnish_SetX(j, cur_sprite_x + kNebuleGarnish_XY[GetRandomNumber() & 7]);
Garnish_SetY(j, cur_sprite_y + kNebuleGarnish_XY[GetRandomNumber() & 7] + 16);
garnish_floor[j] = 0;
}
void Sprite_A4_FallingIce(int k) { // 9e9710
if (!sprite_C[k]) {
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_state[2] < 9 && sprite_state[3] < 9 && sprite_state[4] < 9)
sprite_state[k] = 0;
GenerateIceball(k);
return;
}
sprite_ignore_projectile[k] = 1;
sprite_obj_prio[k] = 0x30;
SpriteDraw_SingleLarge(k);
if (!sprite_ai_state[k])
sprite_flags3[k] ^= 16;
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_delay_main[k]) {
if (sprite_delay_main[k] == 1)
sprite_state[k] = 0;
sprite_graphics[k] = (sprite_delay_main[k] >> 3) + 2;
return;
}
Sprite_MoveXY(k);
if (!sprite_ai_state[k] || (Sprite_CheckDamageToLink(k), !Sprite_CheckTileCollision(k))) {
uint8 old_z = sprite_z[k];
Sprite_MoveZ(k);
if (!sign8(sprite_z_vel[k] + 64))
sprite_z_vel[k] -= 3;
if (!(sign8(old_z ^ sprite_z[k]) && sign8(sprite_z[k])))
return;
sprite_z[k] = 0;
if (!sprite_ai_state[k]) {
sprite_state[k] = 0;
IceBall_Split(k);
return;
}
}
sprite_delay_main[k] = 15;
sprite_oam_flags[k] = 4;
if (!sound_effect_1) {
SpriteSfx_QueueSfx2WithPan(k, 0x1e);
sprite_graphics[k] = 3;
}
}
void IceBall_Split(int k) { // 9e97cf
static const int8 kIceBall_Quadruplicate_Xvel[8] = {0, 32, 0, -32, 24, 24, -24, -24};
static const int8 kIceBall_Quadruplicate_Yvel[8] = {-32, 0, 32, 0, -24, 24, -24, 24};
SpriteSfx_QueueSfx2WithPan(k, 0x1f);
int b = GetRandomNumber() & 4;
for (int i = 3; i >= 0; i--) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xa4, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_ai_state[j] = 1;
sprite_graphics[j] = 1;
sprite_C[j] = 1;
sprite_z_vel[j] = 32;
sprite_x_vel[j] = kIceBall_Quadruplicate_Xvel[i + b];
sprite_y_vel[j] = kIceBall_Quadruplicate_Yvel[i + b];
sprite_flags4[j] = 0x1c;
}
}
tmp_counter = 0xff;
}
void Sprite_A1_Freezor(int k) { // 9e981d
Freezor_Draw(k);
if (sprite_state[k] != 9) {
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 31;
sprite_ignore_projectile[k] = 31;
sprite_state[k] = 9;
sprite_hit_timer[k] = 0;
}
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_ai_state[k] != 3) {
if (Sprite_ReturnIfRecoiling(k))
return;
}
switch(sprite_ai_state[k]) {
case 0: // stasis
sprite_ignore_projectile[k]++;
if ((uint8)(Sprite_IsRightOfLink(k).b + 16) < 32) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 32;
}
break;
case 1: { // awakening
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
uint16 x = Sprite_GetX(k) - 5;
uint16 y = Sprite_GetY(k);
Dungeon_UpdateTileMapWithCommonTile(x, y, 8);
sprite_delay_aux1[k] = 96;
sprite_D[k] = 2;
sprite_delay_main[k] = 80;
} else {
sprite_x_vel[k] = (sprite_delay_main[k] & 1) ? -16 : 16;
Sprite_MoveX(k);
}
break;
}
case 2: { // moving
static const int8 kFreezor_Xvel[4] = {8, -8, 0, 0};
static const int8 kFreezor_Yvel[4] = {0, 0, 18, -18};
static const uint8 kFreezor_Moving_Gfx[4] = {1, 2, 1, 3};
static const int8 kFreezor_Sparkle_X[8] = {-4, -2, 0, 2, 4, 6, 8, 10};
Sprite_CheckDamageToLink(k);
if (Sprite_CheckDamageFromLink(k))
sprite_hit_timer[k] = 0;
if (sprite_delay_aux1[k] && !((k ^ frame_counter) & 7)) {
Sprite_GarnishSpawn_Sparkle(k, kFreezor_Sparkle_X[GetRandomNumber() & 7], -4);
}
if (!sprite_delay_main[k])
sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
int j = sprite_D[k];
sprite_x_vel[k] = kFreezor_Xvel[j];
sprite_y_vel[k] = kFreezor_Yvel[j];
if (!(sprite_wallcoll[k] & 15))
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
sprite_graphics[k] = kFreezor_Moving_Gfx[(k ^ frame_counter) >> 2 & 3];
break;
}
case 3: { // melting
static const uint8 kFreezor_Melting_Gfx[4] = { 6, 5, 4, 7 };
if (!sprite_delay_main[k]) {
Sprite_ManuallySetDeathFlagUW(k);
sprite_state[k] = 0;
}
sprite_graphics[k] = kFreezor_Melting_Gfx[sprite_delay_main[k] >> 3];
break;
}
}
}
void Sprite_9E_HauntedGroveOstritch(int k) { // 9e995b
static const uint8 kFluteBoyOstrich_Gfx[4] = {0, 1, 0, 2};
FluteBoyOstrich_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch (sprite_ai_state[k]) {
case 0: // wait
sprite_graphics[k] = (frame_counter & 0x18) ? 3 : 0;
if (byte_7E0FDD) {
sprite_ai_state[k] = 1;
sprite_y_vel[k] = -8;
sprite_x_vel[k] = -16;
}
break;
case 1: // run away
Sprite_MoveXYZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z_vel[k] = 32;
sprite_z[k] = 0;
sprite_subtype2[k] = 0;
sprite_A[k] = 0;
}
if (!(++sprite_subtype2[k] & 7) && sprite_A[k] != 3)
sprite_A[k]++;
sprite_graphics[k] = kFluteBoyOstrich_Gfx[sprite_A[k]];
break;
}
}
void FluteBoyOstrich_Draw(int k) { // 9e9a4b
static const DrawMultipleData kFluteBoyOstrich_Dmd[16] = {
{-4, -8, 0x0080, 2},
{ 4, -8, 0x0081, 2},
{-4, 8, 0x00a3, 2},
{ 4, 8, 0x00a4, 2},
{-4, -8, 0x0080, 2},
{ 4, -8, 0x0081, 2},
{-4, 8, 0x00a0, 2},
{ 4, 8, 0x00a1, 2},
{-4, -8, 0x0080, 2},
{ 4, -8, 0x0081, 2},
{-4, 8, 0x0083, 2},
{ 4, 8, 0x0084, 2},
{-4, -7, 0x0080, 2},
{ 4, -7, 0x0081, 2},
{-4, 9, 0x00a3, 2},
{ 4, 9, 0x00a4, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kFluteBoyOstrich_Dmd[sprite_graphics[k] * 4], 4, &info);
SpriteDraw_Shadow_custom(k, &info, 18);
}
void Sprite_9F_HauntedGroveRabbit(int k) { // 9e9a6d
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kFluteBoyAnimal_OamFlags[sprite_D[k]];
SpriteDraw_SingleLarge(k);
switch (sprite_ai_state[k]) {
case 0: // wait
sprite_graphics[k] = 3;
if (byte_7E0FDD) {
sprite_ai_state[k] = 1;
sprite_D[k] ^= 1;
sprite_x_vel[k] = kFluteBoyAnimal_Xvel[sprite_D[k]];
sprite_y_vel[k] = -8;
}
break;
case 1: // run
Sprite_MoveXYZ(k);
sprite_z_vel[k]-=3;
if (sign8(sprite_z[k])) {
sprite_z_vel[k] = 24;
sprite_z[k] = 0;
sprite_subtype2[k] = 0;
sprite_A[k] = 0;
}
sprite_subtype2[k]++;
if (!(sprite_subtype2[k] & 3) && sprite_A[k] != 2)
sprite_A[k]++;
sprite_graphics[k] = kFluteBoyAnimal_Gfx[sprite_A[k]];
break;
}
}
void Sprite_A0_HauntedGroveBird(int k) { // 9e9aec
if (sprite_graphics[k] == 3)
HauntedGroveBird_Blink(k);
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kFluteBoyAnimal_OamFlags[sprite_D[k]];
oam_cur_ptr += 4;
oam_ext_cur_ptr++;
sprite_flags2[k]--;
SpriteDraw_SingleLarge(k);
sprite_flags2[k]++;
Sprite_MoveXYZ(k);
switch (sprite_ai_state[k]) {
case 0: // wait
sprite_graphics[k] = (frame_counter & 0x18) ? 0 : 3;
if (byte_7E0FDD) {
sprite_ai_state[k] = 1;
sprite_D[k] ^= 1;
sprite_x_vel[k] = kFluteBoyAnimal_Xvel[sprite_D[k]];
sprite_delay_main[k] = 32;
sprite_z_vel[k] = 16;
sprite_y_vel[k] = -8;
}
break;
case 1: // rising
if (!sprite_delay_main[k]) {
sprite_z_vel[k] += 2;
if (!sign8(sprite_z_vel[k] - 0x10))
sprite_ai_state[k] = 2;
}
sprite_graphics[k] = (++sprite_subtype2[k] >> 1 & 1) + 1;
break;
case 2: // falling
sprite_graphics[k] = 1;
sprite_z_vel[k] -= 1;
if (sign8(sprite_z_vel[k] + 15))
sprite_ai_state[k] = 1;
break;
}
}
void HauntedGroveBird_Blink(int k) { // 9e9b9c
static const int8 kFluteBoyBird_X[2] = {8, 0};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int j = sprite_D[k];
oam->x = info.x + kFluteBoyBird_X[j];
oam->y = info.y;
oam->charnum = 0xae;
oam->flags = info.flags | kFluteBoyAnimal_OamFlags[j];
Sprite_CorrectOamEntries(k, 0, 0);
}
void Sprite_9C_Zoro(int k) { // 9e9bc8
if (sprite_E[k])
Zoro(k);
else
Babasu(k);
//
}
void Zoro(int k) { // 9e9bd0
if (!sprite_C[k]) {
sprite_C[k]++;
if (Sprite_IsBelowLink(k).a != 0) {
sprite_state[k] = 0;
return;
}
}
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_graphics[k] = ++sprite_subtype2[k] >> 1 & 1;
sprite_x_vel[k] = kFluteBoyAnimal_Xvel[sprite_subtype2[k] >> 2 & 1];
Sprite_MoveXY(k);
if (!sprite_delay_main[k] && Sprite_CheckTileCollision(k))
sprite_state[k] = 0;
if (sprite_subtype2[k] & 3)
return;
int j = GarnishAlloc();
if (j < 0)
return;
garnish_type[j] = 6;
garnish_active = 6;
Garnish_SetX(j, Sprite_GetX(k));
Garnish_SetY(j, Sprite_GetY(k) + 16);
garnish_countdown[j] = 10;
garnish_sprite[j] = k;
garnish_floor[j] = sprite_floor[k];
}
void Babasu(int k) { // 9e9c6b
static const uint8 kBabusu_Gfx[6] = {5, 4, 3, 2, 1, 0};
static const uint8 kBabusu_DirGfx[4] = {6, 6, 0, 0};
static const int8 kBabusu_XyVel[6] = {32, -32, 0, 0, 32, -32};
Babusu_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch(sprite_ai_state[k]) {
case 0: // reset
sprite_ai_state[k]++;
sprite_delay_main[k] = 128;
sprite_graphics[k] = 255;
break;
case 1: // hiding
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 55;
}
break;
case 2: { // terror sprinkles
int j = sprite_delay_main[k], i = sprite_D[k];
if (j == 0) {
sprite_ai_state[k] = 3;
sprite_x_vel[k] = kBabusu_XyVel[i];
sprite_y_vel[k] = kBabusu_XyVel[i + 2];
sprite_delay_main[k] = 32;
}
if (j >= 32) {
sprite_graphics[k] = kBabusu_Gfx[(j - 32) >> 2] + kBabusu_DirGfx[i];
} else {
sprite_graphics[k] = 0xff;
}
break;
}
case 3: { // scurry across
static const uint8 kBabusu_Scurry_Gfx[4] = {18, 14, 12, 16};
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
sprite_graphics[k] = (frame_counter >> 1 & 1) + kBabusu_Scurry_Gfx[sprite_D[k]];
if (!sprite_delay_main[k] && Sprite_CheckTileCollision(k)) {
sprite_D[k] ^= 1;
sprite_ai_state[k] = 0;
}
break;
}
}
}
void Sprite_9B_Wizzrobe(int k) { // 9e9d1b
int j;
if (sprite_C[k]) {
Sprite_Wizzbeam(k);
return;
}
if (sprite_ai_state[k] == 0 || sprite_ai_state[k] & 1 && sprite_delay_main[k] & 1) {
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
} else {
Wizzrobe_Draw(k);
}
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_ignore_projectile[k] = 1;
switch(sprite_ai_state[k]) {
case 0: // cloaked
if (!sprite_delay_main[k]) {
sprite_y_vel[k] = sprite_x_vel[k] = 1;
if (!Sprite_CheckTileCollision(k)) {
static const uint8 kWizzrobe_Cloak_Gfx[4] = {4, 2, 0, 6};
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 63;
sprite_D[k] = j = Sprite_DirectionToFaceLink(k, NULL);
sprite_graphics[k] = kWizzrobe_Cloak_Gfx[j];
} else {
sprite_state[k] = 0;
}
}
break;
case 1: // phasing in
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 63;
}
break;
case 2: { // attack
static const uint8 kWizzrobe_Attack_Gfx[8] = {0, 1, 1, 1, 1, 1, 1, 0};
static const uint8 kWizzrobe_Attack_DirGfx[4] = {4, 2, 0, 6};
sprite_ignore_projectile[k] = 0;
Sprite_CheckDamageToAndFromLink(k);
j = sprite_delay_main[k];
if (!j) {
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 63;
return;
}
if (j == 32)
Wizzrobe_FireBeam(k);
sprite_graphics[k] = kWizzrobe_Attack_Gfx[j >> 3] + kWizzrobe_Attack_DirGfx[sprite_D[k]];
break;
}
case 3: // phasing out
if (!sprite_delay_main[k]) {
if (sprite_B[k])
sprite_state[k] = 0;
sprite_ai_state[k] = 0;
sprite_delay_main[k] = (GetRandomNumber() & 31) + 32;
}
break;
}
}
void Wizzrobe_FireBeam(int k) { // 9e9e15
static const int8 kWizzrobe_Beam_XYvel[6] = {32, -32, 0, 0, 32, -32};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x9b, &info);
if (j >= 0) {
SpriteSfx_QueueSfx3WithPan(k, 0x36);
sprite_C[j] = 1;
sprite_ignore_projectile[j] = 1;
Sprite_SetX(j, info.r0_x + 4);
Sprite_SetY(j, info.r2_y);
int i = sprite_D[k];
sprite_x_vel[j] = kWizzrobe_Beam_XYvel[i];
sprite_y_vel[j] = kWizzrobe_Beam_XYvel[i + 2];
sprite_defl_bits[j] = 0x48;
sprite_oam_flags[j] = 2;
sprite_flags5[j] = link_shield_type == 3 ? 0x20 : 0;
sprite_flags4[j] = 0x14;
}
}
void Sprite_9A_Kyameron(int k) { // 9e9e7b
PrepOamCoordsRet info;
if (!sprite_ai_state[k])
Sprite_PrepOamCoord(k, &info);
else
Kyameron_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_ignore_projectile[k] = 1;
switch(sprite_ai_state[k]) {
case 0: // reset
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = (GetRandomNumber() & 63) + 96;
sprite_x_lo[k] = sprite_A[k];
sprite_x_hi[k] = sprite_B[k];
sprite_y_lo[k] = sprite_C[k];
sprite_y_hi[k] = sprite_head_dir[k];
sprite_subtype2[k] = 5;
sprite_graphics[k] = 8;
}
break;
case 1: // puddleup
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 31;
sprite_ai_state[k] = 2;
}
if (sign8(--sprite_subtype2[k])) {
sprite_subtype2[k] = 5;
sprite_graphics[k] = (++sprite_graphics[k] & 3) + 8;
}
break;
case 2: { // coagulate
static const int8 kKyameron_Coagulate_Gfx[8] = {4, 7, 14, 13, 12, 6, 6, 5};
static const int8 kKyameron_Xvel[4] = {32, -32, 32, -32};
static const int8 kKyameron_Yvel[4] = {32, 32, -32, -32};
int j = sprite_delay_main[k];
if (j == 0) {
sprite_ai_state[k] = 3;
j = Sprite_IsBelowLink(k).a * 2 + Sprite_IsRightOfLink(k).a;
sprite_x_vel[k] = kKyameron_Xvel[j];
sprite_y_vel[k] = kKyameron_Yvel[j];
} else {
if (j == 7)
Sprite_SetY(k, Sprite_GetY(k) - 29);
sprite_graphics[k] = kKyameron_Coagulate_Gfx[j >> 2];
}
break;
}
case 3: { // moving
sprite_ignore_projectile[k] = 0;
if (!Sprite_CheckDamageToAndFromLink(k)) {
Sprite_MoveXY(k);
int j = Sprite_CheckTileCollision(k);
if (j & 3) {
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_anim_clock[k]++;
}
if (j & 12) {
sprite_y_vel[k] = -sprite_y_vel[k];
sprite_anim_clock[k]++;
}
if (sprite_anim_clock[k] < 3)
goto skip_sound;
}
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 15;
SpriteSfx_QueueSfx2WithPan(k, 0x28);
static const uint8 kKyameron_Moving_Gfx[4] = {3, 2, 1, 0};
skip_sound:
sprite_graphics[k] = kKyameron_Moving_Gfx[++sprite_subtype2[k] >> 3 & 3];
if (!((k ^ frame_counter) & 7)) {
uint16 x = (GetRandomNumber() & 0xf) - 4;
uint16 y = (GetRandomNumber() & 0xf) - 4;
Sprite_GarnishSpawn_Sparkle(k, x, y);
}
break;
}
case 4: // disperse
if (!sprite_delay_main[k]) {
sprite_anim_clock[k] = 0;
sprite_ai_state[k] = 0;
sprite_z[k] = 0;
sprite_delay_main[k] = 64;
} else {
sprite_graphics[k] = (sprite_delay_main[k] >> 2) + 15;
}
break;
}
}
void Kyameron_Draw(int k) { // 9ea158
static const uint8 kKyameron_OamFlags[12] = {0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0xc0, 0x80};
static const DrawMultipleData kKyameron_Dmd[28] = {
{ 1, 8, 0x00b4, 0},
{ 7, 8, 0x00b5, 0},
{ 4, -3, 0x0086, 0},
{ 0, -13, 0x80a2, 2},
{ 2, 8, 0x00b4, 0},
{ 6, 8, 0x00b5, 0},
{ 4, -6, 0x0096, 0},
{ 0, -20, 0x00a2, 2},
{ 4, -1, 0x0096, 0},
{ 0, -27, 0x00a2, 2},
{ 0, -27, 0x00a2, 2},
{ 0, -27, 0x00a2, 2},
{-6, -6, 0x01df, 0},
{14, -6, 0x41df, 0},
{-6, 14, 0x81df, 0},
{14, 14, 0xc1df, 0},
{-6, -6, 0x0096, 0},
{14, -6, 0x4096, 0},
{-6, 14, 0x8096, 0},
{14, 14, 0xc096, 0},
{-4, -4, 0x018d, 0},
{12, -4, 0x418d, 0},
{-4, 12, 0x818d, 0},
{12, 12, 0xc18d, 0},
{ 0, 0, 0x018d, 0},
{ 8, 0, 0x418d, 0},
{ 0, 8, 0x818d, 0},
{ 8, 8, 0xc18d, 0},
};
int j = sprite_graphics[k];
if (j < 12) {
uint8 bak = sprite_oam_flags[k];
sprite_oam_flags[k] = sprite_oam_flags[k] & 0x3f | kKyameron_OamFlags[j];
SpriteDraw_SingleLarge(k);
sprite_oam_flags[k] = bak;
} else {
Sprite_DrawMultiple(k, &kKyameron_Dmd[(j - 12) * 4], 4, NULL);
}
}
void Sprite_99_Pengator(int k) { // 9ea196
static const uint8 kPengator_Gfx[4] = {5, 0, 10, 15};
sprite_graphics[k] = sprite_A[k] + kPengator_Gfx[sprite_D[k]];
Pengator_Draw(k);
if (sprite_F[k] || sprite_wallcoll[k] & 15) {
sprite_ai_state[k] = 0;
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
}
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXYZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z_vel[k] = 0;
sprite_z[k] = 0;
}
Sprite_CheckTileCollision(k);
switch(sprite_ai_state[k]) {
case 0: // face player
sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
sprite_ai_state[k] = 1;
break;
case 1: // speedup
if (!((k ^ frame_counter) & 3)) {
static const int8 kPengator_XYVel[6] = { 1, -1, 0, 0, 1, -1 };
bool flag = false;
int j = sprite_D[k];
if (sprite_x_vel[k] != (uint8)kFluteBoyAnimal_Xvel[j])
sprite_x_vel[k] += kPengator_XYVel[j], flag = true;
if (sprite_y_vel[k] != (uint8)kZazak_Yvel[j])
sprite_y_vel[k] += kPengator_XYVel[j + 2], flag = true;
if (!flag) {
sprite_delay_main[k] = 15;
sprite_ai_state[k] = 2;
}
}
sprite_A[k] = (frame_counter & 4) >> 2;
break;
case 2: { // jump
static const uint8 kPengator_Jump[4] = {4, 4, 3, 2};
if (!sprite_delay_main[k])
sprite_ai_state[k]++;
else if (sprite_delay_main[k] == 5)
sprite_z_vel[k] = 24;
sprite_A[k] = kPengator_Jump[sprite_delay_main[k] >> 2];
break;
}
case 3: // slide and sparkle
if (!((k ^ frame_counter) & 7 | sprite_z[k])) {
static const int8 kPengator_Garnish_Y[8] = { 8, 10, 12, 14, 12, 12, 12, 12 };
static const int8 kPengator_Garnish_X[8] = { 4, 4, 4, 4, 0, 4, 8, 12 };
int i = sprite_D[k];
int x = kPengator_Garnish_X[(GetRandomNumber() & 3) + (i >= 2) * 4];
int y = kPengator_Garnish_Y[(GetRandomNumber() & 3) + (i >= 2) * 4];
Sprite_GarnishSpawn_Sparkle_limited(k, x, y);
}
break;
}
}
void Pengator_Draw(int k) { // 9ea415
static const DrawMultipleData kPengator_Dmd0[40] = {
{-1, -8, 0x0082, 2},
{ 0, 0, 0x0088, 2},
{-1, -7, 0x0082, 2},
{ 0, 0, 0x008a, 2},
{-3, -6, 0x0082, 2},
{ 0, 0, 0x0088, 2},
{-6, -4, 0x0082, 2},
{ 0, 0, 0x008a, 2},
{-4, 0, 0x00a2, 2},
{ 4, 0, 0x00a3, 2},
{ 1, -8, 0x4082, 2},
{ 0, 0, 0x4088, 2},
{ 1, -7, 0x4082, 2},
{ 0, 0, 0x408a, 2},
{ 3, -6, 0x4082, 2},
{ 0, 0, 0x4088, 2},
{ 6, -4, 0x4082, 2},
{ 0, 0, 0x408a, 2},
{ 4, 0, 0x40a2, 2},
{-4, 0, 0x40a3, 2},
{ 0, -7, 0x0080, 2},
{ 0, 0, 0x0086, 2},
{ 0, -7, 0x4080, 2},
{ 0, 0, 0x4086, 2},
{ 0, -4, 0x0080, 2},
{ 0, 0, 0x0086, 2},
{ 0, -1, 0x0080, 2},
{ 0, 0, 0x0086, 2},
{-8, 0, 0x008e, 2},
{ 8, 0, 0x408e, 2},
{ 0, -8, 0x0084, 2},
{ 0, 0, 0x008c, 2},
{ 0, -8, 0x4084, 2},
{ 0, 0, 0x408c, 2},
{ 0, -7, 0x0084, 2},
{ 0, 0, 0x008c, 2},
{ 0, 0, 0x408c, 2},
{ 0, -6, 0x4084, 2},
{-8, 0, 0x00a0, 2},
{ 8, 0, 0x40a0, 2},
};
static const DrawMultipleData kPengator_Dmd1[4] = {
{0, 16, 0x00b5, 0},
{8, 16, 0x40b5, 0},
{0, -8, 0x00a5, 0},
{8, -8, 0x40a5, 0},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kPengator_Dmd0[sprite_graphics[k] * 2], 2, &info);
int i;
if ((i = 0, sprite_graphics[k] == 14) || (i = 1, sprite_graphics[k] == 19)) {
oam_cur_ptr += 8, oam_ext_cur_ptr += 2;
Sprite_DrawMultiple(k, &kPengator_Dmd1[i * 2], 2, &info);
}
SpriteDraw_Shadow(k, &info);
}
void Sprite_LaserBeam(int k) { // 9ea462
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
LaserBeam_BuildUpGarnish(k);
Sprite_MoveXY(k);
Sprite_CheckDamageToLink_same_layer(k);
if (!sprite_delay_main[k] && Sprite_CheckTileCollision(k)) {
sprite_state[k] = 0;
SpriteSfx_QueueSfx3WithPan(k, 0x26);
}
}
void LaserBeam_BuildUpGarnish(int k) { // 9ea488
int j = GarnishAllocOverwriteOld();
garnish_type[j] = 4;
garnish_active = 4;
Garnish_SetX(j, Sprite_GetX(k));
Garnish_SetY(j, Sprite_GetY(k) + 16);
garnish_countdown[j] = 16;
garnish_oam_flags[j] = sprite_graphics[k];
garnish_sprite[j] = k;
garnish_floor[j] = sprite_floor[k];
}
void Sprite_95_LaserEyeLeft(int k) { // 9ea541
static const uint8 kLaserEye_Dirs[4] = {2, 3, 0, 1};
if (sprite_A[k]) {
Sprite_LaserBeam(k);
return;
}
LaserEye_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch(sprite_ai_state[k]) {
case 0: // monitor firing zone
if (sprite_head_dir[k] == 0 && sprite_D[k] != kLaserEye_Dirs[link_direction_facing >> 1]) {
sprite_graphics[k] = 0;
} else {
uint16 j = (sprite_D[k] < 2) ? link_y_coord - cur_sprite_y : link_x_coord - cur_sprite_x;
if ((uint16)(j + 16) < 32) {
sprite_delay_main[k] = 32;
sprite_ai_state[k] = 1;
} else {
sprite_graphics[k] = 0;
}
}
break;
case 1: // firing beam
sprite_graphics[k] = 1;
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
LaserEye_FireBeam(k);
sprite_delay_aux4[k] = 12;
}
break;
}
}
void LaserEye_FireBeam(int k) { // 9ea5d8
static const int8 kLaserEye_SpawnXY[6] = {12, -4, 4, 4, 12, -4};
static const int8 kLaserEye_SpawnXYVel[6] = {112, -112, 0, 0, 112, -112};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x95, &info);
if (j >= 0) {
int i = sprite_D[k];
sprite_graphics[j] = (i & 2) >> 1;
Sprite_SetX(j, info.r0_x + kLaserEye_SpawnXY[i]);
Sprite_SetY(j, info.r2_y + kLaserEye_SpawnXY[i + 2]);
sprite_x_vel[j] = kLaserEye_SpawnXYVel[i];
sprite_y_vel[j] = kLaserEye_SpawnXYVel[i + 2];
sprite_flags2[j] = 0x20;
sprite_A[j] = 0x20;
sprite_oam_flags[j] = 5;
sprite_defl_bits[j] = 0x48;
sprite_ignore_projectile[j] = 0x48;
sprite_delay_main[j] = 5;
if (link_shield_type == 3)
sprite_flags5[j] = 32;
SpriteSfx_QueueSfx3WithPan(k, 0x19);
}
}
void LaserEye_Draw(int k) { // 9ea708
static const DrawMultipleData kLaserEye_Dmd[24] = {
{ 8, -4, 0x40c8, 0},
{ 8, 4, 0x40d8, 0},
{ 8, 12, 0xc0c8, 0},
{ 8, -4, 0x40c9, 0},
{ 8, 4, 0x40d9, 0},
{ 8, 12, 0xc0c9, 0},
{ 0, -4, 0x00c8, 0},
{ 0, 4, 0x00d8, 0},
{ 0, 12, 0x80c8, 0},
{ 0, -4, 0x00c9, 0},
{ 0, 4, 0x00d9, 0},
{ 0, 12, 0x80c9, 0},
{-4, 8, 0x00d6, 0},
{ 4, 8, 0x00d7, 0},
{12, 8, 0x40d6, 0},
{-4, 8, 0x00c6, 0},
{ 4, 8, 0x00c7, 0},
{12, 8, 0x40c6, 0},
{-4, 0, 0x80d6, 0},
{ 4, 0, 0x80d7, 0},
{12, 0, 0xc0d6, 0},
{-4, 0, 0x80c6, 0},
{ 4, 0, 0x80c7, 0},
{12, 0, 0xc0c6, 0},
};
if (sprite_head_dir[k])
sprite_graphics[k] = (sprite_delay_aux4[k] == 0);
sprite_obj_prio[k] = 0x30;
Sprite_DrawMultiple(k, &kLaserEye_Dmd[(sprite_graphics[k] + sprite_D[k] * 2) * 3], 3, NULL);
}
void Sprite_94_Pirogusu(int k) { // 9ea742
static const uint8 kPirogusu_A0[4] = {2, 3, 0, 1};
static const uint8 kPirogusu_A1[8] = {9, 11, 5, 7, 5, 11, 7, 9};
static const uint8 kPirogusu_A2[8] = {16, 17, 18, 19, 12, 13, 14, 15};
static const int8 kPirogusu_XYvel[6] = {0, 0, 4, -4, 0, 0};
static const int8 kPirogusu_XYvel2[6] = {2, -2, 0, 0, 2, -2};
static const int8 kPirogusu_XYvel3[6] = {24, -24, 0, 0, 24, -24};
if (sprite_E[k]) {
Sprite_94_Tile(k);
return;
}
sprite_obj_prio[k] |= 0x30;
Pirogusu_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch(sprite_ai_state[k]) {
case 0: // wriggle in hole
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 31;
}
sprite_ignore_projectile[k] = sprite_delay_main[k];
sprite_A[k] = kPirogusu_A0[sprite_D[k]];
break;
case 1: { // emerge
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 32;
sprite_ignore_projectile[k] = 0;
Sprite_ZeroVelocity_XY(k);
} else {
sprite_A[k] = kPirogusu_A1[sprite_delay_main[k] >> 3 & 1 | sprite_D[k] << 1];
int j = sprite_D[k];
sprite_x_vel[k] = kPirogusu_XYvel[j + 2];
sprite_y_vel[k] = kPirogusu_XYvel[j];
Sprite_MoveXY(k);
}
break;
}
case 2: { // splash into play
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
int j = sprite_D[k];
sprite_x_vel[k] += kPirogusu_XYvel2[j];
sprite_y_vel[k] += kPirogusu_XYvel2[j + 2];
if (!sprite_delay_main[k]) {
Sprite_SpawnSmallSplash(k);
sprite_delay_aux1[k] = 16;
sprite_ai_state[k] = 3;
}
sprite_A[k] = kPirogusu_A2[frame_counter >> 2 & 1 | sprite_D[k] << 1];
break;
}
case 3: { // swim
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_A[k] = kPirogusu_A2[frame_counter >> 2 & 1 | sprite_D[k] << 1] + 8;
if (!sprite_delay_aux1[k]) {
Pirogusu_SpawnSplash(k);
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k) & 15) {
static const uint8 kPirogusu_Dir[8] = {2, 3, 2, 3, 0, 1, 0, 1};
sprite_D[k] = kPirogusu_Dir[sprite_D[k] << 1 | GetRandomNumber() & 1];
}
int j = sprite_D[k];
sprite_x_vel[k] = kPirogusu_XYvel3[j];
sprite_y_vel[k] = kPirogusu_XYvel3[j + 2];
}
break;
}
}
}
void Pirogusu_SpawnSplash(int k) { // 9ea897
static const uint8 kPirogusu_Tab0[4] = {3, 4, 5, 4};
if ((k ^ frame_counter) & 3)
return;
int x = kPirogusu_Tab0[GetRandomNumber() & 3];
int y = kPirogusu_Tab0[GetRandomNumber() & 3];
int j = GarnishAllocLow();
if (j >= 0) {
garnish_type[j] = 11;
garnish_active = 11;
Garnish_SetX(j, Sprite_GetX(k) + x);
Garnish_SetY(j, Sprite_GetY(k) + y + 16);
garnish_countdown[j] = 15;
}
}
void Pirogusu_Draw(int k) { // 9ea93b
static const uint8 kPirogusu_OamFlags[28] = {
0, 0x80, 0x40, 0, 0, 0, 0, 0x80, 0x80, 0xc0, 0x40, 0x40, 0, 0x40, 0x80, 0xc0,
0x40, 0xc0, 0, 0x80, 0, 0x40, 0x80, 0xc0, 0x40, 0xc0, 0, 0x80,
};
static const uint8 kPirogusu_Gfx[28] = {
0, 0, 1, 1, 2, 3, 4, 3, 2, 3, 4, 3, 5, 5, 5, 5,
7, 7, 7, 7, 6, 6, 6, 6, 8, 8, 8, 8,
};
int j = sprite_A[k];
sprite_oam_flags[k] = sprite_oam_flags[k] & 0x3f | kPirogusu_OamFlags[j];
sprite_graphics[k] = kPirogusu_Gfx[j];
if (j < 4) {
cur_sprite_x += 4, cur_sprite_y += 4;
SpriteDraw_SingleSmall(k);
} else {
SpriteDraw_SingleLarge(k);
}
}
void Sprite_93_Bumper(int k) { // 9ea982
static const int8 kBumper_Vels[4] = { 0, 2, -2, 0 };
Bumper_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckTileCollision(k);
if (!link_cape_mode && Sprite_CheckDamageToLink_same_layer(k)) {
Link_CancelDash();
sprite_delay_main[k] = 32;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, 0x30);
link_actual_vel_y = pt.y + kBumper_Vels[joypad1H_last >> 2 & 3];
link_actual_vel_x = pt.x + kBumper_Vels[joypad1H_last & 3];
link_incapacitated_timer = 20;
Link_ResetSwimmingState();
SpriteSfx_QueueSfx3WithPan(k, 0x32);
}
for (int j = 15; j >= 0; j--) {
if ((j ^ frame_counter) & 3 | sprite_z[j])
continue;
if (sprite_state[j] < 9 || (sprite_flags3[j] | sprite_flags4[j]) & 0x40)
continue;
int x = Sprite_GetX(j), y = Sprite_GetY(j);
if ((uint16)(cur_sprite_x - x + 16) < 32 && (uint16)(cur_sprite_y - y + 16) < 32) {
sprite_F[j] = 15;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 0x40);
sprite_y_recoil[j] = pt.y;
sprite_x_recoil[j] = pt.x;
sprite_delay_main[k] = 32;
SpriteSfx_QueueSfx3WithPan(k, 0x32);
}
}
}
void Bumper_Draw(int k) { // 9eaa8b
static const DrawMultipleData kBumper_Dmd[8] = {
{-8, -8, 0x00ec, 2},
{ 8, -8, 0x40ec, 2},
{-8, 8, 0x80ec, 2},
{ 8, 8, 0xc0ec, 2},
{-7, -7, 0x00ec, 2},
{ 7, -7, 0x40ec, 2},
{-7, 7, 0x80ec, 2},
{ 7, 7, 0xc0ec, 2},
};
Sprite_DrawMultiple(k, &kBumper_Dmd[(sprite_delay_main[k] >> 1 & 1) * 4], 4, NULL);
}
void Sprite_91_StalfosKnight(int k) { // 9eaaa7
int j;
if (!sprite_ai_state[k]) {
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
} else {
StalfosKnight_Draw(k);
}
if (Sprite_ReturnIfInactive(k))
return;
if ((sprite_hit_timer[k] & 127) == 1) {
sprite_hit_timer[k] = 0;
sprite_ai_state[k] = 6;
sprite_delay_main[k] = 255;
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
enemy_damage_data[0x918] = 2;
}
if (Sprite_ReturnIfRecoiling(k))
return;
switch(sprite_ai_state[k]) {
case 0: { // waiting for player
sprite_flags4[k] = 9;
sprite_ignore_projectile[k] = 9;
uint8 bak0 = sprite_flags2[k];
sprite_flags2[k] |= 128;
bool flag = Sprite_CheckDamageToLink(k);
sprite_flags2[k] = bak0;
if (flag) {
sprite_z[k] = 144;
sprite_ai_state[k] = 1;
sprite_head_dir[k] = 2;
sprite_graphics[k] = 2;
SpriteSfx_QueueSfx2WithPan(k, 0x20);
}
break;
}
case 1: { // falling
uint8 old_z = sprite_z[k];
Sprite_MoveZ(k);
if (!sign8(sprite_z_vel[k] + 64))
sprite_z_vel[k] -= 3;
if (sign8(old_z ^ sprite_z[k]) && sign8(sprite_z[k])) {
sprite_ai_state[k] = 2;
sprite_ignore_projectile[k] = 0;
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
sprite_delay_main[k] = 63;
}
break;
}
case 2: { //
static const uint8 kStalfosKnight_Case2_Gfx[2] = {0, 1};
enemy_damage_data[0x918] = 0;
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 3;
sprite_B[k] = GetRandomNumber() & 63;
sprite_delay_main[k] = 127;
} else {
sprite_C[k] = sprite_graphics[k] = kStalfosKnight_Case2_Gfx[sprite_delay_main[k] >> 5];
sprite_head_dir[k] = 2;
}
break;
}
case 3: //
Sprite_CheckDamageToAndFromLink(k);
if (sprite_delay_main[k] == sprite_B[k]) {
sprite_head_dir[k] = Sprite_IsRightOfLink(k).a;
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 32;
} else {
static const uint8 kStalfosKnight_Case2_Dir[16] = {0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 2};
sprite_head_dir[k] = kStalfosKnight_Case2_Dir[sprite_delay_main[k] >> 3];
sprite_C[k] = 0;
sprite_graphics[k] = 0;
}
break;
case 4: //
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 5;
sprite_delay_main[k] = 255;
sprite_delay_aux1[k] = 32;
}
sprite_C[k] = 1;
sprite_graphics[k] = 1;
break;
case 5: //
Sprite_CheckDamageToAndFromLink(k);
if (sprite_delay_aux1[k] == 0) {
Sprite_MoveXYZ(k);
Sprite_CheckTileCollision(k);
if (!sign8(sprite_z_vel[k] + 64))
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k] - 1)) {
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
if (!sprite_delay_main[k])
goto SetToGround;
sprite_delay_aux1[k] = 16;
}
sprite_graphics[k] = sign8(sprite_z_vel[k] - 24) ? 2 : 0;
} else {
if (sprite_delay_aux1[k] == 1) {
sprite_z_vel[k] = 48;
Sprite_ApplySpeedTowardsLink(k, 16);
sprite_head_dir[k] = Sprite_IsRightOfLink(k).a;
SpriteSfx_QueueSfx3WithPan(k, 0x13);
}
sprite_C[k] = 1;
sprite_graphics[k] = 1;
}
break;
case 6: //
Sprite_MoveXYZ(k);
Sprite_CheckTileCollision(k);
if (!sign8(sprite_z_vel[k] + 64))
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k] - 1)) {
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
}
j = sprite_delay_main[k];
if (!j) {
if (GetRandomNumber() & 1)
goto SetToGround;
sprite_ai_state[k] = 7;
sprite_delay_main[k] = 80;
} else {
if (j >= 224 && (j & 3) == 0)
SpriteSfx_QueueSfx3WithPan(k, 0x14);
static const uint8 kStalfosKnight_Case6_C[32] = {
0, 4, 8, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 14, 12, 8, 4, 0,
};
sprite_C[k] = kStalfosKnight_Case6_C[j >> 3];
sprite_graphics[k] = 3;
sprite_head_dir[k] = 2;
}
break;
case 7: //
if (!sprite_delay_main[k]) {
SetToGround:
sprite_ai_state[k] = 2;
sprite_ignore_projectile[k] = 0;
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
sprite_delay_main[k] = 63;
} else {
static const uint8 kStalfosKnight_Case7_Gfx[2] = {1, 4};
sprite_graphics[k] = kStalfosKnight_Case7_Gfx[sprite_delay_main[k] >> 2 & 1];
}
break;
}
}
void StalfosKnight_Draw(int k) { // 9eae04
static const DrawMultipleData kStalfosKnight_Dmd[35] = {
{-4, -8, 0x0064, 0},
{-4, 0, 0x0061, 2},
{ 4, 0, 0x0062, 2},
{-3, 16, 0x0074, 0},
{11, 16, 0x4074, 0},
{-4, -7, 0x0064, 0},
{-4, 1, 0x0061, 2},
{ 4, 1, 0x0062, 2},
{-3, 16, 0x0065, 0},
{11, 16, 0x4065, 0},
{-4, -8, 0x0048, 2},
{ 4, -8, 0x0049, 2},
{-4, 8, 0x004b, 2},
{ 4, 8, 0x004c, 2},
{ 4, 8, 0x004c, 2},
{-4, 8, 0x0068, 2},
{ 4, 8, 0x0069, 2},
{ 4, 8, 0x0069, 2},
{ 4, 8, 0x0069, 2},
{ 4, 8, 0x0069, 2},
{12, -7, 0x4064, 0},
{-4, 1, 0x4062, 2},
{ 4, 1, 0x4061, 2},
{-3, 16, 0x0065, 0},
{11, 16, 0x4065, 0},
{12, -8, 0x4064, 0},
{-4, 0, 0x4062, 2},
{ 4, 0, 0x4061, 2},
{-3, 16, 0x0074, 0},
{11, 16, 0x4074, 0},
{-4, -8, 0x4049, 2},
{ 4, -8, 0x4048, 2},
{-4, 8, 0x404c, 2},
{ 4, 8, 0x404b, 2},
{ 4, 8, 0x404b, 2},
};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
SpriteDraw_StalfosKnight_Head(k, &info);
oam_cur_ptr += 4, oam_ext_cur_ptr += 1;
Sprite_DrawMultiple(k, &kStalfosKnight_Dmd[sprite_graphics[k] * 5], 5, &info);
oam_cur_ptr -= 4, oam_ext_cur_ptr -= 1;
SpriteDraw_Shadow_custom(k, &info, 18);
}
void SpriteDraw_StalfosKnight_Head(int k, PrepOamCoordsRet *info) { // 9eae4e
static const uint8 kStalfosKnight_DrawHead_Char[4] = {0x66, 0x66, 0x46, 0x46};
static const uint8 kStalfosKnight_DrawHead_Flags[4] = {0x40, 0, 0, 0};
if (sprite_graphics[k] == 2)
return;
int i = sprite_head_dir[k];
OamEnt *oam = GetOamCurPtr();
oam->x = info->x;
oam->y = ClampYForOam(info->y + sprite_C[k] - 12);
oam->charnum = kStalfosKnight_DrawHead_Char[i];
oam->flags = info->flags | kStalfosKnight_DrawHead_Flags[i];
bytewise_extended_oam[oam - oam_buf] = 2 | (info->x >> 8 & 1);
}
void Sprite_90_Wallmaster(int k) { // 9eaea4
sprite_obj_prio[k] |= 0x30;
WallMaster_Draw(k);
if (sprite_state[k] != 9) {
flag_is_link_immobilized = 0;
link_disable_sprite_damage = 0;
}
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_A[k]) {
link_x_coord = Sprite_GetX(k);
link_y_coord = Sprite_GetY(k) - sprite_z[k] + 3;
flag_is_link_immobilized = 1;
link_disable_sprite_damage = 1;
link_incapacitated_timer = 0;
link_actual_vel_x = link_actual_vel_y = 0;
link_y_vel = link_x_vel = 0;
if ((uint16)(link_y_coord - BG2VOFS_copy2 - 16) >= 0x100) {
flag_is_link_immobilized = 0;
link_disable_sprite_damage = 0;
WallMaster_SendPlayerToLastEntrance();
Link_Initialize();
return;
}
} else {
Sprite_CheckDamageFromLink(k);
}
switch(sprite_ai_state[k]) {
case 0: { // Descend
uint8 old_z = sprite_z[k];
Sprite_MoveZ(k);
if (!sign8(sprite_z_vel[k] + 64))
sprite_z_vel[k] -= 3;
if (sign8(old_z ^ sprite_z[k]) && sign8(sprite_z[k])) {
sprite_ai_state[k] = 1;
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
sprite_delay_main[k] = 63;
}
break;
}
case 1: // Attempt Grab
if (!sprite_delay_main[k])
sprite_ai_state[k] = 2;
sprite_graphics[k] = (sprite_delay_main[k] & 0x20) ? 0 : 1;
if (Sprite_CheckDamageToLink(k)) {
sprite_A[k] = 1;
sprite_flags3[k] = 64;
SpriteSfx_QueueSfx3WithPan(k, 0x2a);
}
break;
case 2: { // Ascend
uint8 old_z = sprite_z[k];
Sprite_MoveZ(k);
if (sign8(sprite_z_vel[k] - 64))
sprite_z_vel[k] += 2;
if (sign8(old_z ^ sprite_z[k]) && !sign8(sprite_z[k])) {
sprite_state[k] = 0;
}
break;
}
}
}
void WallMaster_Draw(int k) { // 9eafe4
static const DrawMultipleData kWallMaster_Dmd[8] = {
{-4, 0, 0x01a6, 2},
{12, 0, 0x01aa, 0},
{-4, 16, 0x01ba, 0},
{ 4, 8, 0x01a8, 2},
{-4, 0, 0x01ab, 2},
{12, 0, 0x01af, 0},
{-4, 16, 0x01bf, 0},
{ 4, 8, 0x01ad, 2},
};
Sprite_DrawMultiple(k, &kWallMaster_Dmd[sprite_graphics[k] * 4], 4, NULL);
Sprite_DrawLargeShadow2(k);
}
void Sprite_8F_Blob(int k) { // 9eb002
if (sprite_state[k] == 9 && sprite_E[k]) {
sprite_E[k] = 0;
sprite_x_vel[k] = 1;
uint8 t = Sprite_CheckTileCollision(k);
sprite_x_vel[k] = 0;
if (t) {
sprite_state[k] = 0;
return;
}
SpriteSfx_QueueSfx2WithPan(k, 0x20);
}
if (sprite_C[k])
sprite_obj_prio[k] = 0x30;
Zol_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_ai_state[k] >= 2) {
Sprite_CheckDamageFromLink(k);
}
if (Sprite_ReturnIfRecoiling(k))
return;
switch(sprite_ai_state[k]) {
case 0: { // hiding unseen
uint8 bak = sprite_flags4[k];
sprite_flags4[k] |= 9;
sprite_flags2[k] |= 0x80;
uint8 t = Sprite_CheckDamageToLink(k);
sprite_flags4[k] = bak;
if (t) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 127;
sprite_flags2[k] &= ~0x80;
Sprite_SetX(k, link_x_coord);
Sprite_SetY(k, link_y_coord + 8);
sprite_delay_aux4[k] = 48;
sprite_ignore_projectile[k] = 0;
}
break;
}
case 1: { // popping out
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_z_vel[k] = 32;
Sprite_ApplySpeedTowardsLink(k, 16);
SpriteSfx_QueueSfx3WithPan(k, 0x30);
} else {
static const int8 kZol_PoppingOutGfx[16] = {0, 1, 7, 7, 6, 6, 5, 5, 6, 6, 5, 5, 4, 4, 4, 4};
sprite_graphics[k] = kZol_PoppingOutGfx[sprite_delay_main[k] >> 3];
}
break;
}
case 2: { // falling
if (sprite_delay_main[k] == 0) {
Sprite_CheckDamageFromLink(k);
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
uint8 oldz = sprite_z[k];
Sprite_MoveZ(k);
if (!sign8(sprite_z_vel[k] + 64))
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k] ^ oldz) && sign8(sprite_z[k])) {
sprite_z_vel[k] = 0;
sprite_z[k] = 0;
sprite_C[k] = 0;
sprite_delay_main[k] = 31;
sprite_head_dir[k] = 8;
}
} else if (sprite_delay_main[k] == 1) {
sprite_delay_main[k] = 32;
sprite_ai_state[k]++;
sprite_graphics[k] = 0;
} else {
static const int8 kZol_FallingXvel[2] = {-8, 8};
static const int8 kZol_FallingGfx[2] = {0, 1};
sprite_graphics[k] = kZol_FallingGfx[(sprite_delay_main[k] - 1) >> 4];
sprite_x_vel[k] = kZol_FallingXvel[frame_counter >> 1 & 1];
Sprite_MoveX(k);
}
break;
}
case 3: // active
Sprite_CheckDamageToLink(k);
if (!sprite_delay_aux1[k]) {
Sprite_ApplySpeedTowardsLink(k, 48);
sprite_delay_aux1[k] = GetRandomNumber() & 63 | 96;
sprite_oam_flags[k] = sprite_oam_flags[k] & 0x3f | (sign8(sprite_x_vel[k]) ? 0x40 : 0);
}
if (!sprite_delay_aux2[k]) {
sprite_subtype2[k]++;
if (!(sprite_subtype2[k] & 14 | sprite_wallcoll[k])) {
Sprite_MoveXY(k);
if (++sprite_G[k] == sprite_head_dir[k]) {
sprite_G[k] = 0;
sprite_delay_aux2[k] = (GetRandomNumber() & 31) + 64;
sprite_head_dir[k] = GetRandomNumber() & 31 | 16;
}
}
Sprite_CheckTileCollision(k);
sprite_graphics[k] = (sprite_subtype2[k] & 8) >> 3;
} else {
sprite_graphics[k] = sprite_delay_aux2[k] & 0x10 ? 1 : 0;
}
break;
}
}
void Zol_Draw(int k) { // 9eb1c5
PrepOamCoordsRet info;
if (!(sprite_oam_flags[k] & 1) && byte_7E0FC6 >= 3)
return;
if (sprite_delay_aux4[k])
Oam_AllocateFromRegionB(8);
if (!sprite_ai_state[k]) {
Sprite_PrepOamCoord(k, &info);
return;
}
uint8 gfx = sprite_graphics[k];
if (gfx < 4) {
static const uint8 kZol_OamFlags[4] = {0, 0, 0x40, 0x40};
uint8 bak1 = sprite_oam_flags[k];
sprite_oam_flags[k] = bak1 ^ kZol_OamFlags[gfx];
sprite_graphics[k] = gfx + ((sprite_oam_flags[k] & 1 ^ 1) << 2);
SpriteDraw_SingleLarge(k);
sprite_graphics[k] = gfx;
sprite_oam_flags[k] = bak1;
} else {
static const DrawMultipleData kZol_Dmd[8] = {
{0, 8, 0x036c, 0},
{8, 8, 0x036d, 0},
{0, 8, 0x0060, 0},
{8, 8, 0x0070, 0},
{0, 8, 0x4070, 0},
{8, 8, 0x4060, 0},
{0, 0, 0x0040, 2},
{0, 0, 0x0040, 2},
};
Sprite_DrawMultiple(k, &kZol_Dmd[(gfx - 4) * 2], 2, NULL);
}
}
void Sprite_8E_Terrorpin(int k) { // 9eb26f
int j;
static const int8 kTerrorpin_Xvel[8] = {8, -8, 0, 0, 12, -12, 0, 0};
static const int8 kTerrorpin_Yvel[8] = {0, 0, 8, -8, 0, 0, 12, -12};
static const uint8 kTerrorpin_Oamflags[2] = {0, 0x40};
static const int8 kTerrorpin_Overturned_Xvel[2] = {8, -8};
SpriteDraw_SingleLarge(k);
Sprite_CheckTileCollision(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
if (!sprite_delay_aux2[k])
Sprite_CheckDamageFromLink(k);
Terrorpin_CheckForHammer(k);
Sprite_MoveXYZ(k);
switch (sprite_B[k]) {
case 0: // upright
if (!sprite_delay_aux4[k]) {
sprite_delay_aux4[k] = (GetRandomNumber() & 31) + 32;
sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
}
j = sprite_D[k] + sprite_G[k];
sprite_x_vel[k] = kTerrorpin_Xvel[j];
sprite_y_vel[k] = kTerrorpin_Yvel[j];
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
}
sprite_graphics[k] = frame_counter >> (sprite_G[k] ? 2 : 3) & 1;
sprite_flags3[k] |= 64;
sprite_defl_bits[k] = 4;
Sprite_CheckDamageToLink(k);
break;
case 1: // overturned
sprite_flags3[k] &= 191;
sprite_defl_bits[k] = 0;
if (!sprite_delay_aux4[k]) {
sprite_B[k] = 0;
sprite_z_vel[k] = 32;
sprite_delay_aux4[k] = 64;
return;
}
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
uint8 t = (uint8)-sprite_z_vel[k] >> 1;
sprite_z_vel[k] = (t < 9) ? 0 : t;
sprite_x_vel[k] = (int8)sprite_x_vel[k] >> 1;
if (sprite_x_vel[k] == 0xff)
sprite_x_vel[k] = 0;
sprite_y_vel[k] = (int8)sprite_y_vel[k] >> 1;
if (sprite_y_vel[k] == 0xff)
sprite_y_vel[k] = 0;
}
if (sprite_delay_aux4[k] < 64) {
sprite_x_vel[k] = kTerrorpin_Overturned_Xvel[sprite_delay_aux4[k] >> 1 & 1];
sprite_subtype2[k]++;
}
sprite_graphics[k] = 2;
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kTerrorpin_Oamflags[++sprite_subtype2[k] >> 3 & 1];
break;
}
}
void Terrorpin_CheckForHammer(int k) { // 9eb3a3
if (!(sprite_z[k] | sprite_delay_aux2[k]) &&
sprite_floor[k] == link_is_on_lower_level &&
player_oam_y_offset != 0x80 &&
link_item_in_hand & 0xa) {
SpriteHitBox hb;
Player_SetupActionHitBox(&hb);
Terrorpin_SetUpHammerHitBox(k, &hb);
if (CheckIfHitBoxesOverlap(&hb)) {
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_y_vel[k] = -sprite_y_vel[k];
sprite_delay_aux2[k] = 32;
sprite_z_vel[k] = 32;
sprite_G[k] = 4;
sprite_B[k] ^= 1;
sprite_delay_aux4[k] = sprite_B[k] ? 0xff : 0x40;
}
}
sprite_head_dir[k] = 0;
}
void Terrorpin_SetUpHammerHitBox(int k, SpriteHitBox *hb) { // 9eb405
int x = Sprite_GetX(k) - 16;
int y = Sprite_GetY(k) - 16;
hb->r4_spr_xlo = x;
hb->r10_spr_xhi = x >> 8;
hb->r5_spr_ylo = y;
hb->r11_spr_yhi = y >> 8;
hb->r6_spr_xsize = hb->r7_spr_ysize = 48;
}
void Sprite_8C_Arrghus(int k) { // 9eb433
static const uint8 kArrghus_Gfx[9] = {1, 1, 1, 2, 2, 1, 1, 0, 0};
sprite_obj_prio[k] |= 0x30;
Arrghus_Draw(k);
if (sprite_state[k] != 9 || sprite_z[k] < 96) {
if (Sprite_ReturnIfInactive(k))
return;
}
Arrghus_HandlePuffs(k);
overlord_x_lo[4] = 1;
if ((sprite_hit_timer[k] & 127) == 2) {
sprite_ai_state[k] = 3;
SpriteSfx_QueueSfx3WithPan(k, 0x32);
sprite_subtype2[k] = 0;
sprite_flags3[k] = 64;
}
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToLink(k);
if (!(sprite_subtype2[k]++ & 3)) {
if (++sprite_G[k] == 9)
sprite_G[k] = 0;
sprite_graphics[k] = kArrghus_Gfx[sprite_G[k]];
}
uint8 a = Sprite_CheckTileCollision(k);
if (a) {
if (sprite_ai_state[k] == 5) {
if (a & 3)
sprite_x_vel[k] = -sprite_x_vel[k];
else
sprite_y_vel[k] = -sprite_y_vel[k];
} else {
Sprite_ZeroVelocity_XY(k);
}
}
switch (sprite_ai_state[k]) {
case 0: // approach speed
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 48;
}
Sprite_MoveXY(k);
Sprite_ApproachTargetSpeed(k, sprite_head_dir[k], sprite_D[k]);
break;
case 1: // decelerate
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
if (!Sprite_CheckIfScreenIsClear()) {
if (++overlord_x_lo[3] == 4) {
overlord_x_lo[3] = 0;
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 176;
} else {
sprite_delay_main[k] = (GetRandomNumber() & 63) + 48;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, (sprite_delay_main[k] & 3) + 8);
sprite_head_dir[k] = pt.x;
sprite_D[k] = pt.y;
}
} else {
sprite_ai_state[k] = 3;
SpriteSfx_QueueSfx3WithPan(k, 0x32);
sprite_subtype2[k] = 0;
}
} else {
Sprite_MoveXY(k);
Sprite_ApproachTargetSpeed(k, 0, 0);
}
break;
case 2: // case2
overlord_x_lo[4] = 8;
if (sprite_delay_main[k] < 32) {
if (sign8(--overlord_x_lo[2])) {
overlord_x_lo[2] = 0;
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 112;
}
} else if (sprite_delay_main[k] < 96) {
overlord_x_lo[2]++;
} else if (sprite_delay_main[k] == 96) {
SpriteSfx_QueueSfx3WithPan(k, 0x26);
} else if ((sprite_delay_main[k] & 0xf) == 0) {
SpriteSfx_QueueSfx3WithPan(k, 0x6);
}
break;
case 3: // jump way up
sprite_z_vel[k] = 120;
Sprite_MoveZ(k);
if (sprite_z[k] >= 224) {
sprite_delay_main[k] = 64;
sprite_ai_state[k] = 4;
sprite_z_vel[k] = 0;
sprite_x_lo[k] = link_x_coord;
sprite_y_lo[k] = link_y_coord;
}
break;
case 4: { // swoosh from above
if (!(a = sprite_delay_main[k])) {
sprite_z_vel[k] = 144;
uint8 old_z = sprite_z[k];
Sprite_MoveZ(k);
if (sign8(a = old_z ^ sprite_z[k]) && sign8(a = sprite_z[k])) {
sprite_z[k] = 0;
Sprite_SpawnBigSplash(k);
sprite_ai_state[k] = 5;
sprite_delay_main[k] = 32;
SpriteSfx_QueueSfx3WithPan(k, 0x3);
sprite_x_vel[k] = 32;
sprite_y_vel[k] = 32;
}
}
if (a == 1) { // wtf
SpriteSfx_QueueSfx2WithPan(k, 0x20);
}
break;
}
case 5: // swim frantically
if (!sprite_delay_main[k]) {
sprite_flags3[k] = 0;
Sprite_MoveXY(k);
Sprite_CheckDamageFromLink(k);
if (!(frame_counter & 7)) {
SpriteSfx_QueueSfx2WithPan(k, 0x28);
int j = GarnishAllocLimit(sign8(sprite_y_vel[k]) ? 29 : 14);
if (j >= 0) {
garnish_type[j] = 21;
garnish_active = 21;
garnish_x_lo[j] = sprite_x_lo[k];
garnish_x_hi[j] = sprite_x_hi[k];
garnish_y_lo[j] = sprite_y_lo[k] + 24; // why no carry propagation
garnish_y_hi[j] = sprite_y_hi[k];
garnish_countdown[j] = 15;
}
}
}
break;
}
}
void Arrghus_Draw(int k) { // 9eb840
static const DrawMultipleData kArrghus_Dmd[5] = {
{-8, -4, 0x0080, 2},
{ 8, -4, 0x4080, 2},
{-8, 12, 0x00a0, 2},
{ 8, 12, 0x40a0, 2},
{ 0, 24, 0x00a8, 2},
};
Sprite_DrawMultiple(k, kArrghus_Dmd, 5, NULL);
OamEnt *oam = GetOamCurPtr();
uint8 chr = sprite_graphics[k] * 2;
for (int i = 0; i < 4; i++)
oam[i].charnum += chr;
if (sprite_ai_state[k] == 5)
oam[4].y = 0xf0;
if (sprite_subtype2[k] & 8)
oam[4].flags |= 0x40;
if (sprite_ai_state[k] != 5) {
oam_cur_ptr += 4, oam_ext_cur_ptr += 1;
if (sprite_z[k] < 0xa0) {
uint8 bak = sprite_oam_flags[k];
sprite_oam_flags[k] &= ~1;
SpriteDraw_BigShadow(k, 0);
sprite_oam_flags[k] = bak;
}
} else {
Sprite_DrawLargeWaterTurbulence(k);
}
}
void Arrghus_HandlePuffs(int k) { // 9eb8b4
static const uint16 kArrgi_Tab0[13] = {0, 0x40, 0x80, 0xc0, 0x100, 0x140, 0x180, 0x1c0, 0, 0x66, 0xcc, 0x132, 0x198};
static const uint16 kArrgi_Tab1[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0x1ff, 0x1ff, 0x1ff, 0x1ff, 0x1ff};
static const uint8 kArrgi_Tab2[13] = {0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xc, 0xc, 0xc, 0xc, 0xc};
static const int8 kArrgi_Tab3[52] = {
0, -1, -2, -3, -4, -5, -6, -6, -5, -4, -3, -2, -1, 0, -1, -2,
-3, -4, -5, -6, -6, -5, -4, -3, -2, -1, 0, -1, -2, -3, -4, -5,
-6, -6, -5, -4, -3, -2, -1, 0, -1, -2, -3, -4, -5, -6, -6, -5,
-4, -3, -2, -1,
};
WORD(overlord_x_lo[0]) += overlord_x_lo[4];
if (!(frame_counter & 3) && ++sprite_A[k] == 13)
sprite_A[k] = 0;
if (!(frame_counter & 7) && ++sprite_B[k] == 13)
sprite_B[k] = 0;
for(int i = 0; i != 13; i++) {
uint16 r0 = (WORD(overlord_x_lo[0]) + kArrgi_Tab0[i]) ^ kArrgi_Tab1[i];
uint8 r14 = overlord_x_lo[2] + kArrgi_Tab2[i];
int8 sin_val = ArrgiSin(r0 + 0x00, r14 + kArrgi_Tab3[sprite_A[k] + i]);
int8 cos_val = ArrgiSin(r0 + 0x80, r14 + kArrgi_Tab3[sprite_B[k] + i]);
int tx = Sprite_GetX(k) + sin_val;
overlord_x_hi[i] = tx;
overlord_y_hi[i] = tx >> 8;
int ty = Sprite_GetY(k) + cos_val - 0x10;
overlord_gen2[i] = ty;
overlord_floor[i] = ty >> 8;
}
tmp_counter = 13;
}
void Sprite_8D_Arrghi(int k) { // 9eb8c4
static const uint8 kArrgi_Gfx[8] = {0, 1, 2, 2, 2, 2, 2, 1};
sprite_obj_prio[k] |= 0x30;
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_graphics[k] = kArrgi_Gfx[++sprite_subtype2[k] >> 3 & 7];
if (sprite_B[k]) {
int j = sprite_B[k] - 1;
if (ancilla_type[j]) {
sprite_x_lo[k] = ancilla_x_lo[j];
sprite_x_hi[k] = ancilla_x_hi[j];
sprite_y_lo[k] = ancilla_y_lo[j];
sprite_y_hi[k] = ancilla_y_hi[j];
sprite_oam_flags[k] = 5;
sprite_flags3[k] &= ~0x40;
return;
}
sprite_ai_state[k] = 1;
sprite_B[k] = 0;
sprite_delay_main[k] = 32;
}
if (!sprite_delay_main[k])
Sprite_CheckDamageToLink(k);
if (!sprite_ai_state[k]) {
sprite_x_lo[k] = overlord_x_lo[k + 7];
sprite_x_hi[k] = overlord_y_lo[k + 7];
sprite_y_lo[k] = overlord_gen1[k + 7];
sprite_y_hi[k] = overlord_gen3[k + 7];
return;
}
Sprite_CheckDamageFromLink(k);
if (!((k ^ frame_counter) & 3)) {
uint16 x = overlord_y_lo[k + 7] << 8 | overlord_x_lo[k + 7];
uint16 y = overlord_gen3[k + 7] << 8 | overlord_gen1[k + 7];
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 4);
sprite_y_vel[k] = pt.y;
sprite_x_vel[k] = pt.x;
if ((uint8)(sprite_x_lo[k] - overlord_x_lo[k + 7] + 8) < 16 && (uint8)(sprite_y_lo[k] - overlord_gen1[k + 7] + 8) < 16) {
sprite_ai_state[k] = 0;
sprite_oam_flags[k] = 0xd;
sprite_flags3[k] |= 0x40;
}
}
Sprite_MoveXY(k);
}
void Sprite_8B_Gibdo(int k) { // 9eb9a9
Gibdo_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
switch(sprite_ai_state[k]) {
case 0: {
static const uint8 kGibdo_DirTarget[4] = {2, 6, 4, 0};
static const uint8 kGibdo_Gfx[8] = {4, 8, 11, 10, 0, 6, 3, 7};
sprite_graphics[k] = kGibdo_Gfx[sprite_D[k]];
if (!(frame_counter & 7)) {
int j = sprite_A[k];
if (sprite_D[k] - kGibdo_DirTarget[j]) {
sprite_D[k] += sign8(sprite_D[k] - kGibdo_DirTarget[j]) ? 1 : -1;
} else {
sprite_delay_main[k] = (GetRandomNumber() & 31) + 48;
sprite_ai_state[k] = 1;
}
}
break;
}
case 1: {
static const int8 kGibdo_XyVel[10] = {-16, 0, 0, 0, 16, 0, 0, 0, -16, 0};
static const uint8 kGibdo_Gfx2[8] = {9, 2, 0, 4, 11, 3, 1, 5};
int j = sprite_D[k];
sprite_x_vel[k] = kGibdo_XyVel[j + 2];
sprite_y_vel[k] = kGibdo_XyVel[j];
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
if ((!sprite_delay_main[k] || sprite_wallcoll[k]) && (j = Sprite_DirectionToFaceLink(k, NULL)) != sprite_A[k]) {
sprite_A[k] = j;
sprite_ai_state[k] = 0;
} else {
if (sign8(--sprite_B[k])) {
sprite_B[k] = 14;
sprite_subtype2[k]++;
}
sprite_graphics[k] = kGibdo_Gfx2[(sprite_subtype2[k] & 1) << 2 | sprite_A[k]];
}
break;
}
}
}
void Gibdo_Draw(int k) { // 9ebb20
static const DrawMultipleData kGibdo_Dmd[24] = {
{0, -9, 0x0080, 2},
{0, 0, 0x008a, 2},
{0, -8, 0x0080, 2},
{0, 1, 0x408a, 2},
{0, -9, 0x0082, 2},
{0, 0, 0x008c, 2},
{0, -8, 0x0082, 2},
{0, 0, 0x008e, 2},
{0, -9, 0x0084, 2},
{0, 0, 0x00a0, 2},
{0, -8, 0x0084, 2},
{0, 1, 0x40a0, 2},
{0, -9, 0x0086, 2},
{0, 0, 0x00a2, 2},
{0, -9, 0x0088, 2},
{0, 0, 0x00a4, 2},
{0, -9, 0x4088, 2},
{0, 0, 0x40a4, 2},
{0, -9, 0x4082, 2},
{0, 0, 0x408c, 2},
{0, -9, 0x4086, 2},
{0, 0, 0x40a2, 2},
{0, -8, 0x4082, 2},
{0, 1, 0x408e, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kGibdo_Dmd[sprite_graphics[k] * 2], 2, &info);
if (!sprite_pause[k])
SpriteDraw_Shadow(k, &info);
}
void Sprite_89_MothulaBeam(int k) { // 9ebb42
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToLink(k);
if (!(frame_counter & 1))
sprite_oam_flags[k] ^= 0x80;
Sprite_MoveXY(k);
if (!sprite_delay_main[k] && Sprite_CheckTileCollision(k))
sprite_state[k] = 0;
if ((k ^ frame_counter) & 3)
return;
for (int i = 14; i >= 0; i--) {
if (garnish_type[i] == 0) {
garnish_type[i] = 2;
garnish_active = 2;
garnish_x_lo[i] = sprite_x_lo[k];
garnish_x_hi[i] = sprite_x_hi[k];
garnish_y_lo[i] = sprite_y_lo[k];
garnish_y_hi[i] = sprite_y_hi[k];
garnish_countdown[i] = 16;
garnish_sprite[i] = k;
garnish_floor[i] = sprite_floor[k];
break;
}
}
}
void Sprite_94_Tile(int k) { // 9ebbb9
sprite_obj_prio[k] = 0x30;
FlyingTile_Draw(k);
if (Sprite_ReturnIfPaused(k))
return;
if (sprite_hit_timer[k])
goto lbl_a;
sprite_ignore_projectile[k] = 1;
switch (sprite_ai_state[k]) {
case 0: // erase tilemap
Dungeon_UpdateTileMapWithCommonTile(Sprite_GetX(k), (sprite_y_lo[k] + 8) & 0xff | (sprite_y_hi[k] << 8), 6);
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 128;
break;
case 1: // rise up
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 16;
Sprite_ApplySpeedTowardsLink(k, 32);
} else {
if (sprite_delay_main[k] >= 0x40) {
sprite_z_vel[k] = 4;
Sprite_MoveZ(k);
}
lbl_b:
sprite_graphics[k] = ++sprite_subtype2[k] >> 2 & 1;
if (!((k ^ frame_counter) & 7))
SpriteSfx_QueueSfx2WithPan(k, 0x7);
}
break;
case 2: // towards player
sprite_ignore_projectile[k] = 0;
if (sprite_delay_main[k] && (sprite_delay_main[k] & 3) == 0)
Sprite_ApplySpeedTowardsLink(k, 32);
if (!Sprite_CheckDamageToAndFromLink(k)) {
Sprite_MoveXY(k);
cur_sprite_y -= sprite_z[k];
if (!Sprite_CheckTileCollision(k))
goto lbl_b;
}
lbl_a:
SpriteSfx_QueueSfx2WithPan(k, 0x1f);
sprite_state[k] = 6;
sprite_delay_main[k] = 31;
sprite_type[k] = 0xec;
sprite_hit_timer[k] = 0;
sprite_C[k] = 0x80;
break;
}
}
void FlyingTile_Draw(int k) { // 9ebcca
static const DrawMultipleData kFlyingTile_Dmd[8] = {
{0, 0, 0x00d3, 0},
{8, 0, 0x40d3, 0},
{0, 8, 0x80d3, 0},
{8, 8, 0xc0d3, 0},
{0, 0, 0x00c3, 0},
{8, 0, 0x40c3, 0},
{0, 8, 0x80c3, 0},
{8, 8, 0xc0c3, 0},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kFlyingTile_Dmd[sprite_graphics[k] * 4], 4, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_8A_SpikeBlock(int k) { // 9ebce8
if (!sprite_E[k]) {
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
if (!sprite_delay_main[k] && (!SpikeBlock_CheckStatueCollision(k) || (sprite_wallcoll[k] & 0xf))) {
sprite_delay_main[k] = 4;
sprite_x_vel[k] = -sprite_x_vel[k];
SpriteSfx_QueueSfx2WithPan(k, 0x5);
}
return;
}
Oam_AllocateFromRegionB(4);
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
if (sprite_ai_state[k] == 0) {
Dungeon_UpdateTileMapWithCommonTile(Sprite_GetX(k), Sprite_GetY(k), 0);
sprite_ai_state[k] = 1;
sprite_delay_main[k] = 64;
sprite_delay_aux1[k] = 105;
} else if (sprite_delay_main[k] != 0) {
if (sprite_delay_main[k] == 1) {
sprite_x_lo[k] = sprite_A[k];
sprite_y_lo[k] = sprite_B[k];
} else {
sprite_x_vel[k] = (sprite_delay_main[k] >> 1) & 1 ? -8 : 8;
Sprite_MoveX(k);
sprite_x_vel[k] = 0;
}
} else if (sprite_ai_state[k] == 1) {
static const int8 kSpikeBlock_XVelTarget[4] = {32, -32, 0, 0};
static const int8 kSpikeBlock_YVelTarget[4] = {0, 0, 32, -32};
static const int8 kSpikeBlock_XVelDelta[4] = {1, -1, 0, 0};
static const int8 kSpikeBlock_YVelDelta[4] = {0, 0, 1, -1};
int j = sprite_D[k];
if (sprite_x_vel[k] != (uint8)kSpikeBlock_XVelTarget[j])
sprite_x_vel[k] += kSpikeBlock_XVelDelta[j];
if (sprite_y_vel[k] != (uint8)kSpikeBlock_YVelTarget[j])
sprite_y_vel[k] += kSpikeBlock_YVelDelta[j];
Sprite_MoveXY(k);
if (!sprite_delay_aux1[k]) {
Sprite_Get16BitCoords(k);
if (Sprite_CheckTileCollision(k)) {
sprite_ai_state[k] = 2;
sprite_delay_aux1[k] = 64;
}
}
} else if (sprite_delay_aux1[k] == 0) {
static const int8 kSpikeBlock_XVel[4] = {-16, 16, 0, 0};
static const int8 kSpikeBlock_YVel[4] = {0, 0, -16, 16};
int j = sprite_D[k];
sprite_x_vel[k] = kSpikeBlock_XVel[j];
sprite_y_vel[k] = kSpikeBlock_YVel[j];
Sprite_MoveXY(k);
if (sprite_x_lo[k] == sprite_A[k] && sprite_y_lo[k] == sprite_B[k]) {
sprite_state[k] = 0;
Dungeon_UpdateTileMapWithCommonTile(Sprite_GetX(k), Sprite_GetY(k), 2);
}
}
}
bool SpikeBlock_CheckStatueCollision(int k) { // 9ebe19
for (int j = 15; j >= 0; j--) {
if (!((j ^ frame_counter) & 1) && sprite_state[j] && sprite_type[j] == 0x1c) {
int x0 = Sprite_GetX(k), y0 = Sprite_GetY(k);
int x1 = Sprite_GetX(j), y1 = Sprite_GetY(j);
if ((uint16)(x0 - x1 + 16) < 32 && (uint16)(y0 - y1 + 16) < 32)
return false;
}
}
return true;
}
void Sprite_88_Mothula(int k) { // 9ebe7e
if (enhanced_features0 & kFeatures0_MiscBugFixes) {
// L4 sword and L3 spin slash can now damage Mothula
enemy_damage_data[0x884] = 1;
enemy_damage_data[0x885] = 1;
}
Mothula_Main(k);
if (Sprite_ReturnIfInactive(k))
return;
Mothula_HandleSpikes(k);
}
void Mothula_Main(int k) { // 9ebe88
int j;
Mothula_Draw(k);
if (sprite_state[k] == 11)
sprite_ai_state[k] = 0;
if (Sprite_ReturnIfInactive(k))
return;
sprite_flags3[k] = 0;
if (sprite_delay_aux3[k])
sprite_flags3[k] = 64;
if ((sprite_F[k] & 127) == 6) {
sprite_F[k] = 0;
sprite_delay_aux3[k] = 32;
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 0;
sprite_G[k] = 64;
}
if (Sprite_ReturnIfRecoiling(k))
return;
switch(sprite_ai_state[k]) {
case 0: // Delay
if (!sprite_delay_main[k])
sprite_ai_state[k] = 1;
break;
case 1: // Ascend
sprite_z_vel[k] = 8;
Sprite_MoveZ(k);
sprite_z_vel[k] = 0;
if (sprite_z[k] >= 24) {
sprite_G[k] = 128;
sprite_ai_state[k] = 2;
sprite_ignore_projectile[k] = 0;
sprite_delay_main[k] = 64;
}
Mothula_FlapWings(k);
break;
case 2: // FlyAbout
if (!sprite_G[k]) {
sprite_delay_main[k] = 63;
sprite_ai_state[k] = 3;
return;
}
sprite_G[k]--;
Mothula_FlapWings(k);
j = sprite_A[k] & 1;
sprite_z_vel[k] += j ? -1 : 1;
if (sprite_z_vel[k] == (uint8)(j ? -16 : 16))
sprite_A[k]++;
if (!sprite_delay_main[k]) {
if (++sprite_C[k] == 7) {
sprite_C[k] = 0;
Sprite_ApplySpeedTowardsLink(k, 32);
sprite_delay_main[k] = 128;
} else {
static const int8 kMothula_XYvel[10] = {-16, -12, 0, 12, 16, 12, 0, -12, -16, -12};
j = GetRandomNumber() & 7;
sprite_x_vel[k] = kMothula_XYvel[j + 2];
sprite_y_vel[k] = kMothula_XYvel[j];
sprite_delay_main[k] = (GetRandomNumber() & 31) + 64;
}
}
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_MoveZ(k);
if (Sprite_CheckTileCollision(k))
sprite_delay_main[k] = 0;
Sprite_CheckDamageToAndFromLink(k);
sprite_subtype2[k] += 2;
break;
case 3: // FireBeams
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k]) {
sprite_ai_state[k]--;
sprite_G[k] = GetRandomNumber() & 31 | 64;
} else {
if (sprite_delay_main[k] == 0x20)
Mothula_SpawnBeams(k);
Mothula_FlapWings(k);
}
break;
}
}
void Mothula_FlapWings(int k) { // 9ebf9f
static const uint8 kMothula_FlapWingsGfx[4] = {0, 1, 2, 1};
int j = ++sprite_subtype2[k] >> 2 & 3;
if (j == 0)
SpriteSfx_QueueSfx3WithPan(k, 0x2);
sprite_graphics[k] = kMothula_FlapWingsGfx[j];
}
void Mothula_SpawnBeams(int k) { // 9ebfdf
static const int8 kMothula_Beam_Xvel[3] = {-16, 0, 16};
static const int8 kMothula_Beam_Yvel[3] = {24, 32, 24};
SpriteSfx_QueueSfx3WithPan(k, 0x36);
for (int i = 2; i >= 0; i--) {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x89, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_y_lo[j] = info.r2_y - info.r4_z + 3;
sprite_delay_main[j] = 16;
sprite_ignore_projectile[j] = 16;
sprite_x_lo[j] = info.r0_x + kMothula_Beam_Xvel[i];
sprite_x_vel[j] = kMothula_Beam_Xvel[i];
sprite_y_vel[j] = kMothula_Beam_Yvel[i];
sprite_z[j] = 0;
}
}
tmp_counter = 0xff;
}
void Mothula_HandleSpikes(int k) { // 9ec088
static const uint8 kMothula_Spike_XLo[30] = {
0x38, 0x48, 0x58, 0x68, 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xb8,
0xa8, 0x98, 0x78, 0x68, 0x58, 0x48, 0x38, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
};
static const uint8 kMothula_Spike_YLo[30] = {
0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x48, 0x58, 0x68, 0x78, 0x98, 0xa8, 0xb8, 0xc8,
0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xb8, 0xa8, 0x98, 0x78, 0x68, 0x58, 0x48,
};
static const uint8 kMothula_Spike_Dir[30] = {
2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 3,
3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0,
};
if (--sprite_head_dir[k])
return;
sprite_head_dir[k] = 0x40;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x8a, &info);
if (j < 0)
return;
int i = GetRandomNumber() & 0x1f;
if (i >= 30) i -= 30;
sprite_A[j] = sprite_x_lo[j] = kMothula_Spike_XLo[i];
sprite_B[j] = sprite_y_lo[j] = kMothula_Spike_YLo[i] - 1;
sprite_D[j] = kMothula_Spike_Dir[i];
sprite_E[j] = 1;
sprite_x_hi[j] = byte_7E0FB0 + 1;
sprite_y_hi[j] = byte_7E0FB1 + 1;
sprite_x_vel[j] = 1;
Sprite_Get16BitCoords(j);
Sprite_CheckTileCollision(j);
sprite_x_vel[j] = 0;
sprite_x_lo[j] = sprite_A[j];
sprite_y_lo[j] = sprite_B[j];
if (!sprite_wallcoll[j]) {
sprite_state[j] = 0;
sprite_head_dir[k] = 1;
}
}
void Sprite_86_Kodongo(int k) { // 9ec103
static const int8 kKodondo_Xvel[4] = {1, -1, 0, 0};
static const int8 kKodondo_Yvel[4] = {0, 0, 1, -1};
static const uint8 kKodondo_Gfx[8] = {2, 2, 0, 5, 3, 3, 0, 5};
static const uint8 kKodondo_OamFlags[8] = {0x40, 0, 0, 0, 0x40, 0, 0x40, 0x40};
static const uint8 kKodondo_FlameGfx[8] = {2, 2, 0, 5, 4, 4, 1, 6};
int j;
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_flags[k] = 0;
switch(sprite_ai_state[k]) {
case 0: // choose dir
sprite_ai_state[k]++;
sprite_D[k] = GetRandomNumber() & 3;
sprite_flags[k] = 176;
for(;;) {
j = sprite_D[k];
sprite_x_vel[k] = kKodondo_Xvel[j];
sprite_y_vel[k] = kKodondo_Yvel[j];
if (!Sprite_CheckTileCollision(k))
break;
sprite_D[k] = (sprite_D[k] + 1) & 3;
}
Kodongo_SetDirection(k);
break;
case 1: // move
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k)) {
sprite_D[k] ^= 1;
Kodongo_SetDirection(k);
}
if ((sprite_x_lo[k] & 0x1f) == 4 && (sprite_y_lo[k] & 0x1f) == 0x1b && (GetRandomNumber() & 3) == 0) {
sprite_delay_main[k] = 111;
sprite_ai_state[k] = 2;
sprite_A[k] = 0;
}
j = ++sprite_subtype2[k] & 4 | sprite_D[k];
sprite_graphics[k] = kKodondo_Gfx[j];
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kKodondo_OamFlags[j];
break;
case 2: // breathe flame
if (!sprite_delay_main[k])
sprite_ai_state[k] = 0;
j = (uint8)(sprite_delay_main[k] - 0x20) < 0x30;
if (j && (sprite_delay_main[k] & 0xf) == 0)
Kodongo_SpawnFire(k);
sprite_graphics[k] = kKodondo_FlameGfx[j * 4 + sprite_D[k]];
break;
}
}
void Kodongo_SetDirection(int k) { // 9ec158
int j = sprite_D[k];
sprite_x_vel[k] = kFluteBoyAnimal_Xvel[j];
sprite_y_vel[k] = kZazak_Yvel[j];
}
void Kodongo_SpawnFire(int k) { // 9ec223
static const int8 kKodondo_Flame_X[4] = {8, -8, 0, 0};
static const int8 kKodondo_Flame_Y[4] = {0, 0, 8, -8};
static const int8 kKodondo_Flame_Xvel[4] = {24, -24, 0, 0};
static const int8 kKodondo_Flame_Yvel[4] = {0, 0, 24, -24};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0x87, &info, 13);
if (j >= 0) {
int i = sprite_D[k];
Sprite_SetX(j, info.r0_x + kKodondo_Flame_X[i]);
Sprite_SetY(j, info.r2_y + kKodondo_Flame_Y[i]);
sprite_x_vel[j] = kKodondo_Flame_Xvel[i];
sprite_y_vel[j] = kKodondo_Flame_Yvel[i];
sprite_ignore_projectile[j] = 1;
}
}
void Sprite_87_KodongoFire(int k) { // 9ec274
static const uint8 kFlame_OamFlags[4] = { 0, 0x40, 0xc0, 0x80 };
static const int8 kFlame_Gfx[32] = {
5, 4, 3, 1, 2, 0, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0,
1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0,
};
if (!sprite_delay_main[k]) {
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_oam_flags[k] = sprite_oam_flags[k] & 0x3f | kFlame_OamFlags[frame_counter >> 2 & 3];
if (!Sprite_CheckDamageToLink(k)) {
Sprite_MoveXY(k);
if (!Sprite_CheckTileCollision(k))
return;
}
sprite_delay_main[k] = 127;
sprite_oam_flags[k] &= 63;
SpriteSfx_QueueSfx2WithPan(k, 0x2a);
} else {
if (Sprite_CheckDamageFromLink(k) & kCheckDamageFromPlayer_Carry && !--sprite_delay_main[k] || sprite_delay_main[k] == 1)
sprite_state[k] = 0;
sprite_graphics[k] = kFlame_Gfx[sprite_delay_main[k] >> 3];
Flame_Draw(k);
Sprite_CheckDamageToLink(k);
}
}
void Flame_Draw(int k) { // 9ec35c
static const DrawMultipleData kFlame_Dmd[12] = {
{0, 0, 0x018e, 2},
{0, 0, 0x018e, 2},
{0, 0, 0x01a0, 2},
{0, 0, 0x01a0, 2},
{0, 0, 0x418e, 2},
{0, 0, 0x418e, 2},
{ 0, 0, 0x41a0, 2 },
{ 0, 0, 0x41a0, 2 },
{ 0, 0, 0x01a2, 2 },
{ 0, 0, 0x01a2, 2 },
{ 0, -6, 0x01a4, 0 },
{ 8, -6, 0x01a5, 0 },
};
Sprite_DrawMultiple(k, &kFlame_Dmd[sprite_graphics[k] * 2], 2, NULL);
}
void Sprite_85_YellowStalfos(int k) { // 9ec37f
static const int8 kYellowStalfos_ObjPrio[6] = {0x30, 0, 0, 0, 0x30, 0};
static const int8 kYellowStalfos_Gfx[32] = {
8, 5, 1, 1, 8, 5, 1, 1, 8, 5, 1, 1, 7, 4, 2, 2,
7, 4, 2, 2, 7, 4, 2, 2, 7, 4, 2, 2, 7, 4, 2, 2,
};
static const int8 kYellowStalfos_HeadX[32] = {
-0x80, -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, 0, 0, 0, 0,
0, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0, 0, 0, 0,
};
static const uint8 kYellowStalfos_HeadY[32] = {
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 12, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
};
static const int8 kYellowStalfos_NeutralizedGfx[16] = {1, 1, 1, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9};
static const int8 kYellowStalfos_NeutralizedHeadY[16] = {10, 10, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7};
int j;
if (!sprite_A[k]) {
sprite_x_vel[k] = 1;
sprite_y_vel[k] = 1;
if (Sprite_CheckTileCollision(k)) {
sprite_state[k] = 0;
return;
}
sprite_A[k]++;
sprite_C[k] = 10;
sprite_flags3[k] |= 64;
SpriteSfx_QueueSfx2WithPan(k, 0x20);
}
sprite_obj_prio[k] |= kYellowStalfos_ObjPrio[sprite_ai_state[k]];
YellowStalfos_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (link_sword_type >= 3) {
if (Sprite_ReturnIfRecoiling(k))
return;
} else if (sprite_ai_state[k] != 5 && sprite_hit_timer[k]) {
sprite_hit_timer[k] = 0;
sprite_ai_state[k] = 5;
sprite_delay_main[k] = 255;
}
sprite_ignore_projectile[k] = 1;
switch (sprite_ai_state[k]) {
case 0: { // descend
sprite_head_dir[k] = 2;
uint8 bak0 = sprite_z[k];
Sprite_MoveZ(k);
if (!sign8(sprite_z_vel[k] - 192))
sprite_z_vel[k] -= 3;
if (!sign8(bak0) && sign8(sprite_z[k])) {
sprite_ai_state[k]++;
sprite_z[k] = 0;
sprite_z_vel[k] = 0;
sprite_delay_main[k] = 64;
YellowStalfos_Animate(k);
}
break;
}
case 1: // face player
sprite_ignore_projectile[k] = 0;
Sprite_CheckDamageToAndFromLink(k);
sprite_head_dir[k] = sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 127;
}
sprite_flags3[k] &= ~0x40;
break;
case 2: // pause then detach head
sprite_ignore_projectile[k] = 0;
Sprite_CheckDamageToAndFromLink(k);
j = sprite_delay_main[k];
if (!j) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 64;
return;
}
if (j == 48)
YellowStalfos_EmancipateHead(k);
sprite_graphics[k] = kYellowStalfos_Gfx[j >> 2 & ~3 | sprite_D[k]];
j = sprite_delay_main[k] >> 2;
sprite_B[k] = kYellowStalfos_HeadX[j];
sprite_C[k] = kYellowStalfos_HeadY[j];
sprite_flags3[k] &= ~0x40;
break;
case 3: // delay before ascending
sprite_ignore_projectile[k] = 0;
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_delay_main[k])
sprite_ai_state[k]++;
YellowStalfos_Animate(k);
break;
case 4: // ascend
sprite_graphics[k] = 0;
sprite_head_dir[k] = 2;
j = sprite_z[k];
Sprite_MoveZ(k);
if (sign8(sprite_z_vel[k] - 64))
sprite_z_vel[k] += 2;
if (sign8(j) && !sign8(sprite_z[k]))
sprite_state[k] = 0;
break;
case 5: // neutralized
sprite_ignore_projectile[k] = 0;
Sprite_CheckDamageFromLink(k);
j = sprite_delay_main[k];
if (!j)
sprite_ai_state[k]--;
sprite_graphics[k] = kYellowStalfos_NeutralizedGfx[j >> 4];
sprite_C[k] = kYellowStalfos_NeutralizedHeadY[j >> 4];
break;
}
}
void YellowStalfos_Animate(int k) { // 9ec509
static const uint8 kYellowStalfos_Gfx2[4] = {6, 3, 1, 1};
sprite_graphics[k] = kYellowStalfos_Gfx2[sprite_D[k]];
sprite_flags3[k] &= ~0x40;
}
void YellowStalfos_EmancipateHead(int k) { // 9ec580
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 2, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_z[j] = 13;
Sprite_ApplySpeedTowardsLink(j, 16);
sprite_delay_main[j] = 255;
sprite_delay_aux1[j] = 32;
}
}
void YellowStalfos_Draw(int k) { // 9ec655
static const DrawMultipleData kYellowStalfos_Dmd[22] = {
{0, 0, 0x000a, 2},
{0, 0, 0x000a, 2},
{0, 0, 0x000c, 2},
{0, 0, 0x000c, 2},
{0, 0, 0x002c, 2},
{0, 0, 0x002c, 2},
{5, 5, 0x002e, 0},
{0, 0, 0x0024, 2},
{4, 1, 0x003e, 0},
{0, 0, 0x0024, 2},
{0, 0, 0x000e, 2},
{0, 0, 0x000e, 2},
{3, 5, 0x402e, 0},
{0, 0, 0x4024, 2},
{4, 1, 0x403e, 0},
{0, 0, 0x4024, 2},
{0, 0, 0x400e, 2},
{0, 0, 0x400e, 2},
{0, 0, 0x002a, 2},
{0, 0, 0x002a, 2},
{0, 0, 0x002a, 2},
{0, 0, 0x002a, 2},
};
oam_cur_ptr += 4, oam_ext_cur_ptr++;
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kYellowStalfos_Dmd[sprite_graphics[k] * 2], 2, &info);
oam_cur_ptr -= 4, oam_ext_cur_ptr--;
if (!sprite_pause[k]) {
YellowStalfos_DrawHead(k, &info);
SpriteDraw_Shadow(k, &info);
}
}
void YellowStalfos_DrawHead(int k, PrepOamCoordsRet *info) { // 9ec69a
static const uint8 kYellowStalfos_Head_Char[4] = {2, 2, 0, 4};
static const uint8 kYellowStalfos_Head_Flags[4] = {0x40, 0, 0, 0};
OamEnt *oam = GetOamCurPtr();
if (sprite_graphics[k] == 10 || sprite_B[k] == 0x80)
return;
uint16 x = info->x + (int8)sprite_B[k];
uint16 y = info->y - sprite_C[k];
int j = sprite_head_dir[k];
oam->x = x;
oam->y = ClampYForOam(y);
oam->charnum = kYellowStalfos_Head_Char[j];
oam->flags = kYellowStalfos_Head_Flags[j] | info->flags;
bytewise_extended_oam[oam - oam_buf] = 2 | (x >> 8 & 1);
}
void SpritePrep_Eyegore(int k) { // 9ec700
uint8 t = BYTE(dungeon_room_index2);
if (t == 12 || t == 27 || t == 75 || t == 107) {
sprite_B[k]++;
if (sprite_type[k] == 0x83)
sprite_defl_bits[k] = 0;
}
}
void Sprite_83_GreenEyegore(int k) { // 9ec79b
static const int8 kGoriya_Xvel[32] = {
0, 16, -16, 0, 0, 13, -13, 0, 0, 13, -13, 0, 0, 0, 0, 0,
0, -24, 24, 0, 0, -16, 16, 0, 0, -16, 16, 0, 0, 0, 0, 0,
};
static const int8 kGoriya_Yvel[32] = {
0, 0, 0, 0, -16, -5, -5, 0, 16, 13, 13, 0, 0, 0, 0, 0,
0, 0, 0, 0, -24, -16, -16, 0, 24, 16, 16, 0, 0, 0, 0, 0,
};
static const uint8 kGoriya_Dir[32] = {
0, 0, 1, 0, 3, 3, 3, 0, 2, 2, 2, 0, 0, 0, 0, 0,
0, 1, 0, 0, 3, 3, 3, 0, 2, 2, 2, 0, 0, 0, 0, 0,
};
static const uint8 kGoriya_Gfx[16] = {8, 6, 0, 3, 9, 7, 1, 4, 8, 6, 0, 3, 9, 7, 2, 5};
if (!sprite_B[k]) {
Eyegore_Main(k);
return;
}
Goriya_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
if (sprite_delay_aux1[k] == 8)
Sprite_SpawnFirePhlegm(k);
if (bitmask_of_dragstate != 0 || !(joypad1H_last & 0xf)) {
sprite_A[k] = 0;
Sprite_CheckDamageToAndFromLink(k);
Sprite_CheckTileCollision(k);
return;
}
int j = (joypad1H_last & 0xf) | (sprite_type[k] == 0x84) * 16;
sprite_D[k] = kGoriya_Dir[j];
sprite_x_vel[k] = kGoriya_Xvel[j];
sprite_y_vel[k] = kGoriya_Yvel[j];
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckDamageToAndFromLink(k);
Sprite_CheckTileCollision(k);
sprite_graphics[k] = kGoriya_Gfx[++sprite_subtype2[k] & 12 | sprite_D[k]];
if (sprite_type[k] == 0x84) {
PointU8 pt;
uint8 dir = Sprite_DirectionToFaceLink(k, &pt);
if (((uint8)(pt.x + 8) < 16 || (uint8)(pt.y + 8) < 16) && sprite_D[k] == dir) {
if (!(sprite_A[k] & 0x1f))
sprite_delay_aux1[k] = 16;
sprite_A[k]++;
return;
}
}
sprite_A[k] = 0;
}
void Eyegore_Main(int k) { // 9ec839
static const uint8 kEyeGore_Closing_Gfx[8] = {0, 0, 1, 1, 2, 2, 2, 2};
static const uint8 kEyeGore_Opening_Gfx[8] = {2, 2, 2, 2, 1, 1, 0, 0};
static const uint8 kEyeGore_Chasing_Gfx[16] = {7, 5, 2, 9, 8, 6, 3, 10, 7, 5, 2, 9, 8, 6, 4, 11};
static const uint8 kEyeGore_Opening_Delay[4] = {0x60, 0x80, 0xa0, 0x80};
Eyegore_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
sprite_flags3[k] |= 64;
sprite_defl_bits[k] |= 4;
switch (sprite_ai_state[k]) {
case 0: // wait until player
if (!sprite_delay_main[k]) {
PointU8 pt;
Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.x + 48) < 96 &&
(uint8)(pt.y + 48) < 96) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 63;
}
}
break;
case 1: // openig eye
if (!sprite_delay_main[k]) {
sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
sprite_ai_state[k] = 2;
sprite_delay_main[k] = kEyeGore_Opening_Delay[GetRandomNumber() & 3];
} else {
sprite_graphics[k] = kEyeGore_Opening_Gfx[sprite_delay_main[k] >> 3];
}
break;
case 2: // chase player
sprite_flags3[k] &= ~0x40;
if (sprite_type[k] != 0x84)
sprite_defl_bits[k] &= ~4;
if (!sprite_delay_main[k]) {
sprite_delay_main[k] = 63;
sprite_ai_state[k]++;
sprite_graphics[k] = 0;
} else {
if (!((k ^ frame_counter) & 31))
sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL);
int j = sprite_D[k];
sprite_x_vel[k] = kFluteBoyAnimal_Xvel[j];
sprite_y_vel[k] = kZazak_Yvel[j];
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
sprite_graphics[k] = kEyeGore_Chasing_Gfx[++sprite_subtype2[k] & 12 | sprite_D[k]];
}
break;
case 3: // closing eye
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 96;
} else {
sprite_graphics[k] = kEyeGore_Closing_Gfx[sprite_delay_main[k] >> 3];
}
break;
}
}
void Eyegore_Draw(int k) { // 9ecacf
static const DrawMultipleData kEyeGore_Dmd[48] = {
{-4, -4, 0x00a2, 2},
{ 4, -4, 0x40a2, 2},
{-4, 4, 0x009c, 2},
{ 4, 4, 0x409c, 2},
{-4, -4, 0x00a4, 2},
{ 4, -4, 0x40a4, 2},
{-4, 4, 0x009c, 2},
{ 4, 4, 0x409c, 2},
{-4, -4, 0x008c, 2},
{ 4, -4, 0x408c, 2},
{-4, 4, 0x009c, 2},
{ 4, 4, 0x409c, 2},
{-4, -3, 0x008c, 2},
{12, -3, 0x408c, 0},
{-4, 13, 0x00bc, 0},
{ 4, 5, 0x408a, 2},
{-4, -3, 0x008c, 0},
{ 4, -3, 0x408c, 2},
{-4, 5, 0x008a, 2},
{12, 13, 0x40bc, 0},
{ 0, -4, 0x00aa, 2},
{ 0, 4, 0x00a6, 2},
{ 0, -4, 0x00aa, 2},
{ 0, 4, 0x00a6, 2},
{ 0, -3, 0x00aa, 2},
{ 0, 4, 0x00a8, 2},
{ 0, -3, 0x00aa, 2},
{ 0, 4, 0x00a8, 2},
{ 0, -4, 0x40aa, 2},
{ 0, 4, 0x40a6, 2},
{ 0, -4, 0x40aa, 2},
{ 0, 4, 0x40a6, 2},
{ 0, -3, 0x40aa, 2},
{ 0, 4, 0x40a8, 2},
{ 0, -3, 0x40aa, 2},
{ 0, 4, 0x40a8, 2},
{-4, -4, 0x008e, 2},
{ 4, -4, 0x408e, 2},
{-4, 4, 0x009e, 2},
{ 4, 4, 0x409e, 2},
{-4, -3, 0x008e, 2},
{12, -3, 0x408e, 0},
{-4, 13, 0x00bd, 0},
{ 4, 5, 0x40a0, 2},
{-4, -3, 0x008e, 0},
{ 4, -3, 0x408e, 2},
{-4, 5, 0x00a0, 2},
{12, 13, 0x40bd, 0},
};
PrepOamCoordsRet info;
Sprite_DrawMultiple(k, &kEyeGore_Dmd[sprite_graphics[k] * 4], 4, &info);
if (!sprite_pause[k])
SpriteDraw_Shadow_custom(k, &info, 14);
}
void SpritePrep_AntifairyCircle(int k) { // 9ecb0c
static const int8 kBubbleGroup_X[3] = {10, 20, 10};
static const int8 kBubbleGroup_Y[3] = {-10, 0, 10};
static const int8 kBubbleGroup_Xvel[3] = {18, 0, -18};
static const int8 kBubbleGroup_Yvel[3] = {0, 18, 0};
static const int8 kBubbleGroup_A[3] = {1, 1, 0};
static const int8 kBubbleGroup_B[3] = { 0, 1, 1 };
Sprite_SetX(k, Sprite_GetX(k) - 10);
sprite_y_vel[k] = -18;
sprite_x_vel[k] = 0;
sprite_A[k] = 0;
sprite_B[k] = 0;
tmp_counter = 2;
do {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x82, &info);
if (j >= 0) {
int i = tmp_counter;
Sprite_SetX(j, info.r0_x + kBubbleGroup_X[i]);
Sprite_SetY(j, info.r2_y + kBubbleGroup_Y[i]);
sprite_x_vel[j] = kBubbleGroup_Xvel[i];
sprite_y_vel[j] = kBubbleGroup_Yvel[i];
sprite_A[j] = kBubbleGroup_A[i];
sprite_B[j] = kBubbleGroup_B[i];
}
} while (!sign8(--tmp_counter));
}
void Sprite_82_AntifairyCircle(int k) { // 9ecb97
static const int8 kBubbleGroup_Vel[2] = {1, -1};
static const uint8 kBubbleGroup_VelTarget[2] = {18, (uint8)-18};
SpriteDraw_Antfairy(k);
if (Sprite_ReturnIfInactive(k))
return;
int j = sprite_A[k] & 1;
if ((sprite_x_vel[k] += kBubbleGroup_Vel[j]) == kBubbleGroup_VelTarget[j])
sprite_A[k]++;
j = sprite_B[k] & 1;
if ((sprite_y_vel[k] += kBubbleGroup_Vel[j]) == kBubbleGroup_VelTarget[j])
sprite_B[k]++;
Sprite_MoveXY(k);
if (sprite_x_vel[k] && sprite_y_vel[k] && Sprite_CheckIfRoomIsClear()) {
sprite_type[k] = 0x15;
sprite_x_vel[k] = sign8(sprite_x_vel[k]) ? -16 : 16;
sprite_y_vel[k] = sign8(sprite_y_vel[k]) ? -16 : 16;
}
Sprite_CheckDamageToLink(k);
}
void Sprite_81_Hover(int k) { // 9ecc02
static const int8 kHover_OamFlags[4] = {0x40, 0, 0x40, 0};
sprite_obj_prio[k] |= 48;
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_F[k])
sprite_ai_state[k] = 0;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
Sprite_CheckTileCollision(k);
sprite_graphics[k] = ++sprite_subtype2[k] >> 3 & 2;
switch(sprite_ai_state[k]) {
case 0: // stopped
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 1;
int j = Sprite_IsRightOfLink(k).a + Sprite_IsBelowLink(k).a * 2;
sprite_D[k] = j;
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kHover_OamFlags[j];
sprite_delay_main[k] = (GetRandomNumber() & 15) + 12;
Sprite_ZeroVelocity_XY(k);
}
break;
case 1: { // moving
static const int8 kHover_AccelX0[4] = {1, -1, 1, -1};
static const int8 kHover_AccelY0[4] = {1, 1, -1, -1};
static const int8 kHover_AccelX1[4] = {-1, 1, -1, 1};
static const int8 kHover_AccelY1[4] = {-1, -1, 1, 1};
int j = sprite_D[k];
if (sprite_delay_main[k]) {
sprite_x_vel[k] += kHover_AccelX0[j];
sprite_y_vel[k] += kHover_AccelY0[j];
sprite_graphics[k] = sprite_subtype2[k] >> 3 & 1;
} else {
sprite_x_vel[k] += kHover_AccelX1[j];
sprite_y_vel[k] += kHover_AccelY1[j];
if (!sprite_y_vel[k]) {
sprite_ai_state[k] = 0;
sprite_delay_main[k] = 64;
}
}
break;
}
}
}
void Sprite_AB_CrystalMaiden(int k) { // 9ece03
cur_sprite_x -= dung_floor_x_offs;
cur_sprite_y -= dung_floor_y_offs;
if (sprite_ai_state[k] >= 3)
CrystalMaiden_Draw(k);
is_nmi_thread_active = 1;
if (!BYTE(intro_did_run_step)) {
CrystalMaiden_RunCutscene(k);
BYTE(intro_did_run_step) = 1;
}
}
void CrystalMaiden_RunCutscene(int k) { // 9ece39
sprite_E[k]++;
poly_b += 6;
if (submodule_index)
return;
switch (sprite_ai_state[k]) {
case 0: // disable subscreen
TS_copy = 0;
sprite_ai_state[k]++;
break;
case 1: // enable subscreen
TS_copy = 1;
sprite_ai_state[k]++;
break;
case 2: // generate sparkles
if (poly_config1 < 6) {
poly_config1 = 0;
sprite_ai_state[k]++;
} else {
poly_config1 -= 3;
if (poly_config1 >= 64)
AncillaAdd_SwordChargeSparkle(sprite_A[k]);
}
break;
case 3: // filter palette
sprite_ai_state[k]++;
case 4:
if (!(sprite_E[k] & 1)) {
PaletteFilter_SP5F();
if (!BYTE(palette_filter_countdown)) {
sprite_ai_state[k]++;
flag_is_link_immobilized = 1;
link_receiveitem_index = 0;
link_pose_for_item = 0;
link_animation_steps = 0;
link_direction_facing = 0;
}
}
break;
case 5: { // show message
static const uint16 kCrystalMaiden_Msgs[9] = {0x133, 0x132, 0x137, 0x134, 0x136, 0x132, 0x135, 0x138, 0x13c};
int j = BYTE(cur_palace_index_x2) - 10;
if (j == 2 && savegame_map_icons_indicator < 7)
savegame_map_icons_indicator = 7;
if (j == 14 && (link_has_crystals & 0x7f) != 0x7f)
j = 16;
Sprite_ShowMessageUnconditional(kCrystalMaiden_Msgs[j >> 1]);
sprite_ai_state[k]++;
if ((link_has_crystals & 0x7f) == 0x7f)
savegame_map_icons_indicator = 8;
break;
}
case 6: // reading comprehension exam
Sprite_ShowMessageUnconditional(0x13a);
sprite_ai_state[k]++;
break;
case 7: // may the way of the hero
if (choice_in_multiselect_box) {
sprite_ai_state[k] = 5;
} else {
Sprite_ShowMessageUnconditional(0x139);
sprite_ai_state[k]++;
}
break;
case 8: // initiate dungeon exit
TS_copy = 0;
PrepareDungeonExitFromBossFight();
sprite_state[k] = 0;
break;
}
}
void Sprite_7D_BigSpike(int k) { // 9ecf47
static const int8 kSpikeTrap_Xvel[4] = {32, -32, 0, 0};
static const int8 kSpikeTrap_Xvel2[4] = {-16, 16, 0, 0};
static const int8 kSpikeTrap_Yvel[4] = {0, 0, 32, -32};
static const int8 kSpikeTrap_Yvel2[4] = {0, 0, -16, 16};
static const uint8 kSpikeTrap_Delay[4] = {0x40, 0x40, 0x38, 0x38};
int j;
SpikeTrap_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_CheckDamageToAndFromLink(k);
if (sprite_ai_state[k] == 0) {
PointU8 pt;
sprite_D[k] = j = Sprite_DirectionToFaceLink(k, &pt);
if ((uint8)(pt.x + 16) < 32 || (uint8)(pt.y + 16) < 32) {
sprite_delay_main[k] = kSpikeTrap_Delay[j];
sprite_ai_state[k] = 1;
sprite_x_vel[k] = kSpikeTrap_Xvel[j];
sprite_y_vel[k] = kSpikeTrap_Yvel[j];
}
} else if (sprite_ai_state[k] == 1) {
if (Sprite_CheckTileCollision(k) || !sprite_delay_main[k]) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 96;
}
Sprite_MoveXY(k);
} else {
if (!sprite_delay_main[k]) {
j = sprite_D[k];
sprite_x_vel[k] = kSpikeTrap_Xvel2[j];
sprite_y_vel[k] = kSpikeTrap_Yvel2[j];
Sprite_MoveXY(k);
if (sprite_x_lo[k] == sprite_A[k] && sprite_y_lo[k] == sprite_C[k])
sprite_ai_state[k] = 0;
}
}
}
void SpikeTrap_Draw(int k) { // 9ecfff
static const DrawMultipleData kSpikeTrap_Dmd[4] = {
{-8, -8, 0x00c4, 2},
{ 8, -8, 0x40c4, 2},
{-8, 8, 0x80c4, 2},
{ 8, 8, 0xc0c4, 2},
};
Sprite_DrawMultiple(k, kSpikeTrap_Dmd, 4, NULL);
}
void Sprite_7E_Firebar_Clockwise(int k) { // 9ed01a
static const int8 kGuruguruBar_incr[4] = {-2, 2, -1, 1};
Firebar_Main(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_subtype2[k]++;
int j = (sprite_type[k] - 0x7e) + (BYTE(cur_palace_index_x2) == 18) * 2;
int t = sprite_A[k] | sprite_B[k] << 8;
t = (t + kGuruguruBar_incr[j]) & 0x1ff;
sprite_A[k] = t;
sprite_B[k] = t >> 8;
}
void Firebar_Main(int k) { // 9ed049
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
byte_7E0FB6 = info.flags;
BYTE(dungmap_var7) = info.x;
HIBYTE(dungmap_var7) = info.y;
int angle = sprite_A[k] | sprite_B[k] << 8;
int8 sinval = GuruguruBarSin(angle, 0x40);
int8 cosval = GuruguruBarSin((angle + 0x80) & 0x1ff, 0x40);
uint8 flags = (sprite_subtype2[k] << 4 & 0xc0) | info.flags;
for (int i = 3; i >= 0; i--, oam++) {
oam->x = info.x + sinval * (i + 1) / 4;
oam->y = info.y + cosval * (i + 1) / 4;
oam->charnum = 0x28;
oam->flags = flags;
bytewise_extended_oam[oam - oam_buf] = 2;
}
Sprite_CorrectOamEntries(k, 3, 0xff);
if (!((k ^ frame_counter) & 3 | submodule_index | flag_unk1)) {
OamEnt *oam = GetOamCurPtr();
for (int i = 0; i < 4; i++, oam++) {
if (bytewise_extended_oam[oam - oam_buf] & 1)
continue;
if ((uint8)(oam->x + BG2HOFS_copy2 - link_x_coord + 12) < 24 &&
oam->y < 0xf0 &&
(uint8)(oam->y + BG2VOFS_copy2 - link_y_coord + 4) < 16)
Sprite_AttemptDamageToLinkPlusRecoil(k);
}
}
}
void Sprite_80_Firesnake(int k) { // 9ed1d1
static const uint8 kWinder_OamFlags[4] = {0, 0x40, 0x80, 0xc0};
static const int8 kWinder_Xvel[4] = {24, -24, 0, 0};
static const int8 kWinder_Yvel[4] = {0, 0, 24, -24};
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_oam_flags[k] = sprite_oam_flags[k] & 0x3f | kWinder_OamFlags[frame_counter >> 2 & 3];
if (sprite_A[k]) {
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (sprite_delay_main[k] == 0)
sprite_state[k] = 0;
return;
}
Sprite_CheckDamageToAndFromLink(k);
Firesnake_SpawnFireball(k);
if (!sprite_wallcoll[k])
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k))
sprite_D[k] = kZazak_Dir2[sprite_D[k] * 2 + (GetRandomNumber() & 1)];
int j = sprite_D[k];
sprite_x_vel[k] = kWinder_Xvel[j];
sprite_y_vel[k] = kWinder_Yvel[j];
}
void Firesnake_SpawnFireball(int j) { // 9ed239
if ((j ^ frame_counter) & 7)
return;
int k = GarnishAlloc();
garnish_type[k] = 1;
garnish_active = 1;
garnish_x_lo[k] = sprite_x_lo[j];
garnish_x_hi[k] = sprite_x_hi[j];
int y = Sprite_GetY(j) + 16;
garnish_y_lo[k] = y;
garnish_y_hi[k] = y >> 8;
garnish_countdown[k] = 32;
garnish_sprite[k] = j;
garnish_floor[k] = sprite_floor[j];
}
void Sprite_7C_GreenStalfos(int k) { // 9ed299
static const uint8 kGreenStalfos_Dir[4] = {4, 6, 0, 2};
static const uint8 kGreenStalfos_OamFlags[4] = {0x40, 0, 0, 0};
static const uint8 kGreenStalfos_Gfx[4] = {0, 0, 1, 2};
int j = sprite_D[k];
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | kGreenStalfos_OamFlags[j];
sprite_graphics[k] = kGreenStalfos_Gfx[j];
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_CheckDamageToAndFromLink(k);
j = Sprite_DirectionToFaceLink(k, NULL);
if (kGreenStalfos_Dir[j] != link_direction_facing) {
sprite_A[k] = 0;
if (!((k ^ frame_counter) & 7)) {
uint8 vel = sprite_B[k];
if (vel != 4)
sprite_B[k]++;
Sprite_ApplySpeedTowardsLink(k, vel);
sprite_D[k] = Sprite_IsRightOfLink(k).a;
}
} else {
sprite_A[k] = 1;
if (!((k ^ frame_counter) & 15)) {
uint8 vel = sprite_B[k];
if (vel)
sprite_B[k]--;
Sprite_ApplySpeedTowardsLink(k, vel);
sprite_D[k] = Sprite_IsRightOfLink(k).a;
}
}
Sprite_MoveXY(k);
}
void Sprite_7A_Agahnim(int k) { // 9ed330
int j;
uint8 t;
static const uint8 kAgahnim_StartState[2] = {1, 6};
static const uint8 kAgahnim_Gfx0[5] = {12, 13, 14, 15, 16};
static const int8 kAgahnim_Tab5[2] = {32, -32};
static const uint8 kAgahnim_Tab6[2] = {9, 11};
static const uint8 kAgahnim_Dir[25] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 1, 1, 4,
4, 0, 2, 2, 4, 4, 3, 2, 2,
};
static const uint8 kAgahnim_Gfx1[6] = {2, 10, 8, 0, 4, 6};
static const uint8 kAgahnim_Tab0[16] = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0};
static const uint8 kAgahnim_Tab1[16] = {0, 0, 0, 0, 0, 0, 0, 6, 5, 4, 3, 2, 1, 0, 0, 0};
static const uint8 kAgahnim_Tab2[6] = {30, 24, 12, 0, 6, 18};
static const uint8 kAgahnim_Gfx2[5] = {16, 15, 14, 13, 12};
static const uint8 kAgahnim_Tab3[16] = {0x38, 0x38, 0x38, 0x58, 0x78, 0x98, 0xb8, 0xb8, 0xb8, 0x98, 0x58, 0x58, 0x60, 0x90, 0x98, 0x78};
static const uint8 kAgahnim_Tab4[16] = {0xb8, 0x78, 0x58, 0x48, 0x48, 0x48, 0x58, 0x78, 0xb8, 0xb8, 0xb8, 0x90, 0x70, 0x70, 0x90, 0xa0};
static const uint8 kAgahnim_Gfx3[7] = {0, 8, 10, 2, 2, 6, 4};
Agahnim_Draw(k);
if (sprite_pause[k]) {
sprite_delay_main[k] = 32;
sprite_graphics[k] = 0;
sprite_D[k] = 3;
}
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
sprite_ignore_projectile[k] = 1;
switch (sprite_ai_state[k]) {
case 0:
sprite_ai_state[k] = kAgahnim_StartState[is_in_dark_world];
break;
case 1:
if (!sprite_delay_main[k]) {
dialogue_message_index = 0x13f;
Sprite_ShowMessageMinimal();
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 32;
}
break;
case 2:
byte_7E0FF8 = 0;
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 255;
} else {
sprite_graphics[k] = kAgahnim_Gfx0[sprite_delay_main[k] >> 3];
}
break;
case 3:
j = sprite_delay_main[k];
if (j == 192)
SpriteSfx_QueueSfx3WithPan(k, 0x27);
if (j >= 239 || j < 16) {
AgahnimWarpShadowFilter(is_in_dark_world ? k : 2);
} else {
if (!k) {
Sprite_CheckDamageToAndFromLink(k);
sprite_ignore_projectile[k] = 0;
}
}
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_delay_main[k] = 39;
return;
}
if (sprite_delay_main[k] >= 128) {
Sprite_ApplySpeedTowardsLink(k, 2);
sprite_D[k] = kAgahnim_Dir[((int8)sprite_y_vel[k] + 2) * 5 + 2 + (int8)sprite_x_vel[k]];
Sprite_ApplySpeedTowardsLink(k, 32);
if (sprite_subtype[k] == 4)
sprite_D[k] = 3;
} else if (sprite_delay_main[k] == 112) {
Agahnim_PerformAttack(k);
}
j = sprite_delay_main[k] >> 4;
sprite_A[k] = kAgahnim_Tab0[j];
t = kAgahnim_Tab1[j];
sprite_head_dir[k] = t ? t + kAgahnim_Tab2[sprite_D[k]] : t ;
sprite_graphics[k] = kAgahnim_Gfx1[sprite_D[k]] + sprite_A[k];
break;
case 4:
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
j = sprite_subtype[k] == 4 ? 4 : GetRandomNumber() & 0xf;
sprite_C[k] = kAgahnim_Tab3[j];
sprite_E[k] = kAgahnim_Tab4[j];
sprite_G[k] = 8;
} else {
sprite_graphics[k] = kAgahnim_Gfx2[sprite_delay_main[k] >> 3];
}
break;
case 5: {
if ((uint16)(sprite_x_lo[k] - sprite_C[k] + 7) < 14 &&
(uint16)(sprite_y_lo[k] - sprite_E[k] + 7) < 14) {
sprite_x_lo[k] = sprite_C[k];
sprite_y_lo[k] = sprite_E[k];
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 39;
return;
}
int x = sprite_x_hi[k] << 8 | sprite_C[k];
int y = sprite_y_hi[k] << 8 | sprite_E[k];
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, sprite_G[k]);
sprite_y_vel[k] = pt.y;
sprite_x_vel[k] = pt.x;
if (sprite_G[k] < 64)
sprite_G[k]++;
Sprite_MoveXY(k);
break;
}
case 6:
if (!sprite_delay_main[k]) {
dialogue_message_index = 0x141;
Sprite_ShowMessageMinimal();
sprite_ai_state[k]++;
sprite_delay_main[k] = 80;
}
break;
case 7:
if (sprite_anim_clock[k]) {
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 32;
} else {
sprite_x_vel[k] = kAgahnim_Tab5[k - 1];
sprite_y_vel[k] += 2;
Sprite_MoveXY(k);
j = Sprite_Agahnim_ApplyMotionBlur(k);
if (j >= 0)
sprite_oam_flags[j] = 4;
}
} else {
if (!sprite_delay_main[k]) {
sprite_ai_state[k] = 3;
sprite_delay_main[k] = 32;
} else if (sprite_delay_main[k] == 64) {
sound_effect_2 = 0x28;
tmp_counter = 1;
do {
SpriteSpawnInfo info;
j = Sprite_SpawnDynamicallyEx(k, 0x7A, &info, 2);
Sprite_SetSpawnedCoordinates(j, &info);
sprite_flags3[j] = kAgahnim_Tab6[j - 1];
sprite_anim_clock[j] = sprite_oam_flags[j] = sprite_flags3[j] & 15;
sprite_ai_state[j] = sprite_ai_state[k];
sprite_delay_main[j] = 32;
} while (!sign8(--tmp_counter));
}
}
break;
case 8:
flag_block_link_menu = 2;
sprite_head_dir[k] = 0;
if (sprite_delay_main[k] >= 64) {
sprite_hit_timer[k] |= 0xe0;
} else {
if (sprite_delay_main[k] == 1) {
Sprite_SpawnPhantomGanon(k);
music_control = 0x1d;
}
sprite_hit_timer[k] = 0;
sprite_graphics[k] = 17;
}
break;
case 9: {
sprite_head_dir[k] = 0;
int x = Sprite_GetX(0), y = Sprite_GetY(0);
if ((uint16)(cur_sprite_x - x + 4) < 8 &&
(uint16)(cur_sprite_y - y + 4) < 8)
sprite_state[k] = 0;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 0x20);
sprite_y_vel[k] = pt.y;
sprite_x_vel[k] = pt.x;
Sprite_MoveXY(k);
Sprite_Agahnim_ApplyMotionBlur(k);
break;
}
case 10:
if (!sprite_delay_main[k]) {
sprite_state[k] = 0;
PrepareDungeonExitFromBossFight();
}
if (sprite_delay_main[k] < 16) {
CGADSUB_copy = 0x7f;
TM_copy = 6;
TS_copy = 0x10;
PaletteFilter_SP5F();
}
if (sprite_z_vel[k] != 0xff)
sprite_z_vel[k]++;
j = sprite_z_subpos[k] + sprite_z_vel[k];
sprite_z_subpos[k] = j;
if (j & 0x100 && ++sprite_subtype2[k] == 7) {
sprite_subtype2[k] = 0;
SpriteSfx_QueueSfx2WithPan(k, 0x4);
}
sprite_graphics[k] = kAgahnim_Gfx3[sprite_subtype2[k]];
break;
}
}
void Agahnim_PerformAttack(int k) { // 9ed67a
static const int8 kAgahnim_X0[6] = {0, 10, 8, 0, -10, -10};
static const int8 kAgahnim_Y0[6] = {-9, -2, -2, -9, -2, -2};
if (!k) {
sprite_subtype[k]++;
if (is_in_dark_world)
sprite_subtype[k] &= 3;
}
if (sprite_subtype[k] == 5) {
sprite_subtype[k] = 0;
SpriteSfx_QueueSfx3WithPan(k, 0x26);
for (int i = 0; i < 4; i++)
Sprite_SpawnLightning(k);
} else {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x7B, &info);
if (j >= 0) {
SpriteSfx_QueueSfx3WithPan(k, 0x29);
int i = sprite_D[k];
Sprite_SetX(j, info.r0_x + kAgahnim_X0[i]);
Sprite_SetY(j, info.r2_y + kAgahnim_Y0[i]);
sprite_ignore_projectile[j] = sprite_y_hi[j];
sprite_x_vel[j] = sprite_x_vel[k];
sprite_y_vel[j] = sprite_y_vel[k];
if (sprite_subtype[k] >= 2 && !(GetRandomNumber() & 1)) {
sprite_B[j] = 1;
sprite_delay_main[j] = 32;
}
}
}
}
void Agahnim_Draw(int k) { // 9ed978
static const int8 kAgahnim_Draw_X0[72] = {
-8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8,
-8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8,
-8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8, -8, 8,
-8, 8, -8, 8, -6, 6, -6, 6, -8, 8, -8, 8, -6, 6, -6, 6,
0, 8, 0, 8, -8, 8, -8, 8,
};
static const int8 kAgahnim_Draw_Y0[72] = {
-8, -8, 8, 8, -8, -8, 8, 8, -8, -8, 8, 8, -8, -8, 8, 8,
-8, -8, 8, 8, -8, -8, 8, 8, -8, -8, 8, 8, -8, -8, 8, 8,
-8, -8, 8, 8, -8, -8, 8, 8, -8, -8, 8, 8, -8, -8, 8, 8,
-8, -8, 8, 8, -6, -6, 6, 6, -8, -8, 8, 8, -6, -6, 6, 6,
0, 0, 8, 8, 8, 8, 8, 8,
};
static const uint8 kAgahnim_Draw_Char0[72] = {
0x82, 0x82, 0xa2, 0xa2, 0x80, 0x80, 0xa0, 0xa0, 0x84, 0x84, 0xa4, 0xa4, 0x86, 0x86, 0xa6, 0xa6,
0x88, 0x8a, 0xa8, 0xaa, 0x8c, 0x8e, 0xac, 0xae, 0xc4, 0xc2, 0xe4, 0xe6, 0xc0, 0xc2, 0xe0, 0xe2,
0x8a, 0x88, 0xaa, 0xa8, 0x8e, 0x8c, 0xae, 0xac, 0xc2, 0xc4, 0xe6, 0xe4, 0xc2, 0xc0, 0xe2, 0xe0,
0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xdf, 0xdf, 0xdf, 0xdf, 0x40, 0x42, 0x40, 0x42,
};
static const uint8 kAgahnim_Draw_Flags0[72] = {
0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40, 0, 0x40,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0,
0, 0x40, 0x80, 0xc0, 0, 0, 0, 0,
};
static const int8 kAgahnim_Draw_X1[72] = {
-7, 15, -11, 11, -11, 11, -8, 8, -4, 4, 0, 0, -10, -1, -14, -5,
-14, -5, -12, -7, -10, -7, -10, -10, 16, 8, 12, 4, 12, 4, 10, 6,
9, 7, 8, 8, -6, -6, -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
14, 14, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, -7, 15, -11, 11,
-11, 11, -8, 8, -4, 4, 0, 0,
};
static const int8 kAgahnim_Draw_Y1[72] = {
-5, -5, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -3, 9, -7, 5,
-7, 5, -5, 3, -3, 3, -2, -2, -3, 9, -7, 5, -7, 5, -5, 3,
-3, 3, -2, -2, -3, 9, -7, 5, -7, 5, -5, 3, -3, 3, -2, -2,
-3, 9, -7, 5, -7, 5, -5, 3, -3, 3, -2, -2, -5, -5, -9, -9,
-9, -9, -9, -9, -9, -9, -9, -9,
};
static const uint8 kAgahnim_Draw_Char1[36] = {
0xce, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0xcc, 0xc6, 0xc6,
0xc6, 0xc6, 0xce, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0xcc,
0xc6, 0xc6, 0xc6, 0xc6,
};
static const uint8 kAgahnim_Draw_Ext1[36] = {
0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2,
2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2,
2, 2, 2, 2,
};
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int g = sprite_graphics[k];
for (int i = 3; i >= 0; i--, oam++) {
int j = g * 4 + i;
oam->x = info.x + kAgahnim_Draw_X0[j];
oam->y = info.y + kAgahnim_Draw_Y0[j];
oam->charnum = kAgahnim_Draw_Char0[j];
oam->flags = info.flags | kAgahnim_Draw_Flags0[j];
bytewise_extended_oam[oam - oam_buf] = (j >= 0x40 && j < 0x44) ? 0 : 2;
}
if (g < 12)
SpriteDraw_Shadow_custom(k, &info, 18);
if (submodule_index)
Sprite_CorrectOamEntries(k, 3, 0xff);
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
if (sprite_D[k])
Oam_AllocateFromRegionC(8);
else
Oam_AllocateFromRegionB(8);
oam = GetOamCurPtr();
if (!sprite_head_dir[k])
return;
g = sprite_head_dir[k] - 1;
uint8 flags = (((frame_counter >> 1) & 2) + 2) + 0x31;
for (int i = 1; i >= 0; i--, oam++) {
oam->x = info.x + kAgahnim_Draw_X1[g * 2 + i];
oam->y = info.y + kAgahnim_Draw_Y1[g * 2 + i];
oam->charnum = kAgahnim_Draw_Char1[g];
oam->flags = flags;
bytewise_extended_oam[oam - oam_buf] = kAgahnim_Draw_Ext1[g];
}
}
void Sprite_7B_AgahnimBalls(int k) { // 9eda42
if (sprite_B[k]) {
if (sprite_delay_main[k])
Sprite_ApplySpeedTowardsLink(k, 32);
sprite_oam_flags[k] = 5;
} else {
sprite_oam_flags[k] = (frame_counter >> 1 & 2) + 3;
}
if (sprite_ai_state[k]) {
static const uint8 kEnergyBall_Gfx[16] = {2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0};
if (sprite_graphics[k] != 2)
SpriteDraw_SingleLarge(k);
else
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_ignore_projectile[k] = sprite_delay_main[k];
if (!sprite_delay_main[k]) {
sprite_state[k] = 0;
} else if (sprite_delay_main[k] == 6) {
sprite_x_vel[k] = sprite_y_vel[k] = 64;
Sprite_MoveXY(k);
}
sprite_graphics[k] = kEnergyBall_Gfx[sprite_delay_main[k]];
return;
}
if (sprite_B[k])
SeekerEnergyBall_Draw(k);
else
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_subtype2[k]++;
Sprite_MoveXY(k);
if (Sprite_CheckTileCollision(k)) {
sprite_state[k] = 0;
if (sprite_B[k]) {
SpriteSfx_QueueSfx3WithPan(k, 0x36);
CreateSixBlueBalls(k);
return;
}
}
if (sprite_A[k] && !sprite_ignore_projectile[0]) {
SpriteHitBox hb;
hb.r0_xlo = sprite_x_lo[k];
hb.r8_xhi = sprite_x_hi[k];
hb.r2 = hb.r3 = 15;
hb.r1_ylo = sprite_y_lo[k];
hb.r9_yhi = sprite_y_hi[k];
Sprite_SetupHitBox(0, &hb);
if (CheckIfHitBoxesOverlap(&hb)) {
Sprite_GiveDamage(0, 16, 0xa0);
sprite_state[k] = 0;
sprite_x_recoil[0] = sprite_x_vel[k];
sprite_y_recoil[0] = sprite_y_vel[k];
}
} else {
Sprite_CheckDamageToLink(k);
if (Sprite_CheckDamageFromLink(k) & kCheckDamageFromPlayer_Carry) {
if (sprite_B[k]) {
sprite_state[k] = 0;
SpriteSfx_QueueSfx3WithPan(k, 0x36);
CreateSixBlueBalls(k);
return;
}
SpriteSfx_QueueSfx2WithPan(k, 0x5);
SpriteSfx_QueueSfx3WithPan(k, 0x29);
Sprite_ApplySpeedTowardsLink(k, 0x30);
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_y_vel[k] = -sprite_y_vel[k];
sprite_A[k]++;
}
}
if ((k ^ frame_counter) & 3 | sprite_B[k])
return;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x7B, &info);
if (j < 0)
return;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_delay_main[j] = 15;
sprite_ai_state[j] = 15;
sprite_B[j] = sprite_B[k];
}
void CreateSixBlueBalls(int k) { // 9edb96
static const int8 kEnergyBall_SplitXVel[6] = {0, 24, 24, 0, -24, -24};
static const int8 kEnergyBall_SplitYVel[6] = {-32, -16, 16, 32, 16, -16};
SpriteSfx_QueueSfx3WithPan(k, 0x36);
tmp_counter = 5;
do {
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x55, &info);
if (j >= 0) {
Sprite_SetX(j, info.r0_x + 4);
Sprite_SetY(j, info.r2_y + 4);
sprite_flags3[j] = sprite_flags3[j] & ~1 | 0x40;
sprite_oam_flags[j] = 4;
sprite_delay_aux1[j] = 4;
sprite_flags4[j] = 20;
sprite_C[j] = 20;
sprite_E[j] = 20;
sprite_x_vel[j] = kEnergyBall_SplitXVel[tmp_counter];
sprite_y_vel[j] = kEnergyBall_SplitYVel[tmp_counter];
}
} while (!sign8(--tmp_counter));
tmp_counter = 0;
}
void SeekerEnergyBall_Draw(int k) { // 9edc3e
static const DrawMultipleData kEnergyBall_Dmd[8] = {
{ 4, -3, 0x00ce, 0},
{11, 4, 0x00ce, 0},
{ 4, 11, 0x00ce, 0},
{-3, 4, 0x00ce, 0},
{-1, -1, 0x00ce, 0},
{ 9, -1, 0x00ce, 0},
{-1, 9, 0x00ce, 0},
{ 9, 9, 0x00ce, 0},
};
Sprite_DrawMultiple(k, &kEnergyBall_Dmd[(sprite_subtype2[k] >> 2 & 1) * 4], 4, NULL);
}
void Sprite_79_Bee(int k) { // 9edc5b
switch (sprite_ai_state[k]) {
case 0:
Bee_DormantHive(k);
break;
case 1:
Bee_Main(k);
break;
case 2:
Bee_PutInBottle(k);
break;
}
}
void Bee_DormantHive(int k) { // 9edc68
if (sprite_E[k])
return;
sprite_state[k] = 0;
for (int i = 11; i >= 0; i--)
SpawnBeeFromHive(k);
}
void SpawnBeeFromHive(int k) { // 9edc8f
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x79, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
InitializeSpawnedBee(j);
}
}
void InitializeSpawnedBee(int k) { // 9edc9b
sprite_ai_state[k] = 1;
sprite_A[k] = sprite_delay_main[k] = kSpawnBee_InitDelay[k & 3];
sprite_delay_aux4[k] = 96;
sprite_x_vel[k] = kSpawnBee_InitVel[GetRandomNumber() & 7];
sprite_y_vel[k] = kSpawnBee_InitVel[GetRandomNumber() & 7];
}
int ReleaseBeeFromBottle(int x_value) { // 9edccf
static const int8 kSpawnBee_XY[8] = {8, 2, -2, -8, 10, 5, -5, -10};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(x_value, 0xb2, &info);
if (j >= 0) {
sprite_floor[j] = link_is_on_lower_level;
Sprite_SetX(j, link_x_coord + 8);
Sprite_SetY(j, link_y_coord + 16);
if (link_bottle_info[link_item_bottle_index - 1] == 8)
sprite_head_dir[j] = 1;
InitializeSpawnedBee(j);
sprite_x_vel[j] = kSpawnBee_XY[GetRandomNumber() & 7];
sprite_y_vel[j] = kSpawnBee_XY[GetRandomNumber() & 7];
sprite_delay_main[j] = 64;
sprite_A[j] = 64;
}
return j;
}
void Bee_Main(int k) { // 9edd45
Bee_HandleZ(k);
SpriteDraw_SingleSmall(k);
Bee_HandleInteractions(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_ReturnIfRecoiling(k))
return;
if (sprite_head_dir[k])
Sprite_SpawnSparkleGarnish(k);
Bee_Bzzt(k);
Sprite_MoveXY(k);
sprite_graphics[k] = (k ^ frame_counter) >> 1 & 1;
if (!sprite_delay_aux4[k]) {
Sprite_CheckDamageToLink(k);
if (Sprite_CheckDamageFromLink(k) & kCheckDamageFromPlayer_Ne) {
Sprite_ShowMessageUnconditional(0xc8);
sprite_ai_state[k] = 2; // put in bottle
return;
}
}
if (!frame_counter && sprite_A[k] != 16)
sprite_A[k] -= 8;
if (sprite_delay_main[k] == 0) {
uint16 x = link_x_coord + (GetRandomNumber() & 3) * 5;
uint16 y = link_y_coord + (GetRandomNumber() & 3) * 5;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 20);
sprite_y_vel[k] = pt.y;
sprite_x_vel[k] = pt.x;
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | (sign8(pt.x) ? 0 : 0x40);
sprite_delay_main[k] = k + sprite_A[k];
}
}
int Sprite_Find_EmptyBottle() { // 9ede2e
for (int i = 0; i != 4; i++)
if (link_bottle_info[i] == 2)
return i;
return -1;
}
void Bee_HandleInteractions(int k) { // 9ede44
if (submodule_index == 2 && (dialogue_message_index == 0xc8 || dialogue_message_index == 0xca))
sprite_delay_aux4[k] = 40;
}
void Sprite_B2_PlayerBee(int k) { // 9ede63
static const uint8 kGoodBee_Tab0[2] = {0xa, 0x14};
switch (sprite_ai_state[k]) {
case 0: // wait
if (!sprite_E[k]) {
sprite_state[k] = 0;
uint8 or_bottle = link_bottle_info[0] | link_bottle_info[1] | link_bottle_info[2] | link_bottle_info[3];
if (!(or_bottle & 8))
GoldBee_SpawnSelf(k);
}
break;
case 1: {// activated
sprite_ignore_projectile[k] = 1;
Bee_HandleZ(k);
SpriteDraw_SingleSmall(k);
Bee_HandleInteractions(k);
if (Sprite_ReturnIfInactive(k))
return;
Bee_Bzzt(k);
Sprite_MoveXY(k);
sprite_graphics[k] = (k ^ frame_counter) >> 1 & 1;
if (sprite_head_dir[k])
Sprite_SpawnSparkleGarnish(k);
if (sprite_B[k] >= kGoodBee_Tab0[sprite_head_dir[k]]) {
sprite_defl_bits[k] = 64;
return;
}
if (sprite_delay_aux4[k])
return;
if (Sprite_CheckDamageFromLink(k) & kCheckDamageFromPlayer_Ne) {
Sprite_ShowMessageUnconditional(0xc8);
sprite_ai_state[k]++;
return;
}
if ((k ^ frame_counter) & 3)
return;
Point16U pt2;
if (!PlayerBee_FindTarget(k, &pt2)) {
pt2.x = link_x_coord + (GetRandomNumber() & 3) * 5;
pt2.y = link_y_coord + (GetRandomNumber() & 3) * 5;
}
if ((k ^ frame_counter) & 7)
return;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, pt2.x, pt2.y, 32);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x40 | (sign8(pt.x) ? 0 : 0x40);
break;
}
case 2: // bottle
Bee_PutInBottle(k);
break;
}
}
void GoldBee_SpawnSelf(int k) { // 9ede90
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x79, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_ai_state[j] = 1;
sprite_delay_main[j] = 64;
sprite_A[j] = 64;
sprite_delay_aux4[j] = 96;
sprite_head_dir[j] = 1;
sprite_x_vel[j] = kSpawnBee_InitVel[GetRandomNumber() & 7];
sprite_y_vel[j] = kSpawnBee_InitVel[GetRandomNumber() & 7];
}
}
void Bee_HandleZ(int k) { // 9edf8a
sprite_z[k] = 16;
if (sprite_head_dir[k])
sprite_oam_flags[k] = (sprite_oam_flags[k] & 0xf1) | (((frame_counter >> 4 & 3) + 1) << 1);
}
bool PlayerBee_FindTarget(int k, Point16U *pt) { // 9edfab
int n = 16;
int j = k * 4 & 0xf;
do {
if (j == k || sprite_state[j] < 9 || sprite_pause[j])
continue;
if (!(sprite_flags2[j] & 0x80)) {
if (sprite_floor[k] != sprite_floor[j] || sprite_flags4[j] & 0x40 || sprite_ignore_projectile[j])
continue;
} else {
if (!sprite_head_dir[k] || !(sprite_bump_damage[j] & 0x40))
continue;
}
PlayerBee_HoneInOnTarget(j, k);
pt->x = Sprite_GetX(j) + (GetRandomNumber() & 3) * 5;
pt->y = Sprite_GetY(j) + (GetRandomNumber() & 3) * 5;
return true;
} while (j = (j - 1) & 0xf, --n);
return false;
}
void Bee_Bzzt(int k) { // 9ee02e
if (!((k ^ frame_counter) & 31))
SpriteSfx_QueueSfx3WithPan(k, 0x2c);
}
void Sprite_B3_PedestalPlaque(int k) { // 9ee044
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
if (!flag_is_link_immobilized && Sprite_CheckIfLinkIsBusy())
return;
link_position_mode &= ~0x20;
if (BYTE(overworld_screen_index) != 48) {
if (link_direction_facing || !Sprite_CheckDamageToLink_same_layer(k))
return;
if (hud_cur_item != kHudItem_BookMudora || !(filtered_joypad_H & 0x40)) {
if (!(filtered_joypad_L & 0x80))
return;
Sprite_ShowMessageUnconditional(0xb6);
} else {
player_handler_timer = 0;
link_position_mode = 32;
sound_effect_1 = 0;
Sprite_ShowMessageUnconditional(0xb7);
}
} else {
if (link_direction_facing || !Sprite_CheckDamageToLink_same_layer(k))
return;
if (hud_cur_item != kHudItem_BookMudora || !(filtered_joypad_H & 0x40)) {
if (!(filtered_joypad_L & 0x80))
return;
Sprite_ShowMessageUnconditional(0xbc);
} else {
player_handler_timer = 0;
link_position_mode = 32;
sound_effect_1 = 0;
button_b_frames = 1;
link_delay_timer_spin_attack = 0;
link_player_handler_state = kPlayerState_OpeningDesertPalace;
Sprite_ShowMessageUnconditional(0xbd);
}
}
}
void Sprite_B4_PurpleChest(int k) { // 9ee0dd
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_ai_state[k]) {
if (Sprite_ShowMessageOnContact(k, 0x116) & 0x100 && follower_indicator == 0)
sprite_ai_state[k] = 1;
} else {
sprite_state[k] = 0;
follower_indicator = 12;
LoadFollowerGraphics();
Sprite_BecomeFollower(k);
}
}
void Sprite_B5_BombShop(int k) { // 9ee111
switch (sprite_subtype2[k]) {
case 0: Sprite_BombShop_Clerk(k); break;
case 1: Sprite_BombShop_Bomb(k); break;
case 2: Sprite_BombShop_SuperBomb(k); break;
case 3: Sprite_BombShop_Huff(k); break;
}
}
void Sprite_BombShop_Clerk(int k) { // 9ee134
static const uint8 kBombShopGuy_Gfx[8] = {0, 1, 0, 1, 0, 1, 0, 1};
static const uint8 kBombShopGuy_Delay[8] = {255, 32, 255, 24, 15, 24, 255, 15};
BombShopEntity_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_delay_main[k]) {
int j = sprite_E[k];
sprite_E[k] = j + 1 & 7;
sprite_delay_main[k] = kBombShopGuy_Delay[j];
sprite_graphics[k] = kBombShopGuy_Gfx[j];
if (sprite_graphics[k] == 0) {
SpriteSfx_QueueSfx3WithPan(k, 0x11);
BombShop_ClerkExhalation(k);
} else {
SpriteSfx_QueueSfx3WithPan(k, 0x12);
}
}
bool flag = ((link_has_crystals & 5) == 5 && sram_progress_indicator_3 & 32);
Sprite_ShowSolicitedMessage(k, flag ? 0x118 : 0x117);
Sprite_BehaveAsBarrier(k);
}
void Sprite_BombShop_Bomb(int k) { // 9ee190
BombShopEntity_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (!ShopItem_CheckForAPress(k))
return;
if (link_item_bombs != kMaxBombsForLevel[link_bomb_upgrades]) {
if (!ShopItem_HandleCost(100)) {
Sprite_ShowMessageUnconditional(0x17c);
ShopItem_PlayBeep(k);
} else {
link_bomb_filler = 27;
sprite_state[k] = 0;
Sprite_ShowMessageUnconditional(0x119);
ShopItem_HandleReceipt(k, 0x28);
}
} else {
Sprite_ShowMessageUnconditional(0x16e);
ShopItem_PlayBeep(k);
}
}
void Sprite_BombShop_SuperBomb(int k) { // 9ee1df
BombShopEntity_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (ShopItem_CheckForAPress(k)) {
if (!ShopItem_HandleCost(100)) {
Sprite_ShowMessageUnconditional(0x17c);
ShopItem_PlayBeep(k);
} else {
follower_indicator = 13;
LoadFollowerGraphics();
Sprite_BecomeFollower(k);
sprite_state[k] = 0;
Sprite_ShowMessageUnconditional(0x11a);
}
}
}
void Sprite_BombShop_Huff(int k) { // 9ee21a
static const uint8 kSnoutPutt_Dmd[4] = {4, 0x44, 0xc4, 0x84};
Oam_AllocateFromRegionC(4);
SpriteDraw_SingleSmall(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_oam_flags[k] &= 0x30;
sprite_oam_flags[k] |= kSnoutPutt_Dmd[frame_counter >> 2 & 3];
sprite_z_vel[k]++;
Sprite_MoveZ(k);
if (!sprite_delay_main[k])
sprite_state[k] = 0;
sprite_graphics[k] = sprite_delay_main[k] >> 3 & 3;
}
void BombShop_ClerkExhalation(int k) { // 9ee256
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xb5, &info);
if (j >= 0) {
Sprite_SetX(j, info.r0_x + 4);
Sprite_SetY(j, info.r2_y + 16);
sprite_subtype2[j] = 3;
sprite_ignore_projectile[j] = 3;
sprite_z[j] = 4;
sprite_z_vel[j] = -12;
sprite_delay_main[j] = 23;
sprite_flags3[j] &= ~0x11;
}
}
void BombShopEntity_Draw(int k) { // 9ee2c6
static const DrawMultipleData kBombShopEntity_Dmd[6] = {
{0, 0, 0x0a48, 2},
{0, 0, 0x0a4c, 2},
{0, 0, 0x04c2, 2},
{0, 0, 0x04c2, 2},
{0, 0, 0x084e, 2},
{0, 0, 0x084e, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kBombShopEntity_Dmd[sprite_subtype2[k] * 2 + sprite_graphics[k]], 1, &info);
SpriteDraw_Shadow(k, &info);
}
void Sprite_B6_Kiki(int k) { // 9ee2ef
switch(sprite_subtype2[k]) {
case 0: Kiki_LyingInwait(k); break;
case 1: Kiki_OfferEntranceService(k); break;
case 2: Kiki_OfferInitialService(k); break;
case 3: Kiki_Flee(k); break;
}
}
void Kiki_Flee(int k) { // 9ee2fe
bool flag = Kiki_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!sprite_z[k] &&
(uint16)(cur_sprite_x - 0xc98) < 0xd0 &&
(uint16)(cur_sprite_y - 0x6a5) < 0xd0)
flag = true;
if (flag)
sprite_state[k] = 0;
sprite_z_vel[k]-=2;
Sprite_MoveXYZ(k);
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = GetRandomNumber() & 15 | 16;
}
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, 0xcf5, 0x6fe, 16);
sprite_x_vel[k] = pt.x << 1;
sprite_y_vel[k] = pt.y << 1;
tagalong_event_flags &= ~3;
if (sign8(pt.x)) pt.x = -pt.x;
if (sign8(pt.y)) pt.y = -pt.y;
sprite_D[k] = (pt.x >= pt.y) ? (sprite_x_vel[k] >> 7) ^ 3 : (sprite_y_vel[k] >> 7) ^ 1;
sprite_graphics[k] = frame_counter >> 3 & 1;
}
void Kiki_OfferInitialService(int k) { // 9ee3af
if (!sign8(sprite_ai_state[k] - 2))
Kiki_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXYZ(k);
sprite_z_vel[k]--;
if (sign8(sprite_z[k])) {
sprite_z_vel[k] = 0;
sprite_z[k] = 0;
}
sprite_graphics[k] = frame_counter >> 3 & 1;
switch(sprite_ai_state[k]) {
case 0:
Sprite_ShowMessageUnconditional(0x11e);
sprite_ai_state[k]++;
break;
case 1:
if (!choice_in_multiselect_box && ShopItem_HandleCost(10)) {
Sprite_ShowMessageUnconditional(0x11f);
tagalong_event_flags |= 3;
sprite_state[k] = 0;
} else {
Sprite_ShowMessageUnconditional(0x120);
tagalong_event_flags &= ~3;
follower_indicator = 0;
sprite_ai_state[k]++;
flag_is_link_immobilized++;
}
break;
case 2: {
sprite_ai_state[k]++;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, 0xc45, 0x6fe, 9);
sprite_y_vel[k] = pt.y;
sprite_x_vel[k] = pt.x;
sprite_D[k] = (pt.x >> 7) ^ 3;
sprite_delay_main[k] = 32;
break;
}
case 3:
if (!sprite_delay_main[k]) {
sprite_ai_state[k]++;
sprite_z_vel[k] = 16;
sprite_delay_main[k] = 16;
}
break;
case 4:
if (!sprite_delay_main[k] && !sprite_z[k]) {
sprite_state[k] = 0;
flag_is_link_immobilized = 0;
}
break;
}
}
void Kiki_OfferEntranceService(int k) { // 9ee4c9
int j, t;
Kiki_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_MoveXYZ(k);
sprite_z_vel[k]--;
if (sign8(sprite_z[k])) {
sprite_z_vel[k] = 0;
sprite_z[k] = 0;
}
switch(sprite_ai_state[k]) {
case 0: //
Sprite_ShowMessageUnconditional(0x11b);
sprite_ai_state[k]++;
break;
case 1: //
if (choice_in_multiselect_box || !ShopItem_HandleCost(100)) {
Sprite_ShowMessageUnconditional(0x11c);
sprite_subtype2[k] = 3;
} else {
Sprite_ShowMessageUnconditional(0x11d);
flag_is_link_immobilized++;
sprite_ai_state[k]++;
sprite_D[k] = 0;
}
break;
case 2: //
case 4: //
case 6: { //
static const uint16 kKiki_Leave_X[3] = {0xf4f, 0xf70, 0xf5d};
static const uint16 kKiki_Leave_Y[3] = { 0x661, 0x64c, 0x624 };
sprite_graphics[k] = frame_counter >> 3 & 1;
j = (sprite_ai_state[k] >> 1) - 1;
if ((uint8)(kKiki_Leave_X[j] - sprite_x_lo[k] + 2) < 4 &&
(uint8)(kKiki_Leave_Y[j] - sprite_y_lo[k] + 2) < 4) {
sprite_ai_state[k]++;
sprite_x_vel[k] = sprite_y_vel[k] = 0;
sprite_delay_aux1[k] = 32;
SpriteSfx_QueueSfx2WithPan(k, 0x21);
return;
}
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, kKiki_Leave_X[j], kKiki_Leave_Y[j], 9);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
break;
}
case 3: //
case 5: //
if (!sprite_delay_aux1[k]) {
static const uint8 kKiki_Zvel[2] = {32, 28};
sprite_z_vel[k] = kKiki_Zvel[sprite_ai_state[k]++ >> 1 & 1];
SpriteSfx_QueueSfx2WithPan(k, 0x20);
sprite_D[k] = sprite_ai_state[k] >> 1 & 1 | 4;
} else {
sprite_D[k] = sprite_ai_state[k] >> 1 & 1 | 6;
sprite_graphics[k] = frame_counter >> 3 & 1;
}
break;
case 7: { //
static const uint8 kKiki_Tab7[3] = {2, 1, 0xff};
static const uint8 kKiki_Delay7[2] = {82, 0};
static const int8 kKiki_Xvel7[4] = {0, 0, -9, 9};
static const int8 kKiki_Yvel7[4] = {-9, 9, 0, 0};
sprite_graphics[k] = frame_counter >> 3 & 1;
if (sprite_z[k] || sprite_delay_main[k])
return;
j = sprite_A[k]++;
t = kKiki_Tab7[j];
if (!sign8(t)) {
sprite_D[k] = t;
sprite_delay_main[k] = kKiki_Delay7[j];
sprite_x_vel[k] = kKiki_Xvel7[t];
sprite_y_vel[k] = kKiki_Yvel7[t];
} else {
sprite_ai_state[k]++;
sprite_x_vel[k] = sprite_y_vel[k] = 0;
trigger_special_entrance = 1;
subsubmodule_index = 0;
overworld_entrance_sequence_counter = 0;
sprite_D[k] = 0;
flag_is_link_immobilized = 0;
}
break;
}
case 8: //
sprite_D[k] = 8;
sprite_graphics[k] = 0;
sprite_z_vel[k] = (GetRandomNumber() & 15) + 16;
sprite_ai_state[k]++;
break;
case 9: //
if (sign8(sprite_z_vel[k]) && !sprite_z[k]) {
sprite_ai_state[k]++;
SpriteSfx_QueueSfx3WithPan(k, 0x25);
}
break;
case 10: //
break;
}
}
bool Kiki_Draw(int k) { // 9ee859
static const DrawMultipleData kKiki_Dmd1[32] = {
{ 0, -6, 0x0020, 2},
{ 0, 0, 0x0022, 2},
{ 0, -6, 0x0020, 2},
{ 0, 0, 0x4022, 2},
{ 0, -6, 0x0020, 2},
{ 0, 0, 0x0022, 2},
{ 0, -6, 0x0020, 2},
{ 0, 0, 0x4022, 2},
{-1, -6, 0x0020, 2},
{ 0, 0, 0x0022, 2},
{-1, -6, 0x0020, 2},
{ 0, 0, 0x0022, 2},
{ 1, -6, 0x4020, 2},
{ 0, 0, 0x4022, 2},
{ 1, -6, 0x4020, 2},
{ 0, 0, 0x4022, 2},
{ 0, -6, 0x01ce, 2},
{ 0, 0, 0x01ee, 2},
{ 0, -6, 0x01ce, 2},
{ 0, 0, 0x01ee, 2},
{ 0, -6, 0x41ce, 2},
{ 0, 0, 0x41ee, 2},
{ 0, -6, 0x41ce, 2},
{ 0, 0, 0x41ee, 2},
{-1, -6, 0x01ce, 2},
{ 0, 0, 0x01ec, 2},
{-1, -6, 0x41ce, 2},
{ 0, 0, 0x01ec, 2},
{ 1, -6, 0x41ce, 2},
{ 0, 0, 0x41ec, 2},
{ 1, -6, 0x01ce, 2},
{ 0, 0, 0x41ec, 2},
};
static const DrawMultipleData kKiki_Dmd2[12] = {
{0, -6, 0x01ca, 0},
{8, -6, 0x41ca, 0},
{0, 2, 0x01da, 0},
{8, 2, 0x41da, 0},
{0, 10, 0x01cb, 0},
{8, 10, 0x41cb, 0},
{0, -6, 0x01db, 0},
{8, -6, 0x41db, 0},
{0, 2, 0x01cc, 0},
{8, 2, 0x41cc, 0},
{0, 10, 0x01dc, 0},
{8, 10, 0x41dd, 0},
};
static const uint8 kKikiDma[32] = {
0x20, 0xc0, 0x20, 0xc0, 0, 0xa0, 0, 0xa0, 0x40, 0x80, 0x40, 0x60, 0x40, 0x80, 0x40, 0x60,
0, 0, 0xfa, 0xff, 0x20, 0, 0, 2, 0, 0, 0, 0, 0x22, 0, 0, 2 // zelda bug: OOB read
};
PrepOamCoordsRet info;
if (sprite_D[k] < 8) {
int j = sprite_D[k] * 2 + sprite_graphics[k];
BYTE(dma_var6) = kKikiDma[j * 2 + 0];
BYTE(dma_var7) = kKikiDma[j * 2 + 1];
Sprite_DrawMultiple(k, &kKiki_Dmd1[j * 2], 2, &info);
if (!sprite_pause[k])
SpriteDraw_Shadow(k, &info);
} else {
Sprite_DrawMultiple(k, &kKiki_Dmd2[sprite_graphics[k] * 6], 6, &info);
if (!sprite_pause[k])
SpriteDraw_Shadow(k, &info);
}
return ((info.x | info.y) & 0xff00) != 0;
}
void Sprite_B7_BlindMaiden(int k) { // 9ee8b6
CrystalMaiden_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_TrackBodyToHead(k);
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
if (!sprite_ai_state[k]) {
if (Sprite_ShowMessageOnContact(k, 0x122) & 0x100)
sprite_ai_state[k] = 1;
} else {
sprite_state[k] = 0;
follower_indicator = 6;
LoadFollowerGraphics();
Sprite_BecomeFollower(k);
}
}
void OldMan_RevertToSprite(int k) { // 9ee938
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xAD, &info);
sprite_D[j] = sprite_head_dir[j] = tagalong_layerbits[k] & 3;
Sprite_SetY(j, (tagalong_y_lo[k] | tagalong_y_hi[k] << 8) + 2);
Sprite_SetX(j, (tagalong_x_lo[k] | tagalong_x_hi[k] << 8) + 2);
sprite_floor[j] = link_is_on_lower_level;
sprite_ignore_projectile[j] = 1;
sprite_subtype2[j] = 1;
OldMan_EnableCutscene();
follower_indicator = 0;
link_speed_setting = 0;
}
void OldMan_EnableCutscene() { // 9ee989
flag_is_link_immobilized = 1;
link_disable_sprite_damage = 1;
}
void Sprite_AD_OldMan(int k) { // 9ee992
static const uint16 kOldMountainManMsgs[3] = {0x9e, 0x9f, 0xa0};
int j;
OldMountainMan_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
switch(sprite_subtype2[k]) {
case 0: // lost
switch (sprite_ai_state[k]) {
case 0: // supplicate
Sprite_TrackBodyToHead(k);
sprite_head_dir[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
j = Sprite_ShowMessageOnContact(k, 0x9c);
if (j & 0x100) {
sprite_D[k] = sprite_head_dir[k] = j;
sprite_ai_state[k] = 1;
}
break;
case 1: // switch to tagalong
follower_indicator = 4;
Sprite_BecomeFollower(k);
which_starting_point = 5;
sprite_state[k] = 0;
CacheCameraProperties();
break;
}
break;
case 1: // entering domicile
Sprite_MoveXY(k);
switch(sprite_ai_state[k]) {
case 0: // grant mirror
sprite_ai_state[k]++;
item_receipt_method = 0;
Link_ReceiveItem(0x1a, 0);
which_starting_point = 1;
OldMan_EnableCutscene();
sprite_delay_main[k] = 48;
sprite_x_vel[k] = 8;
sprite_y_vel[k] = 4;
sprite_D[k] = sprite_head_dir[k] = 3;
break;
case 1: // shuffle away
OldMan_EnableCutscene();
if (!sprite_delay_main[k])
sprite_ai_state[k]++;
sprite_graphics[k] = (k ^ frame_counter) >> 3 & 1;
break;
case 2: { // approach door
sprite_head_dir[k] = 0;
sprite_D[k] = 0;
j = byte_7E0FDE;
int x = overlord_x_lo[j] | overlord_x_hi[j] << 8;
int y = overlord_y_lo[j] | overlord_y_hi[j] << 8;
if (y >= Sprite_GetY(k)) {
sprite_ai_state[k]++;
sprite_y_vel[k] = sprite_x_vel[k] = 0;
} else {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 8);
sprite_y_vel[k] = pt.y;
sprite_x_vel[k] = pt.x;
sprite_graphics[k] = (k ^ frame_counter) >> 3 & 1;
OldMan_EnableCutscene();
}
break;
}
case 3: // made it inside
sprite_state[k] = 0;
flag_is_link_immobilized = 0;
link_disable_sprite_damage = 0;
break;
}
break;
case 2: // sitting at home
Sprite_BehaveAsBarrier(k);
if (sprite_ai_state[k]) {
link_hearts_filler = 160;
sprite_ai_state[k] = 0;
}
j = sram_progress_indicator >= 3 ? 2 : link_item_moon_pearl;
if (Sprite_ShowSolicitedMessage(k, kOldMountainManMsgs[j]) & 0x100)
sprite_ai_state[k]++;
break;
}
}
void Sprite_B8_DialogueTester(int k) { // 9eeae7
assert(0);
}
void Sprite_B9_BullyAndPinkBall(int k) { // 9eeb33
switch(sprite_subtype2[k]) {
case 0: Sprite_PinkBall(k); return;
case 1: PinkBall_Distress(k); return;
case 2: Sprite_Bully(k); return;
}
}
void Sprite_PinkBall(int k) { // 9eeb40
Oam_AllocateDeferToPlayer(k);
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
PinkBall_HandleMessage(k);
sprite_oam_flags[k] = sprite_oam_flags[k] & ~0x80 | sprite_head_dir[k];
Sprite_MoveXYZ(k);
int t = Sprite_CheckTileCollision(k);
if (t) {
if (!(t & 3)) {
sprite_y_vel[k] = -sprite_y_vel[k];
if (sprite_E[k])
goto play_sound;
}
sprite_x_vel[k] = -sprite_x_vel[k];
if (sprite_E[k]) {
play_sound:
BallGuy_PlayBounceNoise(k);
}
}
sprite_z_vel[k]--;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_z_vel[k] = (uint8)-sprite_z_vel[k] >> 2;
if (sprite_z_vel[k] & 0xfc)
BallGuy_PlayBounceNoise(k);
PinkBall_HandleDeceleration(k);
}
if (!sprite_E[k]) {
if (!sprite_head_dir[k]) {
PinkBall_Distress(k);
sprite_graphics[k] = (k ^ frame_counter) >> 3 & 1;
if (!((k ^ frame_counter) & 0x3f)) {
uint16 x = (link_x_coord & 0xff00) | GetRandomNumber();
uint16 y = (link_y_coord & 0xff00) | GetRandomNumber();
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 8);
sprite_B[k] = pt.x;
sprite_A[k] = pt.y;
if (pt.y) {
sprite_oam_flags[k] |= 64;
sprite_oam_flags[k] ^= sprite_x_vel[k] >> 1 & 64;
}
}
sprite_x_vel[k] = sprite_B[k];
sprite_y_vel[k] = sprite_A[k];
} else {
PinkBall_Distress(k);
if (k ^ frame_counter) {
sprite_graphics[k] = (k ^ frame_counter) >> 2 & 1;
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
} else {
sprite_head_dir[k] = 0;
}
}
} else {
if ((sprite_x_vel[k] | sprite_y_vel[k]) == 0) {
sprite_E[k] = 0;
} else {
sprite_graphics[k] = (k ^ frame_counter) >> 2 & 1;
sprite_head_dir[k] = (k ^ frame_counter) << 2 & 128;
}
}
}
void PinkBall_HandleDeceleration(int k) { // 9eec4d
if (sprite_x_vel[k])
sprite_x_vel[k] += sign8(sprite_x_vel[k]) ? 2 : -2;
if (sprite_y_vel[k])
sprite_y_vel[k] += sign8(sprite_y_vel[k]) ? 2 : -2;
}
void PinkBall_Distress(int k) { // 9eec74
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
Sprite_DrawDistress_custom(info.x, info.y, frame_counter);
}
void Sprite_Bully(int k) { // 9eec7c
Bully_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Bully_HandleMessage(k);
Sprite_MoveXYZ(k);
int t = Sprite_CheckTileCollision(k);
if (t) {
if (!(t & 3))
sprite_y_vel[k] = -sprite_y_vel[k];
else
sprite_x_vel[k] = -sprite_x_vel[k];
}
switch(sprite_ai_state[k]) {
case 0: { // chase
sprite_graphics[k] = (k ^ frame_counter) >> 3 & 1;
int j = sprite_head_dir[k];
if (!((k ^ frame_counter) & 0x1f)) {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, Sprite_GetX(j), Sprite_GetY(j), 14);
sprite_y_vel[k] = pt.y;
sprite_x_vel[k] = pt.x;
if (pt.x)
sprite_D[k] = sprite_x_vel[k] >> 7;
}
if (!sprite_z[j]) {
if ((uint8)(sprite_x_lo[k] - sprite_x_lo[j] + 8) < 16 &&
(uint8)(sprite_y_lo[k] - sprite_y_lo[j] + 8) < 16) {
sprite_ai_state[k]++;
BallGuy_PlayBounceNoise(k);
}
}
break;
}
case 1: { // kick ball
sprite_ai_state[k] = 2;
int j = sprite_head_dir[k];
sprite_x_vel[j] = sprite_x_vel[k] << 1;
sprite_y_vel[j] = sprite_y_vel[k] << 1;
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
sprite_z_vel[j] = GetRandomNumber() & 31;
sprite_delay_main[k] = 96;
sprite_graphics[k] = 1;
sprite_E[j] = 1;
break;
}
case 2: // waiting
if (!sprite_delay_main[k])
sprite_ai_state[k] = 0;
break;
}
}
void Bully_Draw(int k) { // 9eed9e
static const DrawMultipleData kBully_Dmd[8] = {
{0, -7, 0x46e0, 2},
{0, 0, 0x46e2, 2},
{0, -7, 0x46e0, 2},
{0, 0, 0x46c4, 2},
{0, -7, 0x06e0, 2},
{0, 0, 0x06e2, 2},
{0, -7, 0x06e0, 2},
{0, 0, 0x06c4, 2},
};
PrepOamCoordsRet info;
Sprite_DrawMultiplePlayerDeferred(k, &kBully_Dmd[sprite_D[k] * 4 + sprite_graphics[k] * 2], 2, &info);
SpriteDraw_Shadow(k, &info);
}
void BallGuy_PlayBounceNoise(int k) { // 9eedc2
SpriteSfx_QueueSfx3WithPan(k, 0x32);
}
void SpawnBully(int k) { // 9eedc9
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xB9, &info);
if (j >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
sprite_subtype2[j] = 2;
sprite_head_dir[j] = k;
sprite_ignore_projectile[j] = 1;
}
}
void PinkBall_HandleMessage(int k) { // 9eede8
if (sprite_delay_aux4[k])
return;
int msg = link_item_moon_pearl & 1 ? 0x15c : 0x15b;
if (Sprite_ShowMessageOnContact(k, msg) & 0x100) {
sprite_x_vel[k] ^= 255;
sprite_y_vel[k] ^= 255;
if (sprite_E[k])
BallGuy_PlayBounceNoise(k);
sprite_delay_aux4[k] = 64;
}
}
void Bully_HandleMessage(int k) { // 9eee25
if (sprite_delay_aux4[k])
return;
int msg = link_item_moon_pearl & 1 ? 0x15e : 0x15d;
if (Sprite_ShowMessageOnContact(k, msg) & 0x100) {
sprite_x_vel[k] ^= 255;
sprite_y_vel[k] ^= 255;
sprite_delay_aux4[k] = 64;
}
}
void Sprite_BA_Whirlpool(int k) { // 9eee5a
static const uint8 kWhirlpool_OamFlags[4] = {0, 0x40, 0xc0, 0x80};
if (BYTE(overworld_screen_index) == 0x1b) {
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
return;
uint16 x = cur_sprite_x - link_x_coord + 0x40;
uint16 y = cur_sprite_y - link_y_coord + 0xf;
if (x < 0x51 && y < 0x12) {
submodule_index = 35;
link_triggered_by_whirlpool_sprite = 1;
subsubmodule_index = 0;
link_actual_vel_y = 0;
link_actual_vel_x = 0;
link_player_handler_state = 20;
last_light_vs_dark_world = overworld_screen_index & 0x40;
}
} else {
sprite_oam_flags[k] = (sprite_oam_flags[k] & 0x3f) | kWhirlpool_OamFlags[frame_counter >> 3 & 3];
Oam_AllocateFromRegionB(4);
cur_sprite_x -= 5;
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (Sprite_CheckDamageToLink_same_layer(k)) {
if (sprite_A[k] == 0) {
submodule_index = 46;
subsubmodule_index = 0;
}
} else {
sprite_A[k] = 0;
}
}
}
void Sprite_BB_Shopkeeper(int k) { // 9eeeef
switch (sprite_subtype2[k]) {
case 0: Shopkeeper_StandardClerk(k); break;
case 1: ChestGameGuy(k); break;
case 2: NiceThiefWithGift(k); break;
case 3: MiniChestGameGuy(k); break;
case 4: LostWoodsChestGameGuy(k); break;
case 5:
case 6: NiceThiefUnderRock(k); break;
case 7: ShopItem_RedPotion150(k); break;
case 8: ShopItem_FighterShield(k); break;
case 9: ShopItem_FireShield(k); break;
case 10: ShopItem_Heart(k); break;
case 11: ShopItem_Arrows(k); break;
case 12: ShopItem_Bombs(k); break;
case 13: ShopItem_Bee(k); break;
}
}
void Shopkeeper_StandardClerk(int k) { // 9eef12
if (is_in_dark_world) {
Oam_AllocateDeferToPlayer(k);
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_oam_flags[k] = (sprite_oam_flags[k] & 63) | (frame_counter << 3 & 64);
} else {
sprite_oam_flags[k] = 7;
Shopkeeper_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
sprite_graphics[k] = frame_counter >> 4 & 1;
}
Sprite_BehaveAsBarrier(k);
int msg = is_in_dark_world == 0 ? 0x165 : 0x15f;
Sprite_ShowSolicitedMessage(k, msg);
if (sprite_ai_state[k] == 0 && (uint16)(cur_sprite_y + 0x60) >= link_y_coord) {
Sprite_ShowMessageUnconditional(msg);
sprite_ai_state[k] = 1;
}
}
void ChestGameGuy(int k) { // 9eef90
Oam_AllocateDeferToPlayer(k);
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
sprite_oam_flags[k] = (sprite_oam_flags[k] & 63) | (frame_counter << 3 & 64);
switch (sprite_ai_state[k]) {
case 0:
if ((uint8)(minigame_credits - 1) >= 2 && Sprite_ShowSolicitedMessage(k, 0x160) & 0x100)
sprite_ai_state[k] = 1;
break;
case 1:
if (choice_in_multiselect_box == 0 && ShopItem_HandleCost(30)) {
minigame_credits = 2;
Sprite_ShowMessageUnconditional(0x164);
sprite_ai_state[k] = 2;
} else {
Sprite_ShowMessageUnconditional(0x161);
sprite_ai_state[k] = 0;
}
break;
case 2:
if (minigame_credits == 0)
Sprite_ShowSolicitedMessage(k, 0x163);
else
Sprite_ShowSolicitedMessage(k, 0x17f);
break;
}
}
void NiceThief_Animate(int k) { // 9ef017
if (!(frame_counter & 3)) {
sprite_graphics[k] = 2;
uint8 dir = Sprite_DirectionToFaceLink(k, NULL);
sprite_head_dir[k] = (dir == 3) ? 2 : dir;
}
Oam_AllocateDeferToPlayer(k);
Thief_Draw(k);
}
void NiceThiefWithGift(int k) { // 9ef038
NiceThief_Animate(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
switch (sprite_ai_state[k]) {
case 0:
if (Sprite_ShowSolicitedMessage(k, 0x176) & 0x100)
sprite_ai_state[k] = 1;
break;
case 1:
if (!(dung_savegame_state_bits & 0x4000)) {
dung_savegame_state_bits |= 0x4000;
sprite_ai_state[k] = 2;
ShopItem_HandleReceipt(k, 0x46);
} else {
sprite_ai_state[k] = 0;
}
break;
case 2:
sprite_ai_state[k] = 0;
break;
}
}
void MiniChestGameGuy(int k) { // 9ef078
sprite_D[k] = Sprite_DirectionToFaceLink(k, NULL) ^ 3;
sprite_graphics[k] = 0;
MazeGameGuy_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
switch (sprite_ai_state[k]) {
case 0:
if ((uint8)(minigame_credits - 1) >= 2 && Sprite_ShowSolicitedMessage(k, 0x17e) & 0x100)
sprite_ai_state[k] = 1;
break;
case 1:
if (choice_in_multiselect_box == 0 && ShopItem_HandleCost(20)) {
minigame_credits = 1;
Sprite_ShowMessageUnconditional(0x17f);
sprite_ai_state[k] = 2;
} else {
Sprite_ShowMessageUnconditional(0x180);
sprite_ai_state[k] = 0;
}
break;
case 2:
Sprite_ShowSolicitedMessage(k, (minigame_credits == 0) ? 0x163 : 0x17f);
break;
}
}
void LostWoodsChestGameGuy(int k) { // 9ef0f3
NiceThief_Animate(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
switch (sprite_ai_state[k]) {
case 0:
if ((uint8)(minigame_credits - 1) >= 2 && Sprite_ShowSolicitedMessage(k, 0x181) & 0x100)
sprite_ai_state[k] = 1;
break;
case 1:
if (choice_in_multiselect_box == 0 && ShopItem_HandleCost(100)) {
minigame_credits = 1;
Sprite_ShowMessageUnconditional(0x17f);
sprite_ai_state[k] = 2;
} else {
Sprite_ShowMessageUnconditional(0x180);
sprite_ai_state[k] = 0;
}
break;
case 2:
Sprite_ShowSolicitedMessage(k, (minigame_credits == 0) ? 0x163 : 0x17f);
break;
}
}
void NiceThiefUnderRock(int k) { // 9ef14f
NiceThief_Animate(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
Sprite_ShowSolicitedMessage(k, sprite_subtype2[k] == 5 ? 0x177 : 0x178);
}
void ShopItem_RedPotion150(int k) { // 9ef16e
SpriteDraw_ShopItem(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (ShopItem_CheckForAPress(k)) {
if (Sprite_Find_EmptyBottle() < 0) {
Sprite_ShowMessageUnconditional(0x16d);
ShopItem_PlayBeep(k);
} else if (ShopItem_HandleCost(150)) {
sprite_state[k] = 0;
ShopItem_HandleReceipt(k, 0x2e);
} else {
Sprite_ShowMessageUnconditional(0x17c);
ShopItem_PlayBeep(k);
}
}
}
void ShopKeeper_SpawnShopItem(int k, int pos, int what) { // 9ef1b3
static const int8 kShopKeeper_ItemX[3] = {-44, 8, 60};
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0xbb, &info, 12);
assert(j >= 0);
sprite_ignore_projectile[j] = sprite_subtype2[j] = what;
Sprite_SetX(j, info.r0_x + kShopKeeper_ItemX[pos]);
Sprite_SetY(j, info.r2_y + 0x27);
sprite_flags2[j] |= 4;
}
void ShopItem_FighterShield(int k) { // 9ef1f2
SpriteDraw_ShopItem(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
ShopItem_MakeShieldsDeflect(k);
if (ShopItem_CheckForAPress(k)) {
if (link_shield_type) {
Sprite_ShowMessageUnconditional(0x166);
ShopItem_PlayBeep(k);
return;
}
if (!ShopItem_HandleCost(50)) {
Sprite_ShowMessageUnconditional(0x17c);
ShopItem_PlayBeep(k);
return;
}
sprite_state[k] = 0;
ShopItem_HandleReceipt(k, 4);
}
sprite_flags4[k] = 0x1c;
}
void ShopItem_FireShield(int k) { // 9ef230
SpriteDraw_ShopItem(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
ShopItem_MakeShieldsDeflect(k);
if (ShopItem_CheckForAPress(k)) {
if (link_shield_type >= 2) {
Sprite_ShowMessageUnconditional(0x166);
ShopItem_PlayBeep(k);
return;
}
if (!ShopItem_HandleCost(500)) {
Sprite_ShowMessageUnconditional(0x17c);
ShopItem_PlayBeep(k);
return;
}
sprite_state[k] = 0;
ShopItem_HandleReceipt(k, 5);
}
sprite_flags4[k] = 0x1c;
}
void ShopItem_MakeShieldsDeflect(int k) { // 9ef261
sprite_ignore_projectile[k] = 0;
sprite_flags[k] = 8;
sprite_defl_bits[k] = 4;
sprite_flags4[k] = 0x1c;
Sprite_CheckDamageFromLink(k);
sprite_flags4[k] = 0xa;
}
void ShopItem_Heart(int k) { // 9ef27d
SpriteDraw_ShopItem(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (ShopItem_CheckForAPress(k)) {
if (link_health_current == link_health_capacity) {
ShopItem_PlayBeep(k);
} else if (ShopItem_HandleCost(10)) {
sprite_state[k] = 0;
ShopItem_HandleReceipt(k, 0x42);
} else {
Sprite_ShowMessageUnconditional(0x17c);
ShopItem_PlayBeep(k);
}
}
}
void ShopItem_Arrows(int k) { // 9ef2af
SpriteDraw_ShopItem(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (ShopItem_CheckForAPress(k)) {
if (link_num_arrows == kMaxArrowsForLevel[link_arrow_upgrades]) {
Sprite_ShowSolicitedMessage(k, 0x16e);
ShopItem_PlayBeep(k);
} else if (ShopItem_HandleCost(30)) {
sprite_state[k] = 0;
ShopItem_HandleReceipt(k, 0x44);
} else {
Sprite_ShowMessageUnconditional(0x17c);
ShopItem_PlayBeep(k);
}
}
}
void ShopItem_Bombs(int k) { // 9ef2f0
SpriteDraw_ShopItem(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (ShopItem_CheckForAPress(k)) {
if (link_item_bombs == kMaxBombsForLevel[link_bomb_upgrades]) {
Sprite_ShowSolicitedMessage(k, 0x16e);
ShopItem_PlayBeep(k);
} else if (ShopItem_HandleCost(50)) {
sprite_state[k] = 0;
ShopItem_HandleReceipt(k, 0x31);
} else {
Sprite_ShowMessageUnconditional(0x17c);
ShopItem_PlayBeep(k);
}
}
}
void ShopItem_Bee(int k) { // 9ef322
SpriteDraw_ShopItem(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (ShopItem_CheckForAPress(k)) {
if (Sprite_Find_EmptyBottle() < 0) {
Sprite_ShowSolicitedMessage(k, 0x16d);
ShopItem_PlayBeep(k);
} else if (ShopItem_HandleCost(10)) {
sprite_state[k] = 0;
ShopItem_HandleReceipt(k, 0xe);
} else {
Sprite_ShowMessageUnconditional(0x17c);
ShopItem_PlayBeep(k);
}
}
}
void ShopItem_HandleReceipt(int k, uint8 item) { // 9ef366
static const uint16 kShopKeeper_GiveItemMsgs[7] = {0x168, 0x167, 0x167, 0x16c, 0x169, 0x16a, 0x16b};
item_receipt_method = 0;
Link_ReceiveItem(item, 0);
int j = sprite_subtype2[k];
if (j >= 7) {
Sprite_ShowMessageUnconditional(kShopKeeper_GiveItemMsgs[j - 7]);
ShopKeeper_RapidTerminateReceiveItem();
}
}
void ShopItem_PlayBeep(int k) { // 9ef38a
SpriteSfx_QueueSfx2WithPan(k, 0x3c);
}
bool ShopItem_CheckForAPress(int k) { // 9ef391
if (!(filtered_joypad_L & 0x80))
return false;
return Sprite_CheckDamageToLink_same_layer(k);
}
bool ShopItem_HandleCost(int amt) { // 9ef39e
if (amt > link_rupees_goal)
return false;
link_rupees_goal -= amt;
return true;
}
void SpriteDraw_ShopItem(int k) { // 9ef4ce
static const DrawMultipleData kShopKeeper_ItemWithPrice_Dmd[35] = {
{-4, 16, 0x0231, 0},
{ 4, 16, 0x0213, 0},
{12, 16, 0x0230, 0},
{ 0, 0, 0x02c0, 2},
{ 0, 11, 0x036c, 2},
{ 0, 16, 0x0213, 0},
{ 0, 16, 0x0213, 0},
{ 8, 16, 0x0230, 0},
{ 0, 0, 0x04ce, 2},
{ 4, 12, 0x0338, 0},
{-4, 16, 0x0213, 0},
{ 4, 16, 0x0230, 0},
{12, 16, 0x0230, 0},
{ 0, 0, 0x08cc, 2},
{ 4, 12, 0x0338, 0},
{ 0, 16, 0x0231, 0},
{ 0, 16, 0x0231, 0},
{ 8, 16, 0x0230, 0},
{ 4, 8, 0x0329, 0},
{ 4, 11, 0x0338, 0},
{-4, 16, 0x0203, 0},
{-4, 16, 0x0203, 0},
{ 4, 16, 0x0230, 0},
{ 0, 0, 0x04c4, 2},
{ 0, 11, 0x0338, 0},
{ 0, 16, 0x0213, 0},
{ 0, 16, 0x0213, 0},
{ 8, 16, 0x0230, 0},
{ 0, 0, 0x04e8, 2},
{ 0, 11, 0x036c, 2},
{ 0, 16, 0x0231, 0},
{ 0, 16, 0x0231, 0},
{ 8, 16, 0x0230, 0},
{ 4, 8, 0x0ff4, 0},
{ 4, 11, 0x0338, 0},
};
Sprite_DrawMultiplePlayerDeferred(k, &kShopKeeper_ItemWithPrice_Dmd[(sprite_subtype2[k] - 7) * 5], 5, NULL);
}
void Sprite_AC_Apple(int k) { // 9ef515
if (sprite_ai_state[k]) {
Sprite_Apple(k);
return;
}
if (sprite_E[k] == 0) {
sprite_state[k] = 0;
int n = (GetRandomNumber() & 3) + 2;
do {
SpawnApple(k);
} while (--n >= 0);
}
}
void SpawnApple(int k) { // 9ef535
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xac, &info);
if (j < 0)
return;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_ai_state[j] = 1;
sprite_A[j] = 255;
sprite_z[j] = 8;
sprite_z_vel[j] = 22;
uint16 x = info.r0_x & ~0xff | GetRandomNumber();
uint16 y = info.r2_y & ~0xff | GetRandomNumber();
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 10);
sprite_x_vel[j] = pt.x;
sprite_y_vel[j] = pt.y;
}
void Sprite_Apple(int k) { // 9ef57c
if (sprite_A[k] >= 16 || frame_counter & 2)
SpriteDraw_SingleLarge(k);
if (Sprite_ReturnIfInactive(k))
return;
if (sprite_A[k] == 0) {
sprite_state[k] = 0;
return;
}
Sprite_MoveXYZ(k);
if (Sprite_CheckDamageToLink(k)) {
SpriteSfx_QueueSfx3WithPan(k, 0xb);
link_hearts_filler += 8;
sprite_state[k] = 0;
return;
}
if (!(frame_counter & 1))
sprite_A[k]--;
if (!sign8(sprite_z[k] - 1)) {
sprite_z_vel[k] -= 1;
return;
}
sprite_z[k] = 0;
uint8 a = sign8(sprite_z_vel[k]) ? sprite_z_vel[k] : 0;
sprite_z_vel[k] = (uint8)(-a) >> 1;
if (sprite_x_vel[k])
sprite_x_vel[k] += sign8(sprite_x_vel[k]) ? 1 : -1;
if (sprite_y_vel[k])
sprite_y_vel[k] += sign8(sprite_y_vel[k]) ? 1 : -1;
}
void Sprite_BC_Drunkard(int k) { // 9ef603
DrinkingGuy_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
Sprite_BehaveAsBarrier(k);
if (!GetRandomNumber())
sprite_delay_main[k] = 32;
sprite_graphics[k] = sprite_delay_main[k] ? 1 : 0;
if (Sprite_ShowSolicitedMessage(k, 0x175) & 0x100)
sprite_graphics[k] = 0;
}
void SomariaPlatform_LocatePath(int k) { // 9ef640
for (;;) {
uint8 tiletype = SomariaPlatformAndPipe_CheckTile(k);
sprite_E[k] = tiletype;
if (tiletype >= 0xb0 && tiletype < 0xbf)
break;
Sprite_SetX(k, Sprite_GetX(k) + 8);
Sprite_SetY(k, Sprite_GetY(k) + 8);
}
sprite_x_lo[k] = (sprite_x_lo[k] & ~7) + 4;
sprite_y_lo[k] = (sprite_y_lo[k] & ~7) + 4;
sprite_head_dir[k] = sprite_D[k];
SomariaPlatformAndPipe_HandleMovement(k);
sprite_ignore_projectile[k]++;
player_on_somaria_platform = 0;
sprite_delay_aux4[k] = 14;
sprite_graphics[k]++;
}
void Sprite_SomariaPlatform(int k) { // 9ef6d4
switch(sprite_graphics[k]) {
case 0: {
SomariaPlatform_LocatePath(k);
int j = Sprite_SpawnSuperficialBombBlast(k);
if (j >= 0) {
Sprite_SetX(j, Sprite_GetX(j) - 8);
Sprite_SetY(j, Sprite_GetY(j) - 8);
}
break;
}
case 1:
SomariaPlatform_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (!(drag_player_x | drag_player_y) && sign8(player_near_pit_state - 2) && Sprite_CheckDamageToLink_ignore_layer(k)) {
sprite_C[k] = 1;
Link_CancelDash();
if (link_player_handler_state != kPlayerState_Hookshot && link_player_handler_state != kPlayerState_SpinAttacking) {
if (sprite_ai_state[k]) {
SomariaPlatformAndPipe_HandleMovement(k);
return;
}
sprite_A[k]++;
player_on_somaria_platform = 2;
if (!(sprite_A[k] & 7)) {
uint8 a = SomariaPlatformAndPipe_CheckTile(k);
if (a != sprite_E[k]) {
sprite_E[k] = a;
sprite_head_dir[k] = sprite_D[k];
SomariaPlatformAndPipe_HandleMovement(k);
SomariaPlatform_HandleDrag(k);
}
}
if (BYTE(dungeon_room_index) != 36) {
static const int8 kSomariaPlatform_DragX[8] = {0, 0, -1, 1, -1, 1, 1, -1};
static const int8 kSomariaPlatform_DragY[8] = {-1, 1, 0, 0, -1, 1, -1, 1};
int j = sprite_D[k];
drag_player_x += kSomariaPlatform_DragX[j];
drag_player_y += kSomariaPlatform_DragY[j];
Sprite_MoveXY(k);
SomariaPlatform_DragLink(k);
} else {
player_on_somaria_platform = 1;
}
return;
}
}
if (sprite_C[k]) {
player_on_somaria_platform = 0;
sprite_C[k] = 0;
}
break;
}
}
void SomariaPlatformAndPipe_HandleMovement(int k) { // 9ef7af
static const int8 kSomariaPlatform_Xvel[8] = {0, 0, -16, 16, -16, 16, 16, -16};
static const int8 kSomariaPlatform_Yvel[8] = {-16, 16, 0, 0, -16, 16, -16, 16};
SomariaPlatform_HandleJunctions(k);
int j = sprite_D[k];
sprite_x_vel[k] = kSomariaPlatform_Xvel[j];
sprite_y_vel[k] = kSomariaPlatform_Yvel[j];
}
uint8 SomariaPlatformAndPipe_CheckTile(int k) { // 9ef7c2
uint16 x = Sprite_GetX(k), y = Sprite_GetY(k);
return GetTileAttribute(0, &x, y);
}
void SomariaPlatform_Draw(int k) { // 9ef860
static const DrawMultipleData kSomariaPlatform_Dmd[16] = {
{-16, -16, 0x00ac, 2},
{ 0, -16, 0x40ac, 2},
{-16, 0, 0x80ac, 2},
{ 0, 0, 0xc0ac, 2},
{-13, -13, 0x00ac, 2},
{ -3, -13, 0x40ac, 2},
{-13, -3, 0x80ac, 2},
{ -3, -3, 0xc0ac, 2},
{-10, -10, 0x00ac, 2},
{ -6, -10, 0x40ac, 2},
{-10, -6, 0x80ac, 2},
{ -6, -6, 0xc0ac, 2},
{ -8, -8, 0x00ac, 2},
{ -8, -8, 0x40ac, 2},
{ -8, -8, 0x80ac, 2},
{ -8, -8, 0xc0ac, 2},
};
Oam_AllocateFromRegionB(0x10);
Sprite_DrawMultiple(k, &kSomariaPlatform_Dmd[sprite_delay_aux4[k] & 12], 4, NULL);
}
void SomariaPlatform_HandleJunctions(int k) { // 9ef87d
switch (sprite_E[k]) {
case 0xb2:
case 0xb5: // ZigZagRisingSlope
sprite_D[k] ^= 3;
break;
case 0xb3:
case 0xb4: // ZigZagFallingSlope
sprite_D[k] ^= 2;
break;
case 0xb6: { // TransitTile
static const uint8 kSomariaPlatform_TransitDir[4] = {4, 8, 1, 2};
sprite_ai_state[k] = 1;
if (!link_auxiliary_state && joypad1H_last & kSomariaPlatform_TransitDir[sprite_D[k]]) {
sprite_ai_state[k] = 0;
sprite_D[k] ^= 1;
}
link_visibility_status = 0;
player_on_somaria_platform = 1;
break;
}
case 0xb7: { // Tjunc_NoUp
static const uint8 kSomariaPlatform_Keys1[4] = {3, 7, 6, 5};
uint8 t = joypad1H_last & kSomariaPlatform_Keys1[sprite_D[k]];
if (t & 8) {
sprite_D[k] = 0;
} else if (t & 4) {
sprite_D[k] = 1;
} else if (t & 2) {
sprite_D[k] = 2;
} else if (t & 1) {
sprite_D[k] = 3;
} else if (sprite_D[k] == 0) {
sprite_D[k] = 2;
}
sprite_ai_state[k] = 0;
break;
}
case 0xb8: { // Tjunc_NoDown
static const uint8 kSomariaPlatform_Keys2[4] = {11, 3, 10, 9};
uint8 t = joypad1H_last & kSomariaPlatform_Keys2[sprite_D[k]];
if (t & 8) {
sprite_D[k] = 0;
} else if (t & 4) {
sprite_D[k] = 1;
} else if (t & 2) {
sprite_D[k] = 2;
} else if (t & 1) {
sprite_D[k] = 3;
} else if (sprite_D[k] == 1) {
sprite_D[k] = 2;
}
sprite_ai_state[k] = 0;
break;
}
case 0xb9: { // Tjunc_NoLeft
static const uint8 kSomariaPlatform_Keys3[4] = {9, 5, 12, 13};
uint8 t = joypad1H_last & kSomariaPlatform_Keys3[sprite_D[k]];
if (t & 8) {
sprite_D[k] = 0;
} else if (t & 4) {
sprite_D[k] = 1;
} else if (t & 2) {
sprite_D[k] = 2;
} else if (t & 1) {
sprite_D[k] = 3;
} else if (sprite_D[k] == 2) {
sprite_D[k] = 0;
}
sprite_ai_state[k] = 0;
break;
}
case 0xba: { // Tjunc_NoRight
static const uint8 kSomariaPlatform_Keys4[4] = {0xa, 6, 0xe, 0xc};
uint8 t = joypad1H_last & kSomariaPlatform_Keys4[sprite_D[k]];
if (t & 8) {
sprite_D[k] = 0;
} else if (t & 4) {
sprite_D[k] = 1;
} else if (t & 2) {
sprite_D[k] = 2;
} else if (t & 1) {
sprite_D[k] = 3;
} else if (sprite_D[k] == 3) {
sprite_D[k] = 0;
}
sprite_ai_state[k] = 0;
break;
}
case 0xbb: { // TransitTileNoBack
static const uint8 kSomariaPlatform_Keys5[4] = {0xb, 7, 0xe, 0xd};
uint8 t = joypad1H_last & kSomariaPlatform_Keys5[sprite_D[k]];
if (t & 8) {
sprite_D[k] = 0;
} else if (t & 4) {
sprite_D[k] = 1;
} else if (t & 2) {
sprite_D[k] = 2;
} else if (t & 1) {
sprite_D[k] = 3;
}
break;
}
case 0xbc: { // TransitTileQuestion
static const uint8 kSomariaPlatform_Keys6[4] = {0xc, 0xc, 3, 3};
sprite_ai_state[k] = 1;
uint8 t = joypad1H_last & kSomariaPlatform_Keys6[sprite_D[k]];
if (t) {
if (t & 8) {
sprite_D[k] = 0;
} else if (t & 4) {
sprite_D[k] = 1;
} else if (t & 2) {
sprite_D[k] = 2;
} else {
sprite_D[k] = 3;
}
sprite_ai_state[k] = 0;
}
player_on_somaria_platform = 1;
break;
}
case 0xbe: // endpoint
sprite_ai_state[k] = 0;
sprite_D[k] ^= 1;
link_visibility_status = 0;
player_on_somaria_platform = 1;
break;
}
}
void SomariaPlatform_HandleDragX(int k) { // 9ef8ad
if ((sprite_D[k] ^ sprite_head_dir[k]) & 2) {
uint8 x = (sprite_x_lo[k] & ~7) + 4;
uint8 t = x - sprite_x_lo[k];
if (!t)
return;
drag_player_x = (int8)t;
sprite_x_lo[k] = x;
}
}
void SomariaPlatform_HandleDragY(int k) { // 9ef8d7
if ((sprite_D[k] ^ sprite_head_dir[k]) & 2) {
uint8 y = (sprite_y_lo[k] & ~7) + 4;
uint8 t = y - sprite_y_lo[k];
if (!t)
return;
drag_player_y = (int8)t;
sprite_y_lo[k] = y;
}
}
void SomariaPlatform_HandleDrag(int k) { // 9ef901
SomariaPlatform_HandleDragX(k);
SomariaPlatform_HandleDragY(k);
}
void SomariaPlatform_DragLink(int k) { // 9efb49
uint16 x = cur_sprite_x - 8 - link_x_coord;
if (x)
drag_player_x += sign16(x) ? -1 : 1;
uint16 y = cur_sprite_y - 16 - link_y_coord;
if (y)
drag_player_y += sign16(y) ? -1 : 1;
}
void Sprite_AE_Pipe_Down(int k) { // 9efb7e
static const uint8 kPipe_Dirs[4] = {8, 4, 2, 1};
uint8 t;
if (Sprite_ReturnIfInactive(k))
return;
switch(sprite_graphics[k]) {
case 0: // locate transit tile
alt_sprite_spawned_flag[0] = 255;
sprite_D[k] = sprite_type[k] - 0xae;
SomariaPlatform_LocatePath(k);
break;
case 1: // locate endpoint
t = SomariaPlatformAndPipe_CheckTile(k);
if (t == 0xbe) {
sprite_graphics[k]++;
t = (sprite_D[k] ^= 1);
}
sprite_E[k] = t;
sprite_head_dir[k] = sprite_D[k];
SomariaPlatformAndPipe_HandleMovement(k);
Sprite_MoveXY(k);
break;
case 2: // wait for player
if (alt_sprite_spawned_flag[0] == 255 && Sprite_CheckDamageToLink_ignore_layer(k)) {
if (!Pipe_ValidateEntry()) {
sprite_graphics[k]++;
sprite_delay_aux1[k] = 4;
Link_ResetProperties_A();
flag_is_link_immobilized = 1;
link_disable_sprite_damage = 1;
alt_sprite_spawned_flag[0] = k;
} else {
Sprite_HaltAllMovement();
}
}
break;
case 3: // draw player in
if (!sprite_delay_aux1[k]) {
sprite_graphics[k]++;
link_visibility_status = 12;
} else {
flag_is_link_immobilized = 1;
link_disable_sprite_damage = 1;
Pipe_HandlePlayerMovement(kPipe_Dirs[sprite_D[k]]);
}
break;
case 4: { // draw player along
sprite_subtype2[k] = 3;
link_x_coord_safe_return_lo = link_x_coord;
link_x_coord_safe_return_hi = link_x_coord >> 8;
link_y_coord_safe_return_lo = link_y_coord;
link_y_coord_safe_return_hi = link_y_coord >> 8;
do {
if (!(++sprite_A[k] & 7)) {
uint8 t = SomariaPlatformAndPipe_CheckTile(k);
if (t >= 0xb2 && t < 0xb6)
SpriteSfx_QueueSfx2WithPan(k, 0xb);
if (t != sprite_E[k]) {
sprite_E[k] = t;
if (t == 0xbe) {
sprite_graphics[k]++;
sprite_delay_aux1[k] = 24;
}
sprite_head_dir[k] = sprite_D[k];
SomariaPlatformAndPipe_HandleMovement(k);
SomariaPlatform_HandleDrag(k);
}
}
Sprite_MoveXY(k);
uint16 x = Sprite_GetX(k) - 8;
uint16 y = Sprite_GetY(k) - 14;
if (x != link_x_coord)
link_x_coord += (x < link_x_coord) ? -1 : 1;
if (y != link_y_coord)
link_y_coord += (y < link_y_coord) ? -1 : 1;
} while (--sprite_subtype2[k]);
link_x_vel = link_x_coord - link_x_coord_safe_return_lo;
link_y_vel = link_y_coord - link_y_coord_safe_return_lo;
link_direction_last = kPipe_Dirs[sprite_D[k]];
Link_HandleMovingAnimation_FullLongEntry();
HandleIndoorCameraAndDoors();
Link_CancelDash();
break;
}
case 5: //
if (!sprite_delay_aux1[k]) {
flag_is_link_immobilized = 0;
player_on_somaria_platform = 0;
link_disable_sprite_damage = 0;
link_visibility_status = 0;
link_x_vel = link_y_vel = 0;
alt_sprite_spawned_flag[0] = 255;
sprite_graphics[k] = 2;
} else {
Pipe_HandlePlayerMovement(kPipe_Dirs[sprite_D[k] ^ 1]);
}
break;
}
}
void Pipe_HandlePlayerMovement(uint8 dir) { // 9efcff
link_direction_last = link_direction = dir;
Link_HandleVelocity();
Link_HandleMovingAnimation_FullLongEntry();
HandleIndoorCameraAndDoors();
}
void Faerie_HandleMovement(int k) { // 9efd1c
sprite_graphics[k] = frame_counter >> 3 & 1;
if (player_is_indoors && !sprite_delay_aux1[k]) {
if (Sprite_CheckTileCollision(k) & 3) {
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_D[k] = -sprite_D[k];
sprite_delay_aux1[k] = 32;
}
if (sprite_wallcoll[k] & 12) {
sprite_y_vel[k] = -sprite_y_vel[k];
sprite_A[k] = -sprite_A[k];
sprite_delay_aux1[k] = 32;
}
}
if (sprite_x_vel[k]) {
if (sign8(sprite_x_vel[k]))
sprite_oam_flags[k] &= ~0x40;
else
sprite_oam_flags[k] |= 0x40;
}
Sprite_MoveXY(k);
if (!(frame_counter & 63)) {
uint16 x = (link_x_coord & ~0xff) + GetRandomNumber();
uint16 y = (link_y_coord & ~0xff) + GetRandomNumber();
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(k, x, y, 16);
sprite_A[k] = pt.y;
sprite_D[k] = pt.x;
}
if (!(frame_counter & 15)) {
sprite_y_vel[k] = ((int8)sprite_A[k] + (int8)sprite_y_vel[k]) >> 1;
sprite_x_vel[k] = ((int8)sprite_D[k] + (int8)sprite_x_vel[k]) >> 1;
}
Sprite_MoveZ(k);
sprite_z_vel[k] += (GetRandomNumber() & 1) ? -1 : 1;
if (sprite_z[k] < 8) {
sprite_z[k] = 8;
sprite_z_vel[k] = 5;
} else if (sprite_z[k] >= 24) {
sprite_z[k] = 24;
sprite_z_vel[k] = -5;
}
}