ref: 6ccbc7fba30bab731577a0ce4512bec6ce420e8f
dir: /ancilla.c/
#include "ancilla.h"
#include "variables.h"
#include "sprite.h"
#include "hud.h"
#include "load_gfx.h"
#include "tagalong.h"
#include "overworld.h"
#include "tile_detect.h"
#include "player.h"
#include "misc.h"
#include "dungeon.h"
#include "sprite_main.h"
#include "assets.h"
static const uint8 kAncilla_Pflags[68] = {
0, 8, 0xc, 0x10, 0x10, 4, 0x10, 0x18, 8, 8, 8, 0, 0x14, 0, 0x10, 0x28,
0x18, 0x10, 0x10, 0x10, 0x10, 0xc, 8, 8, 0x50, 0, 0x10, 8, 0x40, 0, 0xc, 0x24,
0x10, 0xc, 8, 0x10, 0x10, 4, 0xc, 0x1c, 0, 0x10, 0x14, 0x14, 0x10, 8, 0x20, 0x10,
0x10, 0x10, 4, 0, 0x80, 0x10, 4, 0x30, 0x14, 0x10, 0, 0x10, 0, 0, 8, 0,
0x10, 8, 0x78, 0x80,
};
static const int8 kFireRod_Xvel2[12] = {0, 0, -40, 40, 0, 0, -48, 48, 0, 0, -64, 64};
static const int8 kFireRod_Yvel2[12] = {-40, 40, 0, 0, -48, 48, 0, 0, -64, 64, 0, 0};
static const uint8 kTagalongLayerBits[4] = {0x20, 0x10, 0x30, 0x20};
static const uint8 kBombos_Sfx[8] = {0x80, 0x80, 0x80, 0, 0, 0x40, 0x40, 0x40};
const uint8 kBomb_Tab0[11] = {0xA0, 6, 4, 4, 4, 4, 4, 6, 6, 6, 6};
#define swordbeam_temp_x (*(uint16*)(g_ram+0x1580E))
#define swordbeam_temp_y (*(uint16*)(g_ram+0x15810))
#define swordbeam_arr ((uint8*)(g_ram+0x15800))
#define swordbeam_var1 (*(uint8*)(g_ram+0x15804))
#define swordbeam_var2 (*(uint8*)(g_ram+0x15808))
static const int8 kAncilla_TileColl_Attrs[256] = {
0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 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, 0, 0, 0, 0, 0, 3, 3, 3,
0, 0, 0, 1, 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, 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,
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 kAncilla_TileColl0_Attrs[256] = {
0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 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, 0, 0, 0, 0, 0, 3, 3, 3,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 1, 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,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 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,
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,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
static const uint8 kBomb_Draw_Tab0[12] = {0, 1, 2, 3, 2, 3, 4, 5, 6, 7, 8, 9};
static const uint8 kBomb_Draw_Tab2[11] = {1, 4, 4, 4, 4, 4, 5, 4, 6, 6, 6};
static const uint8 kMagicPowder_Tab0[40] = {
13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 0, 1, 2,
3, 4, 5, 6, 16, 17, 18, 0, 1, 2, 3, 4, 5, 6, 7, 8,
9, 0, 1, 2, 3, 4, 5, 6,
};
#define ether_arr1 ((uint8*)(g_ram+0x15800))
#define ether_var2 (*(uint8*)(g_ram+0x15808))
#define ether_y2 (*(uint16*)(g_ram+0x1580A))
#define ether_y_adjusted (*(uint16*)(g_ram+0x1580C))
#define ether_x2 (*(uint16*)(g_ram+0x1580E))
#define ether_y3 (*(uint16*)(g_ram+0x15810))
#define ether_var1 (*(uint8*)(g_ram+0x15812))
#define ether_y (*(uint16*)(g_ram+0x15813))
#define ether_x (*(uint16*)(g_ram+0x15815))
static const uint8 kEther_BlitzOrb_Char[8] = {0x48, 0x48, 0x4a, 0x4a, 0x4c, 0x4c, 0x4e, 0x4e};
static const uint8 kEther_BlitzOrb_Flags[8] = {0x3c, 0x7c, 0x3c, 0x7c, 0x3c, 0x7c, 0x3c, 0x7c};
static const uint8 kEther_BlitzSegment_Char[4] = {0x40, 0x42, 0x44, 0x46};
#define bombos_arr1 ((uint8*)(g_ram+0x15800))
#define bombos_arr2 ((uint8*)(g_ram+0x15810))
static const uint8 kBombosBlasts_Tab[72] = {
0xb6, 0x5d, 0xa1, 0x30, 0x69, 0xb5, 0xa3, 0x24, 0x96, 0xac, 0x73, 0x5f, 0x92, 0x48, 0x52, 0x81,
0x39, 0x95, 0x7f, 0x20, 0x88, 0x5d, 0x34, 0x98, 0xbc, 0xd2, 0x51, 0x77, 0xa2, 0x47, 0x94, 0xb2,
0x34, 0xda, 0x30, 0x62, 0x9f, 0x76, 0x51, 0x46, 0x98, 0x5c, 0x9b, 0x61, 0x58, 0x95, 0x4c, 0xba,
0x7e, 0xcb, 0x12, 0xd0, 0x70, 0xa6, 0x46, 0xbf, 0x40, 0x50, 0x7e, 0x8c, 0x2d, 0x61, 0xac, 0x88,
0x20, 0x6a, 0x72, 0x5f, 0xd2, 0x28, 0x52, 0x80,
};
static const uint8 kQuake_Tab1[5] = {0x17, 0x16, 0x17, 0x16, 0x10};
static const uint8 kQuakeDrawGroundBolts_Char[15] = { 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x63 };
typedef struct QuakeItem {
int8 x, y;
uint8 f;
} QuakeItem;
static const QuakeItem kQuakeItems[] = {
{0, -16, 0x00},
{0, -16, 0x01},
{0, -16, 0x02},
{0, -16, 0x03},
{0, -16, 0x43},
{0, -16, 0x42},
{0, -16, 0x41},
{0, -16, 0x40},
{0, -16, 0x40}, {14, -8, 0x84},
{29, -8, 0x44}, {13, -7, 0x84},
{31, -7, 0x44}, {47, -4, 0x84},
{49, -11, 0x06}, {63, -5, 0x44}, {47, -4, 0x84},
{36, -17, 0x08}, {49, -11, 0x06}, {63, -5, 0x44}, {78, 4, 0x08},
{22, -31, 0x08}, {36, -17, 0x08}, {78, 4, 0x08}, {93, 20, 0x08},
{7, -46, 0x08}, {23, -45, 0x48}, {22, -31, 0x08}, {93, 20, 0x08}, {93, 36, 0x48},
{-7, -61, 0x08}, {37, -59, 0x48}, {7, -46, 0x08}, {23, -45, 0x48}, {93, 36, 0x48}, {93, 52, 0x08},
{-22, -75, 0x08}, {47, -74, 0x01}, {-8, -61, 0x08}, {36, -60, 0x48}, {93, 52, 0x08}, {108, 67, 0x08},
{-37, -90, 0x08}, {-22, -75, 0x08}, {47, -74, 0x01}, {59, -62, 0x81}, {108, 67, 0x08}, {121, 80, 0x08},
{-44, -104, 0xc9}, {-37, -90, 0x08}, {73, -74, 0x48}, {59, -62, 0x81}, {121, 80, 0x08},
{-44, -120, 0x09}, {-44, -104, 0xc9}, {87, -89, 0x48}, {73, -74, 0x48},
{-44, -120, 0x09}, {102, -104, 0x48}, {87, -89, 0x48},
{102, -104, 0x48}, {87, -89, 0x48},
{112, -116, 0x48}, {102, -104, 0x48},
{112, -116, 0x48},
{-13, -16, 0x00},
{-13, -16, 0x01},
{-13, -16, 0x02},
{-13, -16, 0x03},
{-11, -16, 0x43},
{-11, -16, 0x42},
{-11, -16, 0x41},
{-11, -16, 0x40}, {-24, -10, 0x04},
{-38, -18, 0x08}, {-24, -10, 0x04}, {-40, -7, 0xc4},
{-45, -33, 0xc9}, {-38, -18, 0x08}, {-57, -7, 0x04}, {-40, -7, 0xc4},
{-48, -45, 0x07}, {-45, -33, 0xc9}, {-57, -7, 0x04}, {-71, 2, 0x48},
{-48, -45, 0x06}, {-71, 2, 0x48}, {-70, 18, 0x08},
{-48, -45, 0x05}, {-70, 18, 0x08}, {-56, 33, 0x08},
{-48, -45, 0x07}, {-54, 34, 0x08}, {-54, 49, 0x88},
{-48, -45, 0x06}, {-54, 49, 0x88}, {-69, 64, 0x88},
{-48, -45, 0x07}, {-69, 64, 0x88}, {-85, 73, 0xc4},
{-48, -45, 0x05}, {-101, 73, 0x04}, {-85, 73, 0xc4},
{-60, -53, 0x08}, {-48, -45, 0x06}, {-101, 73, 0x04}, {-116, 77, 0xc4},
{-75, -67, 0x08}, {-60, -53, 0x08}, {-128, 76, 0x04}, {-116, 77, 0xc4},
{-90, -82, 0x08}, {-75, -67, 0x08}, {-128, 76, 0x04},
{-105, -97, 0x08}, {-90, -82, 0x08},
{-120, -111, 0x08}, {-105, -97, 0x08},
{-120, -111, 0x08},
{0, -5, 0x0a},
{0, -5, 0x0b},
{2, -3, 0x0c},
{1, -3, 0x0d},
{0, -3, 0x8d},
{1, -3, 0x8c},
{1, -3, 0x8b},
{1, -3, 0x8a}, {-6, 12, 0x89},
{-6, 12, 0x89}, {-10, 28, 0xc9},
{-10, 28, 0x49}, {-8, 44, 0x89},
{-8, 44, 0x89}, {-10, 56, 0x02},
{-10, 56, 0x02}, {-23, 70, 0x48}, {5, 70, 0x08},
{-23, 70, 0x48}, {5, 70, 0x08}, {-38, 85, 0x48}, {19, 85, 0x08},
{-38, 85, 0x48}, {19, 85, 0x08}, {-52, 99, 0x48}, {33, 101, 0x08},
{-52, 99, 0x48}, {33, 101, 0x08}, {-66, 113, 0x48}, {47, 115, 0x08},
{-66, 113, 0x48}, {47, 115, 0x08},
};
static const uint8 kQuakeItemPos[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 17, 21, 25, 30,
36, 42, 48, 53, 57, 60, 62, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 77, 81, 85, 88, 91, 94, 97, 100, 103, 107, 111, 114, 116, 118, 119, 120, 121, 122, 123, 124, 125, 126, 128, 130, 132, 134, 137, 141, 145, 149, 151
};
static const QuakeItem kQuakeItems2[] = {
{-96, 112, 0x20},
{-96, 112, 0x21},
{-96, 112, 0x66},
{-96, 112, 0x22},
{-96, 112, 0x23},
{-96, 112, 0x63},
{-96, 112, 0x62},
{-96, 112, 0x26},
{-96, 112, 0x27}, {-86, 124, 0x28},
{-86, 124, 0x28}, {-72, -117, 0x28},
{-72, -117, 0x28}, {-59, -102, 0xa1},
{-59, -102, 0xa1}, {-44, -116, 0x68},
{-44, -116, 0x68}, {-29, 126, 0x68},
{-29, 126, 0x68},
{-19, 125, 0xc5},
{-112, 96, 0x2a},
{-112, 96, 0x2b},
{-112, 96, 0x2c},
{-112, 96, 0x2d},
{-119, 82, 0x29}, {-112, 96, 0x2a},
{-123, 66, 0xe9}, {-119, 82, 0x29},
{-121, 50, 0x29}, {-123, 66, 0xe9},
{126, 34, 0x28}, {-115, 34, 0x68}, {-121, 50, 0x29},
{-106, 18, 0xa9}, {111, 19, 0x28}, {126, 34, 0x28}, {-115, 34, 0x68},
{-100, 2, 0x68}, {102, 4, 0xe9}, {-106, 18, 0xa9}, {111, 19, 0x28},
{-91, -14, 0xa9}, {95, -11, 0x28}, {-100, 2, 0x68}, {102, 4, 0xe9},
{96, 112, 0x60},
{96, 112, 0x61},
{96, 112, 0x26},
{96, 112, 0x62},
{96, 112, 0x63},
{96, 112, 0x23},
{96, 112, 0x22},
{96, 112, 0x66},
{85, 111, 0xe8}, {96, 112, 0x67},
{70, 104, 0x24}, {85, 111, 0xe8},
{70, 104, 0x24}, {54, 108, 0xe4},
{40, 100, 0x28}, {38, 107, 0x24}, {54, 108, 0xe4},
{25, 85, 0x28}, {40, 100, 0x28}, {38, 107, 0x24}, {22, 110, 0xe4},
{11, 70, 0x28}, {25, 85, 0x28}, {7, 108, 0x24}, {22, 110, 0xe4},
{11, 70, 0x28}, {7, 108, 0x24},
{112, 112, 0x2a},
{112, 112, 0x2b},
{112, 112, 0x2c},
{112, 112, 0x2d},
{112, 112, 0x2a}, {108, 125, 0x29},
{108, 125, 0x29}, {114, -116, 0x28},
{114, -116, 0x28}, {124, -100, 0x29},
{124, -100, 0x29}, {123, -84, 0xe9},
{123, -84, 0xe9}, {117, -74, 0xe4}, {-124, -69, 0x28},
{117, -74, 0xe4}, {-124, -69, 0x28}, {103, -67, 0x68}, {-110, -54, 0x28},
{103, -67, 0x68}, {-110, -54, 0x28}, {95, -52, 0x69}, {-102, -39, 0x29},
{95, -52, 0x69}, {-102, -39, 0x29}, {96, -36, 0xe9}, {-102, -24, 0xe9},
{96, -36, 0xe9}, {-102, -24, 0xe9},
{-123, -14, 0x29}, {-115, -14, 0x2e}, {49, -12, 0x28},
};
static const uint8 kQuakeItemPos2[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 19, 20, 21, 22, 23, 24, 26, 28, 30, 33, 37, 41, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 57, 59, 62, 66, 70, 72, 73, 74, 75, 76, 78, 80, 82, 84, 87, 91, 95, 99, 101, 104
};
static const uint8 kReceiveItem_Tab4[3] = {9, 5, 5};
static const uint8 kReceiveItem_Tab5[3] = {0x24, 0x25, 0x26};
static const uint8 kReceiveItem_Tab0[3] = {5, 1, 4};
static const int16 kReceiveItemMsgs[76] = {
-1, 0x70, 0x77, 0x52, -1, 0x78, 0x78, 0x62, 0x61, 0x66, 0x69, 0x53, 0x52, 0x56, -1, 0x64,
0x63, 0x65, 0x51, 0x54, 0x67, 0x68, 0x6b, 0x77, 0x79, 0x55, 0x6e, 0x58, 0x6d, 0x5d, 0x57, 0x5e,
-1, 0x74, 0x75, 0x76, -1, 0x5f, 0x158, -1, 0x6a, 0x5c, 0x8f, 0x71, 0x72, 0x73, 0x71, 0x72,
0x73, 0x6a, 0x6c, 0x60, -1, -1, -1, 0x59, 0x84, 0x5a, -1, -1, -1, -1, -1, 0x159,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 0xdb, 0x67, 0x7c,
};
static const int16 kReceiveItemMsgs2[2] = {0x5b, 0x83};
static const int16 kReceiveItemMsgs3[4] = {-1, 0x155, 0x156, 0x157};
static const uint8 kTravelBird_DmaStuffs[4] = {0, 0x20, 0x40, 0xe0};
static const int8 kTravelBird_Draw_X[3] = {0, -9, -9};
static const int8 kTravelBird_Draw_Y[3] = {0, 12, 20};
static const uint8 kTravelBird_Draw_Char[3] = {0xe, 0, 2};
static const uint8 kTravelBird_Draw_Flags[3] = {0x22, 0x2e, 0x2e};
static const int8 kSomarianBlock_Coll_X[12] = {0, 0, -8, 8, 0, 0, 0, 0, 8, -8, -8, 8};
static const int8 kSomarianBlock_Coll_Y[12] = {-8, 8, 0, 0, 0, 0, 0, 0, -8, 8, -8, 8};
static HandlerFuncK *const kAncilla_Funcs[67] = {
&Ancilla01_SomariaBullet,
&Ancilla02_FireRodShot,
&Ancilla_Empty,
&Ancilla04_BeamHit,
&Ancilla05_Boomerang,
&Ancilla06_WallHit,
&Ancilla07_Bomb,
&Ancilla08_DoorDebris,
&Ancilla09_Arrow,
&Ancilla0A_ArrowInTheWall,
&Ancilla0B_IceRodShot,
&Ancilla_SwordBeam,
&Ancilla0D_SpinAttackFullChargeSpark,
&Ancilla33_BlastWallExplosion,
&Ancilla33_BlastWallExplosion,
&Ancilla33_BlastWallExplosion,
&Ancilla11_IceRodWallHit,
&Ancilla33_BlastWallExplosion,
&Ancilla13_IceRodSparkle,
&Ancilla_Unused_14,
&Ancilla15_JumpSplash,
&Ancilla16_HitStars,
&Ancilla17_ShovelDirt,
&Ancilla18_EtherSpell,
&Ancilla19_BombosSpell,
&Ancilla1A_PowderDust,
&Ancilla_SwordWallHit,
&Ancilla1C_QuakeSpell,
&Ancilla1D_ScreenShake,
&Ancilla1E_DashDust,
&Ancilla1F_Hookshot,
&Ancilla20_Blanket,
&Ancilla21_Snore,
&Ancilla22_ItemReceipt,
&Ancilla23_LinkPoof,
&Ancilla24_Gravestone,
&Ancilla_Unused_25,
&Ancilla26_SwordSwingSparkle,
&Ancilla27_Duck,
&Ancilla28_WishPondItem,
&Ancilla29_MilestoneItemReceipt,
&Ancilla2A_SpinAttackSparkleA,
&Ancilla2B_SpinAttackSparkleB,
&Ancilla2C_SomariaBlock,
&Ancilla2D_SomariaBlockFizz,
&Ancilla2E_SomariaBlockFission,
&Ancilla2F_LampFlame,
&Ancilla30_ByrnaWindupSpark,
&Ancilla31_ByrnaSpark,
&Ancilla32_BlastWallFireball,
&Ancilla33_BlastWallExplosion,
&Ancilla34_SkullWoodsFire,
&Ancilla35_MasterSwordReceipt,
&Ancilla36_Flute,
&Ancilla37_WeathervaneExplosion,
&Ancilla38_CutsceneDuck,
&Ancilla39_SomariaPlatformPoof,
&Ancilla3A_BigBombExplosion,
&Ancilla3B_SwordUpSparkle,
&Ancilla3C_SpinAttackChargeSparkle,
&Ancilla3D_ItemSplash,
&Ancilla_RisingCrystal,
&Ancilla3F_BushPoof,
&Ancilla40_DwarfPoof,
&Ancilla41_WaterfallSplash,
&Ancilla42_HappinessPondRupees,
&Ancilla43_GanonsTowerCutscene,
};
uint16 Ancilla_GetX(int k) {
return ancilla_x_lo[k] | ancilla_x_hi[k] << 8;
}
uint16 Ancilla_GetY(int k) {
return ancilla_y_lo[k] | ancilla_y_hi[k] << 8;
}
void Ancilla_SetX(int k, uint16 x) {
ancilla_x_lo[k] = x;
ancilla_x_hi[k] = x >> 8;
}
void Ancilla_SetY(int k, uint16 y) {
ancilla_y_lo[k] = y;
ancilla_y_hi[k] = y >> 8;
}
int Ancilla_AllocHigh() {
for (int k = 9; k >= 0; k--) {
if (ancilla_type[k] == 0)
return k;
}
return -1;
}
void Ancilla_Empty(int k) {
}
void Ancilla_Unused_14(int k) {
assert(0);
}
void Ancilla_Unused_25(int k) {
assert(0);
}
void SpinSpark_Draw(int k, int offs) {
static const uint8 kInitialSpinSpark_Char[32] = {
0x92, 0xff, 0xff, 0xff, 0x8c, 0x8c, 0x8c, 0x8c, 0xd6, 0xd6, 0xd6, 0xd6, 0x93, 0x93, 0x93, 0x93,
0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0x22, 0xff, 0xff, 0xff, // wtf oob
};
static const uint8 kInitialSpinSpark_Flags[29] = {
0x22, 0xff, 0xff, 0xff, 0x22, 0x62, 0xa2, 0xe2, 0x24, 0x64, 0xa4, 0xe4, 0x22, 0x62, 0xa2, 0xe2,
0x22, 0x62, 0xa2, 0xe2, 0x22, 0xff, 0xff, 0xff, 0x22, 0xff, 0xff, 0xff,
0xfc,
};
static const int8 kInitialSpinSpark_Y[29] = {
-4, 0, 0, 0, -8, -8, 0, 0, -8, -8, 0, 0, -8, -8, 0, 0,
-8, -8, 0, 0, -4, 0, 0, 0, -4, 0, 0, 0,
-4,
};
static const int16 kInitialSpinSpark_X[29] = {
-4, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, 0, -8, 0, -8, 0,
-8, 0, -8, 0, -4, 0, 0, 0, -4, 0, 0, 0,
0x11a5
};
Point16U info;
Ancilla_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
int t = (ancilla_item_to_link[k] + offs) * 4;
assert(t < 32);
for(int i = 0; i < 4; i++, t++) {
if (kInitialSpinSpark_Char[t] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam,
info.x + kInitialSpinSpark_X[t], info.y + kInitialSpinSpark_Y[t]);
oam->charnum = kInitialSpinSpark_Char[t];
oam->flags = kInitialSpinSpark_Flags[t] & ~0x30 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
}
}
bool SomarianBlock_CheckEmpty(OamEnt *oam) {
for (int i = 0; i != 4; i++) {
if (oam[i].y == 0xf0)
continue;
for (i = 0; i < 4; i++)
if (!(bytewise_extended_oam[oam + i - oam_buf] & 1))
return false;
break;
}
return true;
}
void AddDashingDustEx(uint8 a, uint8 y, uint8 flag) {
static const int8 kAddDashingDust_X[4] = {4, 4, 6, 0};
static const int8 kAddDashingDust_Y[4] = {20, 4, 16, 16};
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_step[k] = flag;
ancilla_item_to_link[k] = 0;
ancilla_timer[k] = 3;
int j = link_direction_facing >> 1;
ancilla_dir[k] = j;
if (!flag) {
Ancilla_SetXY(k, link_x_coord, link_y_coord + 20);
} else {
Ancilla_SetXY(k, link_x_coord + kAddDashingDust_X[j], link_y_coord + kAddDashingDust_Y[j]);
}
}
}
void AddBirdCommon(int k) {
ancilla_y_vel[k] = 0;
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 1;
ancilla_x_vel[k] = 56;
ancilla_arr3[k] = 3;
ancilla_K[k] = 0;
ancilla_G[k] = 0;
int xt = (enhanced_features0 & kFeatures0_ExtendScreen64) ? 0x40 : 0;
Ancilla_SetXY(k, BG2HOFS_copy2 - 16 - xt, link_y_coord - 8);
}
ProjectSpeedRet Bomb_ProjectSpeedTowardsPlayer(int k, uint16 x, uint16 y, uint8 vel) { // 84eb63
uint16 old_x = Sprite_GetX(0), old_y = Sprite_GetY(0), old_z = sprite_z[0];
Sprite_SetX(0, x);
Sprite_SetY(0, y);
sprite_z[0] = 0;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(0, vel);
sprite_z[0] = old_z;
Sprite_SetX(0, old_x);
Sprite_SetY(0, old_y);
return pt;
}
void Boomerang_CheatWhenNoOnesLooking(int k, ProjectSpeedRet *pt) { // 86809f
uint16 x = link_x_coord - Ancilla_GetX(k) + 0xf0;
uint16 y = link_y_coord - Ancilla_GetY(k) + 0xf0;
if (x >= 0x1e0) {
pt->x = sign16(x - 0x1e0) ? 0x90 : 0x70;
} else if (y >= 0x1e0) {
pt->y = sign16(y - 0x1e0) ? 0x90 : 0x70;
}
}
void Medallion_CheckSpriteDamage(int k) { // 86ec5c
tmp_counter = ancilla_type[k];
for (int j = 15; j >= 0; j--) {
if (sprite_state[j] >= 9 && !(sprite_ignore_projectile[j] | sprite_pause[j])) {
Ancilla_CheckDamageToSprite_aggressive(j, tmp_counter);
}
}
}
void Ancilla_CheckDamageToSprite(int k, uint8 type) { // 86ecb7
if (!sign8(sprite_hit_timer[k]))
Ancilla_CheckDamageToSprite_aggressive(k, type);
}
void Ancilla_CheckDamageToSprite_aggressive(int k, uint8 type) { // 86ecbd
static const uint8 kAncilla_Damage[57] = {
6, 1, 11, 0, 0, 0, 0, 8, 0, 6, 0, 12, 1, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 14, 13, 0, 0, 15, 0, 0, 7,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11,
0, 1, 1, 1, 1, 1, 1, 1, 1,
};
uint8 dmg = kAncilla_Damage[type];
if (dmg == 6 && link_item_bow >= 3) {
if (sprite_type[k] == 0xd7)
sprite_delay_aux4[k] = 32;
dmg = 9;
}
Ancilla_CheckDamageToSprite_preset(k, dmg);
}
void CallForDuckIndoors() { // 87a45f
Ancilla_Sfx2_Near(0x13);
AncillaAdd_Duck_take_off(0x27, 4);
}
void Ancilla_Sfx1_Pan(int k, uint8 v) { // 888020
byte_7E0CF8 = v;
sound_effect_ambient = v | Ancilla_CalculateSfxPan(k);
}
void Ancilla_Sfx2_Pan(int k, uint8 v) { // 888027
byte_7E0CF8 = v;
sound_effect_1 = v | Ancilla_CalculateSfxPan(k);
}
void Ancilla_Sfx3_Pan(int k, uint8 v) { // 88802e
byte_7E0CF8 = v;
sound_effect_2 = v | Ancilla_CalculateSfxPan(k);
}
void AncillaAdd_FireRodShot(uint8 type, uint8 y) { // 8880b3
static const int8 kFireRod_X[4] = {0, 0, -8, 16};
static const int8 kFireRod_Y[4] = {-8, 16, 3, 3};
static const int8 kFireRod_Xvel[4] = {0, 0, -64, 64};
static const int8 kFireRod_Yvel[4] = {-64, 64, 0, 0};
y = 1;
int j= Ancilla_AllocInit(type, 1);
if (j < 0) {
if (type != 1)
Refund_Magic(0);
return;
}
if (type != 1)
Ancilla_Sfx2_Near(0xe);
ancilla_type[j] = type;
ancilla_numspr[j] = kAncilla_Pflags[type];
ancilla_timer[j] = 3;
ancilla_step[j] = 0;
ancilla_item_to_link[j] = 0;
ancilla_objprio[j] = 0;
ancilla_U[j] = 0;
int i = link_direction_facing >> 1;
ancilla_dir[j] = i;
if (Ancilla_CheckInitialTile_A(j) < 0) {
Ancilla_SetXY(j, link_x_coord + kFireRod_X[i], link_y_coord + kFireRod_Y[i]);
if (type != 1) {
ancilla_x_vel[j] = kFireRod_Xvel[i];
ancilla_y_vel[j] = kFireRod_Yvel[i];
} else {
i += (link_sword_type - 2) * 4;
ancilla_x_vel[j] = kFireRod_Xvel2[i];
ancilla_y_vel[j] = kFireRod_Yvel2[i];
}
ancilla_floor[j] = link_is_on_lower_level;
ancilla_floor2[j] = link_is_on_lower_level_mirror;
} else {
if (type == 1) {
ancilla_type[j] = 4;
ancilla_timer[j] = 7;
ancilla_numspr[j] = 16;
} else {
ancilla_step[j] = 1;
ancilla_timer[j] = 31;
ancilla_numspr[j] = 8;
j = link_direction_facing >> 1; // wtf
Ancilla_Sfx2_Pan(j, 0x2a);
}
}
}
void SomariaBlock_SpawnBullets(int k) { // 8881a7
static const int8 kSpawnCentrifugalQuad_X[4] = {-8, -8, -9, -4};
static const int8 kSpawnCentrifugalQuad_Y[4] = {-15, -4, -8, -8};
uint8 z = (ancilla_z[k] == 0xff) ? 0 : ancilla_z[k];
uint16 x = Ancilla_GetX(k);
uint16 y = Ancilla_GetY(k) - z;
for (int i = 3; i >= 0; i--) {
int j = Ancilla_AllocInit(1, 4);
if (j >= 0) {
ancilla_type[j] = 0x1;
ancilla_numspr[j] = kAncilla_Pflags[0x1];
ancilla_step[j] = 4;
ancilla_item_to_link[j] = 0;
ancilla_objprio[j] = 0;
ancilla_dir[j] = i;
Ancilla_SetXY(j, x + kSpawnCentrifugalQuad_X[i], y + kSpawnCentrifugalQuad_Y[i]);
Ancilla_TerminateIfOffscreen(j);
ancilla_x_vel[j] = kFireRod_Xvel2[i];
ancilla_y_vel[j] = kFireRod_Yvel2[i];
ancilla_floor[j] = ancilla_floor[k];
ancilla_floor2[j] = link_is_on_lower_level_mirror;
}
}
tmp_counter = 0xff;
}
void Ancilla_Main() { // 888242
Ancilla_WeaponTink();
Ancilla_ExecuteAll();
}
ProjectSpeedRet Ancilla_ProjectReflexiveSpeedOntoSprite(int k, uint16 x, uint16 y, uint8 vel) { // 88824d
uint16 old_x = link_x_coord, old_y = link_y_coord;
link_x_coord = x;
link_y_coord = y;
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, vel);
link_x_coord = old_x;
link_y_coord = old_y;
return pt;
}
void Bomb_CheckSpriteDamage(int k) { // 888287
for (int j = 15; j >= 0; j--) {
if ((j ^ frame_counter) & 3 | sprite_hit_timer[j] | sprite_ignore_projectile[j])
continue;
if (sprite_floor[j] != ancilla_floor[k] || sprite_state[j] < 9)
continue;
SpriteHitBox hb;
int ax = Ancilla_GetX(k) - 24;
int ay = Ancilla_GetY(k) - 24 - ancilla_z[k];
hb.r0_xlo = ax;
hb.r8_xhi = ax >> 8;
hb.r1_ylo = ay;
hb.r9_yhi = ay >> 8;
hb.r2 = 48;
hb.r3 = 48;
Sprite_SetupHitBox(j, &hb);
if (!CheckIfHitBoxesOverlap(&hb))
continue;
if (sprite_type[j] == 0x92 && sprite_C[j] >= 3)
continue;
Ancilla_CheckDamageToSprite(j, ancilla_type[k]);
ProjectSpeedRet pt = Ancilla_ProjectReflexiveSpeedOntoSprite(j, Ancilla_GetX(k), Ancilla_GetY(k), 64);
sprite_x_recoil[j] = -pt.x;
sprite_y_recoil[j] = -pt.y;
}
}
void Ancilla_ExecuteAll() { // 88832b
for (int i = 9; i >= 0; i--) {
cur_object_index = i;
if (ancilla_type[i])
Ancilla_ExecuteOne(ancilla_type[i], i);
}
}
void Ancilla_ExecuteOne(uint8 type, int k) { // 88833c
if (k < 6) {
ancilla_oam_idx[k] = Ancilla_AllocateOamFromRegion_A_or_D_or_F(k, ancilla_numspr[k]);
}
if (submodule_index == 0 && ancilla_timer[k] != 0)
ancilla_timer[k]--;
kAncilla_Funcs[type - 1](k);
}
void Ancilla13_IceRodSparkle(int k) { // 888435
static const uint8 kIceShotSparkle_X[16] = {2, 7, 6, 1, 1, 7, 7, 1, 0, 7, 8, 1, 4, 9, 4, 0xff};
static const uint8 kIceShotSparkle_Y[16] = {2, 3, 8, 7, 1, 1, 7, 7, 1, 0, 7, 8, 0xff, 4, 9, 4};
static const uint8 kIceShotSparkle_Char[16] = {0x83, 0x83, 0x83, 0x83, 0xb6, 0x80, 0xb6, 0x80, 0xb7, 0xb6, 0xb7, 0xb6, 0xb7, 0xb6, 0xb7, 0xb6};
if (!ancilla_timer[k])
ancilla_type[k] = 0;
if (!submodule_index) {
Ancilla_MoveX(k);
Ancilla_MoveY(k);
}
AncillaOamInfo info;
if (Ancilla_ReturnIfOutsideBounds(k, &info))
return;
int j;
for (j = 4; j >= 0 && ancilla_type[j] != 0xb; j--) {}
if (j >= 0 && ancilla_objprio[j])
info.flags = 0x30;
if (sort_sprites_setting) {
if (ancilla_floor[k])
Oam_AllocateFromRegionE(0x10);
else
Oam_AllocateFromRegionD(0x10);
} else {
Oam_AllocateFromRegionA(0x10);
}
OamEnt *oam = GetOamCurPtr();
j = ancilla_timer[k] & 0x1c;
for (int i = 3; i >= 0; i--, oam++) {
oam->x = info.x + kIceShotSparkle_X[i + j];
oam->y = info.y + kIceShotSparkle_Y[i + j];
oam->charnum = kIceShotSparkle_Char[i + j];
oam->flags = info.flags | 4;
bytewise_extended_oam[oam - oam_buf] = 0;
}
}
void AncillaAdd_IceRodSparkle(int k) { // 8884c8
static const int8 kIceShotSparkle_Xvel[4] = {0, 0, -4, 4};
static const int8 kIceShotSparkle_Yvel[4] = {-4, 4, 0, 0};
if (submodule_index || !sign8(--ancilla_arr4[k]))
return;
ancilla_arr4[k] = 5;
int j = Ancilla_AllocHigh();
if (j >= 0) {
ancilla_type[j] = 0x13;
ancilla_timer[j] = 15;
int i = ancilla_dir[k];
ancilla_x_vel[j] = kIceShotSparkle_Xvel[i];
ancilla_y_vel[j] = kIceShotSparkle_Yvel[i];
ancilla_x_lo[j] = ancilla_x_lo[k];
ancilla_y_lo[j] = ancilla_y_lo[k];
ancilla_floor[j] = ancilla_floor[k];
ancilla_numspr[j] = 0;
}
}
void Ancilla01_SomariaBullet(int k) { // 88851b
static const uint8 kSomarianBlast_Mask[6] = {7, 3, 1, 0, 0, 0};
if (!submodule_index) {
if (!(frame_counter & kSomarianBlast_Mask[ancilla_step[k]])) {
Ancilla_MoveX(k);
Ancilla_MoveY(k);
}
if (ancilla_timer[k] == 0) {
ancilla_timer[k] = 3;
uint8 a = ancilla_step[k] + 1;
if (a >= 6)
a = 4;
ancilla_step[k] = a;
}
if (Ancilla_CheckSpriteCollision(k) >= 0 || Ancilla_CheckTileCollision_staggered(k)) {
ancilla_type[k] = 4;
ancilla_timer[k] = 7;
ancilla_numspr[k] = 16;
}
}
SomarianBlast_Draw(k);
}
bool Ancilla_ReturnIfOutsideBounds(int k, AncillaOamInfo *info) { // 88862a
static const uint8 kAncilla_FloorFlags[2] = {0x20, 0x10};
info->flags = kAncilla_FloorFlags[ancilla_floor[k]];
if ((info->x = ancilla_x_lo[k] - BG2HOFS_copy2) >= 0xf4 ||
(info->y = ancilla_y_lo[k] - BG2VOFS_copy2) >= 0xf0) {
ancilla_type[k] = 0;
return true;
}
return false;
}
void SomarianBlast_Draw(int k) { // 888650
static const uint8 kSomarianBlast_Flags[2] = {2, 6};
AncillaOamInfo info;
if (Ancilla_ReturnIfOutsideBounds(k, &info))
return;
info.flags |= kSomarianBlast_Flags[ancilla_item_to_link[k]];
if (ancilla_objprio[k])
info.flags |= 0x30;
static const int8 kSomarianBlast_Draw_X0[24] = {
0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
static const int8 kSomarianBlast_Draw_X1[24] = {
8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 4, 4, 0, 0, 0, 0,
8, 8, 0, 0, 0, 0, 8, 8,
};
static const uint8 kSomarianBlast_Draw_Y0[24] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4, 4, 0, 0, 0, 0, 4, 4,
};
static const uint8 kSomarianBlast_Draw_Y1[24] = {
0, 0, 0, 0, 8, 8, 0x80, 0, 0, 0, 8, 8, 0x80, 8, 8, 8,
4, 4, 0x80, 8, 8, 8, 4, 4,
};
static const uint8 kSomarianBlast_Draw_Flags0[24] = {
0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0xc0, 0x40, 0x40, 0x40, 0x40, 0, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0xc0, 0, 0, 0, 0, 0, 0x80,
};
static const uint8 kSomarianBlast_Draw_Flags1[24] = {
0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0, 0, 0, 0, 0, 0x40, 0xc0, 0xc0, 0xc0, 0xc0,
0x40, 0xc0, 0x80, 0x80, 0x80, 0x80, 0, 0x80,
};
static const uint8 kSomarianBlast_Draw_Char0[24] = {
0x50, 0x50, 0x44, 0x44, 0x52, 0x52, 0x50, 0x50, 0x44, 0x44, 0x51, 0x51, 0x43, 0x43, 0x42, 0x42,
0x41, 0x41, 0x43, 0x43, 0x42, 0x42, 0x40, 0x40,
};
static const uint8 kSomarianBlast_Draw_Char1[24] = {
0x50, 0x50, 0x44, 0x44, 0x51, 0x51, 0x50, 0x50, 0x44, 0x44, 0x52, 0x52, 0x43, 0x43, 0x42, 0x42,
0x40, 0x40, 0x43, 0x43, 0x42, 0x42, 0x41, 0x41,
};
OamEnt *oam = GetOamCurPtr();
int j = ancilla_dir[k] * 6 + ancilla_step[k];
oam[0].x = info.x + kSomarianBlast_Draw_X0[j];
oam[1].x = info.x + kSomarianBlast_Draw_X1[j];
if (!sign8(kSomarianBlast_Draw_Y0[j]))
oam[0].y = info.y + kSomarianBlast_Draw_Y0[j];
if (!sign8(kSomarianBlast_Draw_Y1[j]))
oam[1].y = info.y + kSomarianBlast_Draw_Y1[j];
oam[0].charnum = 0x82 + kSomarianBlast_Draw_Char0[j];
oam[1].charnum = 0x82 + kSomarianBlast_Draw_Char1[j];
oam[0].flags = info.flags | kSomarianBlast_Draw_Flags0[j];
oam[1].flags = info.flags | kSomarianBlast_Draw_Flags1[j];
bytewise_extended_oam[oam - oam_buf] = 0;
bytewise_extended_oam[oam - oam_buf + 1] = 0;
}
void Ancilla02_FireRodShot(int k) { // 8886d2
if (ancilla_step[k] == 0) {
if (!submodule_index) {
ancilla_L[k] = 0;
Ancilla_MoveX(k);
Ancilla_MoveY(k);
uint8 coll = Ancilla_CheckSpriteCollision(k) >= 0;
if (!coll) {
ancilla_dir[k] |= 8;
coll = Ancilla_CheckTileCollision(k);
ancilla_L[k] = ancilla_tile_attr[k];
if (!coll) {
ancilla_dir[k] |= 12;
uint8 bak = ancilla_U[k];
coll = Ancilla_CheckTileCollision(k);
ancilla_U[k] = bak;
}
}
if (coll) {
ancilla_step[k]++;
ancilla_timer[k] = 31;
ancilla_numspr[k] = 8;
Ancilla_Sfx2_Pan(k, 0x2a);
}
ancilla_item_to_link[k]++;
ancilla_dir[k] &= ~0xC;
if (((byte_7E0333 = ancilla_L[k]) & 0xf0) == 0xc0 || ((byte_7E0333 = ancilla_tile_attr[k]) & 0xf0) == 0xc0)
Dungeon_LightTorch();
}
FireShot_Draw(k);
} else {
AncillaOamInfo info;
Ancilla_CheckBasicSpriteCollision(k);
if (Ancilla_ReturnIfOutsideBounds(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
if (!ancilla_timer[k]) {
uint8 old_type = ancilla_type[k];
ancilla_type[k] = 0;
if (old_type != 0x2f && BYTE(overworld_screen_index) == 64 && ancilla_tile_attr[k] == 0x43)
FireRodShot_BecomeSkullWoodsFire(k);
return;
}
int j = ancilla_timer[k] >> 3;
if (j != 0) {
static const uint8 kFireShot_Draw_Char[3] = {0xa2, 0xa0, 0x8e};
oam->x = info.x;
oam->y = info.y;
oam->charnum = kFireShot_Draw_Char[j - 1];
oam->flags = info.flags | 2;
bytewise_extended_oam[oam - oam_buf] = 2;
} else {
bytewise_extended_oam[oam - oam_buf] = 0;
bytewise_extended_oam[oam - oam_buf + 1] = 0;
oam[0].x = info.x;
oam[1].x = info.x + 8;
oam[0].y = info.y - 3;
oam[1].y = info.y - 3;
oam[0].charnum = 0xa4;
oam[1].charnum = 0xa5;
oam[0].flags = info.flags | 2;
oam[1].flags = info.flags | 2;
}
}
}
void FireShot_Draw(int k) { // 88877c
static const uint8 kFireShot_Draw_X2[16] = {7, 0, 8, 0, 8, 4, 0, 0, 2, 8, 0, 0, 1, 4, 9, 0};
static const uint8 kFireShot_Draw_Y2[16] = {1, 4, 9, 0, 7, 0, 8, 0, 8, 4, 0, 0, 2, 8, 0, 0};
static const uint8 kFireShot_Draw_Char2[3] = {0x8d, 0x9d, 0x9c};
AncillaOamInfo info;
if (Ancilla_ReturnIfOutsideBounds(k, &info))
return;
if (ancilla_objprio[k])
info.flags |= 0x30;
OamEnt *oam = GetOamCurPtr();
int j = ancilla_item_to_link[k] & 0xc;
for (int i = 2; i >= 0; i--) {
oam->x = info.x + kFireShot_Draw_X2[j + i];
oam->y = info.y + kFireShot_Draw_Y2[j + i];
oam->charnum = kFireShot_Draw_Char2[i];
oam->flags = info.flags | 2;
bytewise_extended_oam[oam - oam_buf] = 0;
oam++;
}
}
uint8 Ancilla_CheckTileCollision_staggered(int k) { // 88897b
if ((frame_counter ^ k) & 1)
return Ancilla_CheckTileCollision(k);
return 0;
}
uint8 Ancilla_CheckTileCollision(int k) { // 888981
if (!player_is_indoors && ancilla_objprio[k]) {
ancilla_tile_attr[k] = 0;
return 0;
}
if (!dung_hdr_collision)
return Ancilla_CheckTileCollisionOneFloor(k);
uint16 x = 0, y = 0;
if (dung_hdr_collision < 3) {
x = BG1HOFS_copy2 - BG2HOFS_copy2;
y = BG1VOFS_copy2 - BG2VOFS_copy2;
}
uint16 oldx = Ancilla_GetX(k), oldy = Ancilla_GetY(k);
Ancilla_SetX(k, oldx + x);
Ancilla_SetY(k, oldy + y);
ancilla_floor[k] = 1;
uint8 b = Ancilla_CheckTileCollisionOneFloor(k);
ancilla_floor[k] = 0;
Ancilla_SetX(k, oldx);
Ancilla_SetY(k, oldy);
return (b << 1) | (uint8)Ancilla_CheckTileCollisionOneFloor(k);
}
bool Ancilla_CheckTileCollisionOneFloor(int k) { // 888a03
static const int8 kAncilla_CheckTileColl0_X[20] = {
8, 8, 0, 16, 4, 4, 0, 16, 4, 4, 4, 12, 12, 12, 4, 12, 0, 0, 0, 0,
};
static const int8 kAncilla_CheckTileColl0_Y[20] = {
0, 16, 5, 5, 0, 16, 4, 4, 4, 12, 5, 5, 4, 12, 12, 12, 0, 0, 0, 0,
};
uint16 x = Ancilla_GetX(k) + kAncilla_CheckTileColl0_X[ancilla_dir[k]];
uint16 y = Ancilla_GetY(k) + kAncilla_CheckTileColl0_Y[ancilla_dir[k]];
return Ancilla_CheckTileCollision_targeted(k, x, y);
}
bool Ancilla_CheckTileCollision_targeted(int k, uint16 x, uint16 y) { // 888a26
if ((uint16)(y - BG2VOFS_copy2) >= 224 || (uint16)(x - BG2HOFS_copy2) >= 256)
return 0;
uint8 tile_attr;
if (!player_is_indoors) {
x >>= 3;
tile_attr = Overworld_GetTileAttributeAtLocation(x, y);
} else {
tile_attr = GetTileAttribute(ancilla_floor[k], &x, y);
}
ancilla_tile_attr[k] = tile_attr;
if (tile_attr == 3 && ancilla_floor2[k])
return 0;
uint8 t = kAncilla_TileColl0_Attrs[tile_attr];
if (ancilla_type[k] == 2 && (tile_attr & 0xf0) == 0xc0)
t = 0;
if (!ancilla_objprio[k]) {
if (t == 0)
return false;
if (t == 1)
goto return_true_set_alert;
if (t == 2)
return Entity_CheckSlopedTileCollision(x, y);
if (t == 3) {
if (ancilla_floor2[k])
goto return_true_set_alert;
return 0;
}
}
if (sign8(--ancilla_U[k])) {
ancilla_U[k] = 0;
if (t == 4) {
ancilla_U[k] = 6;
ancilla_objprio[k] ^= 1;
}
}
return 0;
return_true_set_alert:
sprite_alert_flag = 3;
return 1;
}
bool Ancilla_CheckTileCollision_Class2(int k) { // 888bcf
if (!dung_hdr_collision)
return Ancilla_CheckTileCollision_Class2_Inner(k);
uint16 x = 0, y = 0;
if (dung_hdr_collision < 3) {
x = BG1HOFS_copy2 - BG2HOFS_copy2;
y = BG1VOFS_copy2 - BG2VOFS_copy2;
}
uint16 oldx = Ancilla_GetX(k), oldy = Ancilla_GetY(k);
Ancilla_SetX(k, oldx + x);
Ancilla_SetY(k, oldy + y);
ancilla_floor[k] = 1;
bool b = Ancilla_CheckTileCollision_Class2_Inner(k);
ancilla_floor[k] = 0;
Ancilla_SetX(k, oldx);
Ancilla_SetY(k, oldy);
return (b | Ancilla_CheckTileCollision_Class2_Inner(k)) != 0;
}
bool Ancilla_CheckTileCollision_Class2_Inner(int k) { // 888c43
static const int8 kAncilla_CheckTileColl_Y[4] = {-8, 8, 0, 0};
static const int8 kAncilla_CheckTileColl_X[4] = {0, 0, -8, 8};
uint16 x = Ancilla_GetX(k) + kAncilla_CheckTileColl_X[ancilla_dir[k]];
uint16 y = Ancilla_GetY(k) + kAncilla_CheckTileColl_Y[ancilla_dir[k]];
if ((uint16)(y - BG2VOFS_copy2) >= 224 || (uint16)(x - BG2HOFS_copy2) >= 256)
return false;
uint8 tile_attr;
if (!player_is_indoors) {
x >>= 3;
tile_attr = Overworld_GetTileAttributeAtLocation(x, y);
} else {
tile_attr = GetTileAttribute(ancilla_floor[k], &x, y);
}
ancilla_tile_attr[k] = tile_attr;
if (tile_attr == 3 && ancilla_floor2[k])
return false;
uint8 t = kAncilla_TileColl_Attrs[tile_attr];
if (t == 0)
return false;
if (t == 2)
return Entity_CheckSlopedTileCollision(x, y);
if (t == 4) {
if (ancilla_floor2[k])
return true;
ancilla_objprio[k] = 1;
return false;
}
if (t == 3)
return ancilla_floor2[k] != 0;
return true;
}
void Ancilla04_BeamHit(int k) { // 888d19
static const int8 kBeamHit_X[16] = {-12, 20, -12, 20, -8, 16, -8, 16, -4, 12, -4, 12, 0, 8, 0, 8};
static const int8 kBeamHit_Y[16] = {-12, -12, 20, 20, -8, -8, 16, 16, -4, -4, 12, 12, 0, 0, 8, 8};
static const uint8 kBeamHit_Char[16] = {0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x54};
static const uint8 kBeamHit_Flags[16] = {0x40, 0, 0xc0, 0x80, 0x40, 0, 0xc0, 0x80, 0x40, 0, 0xc0, 0x80, 0, 0x40, 0x80, 0xc0};
AncillaOamInfo info;
if (Ancilla_ReturnIfOutsideBounds(k, &info))
return;
if (!ancilla_timer[k]) {
ancilla_type[k] = 0;
return;
}
OamEnt *oam = GetOamCurPtr();
int j = ancilla_timer[k] >> 1;
uint16 ancilla_x = Ancilla_GetX(k);
uint16 ancilla_y = Ancilla_GetY(k);
uint8 r7 = ancilla_x - BG2HOFS_copy2;
uint8 r6 = ancilla_y - BG2VOFS_copy2;
for (int i = 3; i >= 0; i--, oam++) {
int m = j * 4 + i;
oam->x = info.x + kBeamHit_X[m];
oam->y = info.y + kBeamHit_Y[m];
oam->charnum = kBeamHit_Char[m] + 0x82;
oam->flags = kBeamHit_Flags[m] | 2 | info.flags;
uint16 x_adj = (uint16)(ancilla_x + (int8)(oam->x - r7) - BG2HOFS_copy2);
bytewise_extended_oam[oam - oam_buf] = (x_adj >= 0x100) ? 1 : 0;
uint16 y_adj = (uint16)(ancilla_y + (int8)(oam->y - r6) - BG2VOFS_copy2 + 0x10);
if (y_adj >= 0x100)
oam->y = 0xf0;
}
}
int Ancilla_CheckSpriteCollision(int k) { // 888d68
for (int j = 15; j >= 0; j--) {
if (ancilla_type[k] == 9 || ancilla_type[k] == 0x1f || ((j ^ frame_counter) & 3 | sprite_pause[j]) == 0) {
if ((sprite_state[j] >= 9 && (sprite_defl_bits[j] & 2 || !ancilla_objprio[k])) && ancilla_floor[k] == sprite_floor[j]) {
if (Ancilla_CheckSpriteCollision_Single(k, j))
return j;
}
}
}
return -1;
}
bool Ancilla_CheckSpriteCollision_Single(int k, int j) { // 888dae
int i;
SpriteHitBox hb;
Ancilla_SetupHitBox(k, &hb);
Sprite_SetupHitBox(j, &hb);
if (!CheckIfHitBoxesOverlap(&hb))
return false;
bool return_value = true;
if (sprite_flags[j] & 8 && ancilla_type[k] == 9) {
if (sprite_type[j] != 0x1b) {
Sprite_CreateDeflectedArrow(k);
return false;
}
if (link_item_bow < 3) {
Sprite_CreateDeflectedArrow(k);
} else {
return_value = false;
}
}
if (sprite_defl_bits[j] & 0x10) {
static const uint8 kAncilla_CheckSpriteColl_Dir[4] = {2, 3, 0, 1};
ancilla_dir[k] &= 3;
if (ancilla_dir[k] == kAncilla_CheckSpriteColl_Dir[ancilla_dir[k]])
goto return_true_set_alert;
}
if (ancilla_type[k] == 5 || ancilla_type[k] == 0x1f) {
if (ancilla_type[k] == 0x1f && sprite_type[j] == 0x8d)
goto skip;
if (sprite_hit_timer[j])
goto return_true_set_alert;
if (sprite_defl_bits[j] & 2) {
skip:
sprite_B[j] = k + 1;
sprite_unk2[j] = ancilla_type[k];
goto return_true_set_alert;
}
}
if (!sprite_ignore_projectile[j]) {
static const int8 kAncilla_CheckSpriteColl_RecoilX[4] = {0, 0, -64, 64};
static const int8 kAncilla_CheckSpriteColl_RecoilY[4] = {-64, 64, 0, 0};
if (sprite_type[j] == 0x92 && sprite_C[j] < 3)
goto return_true_set_alert;
i = ancilla_dir[k] & 3;
sprite_x_recoil[j] = kAncilla_CheckSpriteColl_RecoilX[i];
sprite_y_recoil[j] = kAncilla_CheckSpriteColl_RecoilY[i];
byte_7E0FB6 = k;
Ancilla_CheckDamageToSprite(j, ancilla_type[k]);
return_true_set_alert:
sprite_unk2[j] = ancilla_type[k];
sprite_alert_flag = 3;
return return_value;
}
return false;
}
void Ancilla_SetupHitBox(int k, SpriteHitBox *hb) { // 888ead
static const int8 kAncilla_HitBox_X[12] = {4, 4, 4, 4, 3, 3, 2, 11, -16, -16, -1, -8};
static const int8 kAncilla_HitBox_Y[12] = {4, 4, 4, 4, 2, 11, 3, 3, -1, -8, -16, -16};
static const uint8 kAncilla_HitBox_W[12] = {8, 8, 8, 8, 1, 1, 1, 1, 32, 32, 8, 8};
static const uint8 kAncilla_HitBox_H[12] = {8, 8, 8, 8, 1, 1, 1, 1, 8, 8, 32, 32};
int j = ancilla_dir[k];
if (ancilla_type[k] == 0xc)
j |= 8;
int x = Ancilla_GetX(k) + kAncilla_HitBox_X[j];
hb->r0_xlo = x;
hb->r8_xhi = x >> 8;
int y = Ancilla_GetY(k) + kAncilla_HitBox_Y[j];
hb->r1_ylo = y;
hb->r9_yhi = y >> 8;
hb->r2 = kAncilla_HitBox_W[j];
hb->r3 = kAncilla_HitBox_H[j];
}
ProjectSpeedRet Ancilla_ProjectSpeedTowardsPlayer(int k, uint8 vel) { // 888eed
if (vel == 0) {
ProjectSpeedRet rv = { 0, 0, 0, 0 };
return rv;
}
PairU8 below = Ancilla_IsBelowLink(k);
uint8 r12 = sign8(below.b) ? -below.b : below.b;
PairU8 right = Ancilla_IsRightOfLink(k);
uint8 r13 = sign8(right.b) ? -right.b : right.b;
uint8 t;
bool swapped = false;
if (r13 < r12) {
swapped = true;
t = r12, r12 = r13, r13 = t;
}
uint8 xvel = vel, yvel = 0;
t = 0;
do {
t += r12;
if (t >= r13)
t -= r13, yvel++;
} while (--vel);
if (swapped)
t = xvel, xvel = yvel, yvel = t;
ProjectSpeedRet rv = {
(uint8)(right.a ? -xvel : xvel),
(uint8)(below.a ? -yvel : yvel),
right.b,
below.b
};
return rv;
}
PairU8 Ancilla_IsRightOfLink(int k) { // 888f5c
uint16 x = link_x_coord - Ancilla_GetX(k);
PairU8 rv = { (uint8)(sign16(x) ? 1 : 0), (uint8)x };
return rv;
}
PairU8 Ancilla_IsBelowLink(int k) { // 888f6f
int y = link_y_coord - Ancilla_GetY(k);
PairU8 rv = { (uint8)(sign16(y) ? 1 : 0), (uint8)y };
return rv;
}
void Ancilla_WeaponTink() { // 888f89
if (!repulsespark_timer)
return;
sprite_alert_flag = 2;
if (sign8(--repulsespark_anim_delay)) {
repulsespark_timer--;
repulsespark_anim_delay = 1;
}
if (sort_sprites_setting) {
if (repulsespark_floor_status)
Oam_AllocateFromRegionF(0x10);
else
Oam_AllocateFromRegionD(0x10);
} else {
Oam_AllocateFromRegionA(0x10);
}
uint8 x = repulsespark_x_lo - BG2HOFS_copy2;
uint8 y = repulsespark_y_lo - BG2VOFS_copy2;
if (x >= 0xf8 || y >= 0xf0) {
repulsespark_timer = 0;
return;
}
OamEnt *oam = GetOamCurPtr();
static const uint8 kRepulseSpark_Flags[4] = {0x22, 0x12, 0x22, 0x22};
uint8 flags = kRepulseSpark_Flags[repulsespark_floor_status];
if (repulsespark_timer >= 3) {
oam->x = x;
oam->y = y;
oam->charnum = (repulsespark_timer < 9) ? 0x92 : 0x80;
oam->flags = flags;
bytewise_extended_oam[oam - oam_buf] = 0;
return;
}
oam[0].x = x - 4;
oam[2].x = x - 4;
oam[1].x = x + 4;
oam[3].x = x + 4;
oam[0].y = y - 4;
oam[1].y = y - 4;
oam[2].y = y + 4;
oam[3].y = y + 4;
oam[0].flags = flags;
oam[1].flags = flags | 0x40;
oam[2].flags = flags | 0x80;
oam[3].flags = flags | 0xc0;
static const uint8 kRepulseSpark_Char[3] = {0x93, 0x82, 0x81};
uint8 c = kRepulseSpark_Char[repulsespark_timer];
oam[0].charnum = c;
oam[1].charnum = c;
oam[2].charnum = c;
oam[3].charnum = c;
uint8 *ext = &bytewise_extended_oam[oam - oam_buf];
ext[0] = ext[1] = ext[2] = ext[3] = 0;
}
void Ancilla_MoveX(int k) { // 889080
uint32 t = ancilla_x_subpixel[k] + (ancilla_x_lo[k] << 8) + (ancilla_x_hi[k] << 16) + ((int8)ancilla_x_vel[k] << 4);
ancilla_x_subpixel[k] = t, ancilla_x_lo[k] = t >> 8, ancilla_x_hi[k] = t >> 16;
}
void Ancilla_MoveY(int k) { // 88908b
uint32 t = ancilla_y_subpixel[k] + (ancilla_y_lo[k] << 8) + (ancilla_y_hi[k] << 16) + ((int8)ancilla_y_vel[k] << 4);
ancilla_y_subpixel[k] = t, ancilla_y_lo[k] = t >> 8, ancilla_y_hi[k] = t >> 16;
}
void Ancilla_MoveZ(int k) { // 8890b7
uint32 t = ancilla_z_subpixel[k] + (ancilla_z[k] << 8) + ((int8)ancilla_z_vel[k] << 4);
ancilla_z_subpixel[k] = t, ancilla_z[k] = t >> 8;
}
void Ancilla05_Boomerang(int k) { // 8890fc
int hit_spr;
static const int8 kBoomerang_X0[8] = {0, 0, -8, 8, 8, 8, -8, -8};
static const int8 kBoomerang_Y0[8] = {-16, 6, 0, 0, -8, 8, -8, 8};
for (int j = 4; j >= 0; j--) {
if (ancilla_type[j] == 0x22)
goto exit_and_draw;
}
if (submodule_index)
goto exit_and_draw;
if (!(frame_counter & 7))
Ancilla_Sfx2_Pan(k, 0x9);
if (!ancilla_aux_timer[k]) {
if (button_b_frames < 9 && !player_handler_timer) {
if (!link_is_bunny_mirror && !link_auxiliary_state)
goto exit_and_draw;
Boomerang_Terminate(k);
return;
}
int j = ancilla_arr23[k] >> 1;
Ancilla_SetXY(k, link_x_coord + kBoomerang_X0[j], link_y_coord + 8 + kBoomerang_Y0[j]);
ancilla_aux_timer[k]++;
}
// endif_2
if (ancilla_G[k] && !(frame_counter & 1))
AncillaAdd_SwordChargeSparkle(k);
if (ancilla_item_to_link[k]) {
if (ancilla_K[k])
ancilla_K[k]++;
WORD(ancilla_A[k]) = link_y_coord;
link_y_coord += 8;
ProjectSpeedRet pt = Ancilla_ProjectSpeedTowardsPlayer(k, ancilla_H[k]);
Boomerang_CheatWhenNoOnesLooking(k, &pt);
ancilla_x_vel[k] = pt.x;
ancilla_y_vel[k] = pt.y;
link_y_coord = WORD(ancilla_A[k]);
}
if (ancilla_y_vel[k])
ancilla_y_vel[k] += ancilla_K[k];
Ancilla_MoveY(k);
if (ancilla_x_vel[k])
ancilla_x_vel[k] += ancilla_K[k];
Ancilla_MoveX(k);
hit_spr = Ancilla_CheckSpriteCollision(k);
if (!ancilla_item_to_link[k]) {
if (hit_spr >= 0) {
ancilla_item_to_link[k] ^= 1;
} else if (Ancilla_CheckTileCollision(k)) {
AncillaAdd_BoomerangWallClink(k);
Ancilla_Sfx2_Pan(k, (ancilla_tile_attr[k] == 0xf0) ? 6 : 5);
ancilla_item_to_link[k] ^= 1;
} else if (Boomerang_ScreenEdge(k) || --ancilla_step[k] == 0) {
ancilla_item_to_link[k] ^= 1;
} else {
if (ancilla_step[k] < 5)
ancilla_K[k]--;
}
} else {
uint8 bak0 = ancilla_objprio[k];
uint8 bak1 = ancilla_floor[k];
ancilla_floor[k] = 0;
Ancilla_CheckTileCollision(k);
ancilla_floor[k] = bak1;
ancilla_objprio[k] = bak0;
Boomerang_StopOffScreen(k);
}
exit_and_draw:
Boomerang_Draw(k);
}
bool Boomerang_ScreenEdge(int k) { // 88924b
uint16 x = Ancilla_GetX(k), y = Ancilla_GetY(k);
if (hookshot_effect_index & 3) {
uint16 t = x + (hookshot_effect_index & 1 ? 16 : 0) - BG2HOFS_copy2;
if (t >= 0x100)
return true;
}
if (hookshot_effect_index & 12) {
uint16 t = y + (hookshot_effect_index & 4 ? 16 : 0) - BG2VOFS_copy2;
if (t >= 0xe2)
return true;
}
return false;
}
void Boomerang_StopOffScreen(int k) { // 8892ab
uint16 x = Ancilla_GetX(k) + 8, y = Ancilla_GetY(k) + 8;
if (x >= link_x_coord && x < (uint16)(link_x_coord + 16) &&
y >= link_y_coord && y < (uint16)(link_y_coord + 24))
Boomerang_Terminate(k);
}
void Boomerang_Terminate(int k) { // 8892f5
ancilla_type[k] = 0;
flag_for_boomerang_in_place = 0;
if (link_item_in_hand & 0x80) {
link_item_in_hand = 0;
button_mask_b_y &= ~0x40;
if (!(button_mask_b_y & 0x80))
link_cant_change_direction &= ~1;
}
}
void Boomerang_Draw(int k) { // 889338
static const uint8 kBoomerang_Flags[8] = {0xa4, 0xe4, 0x64, 0x24, 0xa2, 0xe2, 0x62, 0x22};
static const int8 kBoomerang_Draw_XY[8] = {2, -2, 2, 2, -2, 2, -2, -2};
static const uint16 kBoomerang_Draw_OamIdx[2] = {0x180, 0xd0};
static const uint8 kBoomerang_Draw_Tab0[2] = {3, 2};
Point16U info;
Ancilla_PrepOamCoord(k, &info);
if (ancilla_item_to_link[k]) {
ancilla_floor[k] = link_is_on_lower_level;
oam_priority_value = kTagalongLayerBits[link_is_on_lower_level] << 8;
}
if (ancilla_objprio[k])
oam_priority_value = 0x3000;
if (!submodule_index && ancilla_aux_timer[k] && sign8(--ancilla_arr3[k])) {
ancilla_arr3[k] = kBoomerang_Draw_Tab0[ancilla_G[k]];
ancilla_arr1[k] = (ancilla_arr1[k] + (ancilla_S[k] ? -1 : 1)) & 3;
}
int j = ancilla_arr1[k];
uint16 x = info.x + kBoomerang_Draw_XY[j * 2 + 1];
uint16 y = info.y + kBoomerang_Draw_XY[j * 2 + 0];
if (!ancilla_aux_timer[k]) {
int i = kBoomerang_Draw_OamIdx[sort_sprites_setting];
oam_ext_cur_ptr = (i >> 2) + 0xa20;
oam_cur_ptr = i + 0x800;
}
OamEnt *oam = GetOamCurPtr();
uint8 ext = Ancilla_SetOam_XY_safe(oam, x, y);
oam->charnum = 0x26;
oam->flags = kBoomerang_Flags[ancilla_G[k] * 4 + j] & ~0x30 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = 2 | ext;
}
void Ancilla06_WallHit(int k) { // 8893e8
if (sign8(--ancilla_arr3[k])) {
uint8 t = ancilla_item_to_link[k] + 1;
if (t == 5) {
ancilla_type[k] = 0;
return;
}
ancilla_item_to_link[k] = t;
ancilla_arr3[k] = 1;
}
WallHit_Draw(k);
}
void Ancilla_SwordWallHit(int k) { // 8893ff
sprite_alert_flag = 3;
if (sign8(--ancilla_aux_timer[k])) {
uint8 t = ancilla_item_to_link[k] + 1;
if (t == 8) {
ancilla_type[k] = 0;
return;
}
ancilla_item_to_link[k] = t;
ancilla_aux_timer[k] = 1;
}
WallHit_Draw(k);
}
void WallHit_Draw(int k) { // 8894df
static const int8 kWallHit_X[32] = {
-4, 0, 0, 0, -4, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, 0,
-8, 0, -8, 0, -4, 0, 0, 0, -4, 0, 0, 0, -8, 0, 0, 0,
};
static const int8 kWallHit_Y[32] = {
-4, 0, 0, 0, -4, 0, 0, 0, -8, -8, 0, 0, -8, -8, 0, 0,
-8, -8, 0, 0, -4, 0, 0, 0, -4, 0, 0, 0, -8, 0, 0, 0,
};
static const uint8 kWallHit_Char[32] = {
0x80, 0, 0, 0, 0x92, 0, 0, 0, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
0x93, 0x93, 0x93, 0x93, 0x92, 0, 0, 0, 0xb9, 0, 0, 0, 0x90, 0x90, 0, 0,
};
static const uint8 kWallHit_Flags[32] = {
0x32, 0, 0, 0, 0x32, 0, 0, 0, 0x32, 0x72, 0xb2, 0xf2, 0x32, 0x72, 0xb2, 0xf2,
0x32, 0x72, 0xb2, 0xf2, 0x32, 0, 0, 0, 0x72, 0, 0, 0, 0x32, 0xf2, 0, 0,
};
Point16U info;
Ancilla_PrepOamCoord(k, &info);
int t = ancilla_item_to_link[k] * 4;
OamEnt *oam = GetOamCurPtr();
for (int n = 3; n >= 0; n--, t++) {
if (kWallHit_Char[t] != 0) {
uint8 ext = Ancilla_SetOam_XY(oam, info.x + kWallHit_X[t], info.y + kWallHit_Y[t]);
oam->charnum = kWallHit_Char[t];
oam->flags = kWallHit_Flags[t] & ~0x30 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
oam = Ancilla_AllocateOamFromCustomRegion(oam);
}
}
void Ancilla07_Bomb(int k) { // 88955a
if (submodule_index) {
if (submodule_index == 8 || submodule_index == 16) {
Ancilla_HandleLiftLogic(k);
} else if (k + 1 == flag_is_ancilla_to_pick_up && ancilla_K[k] != 0) {
if (ancilla_K[k] != 3) {
Ancilla_LatchLinkCoordinates(k, 3);
Ancilla_LatchAltitudeAboveLink(k);
ancilla_K[k] = 3;
}
Ancilla_LatchCarriedPosition(k);
}
Bomb_Draw(k);
return;
}
Ancilla_HandleLiftLogic(k);
uint16 old_y = Ancilla_LatchYCoordToZ(k);
uint8 s1a = ancilla_dir[k];
uint8 s1b = ancilla_objprio[k];
ancilla_objprio[k] = 0;
bool flag = Ancilla_CheckTileCollision_Class2(k);
if (player_is_indoors && ancilla_L[k] && ancilla_tile_attr[k] == 0x1c)
ancilla_T[k] = 1;
label1:
if (flag && (!(link_state_bits & 0x80) || link_picking_throw_state)) {
if (!s1b && !ancilla_arr4[k]) {
ancilla_arr4[k] = 1;
int qq = (ancilla_dir[k] == 1) ? 16 : 4;
if (ancilla_y_vel[k])
ancilla_y_vel[k] = sign8(ancilla_y_vel[k]) ? qq : -qq;
if (ancilla_x_vel[k])
ancilla_x_vel[k] = sign8(ancilla_x_vel[k]) ? 4 : -4;
if (ancilla_dir[k] == 1 && ancilla_z[k]) {
ancilla_y_vel[k] = -4;
ancilla_L[k] = 2;
}
}
} else if (!((k + 1 == flag_is_ancilla_to_pick_up) && (link_state_bits & 0x80)) && (ancilla_z[k] == 0 || ancilla_z[k] == 0xff)) {
ancilla_dir[k] = 16;
uint8 bak0 = ancilla_objprio[k];
Ancilla_CheckTileCollision(k);
ancilla_objprio[k] = bak0;
uint8 a = ancilla_tile_attr[k];
if (a == 0x26) {
flag = true;
goto label1;
} else if (a == 0xc || a == 0x1c) {
if (dung_hdr_collision != 3) {
if (ancilla_floor[k] == 0 && ancilla_z[k] != 0 && ancilla_z[k] != 0xff)
ancilla_floor[k] = 1;
} else {
old_y = Ancilla_GetY(k) + dung_floor_y_vel;
Ancilla_SetX(k, Ancilla_GetX(k) + dung_floor_x_vel);
}
} else if (a == 0x20 || (a & 0xf0) == 0xb0 && a != 0xb6 && a != 0xbc) {
if (!(link_state_bits & 0x80)) {
if (k + 1 == flag_is_ancilla_to_pick_up)
flag_is_ancilla_to_pick_up = 0;
if (!ancilla_timer[k]) {
ancilla_type[k] = 0;
return;
}
}
} else if (a == 8) {
if (k + 1 == flag_is_ancilla_to_pick_up)
flag_is_ancilla_to_pick_up = 0;
if (ancilla_timer[k] == 0) {
Ancilla_SetY(k, Ancilla_GetY(k) - 24);
Ancilla_TransmuteToSplash(k);
return;
}
} else if (a == 0x68 || a == 0x69 || a == 0x6a || a == 0x6b) {
Ancilla_ApplyConveyor(k);
old_y = Ancilla_GetY(k);
} else {
ancilla_timer[k] = ancilla_L[k] ? 0 : 2;
}
}
// endif_3
Ancilla_SetY(k, old_y);
ancilla_dir[k] = s1a;
ancilla_objprio[k] |= s1b;
Bomb_CheckSpriteAndPlayerDamage(k);
if (!--ancilla_arr3[k]) {
if (++ancilla_item_to_link[k] == 1) {
Ancilla_Sfx2_Pan(k, 0xc);
if (k + 1 == flag_is_ancilla_to_pick_up) {
flag_is_ancilla_to_pick_up = 0;
if (link_state_bits & 0x80) {
link_state_bits = 0;
link_cant_change_direction = 0;
}
}
}
if (ancilla_item_to_link[k] == 11) {
// transmute to door debris?
ancilla_type[k] = ancilla_step[k] ? 8 : 0;
return;
}
ancilla_arr3[k] = kBomb_Tab0[ancilla_item_to_link[k]];
}
if (ancilla_item_to_link[k] == 7 && ancilla_arr3[k] == 2) {
// check whether the bomb causes any door debris, the bomb
// will transmute to debris later on.
door_debris_x[k] = 0;
Bomb_CheckForDestructibles(Ancilla_GetX(k), Ancilla_GetY(k), k);
if (door_debris_x[k])
ancilla_step[k] = 1;
}
Bomb_Draw(k);
}
void Ancilla_ApplyConveyor(int k) { // 8897be
static const int8 kAncilla_Belt_Xvel[4] = {0, 0, -8, 8};
static const int8 kAncilla_Belt_Yvel[4] = {-8, 8, 0, 0};
int j = ancilla_tile_attr[k] - 0x68;
ancilla_y_vel[k] = kAncilla_Belt_Yvel[j];
ancilla_x_vel[k] = kAncilla_Belt_Xvel[j];
Ancilla_MoveY(k);
Ancilla_MoveX(k);
}
void Bomb_CheckSpriteAndPlayerDamage(int k) { // 889815
static const uint8 kBomb_Dmg_Speed[16] = {32, 32, 32, 32, 32, 32, 28, 28, 28, 28, 28, 28, 24, 24, 24, 24};
static const uint8 kBomb_Dmg_Zvel[16] = {16, 16, 16, 16, 16, 16, 12, 12, 12, 12, 8, 8, 8, 8, 8, 8};
static const uint8 kBomb_Dmg_Delay[16] = {32, 32, 32, 32, 32, 32, 24, 24, 24, 24, 24, 24, 16, 16, 16, 16};
static const uint8 kBomb_Dmg_ToLink[3] = {8, 4, 2};
if (ancilla_item_to_link[k] == 0 || ancilla_item_to_link[k] >= 9)
return;
Bomb_CheckSpriteDamage(k);
if (link_disable_sprite_damage) {
if (k + 1 == flag_is_ancilla_to_pick_up && link_state_bits & 0x80) {
link_state_bits &= ~0x80;
link_cant_change_direction = 0;
}
return;
}
if (link_auxiliary_state || link_incapacitated_timer || ancilla_floor[k] != link_is_on_lower_level)
return;
SpriteHitBox hb;
hb.r0_xlo = link_x_coord;
hb.r8_xhi = link_x_coord >> 8;
hb.r1_ylo = link_y_coord;
hb.r9_yhi = link_y_coord >> 8;
hb.r2 = 0x10;
hb.r3 = 0x18;
int ax = Ancilla_GetX(k) - 16, ay = Ancilla_GetY(k) - 16;
hb.r6_spr_xsize = 32;
hb.r7_spr_ysize = 32;
hb.r4_spr_xlo = ax;
hb.r10_spr_xhi = ax >> 8;
hb.r5_spr_ylo = ay;
hb.r11_spr_yhi = ay >> 8;
if (!CheckIfHitBoxesOverlap(&hb))
return;
int x = Ancilla_GetX(k) - 8, y = Ancilla_GetY(k) - 12;
int j = Bomb_GetDisplacementFromLink(k);
ProjectSpeedRet pt = Bomb_ProjectSpeedTowardsPlayer(k, x, y, kBomb_Dmg_Speed[j]);
if (countdown_for_blink || flag_block_link_menu == 2)
return;
link_actual_vel_x = pt.x;
link_actual_vel_y = pt.y;
link_actual_vel_z_copy = link_actual_vel_z = kBomb_Dmg_Zvel[j];
link_incapacitated_timer = kBomb_Dmg_Delay[j];
link_auxiliary_state = 1;
countdown_for_blink = 58;
if (!(dung_savegame_state_bits & 0x8000))
link_give_damage = kBomb_Dmg_ToLink[link_armor];
}
void Ancilla_HandleLiftLogic(int k) { // 889976
static const uint8 kAncilla_Liftable_Delay[3] = {16, 8, 9};
if (ancilla_R[k]) {
label_6:
if (ancilla_item_to_link[k])
return;
if (ancilla_K[k] == 3) {
ancilla_z_vel[k] -= 2;
Ancilla_MoveZ(k);
if (ancilla_z[k] && ancilla_z[k] < 252)
return;
ancilla_z[k] = 0;
if (++ancilla_R[k] != 3) {
ancilla_z_vel[k] = 24;
return;
}
ancilla_K[k] = 0;
}
ancilla_R[k] = 0;
link_speed_setting = 0;
return;
}
if (!ancilla_L[k]) {
if (!flag_is_ancilla_to_pick_up) {
clear_pickup_item:
flag_is_ancilla_to_pick_up = 0;
CheckPlayerCollOut coll;
if (ancilla_item_to_link[k] || link_state_bits || !Ancilla_CheckLinkCollision(k, 0, &coll) || ancilla_floor[k] != link_is_on_lower_level)
return;
if (coll.r8 >= 16 || coll.r10 >= 12) {
int j = (coll.r8 >= coll.r10) ? (sign8(coll.r4) ? 1 : 0) : (sign8(coll.r6) ? 3 : 2);
if (j * 2 != link_direction_facing)
return;
}
flag_is_ancilla_to_pick_up = k + 1;
ancilla_K[k] = 0;
ancilla_aux_timer[k] = kAncilla_Liftable_Delay[0];
ancilla_L[k] = 0;
ancilla_z[k] = 0;
return;
}
if (flag_is_ancilla_to_pick_up != k + 1)
return;
if (!link_disable_sprite_damage && link_incapacitated_timer || byte_7E03FD || link_auxiliary_state == 1) {
ancilla_R[k] = 1;
ancilla_z_vel[k] = 0;
flag_is_ancilla_to_pick_up = 0;
ancilla_arr4[k] = 0;
goto label_6;
}
if (!(link_state_bits & 0x80))
goto clear_pickup_item;
int j = ancilla_K[k];
if (link_picking_throw_state != 2 && flag_is_ancilla_to_pick_up != 0 && j != 3) {
if (j == 0 && ancilla_aux_timer[k] == 16)
Ancilla_Sfx2_Pan(k, 0x1d);
if (sign8(--ancilla_aux_timer[k])) {
ancilla_K[k] = ++j;
ancilla_aux_timer[k] = j == 3 ? -2 : kAncilla_Liftable_Delay[j];
if (j == 3) {
Ancilla_LatchAltitudeAboveLink(k);
return;
}
}
Ancilla_LatchLinkCoordinates(k, j);
return;
}
if (j != 3)
return;
if (link_picking_throw_state != 2 && (submodule_index != 0 || !((filtered_joypad_L | filtered_joypad_H) & 0x80))) {
if (ancilla_item_to_link[k])
return;
if (player_near_pit_state >= 2) {
link_speed_setting = 0;
if (k + 1 == flag_is_ancilla_to_pick_up) {
flag_is_ancilla_to_pick_up = 0;
ancilla_type[k] = 0;
}
return;
}
if (!(link_is_in_deep_water | link_is_bunny_mirror)) {
Ancilla_LatchCarriedPosition(k);
return;
}
link_state_bits = 0;
}
static const int8 kAncilla_Liftable_Yvel[4] = {-32, 32, 0, 0};
static const int8 kAncilla_Liftable_Xvel[4] = {0, 0, -32, 32};
j = link_direction_facing >> 1;
ancilla_dir[k] = j;
ancilla_z_vel[k] = 24;
ancilla_y_vel[k] = kAncilla_Liftable_Yvel[j];
ancilla_x_vel[k] = kAncilla_Liftable_Xvel[j];
link_picking_throw_state = 2;
ancilla_L[k] = 1;
flag_is_ancilla_to_pick_up = 0;
ancilla_arr4[k] = 0;
ancilla_K[k] = 0;
ancilla_objprio[k] = 0;
Ancilla_Sfx3_Pan(k, 0x13);
}
// endif_1
if (!ancilla_item_to_link[k]) {
ancilla_z_vel[k] -= 2;
Ancilla_MoveY(k);
Ancilla_MoveX(k);
uint8 old_z = ancilla_z[k];
Ancilla_MoveZ(k);
if (ancilla_arr4[k] && ancilla_dir[k] == 1 && !sign8(ancilla_z[k]))
Ancilla_SetY(k, Ancilla_GetY(k) + (int8)(ancilla_z[k] - old_z));
if (!sign8(ancilla_z[k]) || ancilla_z[k] == 0xff)
return;
ancilla_z[k] = 0;
Ancilla_Sfx2_Pan(k, 0x21);
if (++ancilla_L[k] != 3) {
ancilla_y_vel[k] = (int8)ancilla_y_vel[k] / 2;
ancilla_x_vel[k] = (int8)ancilla_x_vel[k] / 2;
ancilla_z_vel[k] = 16;
ancilla_arr4[k] = 0;
} else {
ancilla_z[k] = 0;
ancilla_L[k] = 0;
ancilla_arr4[k] = 0;
link_speed_setting = 0;
ancilla_y_vel[k] = 0;
ancilla_x_vel[k] = 0;
ancilla_z_vel[k] = 0;
if (ancilla_T[k]) {
ancilla_floor[k] = ancilla_T[k];
ancilla_T[k] = 0;
}
}
}
}
void Ancilla_LatchAltitudeAboveLink(int k) { // 889a4f
ancilla_z[k] = 17;
Ancilla_SetY(k, Ancilla_GetY(k) + 17);
ancilla_objprio[k] = 0;
}
void Ancilla_LatchLinkCoordinates(int k, int j) { // 889a6a
static const int8 kAncilla_Func3_X[12] = {8, 8, -4, 20, 8, 8, 8, 8, 8, 8, 8, 8};
static const int8 kAncilla_Func3_Y[12] = {16, 8, 4, 4, 8, 2, -1, -1, 2, 2, -1, -1};
j = j * 4 + (link_direction_facing >> 1);
Ancilla_SetXY(k,
link_x_coord + kAncilla_Func3_X[j],
link_y_coord + kAncilla_Func3_Y[j]);
}
void Ancilla_LatchCarriedPosition(int k) { // 889bef
static const int8 kAncilla_Func2_Y[6] = {-2, -1, 0, -2, -1, 0};
link_speed_setting = 12;
ancilla_floor[k] = link_is_on_lower_level;
ancilla_floor2[k] = link_is_on_lower_level_mirror;
uint16 z = link_z_coord;
if (z == 0xffff)
z = 0;
Ancilla_SetXY(k,
link_x_coord + 8,
link_y_coord - z + 18 + kAncilla_Func2_Y[link_animation_steps]);
}
uint16 Ancilla_LatchYCoordToZ(int k) { // 889c7f
uint16 y = Ancilla_GetY(k);
int8 z = ancilla_z[k];
if (ancilla_dir[k] == 1 && z != -1)
Ancilla_SetY(k, y - z);
return y;
}
int Bomb_GetDisplacementFromLink(int k) { // 889cce
int x = Ancilla_GetX(k), y = Ancilla_GetY(k);
return ((abs16(link_x_coord + 8 - x) + abs16(link_y_coord + 12 - y)) & 0xfc) >> 2;
}
void Bomb_Draw(int k) { // 889e9e
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
int z = (int8)ancilla_z[k];
if (z != 0 && z != -1 && ancilla_K[k] != 3 && ancilla_objprio[k])
oam_priority_value = 0x3000;
pt.y -= z;
int j = kBomb_Draw_Tab0[ancilla_item_to_link[k]] * 6;
uint8 r11 = 2;
if (ancilla_item_to_link[k] == 0) {
r11 = (ancilla_arr3[k] < 0x20) ? ancilla_arr3[k] & 0xe : 4;
}
if (ancilla_item_to_link[k] == 0) {
if (ancilla_L[k] == 0 && (sprite_type[0] == 0x92 || k + 1 == flag_is_ancilla_to_pick_up ) && (!(link_state_bits & 0x80) || ancilla_K[k] != 3 && link_direction_facing == 0)) {
Ancilla_AllocateOamFromRegion_B_or_E(12);
} else if (sort_sprites_setting && ancilla_floor[k] && (ancilla_L[k] || k + 1 == flag_is_ancilla_to_pick_up && (link_state_bits & 0x80))) {
oam_cur_ptr = 0x800 + 0x34 * 4;
oam_ext_cur_ptr = 0xa20 + 0x34;
}
}
OamEnt *oam = GetOamCurPtr(), *oam_org = oam;
uint8 numframes = kBomb_Draw_Tab2[ancilla_item_to_link[k]];
oam += (ancilla_item_to_link[k] == 0 && (ancilla_tile_attr[k] == 9 || ancilla_tile_attr[k] == 0x40)) ? 2 : 0;
AncillaDraw_Explosion(oam, j, 0, numframes, r11, pt.x, pt.y);
oam += numframes;
uint8 r10;
if (!Bomb_CheckUndersideSpriteStatus(k, &pt, &r10)) {
if (oam != oam_org + 1)
oam = oam_org;
AncillaDraw_Shadow(oam, r10, pt.x, pt.y, HIBYTE(oam_priority_value));
}
}
void Ancilla08_DoorDebris(int k) { // 889fb6
DoorDebris_Draw(k);
if (sign8(--ancilla_arr26[k])) {
ancilla_arr26[k] = 7;
if (++ancilla_arr25[k] == 4)
ancilla_type[k] = 0;
}
}
void DoorDebris_Draw(int k) { // 88a091
static const uint16 kDoorDebris_XY[64] = {
4, 7, 3, 17, 8, 8, 7, 17, 11, 7, 10, 16, 16, 7, 17, 17,
20, 7, 21, 17, 16, 8, 17, 17, 13, 7, 14, 16, 8, 7, 7, 17,
7, 4, 17, 3, 8, 8, 17, 7, 7, 11, 16, 10, 7, 16, 17, 17,
7, 20, 17, 21, 8, 16, 17, 17, 7, 13, 16, 14, 7, 8, 17, 7,
};
static const uint16 kDoorDebris_CharFlags[32] = {
0x205e, 0xe05e, 0xa05e, 0x605e, 0x204f, 0x204f, 0x204f, 0x204f, 0x605e, 0x605e, 0x205e, 0xe05e, 0x604f, 0x604f, 0x604f, 0x604f,
0x205e, 0xe05e, 0xa05e, 0x605e, 0x204f, 0xe04f, 0x204f, 0x204f, 0x605e, 0x605e, 0x205e, 0xe05e, 0x604f, 0x604f, 0x604f, 0x604f,
};
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
int y = door_debris_y[k] - BG2VOFS_copy2;
int x = door_debris_x[k] - BG2HOFS_copy2;
int j = ancilla_arr25[k] + door_debris_direction[k] * 4;
for (int i = 0; i != 2; i++) {
int t = j * 2 + i;
//kDoorDebris_XY
uint8 ext = Ancilla_SetOam_XY(oam, x + kDoorDebris_XY[t * 2 + 1], y + kDoorDebris_XY[t * 2 + 0]);
uint16 d = kDoorDebris_CharFlags[t];
oam->charnum = d;
oam->flags = (d >> 8) & 0xc0 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
oam = Ancilla_AllocateOamFromCustomRegion(oam + 1);
}
}
void Ancilla09_Arrow(int k) { // 88a131
static const int8 kArrow_Y[4] = {-4, 2, 0, 0};
static const int8 kArrow_X[4] = {0, 0, -4, 4};
int j;
if (submodule_index != 0) {
Arrow_Draw(k);
return;
}
if (!sign8(--ancilla_item_to_link[k])) {
if (ancilla_item_to_link[k] >= 4)
return;
} else {
ancilla_item_to_link[k] = 0xff;
}
Ancilla_MoveY(k);
Ancilla_MoveX(k);
if (link_item_bow & 4 && !(frame_counter & 1))
AncillaAdd_SilverArrowSparkle(k);
ancilla_S[k] = 255;
if ((j = Ancilla_CheckSpriteCollision(k)) >= 0) {
ancilla_x_vel[k] = ancilla_x_lo[k] - sprite_x_lo[j];
ancilla_y_vel[k] = ancilla_y_lo[k] - sprite_y_lo[j] + sprite_z[j];
ancilla_S[k] = j;
if (sprite_type[j] == 0x65) {
if (sprite_A[j] == 1) {
sound_effect_2 = 0x2d;
sprite_delay_aux2[j] = 0x80;
sprite_delay_aux4[0] = 128;
if (byte_7E0B88 < 9)
byte_7E0B88++;
sprite_B[j] = byte_7E0B88;
sprite_G[j] += 1;
} else {
sprite_delay_aux3[j] = 4;
byte_7E0B88 = 0;
}
} else {
byte_7E0B88 = 0;
}
} else if ((j = Ancilla_CheckTileCollision(k)) != 0) {
ancilla_H[k] = j >> 1;
j = ancilla_dir[k] & 3;
Ancilla_SetX(k, Ancilla_GetX(k) + kArrow_X[j]);
Ancilla_SetY(k, Ancilla_GetY(k) + kArrow_Y[j]);
byte_7E0B88 = 0;
} else {
Arrow_Draw(k);
return;
}
if (sprite_type[j] != 0x1b)
Ancilla_Sfx2_Pan(k, 8);
ancilla_item_to_link[k] = 0;
ancilla_type[k] = 10;
ancilla_aux_timer[k] = 1;
if (ancilla_H[k]) {
ancilla_x_lo[k] += BG1HOFS_copy2 - BG2HOFS_copy2;
ancilla_y_lo[k] += BG1VOFS_copy2 - BG2VOFS_copy2;
}
Arrow_Draw(k);
}
void Arrow_Draw(int k) { // 88a36e
static const uint8 kArrow_Draw_Char[48] = {
0x2b, 0x2a, 0x2a, 0x2b, 0x3d, 0x3a, 0x3a, 0x3d, 0x2b, 0xff, 0x2b, 0xff, 0x3d, 0xff, 0x3d, 0xff,
0x3c, 0x2c, 0x3c, 0x2a, 0x3c, 0x2c, 0x3c, 0x2a, 0x2c, 0x3c, 0x2a, 0x3c, 0x2c, 0x3c, 0x2a, 0x3c,
0x3b, 0x2d, 0x3b, 0x3a, 0x3b, 0x2d, 0x3b, 0x3a, 0x2d, 0x3b, 0x3a, 0x3b, 0x2d, 0x3b, 0x3a, 0x3b,
};
static const uint8 kArrow_Draw_Flags[48] = {
0xa4, 0xa4, 0x24, 0x24, 0x64, 0x64, 0x24, 0x24, 0xa4, 0xff, 0x24, 0xff, 0x64, 0xff, 0x24, 0xff,
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xe4, 0xa4, 0xa4, 0x24, 0x24, 0x24, 0x24, 0x64, 0x24, 0x24, 0x24,
0x64, 0x64, 0x64, 0xe4, 0x64, 0xe4, 0x64, 0xe4, 0x24, 0x24, 0x24, 0xa4, 0xa4, 0x24, 0x24, 0xa4,
};
static const int8 kArrow_Draw_Y[48] = {
0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8,
-1, -1, 0, 0, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 0, 0,
};
static const int8 kArrow_Draw_X[48] = {
0, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, -1, -2, 0, 0, 1, 1, 0, 0, -2, -1, 0, 0,
0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8,
};
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
if (ancilla_objprio[k])
HIBYTE(oam_priority_value) = 0x30;
uint16 x = pt.x, y = pt.y;
if (ancilla_H[k] != 0) {
x += BG2VOFS_copy2 - BG1VOFS_copy2;
y += BG2HOFS_copy2 - BG1HOFS_copy2;
}
uint8 r7 = ancilla_item_to_link[k];
int j = ancilla_dir[k] & ~4;
if (ancilla_type[k] == 0xa) {
j = j * 4 + 8 + ((r7 & 8) ? 1 : (r7 & 3));
} else if (!sign8(r7)) {
j |= 4;
}
j *= 2;
OamEnt *oam = GetOamCurPtr(), *oam_org = oam;
uint8 flags = (link_item_bow & 4) ? 2 : 4;
for (int i = 0; i != 2; i++, j++) {
if (kArrow_Draw_Char[j] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam, x + kArrow_Draw_X[j], y + kArrow_Draw_Y[j]);
oam->charnum = kArrow_Draw_Char[j];
oam->flags = kArrow_Draw_Flags[j] & ~0x3E | flags | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
}
if (oam_org[0].y == 0xf0 && oam_org[1].y == 0xf0)
ancilla_type[k] = 0;
}
void Ancilla0A_ArrowInTheWall(int k) { // 88a45b
int j = ancilla_S[k];
if (!sign8(j)) {
if (sprite_state[j] < 9 || sign8(sprite_z[j]) || sprite_ignore_projectile[j] || sprite_defl_bits[j] & 2) {
ancilla_type[k] = 0;
return;
}
Ancilla_SetX(k, Sprite_GetX(j) + (int8)ancilla_x_vel[k]);
Ancilla_SetY(k, Sprite_GetY(j) + (int8)ancilla_y_vel[k] - sprite_z[j]);
}
if (submodule_index == 0 && --ancilla_aux_timer[k] == 0) {
ancilla_aux_timer[k] = 2;
if (++ancilla_item_to_link[k] == 9) {
ancilla_type[k] = 0;
return;
} else if (ancilla_item_to_link[k] & 8) {
ancilla_aux_timer[k] = 0x80;
}
}
Arrow_Draw(k);
}
void Ancilla0B_IceRodShot(int k) { // 88a4dd
if (submodule_index == 0) {
if (sign8(--ancilla_aux_timer[k])) {
if (++ancilla_item_to_link[k] & ~1) {
ancilla_step[k] = 1;
ancilla_item_to_link[k] = ancilla_item_to_link[k] & 7 | 4;
}
ancilla_aux_timer[k] = 3;
}
if (ancilla_step[k]) {
AncillaOamInfo info;
if (Ancilla_ReturnIfOutsideBounds(k, &info))
return;
Ancilla_MoveY(k);
Ancilla_MoveX(k);
if (Ancilla_CheckSpriteCollision(k) >= 0 || Ancilla_CheckTileCollision(k)) {
ancilla_type[k] = 0x11;
ancilla_numspr[k] = kAncilla_Pflags[0x11];
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 4;
}
}
}
AncillaAdd_IceRodSparkle(k);
}
void Ancilla11_IceRodWallHit(int k) { // 88a536
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 7;
if (++ancilla_item_to_link[k] == 2) {
ancilla_type[k] = 0;
return;
}
}
IceShotSpread_Draw(k);
}
void IceShotSpread_Draw(int k) { // 88a571
static const uint8 kIceShotSpread_CharFlags[16] = {0xcf, 0x24, 0xcf, 0x24, 0xcf, 0x24, 0xcf, 0x24, 0xdf, 0x24, 0xdf, 0x24, 0xdf, 0x24, 0xdf, 0x24};
static const uint8 kIceShotSpread_XY[16] = {0, 0, 0, 8, 8, 0, 8, 8, 0xf8, 0xf8, 0xf8, 0x10, 0x10, 0xf8, 0x10, 0x10};
Point16U info;
Ancilla_PrepOamCoord(k, &info);
Ancilla_AllocateOamFromRegion_A_or_D_or_F(k, ancilla_numspr[k]);
OamEnt *oam = GetOamCurPtr();
int j = ancilla_item_to_link[k] * 4;
for (int i = 0; i != 4; i++, j++) {
uint16 y = info.y + (int8)kIceShotSpread_XY[j * 2 + 0];
uint16 x = info.x + (int8)kIceShotSpread_XY[j * 2 + 1];
uint8 yv = 0xf0;
if (x < 256 && y < 256) {
oam->x = x;
if (y < 224)
yv = y;
}
oam->y = yv;
oam->charnum = kIceShotSpread_CharFlags[j * 2 + 0];
oam->flags = kIceShotSpread_CharFlags[j * 2 + 1] & ~0x30 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = 0;
oam = Ancilla_AllocateOamFromCustomRegion(oam + 1);
}
oam = GetOamCurPtr();
if (oam[0].y == 0xf0 && oam[1].y == 0xf0)
ancilla_type[k] = 0;
}
void Ancilla33_BlastWallExplosion(int k) { // 88a60e
if (submodule_index == 0) {
if (blastwall_var5[k]) {
if (--blastwall_var6[k] == 0) {
if (++blastwall_var5[k] != 0 && blastwall_var5[k] < 9) {
AncillaAdd_BlastWallFireball(0x32, 10, k * 4);
}
if (blastwall_var5[k] == 11) {
blastwall_var5[k] = 0;
blastwall_var6[k] = 0;
} else {
blastwall_var6[k] = 3;
}
}
} else if ((k ^= 1), blastwall_var5[k] == 6 && blastwall_var6[k] == 2 && (uint8)(ancilla_item_to_link[0] + 1) < 7) {
ancilla_item_to_link[0]++;
blastwall_var5[k] = 1;
blastwall_var6[k] = 3;
for (int i = 3; i >= 0; i--) {
int8 arr[2] = { 0, 0 };
int j = blastwall_var7 < 4 ? 1 : 0;
arr[j] = (i & 2) ? -13 : 13;
j = k * 4 + i;
blastwall_var10[j] += arr[0];
blastwall_var11[j] += arr[1];
uint16 x = blastwall_var11[j] - BG2HOFS_copy2;
if (x < 256)
sound_effect_1 = kBombos_Sfx[x >> 5] | 0xc;
}
}
}
if (blastwall_var5[ancilla_K[0]]) {
int i = (ancilla_K[0] == 1) ? 7 : 3;
do {
AncillaDraw_BlastWallBlast(ancilla_K[0], blastwall_var11[i], blastwall_var10[i]);
} while ((--i & 3) != 3);
}
if (ancilla_item_to_link[0] == 6) {
if (blastwall_var5[0] == 0 && blastwall_var5[1] == 0) {
ancilla_type[0] = 0;
ancilla_type[1] = 0;
flag_custom_spell_anim_active = 0;
}
}
}
void AncillaDraw_BlastWallBlast(int k, int x, int y) { // 88a756
oam_priority_value = 0x3000;
if (sort_sprites_setting)
Oam_AllocateFromRegionD(0x18);
else
Oam_AllocateFromRegionA(0x18);
OamEnt *oam = GetOamCurPtr();
int i = blastwall_var5[k];
AncillaDraw_Explosion(oam, kBomb_Draw_Tab0[i] * 6, 0, kBomb_Draw_Tab2[i], 0x32,
x - BG2HOFS_copy2, y - BG2VOFS_copy2);
}
OamEnt *AncillaDraw_Explosion(OamEnt *oam, int frame, int idx, int idx_end, uint8 r11, int x, int y) { // 88a7ab
static const int8 kBomb_DrawExplosion_XY[108] = {
-8, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, 0,
0, -8, 0, 0, 0, 0, 0, 0, -16, -16, -16, 0, 0, -16, 0, 0,
0, 0, 0, 0, -16, -16, -16, 0, 0, -16, 0, 0, 0, 0, 0, 0,
-8, -8, -21, -22, -21, 8, 9, -22, 9, 8, 0, 0, -6, -15, 0, -1,
-16, -2, -8, -7, 0, 0, 0, 0, -9, -4, -21, -5, -12, -18, -11, 7,
0, -15, 4, -2, -9, -4, -22, -5, -13, -20, -11, 8, 1, -16, 5, -2,
-20, 4, -12, -19, -9, 16, -5, -2, 2, -9, 10, 6,
};
static const uint8 kBomb_DrawExplosion_CharFlags[108] = {
0x6e, 0x26, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8c, 0x22, 0x8c, 0x62,
0x8c, 0xa2, 0x8c, 0xe2, 0xff, 0xff, 0xff, 0xff, 0x84, 0x22, 0x84, 0x62, 0x84, 0xa2, 0x84, 0xe2,
0xff, 0xff, 0xff, 0xff, 0x88, 0x22, 0x88, 0x62, 0x88, 0xa2, 0x88, 0xe2, 0xff, 0xff, 0xff, 0xff,
0x86, 0x22, 0x88, 0x22, 0x88, 0x62, 0x88, 0xa2, 0x88, 0xe2, 0xff, 0xff, 0x86, 0x22, 0x86, 0x62,
0x86, 0xe2, 0x86, 0xe2, 0xff, 0xff, 0xff, 0xff, 0x86, 0xe2, 0x86, 0x22, 0x86, 0x22, 0x86, 0x62,
0x86, 0xa2, 0x86, 0xa2, 0x8a, 0xa2, 0x8a, 0x62, 0x8a, 0x22, 0x8a, 0x62, 0x8a, 0x62, 0x8a, 0xe2,
0x9b, 0x22, 0x9b, 0xa2, 0x9b, 0x62, 0x9b, 0xe2, 0x9b, 0xa2, 0x9b, 0x22,
};
static const uint8 kBomb_DrawExplosion_Ext[54] = {
2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2,
1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2,
2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
0, 0, 0, 0, 0, 0,
};
int base_frame = frame;
do {
if (kBomb_DrawExplosion_CharFlags[frame * 2] != 0xff) {
int i = idx + base_frame;
uint16 xt = x + kBomb_DrawExplosion_XY[i * 2 + 1];
uint8 ext = Ancilla_SetOam_XY_safe(oam, xt, y + kBomb_DrawExplosion_XY[i * 2 + 0]);
oam->charnum = kBomb_DrawExplosion_CharFlags[frame * 2];
oam->flags = kBomb_DrawExplosion_CharFlags[frame * 2 + 1] & ~0x3E | HIBYTE(oam_priority_value) | r11;
bytewise_extended_oam[oam - oam_buf] = ext | kBomb_DrawExplosion_Ext[frame];
oam++;
}
} while (frame++, ++idx != idx_end);
return oam;
}
void Ancilla15_JumpSplash(int k) { // 88a80f
static const uint8 kAncilla_JumpSplash_Char[2] = {0xac, 0xae};
if (!submodule_index) {
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 0;
ancilla_item_to_link[k] = 1;
}
if (ancilla_item_to_link[k]) {
ancilla_x_vel[k] = ancilla_y_vel[k] = ancilla_y_vel[k] - 4;
if (ancilla_y_vel[k] < 232) {
ancilla_type[k] = 0;
if ((link_is_bunny_mirror || link_player_handler_state == kPlayerState_Swimming) && link_is_in_deep_water)
CheckAbilityToSwim();
return;
}
Ancilla_MoveX(k);
Ancilla_MoveY(k);
}
}
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
int ax = Ancilla_GetX(k);
int x8 = link_x_coord * 2 - ax - BG2HOFS_copy2;
int x6 = ax + 12 - BG2HOFS_copy2;
int j = ancilla_item_to_link[k];
uint8 flags = 0;
for (int i = 0; i < 2; i++) {
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y);
oam->charnum = kAncilla_JumpSplash_Char[j];
oam->flags = 0x24 | flags;
bytewise_extended_oam[oam - oam_buf] = ext | 2;
oam = Ancilla_AllocateOamFromCustomRegion(oam + 1);
pt.x = x8;
flags = 0x40;
}
uint8 ext = Ancilla_SetOam_XY(oam, x6, pt.y);
oam->charnum = 0xc0;
oam->flags = 0x24;
bytewise_extended_oam[oam - oam_buf] = ext | ((j == 1) ? 1 : 2);
}
void Ancilla16_HitStars(int k) { // 88a8e5
static const uint8 kAncilla_HitStars_Char[2] = {0x90, 0x91};
if (!sign8(--ancilla_arr3[k]))
return;
ancilla_arr3[k] = 0;
if (!submodule_index) {
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 0;
ancilla_item_to_link[k] = 1;
}
if (ancilla_item_to_link[k]) {
ancilla_x_vel[k] = (ancilla_y_vel[k] -= 4);
if (ancilla_y_vel[k] < 232) {
ancilla_type[k] = 0;
return;
}
Ancilla_MoveY(k);
Ancilla_MoveX(k);
}
}
Point16U info;
Ancilla_PrepOamCoord(k, &info);
uint16 ax = Ancilla_GetX(k);
uint16 tt = ancilla_B[k] << 8 | ancilla_A[k];
uint16 r8 = 2 * tt - ax - 8 - BG2HOFS_copy2;
if (ancilla_step[k] == 2)
Ancilla_AllocateOamFromRegion_B_or_E(8);
OamEnt *oam = GetOamCurPtr();
uint16 x = info.x, y = info.y;
uint8 flags = 0;
for (int i = 1; i >= 0; i--) {
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = kAncilla_HitStars_Char[ancilla_item_to_link[k]];
oam->flags = HIBYTE(oam_priority_value) | 4 | flags;
bytewise_extended_oam[oam - oam_buf] = ext;
flags = 0x40;
BYTE(x) = r8;
oam = HitStars_UpdateOamBufferPosition(oam + 1);
}
}
void Ancilla17_ShovelDirt(int k) { // 88a9a9
static const int8 kShovelDirt_XY[8] = {18, -13, -9, 4, 18, 13, -9, -11};
static const int8 kShovelDirt_Char[2] = {0x40, 0x50};
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
if (!ancilla_timer[k]) {
ancilla_timer[k] = 8;
if (++ancilla_item_to_link[k] == 2) {
ancilla_type[k] = 0;
return;
}
}
int b = ancilla_item_to_link[k];
int j = b + ((link_direction_facing == 4) ? 0 : 2);
pt.x += kShovelDirt_XY[j * 2 + 1];
pt.y += kShovelDirt_XY[j * 2 + 0];
for (int i = 0; i < 2; i++) {
uint8 ext = Ancilla_SetOam_XY(oam, pt.x + i * 8, pt.y);
oam->charnum = kShovelDirt_Char[b] + i;
oam->flags = 4 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
oam = Ancilla_AllocateOamFromCustomRegion(oam + 1);
}
}
void Ancilla32_BlastWallFireball(int k) { // 88aa35
static const uint8 kBlastWallFireball_Char[3] = {0x9d, 0x9c, 0x8d};
if (!submodule_index) {
ancilla_item_to_link[k] += 2;
ancilla_y_vel[k] += ancilla_item_to_link[k];
Ancilla_MoveY(k);
Ancilla_MoveX(k);
if (sign8(--blastwall_var12[k])) {
ancilla_type[k] = 0;
return;
}
}
if (sort_sprites_setting)
Oam_AllocateFromRegionD(4);
else
Oam_AllocateFromRegionA(4);
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y);
oam->charnum = kBlastWallFireball_Char[blastwall_var12[k] & 8 ? 0 : blastwall_var12[k] & 4 ? 1 : 2];
oam->flags = 0x22;
bytewise_extended_oam[oam - oam_buf] = ext;
}
void Ancilla18_EtherSpell(int k) { // 88aaa0
if (submodule_index)
return;
if (ancilla_step[k] != 0) {
uint8 flag;
if (step_counter_for_spin_attack == 0) {
flag = (++ancilla_arr4[k] & 4) == 0;
} else {
flag = step_counter_for_spin_attack == 11;
}
if (flag) {
Palette_ElectroThemedGear();
Filter_Majorly_Whiten_Bg();
} else {
LoadActualGearPalettes();
Palette_Restore_BG_From_Flash();
}
}
if (ancilla_step[k] == 2) {
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 2;
if (++ancilla_item_to_link[k] == 2) {
ancilla_item_to_link[k]--;
ancilla_x_vel[k] = 16;
ancilla_step[k] = 3;
}
}
ancilla_x_vel[k] += 1;
EtherSpell_HandleRadialSpin(k);
return;
} else {
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 2;
ancilla_item_to_link[k] ^= 1;
}
if (ancilla_step[k] == 0) {
EtherSpell_HandleLightningStroke(k);
} else if (ancilla_step[k] == 1) {
EtherSpell_HandleOrbPulse(k);
} else if (ancilla_step[k] == 3) {
EtherSpell_HandleRadialSpin(k);
} else if (ancilla_step[k] == 4) {
if (!--ether_var1)
ancilla_step[k] = 5;
EtherSpell_HandleRadialSpin(k);
} else {
uint8 vel = ancilla_x_vel[k] + 0x10;
if (sign8(vel)) vel = 0x7f;
ancilla_x_vel[k] = vel;
EtherSpell_HandleRadialSpin(k);
}
}
}
void EtherSpell_HandleLightningStroke(int k) { // 88ab63
Ancilla_MoveY(k);
uint16 y = Ancilla_GetY(k);
if (BYTE(ether_y_adjusted) != (y & 0xf0)) {
BYTE(ether_y_adjusted) = y & 0xf0;
ancilla_arr25[k]++;
}
if (y < 0xe000 && ether_y2 < 0xe000 && ether_y2 <= y) {
ancilla_step[k] = 1;
}
AncillaDraw_EtherBlitz(k);
}
void EtherSpell_HandleOrbPulse(int k) { // 88aba7
if (!sign8(ancilla_arr25[k])) {
if (!sign8(--ancilla_arr3[k])) {
AncillaDraw_EtherBlitz(k);
return;
}
ancilla_arr3[k] = 3;
if (!sign8(--ancilla_arr25[k])) {
AncillaDraw_EtherBlitz(k);
return;
}
ancilla_arr3[k] = 9;
}
if (sign8(--ancilla_arr3[k])) {
ancilla_step[k] = 2;
ancilla_y_vel[k] = 0;
ancilla_x_vel[k] = 16;
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 2;
if (step_counter_for_spin_attack)
Medallion_CheckSpriteDamage(k);
}
AncillaDraw_EtherOrb(k, GetOamCurPtr());
}
void EtherSpell_HandleRadialSpin(int k) { // 88abef
if (ancilla_step[k] == 4) {
if ((frame_counter & 7) == 0)
sound_effect_2 = 0x2a;
else if ((frame_counter & 7) == 4)
sound_effect_2 = 0xaa;
else if ((frame_counter & 7) == 7)
sound_effect_2 = 0x6a;
} else {
ancilla_x_lo[k] = ether_var2;
ancilla_x_hi[k] = 0;
Ancilla_MoveX(k);
ether_var2 = ancilla_x_lo[k];
if (ether_var2 == 0x40)
ancilla_step[k] = 4;
}
uint8 sb = ancilla_step[k];
uint8 sa = ancilla_item_to_link[k];
OamEnt *oam = GetOamCurPtr();
for (int i = 7; i >= 0; i--) {
if (sb != 2 && sb != 5) {
ether_arr1[i] = (ether_arr1[i] + 1) & 0x3f;
}
AncillaRadialProjection arp = Ancilla_GetRadialProjection(ether_arr1[i], ether_var2);
if (sb != 2)
oam = AncillaDraw_EtherBlitzBall(oam, &arp, sa);
else
oam = AncillaDraw_EtherBlitzSegment(oam, &arp, sa, i);
}
if (ether_var2 < 0xf0) {
OamEnt *oam = GetOamCurPtr();
for (int i = 0; i != 8; i++) {
if (oam[i].y != 0xf0)
return;
}
}
ancilla_type[k] = 0;
load_chr_halfslot_even_odd = 1;
byte_7E0324 = 0;
state_for_spin_attack = 0;
step_counter_for_spin_attack = 0;
link_cant_change_direction = 0;
flag_unk1 = 0;
if (BYTE(overworld_screen_index) == 0x70 && !(save_ow_event_info[0x70] & 0x20) && Ancilla_CheckForEntranceTrigger(2)) {
trigger_special_entrance = 3;
subsubmodule_index = 0;
BYTE(R16) = 0;
}
if (link_player_handler_state != kPlayerState_ReceivingEther) {
link_player_handler_state = kPlayerState_Ground;
link_delay_timer_spin_attack = 0;
button_mask_b_y = button_b_frames ? (joypad1H_last & 0x80) : 0;
}
link_speed_setting = 0;
byte_7E0325 = 0;
LoadActualGearPalettes();
Palette_Restore_BG_And_HUD();
}
OamEnt *AncillaDraw_EtherBlitzBall(OamEnt *oam, const AncillaRadialProjection *arp, int s) { // 88aced
static const uint8 kEther_BlitzBall_Char[2] = {0x68, 0x6a};
int x = (arp->r6 ? -arp->r4 : arp->r4) + ether_x2 - 8 - BG2HOFS_copy2;
int y = (arp->r2 ? -arp->r0 : arp->r0) + ether_y3 - 8 - BG2VOFS_copy2;
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = kEther_BlitzBall_Char[s];
oam->flags = 0x3c;
bytewise_extended_oam[oam - oam_buf] = ext | 2;
return Ancilla_AllocateOamFromCustomRegion(oam + 1);
}
OamEnt *AncillaDraw_EtherBlitzSegment(OamEnt *oam, const AncillaRadialProjection *arp, int s, int k) { // 88adc9
static const int8 kEther_SpllittingBlitzSegment_X[16] = {-8, -16, -24, -16, -8, 0, 8, -16, -8, -16, -24, -16, -8, 0, 8, 0};
static const int8 kEther_SpllittingBlitzSegment_Y[16] = {8, 0, -8, -16, -24, -16, -8, -16, 8, 0, -8, -16, -24, -16, -8, 0};
static const uint8 kEther_SpllittingBlitzSegment_Char[32] = {
0x40, 0x42, 0x66, 0x64, 0x62, 0x60, 0x64, 0x66, 0x42, 0x40, 0x66, 0x64, 0x60, 0x62, 0x64, 0x66,
0x68, 0x42, 0x68, 0x64, 0x68, 0x60, 0x68, 0x64, 0x68, 0x40, 0x68, 0x66, 0x68, 0x62, 0x68, 0x64,
};
static const uint8 kEther_SpllittingBlitzSegment_Flags[32] = {
0x3c, 0x3c, 0xfc, 0xfc, 0x3c, 0x3c, 0xbc, 0xbc, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x7c, 0x7c,
0x3c, 0x7c, 0x3c, 0x3c, 0x3c, 0xbc, 0x3c, 0x7c, 0x3c, 0x7c, 0x3c, 0xfc, 0x3c, 0xbc, 0x3c, 0xbc,
};
int x = (arp->r6 ? -arp->r4 : arp->r4);
int y = (arp->r2 ? -arp->r0 : arp->r0);
uint8 ext = Ancilla_SetOam_XY(oam, x + ether_x2 - 8 - BG2HOFS_copy2, y + ether_y3 - 8 - BG2VOFS_copy2);
int t = s * 8 + k;
oam->charnum = kEther_SpllittingBlitzSegment_Char[t * 2];
oam->flags = kEther_SpllittingBlitzSegment_Flags[t * 2];
bytewise_extended_oam[oam - oam_buf] = ext | 2;
oam++;
ext = Ancilla_SetOam_XY(oam,
x + ether_x2 + kEther_SpllittingBlitzSegment_X[t] - BG2HOFS_copy2,
y + ether_y3 + kEther_SpllittingBlitzSegment_Y[t] - BG2VOFS_copy2);
oam->charnum = kEther_SpllittingBlitzSegment_Char[t * 2 + 1];
oam->flags = kEther_SpllittingBlitzSegment_Flags[t * 2 + 1];
bytewise_extended_oam[oam - oam_buf] = ext | 2;
return Ancilla_AllocateOamFromCustomRegion(oam + 1);
}
void AncillaDraw_EtherBlitz(int k) { // 88ae87
Point16U info;
Ancilla_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
int t = ancilla_item_to_link[k];
int i = ancilla_arr25[k];
int m = 0;
do {
uint8 ext = Ancilla_SetOam_XY(oam, info.x, info.y);
oam->charnum = kEther_BlitzSegment_Char[t * 2 + m];
oam->flags = kEther_BlitzOrb_Flags[0] | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext | 2;
info.y -= 16;
oam++;
m ^= 1;
} while (--i >= 0);
if (ancilla_step[k] == 1)
AncillaDraw_EtherOrb(k, oam);
}
void AncillaDraw_EtherOrb(int k, OamEnt *oam) { // 88aedd
uint16 y = ether_y - 1 - BG2VOFS_copy2;
uint16 x = ether_x - 8 - BG2HOFS_copy2;
int t = ancilla_item_to_link[k] * 4;
for (int i = 0; i < 4; i++) {
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = kEther_BlitzOrb_Char[t + i];
oam->flags = kEther_BlitzOrb_Flags[t + i];
bytewise_extended_oam[oam - oam_buf] = ext | 2;
oam++;
oam = Ancilla_AllocateOamFromCustomRegion(oam);
x += 16;
if (i == 1)
x -= 32, y += 16;
}
}
void AncillaAdd_BombosSpell(uint8 a, uint8 y) { // 88af66
int k = AncillaAdd_AddAncilla_Bank08(a, y);
if (k < 0)
return;
for (int i = 0; i < 10; i++) {
bombos_arr2[i] = 0;
bombos_arr1[i] = 3;
}
for (int i = 0; i < 8; i++) {
bombos_arr3[i] = 0;
bombos_arr4[i] = 3;
}
bombos_var4 = 0;
bombos_var2 = 0;
bombos_var3 = 0x80;
bombos_arr7[0] = 0x10;
load_chr_halfslot_even_odd = 11;
flag_custom_spell_anim_active = 1;
ancilla_step[k] = 0;
ancilla_item_to_link[k] = 0;
Ancilla_Sfx2_Near(0x2a);
uint8 t = kGeneratedBombosArr[frame_counter];
t = (t < 0xe0) ? t : t & 0x7f;
bombos_x_coord[0] = link_x_coord & ~0xff | t;
bombos_y_coord[0] = link_y_coord & ~0xff | t;
static const int16 kBombos_YDelta[4] = {16, 24, -128, -16};
static const int16 kBombos_XDelta[4] = {-16, -128, 0, 128};
for (int i = 0; i < 1 ; i++) {
bombos_x_coord2[i] = link_x_coord + kBombos_XDelta[i];
bombos_y_coord2[i] = link_y_coord + kBombos_YDelta[i];
bombos_var1 = 16;
AncillaRadialProjection arp = Ancilla_GetRadialProjection(bombos_arr7[i], 16);
int x = (arp.r6 ? -arp.r4 : arp.r4) + bombos_x_coord2[i];
int y = (arp.r2 ? -arp.r0 : arp.r0) + bombos_y_coord2[i];
bombos_x_lo[i] = (uint8)x;
bombos_x_hi[i] = x >> 8;
bombos_y_lo[i] = (uint8)y;
bombos_y_hi[i] = y >> 8;
}
}
void Ancilla19_BombosSpell(int k) { // 88b0ce
if (bombos_var4 == 0) {
if (submodule_index == 0) {
BombosSpell_ControlFireColumns(k);
return;
}
for (int i = 9; i >= 0; i--)
AncillaDraw_BombosFireColumn(i);
} else if (bombos_var4 != 2) {
if (submodule_index == 0) {
BombosSpell_FinishFireColumns(k);
return;
}
for (int i = 9; i >= 0; i--)
AncillaDraw_BombosFireColumn(i);
} else {
if (submodule_index == 0) {
BombosSpell_ControlBlasting(k);
return;
}
int i = ancilla_step[k];
do {
AncillaDraw_BombosBlast(i);
} while (--i >= 0);
}
}
void BombosSpell_ControlFireColumns(int k) { // 88b10a
uint8 sa = ancilla_item_to_link[k];
uint8 sb = ancilla_step[k];
int j, i = sb;
do {
if (bombos_arr2[i] == 13)
continue;
if (sign8(--bombos_arr1[i])) {
bombos_arr1[i] = 3;
if (++bombos_arr2[i] == 13)
continue;
if (bombos_arr2[i] == 2) {
if (sa)
continue;
// pushed x
if (sb == 9) {
for (j = 9; j >= 0; j--) {
if (bombos_arr2[j] == 13) {
bombos_arr2[j] = 0;
goto exit_loop;
}
}
}
sb = j = (sb + 1) != 10 ? sb + 1 : 9;
exit_loop:
bombos_var1 = (bombos_var1 + 3 >= 207) ? 207 : bombos_var1 + 3;
bombos_arr7[0] += 6;
AncillaRadialProjection arp = Ancilla_GetRadialProjection(bombos_arr7[0] & 0x3f, bombos_var1);
int x = (arp.r6 ? -arp.r4 : arp.r4) + bombos_x_coord2[0];
int y = (arp.r2 ? -arp.r0 : arp.r0) + bombos_y_coord2[0];
bombos_x_lo[j] = (uint8)x;
bombos_x_hi[j] = x >> 8;
bombos_y_lo[j] = (uint8)y;
bombos_y_hi[j] = y >> 8;
uint16 t = x - BG2HOFS_copy2 + 8;
if (t < 256)
sound_effect_1 = kBombos_Sfx[t >> 5] | 0x2a;
}
}
AncillaDraw_BombosFireColumn(i);
} while (--i >= 0);
if (bombos_arr7[0] >= 0x80)
bombos_var4 = 1;
ancilla_step[k] = sb;
}
void BombosSpell_FinishFireColumns(int kk) { // 88b236
int k = ancilla_step[kk];
do {
if (sign8(--bombos_arr1[k])) {
bombos_arr1[k] = 3;
if (++bombos_arr2[k] >= 13)
bombos_arr2[k] = 13;
}
AncillaDraw_BombosFireColumn(k);
} while (--k >= 0);
for (int k = 9; k >= 0; k--) {
if (bombos_arr2[k] != 13)
return;
}
bombos_var4 = 2;
Medallion_CheckSpriteDamage(kk);
ancilla_step[kk] = 0;
}
void AncillaDraw_BombosFireColumn(int kk) { // 88b373
static const int8 kBombosSpell_FireColumn_X[39] = {
0, -1, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-1, 1, -1, -1, 2, -1, -1,
};
static const int8 kBombosSpell_FireColumn_Y[39] = {
0, -1, -1, 0, -4, -1, 0, -8, -1, 0, -12, -1, 0, -16, -1, 0,
-4, -20, 0, -8, -24, 0, -12, -28, 0, -16, -32, 0, -16, -32, -18, -34,
-1, -35, -1, -1, -36, -1, -1,
};
static const uint8 kBombosSpell_FireColumn_Flags[39] = {
0x3c, 0xff, 0xff, 0x3c, 0x3c, 0xff, 0x3c, 0x3c, 0xff, 0x7c, 0x7c, 0xff, 0x3c, 0x7c, 0xff, 0x3c,
0x3c, 0x3c, 0xbc, 0x3c, 0x3c, 0x7c, 0x3c, 0x3c, 0x3c, 0x3c, 0x7c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0xff, 0x3c, 0xff, 0xff, 0x3c, 0xff, 0xff,
};
static const uint8 kBombosSpell_FireColumn_Char[39] = {
0x40, 0xff, 0xff, 0x42, 0x44, 0xff, 0x42, 0x44, 0xff, 0x42, 0x44, 0xff, 0x42, 0x44, 0xff, 0x40,
0x46, 0x44, 0x4a, 0x4a, 0x48, 0x4c, 0x4c, 0x4a, 0x4e, 0x4c, 0x4a, 0x4e, 0x6a, 0x4c, 0x4e, 0x68,
0xff, 0x6a, 0xff, 0xff, 0x4e, 0xff, 0xff,
};
Ancilla_AllocateOamFromRegion_A_or_D_or_F(kk, 0x10);
OamEnt *oam = GetOamCurPtr();
for (int i = 0; i < 1; i++) {
int k = bombos_arr2[kk];
if (k == 13)
continue;
k = k * 3 + 2;
for (int j = 0; j < 3; j++, k--) {
if (kBombosSpell_FireColumn_Char[k] != 0xff) {
uint16 x = bombos_x_lo[kk] | bombos_x_hi[kk] << 8;
uint16 y = bombos_y_lo[kk] | bombos_y_hi[kk] << 8;
y += kBombosSpell_FireColumn_Y[k] - BG2VOFS_copy2;
x += kBombosSpell_FireColumn_X[k] - BG2HOFS_copy2;
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = kBombosSpell_FireColumn_Char[k];
oam->flags = kBombosSpell_FireColumn_Flags[k];
bytewise_extended_oam[oam - oam_buf] = ext | 2;
oam++;
}
oam = Ancilla_AllocateOamFromCustomRegion(oam);
}
}
}
void BombosSpell_ControlBlasting(int kk) { // 88b40d
int k = ancilla_step[kk], sb = k;
for (; k >= 0; k--) {
if (bombos_arr3[k] != 8 && sign8(--bombos_arr4[k])) {
bombos_arr4[k] = 3;
if (++bombos_arr3[k] == 1 && !bombos_var2) {
int j = sb;
if (j != 15) {
j = ++sb;
} else {
for (; j >= 0 && bombos_arr3[j] != 8; j--) {}
}
bombos_arr3[j] = 0;
bombos_arr4[j] = 3;
uint16 y = kBombosBlasts_Tab[frame_counter & 0x3f];
uint16 x = kBombosBlasts_Tab[(frame_counter & 0x3f) + 3];
bombos_y_coord[j] = y + BG2VOFS_copy2;
bombos_x_coord[j] = x + BG2HOFS_copy2;
sound_effect_1 = 0xc | kBombos_Sfx[bombos_x_coord[j] >> 5 & 7];
}
}
AncillaDraw_BombosBlast(k);
}
for (int j = 15; j >= 0; j--) {
if (bombos_arr3[j] != 8) {
ancilla_step[kk] = sb;
goto getout;
}
}
ancilla_type[kk] = 0;
load_chr_halfslot_even_odd = 1;
byte_7E0324 = 0;
state_for_spin_attack = 0;
step_counter_for_spin_attack = 0;
link_cant_change_direction = 0;
flag_unk1 = 0;
if (link_player_handler_state != kPlayerState_ReceivingBombos) {
link_player_handler_state = kPlayerState_Ground;
link_delay_timer_spin_attack = 0;
button_mask_b_y = button_b_frames ? (joypad1H_last & 0x80) : 0;
}
link_speed_setting = 0;
byte_7E0325 = 0;
getout:
if (--bombos_var3 == 0)
bombos_var2 = bombos_var3 = 1;
}
void AncillaDraw_BombosBlast(int k) { // 88b5e1
static const int8 kBombosSpell_DrawBlast_X[32] = {
-8, -1, -1, -1, -12, -4, -12, -4, -16, 0, -16, 0, -16, 0, -16, 0,
-17, 1, -17, 1, -19, 3, -19, 3, -19, 3, -19, 3, -19, 3, -19, 3,
};
static const int8 kBombosSpell_DrawBlast_Y[32] = {
-8, -1, -1, -1, -12, -12, -4, -4, -16, -16, 0, 0, -16, -16, 0, 0,
-17, -17, 1, 1, -19, -19, 3, 3, -19, -19, 3, 3, -19, -19, 3, 3,
};
static const uint8 kBombosSpell_DrawBlast_Flags[32] = {
0x3c, 0xff, 0xff, 0xff, 0x3c, 0x7c, 0xbc, 0xfc, 0x3c, 0x7c, 0xbc, 0xfc, 0x3c, 0x7c, 0xbc, 0xfc,
0x3c, 0x7c, 0xbc, 0xfc, 0x3c, 0x7c, 0xbc, 0xfc, 0x3c, 0x7c, 0xbc, 0xfc, 0x3c, 0x7c, 0xbc, 0xfc,
};
static const uint8 kBombosSpell_DrawBlast_Char[32] = {
0x60, 0xff, 0xff, 0xff, 0x62, 0x62, 0x62, 0x62, 0x64, 0x64, 0x64, 0x64, 0x66, 0x66, 0x66, 0x66,
0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x6a, 0x6a, 0x6a, 0x6a, 0x4e, 0x4e, 0x4e, 0x4e,
};
uint16 x = bombos_x_coord[k];
uint16 y = bombos_y_coord[k];
if (bombos_arr3[k] == 8)
return;
Ancilla_AllocateOamFromRegion_A_or_D_or_F(k, 0x10);
OamEnt *oam = GetOamCurPtr();
int t = bombos_arr3[k] * 4 + 3;
for (int j = 0; j < 4; j++, t--) {
if (kBombosSpell_DrawBlast_Char[t] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam,
x + kBombosSpell_DrawBlast_X[t] - BG2HOFS_copy2,
y + kBombosSpell_DrawBlast_Y[t] - BG2VOFS_copy2);
oam->charnum = kBombosSpell_DrawBlast_Char[t];
oam->flags = kBombosSpell_DrawBlast_Flags[t];
bytewise_extended_oam[oam - oam_buf] = ext | 2;
oam++;
}
oam = Ancilla_AllocateOamFromCustomRegion(oam);
}
}
void Ancilla1C_QuakeSpell(int k) { // 88b66a
if (submodule_index != 0) {
if (quake_arr2[4] != kQuake_Tab1[4])
AncillaDraw_QuakeInitialBolts(k);
return;
}
if (ancilla_step[k] != 2) {
QuakeSpell_ShakeScreen(k);
QuakeSpell_ControlBolts(k);
QuakeSpell_SpreadBolts(k);
return;
}
Medallion_CheckSpriteDamage(k);
Prepare_ApplyRumbleToSprites();
ancilla_type[k] = 0;
link_player_handler_state = 0;
load_chr_halfslot_even_odd = 1;
byte_7E0324 = 0;
state_for_spin_attack = 0;
step_counter_for_spin_attack = 0;
link_cant_change_direction = 0;
link_delay_timer_spin_attack = 0;
flag_unk1 = 0;
bg1_x_offset = 0;
bg1_y_offset = 0;
if (BYTE(overworld_screen_index) == 0x47 && !(save_ow_event_info[0x47] & 0x20) && Ancilla_CheckForEntranceTrigger(3)) {
trigger_special_entrance = 4;
subsubmodule_index = 0;
BYTE(R16) = 0;
}
button_mask_b_y = button_b_frames ? (joypad1H_last & 0x80) : 0;
link_speed_setting = 0;
byte_7E0325 = 0;
}
void QuakeSpell_ShakeScreen(int k) { // 88b6f7
bg1_y_offset = quake_var3;
quake_var3 = -quake_var3;
link_y_vel += bg1_y_offset;
}
void QuakeSpell_ControlBolts(int k) { // 88b718
quake_var4 = ancilla_step[k];
int j = quake_var5;
do {
if (quake_arr2[j] == kQuake_Tab1[j])
continue;
if (sign8(--quake_arr1[j])) {
quake_arr1[j] = 1;
if (++quake_arr2[j] == kQuake_Tab1[j])
continue;
if (j == 0 && quake_arr2[j] == 2) {
Ancilla_Sfx2_Near(0xc);
quake_var5 = 1;
} else if (j == 1 && quake_arr2[j] == 2) {
quake_var5 = 4;
} else if (j == 4 && quake_arr2[j] == 7) {
quake_var4 = 1;
}
}
AncillaDraw_QuakeInitialBolts(j);
} while (--j >= 0);
ancilla_step[k] = quake_var4;
}
void AncillaDraw_QuakeInitialBolts(int k) { // 88b793
static const uint8 kQuakeDrawGroundBolts_Tab[5] = {0, 0x18, 0, 0x18, 0x2f};
int t = quake_arr2[k] + kQuakeDrawGroundBolts_Tab[k];
OamEnt *oam = GetOamCurPtr();
int idx = kQuakeItemPos[t], num = kQuakeItemPos[t + 1] - idx;
const QuakeItem *p = &kQuakeItems[idx], *pend = p + num;
do {
uint16 x = p->x + quake_var2 - BG2HOFS_copy2;
uint16 y = p->y + quake_var1 - BG2VOFS_copy2;
uint8 yval = 0xf0;
if (x < 256 && y < 256) {
oam->x = x;
if (y < 0xf0)
yval = y;
}
oam->y = yval;
oam->charnum = kQuakeDrawGroundBolts_Char[p->f & 0x0f];
oam->flags = p->f & 0xc0 | 0x3c;
bytewise_extended_oam[oam - oam_buf] = 2;
oam++;
oam_cur_ptr += 4, oam_ext_cur_ptr += 1;
} while (++p != pend);
}
void QuakeSpell_SpreadBolts(int k) { // 88b84f
if (ancilla_step[k] != 1)
return;
if (ancilla_timer[k] == 0) {
ancilla_timer[k] = 2;
if (++ancilla_item_to_link[k] == 55) {
ancilla_step[k] = 2;
return;
}
}
int t = ancilla_item_to_link[k];
int idx = kQuakeItemPos2[t], num = kQuakeItemPos2[t + 1] - idx;
const QuakeItem *p = &kQuakeItems2[idx], *pend = p + num;
OamEnt *oam = GetOamCurPtr();
do {
oam->x = p->x;
oam->y = p->y;
oam->charnum = kQuakeDrawGroundBolts_Char[p->f & 0x0f];
oam->flags = p->f & 0xc0 | 0x3c;
bytewise_extended_oam[oam - oam_buf] = p->f >> 4 & 3;
oam_cur_ptr += 4, oam_ext_cur_ptr += 1;
oam = Ancilla_AllocateOamFromCustomRegion(oam + 1);
} while (++p != pend);
}
void Ancilla1A_PowderDust(int k) { // 88bab0
if (submodule_index == 0) {
Powder_ApplyDamageToSprites(k);
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 1;
int j = ancilla_dir[k];
if (ancilla_item_to_link[k] == 9) {
ancilla_type[k] = 0;
byte_7E0333 = 0;
return;
}
ancilla_arr25[k] = kMagicPowder_Tab0[++ancilla_item_to_link[k] + j * 10];
}
}
Ancilla_AllocateOamFromRegion_B_or_E(ancilla_numspr[k]);
Ancilla_MagicPowder_Draw(k);
}
void Ancilla_MagicPowder_Draw(int k) { // 88baeb
static const int8 kMagicPowder_DrawX[76] = {
-5, -12, 2, -9, -7, -10, -6, -2, -6, -12, 1, -6, -6, -12, 1, -6,
-6, -12, 1, -6, -6, -12, 1, -6, -6, -12, 1, -6, -17, -23, -14, -19,
-11, -18, -9, -13, -4, -13, -1, -8, -3, -9, 0, -5, -3, -10, -1, -5,
-4, -13, -1, -8, -3, -9, 0, -5, -3, -10, -1, -5, -3, -13, -1, -8,
9, 15, 6, 11, 3, 10, 1, 5, -4, 5, -7, 0,
};
static const int8 kMagicPowder_DrawY[76] = {
-20, -15, -13, -7, -18, -13, -13, -13, -20, -13, -13, -8, -20, -13, -13, -8,
-19, -12, -12, -7, -18, -11, -11, -6, -17, -10, -10, -5, -16, -14, -12, -9,
-17, -14, -12, -8, -18, -14, -13, -6, -33, -31, -29, -26, -28, -25, -23, -19,
-22, -18, -17, -10, -2, 0, 2, 5, -9, -6, -4, 0, -16, -12, -11, -4,
-16, -14, -12, -9, -17, -14, -12, -8, -18, -14, -13, -6,
};
static const uint8 kMagicPowder_Draw_Char[19] = {
9, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
};
static const uint8 kMagicPowder_Draw_Flags[76] = {
0x68, 0x24, 0xa2, 0x28, 0x68, 0xe2, 0x28, 0xa4, 0x68, 0xe2, 0xa4, 0x28, 0x22, 0xa4, 0xe8, 0x62,
0x24, 0xa8, 0xe2, 0x64, 0x28, 0xa2, 0xe4, 0x68, 0x22, 0xa4, 0xe8, 0x62, 0xe2, 0xa4, 0xe8, 0x64,
0xe8, 0xa8, 0xe4, 0x62, 0xe4, 0xa8, 0xe2, 0x68, 0xe2, 0xa4, 0xe8, 0x64, 0xe8, 0xa8, 0xe4, 0x62,
0xe4, 0xa8, 0xe2, 0x68, 0xe2, 0xa4, 0xe8, 0x64, 0xe8, 0xa8, 0xe4, 0x62, 0xe4, 0xa8, 0xe2, 0x68,
0xe2, 0xa4, 0xe8, 0x64, 0xe8, 0xa8, 0xe4, 0x62, 0xe4, 0xa8, 0xe2, 0x68,
};
Point16U info;
Ancilla_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
int b = ancilla_arr25[k];
for (int i = 0; i < 4; i++, oam++) {
uint8 ext = Ancilla_SetOam_XY(oam, info.x + kMagicPowder_DrawX[b * 4 + i], info.y + kMagicPowder_DrawY[b * 4 + i]);
oam->charnum = kMagicPowder_Draw_Char[b];
oam->flags = kMagicPowder_Draw_Flags[b * 4 + i] & ~0x30 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
}
}
void Powder_ApplyDamageToSprites(int k) { // 88bb58
uint8 a;
for (int j = 15; j >= 0; j--) {
if ((frame_counter ^ j) & 3 || sprite_state[j] != 9 || sprite_bump_damage[j] & 0x20)
continue;
SpriteHitBox hb;
Ancilla_SetupBasicHitBox(k, &hb);
Sprite_SetupHitBox(j, &hb);
if (!CheckIfHitBoxesOverlap(&hb))
continue;
if ((a = sprite_type[j]) != 0xb || (a = player_is_indoors) == 0 || (a = dungeon_room_index2 - 1) != 0) {
if (a != 0xd) {
Ancilla_CheckDamageToSprite_preset(j, 10);
continue;
}
if (sprite_head_dir[j] != 0)
continue;
}
sprite_head_dir[j] = 1;
Sprite_SpawnPoofGarnish(j);
}
}
void Ancilla1D_ScreenShake(int k) { // 88bbbc
if (submodule_index == 0) {
if (sign8(--ancilla_item_to_link[k])) {
bg1_x_offset = 0;
bg1_y_offset = 0;
ancilla_type[k] = 0;
return;
}
int offs = DashTremor_TwiddleOffset(k);
int j = ancilla_dir[k];
if (j == 0) {
bg1_x_offset = offs;
link_x_vel += offs;
} else {
bg1_y_offset = offs;
link_y_vel += offs;
}
}
sprite_alert_flag = 3;
}
void Ancilla1E_DashDust(int k) { // 88bc92
if (ancilla_step[k]) {
DashDust_Motive(k);
return;
}
if (!ancilla_timer[k]) {
ancilla_timer[k] = 3;
if (++ancilla_item_to_link[k] == 5)
return;
if (ancilla_item_to_link[k] == 6) {
ancilla_type[k] = 0;
return;
}
}
if (ancilla_item_to_link[k] == 5)
return;
Point16U info;
Ancilla_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
static const int8 kDashDust_Draw_X1[4] = {0, 0, 4, -4};
static const int16 kDashDust_Draw_X[30] = {
10, 5, -1, 0, 10, 5, 0, 5, -1, 0, -1, -1, 9, -1, -1, 10,
5, -1, 0, 10, 5, 0, 5, -1, 0, -1, -1, 9, -1, -1,
};
static const int16 kDashDust_Draw_Y[30] = {
-2, 0, -1, -3, -2, 0, -3, 0, -1, -3, -1, -1, -2, -1, -1, -2,
0, -1, -3, -2, 0, -3, 0, -1, -3, -1, -1, -2, -1, -1,
};
static const uint8 kDashDust_Draw_Char[30] = {
0xcf, 0xa9, 0xff, 0xa9, 0xdf, 0xcf, 0xcf, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xa9, 0xff, 0xff, 0xcf,
0xcf, 0xff, 0xcf, 0xdf, 0xcf, 0xcf, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xcf, 0xff, 0xff,
};
int r12 = kDashDust_Draw_X1[link_direction_facing >> 1];
int t = 3 * (ancilla_item_to_link[k] + (draw_water_ripples_or_grass == 1 ? 5 : 0));
for (int n = 2; n >= 0; n--, t++) {
if (kDashDust_Draw_Char[t] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam, info.x + r12 + kDashDust_Draw_X[t], info.y + kDashDust_Draw_Y[t]);
oam->charnum = kDashDust_Draw_Char[t];
oam->flags = 4 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
}
}
void Ancilla1F_Hookshot(int k) { // 88bd74
if (submodule_index != 0)
goto do_draw;
if (!ancilla_timer[k]) {
ancilla_timer[k] = 7;
Ancilla_Sfx2_Pan(k, 0xa);
}
if (related_to_hookshot)
goto do_draw;
Ancilla_MoveY(k);
Ancilla_MoveX(k);
if (ancilla_step[k]) {
if (sign8(--ancilla_item_to_link[k])) {
ancilla_type[k] = 0;
return;
}
goto do_draw;
}
if (++ancilla_item_to_link[k] == 32) {
ancilla_step[k] = 1;
ancilla_x_vel[k] = -ancilla_x_vel[k];
ancilla_y_vel[k] = -ancilla_y_vel[k];
}
if (Hookshot_ShouldIEvenBotherWithTiles(k))
goto do_draw;
if (!ancilla_L[k] && !ancilla_step[k] && Ancilla_CheckSpriteCollision(k) >= 0 && !ancilla_step[k]) {
ancilla_step[k] = 1;
ancilla_y_vel[k] = -ancilla_y_vel[k];
ancilla_x_vel[k] = -ancilla_x_vel[k];
}
Hookshot_CheckTileCollision(k);
uint8 r0;
r0 = 0;
if (player_is_indoors) {
if (!(ancilla_dir[k] & 2)) {
r0 = (tiledetect_vertical_ledge | (tiledetect_vertical_ledge >> 4)) & 3;
} else {
r0 = detection_of_ledge_tiles_horiz_uphoriz & 3;
}
if (r0 == 0)
goto endif_7;
} else {
if (!((detection_of_ledge_tiles_horiz_uphoriz & 3 | tiledetect_vertical_ledge | detection_of_unknown_tile_types) & 0x33))
goto endif_7;
}
if (sign8(--ancilla_G[k])) {
if (ancilla_K[k] && ((r0 & 3) || ancilla_K[k] != BYTE(index_of_interacting_tile))) {
ancilla_G[k] = 2;
if (sign8(--ancilla_L[k]))
ancilla_L[k] = 0;
} else {
ancilla_L[k]++;
ancilla_K[k] = index_of_interacting_tile;
ancilla_G[k] = 1;
}
}
endif_7:
if (ancilla_L[k])
goto do_draw;
if (!sign8(ancilla_G[k])) {
ancilla_G[k]--;
goto do_draw;
}
if ((R14 >> 4 | R14 | tiledetect_stair_tile | R12) & 3 && !ancilla_step[k]) {
ancilla_step[k] = 1;
ancilla_y_vel[k] = -ancilla_y_vel[k];
ancilla_x_vel[k] = -ancilla_x_vel[k];
if (!(tiledetect_misc_tiles & 3)) {
AncillaAdd_HookshotWallClink(k, 6, 1);
Ancilla_Sfx2_Pan(k, (tiledetect_misc_tiles & 0x30) ? 6 : 5);
}
}
if (tiledetect_misc_tiles & 3) {
if (ancilla_item_to_link[k] < 4) {
ancilla_type[k] = 0;
return;
}
related_to_hookshot = 1;
hookshot_effect_index = k;
}
static const int8 kHookShot_Move_X[4] = {0, 0, 8, -8};
static const int8 kHookShot_Move_Y[4] = {8, -9, 0, 0};
static const uint8 kHookShot_Draw_Flags[12] = {0, 0, 0xff, 0x80, 0x80, 0xff, 0x40, 0xff, 0x40, 0, 0xff, 0};
static const uint8 kHookShot_Draw_Char[12] = {9, 0xa, 0xff, 9, 0xa, 0xff, 9, 0xff, 0xa, 9, 0xff, 0xa};
Point16U info;
do_draw:
Ancilla_PrepOamCoord(k, &info);
if (ancilla_L[k])
oam_priority_value = 0x3000;
OamEnt *oam = GetOamCurPtr();
int j = ancilla_dir[k] * 3;
int x = info.x, y = info.y;
for (int i = 2; i >= 0; i--, j++) {
if (kHookShot_Draw_Char[j] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = kHookShot_Draw_Char[j];
oam->flags = kHookShot_Draw_Flags[j] | 2 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
if (i == 1)
x -= 8, y += 8;
else
x += 8;
}
int r10 = 0;
int n = ancilla_item_to_link[k] >> 1;
if (n >= 7) {
r10 = n - 7;
n = 6;
}
if (n == 0)
return;
if (ancilla_dir[k] & 1)
r10 = -r10;
x = info.x, y = info.y;
j = ancilla_dir[k];
if (kHookShot_Move_Y[j] == 0)
y += 4;
if (kHookShot_Move_X[j] == 0)
x += 4;
do {
if (kHookShot_Move_Y[j])
y += kHookShot_Move_Y[j] + r10;
if (kHookShot_Move_X[j])
x += kHookShot_Move_X[j] + r10;
if (!Hookshot_CheckProximityToLink(x, y)) {
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = 0x19;
oam->flags = (frame_counter & 2) << 6 | 2 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
} while (--n >= 0);
}
void Ancilla20_Blanket(int k) { // 88c013
static const uint8 kBedSpread_Char[8] = {0xa, 0xa, 0xa, 0xa, 0xc, 0xc, 0xa, 0xa};
static const uint8 kBedSpread_Flags[8] = {0, 0x60, 0xa0, 0xe0, 0, 0x60, 0xa0, 0xe0};
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
if (!link_pose_during_opening) {
Oam_AllocateFromRegionB(0x10);
} else {
Oam_AllocateFromRegionA(0x10);
}
OamEnt *oam = GetOamCurPtr();
int j = link_pose_during_opening ? 4 : 0;
uint16 x = pt.x, y = pt.y;
for (int i = 3; i >= 0; i--, j++, oam++) {
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = kBedSpread_Char[j];
oam->flags = kBedSpread_Flags[j] | 0xd | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext | 2;
x += 16;
if (i == 2)
x -= 32, y += 8;
}
}
void Ancilla21_Snore(int k) { // 88c094
static const uint8 kBedSpread_Dma[3] = {0x44, 0x43, 0x42};
if (sign8(--ancilla_aux_timer[k])) {
if (ancilla_item_to_link[k] != 2)
ancilla_item_to_link[k]++;
ancilla_aux_timer[k] = 7;
}
ancilla_x_vel[k] += ancilla_step[k];
if (abs8(ancilla_x_vel[k]) >= 8)
ancilla_step[k] = -ancilla_step[k];
Ancilla_MoveY(k);
Ancilla_MoveX(k);
if (Ancilla_GetY(k) <= (uint16)(link_y_coord - 24))
ancilla_type[k] = 0;
link_dma_var5 = kBedSpread_Dma[ancilla_item_to_link[k]];
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y);
oam->charnum = 9;
oam->flags = 0x24;
bytewise_extended_oam[oam - oam_buf] = ext;
}
void Ancilla3B_SwordUpSparkle(int k) { // 88c167
static const int8 kAncilla_VictorySparkle_X[16] = {16, 0, 0, 0, 8, 16, 8, 16, 9, 15, 0, 0, 12, 0, 0, 0};
static const int8 kAncilla_VictorySparkle_Y[16] = {-7, 0, 0, 0, -11, -11, -3, -3, -7, -7, 0, 0, -7, 0, 0, 0};
static const uint8 kAncilla_VictorySparkle_Char[16] = {0x92, 0xff, 0xff, 0xff, 0x93, 0x93, 0x93, 0x93, 0xf9, 0xf9, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff};
static const uint8 kAncilla_VictorySparkle_Flags[16] = {0, 0xff, 0xff, 0xff, 0, 0x40, 0x80, 0xc0, 0, 0x40, 0xff, 0xff, 0, 0xff, 0xff, 0xff};
if (ancilla_aux_timer[k]) {
ancilla_aux_timer[k]--;
return;
}
if (sign8(--ancilla_arr3[k])) {
ancilla_arr3[k] = 1;
if (++ancilla_item_to_link[k] == 4) {
ancilla_type[k] = 0;
ancilla_aux_timer[k]--;
return;
}
}
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
int j = ancilla_item_to_link[k] * 4;
for (int i = 0; i < 4; i++, j++) {
if (kAncilla_VictorySparkle_Char[j] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam,
link_x_coord + kAncilla_VictorySparkle_X[j] - BG2HOFS_copy2,
link_y_coord + kAncilla_VictorySparkle_Y[j] - BG2VOFS_copy2);
oam->charnum = kAncilla_VictorySparkle_Char[j];
oam->flags = kAncilla_VictorySparkle_Flags[j] | 4 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
}
}
void Ancilla3C_SpinAttackChargeSparkle(int k) { // 88c1ea
static const uint8 kSwordChargeSpark_Char[3] = {0xb7, 0x80, 0x83};
static const uint8 kSwordChargeSpark_Flags[3] = {4, 4, 0x84};
if (!submodule_index && !ancilla_timer[k]) {
ancilla_timer[k] = 4;
if (++ancilla_item_to_link[k] == 3) {
ancilla_type[k] = 0;
return;
}
}
ancilla_oam_idx[k] = Ancilla_AllocateOamFromRegion_A_or_D_or_F(k, 4);
Point16U info;
Ancilla_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
uint8 ext = Ancilla_SetOam_XY(oam, info.x, info.y);
int j = ancilla_item_to_link[k];
oam->charnum = kSwordChargeSpark_Char[j];
oam->flags = kSwordChargeSpark_Flags[j] | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
}
void Ancilla35_MasterSwordReceipt(int k) { // 88c25f
static const int8 kSwordCeremony_X[8] = {-1, 8, -1, 8, 0, 7, 0, 7};
static const int8 kSwordCeremony_Y[8] = {1, 1, 9, 9, 1, 1, 9, 9};
static const uint8 kSwordCeremony_Char[8] = {0x86, 0x86, 0x96, 0x96, 0x87, 0x87, 0x97, 0x97};
static const uint8 kSwordCeremony_Flags[8] = {1, 0x41, 1, 0x41, 1, 0x41, 1, 0x41};
if (!ancilla_timer[k]) {
ancilla_type[k] = 0;
return;
}
if (sign8(--ancilla_aux_timer[k])) {
ancilla_item_to_link[k] = (ancilla_item_to_link[k] == 2) ? 0 : ancilla_item_to_link[k] + 1;
}
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
int j = (ancilla_item_to_link[k] - 1) * 4;
if (j < 0)
return;
for (int i = 0; i < 4; i++, j++, oam++) {
uint8 ext = Ancilla_SetOam_XY(oam, pt.x + kSwordCeremony_X[j], pt.y + kSwordCeremony_Y[j]);
oam->charnum = kSwordCeremony_Char[j];
oam->flags = kSwordCeremony_Flags[j] & ~0x30 | 4 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
}
}
void Ancilla22_ItemReceipt(int k) { // 88c38a
uint8 a;
if (flag_is_link_immobilized == 2)
goto endif_1;
if (submodule_index != 0 && submodule_index != 43 && submodule_index != 9) {
if (submodule_index == 2)
ancilla_timer[k] = 16;
goto endif_1;
}
flag_unk1++;
if (ancilla_step[k] != 0 && ancilla_step[k] != 3) {
if (sign8(--ancilla_aux_timer[k]))
goto endif_11;
if (ancilla_aux_timer[k] == 0)
goto endif_6;
if (ancilla_aux_timer[k] == 40 && ancilla_step[k] != 2) {
if (Ancilla_AddRupees(k) || ancilla_item_to_link[k] != 0x17)
Ancilla_Sfx3_Near(0xf);
}
goto label_b;
}
if (ancilla_item_to_link[k] == 1 && ancilla_step[k] != 2) {
if (ancilla_timer[k] == 0)
goto label_a;
if (ancilla_timer[k] != 17)
goto endif_1;
word_7E02CD = 0xDF3;
follower_indicator = 0xe;
goto endif_6;
}
a = --ancilla_aux_timer[k];
if (a == 0)
goto label_a;
if (a == 1) {
if (ancilla_item_to_link[k] != 0x37 && ancilla_item_to_link[k] != 0x38 && ancilla_item_to_link[k] != 0x39 || zelda_read_apui00() == 0)
goto endif_6;
ancilla_aux_timer[k]++;
}
goto endif_1;
label_a:
if (ancilla_item_to_link[k] == 1 && !ancilla_step[k]) {
sound_effect_ambient = 5;
music_control = 2;
}
link_player_handler_state = link_is_in_deep_water ? kPlayerState_Swimming : 0;
link_receiveitem_index = 0;
link_pose_for_item = 0;
link_disable_sprite_damage = 0;
Ancilla_AddRupees(k);
endif_11:
item_receipt_method = 0;
a = ancilla_item_to_link[k];
if (a == 23 && link_heart_pieces == 0) {
Link_ReceiveItem(0x26, 0);
ancilla_type[k] = 0;
flag_unk1 = 0;
return;
}
if (a == 0x26 || a == 0x3f) {
if (link_health_capacity != 0xa0) {
link_health_capacity += 8;
link_hearts_filler += link_health_capacity - link_health_current;
Ancilla_Sfx3_Near(0xd);
}
} else if (a == 0x3e) {
flag_is_link_immobilized = 0;
if (link_health_capacity != 0xa0) {
link_health_capacity += 8;
link_hearts_filler += 8;
Ancilla_Sfx3_Near(0xd);
}
} else if (a == 0x42) {
link_hearts_filler += 8;
} else if (a == 0x45) {
link_magic_filler += 16;
} else if (a == 0x22 || a == 0x23) {
Palette_Load_LinkArmorAndGloves();
}
ancilla_type[k] = 0;
flag_unk1 = 0;
a = ancilla_item_to_link[k];
if (ancilla_step[k] == 3 && a != 0x10 && a != 0x26 && a != 0xf && a != 0x20) {
PrepareDungeonExitFromBossFight();
}
if (ancilla_step[k] != 2)
flag_is_link_immobilized = 0;
return;
endif_6:
if (player_is_indoors) {
int room = dungeon_room_index;
if (room == 0xff || room == 0x10f || room == 0x110 || room == 0x112 || room == 0x11f)
goto label_b;
}
int msg;
msg = -1;
if (ancilla_item_to_link[k] == 0x38 || ancilla_item_to_link[k] == 0x39) {
if ((link_which_pendants & 7) == 7)
msg = kReceiveItemMsgs2[ancilla_item_to_link[k] - 0x38];
else
msg = kReceiveItemMsgs[ancilla_item_to_link[k]];
} else if (ancilla_step[k] != 2) {
if (ancilla_item_to_link[k] == 0x17)
msg = kReceiveItemMsgs3[link_heart_pieces];
else
msg = kReceiveItemMsgs[ancilla_item_to_link[k]];
}
if (msg != -1) {
dialogue_message_index = msg;
if (msg == 0x70)
sound_effect_ambient = 9;
Main_ShowTextMessage();
}
goto endif_1;
label_b:
if (ancilla_aux_timer[k] >= 24) {
a = ancilla_y_vel[k] - 1;
if (a >= 248)
ancilla_y_vel[k] = a;
Ancilla_MoveY(k);
}
endif_1:
if (ancilla_item_to_link[k] == 0x20) {
ancilla_z[k] = 0;
AncillaAdd_OccasionalSparkle(k);
if (zelda_read_apui00() == 0) {
music_control = 0x1a;
ItemReceipt_TransmuteToRisingCrystal(k);
return;
}
} else if (ancilla_item_to_link[k] == 0x1) {
ancilla_arr4[k] = kReceiveItem_Tab0[0];
if (ancilla_step[k] != 2) {
if (ancilla_timer[k] < 16) {
a = 0;
} else {
if (!sign8(--ancilla_arr3[k]))
goto skipit;
ancilla_arr3[k] = 2;
a = ancilla_arr1[k] + 1;
if (a == 3)
a = 0;
}
ancilla_arr1[k] = a;
ancilla_arr4[k] = kReceiveItem_Tab0[a];
skipit:;
}
}
if ((ancilla_item_to_link[k] == 0x34 || ancilla_item_to_link[k] == 0x35 || ancilla_item_to_link[k] == 0x36) && sign8(--ancilla_arr3[k])) {
a = ancilla_arr1[k] + 1;
if (a == 3)
a = 0;
ancilla_arr1[k] = a;
ancilla_arr3[k] = kReceiveItem_Tab4[a];
WriteTo4BPPBuffer_at_7F4000(kReceiveItem_Tab5[a]);
}
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
Ancilla_ReceiveItem_Draw(k, pt.x, pt.y);
}
OamEnt *Ancilla_ReceiveItem_Draw(int k, int x, int y) { // 88c690
OamEnt *oam = GetOamCurPtr();
int j = ancilla_item_to_link[k];
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = 0x24;
uint8 a = kWishPond2_OamFlags[j];
if (sign8(a))
a = ancilla_arr4[k];
oam->flags = a * 2 | 0x30;
ext |= kReceiveItem_Tab1[j];
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
if (ext == 0) {
ext = Ancilla_SetOam_XY(oam, x, y + 8);
oam->charnum = 0x34;
oam->flags = a * 2 | 0x30;
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
return oam;
}
void Ancilla28_WishPondItem(int k) { // 88c6f2
Ancilla_AllocateOamFromRegion_A_or_D_or_F(k, 0x10);
if (submodule_index == 0 && ancilla_timer[k] == 0) {
link_picking_throw_state = 2;
link_state_bits = 0;
ancilla_z_vel[k] -= 2;
Ancilla_MoveZ(k);
Ancilla_MoveY(k);
Ancilla_MoveX(k);
if (sign8(ancilla_z[k]) && ancilla_z[k] < 228) {
ancilla_z[k] = 228;
Ancilla_SetXY(k,
Ancilla_GetX(k) + (kGeneratedWishPondItem[ancilla_item_to_link[k]] ? 8 : 4), // wtf
Ancilla_GetY(k) + 18);
Ancilla_TransmuteToSplash(k);
return;
}
}
WishPondItem_Draw(k);
}
void WishPondItem_Draw(int k) { // 88c760
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
if (ancilla_item_to_link[k] == 1)
ancilla_arr4[k] = 5;
OamEnt *oam = Ancilla_ReceiveItem_Draw(k, pt.x, pt.y - (int8)ancilla_z[k]);
if (link_picking_throw_state != 2 || !sign8(ancilla_z_vel[k]) && ancilla_z_vel[k] >= 2)
return;
uint8 xx = kGeneratedWishPondItem[ancilla_item_to_link[k]];
AncillaDraw_Shadow(oam,
(xx == 2) ? 1 : 2,
pt.x - (xx == 2 ? 0 : 4),
pt.y + 40, HIBYTE(oam_priority_value));
}
void Ancilla42_HappinessPondRupees(int k) { // 88c7de
link_picking_throw_state = 2;
link_state_bits = 0;
for (int i = 9; i >= 0; i--) {
if (happiness_pond_arr1[i]) {
HapinessPondRupees_ExecuteRupee(k, i);
if (happiness_pond_step[i] == 2)
happiness_pond_arr1[i] = 0;
}
}
for (int i = 9; i >= 0; i--) {
if (happiness_pond_arr1[i])
return;
}
ancilla_type[k] = 0;
}
void HapinessPondRupees_ExecuteRupee(int k, int i) { // 88c819
Ancilla_AllocateOamFromRegion_A_or_D_or_F(k, 0x10);
HapinessPondRupees_GetState(k, i);
if (ancilla_step[k]) {
if (!submodule_index && !ancilla_timer[k]) {
ancilla_timer[k] = 6;
if (++ancilla_item_to_link[k] == 5) {
ancilla_step[k]++;
} else {
ObjectSplash_Draw(k);
}
} else {
ObjectSplash_Draw(k);
}
} else if (submodule_index == 0 && ancilla_timer[k] == 0) {
ancilla_z_vel[k] -= 2;
Ancilla_MoveY(k);
Ancilla_MoveX(k);
Ancilla_MoveZ(k);
if (!sign8(ancilla_z[k]) || ancilla_z[k] >= 0xe4)
goto else_label;
ancilla_z[k] = 0xe4;
Ancilla_SetXY(k, Ancilla_GetX(k) - 4, Ancilla_GetY(k) + 30);
ancilla_item_to_link[k] = 0;
ancilla_timer[k] = 6;
Ancilla_Sfx2_Pan(k, 0x28);
ancilla_step[k]++;
ObjectSplash_Draw(k);
} else {
else_label:
ancilla_arr4[k] = 2;
ancilla_floor[k] = 0;
WishPondItem_Draw(k);
}
HapinessPondRupees_SaveState(i, k);
}
void HapinessPondRupees_GetState(int j, int k) { // 88c8be
ancilla_y_lo[j] = happiness_pond_y_lo[k];
ancilla_y_hi[j] = happiness_pond_y_hi[k];
ancilla_x_lo[j] = happiness_pond_x_lo[k];
ancilla_x_hi[j] = happiness_pond_x_hi[k];
ancilla_z[j] = happiness_pond_z[k];
ancilla_y_vel[j] = happiness_pond_y_vel[k];
ancilla_x_vel[j] = happiness_pond_x_vel[k];
ancilla_z_vel[j] = happiness_pond_z_vel[k];
ancilla_y_subpixel[j] = happiness_pond_y_subpixel[k];
ancilla_x_subpixel[j] = happiness_pond_x_subpixel[k];
ancilla_z_subpixel[j] = happiness_pond_z_subpixel[k];
ancilla_item_to_link[j] = happiness_pond_item_to_link[k];
ancilla_step[j] = happiness_pond_step[k];
ancilla_timer[j] = happiness_pond_timer[k] ? happiness_pond_timer[k] - 1 : 0;
}
void HapinessPondRupees_SaveState(int k, int j) { // 88c924
happiness_pond_y_lo[k] = ancilla_y_lo[j];
happiness_pond_y_hi[k] = ancilla_y_hi[j];
happiness_pond_x_lo[k] = ancilla_x_lo[j];
happiness_pond_x_hi[k] = ancilla_x_hi[j];
happiness_pond_z[k] = ancilla_z[j];
happiness_pond_y_vel[k] = ancilla_y_vel[j];
happiness_pond_x_vel[k] = ancilla_x_vel[j];
happiness_pond_z_vel[k] = ancilla_z_vel[j];
happiness_pond_y_subpixel[k] = ancilla_y_subpixel[j];
happiness_pond_x_subpixel[k] = ancilla_x_subpixel[j];
happiness_pond_z_subpixel[k] = ancilla_z_subpixel[j];
happiness_pond_item_to_link[k] = ancilla_item_to_link[j];
happiness_pond_timer[k] = ancilla_timer[j];
happiness_pond_step[k] = ancilla_step[j];
}
void Ancilla_TransmuteToSplash(int k) { // 88c9cd
ancilla_type[k] = 0x3d;
ancilla_item_to_link[k] = 0;
ancilla_timer[k] = 6;
Ancilla_SetXY(k, Ancilla_GetX(k) - 8, Ancilla_GetY(k) + 12);
Ancilla_Sfx2_Pan(k, 0x28);
Ancilla3D_ItemSplash(k);
}
void Ancilla3D_ItemSplash(int k) { // 88ca01
Ancilla_AllocateOamFromRegion_A_or_D_or_F(k, 8);
if (!submodule_index && !ancilla_timer[k]) {
ancilla_timer[k] = 6;
if (++ancilla_item_to_link[k] == 5) {
ancilla_type[k] = 0;
return;
}
}
ObjectSplash_Draw(k);
}
void ObjectSplash_Draw(int k) { // 88ca22
static const int8 kObjectSplash_Draw_X[10] = {0, 0, 0, 0, 11, -3, 15, -7, 15, -7};
static const int8 kObjectSplash_Draw_Y[10] = {0, 0, -6, 0, -13, -8, -17, -4, -17, -4};
static const uint8 kObjectSplash_Draw_Char[10] = {0xc0, 0xff, 0xe7, 0xff, 0xaf, 0xbf, 0x80, 0x80, 0x83, 0x83};
static const uint8 kObjectSplash_Draw_Flags[10] = {0, 0xff, 0, 0xff, 0x40, 0, 0x40, 0, 0xc0, 0x80};
static const uint8 kObjectSplash_Draw_Ext[10] = {2, 0, 2, 0, 0, 0, 0, 0, 0, 0};
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
int j = ancilla_item_to_link[k] * 2;
for (int i = 0; i != 2; i++, j++) {
if (kObjectSplash_Draw_Char[j] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam, pt.x + kObjectSplash_Draw_X[j], pt.y + kObjectSplash_Draw_Y[j]);
oam->charnum = kObjectSplash_Draw_Char[j];
oam->flags = kObjectSplash_Draw_Flags[j] | 0x24;
bytewise_extended_oam[oam - oam_buf] = ext | kObjectSplash_Draw_Ext[j];
oam++;
}
}
}
void Ancilla29_MilestoneItemReceipt(int k) { // 88ca8c
if (ancilla_item_to_link[k] != 0x10 && ancilla_item_to_link[k] != 0x0f) {
if (dung_savegame_state_bits & 0x4000) {
ancilla_type[k] = 0;
return;
}
if (!(dung_savegame_state_bits & 0x8000))
return;
if (byte_7E04C2 != 0) {
if (byte_7E04C2 == 1) {
if (ancilla_item_to_link[k] == 0x20) {
sound_effect_ambient = 0x0f;
DecodeAnimatedSpriteTile_variable(0x28);
} else {
DecodeAnimatedSpriteTile_variable(0x23);
}
}
byte_7E04C2--;
return;
}
if (!ancilla_arr3[k] && ancilla_item_to_link[k] == 0x20) {
ancilla_arr3[k] = 1;
palette_sp6 = 4;
overworld_palette_aux_or_main = 0x200;
Palette_Load_SpriteEnvironment_Dungeon();
flag_update_cgram_in_nmi++;
}
} else {
if (ancilla_G[k]) {
ancilla_G[k]--;
return;
}
}
if (ancilla_item_to_link[k] == 0x20)
AncillaAdd_OccasionalSparkle(k);
if (submodule_index == 0) {
CheckPlayerCollOut coll_out;
if (ancilla_z[k] < 24 && Ancilla_CheckLinkCollision(k, 2, &coll_out) && related_to_hookshot == 0 && link_auxiliary_state == 0) {
ancilla_type[k] = 0;
if (link_player_handler_state == kPlayerState_ReceivingEther || link_player_handler_state == kPlayerState_ReceivingBombos) {
flag_custom_spell_anim_active = 0;
link_force_hold_sword_up = 0;
link_player_handler_state = 0;
}
item_receipt_method = 3;
Link_ReceiveItem(ancilla_item_to_link[k], 0);
return;
}
if (ancilla_step[k] != 2) {
if (ancilla_step[k] != 0) {
ancilla_z_vel[k]--;
}
Ancilla_MoveZ(k);
if (ancilla_z[k] >= 0xf8) {
ancilla_step[k]++;
ancilla_z_vel[k] = 0x18;
ancilla_z[k] = 0;
}
}
}
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
OamEnt *oam = Ancilla_ReceiveItem_Draw(k, pt.x, pt.y - ancilla_z[k]);
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 9;
if (++ancilla_L[k] == 3)
ancilla_L[k] = 0;
}
int t;
if (ancilla_z[k] == 0) {
t = (dungeon_room_index == 6) ? ancilla_L[k] + 4 : 0;
} else {
t = ancilla_z[k] < 0x20 ? 1 : 2;
}
AncillaDraw_Shadow(oam, t, pt.x, pt.y + 12, 0x20);
}
void ItemReceipt_TransmuteToRisingCrystal(int k) { // 88cbe4
ancilla_type[k] = 0x3e;
ancilla_y_vel[k] = 0;
ancilla_x_vel[k] = 0;
ancilla_y_subpixel[k] = 0;
Ancilla_RisingCrystal(k);
}
void Ancilla_RisingCrystal(int k) { // 88cbf2
ancilla_z[k] = 0;
AncillaAdd_OccasionalSparkle(k);
uint8 yy = ancilla_y_vel[k] - 1;
if (yy < 0xf0)
yy = 0xf0;
ancilla_y_vel[k] = yy;
Ancilla_MoveY(k);
uint16 y = Ancilla_GetY(k) - BG2VOFS_copy;
if (y < 0x49) {
Ancilla_SetY(k, 0x49 + BG2VOFS_copy);
if (!submodule_index) {
link_has_crystals |= kDungeonCrystalPendantBit[BYTE(cur_palace_index_x2) >> 1];
submodule_index = 0x18;
subsubmodule_index = 0;
memset(aux_palette_buffer + 0x20, 0, sizeof(uint16) * 0x60);
palette_filter_countdown = 0;
darkening_or_lightening_screen = 0;
}
}
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
Ancilla_ReceiveItem_Draw(k, pt.x, pt.y);
}
void AncillaAdd_OccasionalSparkle(int k) { // 88cc93
if (!(frame_counter & 7))
AncillaAdd_SwordChargeSparkle(k);
}
void Ancilla43_GanonsTowerCutscene(int k) { // 88cca0
OamEnt *oam = GetOamCurPtr();
if (!ancilla_step[k]) {
uint8 yy = ancilla_y_vel[k] - 1;
ancilla_y_vel[k] = (yy < 0xf0) ? 0xf0 : yy;
Ancilla_MoveY(k);
uint16 x = Ancilla_GetX(k), y = Ancilla_GetY(k);
if ((uint16)(y - BG2VOFS_copy) >= 0x38)
goto lbl_else;
breaktowerseal_y = 0x38 + 8 + BG2VOFS_copy;
breaktowerseal_x = x + 8;
Ancilla_SetY(k, 0x38 + BG2VOFS_copy);
ancilla_step[k]++;
sound_effect_ambient = 5;
music_control = 0xf1;
dialogue_message_index = 0x13b;
Main_ShowTextMessage();
goto label_a;
}
lbl_else:
if (ancilla_step[k] == 1 && submodule_index == 0) {
ancilla_x_vel[k] = 16;
uint8 bak0 = ancilla_x_lo[k];
uint8 bak1 = ancilla_x_hi[k];
ancilla_x_lo[k] = breaktowerseal_var4;
ancilla_x_hi[k] = 0;
Ancilla_MoveX(k);
breaktowerseal_var4 = ancilla_x_lo[k];
ancilla_x_lo[k] = bak0;
ancilla_x_hi[k] = bak1;
if (breaktowerseal_var4 >= 48) {
breaktowerseal_var4 = 48;
ancilla_step[k]++;
}
}
if (submodule_index)
goto label_b;
if (ancilla_step[k] == 0)
goto label_a;
if (ancilla_step[k] == 1)
goto label_b;
if (ancilla_step[k] == 2) {
if (--breaktowerseal_var5 == 0) {
trigger_special_entrance = 5;
subsubmodule_index = 0;
BYTE(R16) = 0;
ancilla_step[k]++;
}
} else {
ancilla_x_vel[k] = 48;
uint8 bak0 = ancilla_x_lo[k];
uint8 bak1 = ancilla_x_hi[k];
ancilla_x_lo[k] = breaktowerseal_var4;
ancilla_x_hi[k] = 0;
Ancilla_MoveX(k);
breaktowerseal_var4 = ancilla_x_lo[k];
ancilla_x_lo[k] = bak0;
ancilla_x_hi[k] = bak1;
if (breaktowerseal_var4 >= 240) {
palette_sp6 = 0;
overworld_palette_aux_or_main = 0x200;
Palette_Load_SpriteEnvironment_Dungeon();
flag_update_cgram_in_nmi++;
ancilla_type[k] = 0;
return;
}
}
uint8 astep;
label_b:
astep = ancilla_step[k];
if (astep != 0)
oam = GTCutscene_SparkleALot(oam);
for (int j = 6; j >= 0; j--) {
if (submodule_index == 0 && astep != 1 && !(frame_counter & 1))
breaktowerseal_var3[j] = breaktowerseal_var3[j] + 1 & 63;
AncillaRadialProjection arp = Ancilla_GetRadialProjection(breaktowerseal_var3[j], breaktowerseal_var4);
int x = (arp.r6 ? -arp.r4 : arp.r4) + breaktowerseal_x - 8 - BG2HOFS_copy;
int y = (arp.r2 ? -arp.r0 : arp.r0) + breaktowerseal_y - 8 - BG2VOFS_copy;
breaktowerseal_base_sparkle_x_lo[j] = x;
breaktowerseal_base_sparkle_x_hi[j] = x >> 8;
breaktowerseal_base_sparkle_y_lo[j] = y;
breaktowerseal_base_sparkle_y_hi[j] = y >> 8;
AncillaDraw_GTCutsceneCrystal(oam, x, y);
oam++;
}
Point16U info;
label_a:
Ancilla_PrepAdjustedOamCoord(k, &info);
breaktowerseal_base_sparkle_x_lo[7] = info.x;
breaktowerseal_base_sparkle_x_hi[7] = info.x >> 8;
breaktowerseal_base_sparkle_y_lo[7] = info.y;
breaktowerseal_base_sparkle_y_hi[7] = info.y >> 8;
AncillaDraw_GTCutsceneCrystal(oam, info.x, info.y);
if (!ancilla_step[k])
AncillaAdd_OccasionalSparkle(k);
else if (!submodule_index)
GTCutscene_ActivateSparkle();
}
void AncillaDraw_GTCutsceneCrystal(OamEnt *oam, int x, int y) { // 88ceaa
uint8 ext = Ancilla_SetOam_XY_safe(oam, x, y);
oam->charnum = 0x24;
oam->flags = 0x3c;
int j = oam - oam_buf;
bytewise_extended_oam[oam - oam_buf] = ext | 2;
}
void GTCutscene_ActivateSparkle() { // 88cec7
for (int k = 0x17; k >= 0; k--) {
if (breaktowerseal_sparkle_var1[k] == 0xff) {
breaktowerseal_sparkle_var1[k] = 0;
breaktowerseal_sparkle_var2[k] = 4;
int r = GetRandomNumber();
int x = breaktowerseal_base_sparkle_x_hi[k & 7] << 8 | breaktowerseal_base_sparkle_x_lo[k & 7];
int y = breaktowerseal_base_sparkle_y_hi[k & 7] << 8 | breaktowerseal_base_sparkle_y_lo[k & 7];
x += r >> 4;
y += r & 0xf;
breaktowerseal_sparkle_x_lo[k] = x;
breaktowerseal_sparkle_x_hi[k] = x >> 8;
breaktowerseal_sparkle_y_lo[k] = y;
breaktowerseal_sparkle_y_hi[k] = y >> 8;
return;
}
}
}
OamEnt *GTCutscene_SparkleALot(OamEnt *oam) { // 88cf35
static const uint8 kSwordChargeSpark_Char[3] = {0xb7, 0x80, 0x83};
static const uint8 kSwordChargeSpark_Flags[3] = {4, 4, 0x84};
for (int k = 0x17; k >= 0; k--) {
if (breaktowerseal_sparkle_var1[k] == 0xff)
continue;
if (sign8(--breaktowerseal_sparkle_var2[k])) {
breaktowerseal_sparkle_var2[k] = 4;
if (++breaktowerseal_sparkle_var1[k] == 3) {
breaktowerseal_sparkle_var1[k] = 0xff;
continue;
}
}
int x = breaktowerseal_sparkle_x_hi[k] << 8 | breaktowerseal_sparkle_x_lo[k];
int y = breaktowerseal_sparkle_y_hi[k] << 8 | breaktowerseal_sparkle_y_lo[k];
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
int j = breaktowerseal_sparkle_var1[k];
oam->charnum = kSwordChargeSpark_Char[j];
oam->flags = kSwordChargeSpark_Flags[j] | 0x30;
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
return oam;
}
void Ancilla36_Flute(int k) { // 88cfaa
static const uint8 kFlute_Vels[4] = {0x18, 0x10, 0xa, 0};
if (!submodule_index) {
if (ancilla_step[k] != 3) {
ancilla_z_vel[k] -= 2;
Ancilla_MoveX(k);
Ancilla_MoveZ(k);
if (sign8(ancilla_z[k]) || ancilla_z[k] >= 0xf0) {
ancilla_z_vel[k] = kFlute_Vels[++ancilla_step[k]];
ancilla_z[k] = 0;
}
} else {
CheckPlayerCollOut coll_out;
if (Ancilla_CheckLinkCollision(k, 2, &coll_out) && !related_to_hookshot && link_auxiliary_state == 0) {
ancilla_type[k] = 0;
item_receipt_method = 0;
Link_ReceiveItem(0x14, 0);
return;
}
}
}
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y - (int8)ancilla_z[k]);
oam->charnum = 0x24;
oam->flags = HIBYTE(oam_priority_value) | 4;
bytewise_extended_oam[oam - oam_buf] = ext | 2;
if (oam->y == 0xf0)
ancilla_type[k] = 0;
}
void Ancilla37_WeathervaneExplosion(int k) { // 88d03d
if (--weathervane_var2)
return;
weathervane_var2 = 1;
if (!weathervane_var1) {
weathervane_var1 = 1;
music_control = 0xf3;
}
if (--ancilla_G[k])
return;
ancilla_G[k] = 1;
if (!ancilla_arr3[k]) {
ancilla_arr3[k] += 1;
Ancilla_Sfx2_Near(0xc);
}
if (!ancilla_step[k] && sign8(--ancilla_aux_timer[k])) {
ancilla_step[k] = 1;
Overworld_AlterWeathervane();
AncillaAdd_CutsceneDuck(0x38, 0);
}
weathervane_var13 = k;
weathervane_var14 = 0;
for (int i = 11; i >= 0; i--) {
if (weathervane_arr12[i] == 0xff)
continue;
if (sign8(--weathervane_arr11[i])) {
weathervane_arr11[i] = 1;
weathervane_arr12[i] ^= 1;
}
ancilla_item_to_link[k] = weathervane_arr12[i];
ancilla_y_lo[k] = weathervane_arr6[i];
ancilla_y_hi[k] = weathervane_arr7[i];
ancilla_x_lo[k] = weathervane_arr8[i];
ancilla_x_hi[k] = weathervane_arr9[i];
ancilla_z[k] = weathervane_arr10[i];
ancilla_y_vel[k] = weathervane_arr3[i];
ancilla_x_vel[k] = weathervane_arr4[i];
weathervane_arr5[i] = ancilla_z_vel[k] = weathervane_arr5[i] - 1;
Ancilla_MoveY(k);
Ancilla_MoveX(k);
Ancilla_MoveZ(k);
uint8 c = (ancilla_z[k] < 0xf0) ? 0 : 0xff;
AncillaDraw_WeathervaneExplosionWoodDebris(k);
if (sign8(c))
weathervane_arr12[i] = c;
weathervane_arr6[i] = ancilla_y_lo[k];
weathervane_arr7[i] = ancilla_y_hi[k];
weathervane_arr8[i] = ancilla_x_lo[k];
weathervane_arr9[i] = ancilla_x_hi[k];
weathervane_arr10[i] = ancilla_z[k];
}
for (int i = 11; i >= 0; i--) {
if (weathervane_arr12[i] != 0xff)
return;
}
ancilla_type[k] = 0;
}
void AncillaDraw_WeathervaneExplosionWoodDebris(int k) { // 88d188
static const uint8 kWeathervane_Explode_Char[2] = {0x4e, 0x4f};
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
pt.y -= (int8)ancilla_z[k];
int i = ancilla_item_to_link[k];
if (sign8(i))
return;
OamEnt *oam = GetOamCurPtr() + (weathervane_var14 >> 2);
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y);
oam->charnum = kWeathervane_Explode_Char[i];
oam->flags = 0x3c;
weathervane_var14 += 4;
bytewise_extended_oam[oam - oam_buf] = ext;
}
void Ancilla38_CutsceneDuck(int k) { // 88d1d8
static const uint8 kTravelBirdIntro_Tab0[2] = {0x40, 0};
static const uint8 kTravelBirdIntro_Tab1[2] = {28, 60};
if (!(frame_counter & 31))
Ancilla_Sfx3_Pan(k, 0x1e);
if (sign8(--ancilla_arr3[k])) {
ancilla_arr3[k] = 3;
ancilla_K[k] ^= 1;
}
if (!--ancilla_aux_timer[k]) {
ancilla_aux_timer[k] = 1;
if (!ancilla_L[k]) {
if (!sign8(--ancilla_item_to_link[k])) {
ancilla_z_vel[k] += ancilla_step[k] ? 1 : -1;
if (abs8(ancilla_z_vel[k]) >= 12)
ancilla_step[k] ^= 1;
goto after_stuff;
}
ancilla_item_to_link[k] = 0;
ancilla_step[k] = 0;
ancilla_x_vel[k] = kTravelBirdIntro_Tab1[0];
ancilla_z_vel[k] = -16;
ancilla_L[k]++;
ancilla_step[k] = 3;
}
ancilla_x_vel[k] += (ancilla_step[k] & 1) == 0 ? 1 : -1;
uint8 absx = abs8(ancilla_x_vel[k]);
if (absx == 0 && ++ancilla_L[k] == 7)
ancilla_S[k] = 1;
if (absx >= kTravelBirdIntro_Tab1[ancilla_S[k]]) {
ancilla_step[k] ^= 3;
}
ancilla_dir[k] = sign8(ancilla_x_vel[k]) ? 2 : 3;
uint8 t = (uint8)(kTravelBirdIntro_Tab1[ancilla_S[k]] - absx) >> 1;
ancilla_z_vel[k] = (ancilla_step[k] & 2) ? -t : t;
}
after_stuff:
Ancilla_MoveX(k);
Ancilla_MoveZ(k);
BYTE(flag_travel_bird) = kTravelBird_DmaStuffs[ancilla_K[k] + 1];
Point16U info;
Ancilla_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
uint8 ext = Ancilla_SetOam_XY(oam, info.x + kTravelBird_Draw_X[0], info.y + (int8)ancilla_z[k] + kTravelBird_Draw_Y[0]);
oam->charnum = kTravelBird_Draw_Char[0];
oam->flags = kTravelBird_Draw_Flags[0] | 0x30 | kTravelBirdIntro_Tab0[ancilla_dir[k] & 1];
bytewise_extended_oam[oam - oam_buf] = ext | 2;
oam++;
AncillaDraw_Shadow(oam, 1, info.x, info.y + 48, 0x30);
if (!sign16(info.x) && info.x >= 248) {
ancilla_type[k] = 0;
submodule_index = 0;
link_item_flute = 3;
}
}
void Ancilla23_LinkPoof(int k) { // 88d3bc
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 7;
if (++ancilla_item_to_link[k] == 3) {
ancilla_type[k] = 0;
link_is_transforming = 0;
link_cant_change_direction = 0;
if (!ancilla_step[k]) {
link_animation_steps = 0;
link_visibility_status = 0;
link_is_bunny = link_is_bunny_mirror = BYTE(overworld_screen_index) & 0x40 ? 1 : 0;
if (link_is_bunny)
LoadGearPalettes_bunny();
else
LoadActualGearPalettes();
}
return;
}
}
MorphPoof_Draw(k);
}
void MorphPoof_Draw(int k) { // 88d3fd
static const int8 kMorphPoof_X[12] = {0, 0, 0, 0, 0, 8, 0, 8, -4, 12, -4, 12};
static const int8 kMorphPoof_Y[12] = {0, 0, 0, 0, 0, 0, 8, 8, -4, -4, 12, 12};
static const uint8 kMorphPoof_Flags[12] = {0, 0xff, 0xff, 0xff, 0x40, 0, 0xc0, 0x80, 0, 0x40, 0x80, 0xc0};
static const uint8 kMorphPoof_Char[3] = {0x86, 0xa9, 0x9b};
static const uint8 kMorphPoof_Ext[3] = {2, 0, 0};
if (sort_sprites_setting && ancilla_floor[k] && (!flag_for_boomerang_in_place || !(frame_counter & 1))) {
oam_cur_ptr = 0x8d0;
oam_ext_cur_ptr = 0xa20 + (0xd0 >> 2);
}
Point16U info;
Ancilla_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
int j = ancilla_item_to_link[k];
uint8 ext = kMorphPoof_Ext[j];
uint8 chr = kMorphPoof_Char[j];
for (int i = 0; i < 4; i++, oam++) {
uint8 ext2 = Ancilla_SetOam_XY(oam, info.x + kMorphPoof_X[j * 4 + i], info.y + kMorphPoof_Y[j * 4 + i]);
oam->charnum = chr;
oam->flags = kMorphPoof_Flags[j * 4 + i] | 4 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext | ext2;
if (ext == 2)
break;
}
}
void Ancilla40_DwarfPoof(int k) { // 88d49a
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 7;
if (++ancilla_item_to_link[k] == 3) {
ancilla_type[k] = 0;
tagalong_var5 = 0;
return;
}
}
MorphPoof_Draw(k);
}
void Ancilla3F_BushPoof(int k) { // 88d519
static const int8 kBushPoof_Draw_X[16] = {0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, -2, 10, -2, 10};
static const int8 kBushPoof_Draw_Y[16] = {0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, -2, -2, 10, 10};
static const uint8 kBushPoof_Draw_Char[16] = {0x86, 0x87, 0x96, 0x97, 0xa9, 0xa9, 0xa9, 0xa9, 0x8a, 0x8b, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b};
static const uint8 kBushPoof_Draw_Flags[16] = {0, 0, 0, 0, 0, 0x40, 0x80, 0xc0, 0, 0, 0, 0, 0xc0, 0x80, 0x40, 0};
if (ancilla_timer[k] == 0) {
ancilla_timer[k] = 7;
if (++ancilla_item_to_link[k] == 4) {
ancilla_type[k] = 0;
return;
}
}
Oam_AllocateFromRegionC(0x10);
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
int j = ancilla_item_to_link[k] * 4;
for (int i = 0; i < 4; i++, j++, oam++) {
uint8 ext = Ancilla_SetOam_XY(oam, pt.x + kBushPoof_Draw_X[j], pt.y + kBushPoof_Draw_Y[j]);
oam->charnum = kBushPoof_Draw_Char[j];
oam->flags = kBushPoof_Draw_Flags[j] | 4 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
}
}
void Ancilla26_SwordSwingSparkle(int k) { // 88d65a
static const int8 kSwordSwingSparkle_X[48] = {
5, 10, -1, 5, 10, -4, 5, 10, -4, -4, -1, -1, 0, 5, -1, 0,
5, 14, 0, 5, 14, 14, -1, -1, -23, -27, -1, -23, -27, -22, -23, -27,
-22, -22, -1, -1, 32, 35, -1, 32, 35, 30, 32, 35, 30, 30, -1, -1,
};
static const int8 kSwordSwingSparkle_Y[48] = {
-22, -18, -1, -22, -18, -17, -22, -18, -17, -17, -1, -1, 35, 40, -1, 35,
40, 37, 35, 40, 37, 37, -1, -1, 2, 7, -1, 2, 7, 19, 2, 7,
19, 19, -1, -1, 2, 7, -1, 2, 7, 19, 2, 7, 19, 19, -1, -1,
};
static const uint8 kSwordSwingSparkle_Char[48] = {
0xb7, 0xb7, 0xff, 0x80, 0x80, 0xb7, 0x83, 0x83, 0x80, 0x83, 0xff, 0xff, 0xb7, 0xb7, 0xff, 0x80,
0x80, 0xb7, 0x83, 0x83, 0x80, 0x83, 0xff, 0xff, 0xb7, 0xb7, 0xff, 0x80, 0x80, 0xb7, 0x83, 0x83,
0x80, 0x83, 0xff, 0xff, 0xb7, 0xb7, 0xff, 0x80, 0x80, 0xb7, 0x83, 0x83, 0x80, 0x83, 0xff, 0xff,
};
static const uint8 kSwordSwingSparkle_Flags[48] = {
0, 0, 0xff, 0, 0, 0, 0x80, 0x80, 0, 0x80, 0xff, 0xff, 0, 0, 0xff, 0,
0, 0, 0x80, 0x80, 0, 0x80, 0xff, 0xff, 0, 0, 0xff, 0, 0, 0, 0x80, 0x80,
0, 0x80, 0xff, 0xff, 0, 0, 0xff, 0, 0, 0, 0x80, 0x80, 0, 0x80, 0xff, 0xff,
};
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 0;
if (++ancilla_item_to_link[k] == 4) {
ancilla_type[k] = 0;
return;
}
}
Ancilla_SetXY(k, link_x_coord, link_y_coord);
Point16U info;
Ancilla_PrepOamCoord(k, &info);
k = ancilla_item_to_link[k] * 3 + ancilla_dir[k] * 12;
OamEnt *oam = GetOamCurPtr();
for (int n = 2; n >= 0; n--, k++, oam++) {
uint8 chr = kSwordSwingSparkle_Char[k];
if (chr == 0xff)
continue;
oam->charnum = chr;
oam->flags = kSwordSwingSparkle_Flags[k] | 0x4 | (oam_priority_value >> 8);
uint8 ext = Ancilla_SetOam_XY(oam, info.x + kSwordSwingSparkle_X[k], info.y + kSwordSwingSparkle_Y[k]);
bytewise_extended_oam[oam - oam_buf] = ext;
}
}
void Ancilla2A_SpinAttackSparkleA(int k) { // 88d7b2
static const uint8 kInitialSpinSpark_Timer[6] = {4, 2, 3, 3, 2, 1};
if (!submodule_index && sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 0;
if (!ancilla_timer[k]) {
int j = ++ancilla_item_to_link[k];
ancilla_timer[k] = kInitialSpinSpark_Timer[j];
if (j == 5) {
if (ancilla_step[k])
AddSwordBeam(j);
else
SpinAttackSparkleA_TransmuteToNextSpark(k);
return;
}
}
}
if (!ancilla_item_to_link[k])
return;
SpinSpark_Draw(k, -1);
}
void SpinAttackSparkleA_TransmuteToNextSpark(int k) { // 88d86d
static const uint8 kTransmuteSpinSpark_Arr[16] = {0x21, 0x20, 0x1f, 0x1e, 3, 2, 1, 0, 0x12, 0x11, 0x10, 0xf, 0x31, 0x30, 0x2f, 0x2e};
static const int8 kTransmuteSpinSpark_X[4] = {-3, 21, 25, -8};
static const int8 kTransmuteSpinSpark_Y[4] = {28, -2, 24, 6};
ancilla_type[k] = 0x2b;
int j = link_direction_facing * 2;
swordbeam_arr[0] = kTransmuteSpinSpark_Arr[j + 0];
swordbeam_arr[1] = kTransmuteSpinSpark_Arr[j + 1];
swordbeam_arr[2] = kTransmuteSpinSpark_Arr[j + 2];
swordbeam_arr[3] = swordbeam_var1 = kTransmuteSpinSpark_Arr[j + 3];
ancilla_aux_timer[k] = 2;
ancilla_item_to_link[k] = 0x4c;
ancilla_arr3[k] = 8;
ancilla_step[k] = 0;
ancilla_L[k] = 0;
ancilla_arr1[k] = 255;
swordbeam_var2 = 20;
swordbeam_temp_x = link_x_coord + 8;
swordbeam_temp_y = link_y_coord + 12;
j = link_direction_facing>>1;
Ancilla_SetXY(k,
link_x_coord + kTransmuteSpinSpark_X[j],
link_y_coord + kTransmuteSpinSpark_Y[j]);
Ancilla2B_SpinAttackSparkleB(k);
}
void Ancilla2B_SpinAttackSparkleB(int k) { // 88d8fd
static const uint8 kSpinSpark_Char[4] = {0xd7, 0xb7, 0x80, 0x83};
if (ancilla_L[k]) {
SpinAttackSparkleB_Closer(k);
return;
}
uint8 flags = 2;
if (!submodule_index) {
uint8 t = (ancilla_item_to_link[k] -= 3);
if (t < 13) {
ancilla_aux_timer[k] = 1;
ancilla_L[k] = 1;
ancilla_item_to_link[k] = 0;
SpinAttackSparkleB_Closer(k);
return;
}
ancilla_step[k] = (t < 0x42) ? 3 : (t == 0x46) ? 1 : (t == 0x43) ? 2 : 0;
if (sign8(--ancilla_aux_timer[k])) {
flags = 4;
ancilla_aux_timer[k] = 2;
}
}
OamEnt *oam = GetOamCurPtr(), *oam_org = oam;
int i = ancilla_step[k];
do {
if (submodule_index == 0)
swordbeam_arr[i] = (swordbeam_arr[i] + 4) & 0x3f;
Point16U pt = Sparkle_PrepOamFromRadial(Ancilla_GetRadialProjection(swordbeam_arr[i], swordbeam_var2));
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y);
oam->charnum = kSpinSpark_Char[i];
oam->flags = flags | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
} while (oam++, --i >= 0);
if (submodule_index == 0) {
if (!sign8(--ancilla_arr3[k]))
goto endif_2;
ancilla_arr3[k] = 0;
ancilla_arr1[k] = (ancilla_arr1[k] + 1) & 3;
if (ancilla_arr1[k] == 3)
swordbeam_var1 = (swordbeam_var1 + 9) & 0x3f;
}
uint8 t;
t = ancilla_arr1[k];
if (t != 3) {
static const uint8 kSpinSpark_Char2[3] = {0xb7, 0x80, 0x83};
Point16U pt = Sparkle_PrepOamFromRadial(Ancilla_GetRadialProjection(swordbeam_var1, swordbeam_var2));
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y);
oam->charnum = kSpinSpark_Char2[t];
oam->flags = 4 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
}
endif_2:
if (ancilla_item_to_link[k] == 7)
bytewise_extended_oam[oam_org - oam_buf + 3] = 1;
}
Point16U Sparkle_PrepOamFromRadial(AncillaRadialProjection p) { // 88da17
Point16U pt;
pt.y = (p.r2 ? -p.r0 : p.r0) + swordbeam_temp_y - 4 - BG2VOFS_copy2;
pt.x = (p.r6 ? -p.r4 : p.r4) + swordbeam_temp_x - 4 - BG2HOFS_copy2;
return pt;
}
void SpinAttackSparkleB_Closer(int k) { // 88da4c
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 1;
if (++ancilla_item_to_link[k] == 3)
ancilla_type[k] = 0;
}
SpinSpark_Draw(k, 4);
}
void Ancilla30_ByrnaWindupSpark(int k) { // 88db24
static const int8 kInitialCaneSpark_X[16] = {3, 1, 0, 0, 13, 16, 12, 12, 24, 7, -4, -10, -8, 9, 22, 26};
static const int8 kInitialCaneSpark_Y[16] = {5, 0, -3, -6, -8, -3, 12, 28, 5, 0, 8, 16, 5, 0, 8, 16};
static const int8 kInitialCaneSpark_Draw_X[16] = {-4, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, 0, -8, 0, -8, 0};
static const int8 kInitialCaneSpark_Draw_Y[16] = {-4, 0, 0, 0, -8, -8, 0, 0, -8, -8, 0, 0, -8, -8, 0, 0};
static const uint8 kInitialCaneSpark_Draw_Char[16] = {0x92, 0xff, 0xff, 0xff, 0x8c, 0x8c, 0x8c, 0x8c, 0xd6, 0xd6, 0xd6, 0xd6, 0x93, 0x93, 0x93, 0x93};
static const uint8 kInitialCaneSpark_Draw_Flags[16] = {0x22, 0xff, 0xff, 0xff, 0x22, 0x62, 0xa2, 0xe2, 0x24, 0x64, 0xa4, 0xe4, 0x22, 0x62, 0xa2, 0xe2};
if (!submodule_index && sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 1;
if (++ancilla_item_to_link[k] == 17) {
ByrnaWindupSpark_TransmuteToNormal(k);
return;
}
}
if (!ancilla_item_to_link[k])
return;
int j = player_handler_timer;
if (j == 2) {
uint8 a = ancilla_arr3[k] - 1;
if (sign8(a))
a = 0, j = 3;
ancilla_arr3[k] = a;
}
j += link_direction_facing * 2;
Ancilla_SetXY(k, link_x_coord + kInitialCaneSpark_X[j], link_y_coord + kInitialCaneSpark_Y[j]);
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
uint8 a = (ancilla_item_to_link[k] - 1) & 0xf;
j = 0;
if (a != 0)
j = 4 * ((a != 15) ? (a & 1) + 1 : 3);
OamEnt *oam = GetOamCurPtr();
for (int i = 0; i < 4; i++, j++) {
if (kInitialCaneSpark_Draw_Char[j] != 255) {
uint8 ext = Ancilla_SetOam_XY(oam, pt.x + kInitialCaneSpark_Draw_X[j], pt.y + kInitialCaneSpark_Draw_Y[j]);
oam->charnum = kInitialCaneSpark_Draw_Char[j];
oam->flags = kInitialCaneSpark_Draw_Flags[j] & ~0x30 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
}
}
void ByrnaWindupSpark_TransmuteToNormal(int k) { // 88dc21
static const uint8 kCaneSpark_Transmute_Tab[16] = {0x34, 0x33, 0x32, 0x31, 0x16, 0x15, 0x14, 0x13, 0x2a, 0x29, 0x28, 0x27, 0x10, 0xf, 0xe, 0xd};
ancilla_type[k] = 0x31;
int j = link_direction_facing << 1;
swordbeam_arr[0] = kCaneSpark_Transmute_Tab[j + 0];
swordbeam_arr[1] = kCaneSpark_Transmute_Tab[j + 1];
swordbeam_arr[2] = kCaneSpark_Transmute_Tab[j + 2];
swordbeam_arr[3] = kCaneSpark_Transmute_Tab[j + 3];
ancilla_aux_timer[k] = 0x17;
ancilla_G[k] = 0;
ancilla_item_to_link[k] = 0;
ancilla_arr3[k] = 8;
ancilla_step[k] = 0;
ancilla_L[k] = 0;
ancilla_arr1[k] = 2;
ancilla_timer[k] = 21;
swordbeam_var2 = 20;
Ancilla_Sfx3_Near(0x30);
Ancilla31_ByrnaSpark(k);
}
void Ancilla31_ByrnaSpark(int k) { // 88dc70
static const uint8 kCaneSpark_Magic[3] = {4, 2, 1};
uint8 flags = 2;
if (submodule_index == 0) {
if (current_item_y != 13) {
kill_me:
link_disable_sprite_damage = 0;
ancilla_type[k] = 0;
link_give_damage = 0;
return;
}
link_disable_sprite_damage = 1;
if (!--ancilla_aux_timer[k]) {
ancilla_aux_timer[k] = 1;
uint8 r0 = kCaneSpark_Magic[link_magic_consumption];
if (!link_magic_power || (uint8)(r0 = link_magic_power - r0) >= 0x80)
goto kill_me;
if (sign8(--ancilla_G[k])) {
ancilla_G[k] = 0x17;
link_magic_power = r0;
}
if (filtered_joypad_H & 0x40)
goto kill_me;
}
if (ancilla_step[k] != 3) {
uint8 a = ++ancilla_item_to_link[k];
ancilla_step[k] = (a >= 4) ? 3 : (a == 2) ? 1 : (a == 3) ? 2 : 0;
}
if (sign8(--ancilla_arr1[k])) {
ancilla_arr1[k] = 2;
flags = 4;
}
}
int z = (int8)link_z_coord;
if (z == -1)
z = 0;
swordbeam_temp_y = link_y_coord + 12 - z;
swordbeam_temp_x = link_x_coord + 8;
if (!ancilla_timer[k]) {
ancilla_timer[k] = 21;
Ancilla_Sfx3_Near(0x30);
}
OamEnt *oam = GetOamCurPtr();
int i = ancilla_step[k];
do {
static const uint8 kCaneSpark_Char[4] = {0xd7, 0xb7, 0x80, 0x83};
if (!submodule_index)
swordbeam_arr[i] = (swordbeam_arr[i] + 3) & 0x3f;
Point16U pt = Sparkle_PrepOamFromRadial(Ancilla_GetRadialProjection(swordbeam_arr[i], swordbeam_var2));
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y);
oam->charnum = kCaneSpark_Char[i];
oam->flags = flags | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
Ancilla_SetXY(k, pt.x + BG2HOFS_copy2, pt.y + BG2VOFS_copy2);
ancilla_dir[k] = 0;
Ancilla_CheckSpriteCollision(k);
} while (oam++, --i >= 0);
}
void Ancilla_SwordBeam(int k) { // 88ddc5
uint8 flags = 2;
if (!submodule_index) {
Ancilla_SetXY(k, swordbeam_temp_x, swordbeam_temp_y);
Ancilla_MoveX(k);
Ancilla_MoveY(k);
swordbeam_temp_x = Ancilla_GetX(k);
swordbeam_temp_y = Ancilla_GetY(k);
if ((ancilla_G[k]++ & 0xf) == 0) {
sound_effect_2 = Ancilla_CalculateSfxPan(k) | 1;
}
if (Ancilla_CheckSpriteCollision(k) >= 0 || Ancilla_CheckTileCollision(k)) {
static const int8 kSwordBeam_Yvel2[4] = {0, 0, -6, -6};
static const int8 kSwordBeam_Xvel2[4] = {-8, -10, 0, 0};
int j = ancilla_dir[k];
Ancilla_SetXY(k,
Ancilla_GetX(k) + kSwordBeam_Xvel2[j],
Ancilla_GetY(k) + kSwordBeam_Yvel2[j]);
ancilla_type[k] = 4;
ancilla_timer[k] = 7;
ancilla_numspr[k] = 0x10;
return;
}
if (sign8(--ancilla_aux_timer[k])) {
flags = 4;
ancilla_aux_timer[k] = 2;
}
}
OamEnt *oam = GetOamCurPtr();
uint8 s = ancilla_S[k];
for (int i = 3; i >= 0; i--, oam++) {
static const uint8 kSwordBeam_Char[4] = {0xd7, 0xb7, 0x80, 0x83};
if (submodule_index == 0)
swordbeam_arr[i] = (swordbeam_arr[i] + s) & 0x3f;
Point16U pt = Sparkle_PrepOamFromRadial(Ancilla_GetRadialProjection(swordbeam_arr[i], swordbeam_var2));
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y);
oam->charnum = kSwordBeam_Char[i];
oam->flags = flags | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
}
if (submodule_index == 0) {
if (!sign8(--ancilla_arr3[k]))
goto endif_2;
ancilla_arr3[k] = 0;
ancilla_arr1[k] = (ancilla_arr1[k] + 1) & 3;
if (ancilla_arr1[k] == 3)
swordbeam_var1 = (swordbeam_var1 + s) & 0x3f;
}
uint8 t;
t = ancilla_arr1[k];
if (t != 3) {
static const uint8 kSwordBeam_Char2[3] = {0xb7, 0x80, 0x83};
Point16U pt = Sparkle_PrepOamFromRadial(Ancilla_GetRadialProjection(swordbeam_var1, swordbeam_var2));
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y);
oam->charnum = kSwordBeam_Char2[t];
oam->flags = 4 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
}
endif_2:
oam -= 4;
for (int i = 0; i < 4; i++) {
if (oam[i].y != 0xf0)
return;
}
ancilla_type[k] = 0;
}
void Ancilla0D_SpinAttackFullChargeSpark(int k) { // 88ddca
static const int8 kSwordFullChargeSpark_Y[4] = {-8, 27, 12, 12};
static const int8 kSwordFullChargeSpark_X[4] = {4, 4, -13, 20};
static const uint8 kSwordFullChargeSpark_Flags[4] = {0x20, 0x10, 0x30, 0x20};
ancilla_oam_idx[k] = Ancilla_AllocateOamFromRegion_A_or_D_or_F(k, 4);
if (!ancilla_timer[k]) {
ancilla_type[k] = 0;
return;
}
int j = link_direction_facing >> 1;
uint16 x = link_x_coord + kSwordFullChargeSpark_X[j] - BG2HOFS_copy2;
uint16 y = link_y_coord + kSwordFullChargeSpark_Y[j] - BG2VOFS_copy2;
oam_priority_value = kSwordFullChargeSpark_Flags[ancilla_floor[k]] << 8;
OamEnt *oam = GetOamCurPtr();
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = 0xd7;
oam->flags = HIBYTE(oam_priority_value) | 2;
bytewise_extended_oam[oam - oam_buf] = ext;
}
void Ancilla27_Duck(int k) { // 88dde8
CheckPlayerCollOut coll;
int j;
if (submodule_index)
goto endif_1;
if (ancilla_timer[k]) {
int xt = (enhanced_features0 & kFeatures0_ExtendScreen64) ? 0x40 : 0;
Ancilla_SetXY(k, BG2HOFS_copy2 - 16 - xt, link_y_coord - 8);
return;
}
if (sign8(--ancilla_G[k])) {
ancilla_G[k] = 0x28;
Ancilla_Sfx3_Pan(k, 0x1e);
}
if (ancilla_L[k] || ancilla_step[k] && (flag_unk1++, true)) {
ancilla_z_vel[k]--;
Ancilla_MoveZ(k);
}
Ancilla_MoveX(k);
if (ancilla_L[k]) {
uint16 x = Ancilla_GetX(k);
if (ancilla_step[k])
flag_unk1++;
if (!sign16(x) && x >= link_x_coord) {
if (ancilla_step[k]) {
ancilla_step[k] = 0;
link_visibility_status = 0;
tagalong_var5 = 0;
link_pose_for_item = 0;
ancilla_y_vel[k] = 0;
flag_is_link_immobilized = 0;
link_disable_sprite_damage = 0;
byte_7E03FD = 0;
countdown_for_blink = 144;
if (!((follower_indicator == 12 || follower_indicator == 13) && follower_dropped)) {
Follower_Initialize();
}
}
} else if ((uint16)(link_x_coord - x) < 48) {
j = 3;
goto endif_5;
}
goto endif_1;
}
if (!Ancilla_CheckLinkCollision(k, 1, &coll) || main_module_index == 15)
goto endif_1;
if (!player_is_indoors) {
if (link_player_handler_state == 8 || link_player_handler_state == 9 || link_player_handler_state == 10 ||
player_near_pit_state == 2 ||
(link_pose_for_item | related_to_hookshot | link_force_hold_sword_up | link_disable_sprite_damage) ||
(link_state_bits & 0x80))
goto endif_1;
for (int i = 4; i >= 0; i--) {
uint8 a = ancilla_type[i];
if (a == 0x2a || a == 0x1f || a == 0x30 || a == 0x31 || a == 0x41)
ancilla_type[i] = 0;
}
if (follower_indicator == 9) {
follower_indicator = 0;
tagalong_var5 = 0;
}
}
link_state_bits = 0;
link_picking_throw_state = 0;
bg1_x_offset = 0;
bg1_y_offset = 0;
Link_ResetProperties_A();
link_is_in_deep_water = 0;
link_need_for_pullforrupees_sprite = 0;
link_visibility_status = 12;
link_player_handler_state = 0;
link_pose_for_item = 1;
flag_is_link_immobilized = 1;
link_disable_sprite_damage = 1;
tagalong_var5 = 1;
ancilla_step[k] = 2;
flag_unk1++;
link_give_damage = 0;
if (player_is_indoors)
byte_7E03FD = player_is_indoors;
endif_1:
if (sign8(--ancilla_arr3[k])) {
ancilla_arr3[k] = 3;
if (++ancilla_K[k] == 3)
ancilla_K[k] = 0;
}
j = ancilla_K[k];
endif_5:
BYTE(flag_travel_bird) = kTravelBird_DmaStuffs[j];
Point16U info;
Ancilla_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
int z = ancilla_z[k] ? ancilla_z[k] | ~0xff : 0;
int i = 0, n = ancilla_step[k] + 1;
do {
uint8 ext = Ancilla_SetOam_XY(oam, info.x + (int8)kTravelBird_Draw_X[i], info.y + z + (int8)kTravelBird_Draw_Y[i]);
oam->charnum = kTravelBird_Draw_Char[i];
oam->flags = kTravelBird_Draw_Flags[i] | 0x30;
bytewise_extended_oam[oam - oam_buf] = ext | 2;
oam++;
} while (++i != n);
AncillaDraw_Shadow(oam, 1, info.x, info.y + 28, 0x30);
oam += 2;
if (ancilla_step[k])
AncillaDraw_Shadow(oam, 1, info.x - 7, info.y + 28, 0x30);
if (!sign16(info.x) && info.x >= 0x130) {
ancilla_type[k] = 0;
if (!ancilla_L[k] && ancilla_step[k]) {
submodule_index = 10;
saved_module_for_menu = main_module_index;
main_module_index = 14;
}
}
}
void AncillaAdd_SomariaBlock(uint8 type, uint8 y) { // 88e078
int k = AncillaAdd_AddAncilla_Bank08(type, y);
if (k < 0) {
Refund_Magic(4);
return;
}
for (int j = 4; j >= 0; j--) {
if (j == k || ancilla_type[j] != 0x2c)
continue;
if (j == flag_is_ancilla_to_pick_up - 1)
flag_is_ancilla_to_pick_up = 0;
AncillaAdd_ExplodingSomariaBlock(j);
ancilla_type[k] = 0;
dung_flag_somaria_block_switch = 0;
if (link_speed_setting == 0x12) {
bitmask_of_dragstate = 0;
link_speed_setting = 0;
}
return;
}
Ancilla_Sfx3_Near(0x2a);
ancilla_step[k] = 0;
ancilla_y_vel[k] = 0;
ancilla_x_vel[k] = 0;
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 0;
ancilla_arr3[k] = 0;
ancilla_arr1[k] = 0;
ancilla_H[k] = 0;
ancilla_G[k] = 12;
ancilla_timer[k] = 18;
ancilla_L[k] = 0;
ancilla_z[k] = 0;
ancilla_K[k] = 0;
ancilla_R[k] = 0;
ancilla_arr4[k] = 0;
ancilla_S[k] = 9;
ancilla_T[k] = 0;
ancilla_dir[k] = link_direction_facing >> 1;
if (Ancilla_CheckInitialTileCollision_Class2(k)) {
Ancilla_SetX(k, link_x_coord + 8);
Ancilla_SetY(k, link_y_coord + 16);
} else {
static const int8 kCaneOfSomaria_Y[4] = { -8, 31, 17, 17 };
static const int8 kCaneOfSomaria_X[4] = { 8, 8, -8, 23 };
int j = link_direction_facing >> 1;
Ancilla_SetX(k, link_x_coord + kCaneOfSomaria_X[j]);
Ancilla_SetY(k, link_y_coord + kCaneOfSomaria_Y[j]);
SomariaBlock_CheckForTransitTile(k);
}
}
void SomariaBlock_CheckForTransitTile(int k) { // 88e191
static const int8 kSomariaTransitLine_X[12] = { -8, 0, 8, -8, 0, 8, -16, -16, -16, 16, 16, 16 };
static const int8 kSomariaTransitLine_Y[12] = { -16, -16, -16, 16, 16, 16, -8, 0, 8, -8, 0, 8 };
if (!dung_unk6)
return;
for (int j = 11; j >= 0; j--) {
uint16 x = Ancilla_GetX(k) + kSomariaTransitLine_X[j];
uint16 y = Ancilla_GetY(k) + kSomariaTransitLine_Y[j];
uint8 bak = ancilla_objprio[k];
Ancilla_CheckTileCollision_targeted(k, x, y);
ancilla_objprio[k] = bak;
if (ancilla_tile_attr[k] == 0xb6 || ancilla_tile_attr[k] == 0xbc) {
Ancilla_SetX(k, x);
Ancilla_SetY(k, y);
AncillaAdd_SomariaPlatformPoof(k);
return;
}
}
}
int Ancilla_CheckBasicSpriteCollision(int k) { // 88e1f9
for (int j = 15; j >= 0; j--) {
if (((j ^ frame_counter) & 3 | sprite_pause[j] | sprite_hit_timer[j]) != 0)
continue;
if (sprite_state[j] < 9 || !(sprite_defl_bits[j] & 2) && ancilla_objprio[k])
continue;
if (ancilla_floor[k] != sprite_floor[j])
continue;
if (ancilla_type[k] == 0x2c && (sprite_type[j] == 0x1e || sprite_type[j] == 0x90))
continue;
if (Ancilla_CheckBasicSpriteCollision_Single(k, j))
return j;
}
return -1;
}
bool Ancilla_CheckBasicSpriteCollision_Single(int k, int j) { // 88e23d
SpriteHitBox hb;
Ancilla_SetupBasicHitBox(k, &hb);
Sprite_SetupHitBox(j, &hb);
if (!CheckIfHitBoxesOverlap(&hb))
return false;
if (sprite_type[j] == 0x92 && sprite_C[j] < 3)
return true;
if (sprite_type[j] == 0x80 && sprite_delay_aux4[j] == 0) {
sprite_delay_aux4[j] = 24;
sprite_D[j] ^= 1;
}
if (sprite_ignore_projectile[j])
return false;
int x = Ancilla_GetX(k) - 8, y = Ancilla_GetY(k) - 8 - ancilla_z[k];
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLocation(j, x, y, 80);
sprite_y_recoil[j] = ~pt.y;
sprite_x_recoil[j] = ~pt.x;
Ancilla_CheckDamageToSprite(j, ancilla_type[k]);
return true;
}
void Ancilla_SetupBasicHitBox(int k, SpriteHitBox *hb) { // 88e2ca
int x = Ancilla_GetX(k) - 8;
hb->r0_xlo = x;
hb->r8_xhi = x >> 8;
int y = Ancilla_GetY(k) - 8 - ancilla_z[k];
hb->r1_ylo = y;
hb->r9_yhi = y >> 8;
hb->r2 = 15;
hb->r3 = 15;
}
void Ancilla2C_SomariaBlock(int k) { // 88e365
if (!sign8(--ancilla_G[k]))
return;
ancilla_G[k] = 0;
if (ancilla_H[k])
goto label_1;
if (submodule_index == 0 || submodule_index == 8 || submodule_index == 16) {
Ancilla_HandleLiftLogic(k);
} else if (k + 1 == flag_is_ancilla_to_pick_up && ancilla_K[k] != 0) {
if (ancilla_K[k] != 3) {
Ancilla_LatchLinkCoordinates(k, 3);
Ancilla_LatchAltitudeAboveLink(k);
ancilla_K[k] = 3;
}
Ancilla_LatchCarriedPosition(k);
}
if (player_is_indoors) {
if (!ancilla_K[k] && !(link_state_bits & 0x80) && (ancilla_z[k] == 0 || ancilla_z[k] == 0xff)) {
if (dung_unk6) {
int j = frame_counter & 3;
do {
uint8 bak = ancilla_objprio[k];
uint16 x = Ancilla_GetX(k) + kSomarianBlock_Coll_X[j];
uint16 y = Ancilla_GetY(k) + kSomarianBlock_Coll_Y[j];
Ancilla_CheckTileCollision_targeted(k, x, y);
ancilla_objprio[k] = bak;
if (ancilla_tile_attr[k] == 0xb6 || ancilla_tile_attr[k] == 0xbc) {
Ancilla_SetXY(k, x, y);
AncillaAdd_SomariaPlatformPoof(k);
if (k + 1 == flag_is_ancilla_to_pick_up)
flag_is_ancilla_to_pick_up = 0;
return;
}
} while ((j += 4) < 12);
} else {
if (!SomariaBlock_CheckForSwitch(k) && (ancilla_z[k] == 0 || ancilla_z[k] == 0xff))
dung_flag_somaria_block_switch++;
}
} else {
label_1:
if (flag_is_ancilla_to_pick_up == k + 1)
dung_flag_somaria_block_switch = 0;
}
}
uint16 old_y = Ancilla_LatchYCoordToZ(k);
uint8 s1a = ancilla_dir[k];
uint8 s1b = ancilla_objprio[k];
ancilla_objprio[k] = 0;
bool flag = Ancilla_CheckTileCollision_Class2(k);
if (player_is_indoors && ancilla_L[k] && ancilla_tile_attr[k] == 0x1c)
ancilla_T[k] = 1;
label1:
if (flag && (!(link_state_bits & 0x80) || link_picking_throw_state)) {
if (!s1b && !ancilla_arr4[k] && ancilla_z[k]) {
ancilla_arr4[k] = 1;
int qq = (ancilla_dir[k] == 1) ? 16 : 4;
if (ancilla_y_vel[k])
ancilla_y_vel[k] = sign8(ancilla_y_vel[k]) ? qq : -qq;
if (ancilla_x_vel[k])
ancilla_x_vel[k] = sign8(ancilla_x_vel[k]) ? 4 : -4;
if (ancilla_dir[k] == 1 && ancilla_z[k]) {
ancilla_y_vel[k] = -4;
ancilla_L[k] = 2;
}
}
} else if (!(link_state_bits & 0x80) && (ancilla_z[k] == 0 || ancilla_z[k] == 0xff)) {
ancilla_dir[k] = 16;
uint8 bak0 = ancilla_objprio[k];
Ancilla_CheckTileCollision(k);
ancilla_objprio[k] = bak0;
uint8 a = ancilla_tile_attr[k];
if (a == 0x26) {
flag = true;
goto label1;
} else if (a == 0xc || a == 0x1c) {
if (dung_hdr_collision != 3) {
if (ancilla_floor[k] == 0 && ancilla_z[k] != 0 && ancilla_z[k] != 0xff)
ancilla_floor[k] = 1;
} else {
old_y = Ancilla_GetY(k) + dung_floor_y_vel;
Ancilla_SetX(k, Ancilla_GetX(k) + dung_floor_x_vel);
}
} else if (a == 0x20 || (a & 0xf0) == 0xb0 && a != 0xb6 && a != 0xbc) {
if (!(link_state_bits & 0x80)) {
if (k + 1 == flag_is_ancilla_to_pick_up)
flag_is_ancilla_to_pick_up = 0;
if (!ancilla_timer[k]) {
if (link_speed_setting == 18) {
link_speed_setting = 0;
bitmask_of_dragstate = 0;
}
ancilla_type[k] = 0;
return;
}
}
} else if (a == 8) {
if (k + 1 == flag_is_ancilla_to_pick_up)
flag_is_ancilla_to_pick_up = 0;
if (ancilla_timer[k] == 0) {
Ancilla_SetY(k, Ancilla_GetY(k) - 24);
Ancilla_TransmuteToSplash(k);
return;
}
} else if (a == 0x68 || a == 0x69 || a == 0x6a || a == 0x6b) {
Ancilla_ApplyConveyor(k);
old_y = Ancilla_GetY(k);
} else {
ancilla_timer[k] = (ancilla_L[k] | ancilla_H[k]) ? 0 : 2;
}
}
// endif_3
s1b |= ancilla_objprio[k];
if (!(link_state_bits & 0x80) && !--ancilla_S[k]) {
ancilla_S[k] = 1;
ancilla_objprio[k] = 0;
if (Ancilla_CheckBasicSpriteCollision(k) >= 0) {
ancilla_S[k] = 7;
if (++ancilla_step[k] == 5) {
SomariaBlock_FizzleAway(k);
return;
}
}
}
Ancilla_SetY(k, old_y);
ancilla_dir[k] = s1a;
ancilla_objprio[k] = s1b;
AncillaDraw_SomariaBlock(k);
}
void AncillaDraw_SomariaBlock(int k) { // 88e61b
static const int8 kSomarianBlock_Draw_X[12] = {-8, 0, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static const int8 kSomarianBlock_Draw_Y[12] = {-8, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static const uint8 kSomarianBlock_Draw_Flags[12] = {0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0, 0, 0x40, 0x80, 0xc0};
if (k + 1 == flag_is_ancilla_to_pick_up && link_state_bits & 0x80 && ancilla_K[k] != 3 && link_direction_facing == 0) {
Ancilla_AllocateOamFromRegion_B_or_E(ancilla_numspr[k]);
} else if (sort_sprites_setting && ancilla_floor[k] && (ancilla_L[k] || k + 1 == flag_is_ancilla_to_pick_up && (link_state_bits & 0x80))) {
oam_cur_ptr = 0x8d0;
oam_ext_cur_ptr = 0xa20 + 0x34;
}
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr(), *oam_org = oam;
int z = (int8)ancilla_z[k];
if (z != 0 && z != -1 && ancilla_K[k] != 3 && ancilla_objprio[k])
oam_priority_value = 0x3000;
pt.y -= z;
int j = ancilla_arr1[k] * 4;
int r8 = 0;
do {
uint8 t = Ancilla_SetOam_XY_safe(oam, pt.x + kSomarianBlock_Draw_X[j], pt.y + kSomarianBlock_Draw_Y[j]);
oam->charnum = 0xe9;
oam->flags = kSomarianBlock_Draw_Flags[j] & ~0x30 | 2 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = t;
oam++;
} while (j++, ++r8 & 3);
if (SomarianBlock_CheckEmpty(oam_org)) {
dung_flag_somaria_block_switch = 0;
ancilla_type[k] = 0;
if (k + 1 == flag_is_ancilla_to_pick_up) {
flag_is_ancilla_to_pick_up = 0;
if (link_state_bits & 128)
link_state_bits = 0;
}
}
}
bool SomariaBlock_CheckForSwitch(int k) { // 88e75c
static const int8 kSomarianBlock_CheckCover_X[4] = {0, 0, -4, 4};
static const int8 kSomarianBlock_CheckCover_Y[4] = {-4, 4, 0, 0};
dung_flag_somaria_block_switch = 0;
ancilla_arr24[k] = 0;
for (int j = 3; j >= 0; j--) {
uint16 y = Ancilla_GetY(k) + kSomarianBlock_CheckCover_Y[j];
uint16 x = Ancilla_GetX(k) + kSomarianBlock_CheckCover_X[j];
uint8 bak = ancilla_objprio[k];
Ancilla_CheckTileCollision_targeted(k, x, y);
ancilla_objprio[k] = bak;
uint8 a = ancilla_tile_attr[k];
if (a == 0x23 || a == 0x24 || a == 0x25 || a == 0x3b)
ancilla_arr24[k]++;
}
return ancilla_arr24[k] != 4;
}
void SomariaBlock_FizzleAway(int k) { // 88e9b2
if (link_speed_setting == 18) {
bitmask_of_dragstate = 0;
link_speed_setting = 0;
}
dung_flag_somaria_block_switch = 0;
ancilla_type[k] = 0x2d;
ancilla_aux_timer[k] = 0;
ancilla_step[k] = 0;
ancilla_item_to_link[k] = 0;
ancilla_arr3[k] = 0;
ancilla_arr1[k] = 0;
ancilla_R[k] = 0;
if (k + 1 == flag_is_ancilla_to_pick_up) {
flag_is_ancilla_to_pick_up = 0;
link_state_bits &= 0x80;
}
Ancilla2D_SomariaBlockFizz(k);
}
void Ancilla2D_SomariaBlockFizz(int k) { // 88e9e8
static const int8 kSomariaBlockFizzle_X[6] = {-4, -1, -8, 0, -6, -2};
static const int8 kSomariaBlockFizzle_Y[6] = {-4, -1, -4, -4, -4, -4};
static const uint8 kSomariaBlockFizzle_Char[6] = {0x92, 0xff, 0xf9, 0xf9, 0xf9, 0xf9};
static const uint8 kSomariaBlockFizzle_Flags[6] = {6, 0xff, 0x86, 0xc6, 0x86, 0xc6};
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 3;
if (++ancilla_item_to_link[k] == 3) {
ancilla_type[k] = 0;
return;
}
}
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
uint8 z = ancilla_z[k];
if (z == 0xff)
z = 0;
int x = pt.x, y = pt.y - (int8)z;
int j = ancilla_item_to_link[k] * 2;
for (int i = 0; i < 2; i++, j++, oam++) {
if (kSomariaBlockFizzle_Char[j] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam, x + kSomariaBlockFizzle_X[j], y + kSomariaBlockFizzle_Y[j]);
oam->charnum = kSomariaBlockFizzle_Char[j];
oam->flags = kSomariaBlockFizzle_Flags[j] & ~0x30 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
}
}
}
void Ancilla39_SomariaPlatformPoof(int k) { // 88ea83
static const uint8 kSomarianPlatformPoof_Tab0[4] = {1, 0, 3, 2};
if (!sign8(--ancilla_aux_timer[k]))
return;
ancilla_type[k] = 0;
SpriteSpawnInfo info;
int x = Ancilla_GetX(k) & ~7 | 4, y = Ancilla_GetY(k) & ~7 | 4;
uint8 floor = ancilla_floor[k];
int j = Sprite_SpawnDynamically(k, 0xed, &info); // wtf
if (j >= 0) {
player_on_somaria_platform = 0;
Sprite_SetX(j, x);
Sprite_SetY(j, y);
int pos = ((x & 0x1f8) >> 3) + ((y & 0x1f8) << 3) + (floor >= 1 ? 0x1000 : 0);
int t = 0;
if ((dung_bg2_attr_table[pos + XY(0, -1)] & 0xf0) != 0xb0) {
t += 1;
if ((dung_bg2_attr_table[pos + XY(0, 1)] & 0xf0) != 0xb0) {
t += 1;
if ((dung_bg2_attr_table[pos + XY(-1, 0)] & 0xf0) != 0xb0) {
t += 1;
}
}
}
sprite_D[j] = kSomarianPlatformPoof_Tab0[t];
sprite_floor[j] = 0;
} else {
AncillaDraw_SomariaBlock(k);
}
}
void Ancilla2E_SomariaBlockFission(int k) { // 88eb3e
static const int8 kSomarianBlockDivide_X[16] = {-8, 0, -8, 0, -10, -10, 2, 2, -8, 0, -8, 0, -12, -12, 4, 4};
static const int8 kSomarianBlockDivide_Y[16] = {-10, -10, 2, 2, -8, 0, -8, 0, -12, -12, 4, 4, -8, 0, -8, 0};
static const uint8 kSomarianBlockDivide_Char[16] = {0xc6, 0xc6, 0xc6, 0xc6, 0xc4, 0xc4, 0xc4, 0xc4, 0xd2, 0xd2, 0xd2, 0xd2, 0xc5, 0xc5, 0xc5, 0xc5};
static const uint8 kSomarianBlockDivide_Flags[16] = {0xc6, 0x86, 0x46, 6, 0x46, 0xc6, 6, 0x86, 0xc6, 0x86, 0x46, 6, 0x46, 0xc6, 6, 0x86};
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 3;
if (++ancilla_item_to_link[k] == 2) {
ancilla_type[k] = 0;
SomariaBlock_SpawnBullets(k);
return;
}
}
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr(), *oam_org = oam;
int8 z = ancilla_z[k] + (ancilla_K[k] == 3 && BYTE(link_z_coord) != 0xff ? BYTE(link_z_coord) : 0);
int j = ancilla_item_to_link[k] * 8;
for (int i = 0; i != 8; i++, j++, oam++) {
uint8 ext = Ancilla_SetOam_XY(oam, pt.x + kSomarianBlockDivide_X[j], pt.y + kSomarianBlockDivide_Y[j] - z);
oam->charnum = kSomarianBlockDivide_Char[j];
oam->flags = kSomarianBlockDivide_Flags[j] & ~0x30 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
}
}
void Ancilla2F_LampFlame(int k) { // 88ec13
static const uint8 kLampFlame_Draw_Char[12] = {0x9c, 0x9c, 0xff, 0xff, 0xa4, 0xa5, 0xb2, 0xb3, 0xe3, 0xf3, 0xff, 0xff};
static const int8 kLampFlame_Draw_Y[12] = {-3, 0, 0, 0, 0, 0, 8, 8, 0, 8, 0, 0};
static const int8 kLampFlame_Draw_X[12] = {4, 10, 0, 0, 1, 9, 2, 7, 4, 4, 0, 0};
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
if (!ancilla_timer[k]) {
ancilla_type[k] = 0;
return;
}
int j = (ancilla_timer[k] & 0xf8) >> 1;
do {
if (kLampFlame_Draw_Char[j] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam, pt.x + kLampFlame_Draw_X[j], pt.y + kLampFlame_Draw_Y[j]);
oam->charnum = kLampFlame_Draw_Char[j];
oam->flags = HIBYTE(oam_priority_value) | 2;
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
}
} while (++j & 3);
}
void Ancilla41_WaterfallSplash(int k) { // 88ecaf
if (!Ancilla_CheckForEntranceTrigger(player_is_indoors ? 0 : 1)) {
ancilla_type[k] = 0;
return;
}
if (!submodule_index && !(frame_counter & 7))
Ancilla_Sfx2_Near(0x1c);
draw_water_ripples_or_grass = 1;
if (!sign8(link_animation_steps - 6))
link_animation_steps -= 6;
if (!ancilla_timer[k]) {
ancilla_timer[k] = 2;
ancilla_item_to_link[k] = (ancilla_item_to_link[k] + 1) & 3;
}
if (player_is_indoors && BYTE(link_y_coord) < 0x38) {
Ancilla_SetY(k, 0xd38);
} else {
Ancilla_SetY(k, link_y_coord);
}
Ancilla_SetX(k, link_x_coord);
static const int8 kWaterfallSplash_X[8] = {0, 0, -4, 4, -7, 7, -9, 17};
static const int8 kWaterfallSplash_Y[8] = {-4, 0, -5, -5, -3, -3, 12, 12};
static const uint8 kWaterfallSplash_Char[8] = {0xc0, 0xff, 0xac, 0xac, 0xae, 0xae, 0xbf, 0xbf};
static const uint8 kWaterfallSplash_Flags[8] = {0x84, 0xff, 0x84, 0xc4, 0x84, 0xc4, 0x84, 0xc4};
static const uint8 kWaterfallSplash_Ext[8] = {2, 0xff, 2, 2, 2, 2, 0, 0};
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
uint8 z = link_z_coord;
pt.y -= (sign8(z) ? 0 : z);
int j = ancilla_item_to_link[k] * 2;
for (int i = 0; i != 2; i++, j++, oam++) {
if (kWaterfallSplash_Char[j] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam, pt.x + kWaterfallSplash_X[j], pt.y + kWaterfallSplash_Y[j]);
oam->charnum = kWaterfallSplash_Char[j];
oam->flags = kWaterfallSplash_Flags[j] | 0x30;
bytewise_extended_oam[oam - oam_buf] = ext | kWaterfallSplash_Ext[j];
}
}
}
void Ancilla24_Gravestone(int k) { // 88ee01
static const uint8 kAncilla_Gravestone_Char[4] = {0xc8, 0xc8, 0xd8, 0xd8};
static const uint8 kAncilla_Gravestone_Flags[4] = {0, 0x40, 0, 0x40};
Point16U pt;
Ancilla_PrepAdjustedOamCoord(k, &pt);
Oam_AllocateFromRegionB(16);
OamEnt *oam = GetOamCurPtr();
uint16 x = pt.x, y = pt.y;
for (int i = 0; i < 4; i++, oam++) {
uint8 ext = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = kAncilla_Gravestone_Char[i];
oam->flags = kAncilla_Gravestone_Flags[i] | 0x3d;
bytewise_extended_oam[oam - oam_buf] = ext | 2;
x += 16;
if (i == 1)
x -= 32, y += 8;
}
}
void Ancilla34_SkullWoodsFire(int k) { // 88ef9a
static const int8 kSkullWoodsFire_Draw_Y[4] = {0, 0, 0, -3};
static const uint8 kSkullWoodsFire_Draw_Char[4] = {0x8e, 0xa0, 0xa2, 0xa4};
static const uint8 kSkullWoodsFire_Draw_Ext[4] = {2, 2, 2, 0};
static const int8 kSkullWoodsFire_Draw2_X[24] = {
-13, -21, -10, -1, -1, -1, -16, -27, -4, -16, -6, -25, -16, -27, -4, -16,
-6, -25, -13, -5, -27, -11, -22, -3,
};
static const int8 kSkullWoodsFire_Draw2_Y[24] = {
-31, -24, -22, -1, -1, -1, -37, -32, -32, -23, -16, -14, -37, -32, -32, -23,
-16, -14, -35, -29, -28, -20, -13, -11,
};
static const uint8 kSkullWoodsFire_Draw2_Char[24] = {
0x86, 0x86, 0x86, 0xff, 0xff, 0xff, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x8a, 0x8a, 0x8a, 0x8a,
0x8a, 0x8a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
};
static const uint8 kSkullWoodsFire_Draw2_Flags[24] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0x80, 0x40, 0x40, 0x80, 0x40, 0,
};
static const uint8 kSkullWoodsFire_Draw2_Ext[24] = {
2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 0, 0, 0, 0, 0, 0,
};
if (skullwoodsfire_var4 && ancilla_item_to_link[k] != 4 && sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 5;
ancilla_item_to_link[k]++;
}
OamEnt *oam = GetOamCurPtr();
for(int k = 3; k >= 0; k--) {
if (sign8(--skullwoodsfire_var5[k])) {
skullwoodsfire_var5[k] = 5;
if (skullwoodsfire_var0[k] == 128)
goto endif_2;
if (++skullwoodsfire_var0[k] != 0) {
if (skullwoodsfire_var0[k] != 4)
goto endif_2;
skullwoodsfire_var0[k] = 0;
}
skullwoodsfire_var9 -= 8;
if (skullwoodsfire_var9 < 200 && skullwoodsfire_var4 != 1) {
skullwoodsfire_var4 = 1;
sound_effect_1 = kBombos_Sfx[(uint8)(0x98 - BG2HOFS_copy2) >> 5] | 0xc;
}
if (skullwoodsfire_var9 < 168)
skullwoodsfire_var0[k] = 128;
skullwoodsfire_x_arr[k] = skullwoodsfire_var11;
skullwoodsfire_y_arr[k] = skullwoodsfire_var9;
if (sound_effect_1 == 0)
sound_effect_1 = kBombos_Sfx[(uint8)(skullwoodsfire_var11 - BG2HOFS_copy2) >> 5] | 0x2a;
}
endif_2:
if (!sign8(skullwoodsfire_var0[k])) {
int j = skullwoodsfire_var0[k];
uint16 x = skullwoodsfire_x_arr[k] - BG2HOFS_copy2;
uint16 y = skullwoodsfire_y_arr[k] - BG2VOFS_copy2 + kSkullWoodsFire_Draw_Y[j];
uint8 ext2 = Ancilla_SetOam_XY(oam, x, y);
oam->charnum = kSkullWoodsFire_Draw_Char[j];
oam->flags = 0x32;
uint8 ext = kSkullWoodsFire_Draw_Ext[j];
bytewise_extended_oam[oam - oam_buf] = ext | ext2;
oam++;
if (kSkullWoodsFire_Draw_Ext[j] != 2) {
uint8 ext2 = Ancilla_SetOam_XY(oam, x + 8, y);
oam->charnum = kSkullWoodsFire_Draw_Char[j] + 1;
oam->flags = 0x32;
bytewise_extended_oam[oam - oam_buf] = ext | ext2;
oam++;
}
}
}
for (int i = 3; sign8(skullwoodsfire_var0[i]); ) {
if (--i < 0) {
ancilla_type[k] = 0;
return;
}
}
if (skullwoodsfire_var4 == 0 || ancilla_item_to_link[k] == 4)
return;
int j = ancilla_item_to_link[k] * 6;
for (int i = 0; i < 6; i++, j++) {
if (kSkullWoodsFire_Draw2_Char[j] != 0xff) {
uint8 ext = Ancilla_SetOam_XY(oam,
168 - BG2HOFS_copy2 + kSkullWoodsFire_Draw2_X[j],
200 - BG2VOFS_copy2 + kSkullWoodsFire_Draw2_Y[j]);
oam->charnum = kSkullWoodsFire_Draw2_Char[j];
oam->flags = kSkullWoodsFire_Draw2_Flags[j] | 0x32;
bytewise_extended_oam[oam - oam_buf] = ext | kSkullWoodsFire_Draw2_Ext[j];
oam++;
}
}
}
void Ancilla3A_BigBombExplosion(int k) { // 88f18d
static const int8 kSuperBombExplode_X[9] = {0, -16, 0, 16, -24, 24, -16, 0, 16};
static const int8 kSuperBombExplode_Y[9] = {0, -16, -24, -16, 0, 0, 16, 24, 16};
if (!submodule_index && !--ancilla_arr3[k]) {
if (++ancilla_item_to_link[k] == 2)
Ancilla_Sfx2_Pan(k, 0xc);
if (ancilla_item_to_link[k] == 11) {
ancilla_type[k] = 0;
return;
}
ancilla_arr3[k] = kBomb_Tab0[ancilla_item_to_link[k]];
}
oam_priority_value = 0x3000;
uint8 numframes = kBomb_Draw_Tab2[ancilla_item_to_link[k]];
int j = kBomb_Draw_Tab0[ancilla_item_to_link[k]] * 6;
ancilla_step[k] = j * 2;
int yy = 0;
for (int i = 8; i >= 0; i--) {
uint16 x = Ancilla_GetX(k) + kSuperBombExplode_X[i] - BG2HOFS_copy2;
uint16 y = Ancilla_GetY(k) + kSuperBombExplode_Y[i] - BG2VOFS_copy2;
if (x < 256 && y < 256) {
Ancilla_AllocateOamFromRegion_A_or_D_or_F((uint8)(j * 2), 0x18); // wtf
OamEnt *oam = GetOamCurPtr() + yy;
yy += AncillaDraw_Explosion(oam, j, 0, numframes, 0x32, x, y) - oam;
}
}
if (ancilla_item_to_link[k] == 3 && ancilla_arr3[k] == 1) {
Bomb_CheckForDestructibles(Ancilla_GetX(k), Ancilla_GetY(k), 0); // r14?
follower_indicator = 0;
}
}
void RevivalFairy_Main() { // 88f283
static const uint8 kAncilla_RevivalFaerie_Tab0[2] = {0, 0x90};
static const uint8 kAncilla_RevivalFaerie_Tab1[5] = {0x4b, 0x4d, 0x49, 0x47, 0x49};
int k = 0;
switch (ancilla_step[k]) {
case 0:
if (!--ancilla_arr3[k]) {
ancilla_arr3[k] = kAncilla_RevivalFaerie_Tab0[++ancilla_step[k]];
ancilla_K[k] = 0;
ancilla_z_vel[k] = 0;
} else {
Ancilla_MoveZ(k);
}
break;
case 1:
if (!--ancilla_arr3[k]) {
ancilla_step[k]++;
ancilla_z_vel[k] = 0;
ancilla_x_vel[k] = 0;
} else {
if (ancilla_arr3[k] == 0x4f || ancilla_arr3[k] == 0x8f) {
ancilla_L[k]++;
Ancilla_Sfx2_Pan(k, 0x31);
}
if (ancilla_L[k] != 0 && sign8(--ancilla_G[k])) {
ancilla_G[k] = 5;
if (++ancilla_item_to_link[k] == 3) {
ancilla_item_to_link[k] = 0;
ancilla_L[k] = 0;
}
}
ancilla_z_vel[k] += ancilla_K[k] ? 1 : -1;
if (abs8(ancilla_z_vel[k]) == 8)
ancilla_K[k] ^= 1;
Ancilla_MoveZ(k);
}
break;
case 2:
if (ancilla_z_vel[k] < 24)
ancilla_z_vel[k] += 1;
if (ancilla_x_vel[k] < 16)
ancilla_x_vel[k] += 1;
Ancilla_MoveX(k);
Ancilla_MoveZ(k);
break;
case 3:
goto skip_draw;
}
{
Oam_AllocateFromRegionC(12);
Point16U pt;
Ancilla_PrepOamCoord(k, &pt);
OamEnt *oam = GetOamCurPtr();
int t = (ancilla_step[k] == 1 && ancilla_L[k]) ? ancilla_item_to_link[k] + 1 : 0;
uint8 ext = Ancilla_SetOam_XY(oam, pt.x, pt.y - (int8)ancilla_z[k]);
if (t != 0)
t += 1;
else
t = (frame_counter >> 2) & 1;
oam->charnum = kAncilla_RevivalFaerie_Tab1[t];
oam->flags = 0x74;
bytewise_extended_oam[oam - oam_buf] = ext | 2;
if (oam->y == 0xf0) {
ancilla_step[k] = 3;
submodule_index++;
TM_copy = mapbak_TM;
}
}
skip_draw:
RevivalFairy_Dust();
RevivalFairy_MonitorHP();
}
void RevivalFairy_Dust() { // 88f3cf
int k = 2;
if (ancilla_step[0] == 0 || ancilla_step[k] == 2 || !sign8(--ancilla_arr3[k]))
return;
ancilla_arr3[k] = 0;
if (!sort_sprites_setting)
Oam_AllocateFromRegionA(16);
else
Oam_AllocateFromRegionD(16);
if (sign8(--ancilla_aux_timer[k])) {
ancilla_aux_timer[k] = 3;
if (ancilla_item_to_link[k] == 9) {
ancilla_arr3[k] = 32;
ancilla_step[k]++;
ancilla_item_to_link[k] = 2;
return;
}
ancilla_arr25[k] = kMagicPowder_Tab0[30 + ++ancilla_item_to_link[k]];
}
Ancilla_MagicPowder_Draw(k);
}
void RevivalFairy_MonitorHP() { // 88f430
if ((link_health_current == link_health_capacity || link_health_current == 0x38) && !is_doing_heart_animation) {
if (link_is_in_deep_water) {
link_some_direction_bits = 4;
link_player_handler_state = kPlayerState_Swimming;
} else if (link_is_bunny) {
link_player_handler_state = kPlayerState_PermaBunny;
link_is_bunny_mirror = 1;
} else {
link_player_handler_state = kPlayerState_Ground;
}
link_auxiliary_state = 0;
player_unk1 = 0;
link_var30d = 0;
some_animation_timer_steps = 0;
BYTE(link_z_coord) = 0;
link_incapacitated_timer = 0;
for(int i = 0; i < 5; i++)
ancilla_type[i] = 0;
return;
}
int k = 1;
if (!ancilla_step[k]) {
if (!--ancilla_arr3[k]) {
ancilla_arr3[k]++;
ancilla_z_vel[k] = 4;
Ancilla_MoveZ(k);
if (ancilla_z[k] >= 16) {
ancilla_step[k]++;
ancilla_z_vel[k] = 2;
}
}
} else {
if (sign8(--ancilla_K[k])) {
ancilla_K[k] = 32;
ancilla_z_vel[k] = -ancilla_z_vel[k];
}
Ancilla_MoveZ(k);
}
BYTE(link_z_coord) = ancilla_z[k];
}
void GameOverText_Draw() { // 88f5c4
static const uint8 kGameOverText_Chars[16] = {0x40, 0x50, 0x41, 0x51, 0x42, 0x52, 0x43, 0x53, 0x44, 0x54, 0x45, 0x55, 0x43, 0x53, 0x46, 0x56};
oam_cur_ptr = 0x800;
oam_ext_cur_ptr = 0xa20;
OamEnt *oam = GetOamCurPtr();
int k = flag_for_boomerang_in_place;
do {
uint8 ext = Ancilla_SetOam_XY(oam, Ancilla_GetX(k), 0x57);
oam->charnum = kGameOverText_Chars[k * 2 + 0];
oam->flags = 0x3c;
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
ext = Ancilla_SetOam_XY(oam, Ancilla_GetX(k), 0x5f);
oam->charnum = kGameOverText_Chars[k * 2 + 1];
oam->flags = 0x3c;
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
} while (--k >= 0);
}
int AncillaAdd_AddAncilla_Bank08(uint8 type, uint8 y) { // 88f631
int k = Ancilla_AllocInit(type, y);
if (k >= 0) {
ancilla_type[k] = type;
ancilla_numspr[k] = kAncilla_Pflags[type];
ancilla_floor[k] = link_is_on_lower_level;
ancilla_floor2[k] = link_is_on_lower_level_mirror;
ancilla_y_vel[k] = 0;
ancilla_x_vel[k] = 0;
ancilla_objprio[k] = 0;
ancilla_U[k] = 0;
}
return k;
}
void Ancilla_PrepOamCoord(int k, Point16U *info) { // 88f671
oam_priority_value = kTagalongLayerBits[ancilla_floor[k]] << 8;
info->x = Ancilla_GetX(k) - BG2HOFS_copy2;
info->y = Ancilla_GetY(k) - BG2VOFS_copy2;
}
void Ancilla_PrepAdjustedOamCoord(int k, Point16U *info) { // 88f6a4
oam_priority_value = kTagalongLayerBits[ancilla_floor[k]] << 8;
info->x = Ancilla_GetX(k) - BG2HOFS_copy;
info->y = Ancilla_GetY(k) - BG2VOFS_copy;
}
uint8 Ancilla_SetOam_XY(OamEnt *oam, uint16 x, uint16 y) { // 88f6e1
uint8 rv = 0;
uint8 yval = 0xf0;
int xt = enhanced_features0 ? 0x40 : 0;
if ((uint16)(x + xt) < 256 + xt * 2 && y < 256) {
rv = (x >> 8) & 1;
oam->x = x;
if (y < 0xf0)
yval = y;
}
oam->y = yval;
return rv;
}
uint8 Ancilla_SetOam_XY_safe(OamEnt *oam, uint16 x, uint16 y) { // 88f702
uint8 rv = 0;
oam->x = x;
if ((uint16)(x + 0x80) < 0x180) {
rv = (x >> 8) & 1;
oam->y = y;
if ((uint16)(y + 0x10) < 0x100)
return rv;
}
oam->y = 0xf0;
return rv;
}
bool Ancilla_CheckLinkCollision(int k, int j, CheckPlayerCollOut *out) { // 88f76b
static const int16 kAncilla_Coll_Yoffs[5] = {0, 8, 8, 8, 0};
static const int16 kAncilla_Coll_Xoffs[5] = {0, 8, 8, 8, 0};
static const int16 kAncilla_Coll_H[5] = {20, 20, 8, 28, 14};
static const int16 kAncilla_Coll_W[5] = {20, 3, 8, 24, 14};
static const int16 kAncilla_Coll_LinkYoffs[5] = {12, 12, 12, 12, 12};
static const int16 kAncilla_Coll_LinkXoffs[5] = {8, 8, 8, 12, 8};
uint16 x = Ancilla_GetX(k), y = Ancilla_GetY(k);
y += kAncilla_Coll_Yoffs[j] + (int8)ancilla_z[k];
x += kAncilla_Coll_Xoffs[j];
out->r4 = link_y_coord + kAncilla_Coll_LinkYoffs[j] - y;
out->r8 = abs16(out->r4);
out->r6 = link_x_coord + kAncilla_Coll_LinkXoffs[j] - x;
out->r10 = abs16(out->r6);
return out->r8 < kAncilla_Coll_H[j] && out->r10 < kAncilla_Coll_W[j];
}
bool Hookshot_CheckProximityToLink(int x, int y) { // 88f7dc
return abs16(link_y_coord - BG2VOFS_copy2 + 12 - y - 4) < 12 &&
abs16(link_x_coord - BG2HOFS_copy2 + 8 - x - 4) < 12;
}
bool Ancilla_CheckForEntranceTrigger(int what) { // 88f844
static const uint16 kEntranceTrigger_BaseY[4] = {0xd40, 0x210, 0xcfc, 0x100};
static const uint16 kEntranceTrigger_BaseX[4] = {0xd80, 0xe68, 0x130, 0xf10};
static const uint8 kEntranceTrigger_SizeY[4] = {11, 32, 16, 12};
static const uint8 kEntranceTrigger_SizeX[4] = {16, 16, 16, 16};
return
abs16(link_y_coord + 12 - kEntranceTrigger_BaseY[what]) < kEntranceTrigger_SizeY[what] &&
abs16(link_x_coord + 8 - kEntranceTrigger_BaseX[what]) < kEntranceTrigger_SizeX[what];
}
void AncillaDraw_Shadow(OamEnt *oam, int k, int x, int y, uint8 pal) { // 88f897
static const uint8 kAncilla_DrawShadow_Char[14] = {0x6c, 0x6c, 0x28, 0x28, 0x38, 0xff, 0xc8, 0xc8, 0xd8, 0xd8, 0xd9, 0xd9, 0xda, 0xda};
static const uint8 kAncilla_DrawShadow_Flags[14] = {0x28, 0x68, 0x28, 0x68, 0x28, 0xff, 0x22, 0x22, 0x24, 0x64, 0x24, 0x64, 0x24, 0x64};
if (k == 2)
x += 4;
uint8 ext = Ancilla_SetOam_XY_safe(oam, x, y);
oam->charnum = kAncilla_DrawShadow_Char[k * 2];
oam->flags = kAncilla_DrawShadow_Flags[k * 2] & ~0x30 | pal;
bytewise_extended_oam[oam - oam_buf] = ext;
oam++;
uint8 ch = kAncilla_DrawShadow_Char[k * 2 + 1];
if (ch != 0xff) {
x += 8;
ext = Ancilla_SetOam_XY_safe(oam, x, y);
oam->charnum = ch;
oam->flags = kAncilla_DrawShadow_Flags[k * 2 + 1] & ~0x30 | pal;
bytewise_extended_oam[oam - oam_buf] = ext;
}
}
void Ancilla_AllocateOamFromRegion_B_or_E(uint8 size) { // 88f90a
if (!sort_sprites_setting)
Oam_AllocateFromRegionB(size);
else
Oam_AllocateFromRegionE(size);
}
OamEnt *Ancilla_AllocateOamFromCustomRegion(OamEnt *oam) { // 88f9ba
int a = (uint8 *)oam - g_ram;
if (sort_sprites_setting) {
if (a < 0x900) {
if (a < 0x8e0)
return oam;
a = 0x820;
} else {
if (a < 0x9d0)
return oam;
a = 0x940;
}
} else {
if (a < 0x990)
return oam;
a = 0x820;
}
oam_cur_ptr = a;
oam_ext_cur_ptr = ((a - 0x800) >> 2) + 0xa20;
return GetOamCurPtr();
}
OamEnt *HitStars_UpdateOamBufferPosition(OamEnt *oam) { // 88fa00
int a = (uint8 *)oam - g_ram;
if (!sort_sprites_setting && a >= 0x9d0) {
oam_cur_ptr = 0x820;
oam_ext_cur_ptr = 0xa20 + (0x20 >> 2);
oam = GetOamCurPtr();
}
return oam;
}
bool Hookshot_ShouldIEvenBotherWithTiles(int k) { // 88fa2d
uint16 x = Ancilla_GetX(k), y = Ancilla_GetY(k);
if (!player_is_indoors) {
if (!(ancilla_dir[k] & 2)) {
uint16 t = y - kOverworld_OffsetBaseY[BYTE(current_area_of_player) >> 1];
return (t < 4) || (t >= overworld_right_bottom_bound_for_scroll);
} else {
uint16 t = x - kOverworld_OffsetBaseX[BYTE(current_area_of_player) >> 1];
return (t < 6) || (t >= overworld_right_bottom_bound_for_scroll);
}
}
if (!(ancilla_dir[k] & 2)) {
return (y & 0x1ff) < 4 || (y & 0x1ff) >= 0x1e8 || (y & 0x200) != (link_y_coord & 0x200);
} else {
return (x & 0x1ff) < 4 || (x & 0x1ff) >= 0x1f0 || (x & 0x200) != (link_x_coord & 0x200);
}
}
AncillaRadialProjection Ancilla_GetRadialProjection(uint8 a, uint8 r8) { // 88fadd
static const uint8 kRadialProjection_Tab0[64] = {
255, 254, 251, 244, 236, 225, 212, 197, 181, 162, 142, 120, 97, 74, 49, 25,
0, 25, 49, 74, 97, 120, 142, 162, 181, 197, 212, 225, 236, 244, 251, 254,
255, 254, 251, 244, 236, 225, 212, 197, 181, 162, 142, 120, 97, 74, 49, 25,
0, 25, 49, 74, 97, 120, 142, 162, 181, 197, 212, 225, 236, 244, 251, 254,
};
static const uint8 kRadialProjection_Tab2[64] = {
0, 25, 49, 74, 97, 120, 142, 162, 181, 197, 212, 225, 236, 244, 251, 254,
255, 254, 251, 244, 236, 225, 212, 197, 181, 162, 142, 120, 97, 74, 49, 25,
0, 25, 49, 74, 97, 120, 142, 162, 181, 197, 212, 225, 236, 244, 251, 254,
255, 254, 251, 244, 236, 225, 212, 197, 181, 162, 142, 120, 97, 74, 49, 25,
};
static const uint8 kRadialProjection_Tab1[64] = {
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,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
static const uint8 kRadialProjection_Tab3[64] = {
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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
AncillaRadialProjection rv;
int p0 = kRadialProjection_Tab0[a] * r8;
int p1 = kRadialProjection_Tab2[a] * r8;
rv.r0 = (p0 >> 8) + (p0 >> 7 & 1);
rv.r2 = kRadialProjection_Tab1[a];
rv.r4 = (p1 >> 8) + (p1 >> 7 & 1);
rv.r6 = kRadialProjection_Tab3[a];
return rv;
}
int Ancilla_AllocateOamFromRegion_A_or_D_or_F(int k, uint8 size) { // 88fb2b
if (sort_sprites_setting) {
if (ancilla_floor[k])
return Oam_AllocateFromRegionF(size);
else
return Oam_AllocateFromRegionD(size);
} else {
return Oam_AllocateFromRegionA(size);
}
}
void Ancilla_AddHitStars(uint8 a, uint8 y) { // 898024
static const int8 kShovelHitStars_XY[12] = {21, -11, 21, 11, 3, -6, 21, 5, 16, -14, 16, 14};
static const int8 kShovelHitStars_X2[6] = {-3, 19, 2, 13, -6, 22};
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 2;
ancilla_arr3[k] = 1;
ancilla_y_vel[k] = 0;
ancilla_x_vel[k] = 0;
int j = a;
if (link_item_in_hand) {
j = (link_direction_facing >> 1) + 2;
} else if (link_position_mode) {
j = link_direction_facing != 4 ? 1 : 0;
}
ancilla_step[k] = j;
int t = link_x_coord + kShovelHitStars_X2[j];
ancilla_A[k] = t;
ancilla_B[k] = t >> 8;
Ancilla_SetXY(k, link_x_coord + kShovelHitStars_XY[j * 2 + 1], link_y_coord + kShovelHitStars_XY[j * 2 + 0]);
}
}
void AncillaAdd_Blanket(uint8 a) { // 898091
int k = 0;
ancilla_type[k] = a;
ancilla_numspr[k] = kAncilla_Pflags[a];
ancilla_floor[k] = link_is_on_lower_level;
ancilla_floor2[k] = link_is_on_lower_level_mirror;
ancilla_objprio[k] = 0;
Ancilla_SetXY(k, 0x938, 0x2162);
}
void AncillaAdd_Snoring(uint8 a, uint8 y) { // 8980c8
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_y_vel[k] = -8;
ancilla_aux_timer[k] = 7;
ancilla_x_vel[k] = 8;
ancilla_step[k] = 255;
Ancilla_SetXY(k, link_x_coord + 16, link_y_coord + 4);
}
}
void AncillaAdd_Bomb(uint8 a, uint8 y) { // 89811f
static const int8 kBomb_Place_X0[4] = {8, 8, 0, 16};
static const int8 kBomb_Place_Y0[4] = {0, 24, 12, 12};
static const int8 kBomb_Place_X1[4] = {8, 8, -6, 22};
static const int8 kBomb_Place_Y1[4] = {4, 28, 12, 12};
int k = Ancilla_AddAncilla(a, y);
if (k < 0)
return;
if (link_item_bombs == 0) {
ancilla_type[k] = 0;
return;
}
if (--link_item_bombs == 0)
Hud_RefreshIcon();
ancilla_R[k] = 0;
ancilla_step[k] = 0;
ancilla_item_to_link[k] = 0;
ancilla_L[k] = 0;
ancilla_arr3[k] = kBomb_Tab0[0];
// These are not used directly by bombs, but used by door debris
ancilla_arr25[k] = 0;
ancilla_arr26[k] = 7;
ancilla_z[k] = 0;
ancilla_timer[k] = 8;
ancilla_dir[k] = link_direction_facing >> 1;
ancilla_T[k] = 0;
ancilla_arr23[k] = 0;
ancilla_arr22[k] = 0;
if (Ancilla_CheckInitialTileCollision_Class2(k)) {
int j = link_direction_facing >> 1;
Ancilla_SetXY(k, link_x_coord + kBomb_Place_X0[j], link_y_coord + kBomb_Place_Y0[j]);
} else {
int j = link_direction_facing >> 1;
Ancilla_SetXY(k, link_x_coord + kBomb_Place_X1[j], link_y_coord + kBomb_Place_Y1[j]);
}
sound_effect_1 = Link_CalculateSfxPan() | 0xb;
}
uint8 AncillaAdd_Boomerang(uint8 a, uint8 y) { // 89820f
static const uint8 kBoomerang_Tab0[4] = {0x20, 0x18, 0x30, 0x28};
static const uint8 kBoomerang_Tab1[2] = {0x20, 0x60};
static const uint8 kBoomerang_Tab2[2] = {3, 2};
static const uint8 kBoomerang_Tab3[4] = {8, 4, 2, 1};
static const uint8 kBoomerang_Tab4[8] = {8, 4, 2, 1, 9, 5, 10, 6};
static const uint8 kBoomerang_Tab5[8] = {2, 3, 3, 2, 2, 3, 3, 3};
static const int8 kBoomerang_Tab6[8] = {-10, -8, -9, -9, -10, -8, -9, -9};
static const int8 kBoomerang_Tab7[8] = {-10, 11, 8, -8, -10, 11, 8, -8};
static const int8 kBoomerang_Tab8[8] = {-16, 6, 0, 0, -8, 8, -8, 8};
static const int8 kBoomerang_Tab9[8] = {0, 0, -8, 8, 8, 8, -8, -8};
int k = Ancilla_AddAncilla(a, y);
if (k < 0)
return 0;
ancilla_aux_timer[k] = 0;
ancilla_item_to_link[k] = 0;
ancilla_K[k] = 0;
ancilla_z[k] = 0;
ancilla_L[k] = ancilla_numspr[k];
flag_for_boomerang_in_place = 1;
int j = link_item_boomerang - 1;
ancilla_G[k] = j;
ancilla_step[k] = kBoomerang_Tab1[j];
ancilla_arr3[k] = kBoomerang_Tab2[j];
int s = ancilla_G[k] * 2 + ((joypad1H_last & 0xc) && (joypad1H_last & 3) ? 1 : 0);
uint8 r0 = kBoomerang_Tab0[s];
ancilla_H[k] = r0;
uint8 r1 = (joypad1H_last & 0xf) ? (joypad1H_last & 0xf) : kBoomerang_Tab3[link_direction_facing >> 1];
hookshot_effect_index = 0;
if (r1 & 0xc) {
ancilla_y_vel[k] = r1 & 8 ? -r0 : r0;
int i = sign8(ancilla_y_vel[k]) ? 0 : 1;
ancilla_dir[k] = i;
hookshot_effect_index = kBoomerang_Tab3[i];
}
ancilla_S[k] = 0;
if (r1 & 3) {
if (!(r1 & 2))
ancilla_S[k] = 1;
ancilla_x_vel[k] = (r1 & 2) ? -r0 : r0;
int i = sign8(ancilla_x_vel[k]) ? 2 : 3;
ancilla_dir[k] = i;
hookshot_effect_index |= kBoomerang_Tab3[i];
}
j = FindInByteArray(kBoomerang_Tab4, r1, 8);
if (j < 0)
j = 0;
ancilla_arr1[k] = kBoomerang_Tab5[j];
ancilla_arr23[k] = j << 1;
if (button_b_frames >= 9) {
ancilla_aux_timer[k]++;
} else {
if (s || !(joypad1H_last & 0xf))
j = link_direction_facing >> 1;
}
s = Ancilla_CheckInitialTile_A(k);
if (s < 0) {
if (ancilla_aux_timer[k]) {
Ancilla_SetXY(k, link_x_coord + kBoomerang_Tab9[j], link_y_coord + 8 + kBoomerang_Tab8[j]);
} else {
Ancilla_SetXY(k, link_x_coord + kBoomerang_Tab7[j], link_y_coord + 8 + kBoomerang_Tab6[j]);
}
} else {
ancilla_type[k] = 0;
flag_for_boomerang_in_place = 0;
if (ancilla_tile_attr[k] != 0xf0) {
sound_effect_1 = Ancilla_CalculateSfxPan(k) | 5;
} else {
sound_effect_1 = Ancilla_CalculateSfxPan(k) | 6;
}
AncillaAdd_BoomerangWallClink(k);
}
return s;
}
void AncillaAdd_TossedPondItem(uint8 a, uint8 xin, uint8 yin) { // 898a32
static const uint8 kWishPondItem_X[76] = {
4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 5, 0, 0, 0,
0, 0, 0, 4, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 11, 0, 0, 0, 2, 0, 5, 0, 0, 0, 0, 0,
0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0,
};
static const int8 kWishPondItem_Y[76] = {
-13, -13, -13, -13, -13, -12, -12, -13, -13, -12, -12, -12, -10, -12, -12, -12,
-12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12,
-12, -12, -12, -13, -12, -12, -12, -12, -12, -12, -10, -12, -12, -12, -12, -12,
-12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, -12,
-12, -12, -12, -12, -12, -12, -12, -12, -12, -13, -12, -12,
};
link_receiveitem_index = xin;
int k = Ancilla_AddAncilla(a, yin);
if (k >= 0) {
sound_effect_2 = Link_CalculateSfxPan() | 0x13;
uint8 sb = kReceiveItemGfx[xin];
if (sb != 0xff) {
if (sb == 0x20)
DecompressShieldGraphics();
DecodeAnimatedSpriteTile_variable(sb);
} else {
DecodeAnimatedSpriteTile_variable(0);
}
if (sb == 6)
DecompressSwordGraphics();
link_state_bits = 0x80;
link_picking_throw_state = 0;
link_direction_facing = 0;
link_animation_steps = 0;
ancilla_z_vel[k] = 20;
ancilla_y_vel[k] = -40;
ancilla_x_vel[k] = 0;
ancilla_z[k] = 0;
ancilla_timer[k] = 16;
ancilla_item_to_link[k] = link_receiveitem_index;
int j = link_receiveitem_index;
Ancilla_SetXY(k,
link_x_coord + kWishPondItem_X[link_receiveitem_index],
link_y_coord + kWishPondItem_Y[link_receiveitem_index]);
}
}
void AddHappinessPondRupees(uint8 arg) { // 898ae0
int k = Ancilla_AddAncilla(0x42, 9);
if (k < 0)
return;
sound_effect_2 = Link_CalculateSfxPan() | 0x13;
uint8 sb = kReceiveItemGfx[0x35];
DecodeAnimatedSpriteTile_variable(sb);
link_state_bits = 0x80;
link_picking_throw_state = 0;
link_direction_facing = 0;
link_animation_steps = 0;
memset(happiness_pond_arr1, 0, 10);
static const int8 kHappinessPond_Start[4] = {0, 4, 4, 9};
static const int8 kHappinessPond_End[4] = {-1, 0, -1, -1};
static const int8 kHappinessPond_Xvel[10] = {0, -12, -6, 6, 12, -9, -5, 0, 5, 9};
static const int8 kHappinessPond_Yvel[10] = {-40, -40, -40, -40, -40, -32, -32, -32, -32, -32};
static const int8 kHappinessPond_Zvel[10] = {20, 20, 20, 20, 20, 16, 16, 16, 16, 16};
int j = kHappinessPond_Start[arg], j_end = kHappinessPond_End[arg];
k = 9;
do {
happiness_pond_arr1[k] = 1;
happiness_pond_z_vel[k] = kHappinessPond_Zvel[j];
happiness_pond_y_vel[k] = kHappinessPond_Yvel[j];
happiness_pond_x_vel[k] = kHappinessPond_Xvel[j];
happiness_pond_z[k] = 0;
happiness_pond_step[k] = 0;
happiness_pond_timer[k] = 16;
happiness_pond_item_to_link[k] = 53;
int x = link_x_coord + 4;
int y = link_y_coord - 12;
happiness_pond_x_lo[k] = x;
happiness_pond_x_hi[k] = x >> 8;
happiness_pond_y_lo[k] = y;
happiness_pond_y_hi[k] = y >> 8;
} while (--k, --j != j_end);
}
int AncillaAdd_FallingPrize(uint8 a, uint8 item_idx, uint8 yv) { // 898bc1
static const int8 kFallingItem_Type[7] = {0x10, 0x37, 0x39, 0x38, 0x26, 0xf, 0x20};
static const int8 kFallingItem_G[7] = {0x40, 0, 0, 0, 0, -1, 0};
static const int16 kFallingItem_X[7] = {0x78, 0x78, 0x78, 0x78, 0x78, 0x80, 0x78};
static const int16 kFallingItem_Y[7] = {0x48, 0x78, 0x78, 0x78, 0x78, 0x68, 0x78};
static const uint8 kFallingItem_Z[7] = {0x60, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80};
link_receiveitem_index = item_idx;
int k = Ancilla_AddAncilla(a, yv);
if (k < 0)
return k;
uint8 item_type = kFallingItem_Type[item_idx];
ancilla_item_to_link[k] = item_type;
if (item_type == 0x10 || item_type == 0xf)
DecodeAnimatedSpriteTile_variable(kReceiveItemGfx[item_type]);
ancilla_z_vel[k] = -48;
ancilla_y_vel[k] = 0;
ancilla_x_vel[k] = 0;
ancilla_step[k] = 0;
ancilla_z[k] = kFallingItem_Z[item_idx];
ancilla_aux_timer[k] = 9;
ancilla_arr3[k] = 0;
ancilla_L[k] = 0;
ancilla_G[k] = kFallingItem_G[item_idx];
link_receiveitem_index = item_type;
int x, y;
if (item_idx != 0 && item_idx != 5) {
if (BYTE(cur_palace_index_x2) == 20) {
x = (link_x_coord & 0xff00) | 0x100;
y = (link_y_coord & 0xff00) | 0x100;
} else {
x = kFallingItem_X[item_idx] + BG2HOFS_copy2;
y = kFallingItem_Y[item_idx] + BG2VOFS_copy2;
}
} else {
x = link_x_coord;
y = kFallingItem_Y[item_idx] + BG2VOFS_copy2;
}
Ancilla_SetXY(k, x, y);
return k;
}
void AncillaAdd_ChargedSpinAttackSparkle() { // 898cb1
for (int k = 9; k >= 0; k--) {
if (ancilla_type[k] == 0 || ancilla_type[k] == 0x3c) {
ancilla_type[k] = 13;
ancilla_floor[k] = link_is_on_lower_level;
ancilla_timer[k] = 6;
break;
}
}
}
void AncillaAdd_ExplodingWeatherVane(uint8 a, uint8 y) { // 898d11
static const int8 kWeathervane_Tab4[12] = {8, 10, 9, 4, 11, 12, -10, -8, 4, -6, -10, -4};
static const int8 kWeathervane_Tab5[12] = {20, 22, 20, 20, 22, 20, 20, 22, 20, 22, 20, 20};
static const uint8 kWeathervane_Tab6[12] = {0xb0, 0xa3, 0xa0, 0xa2, 0xa0, 0xa8, 0xa0, 0xa0, 0xa8, 0xa1, 0xb0, 0xa0};
static const uint8 kWeathervane_Tab8[12] = {0, 2, 4, 6, 3, 8, 14, 8, 12, 7, 10, 8};
static const uint8 kWeathervane_Tab10[12] = {48, 18, 32, 20, 22, 24, 32, 20, 24, 22, 20, 32};
int k = Ancilla_AddAncilla(a, y);
if (k < 0)
return;
ancilla_aux_timer[k] = 10;
ancilla_G[k] = 128;
ancilla_step[k] = 0;
ancilla_arr3[k] = 0;
sound_effect_1 = 0;
music_control = 0xf2;
sound_effect_ambient = 0x17;
weathervane_var1 = 0;
weathervane_var2 = 0x280;
for (int i = 11; i >= 0; i--) {
weathervane_arr3[i] = 0;
weathervane_arr4[i] = kWeathervane_Tab4[i];
weathervane_arr5[i] = kWeathervane_Tab5[i];
weathervane_arr6[i] = kWeathervane_Tab6[i];
weathervane_arr7[i] = 7;
weathervane_arr8[i] = kWeathervane_Tab8[i];
weathervane_arr9[i] = 2;
weathervane_arr10[i] = kWeathervane_Tab10[i];
weathervane_arr11[i] = 1;
weathervane_arr12[i] = i & 1;
}
}
void AncillaAdd_CutsceneDuck(uint8 a, uint8 y) { // 898d90
if (AncillaAdd_CheckForPresence(a))
return;
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_dir[k] = 2;
ancilla_arr3[k] = 3;
ancilla_step[k] = 0;
ancilla_aux_timer[k] = 32;
ancilla_item_to_link[k] = 116;
ancilla_z_vel[k] = 0;
ancilla_L[k] = 0;
ancilla_z[k] = 0;
ancilla_S[k] = 0;
Ancilla_SetXY(k, 0x200, 0x788);
}
}
void AncillaAdd_SomariaPlatformPoof(int k) { // 898dd2
ancilla_type[k] = 0x39;
ancilla_aux_timer[k] = 7;
for (int j = 15; j >= 0; j--) {
if (sprite_type[j] == 0xed) {
sprite_state[j] = 0;
player_on_somaria_platform = 0;
}
}
Player_TileDetectNearby();
}
void AncillaAdd_SuperBombExplosion(uint8 a, uint8 y) { // 898df9
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_R[k] = 0;
ancilla_step[k] = 0;
ancilla_arr25[k] = 0;
ancilla_L[k] = 0;
ancilla_arr3[k] = kBomb_Tab0[1];
ancilla_item_to_link[k] = 1;
int j = WORD(tagalong_var2);
int y = tagalong_y_lo[j] | tagalong_y_hi[j] << 8;
int x = tagalong_x_lo[j] | tagalong_x_hi[j] << 8;
Ancilla_SetXY(k, x + 8, y + 16);
}
}
void ConfigureRevivalAncillae() { // 898e4e
link_dma_var5 = 80;
int k = 0;
ancilla_arr3[k] = 64;
ancilla_step[k] = 0;
ancilla_z_vel[k] = 8;
ancilla_L[k] = 0;
ancilla_G[k] = 5;
ancilla_item_to_link[k] = 0;
ancilla_K[k] = 0;
Ancilla_SetXY(k, link_x_coord, link_y_coord);
ancilla_z[k] = 0;
k += 1;
ancilla_z[k] = 0;
ancilla_arr3[k] = 240;
ancilla_step[k] = 0;
ancilla_K[k] = 0;
k += 1;
ancilla_item_to_link[k] = 2;
ancilla_aux_timer[k] = 3;
ancilla_arr3[k] = 8;
ancilla_step[k] = 0;
ancilla_dir[k] = 3;
ancilla_arr25[k] = kMagicPowder_Tab0[30 + ancilla_item_to_link[k]];
Ancilla_SetXY(k, link_x_coord + 20, link_y_coord + 2);
}
void AncillaAdd_LampFlame(uint8 a, uint8 y) { // 898f1c
static const int8 kLampFlame_X[4] = {0, 0, -20, 18};
static const int8 kLampFlame_Y[4] = {-16, 24, 4, 4};
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 0;
ancilla_timer[k] = 23;
int j = link_direction_facing >> 1;
ancilla_dir[k] = j;
Ancilla_SetXY(k, link_x_coord + kLampFlame_X[j], link_y_coord + kLampFlame_Y[j]);
sound_effect_1 = Ancilla_CalculateSfxPan(k) | 42;
}
}
void AncillaAdd_MSCutscene(uint8 a, uint8 y) { // 898f7c
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 2;
ancilla_timer[k] = 64;
Ancilla_SetXY(k, link_x_coord + 8, link_y_coord - 8);
}
}
void AncillaAdd_DashDust(uint8 a, uint8 y) { // 898fba
AddDashingDustEx(a, y, 1);
}
void AncillaAdd_DashDust_charging(uint8 a, uint8 y) { // 898fc1
AddDashingDustEx(a, y, 0);
}
void AncillaAdd_BlastWallFireball(uint8 a, uint8 y, int r4) { // 899031
static const int8 kBlastWall_XY[32] = {
-64, 0, -22, 42, -38, 38, -42, 22, 0, 64, 22, 42, 38, 38, 42, 22,
64, 0, 22, -42, 38, -38, 42, -22, 0, -64, -22, -42, -38, -38, -42, -22,
};
for (int k = 10; k != 4; k--) {
if (ancilla_type[k] == 0) {
ancilla_type[k] = 0x32;
ancilla_floor[k] = link_is_on_lower_level;
blastwall_var12[k] = 16;
int j = frame_counter & 15;
ancilla_y_vel[k] = kBlastWall_XY[j * 2 + 0];
ancilla_x_vel[k] = kBlastWall_XY[j * 2 + 1];
Ancilla_SetXY(k, blastwall_var11[r4] + 16, blastwall_var10[r4] + 8);
return;
}
}
}
int AncillaAdd_Arrow(uint8 a, uint8 ax, uint8 ay, uint16 xcoord, uint16 ycoord) { // 8990a4
static const int8 kShootBow_X[4] = {4, 4, 0, 4};
static const int8 kShootBow_Y[4] = {-4, 3, 4, 4};
static const int8 kShootBow_Xvel[4] = {0, 0, -48, 48};
static const int8 kShootBow_Yvel[4] = {-48, 48, 0, 0};
scratch_0 = ycoord;
scratch_1 = xcoord;
BYTE(index_of_interacting_tile) = ax;
if (AncillaAdd_CheckForPresence(a))
return -1;
int k = AncillaAdd_ArrowFindSlot(a, ay);
if (k >= 0) {
sound_effect_1 = Link_CalculateSfxPan() | 7;
ancilla_H[k] = 0;
ancilla_item_to_link[k] = 8;
int j = ax >> 1;
ancilla_dir[k] = j | 4;
ancilla_y_vel[k] = kShootBow_Yvel[j];
ancilla_x_vel[k] = kShootBow_Xvel[j];
Ancilla_SetXY(k, xcoord + kShootBow_X[j], ycoord + 8 + kShootBow_Y[j]);
}
return k;
}
void AncillaAdd_BunnyPoof(uint8 a, uint8 y) { // 899102
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
link_visibility_status = 0xc;
ancilla_step[k] = 0;
if (!link_is_bunny_mirror)
sound_effect_1 = Link_CalculateSfxPan() | 0x14;
else
sound_effect_1 = Link_CalculateSfxPan() | 0x15;
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 7;
Ancilla_SetXY(k, link_x_coord, link_y_coord + 4);
}
}
void AncillaAdd_CapePoof(uint8 a, uint8 y) { // 89912c
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_step[k] = 1;
link_is_transforming = 1;
link_cant_change_direction |= 1;
link_direction = 0;
link_direction_last = 0;
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 7;
Ancilla_SetXY(k, link_x_coord, link_y_coord + 4);
}
}
void AncillaAdd_DwarfPoof(uint8 ain, uint8 yin) { // 89915f
int k = Ancilla_AddAncilla(ain, yin);
if (k < 0)
return;
if (follower_indicator == 8)
sound_effect_1 = Link_CalculateSfxPan() | 0x14;
else
sound_effect_1 = Link_CalculateSfxPan() | 0x15;
ancilla_item_to_link[k] = 0;
ancilla_step[k] = 0;
ancilla_aux_timer[k] = 7;
tagalong_var5 = 1;
int j = tagalong_var2;
int x = tagalong_x_lo[j] | tagalong_x_hi[j] << 8;
int y = tagalong_y_lo[j] | tagalong_y_hi[j] << 8;
Ancilla_SetXY(k, x, y + 4);
}
void AncillaAdd_BushPoof(uint16 x, uint16 y) { // 8991c3
if (!(link_item_in_hand & 0x40))
return;
int k = Ancilla_AddAncilla(0x3f, 4);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_timer[k] = 7;
sound_effect_1 = Link_CalculateSfxPan() | 21;
Ancilla_SetXY(k, x, y - 2);
}
}
void AncillaAdd_EtherSpell(uint8 a, uint8 y) { // 8991fc
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_arr25[k] = 0;
ancilla_step[k] = 0;
flag_custom_spell_anim_active = 1;
ancilla_aux_timer[k] = 2;
ancilla_arr3[k] = 3;
ancilla_y_vel[k] = 127;
ether_var2 = 40;
load_chr_halfslot_even_odd = 9;
ether_var1 = 0x40;
sound_effect_2 = Link_CalculateSfxPan() | 0x26;
for(int i = 0; i < 8; i++)
ether_arr1[i] = i * 8;
ether_y = link_y_coord;
uint16 y = BG2VOFS_copy2 - 16;
ether_y_adjusted = y & 0xf0;
ether_x = link_x_coord;
ether_x2 = ether_x + 8;
ether_y2 = link_y_coord - 16;
ether_y3 = ether_y2 + 0x24;
Ancilla_SetXY(k, link_x_coord, y);
}
}
void AncillaAdd_VictorySpin() { // 8992ac
if ((link_sword_type + 1 & 0xfe) != 0) {
int k = Ancilla_AddAncilla(0x3b, 0);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_arr3[k] = 1;
ancilla_aux_timer[k] = 34;
}
}
}
void AncillaAdd_MagicPowder(uint8 a, uint8 y) { // 8992f0
static const int8 kMagicPower_X[4] = {-2, -2, -12, 12};
static const int8 kMagicPower_Y[4] = {0, 20, 16, 16};
static const int8 kMagicPower_X1[4] = {10, 10, -8, 28};
static const int8 kMagicPower_Y1[4] = {1, 40, 22, 22};
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_z[k] = 0;
ancilla_aux_timer[k] = 1;
link_dma_var5 = 80;
int j = link_direction_facing >> 1;
ancilla_dir[k] = j;
ancilla_arr25[k] = kMagicPowder_Tab0[j * 10];
Ancilla_SetXY(k, link_x_coord + kMagicPower_X[j], link_y_coord + kMagicPower_Y[j]);
Ancilla_CheckTileCollision(k);
byte_7E0333 = ancilla_tile_attr[k];
if (current_item_active == 9) {
ancilla_type[k] = 0;
return;
}
sound_effect_1 = Link_CalculateSfxPan() | 0xd;
Ancilla_SetXY(k, link_x_coord + kMagicPower_X1[j], link_y_coord + kMagicPower_Y1[j]);
}
}
void AncillaAdd_WallTapSpark(uint8 a, uint8 y) { // 899395
static const int8 kWallTapSpark_X[4] = {11, 10, -12, 29};
static const int8 kWallTapSpark_Y[4] = {-4, 32, 17, 17};
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_item_to_link[k] = 5;
ancilla_aux_timer[k] = 1;
int i = link_direction_facing >> 1;
Ancilla_SetXY(k, link_x_coord + kWallTapSpark_X[i], link_y_coord + kWallTapSpark_Y[i]);
}
}
void AncillaAdd_SwordSwingSparkle(uint8 a, uint8 y) { // 8993c2
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 1;
ancilla_dir[k] = link_direction_facing >> 1;
Ancilla_SetXY(k, link_x_coord, link_y_coord);
}
}
void AncillaAdd_DashTremor(uint8 a, uint8 y) { // 8993f3
static const uint8 kAddDashingDust_X[4] = {4, 4, 6, 0};
static const uint8 kAddDashingDust_Y[4] = {20, 4, 16, 16};
static const uint8 kAddDashTremor_Dir[4] = {2, 2, 0, 0};
static const uint8 kAddDashTremor_Tab[2] = {0x80, 0x78};
if (AncillaAdd_CheckForPresence(a))
return;
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_item_to_link[k] = 16;
ancilla_L[k] = 0;
int j = link_direction_facing >> 1;
ancilla_dir[k] = j = kAddDashTremor_Dir[j];
uint8 y = link_y_coord - BG2VOFS_copy2;
uint8 x = link_x_coord - BG2HOFS_copy2;
Ancilla_SetY(k, (j ? y : x) < kAddDashTremor_Tab[j >> 1] ? 3 : -3);
}
}
void AncillaAdd_BoomerangWallClink(int k) { // 899478
static const int8 kBoomerangWallHit_X[8] = {8, 8, 0, 10, 12, 8, 4, 0};
static const int8 kBoomerangWallHit_Y[8] = {0, 8, 8, 8, 4, 8, 12, 8};
static const uint8 kBoomerangWallHit_Tab0[16] = {0, 6, 4, 0, 2, 10, 12, 0, 0, 8, 14, 0, 0, 0, 0, 0};
boomerang_temp_x = Ancilla_GetX(k);
boomerang_temp_y = Ancilla_GetY(k);
k = Ancilla_AddAncilla(6, 1);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_arr3[k] = 1;
int j = kBoomerangWallHit_Tab0[hookshot_effect_index] >> 1;
Ancilla_SetXY(k, boomerang_temp_x + kBoomerangWallHit_X[j], boomerang_temp_y + kBoomerangWallHit_Y[j]);
}
}
void AncillaAdd_HookshotWallClink(int kin, uint8 a, uint8 y) { // 8994c6
static const int8 kHookshotWallHit_X[8] = {8, 8, 0, 10, 12, 8, 4, 0};
static const int8 kHookshotWallHit_Y[8] = {0, 8, 8, 8, 4, 8, 12, 8};
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_item_to_link[k] = 0;
ancilla_arr3[k] = 1;
int j = ancilla_dir[kin];
Ancilla_SetXY(k, Ancilla_GetX(kin) + kHookshotWallHit_X[j], Ancilla_GetY(kin) + kHookshotWallHit_Y[j]);
}
}
void AncillaAdd_Duck_take_off(uint8 a, uint8 y) { // 8994fe
if (AncillaAdd_CheckForPresence(a))
return;
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_timer[k] = 0x78;
ancilla_L[k] = 0;
ancilla_z_vel[k] = 0;
ancilla_z[k] = 0;
ancilla_step[k] = 0;
AddBirdCommon(k);
}
}
void AddBirdTravelSomething(uint8 a, uint8 y) { // 89951d
if (AncillaAdd_CheckForPresence(a))
return;
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
link_player_handler_state = 0;
link_speed_setting = 0;
button_mask_b_y &= ~0x81;
button_b_frames = 0;
link_delay_timer_spin_attack = 0;
link_cant_change_direction &= ~1;
ancilla_L[k] = 1;
if (enhanced_features0 & kFeatures0_ExtendScreen64) {
// todo: tune these better so the angle of attack is better
ancilla_z_vel[k] = 58;
ancilla_z[k] = -105;
} else {
ancilla_z_vel[k] = 40;
ancilla_z[k] = -51;
}
ancilla_step[k] = 2;
AddBirdCommon(k);
}
}
void AncillaAdd_QuakeSpell(uint8 a, uint8 y) { // 899589
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
ancilla_step[k] = 0;
ancilla_item_to_link[k] = 0;
load_chr_halfslot_even_odd = 13;
sound_effect_1 = 0x35;
for(int i = 0; i < 5; i++)
quake_arr2[i] = 0;
quake_var5 = 0;
for(int i = 0; i < 5; i++)
quake_arr1[i] = 1;
flag_custom_spell_anim_active = 1;
ancilla_timer[k] = 2;
quake_var1 = link_y_coord + 26;
quake_var2 = link_x_coord + 8;
quake_var3 = 3;
}
}
void AncillaAdd_SpinAttackInitSpark(uint8 a, uint8 x, uint8 y) { // 89960b
static const int8 kSpinAttackStartSparkle_Y[4] = {32, -8, 10, 20};
static const int8 kSpinAttackStartSparkle_X[4] = {10, 7, 28, -10};
int k = Ancilla_AddAncilla(a, y);
for (int i = 4; i >= 0; i--) {
if (ancilla_type[i] == 0x31)
ancilla_type[i] = 0;
}
ancilla_item_to_link[k] = 0;
ancilla_step[k] = x;
ancilla_timer[k] = 4;
ancilla_aux_timer[k] = 3;
int j = link_direction_facing >> 1;
Ancilla_SetXY(k,
link_x_coord + kSpinAttackStartSparkle_X[j],
link_y_coord + kSpinAttackStartSparkle_Y[j]);
}
void AncillaAdd_BlastWall() { // 899692
static const int8 kBlastWall_Tab3[4] = {-16, 16, 0, 0};
static const int8 kBlastWall_Tab4[4] = {0, 0, -16, 16};
static const int8 kBlastWall_Tab5[16] = {-8, 0, -8, 16, 16, 0, 16, 16, 0, -8, 16, -8, 0, 16, 16, 16};
ancilla_type[0] = 0x33;
ancilla_type[1] = 0x33;
ancilla_type[2] = 0;
ancilla_type[3] = 0;
ancilla_type[4] = 0;
ancilla_type[5] = 0;
ancilla_item_to_link[0] = 0;
flag_is_ancilla_to_pick_up = 0;
link_state_bits = 0;
link_cant_change_direction = 0;
ancilla_K[0] = 0;
ancilla_floor[0] = link_is_on_lower_level;
ancilla_floor[1] = link_is_on_lower_level;
ancilla_floor2[0] = link_is_on_lower_level_mirror;
blastwall_var1 = 0;
blastwall_var6[1] = 0;
blastwall_var5[1] = 0;
blastwall_var4 = 0;
blastwall_var5[0] = 1;
flag_custom_spell_anim_active = 1;
blastwall_var6[0] = 3;
int j = blastwall_var7;
blastwall_var8 += kBlastWall_Tab3[j];
blastwall_var9 += kBlastWall_Tab4[j];
j = (j < 4) ? 4 : 0;
for (int k = 3; k >= 0; k--, j++) {
blastwall_var10[k] = blastwall_var8 + kBlastWall_Tab5[j * 2 + 0];
blastwall_var11[k] = blastwall_var9 + kBlastWall_Tab5[j * 2 + 1];
uint16 x = blastwall_var11[k] - BG2HOFS_copy2;
if (x < 256)
sound_effect_1 = kBombos_Sfx[x >> 5] | 0xc;
}
// In dark world forest castle hole outside door
}
void AncillaAdd_SwordChargeSparkle(int k) { // 899757
int j;
for (j = 9; ancilla_type[j] != 0; ) {
if (--j < 0)
return;
}
ancilla_type[j] = 60;
ancilla_floor[j] = link_is_on_lower_level;
ancilla_item_to_link[j] = 0;
ancilla_timer[j] = 4;
uint8 rand = GetRandomNumber();
uint8 z = ancilla_z[k];
if (z >= 0xF8)
z = 0;
Ancilla_SetXY(j, Ancilla_GetX(k) + 2 + (rand >> 5), Ancilla_GetY(k) - 2 - z + (rand & 0xf));
}
void AncillaAdd_SilverArrowSparkle(int kin) { // 8997de
static const int8 kSilverArrowSparkle_X[4] = {-4, -4, 0, 2};
static const int8 kSilverArrowSparkle_Y[4] = {0, 2, -4, -4};
int k = Ancilla_AllocHigh();
if (k >= 0) {
ancilla_type[k] = 0x3c;
ancilla_item_to_link[k] = 0;
ancilla_timer[k] = 4;
ancilla_floor[k] = link_is_on_lower_level;
int m = GetRandomNumber();
int j = ancilla_dir[kin] & 3;
Ancilla_SetXY(k,
Ancilla_GetX(kin) + kSilverArrowSparkle_X[j] + (m >> 4 & 7),
Ancilla_GetY(kin) + kSilverArrowSparkle_Y[j] + (m & 7));
}
}
void AncillaAdd_IceRodShot(uint8 a, uint8 y) { // 899863
static const int8 kIceRod_X[4] = {0, 0, -20, 20};
static const int8 kIceRod_Y[4] = {-16, 24, 8, 8};
static const int8 kIceRod_Xvel[4] = {0, 0, -48, 48};
static const int8 kIceRod_Yvel[4] = {-48, 48, 0, 0};
int k = Ancilla_AddAncilla(a, y);
if (k < 0) {
Refund_Magic(0);
return;
}
sound_effect_1 = Link_CalculateSfxPan() | 15;
ancilla_step[k] = 0;
ancilla_arr25[k] = 0;
ancilla_item_to_link[k] = 255;
ancilla_L[k] = 1;
ancilla_aux_timer[k] = 3;
ancilla_arr3[k] = 6;
int j = link_direction_facing >> 1;
ancilla_dir[k] = j;
ancilla_y_vel[k] = kIceRod_Yvel[j];
ancilla_x_vel[k] = kIceRod_Xvel[j];
if (Ancilla_CheckInitialTile_A(k) < 0) {
uint16 x = link_x_coord + kIceRod_X[j];
uint16 y = link_y_coord + kIceRod_Y[j];
if (((x - BG2HOFS_copy2) | (y - BG2VOFS_copy2)) & 0xff00) {
ancilla_type[k] = 0;
return;
}
Ancilla_SetXY(k, x, y);
} else {
ancilla_type[k] = 0x11;
ancilla_numspr[k] = kAncilla_Pflags[0x11];
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 4;
}
}
bool AncillaAdd_Splash(uint8 a, uint8 y) { // 8998fc
int k = Ancilla_AddAncilla(a, y);
if (k >= 0) {
sound_effect_1 = Link_CalculateSfxPan() | 0x24;
ancilla_item_to_link[k] = 0;
ancilla_aux_timer[k] = 2;
if (player_is_indoors && !link_is_in_deep_water)
link_is_on_lower_level = 0;
Ancilla_SetXY(k, link_x_coord - 11, link_y_coord + 8);
}
return k < 0;
}
void AncillaAdd_GraveStone(uint8 ain, uint8 yin) { // 8999e9
static const uint16 kMoveGravestone_Y[8] = {0x550, 0x540, 0x530, 0x520, 0x500, 0x4e0, 0x4c0, 0x4b0};
static const uint16 kMoveGravestone_X[15] = {0x8b0, 0x8f0, 0x910, 0x950, 0x970, 0x9a0, 0x850, 0x870, 0x8b0, 0x8f0, 0x920, 0x950, 0x880, 0x990, 0x840};
static const uint16 kMoveGravestone_Y1[15] = {0x540, 0x530, 0x530, 0x530, 0x520, 0x520, 0x510, 0x510, 0x4f0, 0x4f0, 0x4f0, 0x4f0, 0x4d0, 0x4b0, 0x4a0};
static const uint16 kMoveGravestone_X1[15] = {0x8b0, 0x8f0, 0x910, 0x950, 0x970, 0x9a0, 0x850, 0x870, 0x8b0, 0x8f0, 0x920, 0x950, 0x880, 0x990, 0x840};
static const uint16 kMoveGravestone_Pos[15] = {0xa16, 0x99e, 0x9a2, 0x9aa, 0x92e, 0x934, 0x88a, 0x88e, 0x796, 0x79e, 0x7a4, 0x7aa, 0x690, 0x5b2, 0x508};
static const uint8 kMoveGravestone_Ctr[15] = {0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x58};
static const uint8 kMoveGravestone_Idx[9] = {0, 1, 4, 6, 8, 12, 13, 14, 15};
int k = Ancilla_AddAncilla(ain, yin);
if (k < 0)
return;
int t = ((link_y_coord & 0xf) < 7 ? link_y_coord : link_y_coord + 16) & ~0xf;
int i = 7;
while (kMoveGravestone_Y[i] != t) {
if (--i < 0) {
ancilla_type[k] = 0;
return;
}
}
int j = kMoveGravestone_Idx[i];
int end = kMoveGravestone_Idx[i + 1];
do {
int x = kMoveGravestone_X[j];
if (x < link_x_coord && (uint16)(x + 15) >= link_x_coord) {
if (j == 13 ? !link_is_running : link_is_running)
break;
int pos = kMoveGravestone_Pos[j];
big_rock_starting_address = pos;
door_open_closed_counter = kMoveGravestone_Ctr[j];
if (door_open_closed_counter == 0x58) {
sound_effect_2 = Link_CalculateSfxPan() | 0x1b;
} else if (door_open_closed_counter == 0x38) {
save_ow_event_info[BYTE(overworld_screen_index)] |= 0x20;
sound_effect_2 = Link_CalculateSfxPan() | 0x1b;
}
((uint8 *)door_debris_y)[k] = (pos - 0x80);
((uint8 *)door_debris_x)[k] = (pos - 0x80) >> 8;
Overworld_DoMapUpdate32x32_B();
if ((sound_effect_2 & 0x3f) != 0x1b)
sound_effect_1 = Link_CalculateSfxPan() | 0x22;
int yy = kMoveGravestone_Y1[j];
int xx = kMoveGravestone_X1[j];
bitmask_of_dragstate = 4;
link_something_with_hookshot = 1;
ancilla_A[k] = (yy - 18);
ancilla_B[k] = (yy - 18) >> 8;
Ancilla_SetXY(k, xx, yy - 2);
return;
}
} while (++j != end);
ancilla_type[k] = 0;
}
void AncillaAdd_WaterfallSplash() { // 899b68
if (AncillaAdd_CheckForPresence(0x41))
return;
int k = Ancilla_AddAncilla(0x41, 4);
if (k >= 0) {
ancilla_timer[k] = 2;
ancilla_item_to_link[k] = 0;
}
}
void AncillaAdd_GTCutscene() { // 899b83
if (link_state_bits & 0x80 | link_auxiliary_state ||
(link_has_crystals & 0x7f) != 0x7f ||
save_ow_event_info[0x43] & 0x20)
return;
Ancilla_TerminateSparkleObjects();
if (AncillaAdd_CheckForPresence(0x43))
return;
int k = Ancilla_AddAncilla(0x43, 4);
if (k < 0)
return;
for (int i = 15; i >= 0; i--) {
if (sprite_type[i] == 0x37)
sprite_state[i] = 0;
}
for (int i = 0x17; i >= 0; i--)
breaktowerseal_sparkle_var1[i] = 0xff;
DecodeAnimatedSpriteTile_variable(0x28);
palette_sp6 = 4;
overworld_palette_aux_or_main = 0x200;
Palette_Load_SpriteEnvironment_Dungeon();
flag_update_cgram_in_nmi++;
flag_is_link_immobilized = 1;
ancilla_y_subpixel[k] = 0;
ancilla_x_subpixel[k] = 0;
ancilla_step[k] = 0;
breaktowerseal_var5 = 240;
breaktowerseal_var4 = 0;
breaktowerseal_var3[0] = 0;
breaktowerseal_var3[1] = 10;
breaktowerseal_var3[2] = 22;
breaktowerseal_var3[3] = 32;
breaktowerseal_var3[4] = 42;
breaktowerseal_var3[5] = 54;
Ancilla_SetXY(k, link_x_coord, link_y_coord - 16);
}
int AncillaAdd_DoorDebris() { // 899c38
int k = Ancilla_AddAncilla(8, 1);
if (k >= 0) {
ancilla_arr25[k] = 0;
ancilla_arr26[k] = 7;
}
return k;
}
void FireRodShot_BecomeSkullWoodsFire(int k) { // 899c4f
if (player_is_indoors || !(BYTE(overworld_screen_index) & 0x40))
return;
ancilla_type[0] = 0x34;
ancilla_type[1] = 0;
ancilla_type[2] = 0;
ancilla_type[3] = 0;
ancilla_type[4] = 0;
ancilla_type[5] = 0;
flag_for_boomerang_in_place = 0;
ancilla_numspr[0] = kAncilla_Pflags[0x34];
skullwoodsfire_var0[0] = 253;
skullwoodsfire_var0[1] = 254;
skullwoodsfire_var0[2] = 255;
skullwoodsfire_var0[3] = 0;
skullwoodsfire_var4 = 0;
skullwoodsfire_var5[0] = 5;
skullwoodsfire_var5[1] = 5;
skullwoodsfire_var5[2] = 5;
skullwoodsfire_var5[3] = 5;
ancilla_aux_timer[0] = 5;
skullwoodsfire_var9 = 0x100;
skullwoodsfire_var10 = 0x100;
skullwoodsfire_var11 = 0x98;
skullwoodsfire_var12 = 0x98;
trigger_special_entrance = 2;
subsubmodule_index = 0;
BYTE(R16) = 0;
ancilla_floor[0] = link_is_on_lower_level;
ancilla_floor2[0] = link_is_on_lower_level_mirror;
ancilla_item_to_link[0] = 0;
ancilla_step[0] = 0;
}
int Ancilla_AddAncilla(uint8 a, uint8 y) { // 899ce2
int k = Ancilla_AllocInit(a, y);
if (k >= 0) {
ancilla_type[k] = a;
ancilla_floor[k] = link_is_on_lower_level;
ancilla_floor2[k] = link_is_on_lower_level_mirror;
ancilla_y_vel[k] = 0;
ancilla_x_vel[k] = 0;
ancilla_objprio[k] = 0;
ancilla_U[k] = 0;
ancilla_numspr[k] = kAncilla_Pflags[a];
}
return k;
}
bool AncillaAdd_CheckForPresence(uint8 a) { // 899d20
for (int k = 5; k >= 0; k--) {
if (ancilla_type[k] == a)
return true;
}
return false;
}
int AncillaAdd_ArrowFindSlot(uint8 type, uint8 ay) { // 899d36
int k, n = 0;
for (k = 4; k >= 0; k--) {
if (ancilla_type[k] == 10)
n++;
}
if (n != ay + 1) {
for (k = 4; k >= 0; k--) {
if (ancilla_type[k] == 0)
break;
}
} else {
do {
if (sign8(--ancilla_alloc_rotate))
ancilla_alloc_rotate = 4;
k = ancilla_alloc_rotate;
} while (ancilla_type[k] != 10);
}
if (k >= 0) {
ancilla_type[k] = type;
ancilla_floor[k] = link_is_on_lower_level;
ancilla_floor2[k] = link_is_on_lower_level_mirror;
ancilla_y_vel[k] = 0;
ancilla_x_vel[k] = 0;
ancilla_objprio[k] = 0;
ancilla_U[k] = 0;
ancilla_numspr[k] = kAncilla_Pflags[type];
}
return k;
}
int Ancilla_CheckInitialTile_A(int k) { // 899dd3
static const int8 kAncilla_Yoffs_Hb[12] = {8, 0, -8, 8, 16, 24, 8, 8, 8, 8, 8, 8};
static const int8 kAncilla_Xoffs_Hb[12] = {0, 0, 0, 0, 0, 0, 0, -8, -16, 0, 8, 16};
int j = ancilla_dir[k] * 3;
int i;
for (i = 2; i >= 0; i--, j++) {
uint16 x = link_x_coord + kAncilla_Xoffs_Hb[j];
uint16 y = link_y_coord + kAncilla_Yoffs_Hb[j];
Ancilla_SetXY(k, x, y);
if (Ancilla_CheckTileCollision(k))
break;
}
return i;
}
bool Ancilla_CheckInitialTileCollision_Class2(int k) { // 899e44
static const int16 kAncilla_InitialTileColl_Y[9] = {15, 16, 28, 24, 12, 12, 12, 12, 8};
static const int16 kAncilla_InitialTileColl_X[9] = {8, 8, 8, 8, -1, 0, 17, 16, 0x4b8b}; // wtf
int j = ancilla_dir[k] * 2;
for (int n = 2; n >= 0; n--, j++) {
Ancilla_SetXY(k, link_x_coord + kAncilla_InitialTileColl_X[j],
link_y_coord + kAncilla_InitialTileColl_Y[j]);
if (Ancilla_CheckTileCollision_Class2(k))
return true;
}
return false;
}
uint8 Ancilla_TerminateSelectInteractives(uint8 y) { // 89ac6b
int i = 5;
do {
if (ancilla_type[i] == 0x3e) {
y = i;
}
else if (ancilla_type[i] == 0x2c) {
dung_flag_somaria_block_switch = 0;
if (bitmask_of_dragstate & 0x80) {
bitmask_of_dragstate = 0;
link_speed_setting = 0;
}
}
if (sign8(link_state_bits)) {
if (i + 1 != flag_is_ancilla_to_pick_up)
ancilla_type[i] = 0;
}
else {
if (i + 1 == flag_is_ancilla_to_pick_up)
flag_is_ancilla_to_pick_up = 0;
ancilla_type[i] = 0;
}
} while (--i >= 0);
if (link_position_mode & 0x10) {
link_incapacitated_timer = 0;
link_position_mode = 0;
}
flute_countdown = 0;
tagalong_event_flags = 0;
byte_7E02F3 = 0;
flag_for_boomerang_in_place = 0;
is_archer_or_shovel_game = 0;
link_disable_sprite_damage = 0;
byte_7E03FD = 0;
link_electrocute_on_touch = 0;
if (link_player_handler_state == 19) {
link_player_handler_state = 0;
button_mask_b_y &= ~0x40;
link_cant_change_direction &= ~1;
link_position_mode &= ~4;
related_to_hookshot = 0;
}
return y;
}
void Ancilla_SetXY(int k, uint16 x, uint16 y) { // 89ad06
Ancilla_SetX(k, x);
Ancilla_SetY(k, y);
}
void AncillaAdd_ExplodingSomariaBlock(int k) { // 89ad30
ancilla_type[k] = 0x2e;
ancilla_numspr[k] = kAncilla_Pflags[0x2e];
ancilla_aux_timer[k] = 3;
ancilla_step[k] = 0;
ancilla_item_to_link[k] = 0;
ancilla_arr3[k] = 0;
ancilla_arr1[k] = 0;
ancilla_R[k] = 0;
ancilla_objprio[k] = 0;
dung_flag_somaria_block_switch = 0;
sound_effect_2 = Ancilla_CalculateSfxPan(k) | 1;
}
bool Ancilla_AddRupees(int k) { // 89ad6c
static const uint8 kGiveRupeeGift_Tab[5] = {1, 5, 20, 100, 50};
uint8 a = ancilla_item_to_link[k];
if (a == 0x34 || a == 0x35 || a == 0x36) {
link_rupees_goal += kGiveRupeeGift_Tab[a - 0x34];
} else if (a == 0x40 || a == 0x41) {
link_rupees_goal += kGiveRupeeGift_Tab[a - 0x40 + 3];
} else if (a == 0x46) {
link_rupees_goal += 300;
} else if (a == 0x47) {
link_rupees_goal += 20;
} else {
return false;
}
return true;
}
void DashDust_Motive(int k) { // 89adf4
static const uint8 kMotiveDashDust_Draw_Char[3] = {0xa9, 0xcf, 0xdf};
if (!ancilla_timer[k]) {
ancilla_timer[k] = 3;
if (++ancilla_item_to_link[k] == 3) {
ancilla_type[k] = 0;
return;
}
}
if (link_direction_facing == 2)
Oam_AllocateFromRegionB(4);
Point16U info;
Ancilla_PrepOamCoord(k, &info);
OamEnt *oam = GetOamCurPtr();
uint8 ext = Ancilla_SetOam_XY(oam, info.x, info.y);
oam->charnum = kMotiveDashDust_Draw_Char[ancilla_item_to_link[k]];
oam->flags = 4 | HIBYTE(oam_priority_value);
bytewise_extended_oam[oam - oam_buf] = ext;
}
uint8 Ancilla_CalculateSfxPan(int k) { // 8dbb5e
return CalculateSfxPan(Ancilla_GetX(k));
}
int Ancilla_AllocInit(uint8 type, uint8 limit) { // 8ff577
// snes bug: R14 is used in tile detection already
// unless this is here it the memcmp will fail when entering/leaving a water through steps quickly
if (g_ram[kRam_BugsFixed] >= kBugFix_PolyRenderer)
BYTE(R14) = limit + 1;
int n = 0;
for (int i = 0; i < 5; i++) {
if (ancilla_type[i] == type)
n++;
}
if (limit + 1 == n)
return -1;
// Try to reuse an empty ancilla slot
for (int j = (type == 7 || type == 8) ? limit : 4; j >= 0; j--) {
if (ancilla_type[j] == 0)
return j;
}
int k = ancilla_alloc_rotate;
do {
if (--k < 0)
k = limit;
uint8 old_type = ancilla_type[k];
// reuse slots for sparkles or arrows in wall
if (old_type == 0x3c || old_type == 0x13 || old_type == 0xa) {
ancilla_alloc_rotate = k;
return k;
}
} while (k != 0);
ancilla_alloc_rotate = 0;
return -1;
}
void AddSwordBeam(uint8 y) { // 8ff67b
static const int8 kSwordBeam_X[4] = {-8, -10, -22, 4};
static const int8 kSwordBeam_Y[4] = {-24, 8, -6, -6};
static const int8 kSwordBeam_S[4] = {-8, -8, -8, 8};
static const uint8 kSwordBeam_Tab[16] = {0x21, 0x1d, 0x19, 0x15, 3, 0x3e, 0x3a, 0x36, 0x12, 0xe, 0xa, 6, 0x31, 0x2d, 0x29, 0x25};
static const int8 kSwordBeam_Yvel[4] = {-64, 64, 0, 0};
static const int8 kSwordBeam_Xvel[4] = {0, 0, -64, 64};
int k = Ancilla_AddAncilla(0xc, y);
if (k < 0)
return;
int j = link_direction_facing * 2;
swordbeam_arr[0] = kSwordBeam_Tab[j + 0];
swordbeam_arr[1] = kSwordBeam_Tab[j + 1];
swordbeam_arr[2] = kSwordBeam_Tab[j + 2];
swordbeam_arr[3] = swordbeam_var1 = kSwordBeam_Tab[j + 3];
ancilla_aux_timer[k] = 2;
ancilla_item_to_link[k] = 0x4c;
ancilla_arr3[k] = 8;
ancilla_step[k] = 0;
ancilla_L[k] = 0;
ancilla_G[k] = 0;
ancilla_arr1[k] = 0;
swordbeam_var2 = 14;
j = link_direction_facing >> 1;
ancilla_dir[k] = j;
ancilla_y_vel[k] = kSwordBeam_Yvel[j];
ancilla_x_vel[k] = kSwordBeam_Xvel[j];
ancilla_S[k] = kSwordBeam_S[j];
swordbeam_temp_y = link_y_coord + 12;
swordbeam_temp_x = link_x_coord + 8;
if (Ancilla_CheckInitialTile_A(k) >= 0) {
Ancilla_SetXY(k, swordbeam_temp_x + kSwordBeam_X[j], swordbeam_temp_y + kSwordBeam_Y[j]);
sound_effect_2 = 1 | Ancilla_CalculateSfxPan(k);
ancilla_type[k] = 4;
ancilla_timer[k] = 7;
ancilla_numspr[k] = 16;
}
}
void AncillaSpawn_SwordChargeSparkle() { // 8ff979
static const uint8 kSwordChargeSparkle_A[4] = {0, 0, 7, 7};
static const uint8 kSwordChargeSparkle_B[4] = {0x70, 0x70, 0, 0};
static const uint8 kSwordChargeSparkle_X[4] = {0, 3, 4, 5};
static const uint8 kSwordChargeSparkle_Y[4] = {5, 12, 8, 8};
int k = Ancilla_AllocHigh();
if (k < 0)
return;
ancilla_type[k] = 0x3c;
ancilla_item_to_link[k] = 0;
ancilla_timer[k] = 4;
ancilla_floor[k] = link_is_on_lower_level;
int j = link_direction_facing >> 1;
int8 x = 0, y = 0;
uint8 m0 = kSwordChargeSparkle_A[j];
if (!m0) {
y = link_spin_attack_step_counter >> 2;
if (j == 0)
y = -y;
}
uint8 m1 = kSwordChargeSparkle_B[j];
if (!m1) {
x = link_spin_attack_step_counter >> 2;
if (j == 2)
x = -x;
}
uint8 r = GetRandomNumber();
Ancilla_SetXY(k,
link_x_coord + x + kSwordChargeSparkle_X[j] + ((r & m1) >> 4),
link_y_coord + y + kSwordChargeSparkle_Y[j] + (r & m0));
}
int DashTremor_TwiddleOffset(int k) { // 8ffafe
int j = ancilla_dir[k];
uint16 y = -Ancilla_GetY(k);
Ancilla_SetY(k, y);
if (player_is_indoors)
return y;
if (j == 2) {
uint16 start = ow_scroll_vars0.ystart + 1;
uint16 end = ow_scroll_vars0.yend - 1;
uint16 a = y + BG2VOFS_copy2;
return (a <= start || a >= end) ? 0 : y;
} else {
uint16 start = ow_scroll_vars0.xstart + 1;
uint16 end = ow_scroll_vars0.xend - 1;
uint16 a = y + BG2HOFS_copy2;
return (a <= start || a >= end) ? 0 : y;
}
}
void Ancilla_TerminateIfOffscreen(int j) { // 8ffd52
int xt = (enhanced_features0 & kFeatures0_ExtendScreen64) ? 0x40 : 0;
uint16 x = Ancilla_GetX(j) - BG2HOFS_copy2 + xt;
uint16 y = Ancilla_GetY(j) - BG2VOFS_copy2;
if (x >= 244 + xt * 2 || y >= 240)
ancilla_type[j] = 0;
}
bool Bomb_CheckUndersideSpriteStatus(int k, Point16U *out_pt, uint8 *out_r10) { // 8ffdcf
if (ancilla_item_to_link[k] != 0)
return true;
uint8 r10 = 0;
if (ancilla_tile_attr[k] == 9) {
if (sign8(--ancilla_arr22[k])) {
ancilla_arr22[k] = 3;
if (++ancilla_arr23[k] == 3)
ancilla_arr23[k] = 0;
}
r10 = ancilla_arr23[k] + 4;
if ((sound_effect_1 & 0x3f) == 0xb || (sound_effect_1 & 0x3f) == 0x21)
sound_effect_1 = Ancilla_CalculateSfxPan(k) | 0x28;
} else if (ancilla_tile_attr[k] == 0x40) {
r10 = 3;
}
if (ancilla_z[k] >= 2 && ancilla_z[k] < 252)
r10 = 2;
if (k + 1 == flag_is_ancilla_to_pick_up && (link_state_bits & 0x80))
return true;
int z = (int8)ancilla_z[k];
out_pt->y += z + 2;
out_pt->x += -8;
*out_r10 = r10;
return false;
}
void Sprite_CreateDeflectedArrow(int k) { // 9d8040
ancilla_type[k] = 0;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x1b, &info);
if (j >= 0) {
sprite_x_lo[j] = ancilla_x_lo[k];
sprite_x_hi[j] = ancilla_x_hi[k];
sprite_y_lo[j] = ancilla_y_lo[k];
sprite_y_hi[j] = ancilla_y_hi[k];
sprite_state[j] = 6;
sprite_delay_main[j] = 31;
sprite_x_vel[j] = ancilla_x_vel[k];
sprite_y_vel[j] = ancilla_y_vel[k];
sprite_floor[j] = link_is_on_lower_level;
Sprite_PlaceWeaponTink(j);
}
}