ref: ba4a5ff6d907c08b1a59c2567636aa1ea6196c55
dir: /sprite.c/
#include "sprite.h"
#include "dungeon.h"
#include "hud.h"
#include "load_gfx.h"
#include "overworld.h"
#include "variables.h"
#include "tagalong.h"
#include "overlord.h"
#include "ancilla.h"
#include "player.h"
#include "misc.h"
#include "overlord.h"
#include "tile_detect.h"
#include "sprite_main.h"
#include "assets.h"
static const uint16 kOamGetBufferPos_Tab0[6] = {0x171, 0x201, 0x31, 0xc1, 0x141, 0x1d1};
static const uint16 kOamGetBufferPos_Tab1[48] = {
0x30, 0x50, 0x80, 0xb0, 0xe0, 0x110, 0x140, 0x170, 0x1d0, 0x1d4, 0x1dc, 0x1e0, 0x1e4, 0x1ec, 0x1f0, 0x1f8,
0, 4, 8, 0xc, 0x10, 0x14, 0x18, 0x1c, 0x30, 0x38, 0x50, 0x68, 0x80, 0x98, 0xb0, 0xc8,
0x120, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1a0, 0x1b8,
};
static const uint8 kSprite2_ReturnIfRecoiling_Masks[6] = {3, 1, 0, 0, 0xc, 3};
static const int8 kSpriteHitbox_XLo[32] = {
2, 3, 0, -3, -6, 0, 2, -8, 0, -4, -8, 0, -8, -16, 2, 2,
2, 2, 2, -8, 2, 2, -16, -8, -12, 4, -4, -12, 5, -32, -2, 4,
};
static const int8 kSpriteHitbox_XHi[32] = {
0, 0, 0, -1, -1, 0, 0, -1, 0, -1, -1, 0, -1, -1, 0, 0,
0, 0, 0, -1, 0, 0, -1, -1, -1, 0, -1, -1, 0, -1, -1, 0,
};
static const uint8 kSpriteHitbox_XSize[32] = {
12, 1, 16, 20, 20, 8, 4, 32, 48, 24, 32, 32, 32, 48, 12, 12,
60, 124, 12, 32, 4, 12, 48, 32, 40, 8, 24, 24, 5, 80, 4, 8,
};
static const int8 kSpriteHitbox_YLo[32] = {
0, 3, 4, -4, -8, 2, 0, -16, 12, -4, -8, 0, -10, -16, 2, 2,
2, 2, -3, -12, 2, 10, 0, -12, 16, 4, -4, -12, 3, -16, -8, 10,
};
static const int8 kSpriteHitbox_YHi[32] = {
0, 0, 0, -1, -1, 0, 0, -1, 0, -1, -1, 0, -1, -1, 0, 0,
0, 0, -1, -1, 0, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0,
};
static const uint8 kSpriteHitbox_YSize[32] = {
14, 1, 16, 21, 24, 4, 8, 40, 20, 24, 40, 29, 36, 48, 60, 124,
12, 12, 17, 28, 4, 2, 28, 20, 10, 4, 24, 16, 5, 48, 8, 12,
};
static const uint8 kSpriteDamage_Tab2[4] = {6, 4, 0, 0};
static const uint8 kSpriteDamage_Tab3[4] = {4, 6, 0, 2};
static const uint8 kSprite_Func21_Sfx[9] = {0x1f, 0x1f, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f};
static const int8 kSparkleGarnish_XY[4] = {-4, 12, 3, 8};
static const uint8 kSpriteStunned_Main_Func1_Masks[7] = {0x7f, 0xf, 3, 1, 0, 0, 0};
static const uint8 kSprite_Func7_Tab[4] = {8, 4, 2, 1};
static const int8 kSprite_Func5_X[54] = {
8, 8, 2, 14, 8, 8, -2, 10, 8, 8, 1, 14, 4, 4, 4, 4,
4, 4, -2, 10, 8, 8, -25, 40, 8, 8, 2, 14, 8, 8, -8, 23,
8, 8, -20, 36, 8, 8, -1, 16, 8, 8, -1, 16, 8, 8, -8, 24,
8, 8, -8, 24, 8, 3,
};
static const int8 kSprite_Func5_Y[54] = {
6, 20, 13, 13, 0, 8, 4, 4, 1, 14, 8, 8, 4, 4, 4, 4,
-2, 10, 4, 4, -25, 40, 8, 8, 3, 16, 10, 10, -8, 25, 8, 8,
-20, 36, 8, 8, -1, 16, 8, 8, 14, 3, 8, 8, -8, 24, 8, 8,
-8, 32, 8, 8, 12, 4,
};
static const uint8 kSprite_SimplifiedTileAttr[256] = {
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 3, 3, 3,
0, 0, 0, 0, 0, 0, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
static const int8 kSprite_Func5_Tab3[256] = {
0, 1, 2, 3, 2, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
1, 1, 1, 0, 0, 0, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 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, 1, 0, 2, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
static const int8 kSlopedTile[32] = {
7, 6, 5, 4, 3, 2, 1, 0,
0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6, 7,
7, 6, 5, 4, 3, 2, 1, 0,
};
static const uint8 kSprite_Func1_Tab[8] = {15, 15, 24, 15, 15, 19, 15, 15};
static const uint8 kSprite_Func1_Tab2[8] = {6, 6, 6, 12, 6, 6, 6, 15};
static const uint8 kSprite_Func14_Damage[12] = {1, 2, 3, 4, 2, 3, 4, 5, 1, 1, 2, 3};
static const uint8 kEnemyDamages[128] = {
0, 1, 32, 255, 252, 251, 0, 0, 0, 2, 64, 4, 0, 0, 0, 0,
0, 4, 64, 2, 3, 0, 0, 0, 0, 8, 64, 4, 0, 0, 0, 0,
0, 16, 64, 8, 0, 0, 0, 0, 0, 16, 64, 8, 0, 0, 0, 0,
0, 4, 64, 16, 0, 0, 0, 0, 0, 255, 64, 255, 252, 251, 0, 0,
0, 4, 64, 255, 252, 251, 32, 0, 0, 100, 24, 100, 0, 0, 0, 0,
0, 249, 250, 255, 100, 0, 0, 0, 0, 8, 64, 253, 4, 16, 0, 0,
0, 8, 64, 254, 4, 0, 0, 0, 0, 16, 64, 253, 0, 0, 0, 0,
0, 254, 64, 16, 0, 0, 0, 0, 0, 32, 64, 255, 0, 0, 0, 250,
};
static const uint8 kSpriteInit_Flags2[243] = {
1, 2, 1, 0x82, 0x81, 0x84, 0x84, 0x84, 2, 0xf, 2, 1, 0x20, 3, 4, 0x84,
1, 5, 4, 1, 0x80, 4, 0xa2, 0x83, 4, 2, 0x82, 0x62, 0x82, 0x80, 0x80, 0x85,
1, 0xa5, 3, 4, 4, 0x83, 2, 1, 0x82, 0xa2, 0xa2, 0xa3, 0xaa, 0xa3, 0xa4, 0x82,
0x82, 0x83, 0x82, 0x80, 0x82, 0x82, 0xa5, 0x80, 0xa4, 0x82, 0x81, 0x82, 0x82, 0x82, 0x81, 6,
8, 8, 8, 8, 6, 8, 8, 8, 6, 7, 7, 2, 2, 0x22, 1, 1,
0x20, 0x82, 7, 0x85, 0xf, 0x21, 5, 0x83, 2, 1, 1, 1, 1, 7, 7, 7,
7, 0, 0x85, 0x83, 3, 0xa4, 0, 0, 0, 0, 9, 4, 0xa0, 0, 1, 0,
0, 3, 0x8b, 0x86, 0xc2, 0x82, 0x81, 4, 0x82, 0x21, 6, 3, 1, 3, 3, 3,
0, 0, 4, 5, 5, 3, 1, 2, 0, 0, 0, 2, 7, 0, 1, 1,
0x87, 6, 0, 0x83, 2, 0x22, 0x22, 0x22, 0x22, 4, 3, 5, 1, 1, 4, 1,
2, 8, 8, 0x80, 0x21, 3, 3, 3, 2, 2, 8, 0x8f, 0xa1, 0x81, 0x80, 0x80,
0x80, 0x80, 0xa1, 0x80, 0x81, 0x81, 0x86, 0x81, 0x82, 0x82, 0x80, 0x80, 0x83, 6, 0, 0,
5, 4, 6, 5, 2, 0, 0, 5, 4, 4, 7, 0xb, 0xc, 0xc, 6, 6,
3, 0xa4, 4, 0x82, 0x81, 0x83, 0x10, 0x10, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x81,
0x82, 0x83, 0x83, 0x81, 0x82, 0x81, 0x82, 0xa0, 0xa1, 0xa3, 0xa1, 0xa1, 0xa1, 0x83, 0x85, 0x83,
0x83, 0x83, 0x83,
};
static const uint8 kSpriteInit_Health[243] = {
12, 6, 255, 3, 3, 3, 3, 3, 2, 12, 4, 255, 0, 3, 12, 2,
0, 20, 4, 4, 0, 255, 0, 2, 3, 8, 0, 0, 0, 0, 0, 0,
8, 3, 8, 2, 2, 0, 3, 255, 0, 3, 3, 3, 3, 3, 3, 3,
3, 0, 3, 0, 3, 3, 3, 0, 3, 0, 0, 0, 0, 3, 2, 255,
2, 6, 4, 8, 6, 8, 6, 4, 8, 8, 8, 4, 4, 2, 2, 2,
255, 8, 255, 48, 16, 8, 8, 255, 2, 0, 0, 255, 255, 255, 255, 255,
255, 255, 255, 255, 4, 4, 255, 255, 255, 255, 16, 3, 0, 2, 4, 1,
255, 4, 255, 0, 0, 0, 0, 255, 0, 0, 96, 255, 24, 255, 255, 255,
3, 4, 255, 16, 8, 8, 0, 255, 32, 32, 32, 32, 32, 8, 8, 4,
8, 64, 48, 255, 2, 255, 255, 255, 255, 16, 4, 2, 4, 4, 8, 8,
8, 16, 64, 64, 8, 4, 8, 4, 4, 8, 12, 16, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 48, 255,
255, 255, 255, 8, 0, 0, 0, 32, 0, 8, 5, 40, 40, 40, 90, 16,
24, 64, 0, 4, 0, 0, 255, 255, 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,
};
const uint8 kSpriteInit_BumpDamage[243] = {
0x83, 0x83, 0x81, 2, 2, 2, 2, 2, 1, 0x13, 1, 1, 1, 1, 8, 1,
1, 8, 5, 3, 0x40, 4, 0, 2, 3, 0x85, 0, 1, 0, 0x40, 0, 0,
6, 0, 5, 3, 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0, 0, 0, 0, 0, 2, 2,
0, 1, 1, 3, 1, 3, 1, 1, 3, 3, 3, 1, 3, 1, 1, 1,
1, 1, 1, 0x11, 0x14, 1, 1, 2, 5, 0, 0, 4, 4, 8, 8, 8,
8, 4, 0, 4, 3, 2, 2, 2, 2, 2, 3, 1, 0, 0, 1, 0x80,
5, 1, 0, 0, 0, 0x40, 0, 4, 0, 0, 0x14, 4, 6, 4, 4, 4,
4, 3, 4, 4, 4, 1, 4, 4, 0x15, 5, 4, 5, 0x15, 0x15, 3, 5,
0, 5, 0x15, 5, 5, 6, 6, 6, 6, 5, 3, 6, 5, 5, 3, 3,
3, 6, 0x17, 0x15, 0x15, 5, 5, 1, 0x85, 0x83, 5, 4, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x17, 0x17, 5,
5, 5, 4, 3, 2, 0x10, 0, 6, 0, 5, 7, 0x17, 0x17, 0x17, 0x15, 7,
6, 0x10, 0, 3, 3, 0, 0x19, 0x19, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
};
static const uint8 kSpriteInit_Flags3[243] = {
0x19, 0xb, 0x1b, 0x4b, 0x41, 0x41, 0x41, 0x4d, 0x1d, 1, 0x1d, 0x19, 0x8d, 0x1b, 9, 0x9d,
0x3d, 1, 9, 0x11, 0x40, 1, 0x4d, 0x19, 7, 0x1d, 0x59, 0x80, 0x4d, 0x40, 1, 0x49,
0x1b, 0x41, 3, 0x13, 0x15, 0x41, 0x18, 0x1b, 0x41, 0x47, 0xf, 0x49, 0x4b, 0x4d, 0x41, 0x47,
0x49, 0x4d, 0x49, 0x40, 0x4d, 0x47, 0x49, 0x41, 0x74, 0x47, 0x5b, 0x58, 0x51, 0x49, 0x1d, 0x5d,
3, 0x19, 0x1b, 0x17, 0x19, 0x17, 0x19, 0x1b, 0x17, 0x17, 0x17, 0x1b, 0xd, 9, 0x19, 0x19,
0x49, 0x5d, 0x5b, 0x49, 0xd, 3, 0x13, 0x41, 0x1b, 0x5b, 0x5d, 0x43, 0x43, 0x4d, 0x4d, 0x4d,
0x4d, 0x4d, 0x49, 1, 0, 0x41, 0x4d, 0x4d, 0x4d, 0x4d, 0x1d, 9, 0xc4, 0xd, 0xd, 9,
3, 3, 0x4b, 0x47, 0x47, 0x49, 0x49, 0x41, 0x47, 0x36, 0x8b, 0x49, 0x1d, 0x49, 0x43, 0x43,
0x43, 0xb, 0x41, 0xd, 7, 0xb, 0x1d, 0x43, 0xd, 0x43, 0xd, 0x1d, 0x4d, 0x4d, 0x1b, 0x1b,
0xa, 0xb, 0, 5, 0xd, 1, 1, 1, 1, 0xb, 5, 1, 1, 1, 7, 0x17,
0x19, 0xd, 0xd, 0x80, 0x4d, 0x19, 0x17, 0x19, 0xb, 9, 0xd, 0x4a, 0x12, 0x49, 0xc3, 0xc3,
0xc3, 0xc3, 0x76, 0x40, 0x59, 0x41, 0x58, 0x4f, 0x73, 0x5b, 0x44, 0x41, 0x51, 0xa, 0xb, 0xb,
0x4b, 0, 0x40, 0x5b, 0xd, 0, 0, 0xd, 0x4b, 0xb, 0x59, 0x41, 0xb, 0xd, 1, 0xd,
0xd, 0, 0x50, 0x4c, 0x44, 0x51, 1, 1, 0xf2, 0xf8, 0xf4, 0xf2, 0xd4, 0xd4, 0xd4, 0xf8,
0xf8, 0xf4, 0xf4, 0xd8, 0xf8, 0xd8, 0xdf, 0xc8, 0x69, 0xc1, 0xd2, 0xd2, 0xdc, 0xc7, 0xc1, 0xc7,
0xc7, 0xc7, 0xc1,
};
static const uint8 kSpriteInit_Flags4[243] = {
0, 0, 0, 0x43, 0x43, 0x43, 0x43, 0x43, 0, 0, 0, 0, 0x1c, 0, 0, 2,
1, 3, 0, 0, 3, 0xc0, 7, 0, 0, 0, 7, 0x45, 0x43, 0, 0x40, 0xd,
0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 0xd, 7,
7, 7, 7, 3, 7, 7, 7, 0x40, 3, 7, 0xd, 0, 7, 7, 0, 0,
9, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0, 0, 0, 0,
0x80, 0x12, 9, 9, 0, 0x40, 0, 0xc, 0, 0, 0, 0x40, 0x40, 0x10, 0x10, 0x2e,
0x2e, 0x40, 0x1e, 0x53, 0, 0xa, 0, 0, 0, 0, 0x12, 0x12, 0x40, 0, 0, 0x40,
0x19, 0, 0, 0xa, 0xd, 0xa, 0xa, 0x80, 0xa, 0x41, 0, 0x40, 0, 0x49, 0, 0,
0xc0, 0, 0x40, 0, 0, 0x40, 0, 0, 9, 0x80, 0xc0, 0, 0x40, 0, 0, 0x80,
0, 0, 0x18, 0x5a, 0, 0xd4, 0xd4, 0xd4, 0xd4, 0, 0x40, 0, 0x80, 0x80, 0x40, 0x40,
0x40, 0, 9, 0x1d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xa, 0x1b, 0x1b,
0x1b, 0x1b, 0x41, 0, 3, 7, 7, 3, 0xa, 0, 1, 0xa, 0xa, 9, 0, 0,
0, 0, 9, 0, 0, 0x40, 0x40, 0, 0, 0, 0, 0x89, 0x80, 0x80, 0, 0x1c,
0, 0x40, 0, 0, 0x1c, 7, 3, 3, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x43, 0x44, 0x43, 0x40, 0xc0, 0xc0, 0xc7, 0xc3, 0xc3, 0xc0, 0x1b, 8, 0x1b,
0x1b, 0x1b, 3,
};
static const uint8 kSpriteInit_Flags[243] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0xa, 0, 1, 0x30, 0, 0, 0x20,
0x10, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 8, 0x20, 0, 4, 0,
0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x68,
0x60, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0, 0, 0, 0,
0, 0, 2, 2, 2, 0, 0, 0x70, 0, 0, 0, 0x90, 0x90, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x60, 0x60, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 2, 0, 0, 0x70, 0, 0,
0, 0, 0, 0, 0, 0, 0xb0, 0, 0xc2, 0, 0x20, 0, 2, 0, 0, 0,
0, 0, 2, 0, 0xb0, 0, 0, 0, 0, 0, 0, 0, 0xa0, 0xa0, 0, 0,
0, 4, 2, 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, 0xc2, 0, 0,
0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0,
0, 0, 0, 0, 0, 0, 0xa, 0xa, 0x10, 0x10, 0x10, 0x10, 0, 0, 0, 0x10,
0x10, 0x10, 0x10, 0, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
};
static const uint8 kSpriteInit_Flags5[243] = {
0x83, 0x96, 0x84, 0x80, 0x80, 0x80, 0x80, 0x80, 2, 0, 2, 0x80, 0xa0, 0x83, 0x97, 0x80,
0x80, 0x94, 0x91, 7, 0, 0x80, 0, 0x80, 0x92, 0x96, 0x80, 0xa0, 0, 0, 0, 0x80,
4, 0x80, 0x82, 6, 6, 0, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0, 0, 0x80, 0x80, 0x90,
0x80, 0x91, 0x91, 0x91, 0x97, 0x91, 0x95, 0x95, 0x93, 0x97, 0x14, 0x91, 0x92, 0x81, 0x82, 0x82,
0x80, 0x85, 0x80, 0x80, 0x80, 4, 4, 0x80, 0x91, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0, 0x80, 0x80, 0x82, 0x8a, 0x80, 0x80, 0x80, 0x80, 0x92, 0x91, 0x80, 0x82, 0x81, 0x81,
0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x97, 0x80, 0x80, 0x80,
0x80, 0xc2, 0x80, 0x15, 0x15, 0x17, 6, 0, 0x80, 0, 0xc0, 0x13, 0x40, 0, 2, 6,
0x10, 0x14, 0, 0, 0x40, 0, 0, 0, 0, 0x13, 0x46, 0x11, 0x80, 0x80, 0, 0,
0, 0x10, 0, 0, 0, 0x16, 0x16, 0x16, 0x81, 0x87, 0x82, 0, 0x80, 0x80, 0, 0,
0, 0, 0x80, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0x80, 0, 0, 0, 0x17, 0, 0x12, 0, 0, 0, 0, 0, 0x10,
0x17, 0, 0x40, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0,
0, 0, 0,
};
static const uint8 kSpriteInit_DeflBits[243] = {
0, 0, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0, 0x81, 0, 0, 0x48, 0, 0, 0,
0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0x48, 0x24, 0x80, 0, 0,
0, 0x20, 0, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80,
0x80, 0, 0, 0, 0, 0, 0, 0x80, 0, 0x80, 0, 2, 0, 0, 0, 4,
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x84, 0, 0x81, 5, 1, 0x40, 8, 0xa0, 0, 0, 0, 0, 0, 0x84, 0x84, 0x84,
0x84, 8, 0x80, 0x80, 0x80, 0, 0x80, 0x80, 0x80, 0x80, 0, 8, 0x80, 0, 0, 0,
0x40, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 4, 0, 0,
0, 0, 0x80, 4, 4, 0, 0, 0x48, 0, 0, 4, 0, 1, 1, 0, 0,
0x80, 0, 0, 0, 0x40, 8, 8, 8, 8, 0, 0, 0, 0x80, 0x80, 0, 0,
0, 4, 1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0x80, 0x80,
0x80, 0x80, 0x82, 0x80, 0, 0, 0x80, 0, 0, 0x80, 0x80, 0, 0, 1, 1, 0x40,
0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 5, 0x80, 0x80,
0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0x82, 0x82, 8, 0x80, 0x20, 0x80,
0x80, 0x80, 0x20,
};
static const int8 kPlayerDamages[30] = {
2, 1, 1, 4, 4, 4, 0, 0, 0, 8, 4, 2, 8, 8, 8, 16,
8, 4, 32, 16, 8, 32, 24, 16, 24, 16, 8, 64, 48, 24,
};
static const uint8 kPlayerActionBoxRun_YHi[4] = {0xff, 0, 0, 0};
static const uint8 kPlayerActionBoxRun_YLo[4] = {(uint8)-8, 16, 8, 8};
static const uint8 kPlayerActionBoxRun_XHi[4] = {0, 0, 0xff, 0};
static const uint8 kPlayerActionBoxRun_XLo[4] = {0, 0, (uint8)-8, 8};
static const int8 kPlayer_SetupActionHitBox_X[65] = {
0, 2, 0, 0, -8, 0, 2, 0, 2, 2, 1, 1, 0, 0, 0, 0,
0, 2, 4, 4, 0, 0, -4, -4, -6, 2, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 2, 2, 4, 4, 2, 2, 2, 2, 0, 0, 0, 0,
0, 0, 0, 0, -4, -4, -10, 0, 2, 2, 0, 0, 0, 0, 0, 0,
0,
};
static const int8 kPlayer_SetupActionHitBox_W[65] = {
15, 4, 8, 8, 8, 8, 12, 8, 4, 4, 6, 6, 0, 0, 0, 0,
0, 4, 16, 12, 8, 8, 12, 11, 12, 4, 6, 6, 0, 0, 0, 0,
0, 8, 8, 8, 10, 14, 15, 4, 4, 4, 6, 6, 0, 0, 0, 0,
0, 8, 8, 8, 10, 14, 15, 4, 4, 4, 6, 6, 0, 0, 0, 0,
0,
};
static const int8 kPlayer_SetupActionHitBox_Y[65] = {
0, 2, 0, 2, 4, 4, 4, 7, 2, 2, 1, 1, 0, 0, 0, 0,
0, 2, 0, 2, -4, -3, -8, 0, 0, 2, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, -2, 0, -4, 1, 2, 2, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, -2, 0, -4, 1, 2, 2, 1, 1, 0, 0, 0, 0,
0,
};
static const int8 kPlayer_SetupActionHitBox_H[65] = {
15, 4, 8, 2, 12, 8, 12, 8, 4, 4, 6, 6, 0, 0, 0, 0,
0, 4, 8, 4, 12, 12, 12, 4, 8, 4, 6, 4, 0, 0, 0, 0,
0, 8, 8, 8, 8, 8, 12, 4, 4, 4, 6, 6, 0, 0, 0, 0,
0, 8, 8, 8, 8, 8, 12, 4, 4, 4, 6, 6, 0, 0, 0, 0,
0,
};
static const int8 kPlayer_SetupActionHitBox_Tab4[13] = {
1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1
};
static const uint8 kSprite_PrepAndDrawSingleLarge_Tab1[236] = {
200, 0, 107, 0, 0, 0, 0, 0, 0, 203, 0, 8, 10, 11, 0, 0,
13, 0, 0, 86, 0, 0, 15, 17, 0, 19, 0, 0, 0, 0, 20, 0,
21, 27, 0, 42, 42, 248, 0, 182, 0, 0, 0, 170, 0, 0, 28, 0,
0, 0, 0, 0, 0, 0, 0, 243, 243, 0, 187, 39, 0, 0, 66, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 63, 0, 0, 0, 64, 64,
68, 0, 0, 0, 0, 71, 70, 0, 0, 72, 74, 101, 101, 0, 0, 0,
0, 0, 143, 0, 0, 76, 78, 78, 78, 78, 0, 48, 36, 50, 56, 60,
129, 0, 82, 0, 0, 0, 0, 0, 0, 92, 0, 98, 94, 0, 0, 0,
101, 102, 0, 0, 0, 0, 110, 14, 0, 59, 66, 0, 0, 117, 120, 123,
0, 0, 207, 0, 132, 141, 141, 141, 141, 0, 148, 117, 160, 0, 0, 162,
166, 0, 0, 0, 177, 0, 181, 0, 189, 0, 0, 0, 105, 0, 0, 0,
0, 0, 92, 0, 214, 230, 0, 0, 0, 219, 218, 233, 0, 0, 190, 192,
106, 0, 249, 215, 0, 0, 0, 216, 0, 0, 222, 227, 0, 0, 0, 235,
0, 0, 0, 0, 0, 0, 244, 244, 29, 31, 31, 31, 32, 32, 32, 33,
34, 35, 35, 37, 40, 106, 246, 41, 0, 0, 205, 206,
};
static const uint8 kSprite_PrepAndDrawSingleLarge_Tab2[251] = {
0xa0, 0xa2, 0xa0, 0xa2, 0x80, 0x82, 0x80, 0x82, 0xea, 0xec, 0x84, 0x4e, 0x61, 0xbd, 0x8c, 0x20,
0x22, 0xc0, 0xc2, 0xe6, 0xe4, 0x82, 0xaa, 0x84, 0xac, 0x80, 0xa0, 0xca, 0xaf, 0x29, 0x39, 0xb,
0x6e, 0x60, 0x62, 0x63, 0x4c, 0xea, 0xec, 0x24, 0x6b, 0x24, 0x22, 0x24, 0x26, 0x20, 0x30, 0x21,
0x2a, 0x24, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0x84, 0x80, 0x82, 0x6e,
0x40, 0x42, 0xe6, 0xe8, 0x80, 0x82, 0xc8, 0x8d, 0xe3, 0xe5, 0xc5, 0xe1, 4, 0x24, 0xe, 0x2e,
0xc, 0xa, 0x9c, 0xc7, 0xb6, 0xb7, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0xe4, 0xf4, 2, 2,
0, 4, 0xc6, 0xcc, 0xce, 0x28, 0x84, 0x82, 0x80, 0xe5, 0x24, 0, 2, 4, 0xa0, 0xaa,
0xa4, 0xa6, 0xac, 0xa2, 0xa8, 0xa6, 0x88, 0x86, 0x8e, 0xae, 0x8a, 0x42, 0x44, 0x42, 0x44, 0x64,
0x66, 0xcc, 0xcc, 0xca, 0x87, 0x97, 0x8e, 0xae, 0xac, 0x8c, 0x8e, 0xaa, 0xac, 0xd2, 0xf3, 0x84,
0xa2, 0x84, 0xa4, 0xe7, 0x8a, 0xa8, 0x8a, 0xa8, 0x88, 0xa0, 0xa4, 0xa2, 0xa6, 0xa6, 0xa6, 0xa6,
0x7e, 0x7f, 0x8a, 0x88, 0x8c, 0xa6, 0x86, 0x8e, 0xac, 0x86, 0xbb, 0xac, 0xa9, 0xb9, 0xaa, 0xba,
0xbc, 0x8a, 0x8e, 0x8a, 0x86, 0xa, 0xc2, 0xc4, 0xe2, 0xe4, 0xc6, 0xea, 0xec, 0xff, 0xe6, 0xc6,
0xcc, 0xec, 0xce, 0xee, 0x4c, 0x6c, 0x4e, 0x6e, 0xc8, 0xc4, 0xc6, 0x88, 0x8c, 0x24, 0xe0, 0xae,
0xc0, 0xc8, 0xc4, 0xc6, 0xe2, 0xe0, 0xee, 0xae, 0xa0, 0x80, 0xee, 0xc0, 0xc2, 0xbf, 0x8c, 0xaa,
0x86, 0xa8, 0xa6, 0x2c, 0x28, 6, 0xdf, 0xcf, 0xa9, 0x46, 0x46, 0xea, 0xc0, 0xc2, 0xe0, 0xe8,
0xe2, 0xe6, 0xe4, 0xb, 0x8e, 0xa0, 0xec, 0xea, 0xe9, 0x48, 0x58,
};
static const uint8 kOverworldAreaSprcollSizes[192] = {
4, 4, 2, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 2, 4, 4, 2, 4, 4,
4, 4, 2, 4, 4, 2, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2,
4, 4, 2, 2, 2, 4, 4, 2, 4, 4, 2, 2, 2, 4, 4, 2,
4, 4, 2, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 2, 4, 4, 2, 4, 4,
4, 4, 2, 4, 4, 2, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2,
4, 4, 2, 2, 2, 4, 4, 2, 4, 4, 2, 2, 2, 4, 4, 2,
4, 4, 2, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 2, 4, 4, 2, 4, 4,
4, 4, 2, 4, 4, 2, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2,
4, 4, 2, 2, 2, 4, 4, 2, 4, 4, 2, 2, 2, 4, 4, 2,
};
static const uint16 kOam_ResetRegionBases[6] = {0x30, 0x1d0, 0, 0x30, 0x120, 0x140};
static const uint8 kGarnish_OamMemSize[23] = {
0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
8, 4, 4, 4, 8, 16,
};
static HandlerFuncK *const kGarnish_Funcs[22] = {
&Garnish01_FireSnakeTail,
&Garnish02_MothulaBeamTrail,
&Garnish03_FallingTile,
&Garnish04_LaserTrail,
&Garnish_SimpleSparkle,
&Garnish06_ZoroTrail,
&Garnish07_BabasuFlash,
&Garnish08_KholdstareTrail,
&Garnish09_LightningTrail,
&Garnish0A_CannonSmoke,
&Garnish_WaterTrail,
&Garnish0C_TrinexxIceBreath,
NULL,
&Garnish0E_TrinexxFireBreath,
&Garnish0F_BlindLaserTrail,
&Garnish10_GanonBatFlame,
&Garnish11_WitheringGanonBatFlame,
&Garnish12_Sparkle,
&Garnish13_PyramidDebris,
&Garnish14_KakKidDashDust,
&Garnish15_ArrghusSplash,
&Garnish16_ThrownItemDebris,
};
static const uint8 kSpriteFall_Tab1[32] = {
13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 3, 3, 3, 3,
3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
};
static const uint8 kSpriteFall_Tab2[32] = {
5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3,
3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
};
static const uint8 kSpriteFall_Tab3[16] = {0xff, 0x3f, 0x1f, 0xf, 0xf, 7, 3, 1, 0xff, 0x3f, 0x1f, 0xf, 7, 3, 1, 0};
static const int8 kSpriteFall_Tab4[4] = {0, 4, 8, 0};
static const DrawMultipleData kSpriteDrawFall0Data[12] = {
{0, 0, 0x0146, 2},
{0, 0, 0x0148, 2},
{0, 0, 0x014a, 2},
{4, 4, 0x014c, 0},
{4, 4, 0x00b7, 0},
{4, 4, 0x0080, 0},
{0, 0, 0x016c, 2},
{0, 0, 0x016e, 2},
{0, 0, 0x014e, 2},
{4, 4, 0x015c, 0},
{4, 4, 0x00b7, 0},
{4, 4, 0x0080, 0},
};
static const int8 kSpriteDrawFall1_X[56] = {
-4, 4, -4, 12, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-4, 12, -4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-4, 12, -4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
4, 0, 0, 0, 4, 0, 0, 0,
};
static const int8 kSpriteDrawFall1_Y[56] = {
-4, -4, 4, 12, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-4, -4, 12, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-4, -4, 12, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
4, 0, 0, 0, 4, 0, 0, 0,
};
static const uint8 kSpriteDrawFall1_Char[56] = {
0xae, 0xa8, 0xa6, 0xaf, 0xaa, 0, 0, 0, 0xac, 0, 0, 0, 0xbe, 0, 0, 0,
0xa8, 0xae, 0xaf, 0xa6, 0xaa, 0, 0, 0, 0xac, 0, 0, 0, 0xbe, 0, 0, 0,
0xa6, 0xaf, 0xae, 0xa8, 0xaa, 0, 0, 0, 0xac, 0, 0, 0, 0xbe, 0, 0, 0,
0xb6, 0, 0, 0, 0x80, 0, 0, 0,
};
static const uint8 kSpriteDrawFall1_Flags[56] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x40, 0x40, 0x40, 0x40, 0x40, 0, 0, 0, 0x40, 0, 0, 0, 0x40, 0, 0, 0,
0x80, 0x80, 0x80, 0x80, 0x80, 0, 0, 0, 0x80, 0, 0, 0, 0x80, 0, 0, 0,
1, 0, 0, 0, 1, 0, 0, 0,
};
static const uint8 kSpriteDrawFall1_Ext[56] = {
0, 2, 2, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
static const int8 kSpriteDistress_X[4] = {-3, 2, 7, 11};
static const int8 kSpriteDistress_Y[4] = {-5, -7, -7, -5};
static const uint8 kPikitDropItems[4] = {0xdc, 0xe1, 0xd9, 0xe6};
static const uint8 kPrizeMasks[7] = { 1, 1, 1, 0, 1, 1, 1 };
static const uint8 kPrizeItems[56] = {
0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd8, 0xd8, 0xd9, 0xda, 0xd9, 0xda, 0xdb, 0xda, 0xd9, 0xda, 0xda,
0xe0, 0xdf, 0xdf, 0xda, 0xe0, 0xdf, 0xd8, 0xdf, 0xdc, 0xdc, 0xdc, 0xdd, 0xdc, 0xdc, 0xde, 0xdc,
0xe1, 0xd8, 0xe1, 0xe2, 0xe1, 0xd8, 0xe1, 0xe2, 0xdf, 0xd9, 0xd8, 0xe1, 0xdf, 0xdc, 0xd9, 0xd8,
0xd8, 0xe3, 0xe0, 0xdb, 0xde, 0xd8, 0xdb, 0xe2,
};
static const uint8 kPrizeZ[15] = {0, 0x24, 0x24, 0x24, 0x20, 0x20, 0x20, 0x24, 0x24, 0x24, 0x24, 0, 0x24, 0x20, 0x20};
static const int8 kPerishOverlay_X[32] = {
0, 0, 0, 8, 0, 8, 0, 8, 8, 8, 0, 8, 0, 8, 0, 8,
0, 8, 0, 8, 0, 8, 0, 8, -3, 11, -3, 11, -6, 14, -6, 14,
};
static const int8 kPerishOverlay_Y[32] = {
0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8,
0, 0, 8, 8, 0, 0, 8, 8, -3, -3, 11, 11, -6, -6, 14, 14,
};
static const uint8 kPerishOverlay_Char[32] = {
0, 0xb9, 0, 0, 0xb4, 0xb5, 0xb5, 0xb4, 0xb9, 0, 0, 0, 0xb5, 0xb4, 0xb4, 0xb5,
0xa8, 0xa8, 0xb8, 0xb8, 0xa8, 0xa8, 0xb8, 0xb8, 0xa9, 0xa9, 0xa9, 0xa9, 0x9b, 0x9b, 0x9b, 0x9b,
};
static const uint8 kPerishOverlay_Flags[32] = {
4, 4, 4, 4, 4, 4, 0xc4, 0xc4, 0x44, 4, 4, 4, 0x44, 0x44, 0x84, 0x84,
4, 0x44, 4, 0x44, 4, 0x44, 4, 0x44, 0x44, 4, 0xc4, 0x84, 4, 0x44, 0x84, 0xc4,
};
static HandlerFuncK *const kSprite_ExecuteSingle[12] = {
&Sprite_inactiveSprite,
&SpriteModule_Fall1,
&SpriteModule_Poof,
&SpriteModule_Drown,
&SpriteModule_Explode,
&SpriteModule_Fall2,
&SpriteModule_Die,
&SpriteModule_Burn,
&SpriteModule_Initialize,
&SpriteActive_Main,
&SpriteModule_Carried,
&SpriteModule_Stunned,
};
// it's not my job to tell you what to think, my job is to think about what you tell me'
#define R0 WORD(g_ram[0])
#define R2 WORD(g_ram[2])
static const uint8 kSpawnSecretItems[22] = {
0xd9, 0x3e, 0x79, 0xd9, 0xdc, 0xd8, 0xda, 0xe4, 0xe1, 0xdc, 0xd8, 0xdf, 0xe0, 0xb, 0x42, 0xd3,
0x41, 0xd4, 0xd9, 0xe3, 0xd8, 0,
};
static const uint8 kSpawnSecretItem_SpawnFlag[22] = {
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0,
};
static const uint8 kSpawnSecretItem_XLo[22] = {
4, 0, 4, 4, 0, 4, 4, 4, 4, 0, 4, 4, 4, 0, 0, 0,
0, 0, 4, 0, 4, 4,
};
static const uint8 kSpawnSecretItem_IgnoreProj[22] = {
1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
0, 0, 1, 1, 1, 1,
};
static const uint8 kSpawnSecretItem_ZVel[22] = {
16, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 16, 10, 16, 0, 0,
0, 0, 16, 0, 0, 0,
};
static const uint8 kSprite_ReturnIfLifted_Dirs[4] = {4, 6, 0, 2};
static const uint8 kAbsorbable_Tab1[15] = {0, 1, 1, 1, 2, 2, 2, 0, 1, 1, 2, 2, 1, 2, 2};
static const uint8 kAbsorbable_Tab2[19] = {0, 0, 0, 0, 1, 2, 3, 0, 0, 4, 5, 0, 0, 0, 0, 2, 4, 6, 2};
static const int16 kNumberedAbsorbable_X[18] = { 0, 0, 8, 0, 0, 8, 0, 0, 8, 0, 0, 2, 0, 0, 2, 0, 0, 0, };
static const int16 kNumberedAbsorbable_Y[18] = { 0, 0, 8, 0, 0, 8, 0, 0, 8, 0, 8, 8, 0, 8, 8, 0, 8, 8, };
static const uint8 kNumberedAbsorbable_Char[18] = { 0x6e, 0x6e, 0x68, 0x6e, 0x6e, 0x78, 0x6e, 0x6e, 0x79, 0x63, 0x73, 0x69, 0x63, 0x73, 0x6a, 0x63, 0x73, 0x73, };
static const uint8 kNumberedAbsorbable_Ext[18] = { 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
static const uint8 kRupeesAbsorption[3] = {1, 5, 20};
const uint8 kAbsorptionSfx[15] = {0xb, 0xa, 0xa, 0xa, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0x2f, 0x2f, 0xb};
static const uint8 kBombsAbsorption[3] = {1, 4, 8};
const uint8 kAbsorbBigKey[2] = {0x40, 0x20};
static int AllocOverlord();
static int Overworld_AllocSprite(uint8 type);
uint16 Sprite_GetX(int k) {
return sprite_x_lo[k] | sprite_x_hi[k] << 8;
}
uint16 Sprite_GetY(int k) {
return sprite_y_lo[k] | sprite_y_hi[k] << 8;
}
void Sprite_SetX(int k, uint16 x) {
sprite_x_lo[k] = x;
sprite_x_hi[k] = x >> 8;
}
void Sprite_SetY(int k, uint16 y) {
sprite_y_lo[k] = y;
sprite_y_hi[k] = y >> 8;
}
void Sprite_ApproachTargetSpeed(int k, uint8 x, uint8 y) {
if (sprite_x_vel[k] - x)
sprite_x_vel[k] += sign8(sprite_x_vel[k] - x) ? 1 : -1;
if (sprite_y_vel[k] - y)
sprite_y_vel[k] += sign8(sprite_y_vel[k] - y) ? 1 : -1;
}
void SpriteAddXY(int k, int xv, int yv) {
Sprite_SetX(k, Sprite_GetX(k) + xv);
Sprite_SetY(k, Sprite_GetY(k) + yv);
}
void Sprite_MoveXYZ(int k) {
Sprite_MoveZ(k);
Sprite_MoveX(k);
Sprite_MoveY(k);
}
void Sprite_Invert_XY_Speeds(int k) {
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_y_vel[k] = -sprite_y_vel[k];
}
int Sprite_SpawnSimpleSparkleGarnishEx(int k, uint16 x, uint16 y, int limit) {
int j = GarnishAllocLimit(limit);
if (j >= 0) {
garnish_type[j] = 5;
garnish_active = 5;
Garnish_SetX(j, Sprite_GetX(k) + x);
Garnish_SetY(j, Sprite_GetY(k) + y - sprite_z[k] + 16);
garnish_countdown[j] = 31;
garnish_sprite[j] = k;
garnish_floor[j] = sprite_floor[k];
}
g_ram[15] = j;
return j;
}
static int AllocOverlord() {
int i = 7;
while (i >= 0 && overlord_type[i] != 0)
i--;
return i;
}
static int Overworld_AllocSprite(uint8 type) {
int i = (type == 0x58) ? 4 :
(type == 0xd0) ? 5 :
(type == 0xeb || type == 0x53 || type == 0xf3) ? 14 : 13;
for (; i >= 0; i--) {
if (sprite_state[i] == 0 || sprite_type[i] == 0x41 && sprite_C[i] != 0)
break;
}
return i;
}
uint16 Garnish_GetX(int k) {
return garnish_x_lo[k] | garnish_x_hi[k] << 8;
}
uint16 Garnish_GetY(int k) {
return garnish_y_lo[k] | garnish_y_hi[k] << 8;
}
void Garnish_SparkleCommon(int k, uint8 shift) {
static const uint8 kGarnishSparkle_Char[4] = {0x83, 0xc7, 0x80, 0xb7};
uint8 t = garnish_countdown[k] >> shift;
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
OamEnt *oam = GetOamCurPtr();
int j = garnish_sprite[k];
SetOamPlain(oam, pt.x, pt.y, kGarnishSparkle_Char[t],
(sprite_oam_flags[j] | sprite_obj_prio[j]) & 0xf0 | 4, 0);
}
void Garnish_DustCommon(int k, uint8 shift) {
static const uint8 kRunningManDust_Char[3] = {0xdf, 0xcf, 0xa9};
tmp_counter = garnish_countdown[k] >> shift;
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
OamEnt *oam = GetOamCurPtr();
SetOamPlain(oam, pt.x, pt.y, kRunningManDust_Char[tmp_counter], 0x24, 0);
}
void SpriteModule_Explode(int k) {
static const DrawMultipleData kSpriteExplode_Dmd[32] = {
{ 0, 0, 0x0060, 2},
{ 0, 0, 0x0060, 2},
{ 0, 0, 0x0060, 2},
{ 0, 0, 0x0060, 2},
{-5, -5, 0x0062, 2},
{ 5, -5, 0x4062, 2},
{-5, 5, 0x8062, 2},
{ 5, 5, 0xc062, 2},
{-8, -8, 0x0062, 2},
{ 8, -8, 0x4062, 2},
{-8, 8, 0x8062, 2},
{ 8, 8, 0xc062, 2},
{-8, -8, 0x0064, 2},
{ 8, -8, 0x4064, 2},
{-8, 8, 0x8064, 2},
{ 8, 8, 0xc064, 2},
{-8, -8, 0x0066, 2},
{ 8, -8, 0x4066, 2},
{-8, 8, 0x8066, 2},
{ 8, 8, 0xc066, 2},
{-8, -8, 0x0068, 2},
{ 8, -8, 0x0068, 2},
{-8, 8, 0x0068, 2},
{ 8, 8, 0x0068, 2},
{-8, -8, 0x006a, 2},
{ 8, -8, 0x406a, 2},
{-8, 8, 0x806a, 2},
{ 8, 8, 0xc06a, 2},
{-8, -8, 0x004e, 2},
{ 8, -8, 0x404e, 2},
{-8, 8, 0x804e, 2},
{ 8, 8, 0xc04e, 2},
};
if (sprite_A[k]) {
if (!sprite_delay_main[k]) {
sprite_state[k] = 0;
for (int j = 15; j >= 0; j--) {
if (sprite_state[j] == 4)
return;
}
load_chr_halfslot_even_odd = 1;
if (!Sprite_CheckIfScreenIsClear())
flag_block_link_menu = 0;
} else {
Sprite_DrawMultiple(k, &kSpriteExplode_Dmd[((sprite_delay_main[k] >> 2) ^ 7) * 4], 4, NULL);
}
return;
}
sprite_floor[k] = 2;
if (sprite_delay_main[k] == 32) {
sprite_state[k] = 0;
flag_is_link_immobilized = 0;
if (player_near_pit_state != 2 && Sprite_CheckIfScreenIsClear()) {
if (sprite_type[k] >= 0xd6) {
music_control = 0x13;
} else if (sprite_type[k] == 0x7a) {
PrepareDungeonExitFromBossFight();
} else {
SpriteExplode_SpawnEA(k);
return;
}
}
}
if (sprite_delay_main[k] >= 64 && (sprite_delay_main[k] >= 0x70 || !(sprite_delay_main[k] & 1)))
SpriteActive_Main(k);
uint8 type = sprite_type[k];
if (sprite_delay_main[k] >= 0xc0)
return;
if ((sprite_delay_main[k] & 3) == 0)
SpriteSfx_QueueSfx2WithPan(k, 0xc);
if (sprite_delay_main[k] & ((type == 0x92) ? 3 : 7))
return;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0x1c, &info);
if (j >= 0) {
static const int8 kSpriteExplode_RandomXY[16] = {0, 4, 8, 12, -4, -8, -12, 0, 0, 8, 16, 24, -24, -16, -8, 0};
load_chr_halfslot_even_odd = 11;
sprite_state[j] = 4;
sprite_flags2[j] = 3;
sprite_oam_flags[j] = 0xc;
int xoff = kSpriteExplode_RandomXY[(GetRandomNumber() & 7) | ((type == 0x92) ? 8 : 0)];
int yoff = kSpriteExplode_RandomXY[(GetRandomNumber() & 7) | ((type == 0x92) ? 8 : 0)];
Sprite_SetX(j, info.r0_x + xoff);
Sprite_SetY(j, info.r2_y + yoff - info.r4_z);
sprite_delay_main[j] = 31;
sprite_A[j] = 31;
}
// endif_1
}
void SpriteDeath_MainEx(int k, bool second_entry) {
if (!second_entry) {
uint8 type = sprite_type[k];
if (type == 0xec) {
ThrowableScenery_ScatterIntoDebris(k);
return;
}
if (type == 0x53 || type == 0x54 || type == 0x92 || type == 0x4a && sprite_C[k] >= 2) {
SpriteActive_Main(k);
return;
}
if (sprite_delay_main[k] == 0) {
Sprite_DoTheDeath(k);
return;
}
}
if (sign8(sprite_flags3[k])) {
SpriteActive_Main(k);
return;
}
if (!((frame_counter & 3) | submodule_index | flag_unk1))
sprite_delay_main[k]++;
SpriteDeath_DrawPoof(k);
if (sprite_type[k] != 0x40 && sprite_delay_main[k] < 10)
return;
oam_cur_ptr += 16;
oam_ext_cur_ptr += 4;
uint8 bak = sprite_flags2[k];
sprite_flags2[k] -= 4;
SpriteActive_Main(k);
sprite_flags2[k] = bak;
}
void SpriteModule_Burn(int k) {
static const uint8 kFlame_Gfx[32] = {
5, 4, 3, 1, 2, 0, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0,
1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0,
};
sprite_hit_timer[k] = 0;
int j = sprite_delay_main[k] - 1;
if (j == 0) {
Sprite_DoTheDeath(k);
return;
}
uint8 bak = sprite_graphics[k];
uint8 bak1 = sprite_oam_flags[k];
sprite_graphics[k] = kFlame_Gfx[j >> 3];
sprite_oam_flags[k] = 3;
Flame_Draw(k);
sprite_oam_flags[k] = bak1;
sprite_graphics[k] = bak;
oam_cur_ptr += 8;
oam_ext_cur_ptr += 2;
if (sprite_delay_main[k] >= 0x10) {
uint8 bak = sprite_flags2[k];
sprite_flags2[k] -= 2;
SpriteActive_Main(k);
sprite_flags2[k] = bak;
}
}
void Sprite_HitTimer31(int k) {
if (sprite_type[k] != 0x7a || is_in_dark_world)
return;
if (sprite_health[k] <= sprite_give_damage[k]) {
dialogue_message_index = 0x140;
Sprite_ShowMessageMinimal();
}
}
void SpriteStunned_MainEx(int k, bool second_entry) {
if (second_entry)
goto ThrownSprite_TileAndSpriteInteraction;
Sprite_DrawRippleIfInWater(k);
SpriteStunned_Main_Func1(k);
if (Sprite_ReturnIfPaused(k))
return;
if (sprite_F[k]) {
if (sign8(sprite_F[k]))
sprite_F[k] = 0;
sprite_x_vel[k] = sprite_y_vel[k] = 0;
}
if (sprite_delay_main[k] < 0x20)
Sprite_CheckDamageFromLink(k);
if (Sprite_ReturnIfRecoiling(k))
return;
Sprite_MoveXY(k);
if (!sprite_E[k]) {
Sprite_CheckTileCollision(k);
if (!sprite_state[k])
return;
ThrownSprite_TileAndSpriteInteraction:
if (sprite_wallcoll[k] & 0xf) {
Sprite_ApplyRicochet(k);
if (sprite_state[k] == 11)
SpriteSfx_QueueSfx2WithPan(k, 5);
}
}
Sprite_CheckTileProperty(k, 0x68);
if (kSpriteInit_Flags3[sprite_type[k]] & 0x10) {
sprite_flags3[k] |= 0x10;
if (sprite_tiletype == 32)
sprite_flags3[k] &= ~0x10;
}
Sprite_MoveZ(k);
sprite_z_vel[k] -= 2;
uint8 z = sprite_z[k] - 1;
if (z >= 0xf0) {
sprite_z[k] = 0;
if (sprite_type[k] == 0xe8 && sign8(sprite_z_vel[k] - 0xe8)) {
sprite_state[k] = 6;
sprite_delay_main[k] = 8;
sprite_flags2[k] = 3;
return;
}
ThrowableScenery_TransmuteIfValid(k);
uint8 a = sprite_tiletype;
if (sprite_tiletype == 32 && !(a = sprite_flags[k] >> 1, sprite_flags[k] & 1)) { // wtf
Sprite_Func8(k);
return;
}
if (a == 9) {
z = sprite_z_vel[k];
sprite_z_vel[k] = 0;
int j;
SpriteSpawnInfo info;
if (sign8(z - 0xf0) && (j = Sprite_SpawnDynamically(k, 0xec, &info)) >= 0) {
Sprite_SetSpawnedCoordinates(j, &info);
Sprite_Func22(j);
}
} else if (a == 8) {
if (sprite_type[k] == 0xd2 || (GetRandomNumber() & 1))
Sprite_SpawnLeapingFish(k);
Sprite_Func22(k);
return;
}
z = sprite_z_vel[k];
if (sign8(z)) {
z = (uint8)(-z) >> 1;
sprite_z_vel[k] = z < 9 ? 0 : z;
}
sprite_x_vel[k] = (int8)sprite_x_vel[k] >> 1;
if (sprite_x_vel[k] == 255)
sprite_x_vel[k] = 0;
sprite_y_vel[k] = (int8)sprite_y_vel[k] >> 1;
if (sprite_y_vel[k] == 255)
sprite_y_vel[k] = 0;
}
if (sprite_state[k] != 11 || sprite_unk5[k] != 0) {
if (Sprite_ReturnIfLifted(k))
return;
if (sprite_type[k] != 0x4a)
ThrownSprite_CheckDamageToSprites(k);
}
}
int Ancilla_SpawnFallingPrize(uint8 item) { // 85a51d
return AncillaAdd_FallingPrize(0x29, item, 4);
}
bool Sprite_CheckDamageToAndFromLink(int k) { // 85ab93
Sprite_CheckDamageFromLink(k);
return Sprite_CheckDamageToLink(k);
}
uint8 Sprite_CheckTileCollision(int k) { // 85b88d
Sprite_CheckTileCollision2(k);
return sprite_wallcoll[k];
}
bool Sprite_TrackBodyToHead(int k) { // 85dca2
if (sprite_head_dir[k] != sprite_D[k]) {
if (frame_counter & 0x1f)
return false;
if (!((sprite_head_dir[k] ^ sprite_D[k]) & 2)) {
sprite_D[k] = (((k ^ frame_counter) >> 5 | 2) & 3) ^ (sprite_head_dir[k] & 2);
return false;
}
}
sprite_D[k] = sprite_head_dir[k];
return true;
}
void Sprite_DrawMultiple(int k, const DrawMultipleData *src, int n, PrepOamCoordsRet *info) { // 85df6c
PrepOamCoordsRet info_buf;
if (!info)
info = &info_buf;
if (Sprite_PrepOamCoordOrDoubleRet(k, info))
return;
word_7E0CFE = 0;
uint8 a = sprite_state[k];
if (a == 10)
a = sprite_unk4[k];
if (a == 11)
BYTE(word_7E0CFE) = sprite_unk5[k];
OamEnt *oam = GetOamCurPtr();
do {
uint16 d = src->char_flags ^ WORD(info->r4);
if (word_7E0CFE >= 1)
d = d & ~0xE00 | 0x400;
SetOamHelper0(oam, src->x + info->x, src->y + info->y, d, d >> 8, src->ext);
} while (src++, oam++, --n);
}
void Sprite_DrawMultiplePlayerDeferred(int k, const DrawMultipleData *src, int n, PrepOamCoordsRet *info) { // 85df75
Oam_AllocateDeferToPlayer(k);
Sprite_DrawMultiple(k, src, n, info);
}
int Sprite_ShowSolicitedMessage(int k, uint16 msg) { // 85e1a7
static const uint8 kShowMessageFacing_Tab0[4] = {4, 6, 0, 2};
dialogue_message_index = msg;
if (!Sprite_CheckDamageToLink_same_layer(k) ||
Sprite_CheckIfLinkIsBusy() ||
!(filtered_joypad_L & 0x80) ||
sprite_delay_aux4[k] || link_auxiliary_state == 2)
return sprite_D[k];
uint8 dir = Sprite_DirectionToFaceLink(k, NULL);
if (link_direction_facing != kShowMessageFacing_Tab0[dir])
return sprite_D[k];
Sprite_ShowMessageUnconditional(dialogue_message_index);
sprite_delay_aux4[k] = 64;
return dir ^ 0x103;
}
int Sprite_ShowMessageOnContact(int k, uint16 msg) { // 85e1f0
dialogue_message_index = msg;
if (!Sprite_CheckDamageToLink_same_layer(k) || link_auxiliary_state == 2)
return sprite_D[k];
Sprite_ShowMessageUnconditional(dialogue_message_index);
return Sprite_DirectionToFaceLink(k, NULL) ^ 0x103;
}
void Sprite_ShowMessageUnconditional(uint16 msg) { // 85e219
dialogue_message_index = msg;
byte_7E0223 = 0;
messaging_module = 0;
submodule_index = 2;
saved_module_for_menu = main_module_index;
main_module_index = 14;
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Link_CancelDash();
link_auxiliary_state = 0;
link_incapacitated_timer = 0;
if (link_player_handler_state == kPlayerState_RecoilWall)
link_player_handler_state = kPlayerState_Ground;
}
bool Sprite_TutorialGuard_ShowMessageOnContact(int k, uint16 msg) { // 85fa59
dialogue_message_index = msg;
uint8 bak2 = sprite_flags2[k];
uint8 bak4 = sprite_flags4[k];
sprite_flags2[k] = 0x80;
sprite_flags4[k] = 0x07;
bool rv = Sprite_CheckDamageToLink_same_layer(k);
sprite_flags2[k] = bak2;
sprite_flags4[k] = bak4;
if (!rv)
return rv;
Sprite_NullifyHookshotDrag();
link_is_running = 0;
link_speed_setting = 0;
if (!link_auxiliary_state)
Sprite_ShowMessageMinimal();
return rv;
}
void Sprite_ShowMessageMinimal() { // 85fa8e
byte_7E0223 = 0;
messaging_module = 0;
submodule_index = 2;
saved_module_for_menu = main_module_index;
main_module_index = 14;
}
void Prepare_ApplyRumbleToSprites() { // 8680fa
static const int8 kApplyRumble_X[4] = { -32, -32, -32, 16 };
static const int8 kApplyRumble_Y[4] = { -32, 32, -24, -24 };
static const uint8 kApplyRumble_WH[6] = { 0x50, 0x50, 0x20, 0x20, 0x50, 0x50 };
int j = link_direction_facing >> 1;
SpriteHitBox hb;
uint16 x = link_x_coord + kApplyRumble_X[j];
uint16 y = link_y_coord + kApplyRumble_Y[j];
hb.r0_xlo = x;
hb.r8_xhi = x >> 8;
hb.r1_ylo = y;
hb.r9_yhi = y >> 8;
hb.r2 = kApplyRumble_WH[j];
hb.r3 = kApplyRumble_WH[j + 2];
Entity_ApplyRumbleToSprites(&hb);
}
void Sprite_SpawnImmediatelySmashedTerrain(uint8 what, uint16 x, uint16 y) { // 86812d
uint8 bak1 = flag_is_sprite_to_pick_up;
uint8 bak2 = byte_7E0FB2;
int k = Sprite_SpawnThrowableTerrain_silently(what, x, y);
if (k >= 0)
ThrowableScenery_TransmuteToDebris(k);
byte_7E0FB2 = bak2;
flag_is_sprite_to_pick_up = bak1;
}
void Sprite_SpawnThrowableTerrain(uint8 what, uint16 x, uint16 y) { // 86814b
sound_effect_1 = Link_CalculateSfxPan() | 29;
Sprite_SpawnThrowableTerrain_silently(what, x, y);
}
int Sprite_SpawnThrowableTerrain_silently(uint8 what, uint16 x, uint16 y) { // 868156
int k = 15;
for (; k >= 0 && sprite_state[k] != 0; k--);
if (k < 0)
return k;
sprite_state[k] = 10;
sprite_type[k] = 0xEC;
Sprite_SetX(k, x);
Sprite_SetY(k, y);
SpritePrep_LoadProperties(k);
sprite_floor[k] = link_is_on_lower_level;
sprite_C[k] = what;
if (what >= 6)
sprite_flags2[k] = 0xa6;
// oob read, this array has only 6 elements.
uint8 flags = kThrowableScenery_Flags[what];
if (what == 2) {
if (player_is_indoors)
sprite_oam_flags[k] = 0x80, flags = 0x50; // wtf
}
sprite_oam_flags[k] = flags;
sprite_unk4[k] = 9;
flag_is_sprite_to_pick_up = 2;
byte_7E0FB2 = 2;
sprite_delay_main[k] = 16;
sprite_floor[k] = link_is_on_lower_level;
sprite_graphics[k] = 0;
if (BYTE(dung_secrets_unk1) != 255) {
if (!(BYTE(dung_secrets_unk1) | player_is_indoors) && (uint8)(sprite_C[k] - 2) < 2)
Overworld_SubstituteAlternateSecret();
if (dung_secrets_unk1 & 0x80) {
sprite_graphics[k] = dung_secrets_unk1 & 0x7f;
BYTE(dung_secrets_unk1) = 0;
}
Sprite_SpawnSecret(k);
}
return k;
}
void Sprite_SpawnSecret(int k) { // 868264
if (!player_is_indoors && (GetRandomNumber() & 8))
return;
int b = BYTE(dung_secrets_unk1);
if (b == 0)
return;
if (b == 4)
b = 19 + (GetRandomNumber() & 3);
if (!kSpawnSecretItems[b - 1])
return;
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, kSpawnSecretItems[b - 1], &info);
if (j < 0)
return;
sprite_ai_state[j] = kSpawnSecretItem_SpawnFlag[b - 1];
sprite_ignore_projectile[j] = kSpawnSecretItem_IgnoreProj[b - 1];
sprite_z_vel[j] = kSpawnSecretItem_ZVel[b - 1];
Sprite_SetX(j, info.r0_x + kSpawnSecretItem_XLo[b - 1]);
Sprite_SetY(j, info.r2_y);
sprite_z[j] = info.r4_z;
sprite_graphics[j] = 0;
sprite_delay_aux4[j] = 32;
sprite_delay_aux2[j] = 48;
uint8 type = sprite_type[j];
if (type == 0xe4) {
SpritePrep_SmallKey(j);
sprite_stunned[j] = 255;
} else if (type == 0xb) {
sound_effect_1 = 0x30;
if (BYTE(dungeon_room_index2) == 1)
sprite_subtype[j] = 1;
sprite_stunned[j] = 255;
} else if (type == 0x41 || type == 0x42) {
sound_effect_2 = 4;
sprite_give_damage[j] = 0;
sprite_hit_timer[j] = 160;
} else if (type == 0x3e) {
sprite_oam_flags[j] = 9;
} else {
sprite_stunned[j] = 255;
if (type == 0x79)
sprite_A[j] = 32;
}
}
void Sprite_Main() { // 868328
if (!player_is_indoors) {
ancilla_floor[0] = 0;
ancilla_floor[1] = 0;
ancilla_floor[2] = 0;
ancilla_floor[3] = 0;
ancilla_floor[4] = 0;
Sprite_ProximityActivation();
}
is_in_dark_world = (savegame_is_darkworld != 0);
if (submodule_index == 0)
drag_player_x = drag_player_y = 0;
Oam_ResetRegionBases();
Garnish_ExecuteUpperSlots();
Follower_Main();
byte_7E0FB2 = flag_is_sprite_to_pick_up;
flag_is_sprite_to_pick_up = 0;
HIBYTE(dungmap_var8) = 0x80;
if (set_when_damaging_enemies & 0x7f)
set_when_damaging_enemies--;
else
set_when_damaging_enemies = 0;
byte_7E0379 = 0;
link_unk_master_sword = 0;
link_prevent_from_moving = 0;
if (sprite_alert_flag)
sprite_alert_flag--;
Ancilla_Main();
Overlord_Main();
archery_game_out_of_arrows = 0;
for (int i = 15; i >= 0; i--) {
cur_object_index = i;
Sprite_ExecuteSingle(i);
}
Garnish_ExecuteLowerSlots();
byte_7E069E[0] = byte_7E069E[1] = 0;
ExecuteCachedSprites();
if (load_chr_halfslot_even_odd)
byte_7E0FC6 = load_chr_halfslot_even_odd;
}
void Oam_ResetRegionBases() { // 8683d3
memcpy(oam_region_base, kOam_ResetRegionBases, 12);
}
void Sprite_TimersAndOam(int k) { // 8683f2
Sprite_Get16BitCoords(k);
uint8 num = ((sprite_flags2[k] & 0x1f) + 1) * 4;
if (sort_sprites_setting) {
if (sprite_floor[k])
Oam_AllocateFromRegionF(num);
else
Oam_AllocateFromRegionD(num);
} else {
Oam_AllocateFromRegionA(num);
}
if (!(submodule_index | flag_unk1)) {
if (sprite_delay_main[k])
sprite_delay_main[k]--;
if (sprite_delay_aux1[k])
sprite_delay_aux1[k]--;
if (sprite_delay_aux2[k])
sprite_delay_aux2[k]--;
if (sprite_delay_aux3[k])
sprite_delay_aux3[k]--;
uint8 timer = sprite_hit_timer[k] & 0x7f;
if (timer) {
if (sprite_state[k] >= 9) {
if (timer == 31) {
Sprite_HitTimer31(k);
} else if (timer == 24) {
Sprite_MiniMoldorm_Recoil(k);
}
}
if (sprite_give_damage[k] < 251)
sprite_obj_prio[k] = sprite_hit_timer[k] * 2 & 0xe;
sprite_hit_timer[k]--;
} else {
sprite_hit_timer[k] = 0;
sprite_obj_prio[k] = 0;
}
if (sprite_delay_aux4[k])
sprite_delay_aux4[k]--;
}
static const uint8 kSpritePrios[4] = {0x20, 0x10, 0x30, 0x30};
int floor = link_is_on_lower_level;
if (floor != 3)
floor = sprite_floor[k];
sprite_obj_prio[k] = sprite_obj_prio[k] & 0xcf | kSpritePrios[floor];
}
void Sprite_Get16BitCoords(int k) { // 8684c1
cur_sprite_x = sprite_x_lo[k] | sprite_x_hi[k] << 8;
cur_sprite_y = sprite_y_lo[k] | sprite_y_hi[k] << 8;
}
void Sprite_ExecuteSingle(int k) { // 8684e2
uint8 st = sprite_state[k];
if (st != 0)
Sprite_TimersAndOam(k);
kSprite_ExecuteSingle[st](k);
}
void Sprite_inactiveSprite(int k) { // 868510
if (!player_is_indoors) {
sprite_N_word[k] = 0xffff;
} else {
sprite_N[k] = 0xff;
}
}
void SpriteModule_Fall1(int k) { // 86852e
if (!sprite_delay_main[k]) {
sprite_state[k] = 0;
Sprite_ManuallySetDeathFlagUW(k);
} else {
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
SpriteFall_Draw(k, &info);
}
}
void SpriteModule_Drown(int k) { // 86859c
static const DrawMultipleData kSpriteDrown_Dmd[8] = {
{-7, -7, 0x0480, 0},
{14, -6, 0x0483, 0},
{-6, -6, 0x04cf, 0},
{13, -5, 0x04df, 0},
{-4, -4, 0x04ae, 0},
{12, -4, 0x44af, 0},
{ 0, 0, 0x04e7, 2},
{ 0, 0, 0x04e7, 2},
};
static const uint8 kSpriteDrown_Oam_Flags[4] = {0, 0x40, 0xc0, 0x80};
static const uint8 kSpriteDrown_Oam_Char[11] = {0xc0, 0xc0, 0xc0, 0xc0, 0xcd, 0xcd, 0xcd, 0xcb, 0xcb, 0xcb, 0xcb};
if (sprite_ai_state[k]) {
if (sprite_A[k] == 6)
Oam_AllocateFromRegionC(8);
sprite_flags3[k] ^= 16;
SpriteDraw_SingleLarge(k);
OamEnt *oam = GetOamCurPtr();
int j = sprite_delay_main[k];
if (j == 1)
sprite_state[k] = 0;
if (j != 0) {
assert((j >> 1) < 11);
oam->charnum = kSpriteDrown_Oam_Char[j >> 1];
oam->flags = 0x24;
return;
}
oam->charnum = 0x8a;
oam->flags = kSpriteDrown_Oam_Flags[sprite_subtype2[k] >> 2 & 3] | 0x24;
if (Sprite_ReturnIfPaused(k))
return;
sprite_subtype2[k]++;
Sprite_MoveXY(k);
Sprite_MoveZ(k);
sprite_z_vel[k] -= 2;
if (sign8(sprite_z[k])) {
sprite_z[k] = 0;
sprite_delay_main[k] = 18;
sprite_flags3[k] &= ~0x10;
}
} else {
if (Sprite_ReturnIfPaused(k))
return;
if (!(frame_counter & 1))
sprite_delay_main[k]++;
sprite_oam_flags[k] = 0;
sprite_hit_timer[k] = 0;
if (!sprite_delay_main[k])
sprite_state[k] = 0;
Sprite_DrawMultiple(k, &kSpriteDrown_Dmd[(sprite_delay_main[k] << 1 & 0xf8) >> 2], 2, NULL);
}
}
void Sprite_DrawDistress_custom(uint16 xin, uint16 yin, uint8 time) { // 86a733
Oam_AllocateFromRegionA(0x10);
if (!(time & 0x18))
return;
int i = 3;
OamEnt *oam = GetOamCurPtr();
do {
SetOamHelper0(oam, xin + kSpriteDistress_X[i], yin + kSpriteDistress_Y[i],
0x83, 0x22, 0);
} while (oam++, --i >= 0);
}
void Sprite_CheckIfLifted_permissive(int k) { // 86aa0c
Sprite_ReturnIfLiftedPermissive(k);
}
void Entity_ApplyRumbleToSprites(SpriteHitBox *hb) { // 86ad03
for (int j = 15; j >= 0; j--) {
if (!(sprite_defl_bits[j] & 2) || sprite_E[j] == 0)
continue;
if (byte_7E0FC6 != 0xe) {
Sprite_SetupHitBox(j, hb);
if (!CheckIfHitBoxesOverlap(hb))
continue;
}
sprite_E[j] = 0;
sound_effect_2 = 0x30;
sprite_z_vel[j] = 0x30;
sprite_x_vel[j] = 0x10;
sprite_delay_aux3[j] = 0x30;
sprite_stunned[j] = 255;
if (sprite_type[j] == 0xd8)
Sprite_TransmuteToBomb(j);
}
}
void Sprite_ZeroVelocity_XY(int k) { // 86cf5d
sprite_x_vel[k] = sprite_y_vel[k] = 0;
}
bool Sprite_HandleDraggingByAncilla(int k) { // 86cf64
int j = sprite_B[k];
if (j-- == 0)
return false;
if (ancilla_type[j] == 0) {
Sprite_HandleAbsorptionByPlayer(k);
} else {
sprite_x_lo[k] = ancilla_x_lo[j];
sprite_x_hi[k] = ancilla_x_hi[j];
sprite_y_lo[k] = ancilla_y_lo[j];
sprite_y_hi[k] = ancilla_y_hi[j];
sprite_z[k] = 0;
}
return true;
}
bool Sprite_ReturnIfPhasingOut(int k) { // 86d0ed
if (!sprite_stunned[k] || (submodule_index | flag_unk1))
return false;
if (!(frame_counter & 1))
sprite_stunned[k]--;
uint8 a = sprite_stunned[k];
if (a == 0)
sprite_state[k] = 0;
else if (a >= 0x28 || (a & 1) != 0)
return false;
PrepOamCoordsRet info;
Sprite_PrepOamCoordOrDoubleRet(k, &info);
return true;
}
void Sprite_CheckAbsorptionByPlayer(int k) { // 86d116
if (!sprite_delay_aux4[k] && Sprite_CheckDamageToPlayer_1(k))
Sprite_HandleAbsorptionByPlayer(k);
}
void Sprite_HandleAbsorptionByPlayer(int k) { // 86d13c
sprite_state[k] = 0;
int t = sprite_type[k] - 0xd8;
SpriteSfx_QueueSfx3WithPan(k, kAbsorptionSfx[t]);
switch(t) {
case 0:
link_hearts_filler += 8;
break;
case 1: case 2: case 3:
link_rupees_goal += kRupeesAbsorption[t - 1];
break;
case 4: case 5: case 6:
link_bomb_filler += kBombsAbsorption[t - 4];
break;
case 7:
link_magic_filler += 0x10;
break;
case 8:
link_magic_filler = 0x80;
break;
case 9:
link_arrow_filler += (sprite_head_dir[k] == 0) ? 5 : sprite_head_dir[k];
break;
case 10:
link_arrow_filler += 10;
break;
case 11:
SpriteSfx_QueueSfx2WithPan(k, 0x31);
link_hearts_filler += 56;
break;
case 12:
link_num_keys += 1;
goto after_getkey;
case 13:
item_receipt_method = 0;
Link_ReceiveItem(0x32, 0);
after_getkey:
sprite_N[k] = sprite_subtype[k];
dung_savegame_state_bits |= kAbsorbBigKey[sprite_die_action[k]] << 8;
Sprite_ManuallySetDeathFlagUW(k);
break;
case 14:
link_shield_type = sprite_subtype[k];
// Shield needs to have the right palette after pikit
if (enhanced_features0 & kFeatures0_MiscBugFixes)
Palette_Load_Shield();
break;
}
}
bool SpriteDraw_AbsorbableTransient(int k, bool transient) { // 86d22f
if (transient && Sprite_ReturnIfPhasingOut(k))
return false;
if (sort_sprites_setting == 0 && player_is_indoors != 0)
sprite_obj_prio[k] = 0x30;
if (byte_7E0FC6 >= 3)
return false;
if (sprite_delay_aux2[k] != 0)
Oam_AllocateFromRegionC(12);
if (sprite_E[k] != 0)
return true;
uint8 j = sprite_type[k];
assert(j >= 0xd8 && j < 0xd8 + 19);
uint8 a = kAbsorbable_Tab2[j - 0xd8];
if (a != 0) {
Sprite_DrawNumberedAbsorbable(k, a);
return false;
}
uint8 t = kAbsorbable_Tab1[j - 0xd8];
if (t == 0) {
SpriteDraw_SingleSmall(k);
return false;
}
if (t == 2) {
if (sprite_type[k] == 0xe6) {
if (sprite_subtype[k] == 1)
goto draw_key;
sprite_graphics[k] = 1;
}
SpriteDraw_SingleLarge(k);
return false;
}
draw_key:
Sprite_DrawThinAndTall(k);
return false;
}
void Sprite_DrawNumberedAbsorbable(int k, int a) { // 86d2fa
a = (a - 1) * 3;
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int n = (sprite_head_dir[k] < 1) ? 2 : 1;
do {
int j = n + a;
SetOamHelper0(oam,
info.x + kNumberedAbsorbable_X[j], info.y + kNumberedAbsorbable_Y[j],
kNumberedAbsorbable_Char[j], info.flags,
kNumberedAbsorbable_Ext[j]);
} while (oam++, --n >= 0);
SpriteDraw_Shadow(k, &info);
}
void Sprite_BounceOffWall(int k) { // 86d9c0
if (sprite_wallcoll[k] & 3)
sprite_x_vel[k] = -sprite_x_vel[k];
if (sprite_wallcoll[k] & 12)
sprite_y_vel[k] = -sprite_y_vel[k];
}
void Sprite_InvertSpeed_XY(int k) { // 86d9d5
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_y_vel[k] = -sprite_y_vel[k];
}
bool Sprite_ReturnIfInactive(int k) { // 86d9ec
return (sprite_state[k] != 9 || flag_unk1 || submodule_index || !(sprite_defl_bits[k] & 0x80) && sprite_pause[k]);
}
bool Sprite_ReturnIfPaused(int k) { // 86d9f3
return (flag_unk1 || submodule_index || !(sprite_defl_bits[k] & 0x80) && sprite_pause[k]);
}
void SpriteDraw_SingleLarge(int k) { // 86dc10
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
Sprite_PrepAndDrawSingleLargeNoPrep(k, &info);
}
void Sprite_PrepAndDrawSingleLargeNoPrep(int k, PrepOamCoordsRet *info) { // 86dc13
OamEnt *oam = GetOamCurPtr();
oam->x = info->x;
if ((uint16)(info->y + 0x10) < 0x100) {
oam->y = info->y;
oam->charnum = kSprite_PrepAndDrawSingleLarge_Tab2[kSprite_PrepAndDrawSingleLarge_Tab1[sprite_type[k]] + sprite_graphics[k]];
oam->flags = info->flags;
}
bytewise_extended_oam[oam - oam_buf] = 2 | ((info->x >= 256) ? 1: 0);
if (sprite_flags3[k] & 0x10)
SpriteDraw_Shadow(k, info);
}
void SpriteDraw_Shadow_custom(int k, PrepOamCoordsRet *info, uint8 a) { // 86dc5c
uint16 y = Sprite_GetY(k) + a;
info->y = y;
if (sprite_pause[k] || sprite_state[k] == 10 && sprite_unk3[k] == 3)
return;
y -= BG2VOFS_copy2;
info->y = y;
if ((uint16)(y + 0x10) >= 0x100)
return;
OamEnt *oam = GetOamCurPtr() + (sprite_flags2[k] & 0x1f);
if (sprite_flags3[k] & 0x20) {
SetOamHelper1(oam, info->x, y + 1, 0x38, (info->flags & 0x30) | 8, 0);
} else {
SetOamHelper1(oam, info->x, y, 0x6c, (info->flags & 0x30) | 8, 2);
}
}
void SpriteDraw_Shadow(int k, PrepOamCoordsRet *oam) { // 86dc64
SpriteDraw_Shadow_custom(k, oam, 10);
}
void SpriteDraw_SingleSmall(int k) { // 86dcef
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
oam->x = info.x;
if ((uint16)(info.y + 0x10) < 0x100) {
oam->y = info.y;
oam->charnum = kSprite_PrepAndDrawSingleLarge_Tab2[kSprite_PrepAndDrawSingleLarge_Tab1[sprite_type[k]] + sprite_graphics[k]];
oam->flags = info.flags;
}
bytewise_extended_oam[oam - oam_buf] = 0 | (info.x >= 256);
if (sprite_flags3[k] & 0x10)
SpriteDraw_Shadow_custom(k, &info, 2);
}
void Sprite_DrawThinAndTall(int k) { // 86dd40
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
uint8 a = kSprite_PrepAndDrawSingleLarge_Tab2[kSprite_PrepAndDrawSingleLarge_Tab1[sprite_type[k]] + sprite_graphics[k]];
SetOamHelper0(oam + 0, info.x, info.y + 0, a + 0x00, info.flags, 0);
SetOamHelper0(oam + 1, info.x, info.y + 8, a + 0x10, info.flags, 0);
if (sprite_flags3[k] & 0x10)
SpriteDraw_Shadow(k, &info);
}
void SpriteModule_Carried(int k) { // 86de83
static const uint8 kSpriteHeld_ZForFrame[6] = {3, 2, 1, 3, 2, 1};
static const int8 kSpriteHeld_X[16] = {0, 0, 0, 0, 0, 0, 0, 0, -13, -10, -5, 0, 13, 10, 5, 0};
static const uint8 kSpriteHeld_Z[16] = {13, 14, 15, 16, 0, 10, 22, 16, 8, 11, 14, 16, 8, 11, 14, 16};
sprite_room[k] = overworld_area_index;
if (sprite_unk3[k] != 3) {
if (sprite_delay_main[k] == 0) {
sprite_delay_main[k] = (sprite_C[k] == 6) ? 8 : 4;
sprite_unk3[k]++;
}
} else {
sprite_flags3[k] &= ~0x10;
}
uint8 t = sprite_delay_aux4[k] - 1;
uint8 r0 = t < 63 && (t & 2);
int j = link_direction_facing * 2 + sprite_unk3[k];
int t0 = (uint8)link_x_coord + (uint8)kSpriteHeld_X[j];
int t1 = (uint8)t0 + (t0 >> 8 & 1) + r0;
int t2 = HIBYTE(link_x_coord) + (t1 >> 8 & 1) + (t0 >> 8 & 1) + (uint8)(kSpriteHeld_X[j]>>8);
sprite_x_lo[k] = t1;
sprite_x_hi[k] = t2;
// Sprite_SetX(k, link_x_coord + kSpriteHeld_X[j] + r0);
sprite_z[k] = kSpriteHeld_Z[j];
int an = link_animation_steps < 6 ? link_animation_steps : 0;
uint16 z = link_z_coord + 1 + kSpriteHeld_ZForFrame[an];
Sprite_SetY(k, link_y_coord + 8 - z);
sprite_floor[k] = link_is_on_lower_level & 1;
CarriedSprite_CheckForThrow(k);
Sprite_Get16BitCoords(k);
if (sprite_unk4[k] != 11) {
SpriteActive_Main(k);
if (sprite_delay_aux4[k] == 1) {
sprite_state[k] = 9;
sprite_B[k] = 0;
sprite_delay_aux4[k] = 96;
sprite_z_vel[k] = 32;
sprite_flags3[k] |= 0x10;
link_picking_throw_state = 2;
}
} else {
SpriteStunned_Main_Func1(k);
}
}
void CarriedSprite_CheckForThrow(int k) { // 86df6d
static const int8 kSpriteHeld_Throw_Xvel[4] = {0, 0, -62, 63};
static const int8 kSpriteHeld_Throw_Yvel[4] = {-62, 63, 0, 0};
static const uint8 kSpriteHeld_Throw_Zvel[4] = {4, 4, 4, 4};
if (main_module_index == 14)
return;
if (player_near_pit_state != 2) {
uint8 t = (link_auxiliary_state & 1) | link_is_in_deep_water | link_is_bunny_mirror |
link_pose_for_item | (link_disable_sprite_damage ? 0 : link_incapacitated_timer);
if (!t) {
if (sprite_unk3[k] != 3 || !((filtered_joypad_H | filtered_joypad_L) & 0x80))
return;
filtered_joypad_L &= 0x7f;
}
}
SpriteSfx_QueueSfx3WithPan(k, 0x13);
link_picking_throw_state = 2;
sprite_state[k] = sprite_unk4[k];
sprite_z_vel[k] = 0;
sprite_unk3[k] = 0;
sprite_flags3[k] = sprite_flags3[k] & ~0x10 | kSpriteInit_Flags3[sprite_type[k]] & 0x10;
int j = link_direction_facing >> 1;
sprite_x_vel[k] = kSpriteHeld_Throw_Xvel[j];
sprite_y_vel[k] = kSpriteHeld_Throw_Yvel[j];
sprite_z_vel[k] = kSpriteHeld_Throw_Zvel[j];
sprite_delay_aux4[k] = 0;
}
void SpriteModule_Stunned(int k) { // 86dffa
SpriteStunned_MainEx(k, false);
}
void ThrownSprite_TileAndSpriteInteraction(int k) { // 86e02a
SpriteStunned_MainEx(k, true);
}
void Sprite_Func8(int k) { // 86e0ab
sprite_state[k] = 1;
sprite_delay_main[k] = 0x1f;
sound_effect_1 = 0;
SpriteSfx_QueueSfx2WithPan(k, 0x20);
}
void Sprite_Func22(int k) { // 86e0f6
sound_effect_1 = Sprite_CalculateSfxPan(k) | 0x28;
sprite_state[k] = 3;
sprite_delay_main[k] = 15;
sprite_ai_state[k] = 0;
GetRandomNumber(); // wtf
sprite_flags2[k] = 3;
}
void ThrowableScenery_InteractWithSpritesAndTiles(int k) { // 86e164
Sprite_MoveXY(k);
if (!sprite_E[k])
Sprite_CheckTileCollision(k);
ThrownSprite_TileAndSpriteInteraction(k);
}
void ThrownSprite_CheckDamageToSprites(int k) { // 86e172
if (sprite_delay_aux4[k] || !(sprite_x_vel[k] | sprite_y_vel[k]))
return;
for (int i = 15; i >= 0; i--) {
if (i != cur_object_index && sprite_type[k] != 0xd2 && sprite_state[i] >= 9 &&
((i ^ frame_counter) & 3 | sprite_ignore_projectile[i] | sprite_hit_timer[i]) == 0 && sprite_floor[k] == sprite_floor[i])
ThrownSprite_CheckDamageToSingleSprite(k, i);
}
}
void ThrownSprite_CheckDamageToSingleSprite(int k, int j) { // 86e1b2
SpriteHitBox hb;
hb.r0_xlo = sprite_x_lo[k];
hb.r8_xhi = sprite_x_hi[k];
hb.r2 = 15;
int t = sprite_y_lo[k] - sprite_z[k];
int u = (t & 0xff) + 8;
hb.r1_ylo = u;
hb.r9_yhi = sprite_y_hi[k] + (u >> 8) - (t < 0);
hb.r3 = 8;
Sprite_SetupHitBox(j, &hb);
if (!CheckIfHitBoxesOverlap(&hb))
return;
if (sprite_type[j] == 0x3f) {
Sprite_PlaceWeaponTink(k);
} else {
uint8 a = (sprite_type[k] == 0xec && sprite_C[k] == 2 && !player_is_indoors) ? 1 : 3;
Ancilla_CheckDamageToSprite_preset(j, a);
sprite_x_recoil[j] = sprite_x_vel[k] * 2;
sprite_y_recoil[j] = sprite_y_vel[k] * 2;
sprite_delay_aux4[k] = 16;
}
Sprite_ApplyRicochet(k);
}
void Sprite_ApplyRicochet(int k) { // 86e229
Sprite_InvertSpeed_XY(k);
Sprite_HalveSpeed_XY(k);
ThrowableScenery_TransmuteIfValid(k);
}
void ThrowableScenery_TransmuteIfValid(int k) { // 86e22f
if (sprite_type[k] != 0xec)
return;
repulsespark_timer = 0;
ThrowableScenery_TransmuteToDebris(k);
}
void ThrowableScenery_TransmuteToDebris(int k) { // 86e239
uint8 a = sprite_graphics[k];
if (a != 0) {
BYTE(dung_secrets_unk1) = a;
Sprite_SpawnSecret(k);
BYTE(dung_secrets_unk1) = 0;
}
a = player_is_indoors ? 0 : sprite_C[k];
sound_effect_1 = 0;
SpriteSfx_QueueSfx2WithPan(k, kSprite_Func21_Sfx[a]);
Sprite_ScheduleForBreakage(k);
}
void Sprite_ScheduleForBreakage(int k) { // 86e25a
sprite_delay_main[k] = 31;
sprite_state[k] = 6;
sprite_flags2[k] += 4;
}
void Sprite_HalveSpeed_XY(int k) { // 86e26e
sprite_x_vel[k] = (int8)sprite_x_vel[k] >> 1;
sprite_y_vel[k] = (int8)sprite_y_vel[k] >> 1;
}
void Sprite_SpawnLeapingFish(int k) { // 86e286
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(k, 0xd2, &info);
if (j < 0)
return;
Sprite_SetSpawnedCoordinates(j, &info);
sprite_ai_state[j] = 2;
sprite_delay_main[j] = 48;
if (sprite_type[k] == 0xd2)
sprite_A[j] = 0xd2;
}
void SpriteStunned_Main_Func1(int k) { // 86e2ba
SpriteActive_Main(k);
if (sprite_unk5[k]) {
if (sprite_delay_main[k] < 32)
sprite_oam_flags[k] = sprite_oam_flags[k] & 0xf1 | 4;
uint8 t = ((k << 4) ^ frame_counter) | submodule_index;
if (t & kSpriteStunned_Main_Func1_Masks[sprite_delay_main[k] >> 4])
return;
uint16 x = kSparkleGarnish_XY[GetRandomNumber() & 3];
uint16 y = kSparkleGarnish_XY[GetRandomNumber() & 3];
Sprite_GarnishSpawn_Sparkle(k, x, y);
} else {
if ((frame_counter & 1) | submodule_index | flag_unk1)
return;
uint8 t = sprite_stunned[k];
if (t) {
sprite_stunned[k]--;
if (t < 0x38) {
sprite_x_vel[k] = (t & 1) ? -8 : 8;
Sprite_MoveX(k);
}
return;
}
sprite_state[k] = 9;
sprite_x_recoil[k] = 0;
sprite_y_recoil[k] = 0;
}
}
void SpriteModule_Poof(int k) { // 86e393
static const int8 kSpritePoof_X[16] = {-6, 10, 1, 13, -6, 10, 1, 13, -7, 4, -5, 6, -1, 1, -2, 0};
static const int8 kSpritePoof_Y[16] = {-6, -4, 10, 9, -6, -4, 10, 9, -8, -10, 4, 3, -1, -2, 0, 1};
static const uint8 kSpritePoof_Char[16] = {0x9b, 0x9b, 0x9b, 0x9b, 0xb3, 0xb3, 0xb3, 0xb3, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a};
static const uint8 kSpritePoof_Flags[16] = {0x24, 0xa4, 0x24, 0xa4, 0xe4, 0x64, 0xa4, 0x24, 0x24, 0xe4, 0xe4, 0xe4, 0x24, 0xe4, 0xe4, 0xe4};
static const uint8 kSpritePoof_Ext[16] = {0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2};
// Frozen sprite pulverized by hammer
if (sprite_delay_main[k] == 0) {
if (sprite_type[k] == 0xd && sprite_head_dir[k] != 0) {
// buzz blob?
int bakx = Sprite_GetX(k);
PrepareEnemyDrop(k, 0xd);
Sprite_SetX(k, bakx);
sprite_z_vel[k] = 0;
sprite_ignore_projectile[k] = 0;
} else {
if (sprite_die_action[k] == 0) {
ForcePrizeDrop(k, 2, 2);
} else {
Sprite_DoTheDeath(k);
}
}
} else {
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
int j = ((sprite_delay_main[k] >> 1) & ~3) + 3;
for (int i = 3; i >= 0; i--, j--, oam++) {
SetOamPlain(oam, kSpritePoof_X[j] + BYTE(dungmap_var7), kSpritePoof_Y[j] + HIBYTE(dungmap_var7),
kSpritePoof_Char[j], kSpritePoof_Flags[j], kSpritePoof_Ext[j]);
}
Sprite_CorrectOamEntries(k, 3, 0xff);
}
}
void Sprite_PrepOamCoord(int k, PrepOamCoordsRet *ret) { // 86e416
Sprite_PrepOamCoordOrDoubleRet(k, ret);
}
bool Sprite_PrepOamCoordOrDoubleRet(int k, PrepOamCoordsRet *ret) { // 86e41e
sprite_pause[k] = 0;
uint16 x = cur_sprite_x - BG2HOFS_copy2;
uint16 y = cur_sprite_y - BG2VOFS_copy2;
bool out_of_bounds = false;
R0 = x;
R2 = y - sprite_z[k];
ret->flags = sprite_oam_flags[k] ^ sprite_obj_prio[k];
ret->r4 = 0;
int xt = (enhanced_features0 & kFeatures0_ExtendScreen64) ? 0x40 : 0;
if ((uint16)(x + 0x40 + xt) >= (0x170 + xt * 2) ||
(uint16)(y + 0x40) >= 0x170 && !(sprite_flags4[k] & 0x20)) {
sprite_pause[k]++;
if (!(sprite_defl_bits[k] & 0x80))
Sprite_KillSelf(k);
out_of_bounds = true;
}
ret->x = R0;
ret->y = R2;
BYTE(dungmap_var7) = ret->x;
HIBYTE(dungmap_var7) = ret->y;
return out_of_bounds;
}
void Sprite_CheckTileCollision2(int k) { // 86e4ab
sprite_wallcoll[k] = 0;
if (sign8(sprite_flags4[k]) || !dung_hdr_collision) {
Sprite_CheckTileCollisionSingleLayer(k);
return;
}
byte_7E0FB6 = sprite_floor[k];
sprite_floor[k] = 1;
Sprite_CheckTileCollisionSingleLayer(k);
if (dung_hdr_collision == 4) {
sprite_floor[k] = byte_7E0FB6;
return;
}
sprite_floor[k] = 0;
Sprite_CheckTileCollisionSingleLayer(k);
byte_7FFABC[k] = sprite_tiletype;
}
void Sprite_CheckTileCollisionSingleLayer(int k) { // 86e4db
if (sprite_flags2[k] & 0x20) {
if (Sprite_CheckTileProperty(k, 0x6a))
sprite_wallcoll[k]++;
return;
}
if (sign8(sprite_flags4[k]) || dung_hdr_collision == 0) {
if (sprite_y_vel[k])
Sprite_CheckForTileInDirection_vertical(k, sign8(sprite_y_vel[k]) ? 0 : 1);
if (sprite_x_vel[k])
Sprite_CheckForTileInDirection_horizontal(k, sign8(sprite_x_vel[k]) ? 2 : 3);
} else {
Sprite_CheckForTileInDirection_vertical(k, 1);
Sprite_CheckForTileInDirection_vertical(k, 0);
Sprite_CheckForTileInDirection_horizontal(k, 3);
Sprite_CheckForTileInDirection_horizontal(k, 2);
}
if (sign8(sprite_flags5[k]) || sprite_z[k])
return;
Sprite_CheckTileProperty(k, 0x68);
sprite_I[k] = sprite_tiletype;
if (sprite_tiletype == 0x1c) {
if (sort_sprites_setting && sprite_state[k] == 11)
sprite_floor[k] = 1;
} else if (sprite_tiletype == 0x20) {
if (sprite_flags[k] & 1) {
if (!player_is_indoors) {
Sprite_Func8(k);
} else {
sprite_state[k] = 5;
if (sprite_type[k] == 0x13 || sprite_type[k] == 0x26) {
sprite_oam_flags[k] &= ~1;
sprite_delay_main[k] = 63;
} else {
sprite_delay_main[k] = 95;
}
}
}
} else if (sprite_tiletype == 0xc) {
if (byte_7FFABC[k] == 0x1c) {
SpriteFall_AdjustPosition(k);
sprite_wallcoll[k] |= 0x20;
}
} else if (sprite_tiletype >= 0x68 && sprite_tiletype < 0x6c) {
Sprite_ApplyConveyor(k, sprite_tiletype);
} else if (sprite_tiletype == 8) {
if (dung_hdr_collision == 4)
Sprite_ApplyConveyor(k, 0x6a);
}
}
void Sprite_CheckForTileInDirection_horizontal(int k, int yy) { // 86e5b8
if (!Sprite_CheckTileInDirection(k, yy))
return;
sprite_wallcoll[k] |= kSprite_Func7_Tab[yy];
if ((sprite_subtype[k] & 7) < 5) {
int8 n = sprite_F[k] ? 3 : 1;
SpriteAddXY(k, (yy & 1) ? -n : n, 0);
}
}
void Sprite_CheckForTileInDirection_vertical(int k, int yy) { // 86e5ee
if (!Sprite_CheckTileInDirection(k, yy))
return;
sprite_wallcoll[k] |= kSprite_Func7_Tab[yy];
if ((sprite_subtype[k] & 7) < 5) {
int8 n = sprite_F[k] ? 3 : 1;
SpriteAddXY(k, 0, (yy & 1) ? -n : n);
}
}
void SpriteFall_AdjustPosition(int k) { // 86e624
SpriteAddXY(k, dung_floor_x_vel, dung_floor_y_vel);
}
bool Sprite_CheckTileInDirection(int k, int yy) { // 86e72f
uint8 t = (sprite_flags[k] & 0xf0);
yy = 2 * ((t >> 2) + yy);
return Sprite_CheckTileProperty(k, yy);
}
bool Sprite_CheckTileProperty(int k, int j) { // 86e73c
uint16 x, y;
bool in_bounds;
j >>= 1;
if (player_is_indoors) {
x = (cur_sprite_x + 8 & 0x1ff) + kSprite_Func5_X[j] - 8;
y = (cur_sprite_y + 8 & 0x1ff) + kSprite_Func5_Y[j] - 8;
in_bounds = (x < 0x200) && (y < 0x200);
} else {
x = cur_sprite_x + kSprite_Func5_X[j];
y = cur_sprite_y + kSprite_Func5_Y[j];
in_bounds = (uint16)(x - sprcoll_x_base) < sprcoll_x_size &&
(uint16)(y - sprcoll_y_base) < sprcoll_y_size;
}
if (!in_bounds) {
if (sprite_flags2[k] & 0x40) {
sprite_state[k] = 0;
return false;
} else {
return true;
}
}
int b = Sprite_GetTileAttribute(k, &x, y);
if (sprite_defl_bits[k] & 8) {
uint8 a = kSprite_SimplifiedTileAttr[b];
if (a == 4) {
if (!player_is_indoors)
sprite_E[k] = 4;
} else if (a >= 1) {
return (sprite_tiletype >= 0x10 && sprite_tiletype < 0x14) ? Entity_CheckSlopedTileCollision(x, y) : true;
}
return false;
}
if (sprite_flags5[k] & 0x40) {
uint8 type = sprite_type[k];
if ((type == 0xd2 || type == 0x8a) && b == 9)
return false;
if (type == 0x94 && !sprite_E[k] || type == 0xe3 || type == 0x8c || type == 0x9a || type == 0x81)
return (b != 8) && (b != 9);
}
if (kSprite_Func5_Tab3[b] == 0)
return false;
if (sprite_tiletype >= 0x10 && sprite_tiletype < 0x14)
return Entity_CheckSlopedTileCollision(x, y);
if (sprite_tiletype == 0x44) {
if (sprite_F[k] && !sign8(sprite_give_damage[k])) {
// Some mothula bug fix because we changed damage class 4.
if (sprite_type[k] == 0x88 && (enhanced_features0 & kFeatures0_MiscBugFixes)) {
if (sprite_hit_timer[k] == 0)
Ancilla_CheckDamageToSprite_preset(k, 6);
} else {
Ancilla_CheckDamageToSprite_preset(k, 4);
}
if (sprite_hit_timer[k]) {
sprite_hit_timer[k] = 153;
sprite_F[k] = 0;
}
}
} else if (sprite_tiletype == 0x20) {
return !(sprite_flags[k] & 1) || !sprite_F[k];
}
return true;
}
uint8 GetTileAttribute(uint8 floor, uint16 *x, uint16 y) { // 86e87b
uint8 tiletype;
if (player_is_indoors) {
int t = (floor >= 1) ? 0x1000 : 0;
t += (*x & 0x1f8) >> 3;
t += (y & 0x1f8) << 3;
tiletype = dung_bg2_attr_table[t];
} else {
tiletype = Overworld_GetTileAttributeAtLocation(*x >>= 3, y);
}
sprite_tiletype = tiletype;
return tiletype;
}
uint8 Sprite_GetTileAttribute(int k, uint16 *x, uint16 y) { // 86e883
return GetTileAttribute(sprite_floor[k], x, y);
}
bool Entity_CheckSlopedTileCollision(uint16 x, uint16 y) { // 86e8fe
uint8 a = y & 7;
uint8 r6 = sprite_tiletype - 0x10;
uint8 b = kSlopedTile[r6 * 8 + (x & 7)];
return (r6 < 2) ? (b >= a) : (a >= b);
}
void Sprite_MoveXY(int k) { // 86e92c
Sprite_MoveX(k);
Sprite_MoveY(k);
}
void Sprite_MoveX(int k) { // 86e932
if (sprite_x_vel[k] != 0) {
uint32 t = sprite_x_subpixel[k] + (sprite_x_lo[k] << 8) + (sprite_x_hi[k] << 16) + ((int8)sprite_x_vel[k] << 4);
sprite_x_subpixel[k] = t, sprite_x_lo[k] = t >> 8, sprite_x_hi[k] = t >> 16;
}
}
void Sprite_MoveY(int k) { // 86e93e
if (sprite_y_vel[k] != 0) {
uint32 t = sprite_y_subpixel[k] + (sprite_y_lo[k] << 8) + (sprite_y_hi[k] << 16) + ((int8)sprite_y_vel[k] << 4);
sprite_y_subpixel[k] = t, sprite_y_lo[k] = t >> 8, sprite_y_hi[k] = t >> 16;
}
}
void Sprite_MoveZ(int k) { // 86e96c
uint16 z = (sprite_z[k] << 8 | sprite_z_subpos[k]) + ((int8)sprite_z_vel[k] << 4);
sprite_z_subpos[k] = z;
sprite_z[k] = z >> 8;
}
ProjectSpeedRet Sprite_ProjectSpeedTowardsLink(int k, uint8 vel) { // 86e991
if (vel == 0) {
ProjectSpeedRet rv = { 0, 0, 0, 0 };
return rv;
}
PairU8 below = Sprite_IsBelowLink(k);
uint8 r12 = sign8(below.b) ? -below.b : below.b;
PairU8 right = Sprite_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;
}
void Sprite_ApplySpeedTowardsLink(int k, uint8 vel) { // 86ea04
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, vel);
sprite_x_vel[k] = pt.x;
sprite_y_vel[k] = pt.y;
}
ProjectSpeedRet Sprite_ProjectSpeedTowardsLocation(int k, uint16 x, uint16 y, uint8 vel) { // 86ea2d
if (vel == 0) {
ProjectSpeedRet rv = { 0, 0, 0, 0 };
return rv;
}
PairU8 below = Sprite_IsBelowLocation(k, y);
uint8 r12 = sign8(below.b) ? -below.b : below.b;
PairU8 right = Sprite_IsRightOfLocation(k, x);
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;
}
uint8 Sprite_DirectionToFaceLink(int k, PointU8 *coords_out) { // 86eaa4
PairU8 below = Sprite_IsBelowLink(k);
PairU8 right = Sprite_IsRightOfLink(k);
uint8 ym = sign8(below.b) ? -below.b : below.b;
tmp_counter = ym;
uint8 xm = sign8(right.b) ? -right.b : right.b;
if (coords_out)
coords_out->x = right.b, coords_out->y = below.b;
return (xm >= ym) ? right.a : below.a + 2;
}
PairU8 Sprite_IsRightOfLink(int k) { // 86ead1
uint16 x = link_x_coord - Sprite_GetX(k);
PairU8 rv = { (uint8)(sign16(x) ? 1 : 0), (uint8)x };
return rv;
}
PairU8 Sprite_IsBelowLink(int k) { // 86eae8
int t = BYTE(link_y_coord) + 8;
int u = (t & 0xff) + sprite_z[k];
int v = (u & 0xff) - sprite_y_lo[k];
int w = HIBYTE(link_y_coord) - sprite_y_hi[k] - (v < 0);
uint8 y = (w & 0xff) + (t >> 8) + (u >> 8);
PairU8 rv = { (uint8)(sign8(y) ? 1 : 0), (uint8)v };
return rv;
}
PairU8 Sprite_IsRightOfLocation(int k, uint16 x) { // 86eb0a
uint16 xv = x - Sprite_GetX(k);
PairU8 rv = { (uint8)(sign16(xv) ? 1 : 0), (uint8)xv };
return rv;
}
PairU8 Sprite_IsBelowLocation(int k, uint16 y) { // 86eb1d
uint16 yv = y - Sprite_GetY(k);
PairU8 rv = { (uint8)(sign16(yv) ? 1 : 0), (uint8)yv };
return rv;
}
uint8 Sprite_DirectionToFaceLocation(int k, uint16 x, uint16 y) { // 86eb30
PairU8 below = Sprite_IsBelowLocation(k, y);
PairU8 right = Sprite_IsRightOfLocation(k, x);
uint8 ym = sign8(below.b) ? -below.b : below.b;
tmp_counter = ym;
uint8 xm = sign8(right.b) ? -right.b : right.b;
return (xm >= ym) ? right.a : below.a + 2;
}
void Guard_ParrySwordAttacks(int k) { // 86eb5e
if (link_is_on_lower_level != sprite_floor[k] || link_incapacitated_timer | link_auxiliary_state || sign8(sprite_hit_timer[k]))
return;
SpriteHitBox hb;
Sprite_DoHitBoxesFast(k, &hb);
if (link_position_mode & 0x10 || player_oam_y_offset == 0x80) {
Sprite_AttemptDamageToLinkWithCollisionCheck(k);
return;
}
Player_SetupActionHitBox(&hb);
if (sign8(button_b_frames) || !CheckIfHitBoxesOverlap(&hb)) {
Sprite_SetupHitBox(k, &hb);
if (!CheckIfHitBoxesOverlap(&hb))
Sprite_AttemptDamageToLinkWithCollisionCheck(k);
else
Sprite_AttemptZapDamage(k);
return;
}
if (sprite_type[k] != 0x6a)
sprite_F[k] = kSprite_Func1_Tab[GetRandomNumber() & 7];
link_incapacitated_timer = kSprite_Func1_Tab2[GetRandomNumber() & 7];
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, sign8(button_b_frames - 9) ? 32 : 24);
sprite_x_recoil[k] = -pt.x;
sprite_y_recoil[k] = -pt.y;
Sprite_ApplyRecoilToLink(k, sign8(button_b_frames - 9) ? 8 : 16);
Link_PlaceWeaponTink();
set_when_damaging_enemies = 0x90;
}
void Sprite_AttemptZapDamage(int k) { // 86ec02
uint8 a = sprite_type[k];
if ((a == 0x7a || a == 0xd && (a = link_sword_type) < 4 || (a == 0x24 || a == 0x23) && sprite_delay_main[k] != 0) && sprite_state[k] == 9) {
if (!countdown_for_blink) {
sprite_delay_aux1[k] = 64;
link_electrocute_on_touch = 64;
Sprite_AttemptDamageToLinkPlusRecoil(k);
}
} else {
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, sign8(button_b_frames - 9) ? 0x50 : 0x40);
sprite_x_recoil[k] = -pt.x;
sprite_y_recoil[k] = -pt.y;
Sprite_CalculateSwordDamage(k);
}
}
void Ancilla_CheckDamageToSprite_preset(int k, int a) { // 86ece0
if (a == 15 && sprite_z[k] != 0)
return;
if (a != 0 && a != 7) {
Sprite_Func15(k, a);
return;
}
Sprite_Func15(k, a);
if (sprite_give_damage[k] || repulsespark_timer)
return;
// Called when hitting enemy which is frozen
repulsespark_timer = 5;
int j = byte_7E0FB6;
repulsespark_x_lo = ancilla_x_lo[j] + 4;
repulsespark_y_lo = ancilla_y_lo[j];
repulsespark_floor_status = link_is_on_lower_level;
sound_effect_1 = 0;
SpriteSfx_QueueSfx2WithPan(k, 5);
}
void Sprite_Func15(int k, int a) { // 86ed25
damage_type_determiner = a;
Sprite_ApplyCalculatedDamage(k, a == 8 ? 0x35 : 0x20);
}
void Sprite_CalculateSwordDamage(int k) { // 86ed3f
if (sprite_flags3[k] & 0x40)
return;
sprite_unk1[k] = link_is_running;
uint8 a = link_sword_type - 1;
if (!link_is_running)
a |= sign8(button_b_frames) ? 4 : sign8(button_b_frames - 9) ? 0 : 8;
damage_type_determiner = kSprite_Func14_Damage[a];
if (link_item_in_hand & 10)
damage_type_determiner = 3;
link_sword_delay_timer = 4;
set_when_damaging_enemies = 16;
Sprite_ApplyCalculatedDamage(k, 0x9d);
}
void Sprite_ApplyCalculatedDamage(int k, int a) { // 86ed89
if ((sprite_flags3[k] & 0x40) || sprite_type[k] >= 0xD8)
return;
uint8 dmg = kEnemyDamages[damage_type_determiner * 8 | enemy_damage_data[sprite_type[k] * 16 | damage_type_determiner]];
Sprite_GiveDamage(k, dmg, a);
}
void Sprite_GiveDamage(int k, uint8 dmg, uint8 r0_hit_timer) { // 86edc5
if (dmg == 249) {
Sprite_Func18(k, 0xe3);
return;
}
if (dmg == 250) {
Sprite_Func18(k, 0x8f);
sprite_ai_state[k] = 2;
sprite_z_vel[k] = 32;
sprite_oam_flags[k] = 8;
sprite_F[k] = 0;
sprite_hit_timer[k] = 0;
sprite_health[k] = 0;
sprite_bump_damage[k] = 1;
sprite_flags5[k] = 1;
return;
}
if (dmg >= sprite_give_damage[k])
sprite_give_damage[k] = dmg;
if (dmg == 0) {
if (damage_type_determiner != 10) {
if (sprite_flags[k] & 4)
goto flag4;
link_sword_delay_timer = 0;
}
sprite_hit_timer[k] = 0;
sprite_give_damage[k] = 0;
return;
}
if (dmg >= 254 && sprite_state[k] == 11) {
sprite_hit_timer[k] = 0;
sprite_give_damage[k] = 0;
return;
}
if (sprite_type[k] == 0x9a && sprite_give_damage[k] < 0xf0) {
sprite_state[k] = 9;
sprite_ai_state[k] = 4;
sprite_delay_main[k] = 15;
SpriteSfx_QueueSfx2WithPan(k, 0x28);
return;
}
if (sprite_type[k] == 0x1b) {
SpriteSfx_QueueSfx2WithPan(k, 5);
Sprite_ScheduleForBreakage(k);
Sprite_PlaceWeaponTink(k);
return;
}
sprite_hit_timer[k] = r0_hit_timer;
if (sprite_type[k] != 0x92 || sprite_C[k] >= 3) {
uint8 sfx = sprite_flags[k] & 2 ? 0x21 :
sprite_flags5[k] & 0x10 ? 0x1c : 8;
sound_effect_2 = sfx | Sprite_CalculateSfxPan(k);
}
uint8 type;
flag4:
type = sprite_type[k];
sprite_F[k] = (damage_type_determiner >= 13) ? 0 :
(type == 9) ? 20 :
(type == 0x53 || type == 0x18) ? 11 : 15;
}
void Sprite_Func18(int k, uint8 new_type) { // 86edcb
sprite_type[k] = new_type;
SpritePrep_LoadProperties(k);
Sprite_SpawnPoofGarnish(k);
sound_effect_2 = 0;
SpriteSfx_QueueSfx3WithPan(k, 0x32);
sprite_hit_timer[k] = 0;
sprite_give_damage[k] = 0;
}
void Sprite_MiniMoldorm_Recoil(int k) { // 86eec8
if (sprite_state[k] < 9)
return;
tmp_counter = sprite_state[k];
uint8 dmg = sprite_give_damage[k];
if (dmg == 253) {
sprite_give_damage[k] = 0;
SpriteSfx_QueueSfx3WithPan(k, 9);
sprite_state[k] = 7;
sprite_delay_main[k] = 0x70;
sprite_flags2[k] += 2;
sprite_give_damage[k] = 0;
return;
}
if (dmg >= 251) {
sprite_give_damage[k] = 0;
if (sprite_state[k] == 11)
return;
sprite_unk5[k] = (dmg == 254);
if (sprite_unk5[k]) {
sprite_defl_bits[k] |= 8;
sprite_flags5[k] &= ~0x80;
SpriteSfx_QueueSfx2WithPan(k, 15);
sprite_z_vel[k] = 24;
sprite_bump_damage[k] &= ~0x80;
Sprite_ZeroVelocity_XY(k);
}
sprite_state[k] = 11;
sprite_delay_main[k] = 64;
static const uint8 kHitTimer24StunValues[5] = {0x20, 0x80, 0, 0, 0xff};
sprite_stunned[k] = kHitTimer24StunValues[(uint8)(dmg + 5)];
if (sprite_type[k] == 0x23)
sprite_type[k] = 0x24;
return;
}
int t = sprite_health[k] - sprite_give_damage[k];
sprite_health[k] = t;
sprite_give_damage[k] = 0;
if (t > 0)
return;
if (sprite_die_action[k] == 0) {
if (sprite_state[k] == 11)
sprite_die_action[k] = 3;
if (sprite_unk1[k] != 0) {
sprite_unk1[k] = 0;
sprite_flags5[k] = 0;
}
}
uint8 type = sprite_type[k];
if (type != 0x1b)
SpriteSfx_QueueSfx3WithPan(k, 9);
if (type == 0x40)
save_ow_event_info[BYTE(overworld_screen_index)] |= 0x40;
else if (type == 0xec) {
if (sprite_C[k] == 2)
ThrowableScenery_TransmuteToDebris(k);
return;
}
if (sprite_state[k] == 10) {
link_state_bits = 0;
link_picking_throw_state = 0;
}
sprite_state[k] = 6;
if (type == 0xc) {
Sprite_Func3(k);
} else if (type == 0x92) {
Sprite_KillFriends();
sprite_delay_main[k] = 255;
goto out_common;
} else if (type == 0xcb) {
sprite_ai_state[k] = 128;
sprite_delay_main[k] = 128;
sprite_state[k] = 9;
goto out_common;
} else if (type == 0xcc || type == 0xcd) {
sprite_ai_state[k] = 128;
sprite_delay_main[k] = 96;
sprite_state[k] = 9;
goto out_common;
} else if (type == 0x53) {
sprite_delay_main[k] = 35;
sprite_hit_timer[k] = 0;
goto out_common2;
} else if (type == 0x54) {
sprite_ai_state[k] = 5;
sprite_delay_main[k] = 0xc0;
sprite_hit_timer[k] = 0xc0;
goto out_common;
} else if (type == 0x9) {
sprite_ai_state[k] = 3;
sprite_delay_aux4[k] = 160;
sprite_state[k] = 9;
goto out_common;
} else if (type == 0x7a) {
Sprite_KillFriends();
sprite_state[k] = 9;
sprite_ignore_projectile[k] = 9;
if (is_in_dark_world == 0) {
sprite_ai_state[k] = 10;
sprite_delay_main[k] = 255;
sprite_z_vel[k] = 32;
} else {
sprite_delay_main[k] = 255;
sprite_ai_state[k] = 8;
sprite_ai_state[1] = 9;
sprite_ai_state[2] = 9;
sprite_graphics[1] = 0;
sprite_graphics[2] = 0;
}
goto out_common;
} else if (type == 0x23 && sprite_C[k] == 0) {
sprite_ai_state[k] = 2;
sprite_delay_main[k] = 32;
sprite_state[k] = 9;
sprite_hit_timer[k] = 0;
} else if (type == 0xf) {
sprite_hit_timer[k] = 0;
sprite_delay_main[k] = 15;
} else if (!(sprite_flags[k] & 2)) {
sprite_delay_main[k] = sprite_hit_timer[k] & 0x80 ? 31 : 15;
sprite_flags2[k] += 4;
if (tmp_counter == 11)
sprite_flags5[k] = 1;
} else {
if (type != 0xa2)
Sprite_KillFriends();
sprite_state[k] = 4;
sprite_A[k] = 0;
sprite_delay_main[k] = 255;
sprite_hit_timer[k] = 255;
out_common:
flag_block_link_menu++;
out_common2:
sound_effect_2 = 0;
SpriteSfx_QueueSfx3WithPan(k, 0x22);
}
}
void Sprite_Func3(int k) { // 86efda
sprite_state[k] = 6;
sprite_delay_main[k] = 31;
sprite_flags2[k] = 3;
}
bool Sprite_CheckDamageToLink(int k) { // 86f145
if (link_disable_sprite_damage)
return false;
return Sprite_CheckDamageToPlayer_1(k);
}
bool Sprite_CheckDamageToPlayer_1(int k) { // 86f14a
if ((k ^ frame_counter) & 3 | sprite_hit_timer[k])
return false;
return Sprite_CheckDamageToLink_same_layer(k);
}
bool Sprite_CheckDamageToLink_same_layer(int k) { // 86f154
if (link_is_on_lower_level != sprite_floor[k])
return false;
return Sprite_CheckDamageToLink_ignore_layer(k);
}
bool Sprite_CheckDamageToLink_ignore_layer(int k) { // 86f15c
uint8 carry, t;
if (sprite_flags4[k]) {
SpriteHitBox hitbox;
Link_SetupHitBox(&hitbox);
// Set hitbox to the sword hitbox if the item type is an absorbable
if (sprite_type[k] >= 0xd8 && sprite_type[k] <= 0xe6 && (enhanced_features0 & kFeatures0_CollectItemsWithSword))
Link_UpdateHitBoxWithSword(&hitbox);
Sprite_SetupHitBox(k, &hitbox);
carry = CheckIfHitBoxesOverlap(&hitbox);
} else {
carry = Sprite_SetupHitBox00(k);
}
if (sign8(sprite_flags2[k]))
return carry;
if (!carry || link_auxiliary_state)
return false;
if (link_is_bunny_mirror || sign8(link_state_bits) || !(sprite_flags5[k] & 0x20) || !link_shield_type)
goto if_3;
sprite_state[k] = 0;
t = button_b_frames ? kSpriteDamage_Tab2[link_direction_facing >> 1] : link_direction_facing;
if (t != kSpriteDamage_Tab3[sprite_D[k]]) {
if_3:
Sprite_AttemptDamageToLinkPlusRecoil(k);
if (sprite_type[k] == 0xc)
Sprite_Func3(k);
return true;
}
SpriteSfx_QueueSfx2WithPan(k, 6);
Sprite_PlaceRupulseSpark_2(k);
if (sprite_type[k] == 0x95) {
SpriteSfx_QueueSfx3WithPan(k, 0x26);
return false;
} else if (sprite_type[k] == 0x9B) {
Sprite_Invert_XY_Speeds(k);
sprite_D[k] ^= 1;
sprite_ai_state[k]++;
sprite_state[k] = 9;
return false;
} else if (sprite_type[k] == 0x1B) { // arrow
Sprite_ScheduleForBreakage(k);
return false; // unk ret val
} else if (sprite_type[k] == 0xc) {
Sprite_Func3(k);
return true;
} else {
return false; // unk ret val
}
}
bool Sprite_SetupHitBox00(int k) { // 86f1f6
return (uint16)(link_x_coord - cur_sprite_x + 11) < 23 &&
(uint16)(link_y_coord - cur_sprite_y + sprite_z[k] + 16) < 24;
}
bool Sprite_ReturnIfLifted(int k) { // 86f228
if (submodule_index | button_b_frames | flag_unk1 || sprite_floor[k] != link_is_on_lower_level)
return false;
for (int j = 15; j >= 0; j--)
if (sprite_state[j] == 10)
return false;
if (sprite_type[k] != 0xb && sprite_type[k] != 0x4a && (sprite_x_vel[k] | sprite_y_vel[k]) != 0)
return false;
if (link_is_running)
return false;
return Sprite_ReturnIfLiftedPermissive(k);
}
bool Sprite_ReturnIfLiftedPermissive(int k) { // 86f257
if (link_is_running)
return false;
if ((uint8)(flag_is_sprite_to_pick_up_cached - 1) != cur_object_index) {
SpriteHitBox hb;
Link_SetupHitBox_conditional(&hb);
Sprite_SetupHitBox(k, &hb);
if (CheckIfHitBoxesOverlap(&hb))
byte_7E0FB2 = flag_is_sprite_to_pick_up = k + 1;
return false;
} else {
BYTE(filtered_joypad_L) = 0;
sprite_E[k] = 0;
SpriteSfx_QueueSfx2WithPan(k, 0x1d);
sprite_unk4[k] = sprite_state[k];
sprite_state[k] = 10;
sprite_delay_main[k] = 16;
sprite_unk3[k] = 0;
sprite_I[k] = 0;
link_direction_facing = kSprite_ReturnIfLifted_Dirs[Sprite_DirectionToFaceLink(k, NULL)];
return true;
}
}
uint8 Sprite_CheckDamageFromLink(int k) { // 86f2b4
if (sprite_hit_timer[k] & 0x80 || sprite_floor[k] != link_is_on_lower_level || player_oam_y_offset == 0x80)
return 0;
SpriteHitBox hb;
Player_SetupActionHitBox(&hb);
Sprite_SetupHitBox(k, &hb);
if (!CheckIfHitBoxesOverlap(&hb))
return 0;
set_when_damaging_enemies = 0;
if (link_position_mode & 0x10)
return kCheckDamageFromPlayer_Carry | kCheckDamageFromPlayer_Ne;
if (link_item_in_hand & 10) {
if (sprite_type[k] >= 0xd6)
return 0;
if (sprite_state[k] == 11 && sprite_unk5[k] != 0) {
sprite_state[k] = 2;
sprite_delay_main[k] = 32;
sprite_flags2[k] = (sprite_flags2[k] & 0xe0) | 3;
SpriteSfx_QueueSfx2WithPan(k, 0x1f);
return kCheckDamageFromPlayer_Carry | kCheckDamageFromPlayer_Ne;
}
}
uint8 type = sprite_type[k];
if (type == 0x7b) {
if (!sign8(button_b_frames - 9))
return 0;
} else if (type == 9) {
if (!sprite_A[k]) {
Sprite_ApplyRecoilToLink(k, 48);
set_when_damaging_enemies = 144;
link_incapacitated_timer = 16;
SpriteSfx_QueueSfx2WithPan(k, 0x21);
sprite_delay_aux1[k] = 48;
sound_effect_2 = Sprite_CalculateSfxPan(k) | (enhanced_features0 & kFeatures0_MiscBugFixes ? 0x32 : 0);
Link_PlaceWeaponTink();
return kCheckDamageFromPlayer_Carry;
}
} else if (type == 0x92) {
if (sprite_C[k] >= 3)
goto is_many;
goto getting_out;
} else if (type == 0x26 || type == 0x13 || type == 2) {
bool cond = (type == 0x13 && kSpriteDamage_Tab3[sprite_D[k]] == link_direction_facing) || (type == 2);
Sprite_AttemptZapDamage(k);
Sprite_ApplyRecoilToLink(k, 32);
set_when_damaging_enemies = 16;
link_incapacitated_timer = 16;
if (cond) {
sprite_hit_timer[k] = 0;
Link_PlaceWeaponTink();
}
return 0; // what return value?
} else if (type == 0xcb || type == 0xcd || type == 0xcc || type == 0xd6 || type == 0xd7 || type == 0xce || type == 0x54) {
is_many:
Sprite_ApplyRecoilToLink(k, 32);
set_when_damaging_enemies = 144;
link_incapacitated_timer = 16;
}
if (!(sprite_defl_bits[k] & 4)) {
Sprite_AttemptZapDamage(k);
return kCheckDamageFromPlayer_Carry;
}
getting_out:
if (!set_when_damaging_enemies) {
Sprite_ApplyRecoilToLink(k, 4);
link_incapacitated_timer = 16;
set_when_damaging_enemies = 16;
}
Link_PlaceWeaponTink();
return kCheckDamageFromPlayer_Carry;
}
void Sprite_AttemptDamageToLinkWithCollisionCheck(int k) { // 86f3ca
if ((k ^ frame_counter) & 1)
return;
SpriteHitBox hb;
Sprite_DoHitBoxesFast(k, &hb);
Link_SetupHitBox_conditional(&hb);
if (CheckIfHitBoxesOverlap(&hb))
Sprite_AttemptDamageToLinkPlusRecoil(k);
}
void Sprite_AttemptDamageToLinkPlusRecoil(int k) { // 86f3db
if (countdown_for_blink | link_disable_sprite_damage)
return;
link_incapacitated_timer = 19;
Sprite_ApplyRecoilToLink(k, 24);
link_auxiliary_state = 1;
link_give_damage = kPlayerDamages[3 * (sprite_bump_damage[k] & 0xf) + link_armor];
if (sprite_type[k] == 0x61 && sprite_C[k]) {
link_actual_vel_x = sprite_x_vel[k] * 2;
link_actual_vel_y = sprite_y_vel[k] * 2;
}
}
void Player_SetupActionHitBox(SpriteHitBox *hb) { // 86f5e0
if (link_is_running) {
int j = link_direction_facing >> 1;
int x = link_x_coord + (kPlayerActionBoxRun_XLo[j] | kPlayerActionBoxRun_XHi[j] << 8);
int y = link_y_coord + (kPlayerActionBoxRun_YLo[j] | kPlayerActionBoxRun_YHi[j] << 8);
hb->r0_xlo = x;
hb->r8_xhi = x >> 8;
hb->r1_ylo = y;
hb->r9_yhi = y >> 8;
hb->r2 = hb->r3 = 16;
} else {
int t = 0;
if (!(link_item_in_hand & 10) && !(link_position_mode & 0x10)) {
if (sign8(button_b_frames)) {
int x = link_x_coord - 14;
int y = link_y_coord - 10;
hb->r0_xlo = x;
hb->r8_xhi = x >> 8;
hb->r1_ylo = y;
hb->r9_yhi = y >> 8;
hb->r2 = 44;
hb->r3 = 45;
return;
} else if (kPlayer_SetupActionHitBox_Tab4[button_b_frames]) {
hb->r8_xhi = 0x80;
return;
}
t = link_direction_facing * 8 + button_b_frames + 1;
}
int x = link_x_coord + (int8)(kPlayer_SetupActionHitBox_X[t] + player_oam_x_offset);
int y = link_y_coord + (int8)(kPlayer_SetupActionHitBox_Y[t] + player_oam_y_offset);
hb->r0_xlo = x;
hb->r8_xhi = x >> 8;
hb->r1_ylo = y;
hb->r9_yhi = y >> 8;
hb->r2 = kPlayer_SetupActionHitBox_W[t];
hb->r3 = kPlayer_SetupActionHitBox_H[t];
}
}
void Link_UpdateHitBoxWithSword(SpriteHitBox *hb) { // new
if (link_spin_attack_step_counter != 0 || sign8(button_b_frames) ||
kPlayer_SetupActionHitBox_Tab4[button_b_frames])
return;
int t = link_direction_facing * 8 + button_b_frames + 1, r;
int x = link_x_coord + (int8)(kPlayer_SetupActionHitBox_X[t] + player_oam_x_offset);
int y = link_y_coord + (int8)(kPlayer_SetupActionHitBox_Y[t] + player_oam_y_offset);
// Reduce size of hitbox if 'too' big.
hb->r2 = kPlayer_SetupActionHitBox_W[t];
if (hb->r2 - 2 >= 0)
r = IntMin(6, hb->r2 - 2), hb->r2 -= r, x += r >> 1;
hb->r3 = kPlayer_SetupActionHitBox_H[t];
if (hb->r3 - 2 >= 0)
r = IntMin(6, hb->r3 - 2), hb->r3 -= r, y += r >> 1;
hb->r0_xlo = x;
hb->r8_xhi = x >> 8;
hb->r1_ylo = y;
hb->r9_yhi = y >> 8;
}
void Sprite_DoHitBoxesFast(int k, SpriteHitBox *hb) { // 86f645
if (HIBYTE(dungmap_var8) == 0x80) {
hb->r10_spr_xhi = 0x80;
return;
}
int t;
t = Sprite_GetX(k) + (int8)HIBYTE(dungmap_var8);
hb->r4_spr_xlo = t;
hb->r10_spr_xhi = t >> 8;
t = Sprite_GetY(k) + (int8)BYTE(dungmap_var8);
hb->r5_spr_ylo = t;
hb->r11_spr_yhi = t >> 8;
hb->r6_spr_xsize = hb->r7_spr_ysize = (sprite_type[k] == 0x6a) ? 16 : 3;
}
void Sprite_ApplyRecoilToLink(int k, uint8 vel) { // 86f688
ProjectSpeedRet pt = Sprite_ProjectSpeedTowardsLink(k, vel);
link_actual_vel_x = pt.x;
link_actual_vel_y = pt.y;
g_ram[0xc7] = link_actual_vel_z = vel >> 1;
link_z_coord = 0;
}
void Link_PlaceWeaponTink() { // 86f69f
if (repulsespark_timer)
return;
repulsespark_timer = 5;
int t = (uint8)link_x_coord + player_oam_x_offset;
repulsespark_x_lo = t;
t = (uint8)link_y_coord + player_oam_y_offset + (t >> 8); // carry wtf
repulsespark_y_lo = t;
repulsespark_floor_status = link_is_on_lower_level;
sound_effect_1 = Link_CalculateSfxPan() | 5;
}
void Sprite_PlaceWeaponTink(int k) { // 86f6ca
if (repulsespark_timer)
return;
SpriteSfx_QueueSfx2WithPan(k, 5);
Sprite_PlaceRupulseSpark_2(k);
}
void Sprite_PlaceRupulseSpark_2(int k) { // 86f6d5
uint16 x = Sprite_GetX(k) - BG2HOFS_copy2;
uint16 y = Sprite_GetY(k) - BG2VOFS_copy2;
if (x & ~0xff || y & ~0xff)
return;
repulsespark_x_lo = sprite_x_lo[k];
repulsespark_y_lo = sprite_y_lo[k];
repulsespark_timer = 5;
repulsespark_floor_status = sprite_floor[k];
}
void Link_SetupHitBox_conditional(SpriteHitBox *hb) { // 86f705
if (link_disable_sprite_damage)
hb->r9_yhi = 0x80;
else
Link_SetupHitBox(hb);
}
void Link_SetupHitBox(SpriteHitBox *hb) { // 86f70a
hb->r3 = hb->r2 = 8;
uint16 x = link_x_coord + 4;
hb->r0_xlo = x;
hb->r8_xhi = x >> 8;
uint16 y = link_y_coord + 8;
hb->r1_ylo = y;
hb->r9_yhi = y >> 8;
}
void Sprite_SetupHitBox(int k, SpriteHitBox *hb) { // 86f7ef
if (sign8(sprite_z[k])) {
hb->r10_spr_xhi = 0x80;
return;
}
int i = sprite_flags4[k] & 0x1f;
int t, u;
t = sprite_x_lo[k] + (uint8)kSpriteHitbox_XLo[i];
hb->r4_spr_xlo = t;
t = sprite_x_hi[k] + (uint8)kSpriteHitbox_XHi[i] + (t >> 8);
hb->r10_spr_xhi = t;
t = sprite_y_lo[k] + (uint8)kSpriteHitbox_YLo[i];
u = t >> 8;
t = (t & 0xff) - sprite_z[k];
hb->r5_spr_ylo = t;
t = sprite_y_hi[k] - (t < 0);
hb->r11_spr_yhi = t + u + (uint8)kSpriteHitbox_YHi[i];
hb->r6_spr_xsize = kSpriteHitbox_XSize[i];
hb->r7_spr_ysize = kSpriteHitbox_YSize[i];
}
// Returns the carry flag
bool CheckIfHitBoxesOverlap(SpriteHitBox *hb) { // 86f836
int t;
uint8 r15, r12;
if (hb->r8_xhi == 0x80 || hb->r10_spr_xhi == 0x80)
return false;
t = hb->r5_spr_ylo - hb->r1_ylo;
r15 = t + hb->r7_spr_ysize;
r12 = hb->r11_spr_yhi - hb->r9_yhi - (t < 0);
t = r12 + (((t & 0xff) + 0x80) >> 8);
if (t & 0xff)
return (t >= 0x100);
if ((uint8)(hb->r3 + hb->r7_spr_ysize) < r15)
return false;
t = hb->r4_spr_xlo - hb->r0_xlo;
r15 = t + hb->r6_spr_xsize;
r12 = hb->r10_spr_xhi - hb->r8_xhi - (t < 0);
t = r12 + (((t & 0xff) + 0x80) >> 8);
if (t & 0xff)
return (t >= 0x100);
if ((uint8)(hb->r2 + hb->r6_spr_xsize) < r15)
return false;
return true;
}
void Oam_AllocateDeferToPlayer(int k) { // 86f86c
if (sprite_floor[k] != link_is_on_lower_level)
return;
PairU8 right = Sprite_IsRightOfLink(k);
if ((uint8)(right.b + 0x10) >= 0x20)
return;
PairU8 below = Sprite_IsBelowLink(k);
if ((uint8)(below.b + 0x20) >= 0x48)
return;
uint8 nslots = ((sprite_flags2[k] & 0x1f) + 1) << 2;
if (below.a)
Oam_AllocateFromRegionC(nslots);
else
Oam_AllocateFromRegionB(nslots);
}
void SpriteModule_Die(int k) { // 86f8a2
SpriteDeath_MainEx(k, false);
}
void Sprite_DoTheDeath(int k) { // 86f923
uint8 type = sprite_type[k];
// This is how Vitreous knows whether to come out of his slime pool
if (type == 0xBE)
sprite_G[0]--;
if (type == 0xaa && sprite_E[k] != 0) {
uint8 bak = sprite_subtype[k];
PrepareEnemyDrop(k, kPikitDropItems[sprite_E[k] - 1]);
sprite_subtype[k] = bak;
if (bak == 1) {
sprite_oam_flags[k] = 9;
sprite_flags3[k] = 0xf0;
}
sprite_head_dir[k]++;
return;
}
// Resets the music in the village when the crazy green guards are killed.
if (type == 0x45 && sram_progress_indicator == 2 && BYTE(overworld_area_index) == 0x18)
music_control = 7;
uint8 drop_item = sprite_die_action[k];
if (drop_item != 0) {
sprite_subtype[k] = sprite_N[k];
sprite_N[k] = 255;
uint8 arg = (drop_item == 1) ? 0xe4 : // small key, big key or rupee
(drop_item == 3) ? 0xd9 : 0xe5;
PrepareEnemyDrop(k, arg);
return;
}
uint8 prize = sprite_flags5[k] & 0xf;
if (prize-- != 0) {
uint8 luck = item_drop_luck;
if (luck != 0) {
if (++luck_kill_counter >= 10)
item_drop_luck = 0;
if (luck == 1) {
ForcePrizeDrop(k, prize, 1);
return;
}
} else {
if (!(GetRandomNumber() & kPrizeMasks[prize])) {
ForcePrizeDrop(k, prize, prize);
return;
}
}
}
sprite_state[k] = 0;
SpriteDeath_Func4(k);
}
void ForcePrizeDrop(int k, uint8 prize, uint8 slot) { // 86f9bc
prize = prize * 8 | prizes_arr1[slot];
prizes_arr1[slot] = (prizes_arr1[slot] + 1) & 7;
PrepareEnemyDrop(k, kPrizeItems[prize]);
}
void PrepareEnemyDrop(int k, uint8 item) { // 86f9d1
sprite_type[k] = item;
if (item == 0xe5)
SpritePrep_BigKey_load_graphics(k);
else if (item == 0xe4)
SpritePrep_KeySetItemDrop(k);
sprite_state[k] = 9;
uint8 zbak = sprite_z[k];
SpritePrep_LoadProperties(k);
sprite_ignore_projectile[k]++;
uint8 pz = kPrizeZ[sprite_type[k] - 0xd8];
sprite_z_vel[k] = pz & 0xf0;
Sprite_SetX(k, Sprite_GetX(k) + (pz & 0xf));
sprite_z[k] = zbak;
sprite_delay_aux4[k] = 21;
sprite_stunned[k] = 255;
SpriteDeath_Func4(k);
}
void SpriteDeath_Func4(int k) { // 86fa25
if (sprite_type[k] == 0xa2 && Sprite_CheckIfScreenIsClear())
Ancilla_SpawnFallingPrize(4);
Sprite_ManuallySetDeathFlagUW(k);
num_sprites_killed++;
if (sprite_type[k] == 0x40) {
// evil barrier
sprite_state[k] = 9;
sprite_graphics[k] = 4;
SpriteDeath_MainEx(k, true);
}
}
void SpriteDeath_DrawPoof(int k) { // 86fb2a
if (dung_hdr_collision == 4)
sprite_obj_prio[k] = 0x30;
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
OamEnt *oam = GetOamCurPtr();
uint8 r12 = (sprite_flags3[k] & 0x20) >> 3;
int i = ((sprite_delay_main[k] & 0x1c) ^ 0x1c) + 3, n = 3;
do {
if (kPerishOverlay_Char[i]) {
oam->charnum = kPerishOverlay_Char[i];
oam->y = HIBYTE(dungmap_var7) - r12 + kPerishOverlay_Y[i];
oam->x = BYTE(dungmap_var7) - r12 + kPerishOverlay_X[i];
oam->flags = (info.flags & 0x30) | kPerishOverlay_Flags[i];
}
} while (oam++, i--, --n >= 0);
Sprite_CorrectOamEntries(k, 3, 0);
}
void SpriteModule_Fall2(int k) { // 86fbea
uint8 delay = sprite_delay_main[k];
if (!delay) {
sprite_state[k] = 0;
Sprite_ManuallySetDeathFlagUW(k);
return;
}
if (delay >= 0x40) {
if (sprite_oam_flags[k] != 5) {
if (!(delay & 7 | submodule_index | flag_unk1))
SpriteSfx_QueueSfx3WithPan(k, 0x31);
SpriteActive_Main(k);
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
Sprite_DrawDistress_custom(info.x, info.y - 8, delay + 20);
return;
}
sprite_delay_main[k] = delay = 63;
}
if (delay == 61)
SpriteSfx_QueueSfx2WithPan(k, 0x20);
int j = delay >> 1;
if (sprite_type[k] == 0x26 || sprite_type[k] == 0x13) {
sprite_graphics[k] = kSpriteFall_Tab2[j];
SpriteDraw_FallingHelmaBeetle(k);
} else {
uint8 t = kSpriteFall_Tab1[j];
if (t < 12)
t += kSpriteFall_Tab4[sprite_D[k]];
sprite_graphics[k] = t;
SpriteDraw_FallingHumanoid(k);
}
if (frame_counter & kSpriteFall_Tab3[sprite_delay_main[k] >> 3] | submodule_index)
return;
Sprite_CheckTileProperty(k, 0x68);
if (sprite_tiletype != 0x20) {
sprite_y_recoil[k] = 0;
sprite_x_recoil[k] = 0;
}
sprite_y_vel[k] = (int8)sprite_y_recoil[k] >> 2;
sprite_x_vel[k] = (int8)sprite_x_recoil[k] >> 2;
Sprite_MoveXY(k);
}
void SpriteDraw_FallingHelmaBeetle(int k) { // 86fd17
PrepOamCoordsRet info;
const DrawMultipleData *src = kSpriteDrawFall0Data + sprite_graphics[k];
if (sprite_type[k] == 0x13)
src += 6;
Sprite_DrawMultiple(k, src, 1, &info);
}
void SpriteDraw_FallingHumanoid(int k) { // 86fe5b
PrepOamCoordsRet info;
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
int q = sprite_graphics[k];
OamEnt *oam = GetOamCurPtr();
int n = (q < 12 && (q & 3) == 0) ? 3 : 0, nn = n;
do {
int i = q * 4 + n;
SetOamPlain(oam, info.x + kSpriteDrawFall1_X[i], info.y + kSpriteDrawFall1_Y[i],
kSpriteDrawFall1_Char[i], info.flags ^ kSpriteDrawFall1_Flags[i], kSpriteDrawFall1_Ext[i]);
} while (oam++, --n >= 0);
Sprite_CorrectOamEntries(k, nn, 0xff);
}
void Sprite_CorrectOamEntries(int k, int n, uint8 islarge) { // 86febc
OamEnt *oam = GetOamCurPtr();
uint8 *extp = &g_ram[oam_ext_cur_ptr];
uint16 spr_x = Sprite_GetX(k);
uint16 spr_y = Sprite_GetY(k);
uint8 scrollx = spr_x - BG2HOFS_copy2;
uint8 scrolly = spr_y - BG2VOFS_copy2;
do {
uint16 x = spr_x + (int8)(oam->x - scrollx);
uint16 y = spr_y + (int8)(oam->y - scrolly);
uint8 ext = sign8(islarge) ? (*extp & 2) : islarge;
*extp = ext + ((uint16)(x - BG2HOFS_copy2) >= 0x100);
if ((uint16)(y + 0x10 - BG2VOFS_copy2) >= 0x100)
oam->y = 0xf0;
} while (oam++, extp++, --n >= 0);
}
bool Sprite_ReturnIfRecoiling(int k) { // 86ff78
if (!sprite_F[k])
return false;
if (!(sprite_F[k] & 0x7f)) {
sprite_F[k] = 0;
return false;
}
uint8 yvbak = sprite_y_vel[k];
uint8 xvbak = sprite_x_vel[k];
if (!--sprite_F[k] && ((uint8)(sprite_x_recoil[k] + 0x20) >= 0x40 || (uint8)(sprite_y_recoil[k] + 0x20) >= 0x40))
sprite_F[k] = 144;
int i = sprite_F[k];
uint8 t;
if (!sign8(i) && !(frame_counter & kSprite2_ReturnIfRecoiling_Masks[i>>2])) {
sprite_y_vel[k] = sprite_y_recoil[k];
sprite_x_vel[k] = sprite_x_recoil[k];
if (!sign8(sprite_bump_damage[k]) && (t = (Sprite_CheckTileCollision(k) & 0xf))) {
if (t < 4)
sprite_x_recoil[k] = sprite_x_vel[k] = 0;
else
sprite_y_recoil[k] = sprite_y_vel[k] = 0;
} else {
Sprite_MoveXY(k);
}
}
sprite_y_vel[k] = yvbak;
sprite_x_vel[k] = xvbak;
return sprite_type[k] != 0x7a;
}
bool Sprite_CheckIfLinkIsBusy() { // 87f4d0
if (link_auxiliary_state | link_pose_for_item | (link_state_bits & 0x80))
return true;
for (int i = 4; i >= 0; i--) {
if (ancilla_type[i] == 0x27)
return true;
}
return false;
}
void Sprite_SetSpawnedCoordinates(int k, SpriteSpawnInfo *info) { // 89ae64
sprite_x_lo[k] = info->r0_x;
sprite_x_hi[k] = info->r0_x >> 8;
sprite_y_lo[k] = info->r2_y;
sprite_y_hi[k] = info->r2_y >> 8;
sprite_z[k] = info->r4_z;
}
bool Sprite_CheckIfScreenIsClear() { // 89af32
for (int i = 15; i >= 0; i--) {
if (sprite_state[i] && !(sprite_flags4[i] & 0x40)) {
uint16 x = Sprite_GetX(i) - BG2HOFS_copy2;
uint16 y = Sprite_GetY(i) - BG2VOFS_copy2;
if (x < 256 && y < 256)
return false;
}
}
return Sprite_CheckIfOverlordsClear();
}
bool Sprite_CheckIfRoomIsClear() { // 89af61
for (int i = 15; i >= 0; i--) {
if (sprite_state[i] && !(sprite_flags4[i] & 0x40))
return false;
}
return Sprite_CheckIfOverlordsClear();
}
bool Sprite_CheckIfOverlordsClear() { // 89af76
for (int i = 7; i >= 0; i--) {
if (overlord_type[i] == 0x14 || overlord_type[i] == 0x18)
return false;
}
return true;
}
void Sprite_InitializeMirrorPortal() { // 89af89
for (int k = 15; k >= 0; k--) {
if (sprite_state[k] && sprite_type[k] == 0x6c)
sprite_state[k] = 0;
}
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(0xff, 0x6c, &info);
if (j < 0)
j = 0;
Sprite_SetX(j, bird_travel_x_hi[15] << 8 | bird_travel_x_lo[15]);
Sprite_SetY(j, (bird_travel_y_hi[15] << 8 | bird_travel_y_lo[15]) + 8);
sprite_floor[j] = 0;
sprite_ignore_projectile[j] = 1;
}
void Sprite_InitializeSlots() { // 89afd6
for (int k = 15; k >= 0; k--) {
uint8 st = sprite_state[k], ty = sprite_type[k];
if (st != 0) {
if (st == 10) {
if (ty != 0xec && ty != 0xd2) {
link_picking_throw_state = 0;
link_state_bits = 0;
sprite_state[k] = 0;
}
} else {
if (ty != 0x6c && sprite_room[k] != BYTE(overworld_area_index))
sprite_state[k] = 0;
}
}
}
for (int k = 7; k >= 0; k--) {
if (overlord_type[k] && overlord_spawned_in_area[k] != BYTE(overworld_area_index))
overlord_type[k] = 0;
}
}
void Garnish_ExecuteUpperSlots() { // 89b08c
HandleScreenFlash();
if (garnish_active) {
for (int i = 29; i >= 15; i--)
Garnish_ExecuteSingle(i);
}
}
void Garnish_ExecuteLowerSlots() { // 89b097
if (garnish_active) {
for (int i = 14; i >= 0; i--)
Garnish_ExecuteSingle(i);
}
}
void Garnish_ExecuteSingle(int k) { // 89b0b6
cur_object_index = k;
uint8 type = garnish_type[k];
if (type == 0)
return;
if ((type == 5 || (submodule_index | flag_unk1) == 0) && garnish_countdown[k] != 0 && --garnish_countdown[k] == 0) {
garnish_type[k] = 0;
return;
}
uint8 sprsize = kGarnish_OamMemSize[garnish_type[k]];
if (sort_sprites_setting) {
if (garnish_floor[k])
Oam_AllocateFromRegionF(sprsize);
else
Oam_AllocateFromRegionD(sprsize);
} else {
Oam_AllocateFromRegionA(sprsize);
}
kGarnish_Funcs[garnish_type[k] - 1](k);
}
void Garnish15_ArrghusSplash(int k) { // 89b178
static const int8 kArrghusSplash_X[8] = {-12, 20, -10, 10, -8, 8, -4, 4};
static const int8 kArrghusSplash_Y[8] = {-4, -4, -2, -2, 0, 0, 0, 0};
static const uint8 kArrghusSplash_Char[8] = {0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xac, 0xac};
static const uint8 kArrghusSplash_Flags[8] = {0x34, 0x74, 0x34, 0x74, 0x34, 0x74, 0x34, 0x74};
static const uint8 kArrghusSplash_Ext[8] = {0, 0, 2, 2, 2, 2, 2, 2};
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
OamEnt *oam = GetOamCurPtr();
int g = (garnish_countdown[k] >> 1) & 6;
for (int i = 1; i >= 0; i--, oam++) {
int j = i + g;
SetOamPlain(oam, pt.x + kArrghusSplash_X[j], pt.y + kArrghusSplash_Y[j], kArrghusSplash_Char[j], kArrghusSplash_Flags[j], kArrghusSplash_Ext[j]);
}
}
void Garnish13_PyramidDebris(int k) { // 89b216
OamEnt *oam = GetOamCurPtr();
int y = (garnish_y_lo[k] << 8) + garnish_y_subpixel[k] + ((int8)garnish_y_vel[k] << 4);
garnish_y_subpixel[k] = y;
garnish_y_lo[k] = y >> 8;
int x = (garnish_x_lo[k] << 8) + garnish_x_subpixel[k] + ((int8)garnish_x_vel[k] << 4);
garnish_x_subpixel[k] = x;
garnish_x_lo[k] = x >> 8;
garnish_y_vel[k] = garnish_y_vel[k] + 3;
uint8 t;
if ((t = garnish_x_lo[k] - BG2HOFS_copy2) >= 248) {
garnish_type[k] = 0;
return;
}
oam->x = t;
if ((t = garnish_y_lo[k] - BG2VOFS_copy2) >= 240) {
garnish_type[k] = 0;
return;
}
oam->y = t;
oam->charnum = 0x5c;
oam->flags = (frame_counter << 3) & 0xc0 | 0x34;
bytewise_extended_oam[oam - oam_buf] = 0;
}
void Garnish11_WitheringGanonBatFlame(int k) { // 89b2b2
if ((submodule_index | flag_unk1) == 0) {
Garnish_SetY(k, Garnish_GetY(k) - 1);
}
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
OamEnt *oam = GetOamCurPtr();
SetOamPlain(oam + 0, pt.x + 0, pt.y, 0xa4, 0x22, 0);
SetOamPlain(oam + 1, pt.x + 8, pt.y, 0xa5, 0x22, 0);
}
void Garnish10_GanonBatFlame(int k) { // 89b306
static const uint8 kGanonBatFlame_Idx[32] = {
7, 6, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4,
5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4,
};
static const uint8 kGanonBatFlame_Char[7] = {0xac, 0xac, 0x66, 0x66, 0x8e, 0xa0, 0xa2};
static const uint8 kGanonBatFlame_Flags[7] = {1, 0x41, 1, 0x41, 0, 0, 0};
if (garnish_countdown[k] == 8)
garnish_type[k] = 0x11;
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
int j = kGanonBatFlame_Idx[garnish_countdown[k] >> 3];
SetOamPlain(GetOamCurPtr(), pt.x, pt.y, kGanonBatFlame_Char[j], kGanonBatFlame_Flags[j] | 0x22, 2);
Garnish_CheckPlayerCollision(k, pt.x, pt.y);
}
void Garnish0C_TrinexxIceBreath(int k) { // 89b34f
static const uint8 kTrinexxIce_Char[12] = {0xe8, 0xe8, 0xe6, 0xe6, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4};
static const uint8 kTrinexxIce_Flags[4] = {0, 0x40, 0xc0, 0x80};
if (garnish_countdown[k] == 0x50 && (submodule_index | flag_unk1) == 0) {
Dungeon_UpdateTileMapWithCommonTile(Garnish_GetX(k), Garnish_GetY(k) - 16, 18);
}
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
SetOamPlain(GetOamCurPtr(), pt.x, pt.y, kTrinexxIce_Char[garnish_countdown[k] >> 4],
kTrinexxIce_Flags[(garnish_countdown[k] >> 2) & 3] | 0x35, 2);
}
void Garnish14_KakKidDashDust(int k) { // 89b3bc
Garnish_DustCommon(k, 2);
}
void Garnish_WaterTrail(int k) { // 89b3c2
Garnish_DustCommon(k, 3);
}
void Garnish0A_CannonSmoke(int k) { // 89b3ee
static const uint8 kGarnish_CannonPoof_Char[2] = { 0x8a, 0x86 };
static const uint8 kGarnish_CannonPoof_Flags[4] = { 0x20, 0x10, 0x30, 0x30 };
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
int j = garnish_sprite[k];
SetOamPlain(GetOamCurPtr(), pt.x, pt.y, kGarnish_CannonPoof_Char[garnish_countdown[k] >> 3], kGarnish_CannonPoof_Flags[j] | 4, 2);
}
void Garnish09_LightningTrail(int k) { // 89b429
static const uint8 kLightningTrail_Char[8] = {0xcc, 0xec, 0xce, 0xee, 0xcc, 0xec, 0xce, 0xee};
static const uint8 kLightningTrail_Flags[8] = {0x31, 0x31, 0x31, 0x31, 0x71, 0x71, 0x71, 0x71};
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
int j = garnish_sprite[k];
SetOamPlain(GetOamCurPtr(), pt.x, pt.y,
kLightningTrail_Char[j] - (BYTE(dungeon_room_index2) == 0x20 ? 0x80 : 0),
(frame_counter << 1) & 0xe | kLightningTrail_Flags[j], 2);
Garnish_CheckPlayerCollision(k, pt.x, pt.y);
}
void Garnish_CheckPlayerCollision(int k, int x, int y) { // 89b459
if ((k ^ frame_counter) & 7 | countdown_for_blink | link_disable_sprite_damage)
return;
if ((uint8)(link_x_coord - BG2HOFS_copy2 - x + 12) < 24 &&
(uint8)(link_y_coord - BG2VOFS_copy2 - y + 22) < 28) {
link_auxiliary_state = 1;
link_incapacitated_timer = 16;
link_give_damage = 16;
link_actual_vel_x ^= 255;
link_actual_vel_y ^= 255;
}
}
void Garnish07_BabasuFlash(int k) { // 89b49e
static const uint8 kBabusuFlash_Char[4] = {0xa8, 0x8a, 0x86, 0x86};
static const uint8 kBabusuFlash_Flags[4] = {0x2d, 0x2c, 0x2c, 0x2c};
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
int j = garnish_countdown[k] >> 3;
SetOamPlain(GetOamCurPtr(), pt.x, pt.y, kBabusuFlash_Char[j], kBabusuFlash_Flags[j], 2);
}
void Garnish08_KholdstareTrail(int k) { // 89b4c6
static const int8 kGarnish_Nebule_XY[3] = { -1, -1, 0 };
static const uint8 kGarnish_Nebule_Char[3] = { 0x9c, 0x9d, 0x8d };
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
int i = garnish_countdown[k] >> 2;
int j = garnish_sprite[k];
SetOamPlain(GetOamCurPtr(), pt.x + kGarnish_Nebule_XY[i], pt.y + kGarnish_Nebule_XY[i], kGarnish_Nebule_Char[i],
(sprite_oam_flags[j] | sprite_obj_prio[j]) & ~1, 0);
}
void Garnish06_ZoroTrail(int k) { // 89b4fb
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
int j = garnish_sprite[k];
SetOamPlain(GetOamCurPtr(), pt.x, pt.y, 0x75, sprite_oam_flags[j] | sprite_obj_prio[j], 0);
}
void Garnish12_Sparkle(int k) { // 89b520
Garnish_SparkleCommon(k, 2);
}
void Garnish_SimpleSparkle(int k) { // 89b526
Garnish_SparkleCommon(k, 3);
}
void Garnish0E_TrinexxFireBreath(int k) { // 89b55d
static const uint8 kTrinexxLavaBubble_Char[4] = {0x83, 0xc7, 0x80, 0x9d};
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
int j = garnish_sprite[k];
SetOamPlain(GetOamCurPtr(), pt.x, pt.y, kTrinexxLavaBubble_Char[garnish_countdown[k] >> 3],
(sprite_oam_flags[j] | sprite_obj_prio[j]) & 0xf0 | 0xe, 0);
}
void Garnish0F_BlindLaserTrail(int k) { // 89b591
static const uint8 kBlindLaserTrail_Char[4] = {0x61, 0x71, 0x70, 0x60};
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
int j = garnish_sprite[k];
SetOamPlain(GetOamCurPtr(), pt.x, pt.y, kBlindLaserTrail_Char[garnish_oam_flags[k] - 7], sprite_oam_flags[j] | sprite_obj_prio[j], 0);
}
void Garnish04_LaserTrail(int k) { // 89b5bb
static const uint8 kLaserBeamTrail_Char[2] = {0xd2, 0xf3};
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
SetOamPlain(GetOamCurPtr(), pt.x, pt.y, kLaserBeamTrail_Char[garnish_oam_flags[k]], 0x25, 0);
}
bool Garnish_ReturnIfPrepFails(int k, Point16U *pt) { // 89b5de
uint16 x = Garnish_GetX(k) - BG2HOFS_copy2;
uint16 y = Garnish_GetY(k) - BG2VOFS_copy2;
if (x >= 256 || y >= 256) {
garnish_type[k] = 0;
return true;
}
pt->x = x;
pt->y = y - 16;
return false;
}
void Garnish03_FallingTile(int k) { // 89b627
static const uint8 kCrumbleTile_XY[5] = {4, 0, 0, 0, 0};
static const uint8 kCrumbleTile_Char[5] = {0x80, 0xcc, 0xcc, 0xea, 0xca};
static const uint8 kCrumbleTile_Flags[5] = {0x30, 0x31, 0x31, 0x31, 0x31};
static const uint8 kCrumbleTile_Ext[5] = {0, 2, 2, 2, 2};
int j;
if ((j = garnish_countdown[k]) == 0x1e && (j = (submodule_index | flag_unk1)) == 0)
Dungeon_UpdateTileMapWithCommonTile(Garnish_GetX(k), Garnish_GetY(k) - 16, 4);
j >>= 3;
uint16 x = Garnish_GetX(k) + kCrumbleTile_XY[j] - BG2HOFS_copy2;
uint16 y = Garnish_GetY(k) + kCrumbleTile_XY[j] - BG2VOFS_copy2;
if (x < 256 && y < 256)
SetOamPlain(GetOamCurPtr(), x, y - 16, kCrumbleTile_Char[j], kCrumbleTile_Flags[j], kCrumbleTile_Ext[j]);
}
void Garnish01_FireSnakeTail(int k) { // 89b6c0
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
int j = garnish_sprite[k];
SetOamPlain(GetOamCurPtr(), pt.x, pt.y, 0x28, sprite_oam_flags[j] | sprite_obj_prio[j], 2);
}
void Garnish02_MothulaBeamTrail(int k) { // 89b6e1
int j = garnish_sprite[k];
SetOamPlain(GetOamCurPtr(), garnish_x_lo[k] - BG2HOFS_copy2, garnish_y_lo[k] - BG2VOFS_copy2, 0xaa,
sprite_oam_flags[j] | sprite_obj_prio[j], 2);
}
void Dungeon_ResetSprites() { // 89c114
Dungeon_CacheTransSprites();
link_picking_throw_state = 0;
link_state_bits = 0;
Sprite_DisableAll();
sprcoll_x_size = sprcoll_y_size = 0xffff;
int j = FindInWordArray(dungeon_room_history, dungeon_room_index2, 4);
if (j < 0) {
uint16 blk = dungeon_room_history[3];
dungeon_room_history[3] = dungeon_room_history[2];
dungeon_room_history[2] = dungeon_room_history[1];
dungeon_room_history[1] = dungeon_room_history[0];
dungeon_room_history[0] = dungeon_room_index2;
if (blk != 0xffff)
sprite_where_in_room[blk] = 0;
}
Dungeon_LoadSprites();
}
void Dungeon_CacheTransSprites() { // 89c176
if (!player_is_indoors)
return;
alt_sprites_flag = player_is_indoors;
for (int k = 15; k >= 0; k--) {
alt_sprite_state[k] = 0;
alt_sprite_type[k] = sprite_type[k];
alt_sprite_x_lo[k] = sprite_x_lo[k];
alt_sprite_graphics[k] = sprite_graphics[k];
alt_sprite_x_hi[k] = sprite_x_hi[k];
alt_sprite_y_lo[k] = sprite_y_lo[k];
alt_sprite_y_hi[k] = sprite_y_hi[k];
if (sprite_pause[k] != 0 || sprite_state[k] == 4 || sprite_state[k] == 10)
continue;
alt_sprite_state[k] = sprite_state[k];
alt_sprite_A[k] = sprite_A[k];
alt_sprite_head_dir[k] = sprite_head_dir[k];
alt_sprite_oam_flags[k] = sprite_oam_flags[k];
alt_sprite_obj_prio[k] = sprite_obj_prio[k];
alt_sprite_D[k] = sprite_D[k];
alt_sprite_flags2[k] = sprite_flags2[k];
alt_sprite_floor[k] = sprite_floor[k];
alt_sprite_spawned_flag[k] = sprite_ai_state[k];
alt_sprite_flags3[k] = sprite_flags3[k];
alt_sprite_B[k] = sprite_B[k];
alt_sprite_C[k] = sprite_C[k];
alt_sprite_E[k] = sprite_E[k];
alt_sprite_subtype2[k] = sprite_subtype2[k];
alt_sprite_height_above_shadow[k] = sprite_z[k];
alt_sprite_delay_main[k] = sprite_delay_main[k];
alt_sprite_I[k] = sprite_I[k];
alt_sprite_maybe_ignore_projectile[k] = sprite_ignore_projectile[k];
}
}
void Sprite_DisableAll() { // 89c22f
for (int k = 15; k >= 0; k--) {
if (sprite_state[k] && (player_is_indoors || sprite_type[k] != 0x6c))
sprite_state[k] = 0;
}
for (int k = 9; k >= 0; k--)
ancilla_type[k] = 0;
flag_is_ancilla_to_pick_up = 0;
sprite_limit_instance = 0;
byte_7E0B9B = 0;
byte_7E0B88 = 0;
archery_game_arrows_left = 0;
garnish_active = 0;
byte_7E0B9E = 0;
activate_bomb_trap_overlord = 0;
intro_times_pal_flash = 0;
byte_7E0FF8 = 0;
byte_7E0FFB = 0;
flag_block_link_menu = 0;
byte_7E0FFD = 0;
byte_7E0FC6 = 0;
is_archer_or_shovel_game = 0;
for (int k = 7; k >= 0; k--)
overlord_type[k] = 0;
for (int k = 29; k >= 0; k--)
garnish_type[k] = 0;
}
void Dungeon_LoadSprites() { // 89c290
const uint8 *src = kDungeonSprites + kDungeonSpriteOffs[dungeon_room_index2];
byte_7E0FB1 = dungeon_room_index2 >> 3 & 0xfe;
byte_7E0FB0 = (dungeon_room_index2 & 0xf) << 1;
sort_sprites_setting = *src++;
for (int k = 0; *src != 0xff; src += 3)
k = Dungeon_LoadSingleSprite(k, src) + 1;
}
void Sprite_ManuallySetDeathFlagUW(int k) { // 89c2f5
if (!player_is_indoors || sprite_defl_bits[k] & 1 || sign8(sprite_N[k]))
return;
sprite_where_in_room[dungeon_room_index2] |= 1 << sprite_N[k];
}
int Dungeon_LoadSingleSprite(int k, const uint8 *src) { // 89c327
uint8 y = src[0], x = src[1], type = src[2];
if (type == 0xe4) {
if (y == 0xfe || y == 0xfd) {
sprite_die_action[k - 1] = (y == 0xfe) ? 1 : 2;
return k - 1;
}
} else if (x >= 0xe0) {
Dungeon_LoadSingleOverlord(src);
return k - 1;
}
if (!(kSpriteInit_DeflBits[type] & 1) && (sprite_where_in_room[dungeon_room_index2] & (1 << k)))
return k;
sprite_state[k] = 8;
tmp_counter = y;
sprite_floor[k] = (y >> 7);
Sprite_SetY(k, ((y << 4) & 0x1ff) + (byte_7E0FB1 << 8));
byte_7E0FB6 = x;
Sprite_SetX(k, ((x << 4) & 0x1ff) + (byte_7E0FB0 << 8));
sprite_type[k] = type;
tmp_counter = (tmp_counter & 0x60) >> 2;
sprite_subtype[k] = tmp_counter | byte_7E0FB6 >> 5;
sprite_N[k] = k;
sprite_die_action[k] = 0;
return k;
}
void Dungeon_LoadSingleOverlord(const uint8 *src) { // 89c3e8
int k = AllocOverlord();
if (k < 0)
return;
uint8 y = src[0], x = src[1], type = src[2];
overlord_type[k] = type;
overlord_floor[k] = (y >> 7);
int t = ((y << 4) & 0x1ff) + (byte_7E0FB1 << 8);
overlord_y_lo[k] = t;
overlord_y_hi[k] = t >> 8;
t = ((x << 4) & 0x1ff) + (byte_7E0FB0 << 8);
overlord_x_lo[k] = t;
overlord_x_hi[k] = t >> 8;
overlord_spawned_in_area[k] = overworld_area_index;
overlord_gen2[k] = 0;
overlord_gen1[k] = 0;
overlord_gen3[k] = 0;
if (overlord_type[k] == 10 || overlord_type[k] == 11) {
overlord_gen2[k] = 160;
} else if (overlord_type[k] == 3) {
overlord_gen2[k] = 255;
overlord_x_lo[k] -= 8;
}
}
void Sprite_ResetAll() { // 89c44e
Sprite_DisableAll();
Sprite_ResetAll_noDisable();
}
void Sprite_ResetAll_noDisable() { // 89c452
byte_7E0FDD = 0;
sprite_alert_flag = 0;
byte_7E0FFD = 0;
byte_7E02F0 = 0;
byte_7E0FC6 = 0;
sprite_limit_instance = 0;
sort_sprites_setting = 0;
if (follower_indicator != 13)
super_bomb_indicator_unk2 = 0xfe;
memset(sprite_where_in_room, 0, 0x1000);
memset(overworld_sprite_was_loaded, 0, 0x200);
memset(dungeon_room_history, 0xff, 8);
}
void Sprite_ReloadAll_Overworld() { // 89c499
Sprite_DisableAll();
Sprite_OverworldReloadAll_justLoad();
}
void Sprite_OverworldReloadAll_justLoad() { // 89c49d
Sprite_ResetAll_noDisable();
Overworld_LoadSprites();
Sprite_ActivateAllProxima();
}
void Overworld_LoadSprites() { // 89c4ac
sprcoll_x_base = (overworld_area_index & 7) << 9;
sprcoll_y_base = ((overworld_area_index & 0x3f) >> 2 & 0xe) << 8;
sprcoll_x_size = sprcoll_y_size = kOverworldAreaSprcollSizes[BYTE(overworld_area_index)] << 8;
const uint8 *src = GetOverworldSpritePtr(overworld_area_index);
uint8 b;
for (; (b = src[0]) != 0xff; src += 3) {
if (src[2] == 0xf4) {
byte_7E0FFD++;
continue;
}
uint8 r2 = (src[0] >> 4) << 2;
uint8 r6 = (src[1] >> 4) + r2;
uint8 r5 = src[1] & 0xf | src[0] << 4;
sprite_where_in_overworld[r5 | r6 << 8] = src[2] + 1;
}
}
void Sprite_ActivateAllProxima() { // 89c55e
uint16 bak0 = BG2HOFS_copy2;
uint8 bak1 = byte_7E069E[1];
byte_7E069E[1] = 0xff;
int xt = (enhanced_features0 & kFeatures0_ExtendScreen64) ? 0x40 : 0;
BG2HOFS_copy2 -= xt;
for (int i = 21 + (xt >> 3); i >= 0; i--) {
Sprite_ActivateWhenProximal();
BG2HOFS_copy2 += 16;
}
byte_7E069E[1] = bak1;
BG2HOFS_copy2 = bak0;
}
void Sprite_ProximityActivation() { // 89c58f
if (submodule_index != 0) {
Sprite_ActivateWhenProximal();
Sprite_ActivateWhenProximalBig();
} else {
if (!(spr_ranged_based_toggler & 1))
Sprite_ActivateWhenProximal();
if (spr_ranged_based_toggler & 1)
Sprite_ActivateWhenProximalBig();
spr_ranged_based_toggler++;
}
}
void Sprite_ActivateWhenProximal() { // 89c5bb
if (byte_7E069E[1]) {
int xt = (enhanced_features0 & kFeatures0_ExtendScreen64) ? 0x40 : 0;
uint16 x = BG2HOFS_copy2 + (sign8(byte_7E069E[1]) ? -0x10 - xt : 0x110 + xt);
uint16 y = BG2VOFS_copy2 - 0x30;
for (int i = 21; i >= 0; i--, y += 16)
Sprite_Overworld_ProximityMotivatedLoad(x, y);
}
}
void Sprite_ActivateWhenProximalBig() { // 89c5fa
if (byte_7E069E[0]) {
int xt = (enhanced_features0 & kFeatures0_ExtendScreen64) ? 0x40 : 0;
uint16 x = BG2HOFS_copy2 - 0x30 - xt;
uint16 y = BG2VOFS_copy2 + (sign8(byte_7E069E[0]) ? -0x10 : 0x110);
for (int i = 21 + (xt >> 3); i >= 0; i--, x += 16)
Sprite_Overworld_ProximityMotivatedLoad(x, y);
}
}
void Sprite_Overworld_ProximityMotivatedLoad(uint16 x, uint16 y) { // 89c6f5
uint16 xt = (uint16)(x - sprcoll_x_base);
uint16 yt = (uint16)(y - sprcoll_y_base);
if (xt >= sprcoll_x_size || yt >= sprcoll_y_size)
return;
uint8 r1 = (yt >> 8) * 4 | (xt >> 8);
uint8 r0 = y & 0xf0 | x >> 4 & 0xf;
Overworld_LoadProximaSpriteIfAlive(r1 << 8 | r0);
}
void Overworld_LoadProximaSpriteIfAlive(uint16 blk) { // 89c739
uint8 *p5 = sprite_where_in_overworld + blk;
uint8 sprite_to_spawn = *p5;
if (!sprite_to_spawn)
return;
uint8 loadedmask = (0x80 >> (blk & 7));
uint8 *loadedp = &overworld_sprite_was_loaded[blk >> 3];
if (*loadedp & loadedmask)
return;
if (sprite_to_spawn >= 0xf4) {
// load overlord
int k = AllocOverlord();
if (k < 0)
return;
*loadedp |= loadedmask;
overlord_offset_sprite_pos[k] = blk;
overlord_type[k] = sprite_to_spawn - 0xf3;
overlord_x_lo[k] = (blk << 4 & 0xf0) + (overlord_type[k] == 1 ? 8 : 0);
overlord_y_lo[k] = blk & 0xf0;
overlord_x_hi[k] = (blk >> 8 & 3) + HIBYTE(sprcoll_x_base);
overlord_y_hi[k] = (blk >> 10) + HIBYTE(sprcoll_y_base);
overlord_floor[k] = 0;
overlord_spawned_in_area[k] = overworld_area_index;
overlord_gen2[k] = 0;
overlord_gen1[k] = 0;
overlord_gen3[k] = 0;
} else {
// load regular sprite
int k = Overworld_AllocSprite(sprite_to_spawn);
if (k < 0)
return;
*loadedp |= loadedmask;
sprite_N_word[k] = blk;
sprite_type[k] = sprite_to_spawn - 1;
sprite_state[k] = 8;
sprite_x_lo[k] = blk << 4 & 0xf0;
sprite_y_lo[k] = blk & 0xf0;
sprite_x_hi[k] = (blk >> 8 & 3) + HIBYTE(sprcoll_x_base);
sprite_y_hi[k] = (blk >> 10) + HIBYTE(sprcoll_y_base);
sprite_floor[k] = 0;
sprite_subtype[k] = 0;
sprite_die_action[k] = 0;
}
}
void SpriteExplode_SpawnEA(int k) { // 89ee4c
tmp_counter = sprite_type[k];
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamicallyEx(k, 0xea, &info, 14);
Sprite_SetSpawnedCoordinates(j, &info);
sprite_z_vel[j] = 32;
sprite_floor[j] = link_is_on_lower_level;
sprite_A[j] = (j == 9) ? 2 : 6;
Sprite_SetY(j, info.r2_y + 3);
if (tmp_counter == 0xce) {
Sprite_SetY(j, info.r2_y + 16);
return;
}
if (tmp_counter == 0xcb) {
sprite_y_lo[j] = sprite_x_lo[j] = 0x78;
sprite_x_hi[j] = HIBYTE(link_x_coord);
sprite_y_hi[j] = HIBYTE(link_y_coord);
}
}
void Sprite_KillFriends() { // 89ef56
for(int j = 15; j >= 0; j--) {
if (j != cur_object_index && sprite_state[j] && !(sprite_defl_bits[j] & 2) && sprite_type[j] != 0x7a) {
sprite_state[j] = 6;
sprite_delay_main[j] = 15;
sprite_flags3[j] = 0;
sprite_flags5[j] = 0;
sprite_flags2[j] = 3;
}
}
}
void Garnish16_ThrownItemDebris(int k) { // 89f0cb
static const int16 kScatterDebris_Draw_X[64] = {
0, 8, 0, 8, -2, 9, -1, 9, -4, 9, -1, 10, -6, 9, -1, 12,
-7, 9, -2, 13, -9, 9, -3, 14, -4, -4, 9, 15, -3, -3, -3, 9,
-4, 4, 6, 10, -1, 4, 6, 7, 0, 2, 4, 7, 1, 1, 5, 7,
0, -2, 8, 9, -1, -6, 9, 10, -2, -7, 12, 11, -3, -9, 4, 6,
};
static const int8 kScatterDebris_Draw_Y[64] = {
0, 0, 8, 8, 0, -1, 10, 10, 0, -3, 11, 7, 1, -4, 12, 8,
1, -4, 13, 9, 2, -4, 16, 10, 14, 14, -4, 11, 16, 16, 16, -1,
2, -5, 5, 1, 3, -7, 8, 2, 4, -8, 4, 10, -9, 4, 4, 12,
-10, 4, 8, 14, -12, 4, 8, 15, -15, 3, 8, 17, -17, 1, 18, 15,
};
static const int8 kScatterDebris_Draw_Char[64] = {
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
0x48, 0x58, 0x58, 0x58, 0x48, 0x58, 0x58, 0x48, 0x48, 0x48, 0x58, 0x48, 0x48, 0x48, 0x48, 0x48,
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
};
static const uint8 kScatterDebris_Draw_Flags[64] = {
0x80, 0, 0x80, 0x40, 0x80, 0x40, 0x80, 0, 0, 0xc0, 0, 0x80, 0x80, 0x40, 0x80, 0,
0x80, 0xc0, 0, 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0x80, 0x80, 0, 0, 0, 0,
0x40, 0x40, 0x40, 0, 0x40, 0x40, 0x40, 0, 0x40, 0x40, 0, 0, 0x80, 0, 0x40, 0x40,
0x40, 0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0, 0, 0x40, 0, 0, 0,
};
Point16U pt;
if (Garnish_ReturnIfPrepFails(k, &pt))
return;
uint8 r5 = garnish_oam_flags[k];
if (byte_7E0FC6 >= 3)
return;
if (garnish_sprite[k] == 3) {
ScatterDebris_Draw(k, pt);
return;
}
OamEnt *oam = GetOamCurPtr();
tmp_counter = garnish_sprite[k];
uint8 base = ((garnish_countdown[k] >> 2) ^ 7) << 2;
if (tmp_counter == 4 || tmp_counter == 2 && !player_is_indoors)
base += 0x20;
for (int i = 3; i >= 0; i--, oam++) {
int j = i + base;
SetOamHelper1(oam, pt.x + kScatterDebris_Draw_X[j], pt.y + kScatterDebris_Draw_Y[j],
(tmp_counter == 0) ? 0x4E : (tmp_counter >= 0x80) ? 0xF2 : kScatterDebris_Draw_Char[j],
kScatterDebris_Draw_Flags[j] | r5, 0);
}
}
void ScatterDebris_Draw(int k, Point16U pt) { // 89f198
static const int8 kScatterDebris_Draw_X2[12] = {-8, 8, 16, -5, 8, 15, -1, 7, 11, 1, 3, 8};
static const int8 kScatterDebris_Draw_Y2[12] = {7, 2, 12, 9, 2, 10, 11, 2, 11, 7, 3, 8};
static const uint8 kScatterDebris_Draw_Char2[12] = {0xe2, 0xe2, 0xe2, 0xe2, 0xf2, 0xf2, 0xf2, 0xe2, 0xe2, 0xf2, 0xe2, 0xe2};
static const uint8 kScatterDebris_Draw_Flags2[12] = {0, 0, 0, 0, 0x80, 0x40, 0, 0x80, 0x40, 0, 0, 0};
if (garnish_countdown[k] == 16)
garnish_type[k] = 0;
OamEnt *oam = GetOamCurPtr();
int base = ((garnish_countdown[k] & 0xf) >> 2) * 3;
for (int i = 2; i >= 0; i--, oam++) {
int j = i + base;
SetOamHelper1(oam, pt.x + kScatterDebris_Draw_X2[j], pt.y + kScatterDebris_Draw_Y2[j],
kScatterDebris_Draw_Char2[j], kScatterDebris_Draw_Flags2[j] | 0x22, 0);
}
}
void Sprite_KillSelf(int k) { // 89f1f8
if (!(sprite_defl_bits[k] & 0x40) && player_is_indoors)
return;
sprite_state[k] = 0;
uint16 blk = sprite_N_word[k];
g_ram[0] = blk; // Sprite_PrepOamCoordOrDoubleRet reads this!
WORD(g_ram[1]) = (blk >> 3) + 0xef80; // Sprite_PrepOamCoordOrDoubleRet reads this!
uint8 loadedmask = (0x80 >> (blk & 7));
uint16 addr = 0xEF80 + (blk >> 3); // warning: blk may be bad, seen with cannon balls in 2nd dungeon
uint8 *loadedp = &g_ram[addr + 0x10000];
if (blk < 0xffff)
*loadedp &= ~loadedmask;
if (!player_is_indoors)
sprite_N_word[k] = 0xffff;
else
sprite_N[k] = 0xff;
}
void SpritePrep_LoadProperties(int k) { // 8db818
SpritePrep_ResetProperties(k);
int j = sprite_type[k];
sprite_flags2[k] = kSpriteInit_Flags2[j];
sprite_health[k] = kSpriteInit_Health[j];
sprite_flags4[k] = kSpriteInit_Flags4[j];
sprite_flags5[k] = kSpriteInit_Flags5[j];
sprite_defl_bits[k] = kSpriteInit_DeflBits[j];
sprite_bump_damage[k] = kSpriteInit_BumpDamage[j];
sprite_flags[k] = kSpriteInit_Flags[j];
sprite_room[k] = player_is_indoors ? dungeon_room_index2 : overworld_area_index;
sprite_flags3[k] = kSpriteInit_Flags3[j];
sprite_oam_flags[k] = kSpriteInit_Flags3[j] & 0xf;
}
void SpritePrep_LoadPalette(int k) { // 8db85c
int f = kSpriteInit_Flags3[sprite_type[k]];
sprite_flags3[k] = f;
sprite_oam_flags[k] = f & 15;
}
void SpritePrep_ResetProperties(int k) { // 8db871
sprite_pause[k] = 0;
sprite_E[k] = 0;
sprite_x_vel[k] = 0;
sprite_y_vel[k] = 0;
sprite_z_vel[k] = 0;
sprite_x_subpixel[k] = 0;
sprite_y_subpixel[k] = 0;
sprite_z_subpos[k] = 0;
sprite_ai_state[k] = 0;
sprite_graphics[k] = 0;
sprite_D[k] = 0;
sprite_delay_main[k] = 0;
sprite_delay_aux1[k] = 0;
sprite_delay_aux2[k] = 0;
sprite_delay_aux4[k] = 0;
sprite_head_dir[k] = 0;
sprite_anim_clock[k] = 0;
sprite_G[k] = 0;
sprite_hit_timer[k] = 0;
sprite_wallcoll[k] = 0;
sprite_z[k] = 0;
sprite_health[k] = 0;
sprite_F[k] = 0;
sprite_x_recoil[k] = 0;
sprite_y_recoil[k] = 0;
sprite_A[k] = 0;
sprite_B[k] = 0;
sprite_C[k] = 0;
sprite_unk2[k] = 0;
sprite_subtype2[k] = 0;
sprite_ignore_projectile[k] = 0;
sprite_obj_prio[k] = 0;
sprite_oam_flags[k] = 0;
sprite_stunned[k] = 0;
sprite_give_damage[k] = 0;
sprite_unk3[k] = 0;
sprite_unk4[k] = 0;
sprite_unk5[k] = 0;
sprite_unk1[k] = 0;
sprite_I[k] = 0;
}
uint8 Oam_AllocateFromRegionA(uint8 num) { // 8dba80
return Oam_GetBufferPosition(num, 0);
}
uint8 Oam_AllocateFromRegionB(uint8 num) { // 8dba84
return Oam_GetBufferPosition(num, 2);
}
uint8 Oam_AllocateFromRegionC(uint8 num) { // 8dba88
return Oam_GetBufferPosition(num, 4);
}
uint8 Oam_AllocateFromRegionD(uint8 num) { // 8dba8c
return Oam_GetBufferPosition(num, 6);
}
uint8 Oam_AllocateFromRegionE(uint8 num) { // 8dba90
return Oam_GetBufferPosition(num, 8);
}
uint8 Oam_AllocateFromRegionF(uint8 num) { // 8dba94
return Oam_GetBufferPosition(num, 10);
}
uint8 Oam_GetBufferPosition(uint8 num, uint8 y) { // 8dbb0a
y >>= 1;
uint16 p = oam_region_base[y], pstart = p;
p += num;
if (p >= kOamGetBufferPos_Tab0[y]) {
int j = oam_alloc_arr1[y]++ & 7;
pstart = kOamGetBufferPos_Tab1[y * 8 + j];
} else {
oam_region_base[y] = p;
}
oam_ext_cur_ptr = 0xa20 + (pstart >> 2);
oam_cur_ptr = 0x800 + pstart;
return oam_cur_ptr;
}
void Sprite_NullifyHookshotDrag() { // 8ff540
for (int i = 4; i >= 0; i--) {
if (!(ancilla_type[i] & 0x1f) && related_to_hookshot) {
related_to_hookshot = 0;
break;
}
}
link_x_coord_safe_return_hi = link_x_coord >> 8;
link_y_coord_safe_return_hi = link_y_coord >> 8;
link_x_coord = link_x_coord_prev;
link_y_coord = link_y_coord_prev;
HandleIndoorCameraAndDoors();
}
void Overworld_SubstituteAlternateSecret() { // 9afbdb
static const uint8 kSecretSubst_Tab0[64] = {
0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
4, 4, 6, 4, 4, 6, 0, 0, 15, 15, 4, 5, 5, 4, 6, 6,
15, 15, 4, 5, 5, 7, 6, 6, 31, 31, 4, 7, 7, 4, 6, 6,
6, 7, 2, 0, 0, 0, 0, 0, 6, 6, 2, 0, 0, 0, 0, 0,
};
static const uint8 kSecretSubst_Tab2[16] = { 1, 1, 1, 1, 15, 1, 1, 18, 16, 1, 1, 1, 17, 1, 1, 3 };
static const uint8 kSecretSubst_Tab1[16] = { 0, 0, 0, 0, 2, 0, 0, 8, 16, 0, 0, 0, 1, 0, 0, 0 };
if (GetRandomNumber() & 1)
return;
int n = 0;
for (int j = 15; j >= 0; j--) {
if (sprite_state[j] && sprite_type[j] != 0x6c)
n++;
}
if (n >= 4 || sram_progress_indicator < 2)
return;
int j = (overworld_secret_subst_ctr++ & 7) + (is_in_dark_world ? 8 : 0);
if (!(kSecretSubst_Tab0[BYTE(overworld_area_index) & 0x3f] & kSecretSubst_Tab1[j]))
BYTE(dung_secrets_unk1) = kSecretSubst_Tab2[j];
}
void Sprite_ApplyConveyor(int k, int j) { // 9d8010
if (!(frame_counter & 1))
return;
static const int8 kConveyorAdjustment_X[] = {0, 0, -1, 1};
static const int8 kConveyorAdjustment_Y[] = {-1, 1, 0, 0};
Sprite_SetX(k, Sprite_GetX(k) + kConveyorAdjustment_X[j - 0x68]);
Sprite_SetY(k, Sprite_GetY(k) + kConveyorAdjustment_Y[j - 0x68]);
}
uint8 Sprite_BounceFromTileCollision(int k) { // 9dc751
int j = Sprite_CheckTileCollision(k);
if (j & 3) {
sprite_x_vel[k] = -sprite_x_vel[k];
sprite_G[k]++;
}
if (j & 12) {
sprite_y_vel[k] = -sprite_y_vel[k];
sprite_G[k]++;
return sprite_G[k]; // wtf
}
return 0;
}
void ExecuteCachedSprites() { // 9de9da
if (!player_is_indoors || submodule_index == 0 || submodule_index == 14 || alt_sprites_flag == 0) {
alt_sprites_flag = 0;
return;
}
for (int i = 15; i >= 0; i--) {
cur_object_index = i;
if (alt_sprite_state[i])
UncacheAndExecuteSprite(i);
}
}
void UncacheAndExecuteSprite(int k) { // 9dea00
uint8 bak0 = sprite_state[k];
uint8 bak1 = sprite_type[k];
uint8 bak2 = sprite_x_lo[k];
uint8 bak3 = sprite_x_hi[k];
uint8 bak4 = sprite_y_lo[k];
uint8 bak5 = sprite_y_hi[k];
uint8 bak6 = sprite_graphics[k];
uint8 bak7 = sprite_A[k];
uint8 bak8 = sprite_head_dir[k];
uint8 bak9 = sprite_oam_flags[k];
uint8 bak10 = sprite_obj_prio[k];
uint8 bak11 = sprite_D[k];
uint8 bak12 = sprite_flags2[k];
uint8 bak13 = sprite_floor[k];
uint8 bak14 = sprite_ai_state[k];
uint8 bak15 = sprite_flags3[k];
uint8 bak16 = sprite_B[k];
uint8 bak17 = sprite_C[k];
uint8 bak18 = sprite_E[k];
uint8 bak19 = sprite_subtype2[k];
uint8 bak20 = sprite_z[k];
uint8 bak21 = sprite_delay_main[k];
uint8 bak22 = sprite_I[k];
uint8 bak23 = sprite_ignore_projectile[k];
sprite_state[k] = alt_sprite_state[k];
sprite_type[k] = alt_sprite_type[k];
sprite_x_lo[k] = alt_sprite_x_lo[k];
sprite_x_hi[k] = alt_sprite_x_hi[k];
sprite_y_lo[k] = alt_sprite_y_lo[k];
sprite_y_hi[k] = alt_sprite_y_hi[k];
sprite_graphics[k] = alt_sprite_graphics[k];
sprite_A[k] = alt_sprite_A[k];
sprite_head_dir[k] = alt_sprite_head_dir[k];
sprite_oam_flags[k] = alt_sprite_oam_flags[k];
sprite_obj_prio[k] = alt_sprite_obj_prio[k];
sprite_D[k] = alt_sprite_D[k];
sprite_flags2[k] = alt_sprite_flags2[k];
sprite_floor[k] = alt_sprite_floor[k];
sprite_ai_state[k] = alt_sprite_spawned_flag[k];
sprite_flags3[k] = alt_sprite_flags3[k];
sprite_B[k] = alt_sprite_B[k];
sprite_C[k] = alt_sprite_C[k];
sprite_E[k] = alt_sprite_E[k];
sprite_subtype2[k] = alt_sprite_subtype2[k];
sprite_z[k] = alt_sprite_height_above_shadow[k];
sprite_delay_main[k] = alt_sprite_delay_main[k];
sprite_I[k] = alt_sprite_I[k];
sprite_ignore_projectile[k] = alt_sprite_maybe_ignore_projectile[k];
Sprite_ExecuteSingle(k);
if (sprite_pause[k] != 0)
alt_sprite_state[k] = 0;
sprite_ignore_projectile[k] = bak23;
sprite_I[k] = bak22;
sprite_delay_main[k] = bak21;
sprite_z[k] = bak20;
sprite_subtype2[k] = bak19;
sprite_E[k] = bak18;
sprite_C[k] = bak17;
sprite_B[k] = bak16;
sprite_flags3[k] = bak15;
sprite_ai_state[k] = bak14;
sprite_floor[k] = bak13;
sprite_flags2[k] = bak12;
sprite_D[k] = bak11;
sprite_obj_prio[k] = bak10;
sprite_oam_flags[k] = bak9;
sprite_head_dir[k] = bak8;
sprite_A[k] = bak7;
sprite_graphics[k] = bak6;
sprite_y_hi[k] = bak5;
sprite_y_lo[k] = bak4;
sprite_x_hi[k] = bak3;
sprite_x_lo[k] = bak2;
sprite_type[k] = bak1;
sprite_state[k] = bak0;
}
uint8 Sprite_ConvertVelocityToAngle(uint8 x, uint8 y) { // 9df614
static const uint8 kConvertVelocityToAngle_Tab0[32] = {
0, 0, 1, 1, 1, 2, 2, 2, 0, 0, 15, 15, 15, 14, 14, 14,
8, 8, 7, 7, 7, 6, 6, 6, 8, 8, 9, 9, 9, 10, 10, 10,
};
static const uint8 kConvertVelocityToAngle_Tab1[32] = {
4, 4, 3, 3, 3, 2, 2, 2, 12, 12, 13, 13, 13, 14, 14, 14,
4, 4, 5, 5, 5, 6, 6, 6, 12, 12, 11, 11, 11, 10, 10, 10,
};
int s = ((y >> 7) + (x >> 7) * 2) * 8;
if (sign8(x)) x = -x;
if (sign8(y)) y = -y;
if (x >= y) {
return kConvertVelocityToAngle_Tab0[(y >> 2) + s];
} else {
return kConvertVelocityToAngle_Tab1[(x >> 2) + s];
}
}
int Sprite_SpawnDynamically(int k, uint8 what, SpriteSpawnInfo *info) { // 9df65d
return Sprite_SpawnDynamicallyEx(k, what, info, 15);
}
int Sprite_SpawnDynamicallyEx(int k, uint8 what, SpriteSpawnInfo *info, int j) { // 9df65f
do {
if (sprite_state[j] == 0) {
sprite_type[j] = what;
sprite_state[j] = 9;
info->r0_x = Sprite_GetX(k);
info->r2_y = Sprite_GetY(k);
info->r4_z = sprite_z[k];
info->r5_overlord_x = overlord_x_lo[k] | overlord_x_hi[k] << 8;
info->r7_overlord_y = overlord_y_lo[k] | overlord_y_hi[k] << 8;
SpritePrep_LoadProperties(j);
if (!player_is_indoors) {
sprite_N_word[j] = 0xffff;
} else {
sprite_N[j] = 0xff;
}
sprite_floor[j] = sprite_floor[k];
sprite_D[j] = sprite_D[k];
sprite_die_action[j] = 0;
sprite_subtype[j] = 0;
break;
}
} while (--j >= 0);
return j;
}
void SpriteFall_Draw(int k, PrepOamCoordsRet *info) { // 9dffc5
static const uint8 kSpriteFall_Char[8] = {0x83, 0x83, 0x83, 0x80, 0x80, 0x80, 0xb7, 0xb7};
OamEnt *oam = GetOamCurPtr();
oam->x = info->x + 4;
oam->y = info->y + 4;
oam->charnum = kSpriteFall_Char[sprite_delay_main[k] >> 2];
oam->flags = info->flags & 0x30 | 0x04;
Sprite_CorrectOamEntries(k, 0, 0);
}
void Sprite_GarnishSpawn_Sparkle_limited(int k, uint16 x, uint16 y) { // 9ea001
Sprite_SpawnSimpleSparkleGarnishEx(k, x, y, 14);
}
int Sprite_GarnishSpawn_Sparkle(int k, uint16 x, uint16 y) { // 9ea007
return Sprite_SpawnSimpleSparkleGarnishEx(k, x, y, 29);
}
void Sprite_BehaveAsBarrier(int k) { // 9ef4f3
uint8 bak = sprite_flags4[k];
sprite_flags4[k] = 0;
if (Sprite_CheckDamageToLink_same_layer(k))
Sprite_HaltAllMovement();
sprite_flags4[k] = bak;
}
void Sprite_HaltAllMovement() { // 9ef508
Sprite_NullifyHookshotDrag();
link_speed_setting = 0;
Link_CancelDash();
}
int ReleaseFairy() { // 9efe33
SpriteSpawnInfo info;
int j = Sprite_SpawnDynamically(0, 0xe3, &info);
if (j >= 0) {
sprite_floor[j] = link_is_on_lower_level;
Sprite_SetX(j, link_x_coord + 8);
Sprite_SetY(j, link_y_coord + 16);
sprite_D[j] = 0;
sprite_delay_aux4[j] = 96;
}
return j;
}
void Sprite_DrawRippleIfInWater(int k) { // 9eff8d
if (sprite_I[k] != 8 && sprite_I[k] != 9)
return;
if (sprite_flags3[k] & 0x20) {
cur_sprite_x -= 4;
if (sprite_type[k] == 0xdf)
cur_sprite_y -= 7;
}
SpriteDraw_WaterRipple(k);
Sprite_Get16BitCoords(k);
Oam_AllocateFromRegionA(((sprite_flags2[k] & 0x1f) + 1) * 4);
}