tmc/src/playerUtils.c

2870 lines
82 KiB
C

#define NENT_DEPRECATED
#include "global.h"
#include "area.h"
#include "asm.h"
#include "common.h"
#include "entity.h"
#include "functions.h"
#include "game.h"
#include "kinstone.h"
#include "object.h"
#include "player.h"
#include "room.h"
#include "save.h"
#include "new_player.h"
#include "item.h"
#include "message.h"
static void sub_08077E54(ItemBehavior* beh);
extern void sub_080752E8(ItemBehavior* behavior, u32 arg1); // item.c
extern void sub_0800857C(Entity*);
extern void SetDefaultPriorityForKind(Entity*);
extern void sub_0809D738(Entity*);
extern s32 Mod(s32, s32);
extern void sub_08003FDE(Entity*, u32, u32, u32);
extern u32 sub_080B1B84(u32, u32);
void sub_080790E4(Entity* this);
typedef struct {
u8 unk0[4];
u16 unk4;
u8 unk6[6];
} struct_0811BE48;
extern u8 gMapData;
extern const u8 gUnk_020176E0[];
extern const ScreenTransitionData gUnk_0813AD88[];
extern u8 gUnk_02002B32[];
bool32 sub_08077758(PlayerEntity*);
bool32 sub_080777A0();
void sub_08077880(u32, u32, u32);
bool32 sub_080778CC();
ItemBehavior* sub_0807794C(u32);
u32 sub_080789A8(void);
ItemBehavior* sub_080779EC(u32);
void DeletePlayerItem(ItemBehavior*, u32);
bool32 sub_08079E90(u32);
void PlayerMinishSetNormalAndCollide(void);
void sub_08078D60(void);
void* sub_08077C54(ItemBehavior*);
u32 sub_08079FD4(Entity*, u32);
void LoadRoomGfx(void);
u32 sub_0807A094(u32);
u32 GetSurfaceCalcType(Entity*, s32, s32);
void sub_0807AAF8(Entity*, u32);
extern struct_0811BE48 gUnk_0811BE48[];
extern void (*const gUnk_0811C27C[])(Entity*);
extern void (*const gUnk_0811C284[])(PlayerEntity*);
extern void (*const gUnk_0811C298[])(PlayerEntity*);
extern bool32 (*const gPlayerChargeActions[])(ChargeState*);
extern u8 gUnk_0811C000[];
extern const u8 gUnk_0811C118[];
extern void (*const gUnk_0811C120[])(Entity*);
extern u16 gUnk_0811C268[];
extern ItemBehavior* (*const gUnk_0811BFC8[])(u32);
extern void DeleteLoadedTileEntity(u32, u32);
extern const u8 gUnk_080B3E80[]; // collisionData for tileType?
extern const u8 gUnk_080B37A0[]; // unkData3 for tileType?
extern u8 gUpdateVisibleTiles;
extern u16 gMapDataTopSpecial[];
extern u16 gMapDataBottomSpecial[];
bool32 sub_0807BF88(u32, u32, RoomResInfo*);
void sub_0807BFD0(void);
void ForceSetPlayerState(u32 framestate);
struct_03003DF8* sub_080784E4(void);
extern const u16 gUnk_0811C0F8[];
u32 sub_08079778(void);
u32 sub_0807A500(void);
extern const u16 gUnk_0811C108[];
extern const u16 gUnk_0811C110[];
extern const u16 gUnk_08007CAC[];
u32 sub_0807BEEC(u32 param_1, u32 param_2, u32 param_3);
extern const u16 gUnk_0811C466[];
bool32 sub_0807B434(u32 position, u32 layer);
extern const u16 gUnk_0811C2AC[];
void sub_0807B820(u32);
void sub_0807B8A8(u32);
void sub_0807B930(u32);
bool32 sub_0807B464(u32 param_1, u32 param_2);
void sub_0807B55C(u32, u32, u16*);
void sub_0807B480(u32, u32);
extern const s16 gUnk_0811C456[];
bool32 sub_0807B600(u32);
bool32 sub_0807B464(u32 tilePos, u32 param_2);
extern const u16 gUnk_0811C2CC[];
extern const u16 gUnk_0811C2EC[];
bool32 sub_0807B464(u32 param_1, u32 param_2);
extern void CreateRandomWaterTrace(Entity* parent, int range);
void sub_08079520(Entity* this);
bool32 sub_0807ADB8(Entity*);
extern const u16* sub_0806FC50(u32 param_1, u32 param_2);
bool32 sub_08079F48(u32 param_1, u32 param_2);
void sub_08077698(PlayerEntity* this) {
ItemBehavior* puVar2;
u32 idx;
gPlayerState.field_0x3[0] &= 0xfe;
gPlayerState.field_0x3[1] &= 0xf;
if ((((((gPlayerState.field_0x7 | gPlayerState.jump_status) & 0x80) == 0) &&
((gPlayerState.jump_status & 0x40) == 0)) &&
(gPlayerState.swim_state == 0)) &&
((sub_08077758(this) && (sub_080777A0() == 0)))) {
sub_08077880(gSave.stats.itemButtons[0], 1, 0);
sub_08077880(gSave.stats.itemButtons[1], 2, 0);
sub_080778CC();
}
idx = 0;
puVar2 = gUnk_03000B80;
do {
if (puVar2->field_0x5[4] != 0) {
sub_080752E8(puVar2, idx);
}
puVar2++;
idx++;
} while (idx < 4);
}
void sub_08077728(u32 param_1) {
if (param_1 == 0) {
sub_08077880(gSave.stats.itemButtons[0], 1, 1);
} else {
sub_08077880(gSave.stats.itemButtons[1], 2, 1);
}
}
bool32 sub_08077758(PlayerEntity* this) {
if ((gPlayerState.flags & PL_DRUGGED) == 0) {
if ((gPlayerState.flags & (PL_CAPTURED | PL_HIDDEN | PL_DISABLE_ITEMS | PL_BURNING | PL_FROZEN)) == 0) {
if ((((gPlayerState.dash_state | gPlayerState.mobility) | this->unk_7a) == 0) &&
(super->knockbackDuration == 0)) {
return TRUE;
}
} else {
DeleteClones();
}
}
return FALSE;
}
bool32 sub_080777A0(void) {
if ((gPlayerState.field_0x92 & 0x80) != 0) {
if ((gPlayerState.flags & PL_CLONING) != 0) {
gPlayerState.chargeState.action = 1;
DeleteClones();
return TRUE;
} else {
switch (gArea.portal_mode) {
case 2:
if (gArea.unk1A == 0) {
gPlayerEntity.subAction += 1;
}
break;
case 3:
if ((gArea.unk1A == 0) && ((gPlayerState.flags & PL_MINISH) != 0)) {
gPlayerEntity.subAction += 1;
gPlayerEntity.flags &= ~ENT_COLLIDE;
RequestPriorityDuration(&gPlayerEntity, 0xb4);
return TRUE;
}
return FALSE;
default:
if ((((gUnk_0200AF00.unk_2c == 0xc) && (gPlayerState.field_0x1c == 0)) &&
(gPlayerState.floor_type != 0x11)) &&
((((gPlayerState.field_0x90 & 0xf00) != 0 &&
((gPlayerState.flags & (PL_BURNING | PL_ROLLING)) == 0)) &&
((gPlayerState.jump_status == 0 && (gPlayerState.field_0x3[1] == 0)))))) {
gPlayerState.queued_action = 0x18;
}
return FALSE;
}
}
return TRUE;
} else {
if ((gPlayerState.flags & PL_USE_PORTAL) == 0) {
return FALSE;
}
return TRUE;
}
}
NONMATCH("asm/non_matching/playerUtils/sub_08077880.inc", void sub_08077880(u32 param_1, u32 param_2, u32 param_3)) {
ItemBehavior* item;
u16* puVar2;
if (param_1 - 1 < 0x1f) {
if (gUnk_0811BE48[param_1].unk0[0] != 0) {
puVar2 = &gPlayerState.field_0x92;
} else {
puVar2 = &gPlayerState.field_0x90;
}
if (((*puVar2 & param_2) != 0) || (param_3 != 0)) {
item = sub_0807794C(param_1);
if (item != NULL) {
item->field_0x5[4] = gUnk_0811BE48[param_1].unk0[1];
item->behaviorID = (u8)param_1;
item->field_0x2[1] = (u8)param_2;
}
}
}
}
END_NONMATCH
bool32 sub_080778CC(void) {
ItemBehavior* item;
if (!((((gPlayerState.flags & (PL_USE_PORTAL | PL_MINISH | PL_ROLLING)) == 0) &&
(((gNewPlayerEntity.unk_79 != 0 || (gPlayerState.heldObject != 0)) ||
((gPlayerState.field_0x92 & 0x8000) != 0)))) &&
(((sub_080789A8() != 0 || ((gPlayerState.field_0x90 & 0xf03) == 0)))))) {
return FALSE;
}
item = sub_0807794C(0x1b);
if (item != NULL) {
item->behaviorID = 0x1b;
item->field_0x5[4] = gUnk_0811BE48[0].unk0[0x145];
return TRUE;
} else {
return FALSE;
}
}
ItemBehavior* sub_0807794C(u32 param_1) {
if (((((gPlayerState.queued_action == PLAYER_ROLL) && (param_1 != 0x1b)) ||
(((gPlayerState.flags & (PL_ROLLING | PL_CLONING)) != 0 && (6 < param_1)))) ||
((((gPlayerState.jump_status != 0 || (gPlayerEntity.z.WORD != 0)) && (6 < param_1)) ||
(((gPlayerState.flags & PL_MINISH) != 0 && (gUnk_0811BE48[param_1].unk6[2] == 0)))))) ||
((gPlayerState.floor_type == SURFACE_SWAMP && ((gPlayerState.field_0x37 != 0 && (1 < param_1 - 0x14)))))) {
return NULL;
} else {
u32 tmp = gUnk_0811BE48[param_1].unk0[2];
return gUnk_0811BFC8[tmp](param_1);
}
}
u32 sub_080779E8(void) {
return 0;
}
ItemBehavior* sub_080779EC(u32 param_1) {
if (gUnk_03000B80[1].field_0x5[4] == 0) {
return gUnk_03000B80 + 1;
} else if (gUnk_03000B80[2].field_0x5[4] == 0) {
return gUnk_03000B80 + 2;
} else {
return NULL;
}
}
ItemBehavior* sub_08077A18(u32 param_1) {
ItemBehavior* pIVar1;
if (((gPlayerState.heldObject == 0) && (param_1 != gUnk_03000B80[1].behaviorID)) &&
(param_1 != gUnk_03000B80[2].behaviorID)) {
return sub_080779EC(param_1);
} else {
return NULL;
}
}
ItemBehavior* sub_08077A48(s32 param_1) {
if (gPlayerState.heldObject == 0) {
u32 tmp = gPlayerState.jump_status & 0x20;
if ((((gPlayerState.jump_status & 0x20) == 0)) &&
(gUnk_0811BE48[param_1].unk0[1] >= gUnk_03000B80[0].field_0x5[4])) {
DeletePlayerItem(gUnk_03000B80, 0);
gPlayerState.field_0x0[1] = tmp;
gPlayerState.field_0x1c = tmp;
gPlayerState.sword_state = tmp;
return gUnk_03000B80;
}
}
return NULL;
}
ItemBehavior* sub_08077A98(void) {
if (!(((gSave.stats.bombCount == 0) || (gPlayerState.heldObject != 0)) || (gUnk_03000B80[0].field_0x5[4] != 0))) {
return gUnk_03000B80;
} else {
return NULL;
}
}
ItemBehavior* sub_08077AC8(void) {
ItemBehavior* pIVar1;
u32 index;
index = 0;
pIVar1 = gUnk_03000B80;
while (index < 4) {
if (pIVar1->field_0x5[4] != 0) {
return NULL;
}
pIVar1 += 1;
index += 1;
}
return gUnk_03000B80 + 3;
}
void ResetLantern(void) {
u32 slot;
DeletePlayerItem(gUnk_03000B80 + 3, 3);
gPlayerState.flags &= ~PL_USE_LANTERN;
slot = IsItemEquipped(ITEM_LANTERN_ON);
if (slot != 2) {
ForceEquipItem(ITEM_LANTERN_OFF, slot);
}
}
void PutAwayItems(void) {
ResetPlayerItem();
ResetLantern();
}
void ResetPlayerItem() {
u32 index = 0;
ItemBehavior* ptr = gUnk_03000B80;
do {
DeletePlayerItem(ptr, index);
ptr++;
index++;
} while (index <= 2);
gPlayerState.field_0x3c[1] = 0;
gPlayerState.field_0x1c = 0;
gPlayerState.field_0x1f[2] = 0;
gPlayerState.field_0x0[1] = 0;
gPlayerState.field_0xe = 0;
gPlayerState.dash_state = 0;
gPlayerState.sword_state = 0;
gPlayerState.field_0x3[0] = 0;
gPlayerState.heldObject = 0;
gPlayerState.flags &= ~(PL_ROLLING | PL_SWORD_THRUST);
gNewPlayerEntity.unk_70 = NULL;
if ((gPlayerState.jump_status & 0xc0) == 0) {
gPlayerState.jump_status = 0;
}
switch (gPlayerState.framestate) {
case 2:
case 3:
case 4:
gPlayerState.framestate = PL_STATE_IDLE;
break;
}
}
void sub_08077B98(ItemBehavior* unk) {
if ((gPlayerState.item == NULL) || (gPlayerState.item->id != 1)) {
gPlayerState.item = sub_08077C54(unk);
}
}
void sub_08077BB8(ItemBehavior* beh) {
Entity* temp = sub_08077C54(beh);
if (temp != NULL) {
temp->flags = ENT_PERSIST;
}
gPlayerState.item = temp;
}
Entity* sub_08077BD4(ItemBehavior* beh) {
if (sub_08077C94(beh, gUnk_0811BE48[beh->behaviorID].unk0[3]) != 0) {
return NULL;
} else {
return CreatePlayerItemWithParent(beh, gUnk_0811BE48[beh->behaviorID].unk0[3]);
}
}
Entity* sub_08077C0C(ItemBehavior* beh, u32 arg1) {
u8 bVar1;
Entity* pEVar3;
bVar1 = gUnk_0811BE48[arg1].unk0[3];
if (sub_08077C94(beh, bVar1) != 0) {
return NULL;
} else {
return CreatePlayerItemWithParent(beh, bVar1);
}
}
Entity* CreatePlayerItemWithParent(ItemBehavior* beh, u32 subtype) {
Entity* pEVar1;
pEVar1 = CreatePlayerItem(subtype, 0, 0, beh->behaviorID);
if (pEVar1 != NULL) {
*(ItemBehavior**)&pEVar1->parent = beh;
}
return pEVar1;
}
void* sub_08077C54(ItemBehavior* unk) {
GenericEntity* item;
item = (GenericEntity*)CreateItemGetEntity();
if (item != NULL) {
item->base.id = gUnk_0811BE48[unk->behaviorID].unk0[3];
item->base.kind = PLAYER_ITEM;
item->base.flags = 0xa0;
item->base.parent = (Entity*)unk;
item->field_0x68.HALF.LO = unk->behaviorID;
AppendEntityToList(&item->base, 2);
}
return item;
}
Entity* sub_08077C94(ItemBehavior* arg0, u32 arg1) {
Entity* iVar1;
iVar1 = FindEntityByID(PLAYER_ITEM, gUnk_0811BE48[arg1].unk0[3], 2);
if (iVar1 == NULL) {
return NULL;
}
return iVar1;
}
Entity* CreatePlayerItem(u32 subtype, u32 form, u32 parameter, u32 unk) {
GenericEntity* ent;
ent = (GenericEntity*)GetEmptyEntity();
if (ent != NULL) {
ent->base.flags = ENT_COLLIDE;
ent->base.kind = PLAYER_ITEM;
ent->base.id = subtype;
ent->base.type = form;
ent->base.type2 = parameter;
ent->field_0x68.HALF.LO = unk;
AppendEntityToList(&ent->base, 2);
}
return &ent->base;
}
Entity* sub_08077CF8(u32 subtype, u32 form, u32 parameter, u32 unk) {
GenericEntity* ent;
ent = (GenericEntity*)CreateItemGetEntity();
if (ent != NULL) {
ent->base.flags = ENT_COLLIDE;
ent->base.kind = PLAYER_ITEM;
ent->base.id = subtype;
ent->base.type = form;
ent->base.type2 = parameter;
ent->field_0x68.HALF.LO = unk;
AppendEntityToList(&ent->base, 2);
}
return &ent->base;
}
void sub_08077D38(ItemBehavior* beh, u32 idx) {
u32 r6;
struct_0811BE48* ptr;
gPlayerState.field_0xa |= 8 >> idx;
gPlayerState.keepFacing |= 8 >> idx;
beh->field_0x5[5] = gPlayerEntity.animationState;
if (beh->stateID == 0) {
beh->stateID++;
}
ptr = &gUnk_0811BE48[beh->behaviorID];
if (ptr->unk4) {
if ((gPlayerState.flags & PL_NO_CAP)) {
switch (beh->behaviorID) {
case 0x1b:
r6 = 0x948;
break;
case 1:
r6 = 0x408;
break;
case 0xd:
r6 = 0x40c;
break;
}
sub_08077DF4(beh, r6);
} else {
sub_08077DF4(beh, ptr->unk4);
}
}
beh->field_0xf = ptr->unk6[0];
if (ptr->unk6[1]) {
gPlayerState.field_0x3[1] |= (8 >> idx) | ((8 >> idx) << 4);
}
}
typedef struct {
u8 b0 : 4;
u8 b1 : 4;
} PACKED Unk_bitfield;
typedef struct {
u8 unk[16];
} Unk_struct_in_08077EC8;
void sub_08077DF4(ItemBehavior* beh, u32 animation) {
beh->field_0x10 = animation;
if ((animation & 0xff) > 0xb8) {
animation += beh->field_0x5[5] >> 1;
}
gPlayerEntity.spriteIndex = (short)(animation >> 8);
InitAnimationForceUpdate(&gPlayerEntity, (u8)animation);
sub_08077E54(beh);
}
void UpdateItemAnim(ItemBehavior* beh) {
UpdateAnimationSingleFrame(&gPlayerEntity);
sub_08077E54(beh);
}
void sub_08077E3C(ItemBehavior* ent, u32 idx) {
sub_080042BA(&gPlayerEntity, idx);
sub_08077E54(ent);
}
static void sub_08077E54(ItemBehavior* beh) {
beh->field_0x5[7] = gPlayerEntity.animIndex;
beh->field_0x12[0] = gPlayerEntity.frameIndex;
beh->field_0x5[8] = gPlayerEntity.frameDuration;
beh->field_0x5[9] = gPlayerEntity.frame;
}
void DeletePlayerItem(ItemBehavior* arg0, u32 idx) {
u32 not ;
if (idx == 0) {
if (gPlayerState.item != NULL) {
((Unk_bitfield*)gPlayerState.item)[0x11].b0 = 6;
gPlayerState.item = NULL;
} else {
gPlayerState.item = NULL;
}
}
not = (8 >> idx);
gPlayerState.field_0x3[1] &= ~((u8)((8 >> idx) << 4) | not );
not = ~not ;
gPlayerState.field_0xa &= not ;
gPlayerState.keepFacing &= not ;
MemClear(arg0, 0x1c);
}
bool32 sub_08077EC8(ItemBehavior* beh) {
if ((gPlayerState.sword_state & 8) != 0) {
sub_08077DF4(beh, 0x170);
beh->field_0x5[2] = 0x28;
beh->stateID = 7;
beh->field_0xf = 6;
return TRUE;
} else {
return FALSE;
}
}
bool32 sub_08077EFC(ItemBehavior* arg0) {
return sub_08077F24(arg0, (u16)gPlayerState.field_0x90);
}
bool32 sub_08077F10(ItemBehavior* arg0) {
return sub_08077F24(arg0, (u16)gPlayerState.field_0x92);
}
bool32 sub_08077F24(ItemBehavior* beh, u32 arg1) {
u32 val;
Stats* stats = &gSave.stats;
u32 id = beh->behaviorID;
if (stats->itemButtons[SLOT_A] == id) {
val = 1;
} else if (stats->itemButtons[SLOT_B] == id) {
val = 2;
} else {
val = 0;
}
return (val & arg1) ? 1 : 0;
}
void PlayerCancelHoldItem(ItemBehavior* beh, u32 arg1) {
PlayerDropHeldObject();
DeletePlayerItem(beh, arg1);
}
/**
* Check if player state believes the held item is valid?
* If it's not delete the item?
*/
bool32 PlayerTryDropObject(ItemBehavior* arg0, u32 unk) {
u32 temp;
if (gPlayerState.heldObject == 0) {
PlayerCancelHoldItem(arg0, unk);
temp = FALSE;
} else {
temp = TRUE;
}
return temp;
}
void sub_08077F84(void) {
Entity* obj;
if ((gPlayerEntity.collisionLayer & 2) == 0) {
u32 tile = GetTileTypeByPos(gPlayerEntity.x.HALF.HI, gPlayerEntity.y.HALF.HI - 12, 2);
if (tile == 0x343 || tile == 0x344 || tile == 0x345 || tile == 0x346) {
sub_0807AA80(&gPlayerEntity);
gPlayerState.jump_status |= 8;
obj = CreateObject(OBJECT_44, 0, 0);
if (obj != NULL) {
obj->x = gPlayerEntity.x;
obj->y.HALF.HI = gPlayerEntity.y.HALF.HI - 0xc;
gPlayerEntity.y.HALF.HI -= 0xc;
}
}
}
}
bool32 sub_08077FEC(u32 action) {
ChargeState* state = &gPlayerState.chargeState;
return gPlayerChargeActions[state->action](state);
}
NONMATCH("asm/non_matching/playerUtils/sub_08078008.inc", bool32 sub_08078008(ChargeState* state)) {
u32 swordType;
if (ItemIsSword(gSave.stats.itemButtons[0]) == 0) {
if (ItemIsSword(gSave.stats.itemButtons[1]) != 0) {
swordType = gSave.stats.itemButtons[1];
} else {
swordType = 0;
}
} else {
swordType = gSave.stats.itemButtons[0];
}
if (swordType == 1 || swordType == 2) {
swordType = 0;
}
if ((swordType != 0) && ((gPlayerState.sword_state & 0x20) != 0)) {
if (++state->preChargeTimer > 20) {
state->preChargeTimer = 10;
state->action = 3;
state->swordType = swordType;
}
} else {
state->preChargeTimer = 0;
}
return FALSE;
}
END_NONMATCH
bool32 sub_08078070(ChargeState* state) {
if ((gPlayerState.sword_state & 0x20) != 0) {
if ((gPlayerState.skills & SKILL_FAST_SPLIT) != SKILL_NONE) {
state->chargeTimer += 12;
} else {
state->chargeTimer += 6;
}
if (state->chargeTimer >= 800) {
state->chargeTimer = 800;
state->action = 4;
SoundReq(SFX_ITEM_SWORD_CHARGE_FINISH);
} else {
if (Mod(state->chargeTimer, 20) == 0) {
SoundReq(SFX_ITEM_SWORD_CHARGE);
}
}
} else {
state->action = 1;
}
return TRUE;
}
bool32 sub_080780E0(ChargeState* state) {
if ((gPlayerState.sword_state & 0x40) != 0) {
state->action = 5;
} else {
if ((gPlayerState.sword_state & 0x20) == 0) {
state->action = 1;
}
}
return TRUE;
}
bool32 sub_08078108(ChargeState* state) {
state->chargeTimer -= 1;
if (state->chargeTimer < 0) {
state->chargeTimer = 0;
state->action = 2;
}
return TRUE;
}
bool32 sub_08078124(ChargeState* state) {
state->chargeTimer -= 0x10;
if (state->chargeTimer < 0) {
state->chargeTimer = 0;
state->action = 2;
}
return TRUE;
}
bool32 sub_08078140(ChargeState* info) {
info->preChargeTimer -= 1;
if (info->preChargeTimer < 0) {
info->preChargeTimer = 0;
info->action = 0;
return TRUE;
}
return FALSE;
}
void ForceSetPlayerState(u32 framestate) {
gPlayerState.framestate = framestate;
gPlayerEntity.flags &= ~ENT_COLLIDE;
sub_08078B48();
}
void sub_08078180(void) {
u8 uVar1;
u8 uVar3;
struct_03003DF8* ptr;
if (gUnk_0200AF00.unk_2f != 0)
return;
uVar1 = 0;
if ((gPlayerState.jump_status == 0) &&
((gPlayerState.flags & (PL_IN_HOLE | PL_FROZEN | PL_BURNING | PL_DISABLE_ITEMS | PL_DRUGGED)) == 0)) {
if ((u8)(gPlayerState.heldObject - 1) < 4) {
if (gUnk_0200AF00.unk_2e != 0) {
uVar1 = gUnk_0200AF00.unk_2e;
} else {
uVar1 = 3;
}
} else {
if (gUnk_0200AF00.unk_2d != 0) {
uVar1 = gUnk_0200AF00.unk_2d;
} else {
ptr = sub_080784E4();
if (ptr->entity->interactType == 0) {
switch (ptr->unk_1) {
case 1:
case 7:
uVar1 = 7;
break;
case 8:
if (gRoomVars.shopItemType == ITEM_NONE) {
uVar1 = 9;
}
break;
case 3:
case 5:
case 6:
uVar1 = 6;
break;
case 9:
uVar1 = 5;
break;
case 10:
uVar1 = 2;
break;
}
} else {
if (sub_080789A8()) {
if (((gPlayerState.framestate != 0x0e))) {
if ((gCarriedEntity.unk_1 == 2) && ((gCarriedEntity.unk_8)->carryFlags == 1)) {
uVar1 = 8;
} else {
uVar1 = 9;
}
} else {
return;
}
} else {
if ((gPlayerState.framestate == 1) && (gPlayerState.mobility == 0)) {
uVar1 = 0xc;
} else {
uVar1 = 0;
}
}
}
}
}
}
gUnk_0200AF00.unk_2c = uVar1;
}
bool32 sub_080782C0(void) {
u8 tmp;
Entity* entity;
if (gPlayerState.framestate == 0) {
tmp = gPlayerState.framestate_last;
} else {
tmp = gPlayerState.framestate;
}
switch (tmp) {
case 2:
case 3:
case 0xc:
case 0x12:
case 0x15:
case 0x16:
return FALSE;
}
if ((gPlayerState.field_0x27[0] | gPlayerState.swim_state) != 0) {
return FALSE;
}
if (gPlayerState.floor_type == SURFACE_PIT) {
if (gPlayerState.field_0x14 == 0) {
return FALSE;
}
if (CanDispEzloMessage()) {
return TRUE;
}
return FALSE;
}
if ((gPlayerState.flags & PL_DRUGGED) != 0) {
return FALSE;
}
if (CanDispEzloMessage()) {
return TRUE;
}
entity = sub_080784E4()->entity;
if (entity == NULL) {
return FALSE;
}
if (gPlayerState.heldObject != 0) {
if (gPlayerState.heldObject != 4) {
return FALSE;
}
if ((gNewPlayerEntity.unk_74)->child->kind != OBJECT || (gNewPlayerEntity.unk_74)->child->id != SHOP_ITEM) {
return FALSE;
}
}
if (((gPlayerState.field_0x92 & 0x1000) != 0) && ((u8)(gUnk_03003DF0.unk_4[3] - 1) < 100)) {
sub_0801E738(0);
if (gSave.unk12B[0] != 0) {
gUnk_03003DF0.unk_2 = gUnk_03003DF0.unk_4[3];
*(u8*)(*(int*)(gUnk_03003DF0.unk_4 + 8) + 0x39) = 2;
gPlayerState.queued_action = 7;
} else {
CreateEzloHint(TEXT_INDEX(TEXT_EZLO, 0x65), 0);
}
ForceSetPlayerState(0x13);
return TRUE;
}
if ((gPlayerState.field_0x92 & 0x88) == 0) {
return FALSE;
}
switch (gUnk_03003DF0.unk_4[1]) {
default:
case 0:
return TRUE;
case 1:
case 6:
case 9:
case 0xa:
gPlayerState.queued_action = 7;
ForceSetPlayerState(0x13);
case 3:
case 5:
case 7:
entity->interactType = 1;
gUnk_03003DF0.unk_2 = 0;
return TRUE;
case 8:
if (gRoomVars.shopItemType == 0) {
entity->interactType = 1;
gRoomVars.shopItemType = entity->type;
gRoomVars.shopItemType2 = entity->type2;
return TRUE;
}
return FALSE;
}
return TRUE;
}
void sub_080784C8(void) {
MemClear(&gUnk_03003DF0, 0x188);
gUnk_03003DF0.unk_4 = (u8*)gUnk_0811C000;
}
ASM_FUNC("asm/non_matching/playerUtils/sub_080784E4.inc", struct_03003DF8* sub_080784E4(void))
void sub_08078778(Entity* ent) {
sub_0807887C(ent, 1, 0);
}
void sub_08078784(Entity* ent, u32 arg1) {
sub_0807887C(ent, 1, arg1);
}
void sub_08078790(Entity* ent, u32 arg1) {
sub_0807887C(ent, 2, arg1);
}
void sub_0807879C(Entity* ent) {
sub_0807887C(ent, 7, 0);
}
void sub_080787A8(Entity* ent, u32 arg1) {
sub_0807887C(ent, 7, arg1);
}
void sub_080787B4(Entity* ent) {
sub_0807887C(ent, 9, 0);
}
void sub_080787C0(Entity* ent) {
sub_0807887C(ent, 10, 0);
}
void sub_080787CC(Entity* ent) {
sub_0807887C(ent, 5, 0);
}
s32 sub_080787D8(Entity* ent) {
s32 iVar1;
iVar1 = sub_0807887C(ent, 8, 0);
if (iVar1 >= 0) {
gUnk_03003DF0.array[iVar1].unk_2 = 0xbe;
}
return iVar1;
}
s32 sub_08078800(Entity* ent) {
s32 iVar1;
iVar1 = sub_0807887C(ent, 6, 0);
if (iVar1 >= 0) {
gUnk_03003DF0.array[iVar1].unk_2 = 0xbe;
}
return iVar1;
}
s32 sub_08078828(Entity* ent) {
s32 iVar1;
iVar1 = sub_0807887C(ent, 3, 0);
if (iVar1 >= 0) {
gUnk_03003DF0.array[iVar1].unk_2 = 0xbe;
}
return iVar1;
}
void sub_08078850(Entity* arg0, u32 arg1, u32 arg2, const void* arg3) {
s32 iVar1;
iVar1 = sub_08078904(arg0);
if (iVar1 >= 0) {
gUnk_03003DF0.array[iVar1].unk_0 = arg1;
gUnk_03003DF0.array[iVar1].unk_2 = arg2;
gUnk_03003DF0.array[iVar1].unk_4 = arg3;
}
}
s32 sub_0807887C(Entity* entity, u32 param_2, u32 param_3) {
s32 index;
entity->interactType = 0;
index = sub_08078904(entity);
if (index < 0) {
index = sub_08078904(0);
}
if (index >= 0) {
gUnk_03003DF0.array[index].entity = entity;
gUnk_03003DF0.array[index].unk_1 = param_2;
gUnk_03003DF0.array[index].unk_3 = param_3;
}
if (param_3 != 0) {
Entity* entity = FindEntityByID(OBJECT, OBJECT_9, 6);
if (entity == NULL) {
CreateObject(OBJECT_9, 0, 0);
}
}
return index;
}
/** Clear entry for Entity. */
void sub_080788E0(Entity* entity) {
s32 index = sub_08078904(entity);
if (index > -1) {
MemClear(&gUnk_03003DF0.array[index], 0xc);
}
}
/** Find entry for Entity. */
s32 sub_08078904(Entity* entity) {
u32 index;
for (index = 0; index < 0x20; index++) {
if (entity == gUnk_03003DF0.array[index].entity) {
return index;
}
}
return -1;
}
void RegisterCarryEntity(Entity* this) {
if (gCarriedEntity.count < 0x20) {
gCarriedEntity.unk_c[gCarriedEntity.count] = this;
gCarriedEntity.count++;
}
}
void FreeCarryEntity(Entity* this) {
u32 index;
for (index = 0; index < gCarriedEntity.count; index++) {
if (gCarriedEntity.unk_c[index] == this) {
gCarriedEntity.count--;
break;
}
}
for (; index < gCarriedEntity.count; index++) {
gCarriedEntity.unk_c[index] = gCarriedEntity.unk_c[index + 1];
}
}
ASM_FUNC("asm/non_matching/playerUtils/sub_080789A8.inc", u32 sub_080789A8())
void SetPlayerControl(PlayerControlMode mode) {
if (gPlayerState.controlMode != CONTROL_DISABLED) {
gPlayerState.controlMode = mode;
}
}
void CreateEzloHint(u32 hintId, u32 hintHeight) {
gPlayerState.queued_action = PLAYER_TALKEZLO;
gRoomTransition.hint_idx = hintId;
#if defined(EU) || defined(JP)
// TODO what fields of the room transition are switched in these variants?
gRoomTransition.field_0x2c[7] = hintHeight;
#else
gRoomTransition.hint_height = hintHeight;
#endif
}
void sub_08078AC0(u32 param_1, u32 param_2, u32 param_3) {
gPlayerState.queued_action = PLAYER_ROOM_EXIT;
gPlayerState.field_0x38 = param_1;
gPlayerState.field_0x39 = param_2 != 0;
gPlayerState.field_0x3a = param_3 != 0;
}
/** Set up player states for getting the item? */
void SetPlayerItemGetState(Entity* item, u8 param_2, u8 param_3) {
gPlayerState.field_0x38 = param_2;
gPlayerState.field_0x39 = param_3;
gPlayerState.field_0x3a = 0;
gPlayerState.queued_action = PLAYER_ITEMGET;
gPlayerState.framestate = 0x15;
gPlayerState.swim_state = 0;
gPlayerState.field_0x14 = 1;
gPlayerEntity.child = item;
gPlayerEntity.flags &= ~ENT_COLLIDE;
gPlayerEntity.updatePriority = 2;
DeleteClones();
}
void sub_08078B48(void) {
gPlayerState.field_0x7 |= 0x80;
gPlayerState.keepFacing |= 0x80;
gPlayerState.field_0xa |= 0x80;
gPlayerState.field_0x27[0] = 2;
switch (gPlayerState.framestate) {
case 4:
case 5:
case 0x19:
case 0x1a:
case 0x1d:
break;
case 9:
gPlayerState.flags &= ~PL_ROLLING;
// fallthrough
default:
if (gRoomVars.shopItemType == 0) {
gPlayerState.mobility = 1;
}
break;
}
gPlayerEntity.iframes = -2;
gPlayerState.field_0x82[8] = 2;
}
void ClearPlayerState(void) {
gPlayerState.field_0x0[0] = 0;
gPlayerState.field_0x0[1] = 0;
gPlayerState.jump_status = 0;
gPlayerState.field_0x3[0] = 0;
gPlayerState.field_0x3[1] = 0;
gPlayerState.heldObject = 0;
gPlayerState.pushedObject = 0;
gPlayerState.field_0x7 = 0;
gPlayerState.animation = 0;
gPlayerState.field_0xa = 0;
gPlayerState.keepFacing = 0;
gPlayerState.field_0x35 = 0;
gPlayerState.field_0x36 = 0;
gPlayerState.queued_action = PLAYER_INIT;
gPlayerState.field_0xd = 0;
gPlayerState.field_0xe = 0;
gPlayerState.field_0x11 = 0;
gPlayerState.floor_type = SURFACE_NORMAL;
gPlayerState.floor_type_last = 0;
gPlayerState.field_0x14 = 0;
gPlayerState.sword_state = 0;
gPlayerState.dash_state = 0;
gPlayerState.field_0x1f[0] = 0;
gPlayerState.field_0x1f[1] = 0;
gPlayerState.field_0x1f[2] = 0;
gPlayerState.field_0x22[0] = 0;
gPlayerState.field_0x22[1] = 0;
gPlayerState.swim_state = 0;
gPlayerState.item = NULL;
gPlayerState.speed_modifier = 0;
gPlayerState.field_0x35 = 0;
gPlayerState.flags = 0;
gPlayerState.field_0x38 = 0;
gPlayerState.field_0x39 = 0;
gPlayerState.field_0x3a = 0;
gPlayerState.field_0x3f = 0;
gPlayerState.field_0x3c[0] = 0;
MemFill32(0xffffffff, gPlayerState.path_memory, 0x40);
MemClear(&gUnk_03003DF0, 0x188);
}
void UpdateCarriedObject(void) {
if ((u8)(gPlayerState.heldObject - 3) < 2) {
sub_08078D60();
}
}
ASM_FUNC("asm/non_matching/playerUtils/sub_08078CD0.inc", void sub_08078CD0())
ASM_FUNC("asm/non_matching/playerUtils/sub_08078D60.inc", void sub_08078D60())
void sub_08078E84(Entity* param_1, Entity* param_2) {
SpriteFrame* frame;
if (param_2 == &gPlayerEntity) {
sub_08079BD8(param_1);
param_1->spriteOffsetX = gPlayerEntity.spriteOffsetX;
param_1->spriteOffsetY = gPlayerEntity.spriteOffsetY;
}
frame = &gSpritePtrs[(u16)param_2->spriteIndex].frames[param_2->frameIndex];
if (frame->unk_1 != 0) {
sub_0806FEBC(param_2, 1, param_1);
} else {
sub_0806FEBC(param_2, 3, param_1);
}
}
void ResetPlayerPosition(void) {
gPlayerEntity.x.HALF.HI = gPlayerState.startPosX;
gPlayerEntity.y.HALF.HI = gPlayerState.startPosY;
}
bool32 CheckQueuedAction(void) {
if (gPlayerState.queued_action == 0) {
return FALSE;
} else {
gPlayerEntity.action = gPlayerState.queued_action;
gPlayerEntity.subAction = 0;
gPlayerState.queued_action = 0;
DoPlayerAction(&gPlayerEntity);
return TRUE;
}
}
// this doesnt seem to have any real function where its used
void CheckPlayerVelocity(void) {
u32 angle = gPlayerState.field_0xd;
if ((angle & 0x80) != 0) {
ResetPlayerVelocity();
} else {
gPlayerState.vel_x = gSineTable[angle * 8];
gPlayerState.vel_y = -gSineTable[angle * 8 + 0x40];
}
}
void ResetPlayerVelocity(void) {
gPlayerState.vel_x = 0;
gPlayerState.vel_y = 0;
}
bool32 sub_08078F74(Entity* this) {
if ((gArea.portal_mode == 3) && (gPlayerState.field_0x35 != 0xff)) {
gPlayerState.jump_status = 0x81;
this->action = 0x15;
this->subAction = 0;
this->zVelocity = Q_16_16(2.0);
return TRUE;
} else {
return FALSE;
}
}
ASM_FUNC("asm/non_matching/playerUtils/sub_08078FB0.inc", void sub_08078FB0(Entity* a))
void sub_08079064(Entity* this) {
u32 i;
u32 bVar4;
u32 animation;
if ((gPlayerState.flags & (PL_IN_HOLE | PL_MINISH)) == 0) {
bVar4 = 0;
for (i = 0; i < 4; i++) {
if (gUnk_03000B80[i].field_0xf > bVar4) {
bVar4 = gUnk_03000B80[i].field_0xf;
animation = gUnk_03000B80[i].field_0x10;
}
}
if (gPlayerState.field_0xe < bVar4) {
gPlayerState.animation = animation;
} else if ((gPlayerState.swim_state & 0x80) != 0) {
gPlayerState.animation = 0x2be;
} else {
if (gPlayerState.animation == 0x608 || gPlayerState.animation == 0x104 || gPlayerState.animation == 0x404) {
sub_080790E4(this);
}
}
}
}
void sub_080790E4(Entity* this) {
if (gPlayerState.keepFacing != 0) {
return;
}
if (sub_080793E4(0x10)) {
this->iframes = 0x14;
this->knockbackDuration = 4;
this->knockbackDirection = this->animationState << 2 ^ 0x10;
ModHealth(-2);
SoundReq(SFX_PLY_VO6);
return;
}
if ((gPlayerState.pushedObject & 0x80) != 0) {
return;
}
if (gPlayerState.pushedObject == 0) {
if (sub_080793E4(1)) {
if (this->subtimer <= 5) {
this->subtimer++;
return;
}
} else {
this->subtimer = 0;
return;
}
} else {
gPlayerState.pushedObject--;
}
gPlayerState.field_0x35 = this->animationState;
gPlayerState.framestate = 0x19;
if ((gPlayerState.flags & PL_NO_CAP) != 0) {
gPlayerState.animation = 0x93c;
} else {
gPlayerState.animation = 0x33c;
}
}
void PlayerDropHeldObject(void) {
gPlayerState.heldObject = 0;
gPlayerState.field_0x0[1] = 0;
gNewPlayerEntity.unk_74 = NULL;
}
void PlayerResetStateFromFusion(void) {
if ((gPlayerState.flags & PL_MINISH) == 0) {
SetPlayerActionNormal();
} else {
PlayerMinishSetNormalAndCollide();
}
}
void SetPlayerActionNormal(void) {
gPlayerEntity.action = PLAYER_NORMAL;
gPlayerEntity.subAction = 0;
gPlayerEntity.subtimer = 0;
}
void ResetPlayerAnimationAndAction(void) {
if ((gPlayerState.flags & PL_HIDDEN) == 0) {
gPlayerEntity.spriteSettings.draw = 3;
}
if ((gPlayerState.flags & PL_MINISH) == 0) {
gPlayerEntity.spritePriority.b1 = 1;
PlayerSetNormalAndCollide();
} else {
PlayerMinishSetNormalAndCollide();
}
}
void PlayerSetNormalAndCollide(void) {
gPlayerEntity.flags |= ENT_COLLIDE;
gPlayerEntity.spriteSettings.draw = 3;
gPlayerState.flags &= ~(PL_BUSY | PL_DROWNING | PL_DISABLE_ITEMS | PL_FROZEN | PL_ROLLING | PL_IN_HOLE |
PL_MOLDWORM_RELEASED | PL_PARACHUTE);
ResolvePlayerAnimation();
SetPlayerActionNormal();
SetDefaultPriorityForKind(&gPlayerEntity);
}
void PlayerMinishSetNormalAndCollide(void) {
if ((gPlayerState.flags & PL_HIDDEN) == 0) {
gPlayerEntity.flags |= ENT_COLLIDE;
gPlayerEntity.spriteSettings.draw = 3;
}
gPlayerEntity.action = PLAYER_MINISH;
gPlayerEntity.subAction = 1;
gPlayerEntity.collisionFlags &= 0xfb;
gPlayerState.animation = 0xc18;
gPlayerState.flags &=
~(PL_BUSY | PL_DROWNING | PL_DISABLE_ITEMS | PL_IN_HOLE | PL_MOLDWORM_RELEASED | PL_PARACHUTE);
gPlayerState.swim_state = 0;
gPlayerState.queued_action = 0;
SetDefaultPriorityForKind(&gPlayerEntity);
}
void sub_080792BC(s32 speed, u32 direction, u32 field_0x38) {
gPlayerState.queued_action = PLAYER_08072454;
gPlayerState.field_0x38 = field_0x38;
gPlayerEntity.speed = speed;
gPlayerEntity.direction = direction;
}
ASM_FUNC("asm/non_matching/playerUtils/sub_080792D8.inc", void sub_080792D8())
bool32 sub_080793E4(u32 param_1) {
u32 tmp;
if (gPlayerState.swim_state == 0) {
tmp = gUnk_0811C0F8[gPlayerEntity.animationState >> 1];
} else {
tmp = gUnk_0811C0F8[gPlayerEntity.direction >> 2];
}
if (sub_08079778() && ((gPlayerState.field_0x90 & tmp) != 0)) {
if (param_1 != 0) {
if (!sub_080B1BA4(sub_0807A500(), gPlayerEntity.collisionLayer, param_1)) {
return FALSE;
}
}
return TRUE;
} else {
return FALSE;
}
}
ASM_FUNC("asm/non_matching/playerUtils/RespawnPlayer.inc", void RespawnPlayer())
void sub_08079520(Entity* this) {
s32 tmp = gPlayerState.field_0xd;
if (tmp < 0x80) {
this->direction = gPlayerState.field_0xd;
} else {
this->direction = (this->animationState >> 1) << 3;
}
}
u32 sub_0807953C(void) {
u32 tmp = 0xf38;
return gPlayerState.field_0x92 & tmp;
}
ASM_FUNC("asm/non_matching/playerUtils/sub_08079550.inc", u32 sub_08079550(void))
void sub_08079708(Entity* this) {
gPlayerState.framestate = 0x12;
gPlayerState.field_0x3c[0] = 0xff;
this->flags &= ~ENT_COLLIDE;
this->action = 0xa;
this->subAction = 0;
sub_080085B0(this);
if ((gPlayerState.flags & (PL_CAPTURED | PL_DISABLE_ITEMS)) == 0) {
SetPlayerEventPriority();
}
}
void sub_08079744(Entity* this) {
s32 tmp;
tmp = this->x.HALF.HI & 0xf;
if (tmp != 8) {
if (tmp > 8) {
this->x.HALF.HI--;
} else {
this->x.HALF.HI++;
}
}
tmp = this->y.HALF.HI & 0xf;
if (tmp != 8) {
if (tmp > 8) {
this->y.HALF.HI--;
} else {
this->y.HALF.HI++;
}
}
}
bool32 sub_08079778(void) {
u32 tmp;
if (gPlayerState.swim_state == 0) {
tmp = gUnk_0811C108[gPlayerEntity.animationState >> 1];
} else {
tmp = gUnk_0811C108[gPlayerEntity.direction >> 2];
}
return tmp == (gPlayerEntity.collisions & tmp);
}
u32 sub_080797C4(void) {
u32 tmp = gUnk_0811C110[gPlayerEntity.direction >> 3];
return tmp == (gPlayerEntity.collisions & tmp);
}
ASM_FUNC("asm/non_matching/playerUtils/sub_080797EC.inc", void sub_080797EC())
ASM_FUNC("asm/non_matching/playerUtils/ResolvePlayerAnimation.inc", void ResolvePlayerAnimation())
bool32 sub_08079B24(void) {
if ((gPlayerEntity.action != PLAYER_MINISHDIE) && (gPlayerEntity.health == 0)) {
gPlayerState.flags &= ~PL_PARACHUTE;
gPlayerEntity.knockbackDuration = gPlayerEntity.health;
if (gPlayerState.field_0x7 == 0) {
if (gPlayerState.swim_state != 0) {
RespawnPlayer();
} else {
if ((gPlayerState.field_0x14 == 0) && ((gPlayerState.flags & PL_IN_MINECART) == 0)) {
if (gPlayerEntity.z.HALF.HI < 0) {
if (gPlayerEntity.zVelocity > 0) {
gPlayerEntity.zVelocity = 0;
}
if ((gPlayerState.jump_status & 0x41) == 0) {
gPlayerState.jump_status = 0x41;
gPlayerEntity.direction = 0xff;
gPlayerState.field_0xd = 0xff;
return TRUE;
} else {
return TRUE;
}
}
if (((gPlayerState.flags & PL_FLAGS2) == 0) && (sub_08079D48() == 0)) {
gPlayerState.field_0xa |= 0x10;
return TRUE;
}
}
}
gPlayerEntity.flags &= ~ENT_COLLIDE;
return FALSE;
}
}
return TRUE;
}
void sub_08079BD8(Entity* this) {
this->x = gPlayerEntity.x;
this->y = gPlayerEntity.y;
this->z = gPlayerEntity.z;
this->collisionLayer = gPlayerEntity.collisionLayer;
this->spriteRendering.b3 = gPlayerEntity.spriteRendering.b3;
this->spriteOrientation.flipY = gPlayerEntity.spriteOrientation.flipY;
this->spritePriority.b0 = gPlayerEntity.spritePriority.b0;
}
ASM_FUNC("asm/non_matching/playerUtils/sub_08079C30.inc", bool32 sub_08079C30(Entity* a))
bool32 sub_08079D48(void) {
if (!sub_08079C30(&gPlayerEntity)) {
return TRUE;
} else {
if (!PlayerCheckNEastTile()) {
if (!sub_08007DD6((u16)GetTileUnderEntity(&gPlayerEntity), gUnk_0811C268)) {
return TRUE;
}
}
}
return FALSE;
}
void sub_08079D84(void) {
if ((gPlayerEntity.action == PLAYER_NORMAL) || (gPlayerEntity.action == PLAYER_ROLL)) {
gPlayerState.field_0x38 = 0x9c;
gPlayerState.field_0x39 = 2;
gPlayerState.field_0x3a = 0x3c;
gPlayerState.queued_action = PLAYER_0807204C;
gPlayerEntity.iframes = 0x7c;
PutAwayItems();
SoundReq(SFX_193);
}
}
void sub_08079DCC(void) {
if (gPlayerEntity.action == 1) {
gPlayerState.field_0x38 = 0xa0;
gPlayerState.field_0x39 = 3;
gPlayerState.field_0x3a = 0;
gPlayerState.queued_action = PLAYER_0807204C;
SoundReq(SFX_193);
}
}
void UpdatePlayerMovement(void) {
if ((gPlayerEntity.speed != 0) &&
(gPlayerEntity.speed += gPlayerState.speed_modifier, gPlayerEntity.speed < 0x20)) {
gPlayerEntity.speed = 0x20;
}
if ((gPlayerEntity.direction & 4) == 0) {
sub_08079E90(gPlayerEntity.direction);
}
sub_0800857C(&gPlayerEntity);
sub_0807A5B8(gPlayerEntity.direction);
}
void sub_08079E58(s32 speed, u32 direction) {
if ((gPlayerEntity.direction & 4) == 0) {
sub_08079E90(direction);
}
sub_080085B0(&gPlayerEntity);
sub_080027EA(&gPlayerEntity, (s16)speed, (u8)direction);
sub_0807A5B8(direction);
}
bool32 sub_08079E90(u32 param_1) {
s16 tmp1;
s16 tmp2;
if (gPlayerEntity.direction & DirectionEast) {
if (gPlayerEntity.direction & DirectionSouth) {
tmp2 = -gPlayerEntity.hitbox->unk2[0];
} else {
tmp2 = gPlayerEntity.hitbox->unk2[0];
}
tmp1 = gPlayerEntity.hitbox->unk2[1];
} else {
tmp2 = gPlayerEntity.hitbox->unk2[2];
if (gPlayerEntity.direction != DirectionNorth) {
tmp1 = gPlayerEntity.hitbox->unk2[3];
} else {
tmp1 = -gPlayerEntity.hitbox->unk2[3];
}
}
if (!sub_08079F48(param_1, sub_080B1AF0(&gPlayerEntity, tmp2, tmp1))) {
if ((gPlayerEntity.direction & DirectionSouth) != 0) {
tmp1 = -tmp1;
} else {
tmp2 = -tmp2;
}
if (!sub_08079F48(param_1, sub_080B1AF0(&gPlayerEntity, tmp2, tmp1))) {
return FALSE;
}
}
return TRUE;
}
bool32 sub_08079F48(u32 param_1, u32 param_2) {
if (gUnk_0811C118[param_1 >> 2] == param_2) {
gPlayerEntity.direction = (gPlayerEntity.direction + 4) & 0x1f;
} else {
if (gUnk_0811C118[(param_1 >> 2) + 1] != param_2) {
return FALSE;
}
gPlayerEntity.direction = (gPlayerEntity.direction - 4) & 0x1f;
}
return TRUE;
}
bool32 PlayerCanBeMoved(void) {
if ((gPlayerState.flags &
(PL_BUSY | PL_DROWNING | PL_CAPTURED | PL_USE_PORTAL | PL_HIDDEN | PL_FROZEN | PL_FALLING | PL_DISABLE_ITEMS |
PL_PIT_IS_EXIT | PL_IN_MINECART | PL_MOLDWORM_CAPTURED | PL_IN_HOLE | PL_FLAGS2000000 | PL_CLIMBING)) != 0 ||
gPlayerState.field_0x3c[0] != 0 || gPlayerEntity.action == PLAYER_FALL ||
gPlayerEntity.action == PLAYER_08071DB8) {
return FALSE;
} else {
return TRUE;
}
}
u32 sub_08079FC4(u32 param_1) {
return sub_08079FD4(&gPlayerEntity, param_1);
}
ASM_FUNC("asm/non_matching/playerUtils/sub_08079FD4.inc", u32 sub_08079FD4(Entity* a, u32 b))
void sub_0807A050(void) {
u32 palette;
if ((gPlayerState.hurtBlinkSpeed != 0) && ((gMessage.doTextBox & 0x7f) == 0)) {
gPlayerState.hurtBlinkSpeed--;
}
palette = sub_0807A094(0);
if (palette != gPlayerState.field_0x82[1]) {
gPlayerState.field_0x82[1] = palette;
ChangeObjPalette(&gPlayerEntity, palette);
}
}
u32 sub_0807A094(u32 param_1) {
bool32 condition;
u32 result = 0x16;
if (gPlayerState.hurtBlinkSpeed != 0) {
result = 0x1b;
if (0x78 < gPlayerState.hurtBlinkSpeed) {
result = 0x1a;
}
} else {
if (gSave.stats.charm != 0) {
condition = TRUE;
if (((param_1 == 0) && (gSave.stats.charmTimer < 0xb4)) && ((gSave.stats.charmTimer & 8) != 0)) {
condition = FALSE;
}
if (condition) {
switch (gSave.stats.charm) {
case 0x2f:
result = 0x18;
break;
case 0x31:
result = 0x17;
break;
case 0x30:
default:
result = 0x19;
break;
}
}
}
}
return result;
}
void DeleteClones(void) {
gPlayerClones[0] = NULL;
gPlayerClones[1] = NULL;
gPlayerClones[2] = NULL;
gPlayerState.flags &= ~PL_CLONING;
if (((gPlayerEntity.action != 0x17) || (gPlayerState.chargeState.action != 4)) &&
(gPlayerState.chargeState.action == 4 || gPlayerState.chargeState.action == 5)) {
gPlayerState.chargeState.action = 1;
}
}
bool32 HasSwordEquipped(void) {
if (ItemIsSword((u32)gSave.stats.itemButtons[0]) != 0) {
return TRUE;
} else {
return ItemIsSword((u32)gSave.stats.itemButtons[1]);
}
}
void sub_0807A180(Entity* param_1, u32 param_2, u32 param_3, u32 param_4) {
GenericEntity stackEntity;
PositionRelative(param_1, &stackEntity.base, 0, -0x40000);
stackEntity.base.animationState = param_1->animationState;
sub_08003FDE(&stackEntity.base, param_2, param_3, param_4);
}
void UpdateFloorType(void) {
gPlayerState.floor_type = GetSurfaceCalcType(&gPlayerEntity, 0, 0);
gUnk_0811C120[gPlayerState.floor_type](&gPlayerEntity);
}
u32 GetSurfaceCalcType(Entity* param_1, s32 x, s32 y) {
u32 position = TILE(param_1->x.HALF.HI + (u32)x, param_1->y.HALF.HI + y);
u32 tileType = GetTileTypeByPos(param_1->x.HALF.HI + x, param_1->y.HALF.HI + y, gPlayerEntity.collisionLayer);
if (tileType != gPlayerState.field_0x22[1]) {
gPlayerState.field_0x37 = 0;
}
if ((tileType != gPlayerState.field_0x22[1]) || (position != gPlayerState.field_0x22[0])) {
gPlayerState.field_0x22[0] = position;
gPlayerState.field_0x22[1] = tileType;
gPlayerState.field_0x11 = 0;
}
if (gPlayerState.field_0x11 != 0xff) {
gPlayerState.field_0x11++;
}
if (gPlayerState.field_0x37 != 0xff) {
gPlayerState.field_0x37++;
}
gPlayerState.floor_type_last = gPlayerState.floor_type;
tileType = GetRelativeCollisionTile(param_1, x, y);
return sub_08007DD6(tileType, (u16*)gUnk_08007CAC);
}
void EnablePlayerDraw(Entity* this) {
this->type2 = 0;
this->spriteSettings.draw = 3;
gPlayerState.flags &= ~PL_HIDDEN;
}
bool32 sub_0807A2B8(void) {
if (PlayerCheckNEastTile()) {
return TRUE;
} else {
if (((gPlayerState.jump_status & 200) == 0) && (gPlayerEntity.collisionLayer != 1)) {
CreateObjectWithParent(&gPlayerEntity, OBJECT_44, 0, 0);
}
return FALSE;
}
}
ASM_FUNC("asm/non_matching/playerUtils/sub_0807A2F8.inc", u32 sub_0807A2F8(u32 a1))
ASM_FUNC("asm/non_matching/playerUtils/sub_0807A500.inc", u32 sub_0807A500())
ASM_FUNC("asm/non_matching/playerUtils/sub_0807A5B8.inc", void sub_0807A5B8(u32 a))
ASM_FUNC("asm/non_matching/playerUtils/sub_0807A750.inc", void sub_0807A750())
u32 sub_0807A894(Entity* this) {
s32 x;
s32 y;
switch (this->direction) {
case DirectionNorth:
y = -8;
x = 0;
break;
case DirectionSouth:
y = 5; // why??? ._.
x = 0;
break;
case DirectionEast:
y = 0;
x = 8;
break;
case DirectionWest:
y = 0;
x = -8;
break;
default:
y = 0;
x = 0;
break;
}
return GetRelativeCollisionTile(this, x, y);
}
void nullsub_505(void) {
}
NONMATCH("asm/non_matching/playerUtils/sub_0807A8D8.inc", void sub_0807A8D8(Entity* this)) {
u32 tmp;
if ((gPlayerState.flags & PL_MINISH) == 0) {
tmp = sub_080B1B84(COORD_TO_TILE_OFFSET(this, 0, 1), gPlayerEntity.collisionLayer) & 0x20;
if (tmp != 0) {
sub_0807AAF8(this, COORD_TO_TILE_OFFSET(this, 0, 1));
}
tmp = sub_080B1B84(COORD_TO_TILE_OFFSET(this, -2, 0), gPlayerEntity.collisionLayer) & 0x20;
if (tmp != 0) {
sub_0807AAF8(this, COORD_TO_TILE_OFFSET(this, -2, 0));
}
tmp = sub_080B1B84(COORD_TO_TILE_OFFSET(this, 2, 0), gPlayerEntity.collisionLayer) & 0x20;
if (tmp != 0) {
sub_0807AAF8(this, COORD_TO_TILE_OFFSET(this, 2, 0));
}
}
tmp = sub_080B1B84(COORD_TO_TILE(this), gPlayerEntity.collisionLayer);
if ((tmp & 0x20) != 0) {
sub_0807AAF8(this, COORD_TO_TILE(this));
}
if ((tmp & 2) != 0) {
sub_0807AABC(this);
} else {
if ((tmp & 4) != 0) {
sub_0807AA80(this);
}
}
}
END_NONMATCH
void sub_0807AA80(Entity* this) {
if (((gPlayerState.flags & PL_HIDDEN) == 0) && (this->collisionLayer = 2, this->z.HALF.HI == 0)) {
this->spriteOrientation.flipY = 1;
this->spriteRendering.b3 = 1;
}
}
void sub_0807AABC(Entity* this) {
if (((gPlayerState.flags & PL_HIDDEN) == 0) && (this->collisionLayer = 1, this->z.HALF.HI == 0)) {
this->spriteOrientation.flipY = 2;
this->spriteRendering.b3 = 2;
}
}
void sub_0807AAF8(Entity* this, u32 tilePos) {
u32 tmp;
u32 index;
if (this->z.HALF.HI == 0) {
tilePos |= this->collisionLayer << 0x1e;
for (index = 0; index < 0xf; index++) {
if (gPlayerState.path_memory[index] == tilePos) {
break;
}
tmp = gPlayerState.path_memory[index];
gPlayerState.path_memory[index] = tilePos;
tilePos = tmp;
}
gPlayerState.path_memory[index] = tilePos;
}
}
void sub_0807AB44(Entity* this, s32 xOffset, s32 yOffset) {
Entity* object;
const u16* ptr =
sub_0806FC50(GetTileType(COORD_TO_TILE_OFFSET(this, -xOffset, -yOffset), this->collisionLayer), 0xb);
if (ptr != NULL) {
if (ptr[3] == 0x76) {
object = CreateObject(OBJECT_2A, 1, 0);
if (object != NULL) {
PositionRelative(this, object, xOffset << 0x10, yOffset << 0x10);
sub_08004168(object);
sub_0807B7D8(ptr[3], COORD_TO_TILE(object), object->collisionLayer);
}
} else {
object = CreateObject(OBJECT_2A, 2, 0);
if (object != NULL) {
PositionRelative(this, object, xOffset << 0x10, yOffset << 0x10);
object->child = (Entity*)ptr;
SetTile(0x404f, COORD_TO_TILE(object), object->collisionLayer);
}
}
}
}
bool32 sub_0807AC54(Entity* this) {
if (gPlayerState.field_0x11 == 0) {
return FALSE;
}
switch (gPlayerState.floor_type) {
case SURFACE_LADDER:
this->x.HALF.HI = (this->x.HALF.HI & 0xfff0) | 8;
// fallthrough
case SURFACE_CLIMB_WALL:
this->action = 0x1d;
this->subAction = 0;
this->y.HALF.LO = 0;
gPlayerState.animation = 0x2cf;
return TRUE;
case SURFACE_AUTO_LADDER:
this->x.HALF.HI = (this->x.HALF.HI & 0xfff0) | 8;
// fallthrough
case SURFACE_2C:
this->action = 0x1d;
this->subAction = 1;
this->y.HALF.LO = 0;
return TRUE;
default:
return FALSE;
}
}
void sub_0807ACCC(Entity* this) {
s32 speed;
this->spritePriority.b1 = 0;
this->knockbackDuration = 0;
if (GetInventoryValue(ITEM_SWIM_BUTTERFLY) == 1) {
speed = 0x100;
} else {
speed = 0xc0;
}
if (speed > *(s16*)&this->speed) {
this->speed = speed;
this->direction = gPlayerState.field_0xd;
if ((gPlayerState.swim_state & 0xf) != 1) {
return;
}
} else {
this->speed -= 4;
}
if (gPlayerState.field_0x82[7] == 0) {
if (!sub_0807ADB8(this)) {
sub_0807AE20(this);
}
} else {
gPlayerState.field_0x82[7]--;
if (gPlayerState.field_0x82[7] != 0) {
sub_0807ADB8(this);
} else {
gPlayerState.swim_state &= 0x7f;
this->spritePriority.b0 = 4;
SoundReq(SFX_163);
}
}
if ((gPlayerState.swim_state & 0x80) != 0) {
this->collisionFlags |= 4;
this->spritePriority.b0 = 6;
} else {
this->collisionFlags &= 0xfb;
}
}
bool32 sub_0807ADB8(Entity* this) {
u8 tmp;
if ((gPlayerState.field_0x92 & 0x10) != 0) {
gPlayerState.swim_state ^= 0x80;
tmp = (gPlayerState.swim_state & 0x80);
if (tmp != 0) {
gPlayerState.field_0x82[7] = 0x78;
} else {
this->spritePriority.b0 = 4;
gPlayerState.field_0x82[7] = tmp;
}
SoundReq(SFX_163);
return TRUE;
} else {
return FALSE;
}
}
void sub_0807AE20(Entity* this) {
if ((((this->action != 0x17) || (gPlayerState.field_0xa == 0)) && (gRoomControls.reload_flags == 0)) &&
((gPlayerState.field_0x92 & 8) != 0)) {
if (GetInventoryValue(ITEM_SWIM_BUTTERFLY) == 1) {
this->speed = 0x1c0;
} else {
this->speed = 0x180;
}
sub_08079520(this);
SoundReq(SFX_162);
}
if (sub_080793E4(0x10)) {
this->iframes = 0x14;
this->knockbackDuration = 4;
this->knockbackDirection = this->animationState << 2 ^ 0x10;
ModHealth(-2);
SoundReq(SFX_PLY_VO6);
}
if ((this->direction & 0x80) != 0) {
if ((gRoomTransition.frameCount & 0xf) == 0) {
CreateRandomWaterTrace(this, 4);
}
} else {
if ((gRoomTransition.frameCount & 7) == 0) {
CreateWaterTrace(this);
}
}
}
void UpdatePlayerSkills(void) {
gPlayerState.skills = SKILL_NONE;
if (GetInventoryValue(ITEM_SKILL_SPIN_ATTACK) == 1) {
gPlayerState.skills |= SKILL_SPIN_ATTACK;
}
if (GetInventoryValue(ITEM_SKILL_ROLL_ATTACK) == 1) {
gPlayerState.skills |= SKILL_ROLL_ATTACK;
}
if (GetInventoryValue(ITEM_SKILL_DASH_ATTACK) == 1) {
gPlayerState.skills |= SKILL_DASH_ATTACK;
}
if (GetInventoryValue(ITEM_SKILL_ROCK_BREAKER) == 1) {
gPlayerState.skills |= SKILL_ROCK_BREAKER;
}
if (GetInventoryValue(ITEM_SKILL_SWORD_BEAM) == 1) {
gPlayerState.skills |= SKILL_SWORD_BEAM;
}
if (GetInventoryValue(ITEM_SKILL_GREAT_SPIN) == 1) {
gPlayerState.skills |= SKILL_GREAT_SPIN;
}
if (GetInventoryValue(ITEM_SKILL_DOWN_THRUST) == 1) {
gPlayerState.skills |= SKILL_DOWN_THRUST;
}
if (GetInventoryValue(ITEM_SKILL_PERIL_BEAM) == 1) {
gPlayerState.skills |= SKILL_PERIL_BEAM;
}
if (GetInventoryValue(ITEM_FOURSWORD) == 1) {
gPlayerState.skills |= SKILL_FOURSWORD;
}
if (GetInventoryValue(ITEM_SKILL_FAST_SPIN) == 1) {
gPlayerState.skills |= SKILL_FAST_SPIN;
}
if (GetInventoryValue(ITEM_SKILL_FAST_SPLIT) == 1) {
gPlayerState.skills |= SKILL_FAST_SPLIT;
}
if (GetInventoryValue(ITEM_SKILL_LONG_SPIN) == 1) {
gPlayerState.skills |= SKILL_LONG_SPIN;
}
}
void sub_0807AFE8(void) {
Entity* effect;
PutAwayItems();
effect = CreateFx(&gPlayerEntity, FX_BIG_EXPLOSION2, 0);
if (effect != NULL) {
effect->y.HALF.HI++;
}
gPlayerState.queued_action = PLAYER_MINISH;
}
/** Returns which kind of sword projectile is created. */
u32 sub_0807B014(void) {
if (((gPlayerState.skills & SKILL_SWORD_BEAM) != 0) && gSave.stats.health == gSave.stats.maxHealth) {
return 0xf;
} else {
if ((gPlayerState.skills & SKILL_PERIL_BEAM) != SKILL_NONE && gSave.stats.health <= 8) {
return 0x16;
} else {
return 0;
}
}
}
void sub_0807B068(Entity* entity) {
if ((gPlayerState.dash_state | gPlayerState.field_0x3[1]) == 0) {
if (gPlayerState.swim_state != 0) {
if ((gPlayerState.swim_state & 0x80) != 0) {
gPlayerState.animation = 0xc1c;
} else {
gPlayerState.animation = 0xc0c;
}
} else {
if ((gPlayerState.field_0xd & 0x80) != 0) {
if (gPlayerState.animation != 0xc18) {
gPlayerState.animation = 0xc18;
}
} else {
if (gPlayerState.animation != 0xc04) {
gPlayerState.animation = 0xc04;
}
}
}
}
}
void sub_0807B0C8(void) {
sub_0806FEBC(&gPlayerEntity, 0, 0);
sub_0806FEBC(&gPlayerEntity, 1, 0);
sub_0806FEBC(&gPlayerEntity, 2, &gPlayerEntity);
sub_0806FEBC(&gPlayerEntity, 3, 0);
}
void PlayerWarp(Entity* player) {
gUnk_0811C27C[player->subAction](player);
}
void sub_0807B114(PlayerEntity* this) {
super->subAction = 1;
this->unk_6c = gPlayerState.field_0x38;
}
void sub_0807B128(PlayerEntity* this) {
gUnk_0811C284[this->unk_6c](this);
}
void sub_0807B144(PlayerEntity* this) {
super->spriteSettings.draw = 1;
super->direction = super->animationState << 2;
super->speed = 0xa0;
super->zVelocity = Q_16_16(4.0);
gPlayerState.jump_status = 0x81;
SetPlayerActionNormal();
}
void nullsub_506(void) {
}
void sub_0807B178(PlayerEntity* this) {
super->spriteSettings.draw = 1;
super->direction = 0x10;
super->speed = 0;
super->zVelocity = Q_16_16(4.0);
gPlayerState.jump_status = 0x81;
SetPlayerActionNormal();
}
void sub_0807B1A8(PlayerEntity* this) {
gUnk_0811C298[this->unk_6e](this);
if ((gRoomTransition.frameCount & 7) == 0) {
CreateSparkle(super);
}
}
void sub_0807B1DC(PlayerEntity* this) {
this->unk_6e++;
super->timer = 0x1e;
}
void sub_0807B1EC(PlayerEntity* this) {
if (--super->timer == 0) {
this->unk_6e++;
super->zVelocity = Q_16_16(1.0);
gPlayerState.animation = 0x2c2;
}
}
void sub_0807B21C(PlayerEntity* this) {
UpdateAnimationSingleFrame(super);
if (super->zVelocity < 0) {
GravityUpdate(super, Q_8_8(4.0));
} else {
GravityUpdate(super, Q_8_8(8.0));
}
if (super->zVelocity < -Q_16_16(0.5)) {
super->timer = 0x78;
super->subtimer = 0;
this->unk_6e++;
this->unk_68 = super->z.WORD;
}
}
void sub_0807B264(PlayerEntity* this) {
s32 tmp;
UpdateAnimationSingleFrame(super);
super->subtimer += 2;
tmp = gSineTable[super->subtimer];
tmp >>= 7;
tmp <<= 0x10;
super->z.WORD = this->unk_68 + tmp;
if (--super->timer == 0) {
super->timer = 0x50;
super->zVelocity = Q_16_16(0.5);
this->unk_6e++;
#ifndef EU
SoundReq(SFX_NEAR_PORTAL);
#endif
}
}
void sub_0807B2B8(PlayerEntity* this) {
GravityUpdate(super, Q_8_8(-32.0));
UpdateAnimationSingleFrame(super);
if (super->timer != 0 && --super->timer == 0) {
DoExitTransition(&gUnk_0813AD88[this->unk_6d]);
}
}
void sub_0807B2F8(PlayerEntity* this) {
if (this->unk_6e == 0) {
this->unk_6e += 1;
sub_0809D738(super);
}
}
void SetTileType(u32 tileType, u32 position, u32 layer) {
u8 collisionData;
u16 metatile;
LayerStruct* data;
u16* src;
u16* dest;
if (tileType < 0x800) {
DeleteLoadedTileEntity(position, layer);
data = GetLayerByIndex(layer);
metatile = data->unkData2[tileType];
data->mapData[position] = metatile;
collisionData = gUnk_080B3E80[tileType];
data->collisionData[position] = collisionData;
if ((gRoomControls.scroll_flags & 2) != 0) {
gMapBottom.collisionData[position] = collisionData;
}
data->unkData3[position] = gUnk_080B37A0[tileType];
if ((gRoomControls.scroll_flags & 1) == 0) {
u32 offset = (position & 0x3f) * 2 + (position & 0xfc0) * 4;
if (layer != 2) {
dest = gMapDataBottomSpecial + offset;
} else {
dest = gMapDataTopSpecial + offset;
}
src = data->metatiles + metatile * 4;
*dest = *src;
dest[1] = src[1];
dest[0x80] = src[2];
dest[0x81] = src[3];
if (gRoomControls.reload_flags != 1) {
gUpdateVisibleTiles = 1;
}
}
} else if (tileType >= 0x4000) { // The tile type actually directly is a tileIndex
SetTile(tileType, position, layer);
} else {
RestorePrevTileEntity(position, layer);
}
}
bool32 sub_0807B434(u32 position, u32 layer) {
switch (GetTileType(position, layer)) {
case 0x36:
case 0x37:
return FALSE;
default:
return sub_080B1AE0(position, layer) != 0xd;
}
}
bool32 sub_0807B464(u32 param_1, u32 param_2) {
return sub_080B1AE0(param_1, param_2) == 0x56;
}
void sub_0807B480(u32 tilePos, u32 param_2) {
u32 tmp1;
u16 tmp2;
u16 tmp3;
u16 tileType;
const u16* ptr;
if (sub_0807B464(tilePos, 2)) {
tmp1 = sub_0807B464(tilePos - 0x40, 2);
tmp1 |= sub_0807B464(tilePos + 1, 2) << 1;
tmp1 |= sub_0807B464(tilePos + 0x40, 2) << 2;
tmp1 |= sub_0807B464(tilePos - 1, 2) << 3;
tmp1 |= sub_0807B464(tilePos + 0x41, 1) << 1;
tmp1 |= sub_0807B464(tilePos + 0x3f, 1) << 3;
if (GetTileType(tilePos + 0x40, 2) != 0) {
tmp1 |= sub_0807B464(tilePos + 0x80, 1) << 2;
}
tmp2 = gUnk_0811C2CC[tmp1];
tileType = GetTileType(tilePos, 2);
ptr = gUnk_0811C2EC;
tmp3 = 0;
for (; *ptr != 0; ptr = ptr + 3) {
if (tileType == ptr[0]) {
tmp3 = ptr[1];
break;
}
}
tmp3 = tmp3 & ~(1 << (param_2));
for (ptr = gUnk_0811C2EC; *ptr != 0; ptr = ptr + 3) {
if ((tmp3 == ptr[1]) && (tmp1 == ptr[2])) {
tmp2 = ptr[0];
break;
}
}
SetTileType(tmp2, tilePos, 2);
}
}
void sub_0807B55C(u32 param_1, u32 param_2, u16* param_3) {
u32 tmp;
if (sub_0807B464(param_1, param_2)) {
tmp = sub_0807B464(param_1 - 0x40, param_2);
tmp |= sub_0807B464(param_1 + 1, param_2) << 1;
tmp |= sub_0807B464(param_1 + 0x40, param_2) << 2;
tmp |= sub_0807B464(param_1 - 1, param_2) << 3;
SetTileType(param_3[tmp], param_1, param_2);
}
}
bool32 sub_0807B5B0(Entity* this) {
return sub_0807B600(COORD_TO_TILE_OFFSET(this, -gUnk_0811C456[(this->animationState & 6)],
-gUnk_0811C456[(this->animationState & 6) + 1]));
}
u32 sub_0807B600(u32 param_1) {
u32 tileType;
u32 tile;
tile = param_1 - 0x40;
if (sub_080B1AE0(param_1, 1) != 0x56) {
return FALSE;
} else {
tileType = GetTileType(param_1, 1);
if (tileType == 0x26a) {
sub_0807B820(param_1);
} else if (tileType == 0x267) {
sub_0807B820(param_1 + 0x40);
} else if (tileType == 0x27a) {
sub_0807B8A8(param_1);
} else if (tileType == 0x277) {
sub_0807B8A8(param_1 + 0x40);
} else if (tileType == 0x28a) {
sub_0807B930(param_1);
} else if (tileType == 0x287) {
sub_0807B930(param_1 + 0x40);
} else {
if (GetTileType(param_1, 2) != 0) {
SetTileType(0x2f2, param_1, 1);
if (sub_080B1B44(tile, 1) == 3) {
SetTileType(0x2f4, tile, 1);
}
if (sub_080B1B44(param_1 + 0x40, 1) == 3) {
SetTileType(0x2f4, param_1, 1);
}
} else {
SetTileType(0x2f4, param_1, 1);
}
if (sub_0807B464(tile, 2)) {
SetTileType(0, tile, 2);
if (GetTileType(tile, 1) == 0x2f2) {
SetTileType(0x2f4, tile, 1);
}
sub_0807B55C(param_1 + 1, 1, (u16*)&gUnk_0811C2AC);
sub_0807B55C(param_1 - 1, 1, (u16*)&gUnk_0811C2AC);
sub_0807B55C(tile, 1, (u16*)&gUnk_0811C2AC);
}
sub_0807B480(tile + 1, 3);
sub_0807B480(tile - 1, 1);
sub_0807B480(tile + 0x40, 0);
sub_0807B480(tile - 0x40, 2);
}
return TRUE;
}
}
void sub_0807B778(u32 position, u32 layer) {
u32 tmp;
if (sub_080B1AE0(position, layer) == 0xd) {
tmp = sub_0807B434(position - 0x40, layer);
tmp |= sub_0807B434(position + 1, layer) << 1;
tmp |= sub_0807B434(position + 0x40, layer) << 2;
tmp |= sub_0807B434(position - 1, layer) << 3;
SetTileType(gUnk_0811C466[tmp], position, layer);
}
}
void sub_0807B7D8(u32 param_1, u32 param_2, u32 param_3) {
if (param_1 == 53) {
CloneTile(53, param_2, param_3);
sub_0807B778(param_2, param_3);
sub_0807B778(param_2 + 1, param_3);
sub_0807B778(param_2 - 1, param_3);
sub_0807B778(param_2 + 64, param_3);
sub_0807B778(param_2 - 64, param_3);
} else {
SetTileType(param_1, param_2, param_3);
}
}
void sub_0807B820(u32 position) {
SetTileType(0x26c, position + TILE_POS(-1, -1), 1);
SetTileType(0x273, position + TILE_POS(-1, -1), 2);
SetTileType(0x26d, position + TILE_POS(0, -1), 1);
SetTileType(0x274, position + TILE_POS(0, -1), 2);
SetTileType(0x26e, position + TILE_POS(1, -1), 1);
SetTileType(0x275, position + TILE_POS(1, -1), 2);
SetTileType(0x26f, position + TILE_POS(-1, 0), 1);
SetTileType(0x270, position, 1);
SetTileType(0x272, position + TILE_POS(1, 0), 1);
}
void sub_0807B8A8(u32 position) {
SetTileType(0x27c, position + TILE_POS(-1, -1), 1);
SetTileType(0x283, position + TILE_POS(-1, -1), 2);
SetTileType(0x27d, position + TILE_POS(0, -1), 1);
SetTileType(0x284, position + TILE_POS(0, -1), 2);
SetTileType(0x27e, position + TILE_POS(1, -1), 1);
SetTileType(0x285, position + TILE_POS(1, -1), 2);
SetTileType(0x27f, position + TILE_POS(-1, 0), 1);
SetTileType(0x280, position, 1);
SetTileType(0x282, position + TILE_POS(1, 0), 1);
}
void sub_0807B930(u32 position) {
SetTileType(0x28c, position + TILE_POS(-1, -1), 1);
SetTileType(0x293, position + TILE_POS(-1, -1), 2);
SetTileType(0x28d, position + TILE_POS(0, -1), 1);
SetTileType(0x294, position + TILE_POS(0, -1), 2);
SetTileType(0x28e, position + TILE_POS(1, -1), 1);
SetTileType(0x295, position + TILE_POS(1, -1), 2);
SetTileType(0x28f, position + TILE_POS(-1, 0), 1);
SetTileType(0x290, position, 1);
SetTileType(0x292, position + TILE_POS(1, 0), 1);
}
void sub_0807B9B8(u32 tileIndex, u32 position, u32 layer) {
LayerStruct* data;
u16* src;
u16* dest;
u16 tileType;
DeleteLoadedTileEntity(position, layer);
data = GetLayerByIndex(layer);
data->mapData[position] = tileIndex;
tileType = data->metatileTypes[tileIndex];
data->collisionData[position] = gUnk_080B3E80[tileType];
data->unkData3[position] = gUnk_080B37A0[tileType];
if ((gRoomControls.scroll_flags & 1) == 0) {
u32 offset = (position & 0x3f) * 2 + (position & 0xfc0) * 4;
if (layer != 2) {
dest = gMapDataBottomSpecial + offset;
} else {
dest = gMapDataTopSpecial + offset;
}
src = data->metatiles + tileIndex * 4;
*dest = *src;
dest[1] = src[1];
dest[0x80] = src[2];
dest[0x81] = src[3];
if (gRoomControls.reload_flags != 1) {
gUpdateVisibleTiles = 1;
}
}
}
void RestorePrevTileEntity(u32 position, u32 layer) {
u32 tileIndex;
u32 tileType;
LayerStruct* data;
u16* dest;
u16* src;
DeleteLoadedTileEntity(position, layer);
data = GetLayerByIndex(layer);
data->mapData[position] = tileIndex = data->mapDataClone[position];
tileType = data->metatileTypes[tileIndex];
data->collisionData[position] = gUnk_080B3E80[tileType];
data->unkData3[position] = gUnk_080B37A0[tileType];
if ((gRoomControls.scroll_flags & 1) == 0) {
u32 offset = (position & 0x3f) * 2 + (position & 0xfc0) * 4;
if (layer != 2) {
dest = gMapDataBottomSpecial + offset;
} else {
dest = gMapDataTopSpecial + offset;
}
src = &data->metatiles[tileIndex * 4];
dest[0] = src[0];
dest[1] = src[1];
dest[0x80] = src[2];
dest[0x81] = src[3];
if (gRoomControls.reload_flags != 1) {
gUpdateVisibleTiles = 1;
}
}
}
void sub_0807BB68(const s16* param_1, u32 basePosition, u32 layer) {
while (param_1[0] != -1) {
SetTileType((u16)param_1[0], basePosition + param_1[1], layer);
param_1 += 2;
}
}
void sub_0807BB98(s32 basePosition, u32 layer, u32 width, u32 height) {
u32 y;
u32 x;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
SetTile(0x4072, basePosition + x, layer);
}
basePosition += 0x40;
}
}
ASM_FUNC("asm/non_matching/playerUtils/sub_0807BBE4.inc", void sub_0807BBE4())
void sub_0807BC84(void) {
s32 height;
u32 width;
u8* puVar3;
u8* puVar4;
u8* puVar5;
u8* puVar6;
u32 index;
width = (u32)(gRoomControls.width >> 4);
if (width == 0x40) {
width = 0x3f;
}
puVar4 = gMapBottom.collisionData + width;
puVar6 = gMapBottom.collisionData + 0x3f;
puVar3 = gMapTop.collisionData + width;
puVar5 = gMapTop.collisionData + 0x3f;
index = 0;
while (index < 0x40) {
*puVar4 = 0xff;
*puVar6 = 0xff;
*puVar3 = 0xff;
*puVar5 = 0xff;
puVar4 += 0x40;
puVar6 += 0x40;
puVar3 += 0x40;
puVar5 += 0x40;
index++;
}
height = (gRoomControls.height & 0xfff0) * 4;
puVar4 = gMapBottom.collisionData + height;
puVar6 = gMapBottom.collisionData + 0xfc0;
puVar3 = gMapTop.collisionData + height;
puVar5 = gMapTop.collisionData + 0xfc0;
index = 0;
while (index < 0x40) {
*puVar4 = 0xff;
puVar4++;
*puVar6 = 0xff;
puVar6++;
*puVar3 = 0xff;
puVar3++;
*puVar5 = 0xff;
puVar5++;
index++;
}
}
bool32 sub_0807BD14(Entity* this, u32 scrollDirection) {
u32 room = sub_0807BEEC(this->x.HALF.HI, this->y.HALF.HI, scrollDirection);
if (room != 0xff) {
gRoomControls.unk3 = 2;
gRoomControls.unk4 = 0;
gRoomControls.reload_flags = 1;
gRoomControls.room = room;
gRoomControls.scroll_direction = scrollDirection;
gArea.pCurrentRoomInfo = GetCurrentRoomInfo();
if (gArea.unk_0c_0 != 0) {
switch (scrollDirection) {
case 0:
gArea.pCurrentRoomInfo->map_y -= gArea.pCurrentRoomInfo->pixel_height;
break;
case 1:
gArea.pCurrentRoomInfo->map_x = gArea.pCurrentRoomInfo->map_x + gArea.pCurrentRoomInfo->pixel_width;
break;
case 2:
gArea.pCurrentRoomInfo->map_y =
gArea.pCurrentRoomInfo->map_y + gArea.pCurrentRoomInfo->pixel_height;
break;
case 3:
gArea.pCurrentRoomInfo->map_x = gArea.pCurrentRoomInfo->map_x - gArea.pCurrentRoomInfo->pixel_width;
break;
}
}
gPlayerEntity.updatePriority = 6;
SetInitializationPriority();
return TRUE;
} else {
return FALSE;
}
}
u32 sub_0807BDB8(Entity* this, u32 param_2) {
u32 result = 0xff;
switch (param_2 & 7) {
case 0:
if (this->y.HALF.HI - (u32)gRoomControls.origin_y < 10) {
result = 0;
}
break;
case 1:
if (this->y.HALF.HI - (u32)gRoomControls.origin_y < 10) {
result = 0;
}
if (gRoomControls.width - 10 < this->x.HALF.HI - (u32)gRoomControls.origin_x) {
result = 1;
}
break;
case 2:
if (gRoomControls.width - 10 < this->x.HALF.HI - (u32)gRoomControls.origin_x) {
result = 1;
}
break;
case 3:
if (gRoomControls.height - 10 < this->y.HALF.HI - (u32)gRoomControls.origin_y) {
result = 2;
}
if (gRoomControls.width - 10 < this->x.HALF.HI - (u32)gRoomControls.origin_x) {
result = 1;
}
break;
case 4:
if (gRoomControls.height - 10 < this->y.HALF.HI - (u32)gRoomControls.origin_y) {
result = 2;
}
break;
case 5:
if (gRoomControls.height - 10 < this->y.HALF.HI - (u32)gRoomControls.origin_y) {
result = 2;
}
if (this->x.HALF.HI - (u32)gRoomControls.origin_x < 10) {
result = 3;
}
break;
case 6:
if (this->x.HALF.HI - (u32)gRoomControls.origin_x < 10) {
result = 3;
}
break;
case 7:
if (this->y.HALF.HI - (u32)gRoomControls.origin_y < 10) {
result = 0;
}
if (this->x.HALF.HI - (u32)gRoomControls.origin_x < 10) {
result = 3;
}
}
return result;
}
u32 sub_0807BEEC(u32 param_1, u32 param_2, u32 param_3) {
u32 index;
RoomResInfo* ptr;
if ((gArea.filler3[-1] & 1) != 0) {
return gRoomControls.room;
}
switch (param_3) {
case 0:
param_2 = gRoomControls.origin_y - 0x10;
break;
case 1:
param_1 = gRoomControls.origin_x + gRoomControls.width + 0x10;
break;
case 2:
param_2 = gRoomControls.origin_y + gRoomControls.height + 0x10;
break;
case 3:
param_1 = gRoomControls.origin_x - 0x10;
break;
default:
return 0xff;
}
ptr = gArea.roomResInfos;
index = 0;
while (index < 0x40) {
if (sub_0807BF88(param_1, param_2, ptr)) {
return index;
}
index++;
ptr++;
}
return 0xff;
}
bool32 sub_0807BF88(u32 param_1, u32 param_2, RoomResInfo* info) {
u32 width = param_1 - info->map_x;
u32 height = param_2 - info->map_y;
bool32 result = FALSE;
if (width < info->pixel_width && height < info->pixel_height) {
result = TRUE;
}
return result;
}
void sub_0807BFA8(void) {
gRoomControls.origin_x = (gArea.pCurrentRoomInfo)->map_x;
gRoomControls.origin_y = (gArea.pCurrentRoomInfo)->map_y;
gRoomControls.width = (gArea.pCurrentRoomInfo)->pixel_width;
gRoomControls.height = (gArea.pCurrentRoomInfo)->pixel_height;
}
ASM_FUNC("asm/non_matching/playerUtils/sub_0807BFD0.inc", void sub_0807BFD0())
ASM_FUNC("asm/non_matching/playerUtils/LoadRoomGfx.inc", void LoadRoomGfx())
void sub_0807C460(void) {
u32 x;
u32 y;
u16* mapBottom = gMapBottom.mapData;
u16* mapTop = gMapTop.mapData;
u32 width = gRoomControls.width >> 4;
u32 height = gRoomControls.height >> 4;
u32 position = 0;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if (*mapBottom > 0x3fff) {
SetTile(*mapBottom, position, 1);
}
if (*mapTop > 0x3fff) {
SetTile(*mapTop, position, 2);
}
mapBottom++;
mapTop++;
position++;
}
mapBottom += 0x40 - width;
mapTop += 0x40 - width;
position += 0x40 - width;
}
}
ASM_FUNC("asm/non_matching/playerUtils/sub_0807C4F8.inc", void sub_0807C4F8())
ASM_FUNC("asm/non_matching/playerUtils/sub_0807C5B0.inc", void sub_0807C5B0())
ASM_FUNC("asm/non_matching/playerUtils/sub_0807C5F4.inc", void sub_0807C5F4())
ASM_FUNC("asm/non_matching/playerUtils/sub_0807C69C.inc", void sub_0807C69C())
ASM_FUNC("asm/non_matching/playerUtils/sub_0807C740.inc", void InitializeCamera())
void sub_0807C810(void) {
struct_03004030* ptr;
Entity* player;
RoomControls* ctrls;
sub_0807BFD0();
ptr = &gUnk_03004030;
player = &gPlayerEntity;
ctrls = &gRoomControls;
player->x.HALF.HI = ((ptr->unk_00)->unk_06 & 0x3f) * 0x10 + ctrls->origin_x + ptr->unk_04;
player->y.HALF.HI = (((ptr->unk_00)->unk_06 & 0xfc0) >> 2) + ctrls->origin_y + ptr->unk_06;
sub_080809D4();
gUpdateVisibleTiles = 0;
}
/**
* This function is used to create a copy of the map data for temporary cutscene changes.
*/
void CloneMapData(void) {
gRoomTransition.field_0x2c[0] = 1;
MemCopy(&gMapBottom.mapData, &gMapBottom.mapDataClone, 0x2000);
MemCopy(&gMapTop.mapData, &gMapTop.mapDataClone, 0x2000);
}
void sub_0807C898(void) {
gRoomTransition.field_0x2c[0] = 2;
LoadRoomGfx();
gRoomTransition.field_0x2c[0] = 0;
}
ASM_FUNC("asm/non_matching/playerUtils/sub_0807C8B0.inc", void sub_0807C8B0())
void LoadCompressedMapData(void* dest, u32 offset) {
void* src;
if (offset != -1) {
src = &gMapData + (offset & 0x7fffffff);
if ((u32)dest >> 0x18 == 6) {
LZ77UnCompVram(src, (void*)dest);
} else {
LZ77UnCompWram(src, (void*)dest);
}
}
}
void sub_0807C998(u32* a1) {
LoadCompressedMapData(&gMapBottom.metatiles, a1[0]);
LoadCompressedMapData(&gMapBottom.metatileTypes, a1[1]);
LoadCompressedMapData(&gMapTop.metatiles, a1[2]);
LoadCompressedMapData(&gMapTop.metatileTypes, a1[3]);
}
void sub_0807C9D8(u32* a1) {
u32* v1; // r5@1
v1 = a1;
LoadCompressedMapData((u8*)0x6004000, *a1);
LoadCompressedMapData((u8*)0x6000000, v1[1]);
LoadCompressedMapData((u8*)0x6008000, v1[2]);
LoadCompressedMapData((u8*)gUnk_020176E0, v1[3]);
LoadPalettes(gUnk_020176E0, 2, 13);
}
u32 FinalizeSave(void) {
if (gSave.invalid || gSave.initialized != 1) {
gSave.invalid = 0;
gSave.initialized = 1;
gSave.global_progress = 1;
gSave.stats.health = 24;
gSave.stats.maxHealth = 24;
gSave.saved_status.area_next = 0x22;
gSave.saved_status.room_next = 0x15; // links room
gSave.saved_status.start_anim = 0;
gSave.saved_status.spawn_type = PL_SPAWN_DEFAULT;
gSave.saved_status.layer = 1;
gSave.saved_status.start_pos_x = 0x90;
gSave.saved_status.start_pos_y = 0x38;
}
if (gSave.name[0] == 0) {
MemCopy(gUnk_0811E470, &gSave.name, FILENAME_LENGTH - 1);
}
#ifdef DEMO_USA
{
const u8* tmp;
MemCopy(demoPointers[gSaveHeader->saveFileId], &gSave, 0x4B4);
if (gSaveHeader->language == 0) {
gSave.name[0] = 0x97;
gSave.name[1] = 0x7F;
gSave.name[2] = 0xDD;
gSave.name[3] = 0;
}
ModHealth(0xA0);
ModRupees(-9999);
tmp = demoUnknown1 + gUnk_02000010.field_0x7 * 3;
gSave.demo_timer = tmp[gSaveHeader->saveFileId] * 3600;
}
#endif
return 1;
}
u32 GetInventoryValue(u32 item) {
u32 tmp = item / 4;
return gUnk_02002B32[tmp] >> ((item & 3) << 1) & 3;
}
ASM_FUNC("asm/non_matching/playerUtils/SetInventoryValue.inc", void SetInventoryValue(u32 a, u32 b))
NONMATCH("asm/non_matching/playerUtils/sub_0807CAC8.inc", void sub_0807CAC8(u32 param_1)) {
gSave.unk46C[gArea.dungeon_idx + 0x10] |= (1 << param_1);
}
END_NONMATCH
NONMATCH("asm/non_matching/playerUtils/sub_0807CAEC.inc", u32 sub_0807CAEC(u32 param_1)) {
return gSave.unk46C[gArea.dungeon_idx + 0x10] >> param_1 & 1;
}
END_NONMATCH
u32 CheckLocalFlagByBank(u32 bank, u32 flag) {
return ReadBit(gSave.flags, bank + flag);
}
NONMATCH("asm/non_matching/playerUtils/sub_0807CB24.inc", bool32 sub_0807CB24(s32 param_1, u32 param_2)) {
bool32 result = TRUE;
switch (param_1) {
case 0:
default:
result = FALSE;
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 0xb:
case 0xc:
case 0xd:
result = CheckLocalFlagByBank(gLocalFlagBanks[param_1], param_2);
break;
case 0xf:
if (GetInventoryValue(param_2) == 0) {
result = FALSE;
} else {
result = TRUE;
}
break;
case 0x10:
if (GetInventoryValue(param_2) == 1) {
result = TRUE;
} else {
result = FALSE;
}
break;
case 0x11:
if (GetInventoryValue(param_2) == 2) {
result = TRUE;
} else {
result = FALSE;
}
break;
}
return result;
}
END_NONMATCH