Shipwright/soh/src/overlays/actors/ovl_player_actor/z_player.c

16053 lines
591 KiB
C

/*
* File: z_player.c
* Overlay: ovl_player_actor
* Description: Link
*/
#include <libultraship/libultra.h>
#include "global.h"
#include "overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.h"
#include "overlays/actors/ovl_Door_Shutter/z_door_shutter.h"
#include "overlays/actors/ovl_En_Boom/z_en_boom.h"
#include "overlays/actors/ovl_En_Arrow/z_en_arrow.h"
#include "overlays/actors/ovl_En_Box/z_en_box.h"
#include "overlays/actors/ovl_En_Door/z_en_door.h"
#include "overlays/actors/ovl_En_Elf/z_en_elf.h"
#include "overlays/actors/ovl_En_Fish/z_en_fish.h"
#include "overlays/actors/ovl_En_Horse/z_en_horse.h"
#include "overlays/effects/ovl_Effect_Ss_Fhg_Flash/z_eff_ss_fhg_flash.h"
#include "overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_link_child/object_link_child.h"
#include "textures/icon_item_24_static/icon_item_24_static.h"
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
#include <overlays/actors/ovl_En_Partner/z_en_partner.h>
#include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/Enhancements/randomizer/randomizer_grotto.h"
#include "soh/frame_interpolation.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
// Some player animations are played at this reduced speed, for reasons yet unclear.
// This is called "adjusted" for now.
#define PLAYER_ANIM_ADJUSTED_SPEED (2.0f / 3.0f)
typedef enum {
/* 0x00 */ KNOB_ANIM_ADULT_L,
/* 0x01 */ KNOB_ANIM_CHILD_L,
/* 0x02 */ KNOB_ANIM_ADULT_R,
/* 0x03 */ KNOB_ANIM_CHILD_R
} KnobDoorAnim;
typedef struct {
/* 0x00 */ u8 itemId;
/* 0x02 */ s16 actorId;
} ExplosiveInfo; // size = 0x04
typedef struct {
/* 0x00 */ s16 actorId;
/* 0x02 */ u8 itemId;
/* 0x03 */ u8 itemAction;
/* 0x04 */ u8 textId;
} BottleCatchInfo; // size = 0x06
typedef struct {
/* 0x00 */ s16 actorId;
/* 0x02 */ s16 actorParams;
} BottleDropInfo; // size = 0x04
typedef struct {
/* 0x00 */ s8 damage;
/* 0x01 */ u8 rumbleStrength;
/* 0x02 */ u8 rumbleDuration;
/* 0x03 */ u8 rumbleDecreaseRate;
/* 0x04 */ u16 sfxId;
} FallImpactInfo; // size = 0x06
typedef struct {
/* 0x00 */ Vec3f pos;
/* 0x0C */ s16 yaw;
} SpecialRespawnInfo; // size = 0x10
typedef enum {
/* 1 */ ANIMSFX_TYPE_1 = 1,
/* 2 */ ANIMSFX_TYPE_2,
/* 3 */ ANIMSFX_TYPE_3,
/* 4 */ ANIMSFX_TYPE_4,
/* 5 */ ANIMSFX_TYPE_5,
/* 6 */ ANIMSFX_TYPE_6,
/* 7 */ ANIMSFX_TYPE_7,
/* 8 */ ANIMSFX_TYPE_8,
/* 9 */ ANIMSFX_TYPE_9
} AnimSfxType;
#define ANIMSFX_SHIFT_TYPE(type) ((type) << 11)
#define ANIMSFX_DATA(type, frame) ((ANIMSFX_SHIFT_TYPE(type) | ((frame)&0x7FF)))
#define ANIMSFX_GET_TYPE(data) ((data)&0x7800)
#define ANIMSFX_GET_FRAME(data) ((data)&0x7FF)
typedef struct {
/* 0x00 */ u16 sfxId;
/* 0x02 */ s16 data;
} AnimSfxEntry; // size = 0x04
typedef struct {
/* 0x00 */ u16 unk_00;
/* 0x02 */ s16 unk_02;
} struct_808551A4; // size = 0x04
typedef struct {
/* 0x00 */ LinkAnimationHeader* anim;
/* 0x04 */ u8 changeFrame;
} ItemChangeInfo; // size = 0x08
typedef struct {
/* 0x00 */ LinkAnimationHeader* unk_00;
/* 0x04 */ LinkAnimationHeader* unk_04;
/* 0x08 */ u8 unk_08;
/* 0x09 */ u8 unk_09;
} struct_80854554; // size = 0x0C
typedef struct {
/* 0x00 */ LinkAnimationHeader* unk_00;
/* 0x04 */ LinkAnimationHeader* unk_04;
/* 0x08 */ LinkAnimationHeader* unk_08;
/* 0x0C */ u8 unk_0C;
/* 0x0D */ u8 unk_0D;
} struct_80854190; // size = 0x10
typedef struct {
/* 0x00 */ LinkAnimationHeader* anim;
/* 0x04 */ f32 unk_04;
/* 0x04 */ f32 unk_08;
} struct_80854578; // size = 0x0C
typedef struct {
/* 0x00 */ s8 type;
/* 0x04 */ union {
void* ptr;
void (*func)(PlayState*, Player*, CsCmdActorAction*);
};
} struct_80854B18; // size = 0x08
void Player_InitItemAction(PlayState* play, Player* this, s8 itemAction);
void Player_InitDefaultIA(PlayState* play, Player* this);
void Player_InitHammerIA(PlayState* play, Player* this);
void Player_InitBowOrSlingshotIA(PlayState* play, Player* this);
void Player_InitDekuStickIA(PlayState* play, Player* this);
void Player_InitExplosiveIA(PlayState* play, Player* this);
void Player_InitHookshotIA(PlayState* play, Player* this);
void Player_InitBoomerangIA(PlayState* play, Player* this);
s32 Player_UpperAction_ChangeHeldItem(Player* this, PlayState* play);
s32 func_8083485C(Player* this, PlayState* play);
s32 Player_UpperAction_Sword(Player* this, PlayState* play);
s32 func_80834B5C(Player* this, PlayState* play);
s32 func_80834C74(Player* this, PlayState* play);
s32 func_8083501C(Player* this, PlayState* play);
s32 func_808351D4(Player* this, PlayState* play); // Arrow nocked
s32 func_808353D8(Player* this, PlayState* play); // Aiming in first person
s32 func_80835588(Player* this, PlayState* play);
s32 Player_UpperAction_CarryActor(Player* this, PlayState* play);
s32 func_80835800(Player* this, PlayState* play);
s32 func_80835884(Player* this, PlayState* play); // Start aiming boomerang
s32 func_808358F0(Player* this, PlayState* play); // Aim boomerang
s32 func_808359FC(Player* this, PlayState* play); // Throw boomerang
s32 spawn_boomerang_ivan(EnPartner* this, PlayState* play); // Throw boomerang Ivan
s32 func_80835B60(Player* this, PlayState* play); // Boomerang active
s32 func_80835C08(Player* this, PlayState* play);
void Player_UseItem(PlayState* play, Player* this, s32 item);
void func_80839F90(Player* this, PlayState* play);
s32 func_8083C61C(PlayState* play, Player* this);
void func_8083CA20(PlayState* play, Player* this);
void func_8083CA54(PlayState* play, Player* this);
void func_8083CA9C(PlayState* play, Player* this);
void Player_SetPendingFlag(Player* this, PlayState* play);
void func_80846648(PlayState* play, Player* this);
void func_80846660(PlayState* play, Player* this);
void func_808467D4(PlayState* play, Player* this);
void func_808468A8(PlayState* play, Player* this);
void func_808468E8(PlayState* play, Player* this);
void func_80846978(PlayState* play, Player* this);
void func_808469BC(PlayState* play, Player* this);
void func_80846A68(PlayState* play, Player* this);
void Player_UpdateCommon(Player* this, PlayState* play, Input* input);
s32 func_8084FCAC(Player* this, PlayState* play);
void func_8084FF7C(Player* this);
void Player_UpdateBunnyEars(Player* this);
void func_80851008(PlayState* play, Player* this, void* anim);
void func_80851030(PlayState* play, Player* this, void* anim);
void func_80851050(PlayState* play, Player* this, void* anim);
void func_80851094(PlayState* play, Player* this, void* anim);
void func_808510B4(PlayState* play, Player* this, void* anim);
void func_808510D4(PlayState* play, Player* this, void* anim);
void func_808510F4(PlayState* play, Player* this, void* anim);
void func_80851114(PlayState* play, Player* this, void* anim);
void func_80851134(PlayState* play, Player* this, void* anim);
void func_80851154(PlayState* play, Player* this, void* anim);
void func_80851174(PlayState* play, Player* this, void* anim);
void func_80851194(PlayState* play, Player* this, void* anim);
void func_808511B4(PlayState* play, Player* this, void* anim);
void func_808511D4(PlayState* play, Player* this, void* anim);
void func_808511FC(PlayState* play, Player* this, void* anim);
void func_80851248(PlayState* play, Player* this, void* anim);
void func_80851294(PlayState* play, Player* this, void* anim);
void func_808512E0(PlayState* play, Player* this, void* arg2);
void func_80851368(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808513BC(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808514C0(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_8085157C(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808515A4(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851688(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851750(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851788(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851828(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808518DC(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_8085190C(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851998(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808519C0(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808519EC(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851A50(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851B90(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851BE8(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851CA4(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851D2C(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851D80(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851DEC(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851E28(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851E64(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851E90(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851ECC(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851F84(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80851FB0(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852048(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852080(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852174(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808521B8(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808521F4(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852234(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_8085225C(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852280(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852358(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852388(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852298(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852328(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852480(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852450(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808524B0(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808524D0(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852514(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852544(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852554(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852564(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808525C0(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852608(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852648(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808526EC(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_8085283C(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808528C8(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852944(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_808529D0(PlayState* play, Player* this, CsCmdActorAction* arg2);
void func_80852C50(PlayState* play, Player* this, CsCmdActorAction* arg2);
int Player_IsDroppingFish(PlayState* play);
s32 Player_StartFishing(PlayState* play);
s32 func_80852F38(PlayState* play, Player* this);
s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction);
void func_80853080(Player* this, PlayState* play);
s32 Player_InflictDamage(PlayState* play, s32 damage);
s32 Player_InflictDamageModified(PlayState* play, s32 damage, u8 modified);
void Player_StartTalking(PlayState* play, Actor* actor);
void Player_Action_80840450(Player* this, PlayState* play);
void Player_Action_808407CC(Player* this, PlayState* play);
void Player_Action_80840BC8(Player* this, PlayState* play);
void Player_Action_80840DE4(Player* this, PlayState* play);
void Player_Action_808414F8(Player* this, PlayState* play);
void Player_Action_8084170C(Player* this, PlayState* play);
void Player_Action_808417FC(Player* this, PlayState* play);
void Player_Action_8084193C(Player* this, PlayState* play);
void Player_Action_80841BA8(Player* this, PlayState* play);
void Player_Action_80842180(Player* this, PlayState* play);
void Player_Action_8084227C(Player* this, PlayState* play);
void Player_Action_8084279C(Player* this, PlayState* play);
void Player_Action_808423EC(Player* this, PlayState* play);
void Player_Action_8084251C(Player* this, PlayState* play);
void Player_Action_80843188(Player* this, PlayState* play);
void Player_Action_808435C4(Player* this, PlayState* play);
void Player_Action_8084370C(Player* this, PlayState* play);
void Player_Action_8084377C(Player* this, PlayState* play);
void Player_Action_80843954(Player* this, PlayState* play);
void Player_Action_80843A38(Player* this, PlayState* play);
void Player_Action_80843CEC(Player* this, PlayState* play);
void Player_Action_8084411C(Player* this, PlayState* play);
void Player_Action_80844708(Player* this, PlayState* play);
void Player_Action_80844A44(Player* this, PlayState* play);
void Player_Action_80844AF4(Player* this, PlayState* play);
void Player_Action_80844E68(Player* this, PlayState* play);
void Player_Action_80845000(Player* this, PlayState* play);
void Player_Action_80845308(Player* this, PlayState* play);
void Player_Action_80845668(Player* this, PlayState* play);
void Player_Action_808458D0(Player* this, PlayState* play);
void Player_Action_80845CA4(Player* this, PlayState* play);
void Player_Action_80845EF8(Player* this, PlayState* play);
void Player_Action_80846050(Player* this, PlayState* play);
void Player_Action_80846120(Player* this, PlayState* play);
void Player_Action_80846260(Player* this, PlayState* play);
void Player_Action_80846358(Player* this, PlayState* play);
void Player_Action_80846408(Player* this, PlayState* play);
void Player_Action_808464B0(Player* this, PlayState* play);
void Player_Action_80846578(Player* this, PlayState* play);
void Player_Action_8084B1D8(Player* this, PlayState* play);
void Player_Action_8084B530(Player* this, PlayState* play);
void Player_Action_8084B78C(Player* this, PlayState* play);
void Player_Action_8084B898(Player* this, PlayState* play);
void Player_Action_8084B9E4(Player* this, PlayState* play);
void Player_Action_8084BBE4(Player* this, PlayState* play);
void Player_Action_8084BDFC(Player* this, PlayState* play);
void Player_Action_8084BF1C(Player* this, PlayState* play);
void Player_Action_8084C5F8(Player* this, PlayState* play);
void Player_Action_8084C760(Player* this, PlayState* play);
void Player_Action_8084C81C(Player* this, PlayState* play);
void Player_Action_8084CC98(Player* this, PlayState* play);
void Player_Action_8084D3E4(Player* this, PlayState* play);
void Player_Action_8084D610(Player* this, PlayState* play);
void Player_Action_8084D7C4(Player* this, PlayState* play);
void Player_Action_8084D84C(Player* this, PlayState* play);
void Player_Action_8084DAB4(Player* this, PlayState* play);
void Player_Action_8084DC48(Player* this, PlayState* play);
void Player_Action_8084E1EC(Player* this, PlayState* play);
void Player_Action_8084E30C(Player* this, PlayState* play);
void Player_Action_8084E368(Player* this, PlayState* play);
void Player_Action_8084E3C4(Player* this, PlayState* play);
void Player_Action_8084E604(Player* this, PlayState* play);
void Player_Action_8084E6D4(Player* this, PlayState* play);
void Player_Action_8084E9AC(Player* this, PlayState* play);
void Player_Action_8084EAC0(Player* this, PlayState* play);
void Player_Action_8084ECA4(Player* this, PlayState* play);
void Player_Action_8084EED8(Player* this, PlayState* play);
void Player_Action_8084EFC0(Player* this, PlayState* play);
void Player_Action_8084F104(Player* this, PlayState* play);
void Player_Action_8084F390(Player* this, PlayState* play);
void Player_Action_8084F608(Player* this, PlayState* play);
void Player_Action_8084F698(Player* this, PlayState* play);
void Player_Action_8084F710(Player* this, PlayState* play);
void Player_Action_8084F88C(Player* this, PlayState* play);
void Player_Action_8084F9A0(Player* this, PlayState* play);
void Player_Action_8084F9C0(Player* this, PlayState* play);
void Player_Action_8084FA54(Player* this, PlayState* play);
void Player_Action_8084FB10(Player* this, PlayState* play);
void Player_Action_8084FBF4(Player* this, PlayState* play);
void Player_Action_808502D0(Player* this, PlayState* play);
void Player_Action_808505DC(Player* this, PlayState* play);
void Player_Action_8085063C(Player* this, PlayState* play);
void Player_Action_8085076C(Player* this, PlayState* play);
void Player_Action_808507F4(Player* this, PlayState* play);
void Player_Action_80850AEC(Player* this, PlayState* play);
void Player_Action_80850C68(Player* this, PlayState* play);
void Player_Action_80850E84(Player* this, PlayState* play);
void Player_Action_CsAction(Player* this, PlayState* play);
// .bss part 1
static s32 D_80858AA0;
static s32 D_80858AA4;
static Vec3f sInteractWallCheckResult;
static Input* sControlInput;
// .data
static u8 sUpperBodyLimbCopyMap[PLAYER_LIMB_MAX] = {
false, // PLAYER_LIMB_NONE
false, // PLAYER_LIMB_ROOT
false, // PLAYER_LIMB_WAIST
false, // PLAYER_LIMB_LOWER
false, // PLAYER_LIMB_R_THIGH
false, // PLAYER_LIMB_R_SHIN
false, // PLAYER_LIMB_R_FOOT
false, // PLAYER_LIMB_L_THIGH
false, // PLAYER_LIMB_L_SHIN
false, // PLAYER_LIMB_L_FOOT
true, // PLAYER_LIMB_UPPER
true, // PLAYER_LIMB_HEAD
true, // PLAYER_LIMB_HAT
true, // PLAYER_LIMB_COLLAR
true, // PLAYER_LIMB_L_SHOULDER
true, // PLAYER_LIMB_L_FOREARM
true, // PLAYER_LIMB_L_HAND
true, // PLAYER_LIMB_R_SHOULDER
true, // PLAYER_LIMB_R_FOREARM
true, // PLAYER_LIMB_R_HAND
true, // PLAYER_LIMB_SHEATH
true // PLAYER_LIMB_TORSO
};
static PlayerAgeProperties sAgeProperties[] = {
{
56.0f, // ceilingCheckHeight
90.0f, // unk_04
1.0f, // unk_08
111.0f, // unk_0C
70.0f, // unk_10
79.4f, // unk_14
59.0f, // unk_18
41.0f, // unk_1C
19.0f, // unk_20
36.0f, // unk_24
44.8f, // unk_28
56.0f, // unk_2C
68.0f, // unk_30
70.0f, // unk_34
18.0f, // wallCheckRadius
15.0f, // unk_3C
70.0f, // unk_40
{ 9, 4671, 359 }, // unk_44
{
{ 8, 4694, 380 },
{ 9, 6122, 359 },
{ 8, 4694, 380 },
{ 9, 6122, 359 },
}, // unk_4A
{
{ 9, 6122, 359 },
{ 9, 7693, 380 },
{ 9, 6122, 359 },
{ 9, 7693, 380 },
}, // unk_62
{
{ 8, 4694, 380 },
{ 9, 6122, 359 },
}, // unk_7A
{
{ -1592, 4694, 380 },
{ -1591, 6122, 359 },
}, // unk_86
0, // unk_92
0x80, // unk_94
&gPlayerAnim_link_demo_Tbox_open, // unk_98
&gPlayerAnim_link_demo_back_to_past, // unk_9C
&gPlayerAnim_link_demo_return_to_past, // unk_A0
&gPlayerAnim_link_normal_climb_startA, // unk_A4
&gPlayerAnim_link_normal_climb_startB, // unk_A8
{ &gPlayerAnim_link_normal_climb_upL, &gPlayerAnim_link_normal_climb_upR, &gPlayerAnim_link_normal_Fclimb_upL,
&gPlayerAnim_link_normal_Fclimb_upR }, // unk_AC
{ &gPlayerAnim_link_normal_Fclimb_sideL, &gPlayerAnim_link_normal_Fclimb_sideR }, // unk_BC
{ &gPlayerAnim_link_normal_climb_endAL, &gPlayerAnim_link_normal_climb_endAR }, // unk_C4
{ &gPlayerAnim_link_normal_climb_endBR, &gPlayerAnim_link_normal_climb_endBL }, // unk_CC
},
{
40.0f, // ceilingCheckHeight
60.0f, // unk_04
11.0f / 17.0f, // unk_08
71.0f, // unk_0C
50.0f, // unk_10
47.0f, // unk_14
39.0f, // unk_18
27.0f, // unk_1C
19.0f, // unk_20
22.0f, // unk_24
29.6f, // unk_28
32.0f, // unk_2C
48.0f, // unk_30
70.0f * (11.0f / 17.0f), // unk_34
14.0f, // wallCheckRadius
12.0f, // unk_3C
55.0f, // unk_40
{ -24, 3565, 876 }, // unk_44
{
{ -24, 3474, 862 },
{ -24, 4977, 937 },
{ 8, 4694, 380 },
{ 9, 6122, 359 },
}, // unk_4A
{
{ -24, 4977, 937 },
{ -24, 6495, 937 },
{ 9, 6122, 359 },
{ 9, 7693, 380 },
}, // unk_62
{
{ 8, 4694, 380 },
{ 9, 6122, 359 },
}, // unk_7A
{
{ -1592, 4694, 380 },
{ -1591, 6122, 359 },
}, // unk_86
0x20, // unk_92
0, // unk_94
&gPlayerAnim_clink_demo_Tbox_open, // unk_98
&gPlayerAnim_clink_demo_goto_future, // unk_9C
&gPlayerAnim_clink_demo_return_to_future, // unk_A0
&gPlayerAnim_clink_normal_climb_startA, // unk_A4
&gPlayerAnim_clink_normal_climb_startB, // unk_A8
{ &gPlayerAnim_clink_normal_climb_upL, &gPlayerAnim_clink_normal_climb_upR, &gPlayerAnim_link_normal_Fclimb_upL,
&gPlayerAnim_link_normal_Fclimb_upR }, // unk_AC
{ &gPlayerAnim_link_normal_Fclimb_sideL, &gPlayerAnim_link_normal_Fclimb_sideR }, // unk_BC
{ &gPlayerAnim_clink_normal_climb_endAL, &gPlayerAnim_clink_normal_climb_endAR }, // unk_C4
{ &gPlayerAnim_clink_normal_climb_endBR, &gPlayerAnim_clink_normal_climb_endBL }, // unk_CC
},
};
static u32 D_808535D0 = false;
static f32 sControlStickMagnitude = 0.0f;
static s16 sControlStickAngle = 0;
static s16 D_808535DC = 0;
static s32 D_808535E0 = 0;
static s32 sFloorType = 0;
static f32 D_808535E8 = 1.0f;
static f32 D_808535EC = 1.0f;
static u32 sTouchedWallFlags = 0;
static u32 sConveyorSpeed = 0;
static s16 sIsFloorConveyor = false;
static s16 sConveyorYaw = 0;
static f32 sYDistToFloor = 0.0f;
static s32 sPrevFloorProperty = 0;
static s32 sShapeYawToTouchedWall = 0;
static s32 sWorldYawToTouchedWall = 0;
static s16 sFloorShapePitch = 0;
static s32 sUseHeldItem = false; // When true, the current held item is used. Is reset to false every frame.
static s32 sHeldItemButtonIsHeldDown = false; // Indicates if the button for the current held item is held down.
static u16 D_8085361C[] = {
NA_SE_VO_LI_SWEAT,
NA_SE_VO_LI_SNEEZE,
NA_SE_VO_LI_RELAX,
NA_SE_VO_LI_FALL_L,
};
#define GET_PLAYER_ANIM(group, type) D_80853914[group][type]
static LinkAnimationHeader* D_80853914[PLAYER_ANIMGROUP_MAX][PLAYER_ANIMTYPE_MAX] = {
/* PLAYER_ANIMGROUP_wait */
{
&gPlayerAnim_link_normal_wait_free,
&gPlayerAnim_link_normal_wait,
&gPlayerAnim_link_normal_wait,
&gPlayerAnim_link_fighter_wait_long,
&gPlayerAnim_link_normal_wait_free,
&gPlayerAnim_link_normal_wait_free,
},
/* PLAYER_ANIMGROUP_walk */
{
&gPlayerAnim_link_normal_walk_free,
&gPlayerAnim_link_normal_walk,
&gPlayerAnim_link_normal_walk,
&gPlayerAnim_link_fighter_walk_long,
&gPlayerAnim_link_normal_walk_free,
&gPlayerAnim_link_normal_walk_free,
},
/* PLAYER_ANIMGROUP_run */
{
&gPlayerAnim_link_normal_run_free,
&gPlayerAnim_link_fighter_run,
&gPlayerAnim_link_normal_run,
&gPlayerAnim_link_fighter_run_long,
&gPlayerAnim_link_normal_run_free,
&gPlayerAnim_link_normal_run_free,
},
/* PLAYER_ANIMGROUP_damage_run */
{
&gPlayerAnim_link_normal_damage_run_free,
&gPlayerAnim_link_fighter_damage_run,
&gPlayerAnim_link_normal_damage_run_free,
&gPlayerAnim_link_fighter_damage_run_long,
&gPlayerAnim_link_normal_damage_run_free,
&gPlayerAnim_link_normal_damage_run_free,
},
/* PLAYER_ANIMGROUP_heavy_run */
{
&gPlayerAnim_link_normal_heavy_run_free,
&gPlayerAnim_link_normal_heavy_run,
&gPlayerAnim_link_normal_heavy_run_free,
&gPlayerAnim_link_fighter_heavy_run_long,
&gPlayerAnim_link_normal_heavy_run_free,
&gPlayerAnim_link_normal_heavy_run_free,
},
/* PLAYER_ANIMGROUP_waitL */
{
&gPlayerAnim_link_normal_waitL_free,
&gPlayerAnim_link_anchor_waitL,
&gPlayerAnim_link_anchor_waitL,
&gPlayerAnim_link_fighter_waitL_long,
&gPlayerAnim_link_normal_waitL_free,
&gPlayerAnim_link_normal_waitL_free,
},
/* PLAYER_ANIMGROUP_waitR */
{
&gPlayerAnim_link_normal_waitR_free,
&gPlayerAnim_link_anchor_waitR,
&gPlayerAnim_link_anchor_waitR,
&gPlayerAnim_link_fighter_waitR_long,
&gPlayerAnim_link_normal_waitR_free,
&gPlayerAnim_link_normal_waitR_free,
},
/* PLAYER_ANIMGROUP_wait2waitR */
{
&gPlayerAnim_link_fighter_wait2waitR_long,
&gPlayerAnim_link_normal_wait2waitR,
&gPlayerAnim_link_normal_wait2waitR,
&gPlayerAnim_link_fighter_wait2waitR_long,
&gPlayerAnim_link_fighter_wait2waitR_long,
&gPlayerAnim_link_fighter_wait2waitR_long,
},
/* PLAYER_ANIMGROUP_normal2fighter */
{
&gPlayerAnim_link_normal_normal2fighter_free,
&gPlayerAnim_link_fighter_normal2fighter,
&gPlayerAnim_link_fighter_normal2fighter,
&gPlayerAnim_link_normal_normal2fighter_free,
&gPlayerAnim_link_normal_normal2fighter_free,
&gPlayerAnim_link_normal_normal2fighter_free,
},
/* PLAYER_ANIMGROUP_doorA_free */
{
&gPlayerAnim_link_demo_doorA_link_free,
&gPlayerAnim_link_demo_doorA_link,
&gPlayerAnim_link_demo_doorA_link,
&gPlayerAnim_link_demo_doorA_link_free,
&gPlayerAnim_link_demo_doorA_link_free,
&gPlayerAnim_link_demo_doorA_link_free,
},
/* PLAYER_ANIMGROUP_doorA */
{
&gPlayerAnim_clink_demo_doorA_link,
&gPlayerAnim_clink_demo_doorA_link,
&gPlayerAnim_clink_demo_doorA_link,
&gPlayerAnim_clink_demo_doorA_link,
&gPlayerAnim_clink_demo_doorA_link,
&gPlayerAnim_clink_demo_doorA_link,
},
/* PLAYER_ANIMGROUP_doorB_free */
{
&gPlayerAnim_link_demo_doorB_link_free,
&gPlayerAnim_link_demo_doorB_link,
&gPlayerAnim_link_demo_doorB_link,
&gPlayerAnim_link_demo_doorB_link_free,
&gPlayerAnim_link_demo_doorB_link_free,
&gPlayerAnim_link_demo_doorB_link_free,
},
/* PLAYER_ANIMGROUP_doorB */
{
&gPlayerAnim_clink_demo_doorB_link,
&gPlayerAnim_clink_demo_doorB_link,
&gPlayerAnim_clink_demo_doorB_link,
&gPlayerAnim_clink_demo_doorB_link,
&gPlayerAnim_clink_demo_doorB_link,
&gPlayerAnim_clink_demo_doorB_link,
},
/* PLAYER_ANIMGROUP_carryB */
{
&gPlayerAnim_link_normal_carryB_free,
&gPlayerAnim_link_normal_carryB,
&gPlayerAnim_link_normal_carryB,
&gPlayerAnim_link_normal_carryB_free,
&gPlayerAnim_link_normal_carryB_free,
&gPlayerAnim_link_normal_carryB_free,
},
/* PLAYER_ANIMGROUP_landing */
{
&gPlayerAnim_link_normal_landing_free,
&gPlayerAnim_link_normal_landing,
&gPlayerAnim_link_normal_landing,
&gPlayerAnim_link_normal_landing_free,
&gPlayerAnim_link_normal_landing_free,
&gPlayerAnim_link_normal_landing_free,
},
/* PLAYER_ANIMGROUP_short_landing */
{
&gPlayerAnim_link_normal_short_landing_free,
&gPlayerAnim_link_normal_short_landing,
&gPlayerAnim_link_normal_short_landing,
&gPlayerAnim_link_normal_short_landing_free,
&gPlayerAnim_link_normal_short_landing_free,
&gPlayerAnim_link_normal_short_landing_free,
},
/* PLAYER_ANIMGROUP_landing_roll */
{
&gPlayerAnim_link_normal_landing_roll_free,
&gPlayerAnim_link_normal_landing_roll,
&gPlayerAnim_link_normal_landing_roll,
&gPlayerAnim_link_fighter_landing_roll_long,
&gPlayerAnim_link_normal_landing_roll_free,
&gPlayerAnim_link_normal_landing_roll_free,
},
/* PLAYER_ANIMGROUP_hip_down */
{
&gPlayerAnim_link_normal_hip_down_free,
&gPlayerAnim_link_normal_hip_down,
&gPlayerAnim_link_normal_hip_down,
&gPlayerAnim_link_normal_hip_down_long,
&gPlayerAnim_link_normal_hip_down_free,
&gPlayerAnim_link_normal_hip_down_free,
},
/* PLAYER_ANIMGROUP_walk_endL */
{
&gPlayerAnim_link_normal_walk_endL_free,
&gPlayerAnim_link_normal_walk_endL,
&gPlayerAnim_link_normal_walk_endL,
&gPlayerAnim_link_fighter_walk_endL_long,
&gPlayerAnim_link_normal_walk_endL_free,
&gPlayerAnim_link_normal_walk_endL_free,
},
/* PLAYER_ANIMGROUP_walk_endR */
{
&gPlayerAnim_link_normal_walk_endR_free,
&gPlayerAnim_link_normal_walk_endR,
&gPlayerAnim_link_normal_walk_endR,
&gPlayerAnim_link_fighter_walk_endR_long,
&gPlayerAnim_link_normal_walk_endR_free,
&gPlayerAnim_link_normal_walk_endR_free,
},
/* PLAYER_ANIMGROUP_defense */
{
&gPlayerAnim_link_normal_defense_free,
&gPlayerAnim_link_normal_defense,
&gPlayerAnim_link_normal_defense,
&gPlayerAnim_link_normal_defense_free,
&gPlayerAnim_link_bow_defense,
&gPlayerAnim_link_normal_defense_free,
},
/* PLAYER_ANIMGROUP_defense_wait */
{
&gPlayerAnim_link_normal_defense_wait_free,
&gPlayerAnim_link_normal_defense_wait,
&gPlayerAnim_link_normal_defense_wait,
&gPlayerAnim_link_normal_defense_wait_free,
&gPlayerAnim_link_bow_defense_wait,
&gPlayerAnim_link_normal_defense_wait_free,
},
/* PLAYER_ANIMGROUP_defense_end */
{
&gPlayerAnim_link_normal_defense_end_free,
&gPlayerAnim_link_normal_defense_end,
&gPlayerAnim_link_normal_defense_end,
&gPlayerAnim_link_normal_defense_end_free,
&gPlayerAnim_link_normal_defense_end_free,
&gPlayerAnim_link_normal_defense_end_free,
},
/* PLAYER_ANIMGROUP_side_walk */
{
&gPlayerAnim_link_normal_side_walk_free,
&gPlayerAnim_link_normal_side_walk,
&gPlayerAnim_link_normal_side_walk,
&gPlayerAnim_link_fighter_side_walk_long,
&gPlayerAnim_link_normal_side_walk_free,
&gPlayerAnim_link_normal_side_walk_free,
},
/* PLAYER_ANIMGROUP_side_walkL */
{
&gPlayerAnim_link_normal_side_walkL_free,
&gPlayerAnim_link_anchor_side_walkL,
&gPlayerAnim_link_anchor_side_walkL,
&gPlayerAnim_link_fighter_side_walkL_long,
&gPlayerAnim_link_normal_side_walkL_free,
&gPlayerAnim_link_normal_side_walkL_free,
},
/* PLAYER_ANIMGROUP_side_walkR */
{
&gPlayerAnim_link_normal_side_walkR_free,
&gPlayerAnim_link_anchor_side_walkR,
&gPlayerAnim_link_anchor_side_walkR,
&gPlayerAnim_link_fighter_side_walkR_long,
&gPlayerAnim_link_normal_side_walkR_free,
&gPlayerAnim_link_normal_side_walkR_free,
},
/* PLAYER_ANIMGROUP_45_turn */
{
&gPlayerAnim_link_normal_45_turn_free,
&gPlayerAnim_link_normal_45_turn,
&gPlayerAnim_link_normal_45_turn,
&gPlayerAnim_link_normal_45_turn_free,
&gPlayerAnim_link_normal_45_turn_free,
&gPlayerAnim_link_normal_45_turn_free,
},
/* PLAYER_ANIMGROUP_waitL2wait */
{
&gPlayerAnim_link_fighter_waitL2wait_long,
&gPlayerAnim_link_normal_waitL2wait,
&gPlayerAnim_link_normal_waitL2wait,
&gPlayerAnim_link_fighter_waitL2wait_long,
&gPlayerAnim_link_fighter_waitL2wait_long,
&gPlayerAnim_link_fighter_waitL2wait_long,
},
/* PLAYER_ANIMGROUP_waitR2wait */
{
&gPlayerAnim_link_fighter_waitR2wait_long,
&gPlayerAnim_link_normal_waitR2wait,
&gPlayerAnim_link_normal_waitR2wait,
&gPlayerAnim_link_fighter_waitR2wait_long,
&gPlayerAnim_link_fighter_waitR2wait_long,
&gPlayerAnim_link_fighter_waitR2wait_long,
},
/* PLAYER_ANIMGROUP_throw */
{
&gPlayerAnim_link_normal_throw_free,
&gPlayerAnim_link_normal_throw,
&gPlayerAnim_link_normal_throw,
&gPlayerAnim_link_normal_throw_free,
&gPlayerAnim_link_normal_throw_free,
&gPlayerAnim_link_normal_throw_free,
},
/* PLAYER_ANIMGROUP_put */
{
&gPlayerAnim_link_normal_put_free,
&gPlayerAnim_link_normal_put,
&gPlayerAnim_link_normal_put,
&gPlayerAnim_link_normal_put_free,
&gPlayerAnim_link_normal_put_free,
&gPlayerAnim_link_normal_put_free,
},
/* PLAYER_ANIMGROUP_back_walk */
{
&gPlayerAnim_link_normal_back_walk,
&gPlayerAnim_link_normal_back_walk,
&gPlayerAnim_link_normal_back_walk,
&gPlayerAnim_link_normal_back_walk,
&gPlayerAnim_link_normal_back_walk,
&gPlayerAnim_link_normal_back_walk,
},
/* PLAYER_ANIMGROUP_check */
{
&gPlayerAnim_link_normal_check_free,
&gPlayerAnim_link_normal_check,
&gPlayerAnim_link_normal_check,
&gPlayerAnim_link_normal_check_free,
&gPlayerAnim_link_normal_check_free,
&gPlayerAnim_link_normal_check_free,
},
/* PLAYER_ANIMGROUP_check_wait */
{
&gPlayerAnim_link_normal_check_wait_free,
&gPlayerAnim_link_normal_check_wait,
&gPlayerAnim_link_normal_check_wait,
&gPlayerAnim_link_normal_check_wait_free,
&gPlayerAnim_link_normal_check_wait_free,
&gPlayerAnim_link_normal_check_wait_free,
},
/* PLAYER_ANIMGROUP_check_end */
{
&gPlayerAnim_link_normal_check_end_free,
&gPlayerAnim_link_normal_check_end,
&gPlayerAnim_link_normal_check_end,
&gPlayerAnim_link_normal_check_end_free,
&gPlayerAnim_link_normal_check_end_free,
&gPlayerAnim_link_normal_check_end_free,
},
/* PLAYER_ANIMGROUP_pull_start */
{
&gPlayerAnim_link_normal_pull_start_free,
&gPlayerAnim_link_normal_pull_start,
&gPlayerAnim_link_normal_pull_start,
&gPlayerAnim_link_normal_pull_start_free,
&gPlayerAnim_link_normal_pull_start_free,
&gPlayerAnim_link_normal_pull_start_free,
},
/* PLAYER_ANIMGROUP_pulling */
{
&gPlayerAnim_link_normal_pulling_free,
&gPlayerAnim_link_normal_pulling,
&gPlayerAnim_link_normal_pulling,
&gPlayerAnim_link_normal_pulling_free,
&gPlayerAnim_link_normal_pulling_free,
&gPlayerAnim_link_normal_pulling_free,
},
/* PLAYER_ANIMGROUP_pull_end */
{
&gPlayerAnim_link_normal_pull_end_free,
&gPlayerAnim_link_normal_pull_end,
&gPlayerAnim_link_normal_pull_end,
&gPlayerAnim_link_normal_pull_end_free,
&gPlayerAnim_link_normal_pull_end_free,
&gPlayerAnim_link_normal_pull_end_free,
},
/* PLAYER_ANIMGROUP_fall_up */
{
&gPlayerAnim_link_normal_fall_up_free,
&gPlayerAnim_link_normal_fall_up,
&gPlayerAnim_link_normal_fall_up,
&gPlayerAnim_link_normal_fall_up_free,
&gPlayerAnim_link_normal_fall_up_free,
&gPlayerAnim_link_normal_fall_up_free,
},
/* PLAYER_ANIMGROUP_jump_climb_hold */
{
&gPlayerAnim_link_normal_jump_climb_hold_free,
&gPlayerAnim_link_normal_jump_climb_hold,
&gPlayerAnim_link_normal_jump_climb_hold,
&gPlayerAnim_link_normal_jump_climb_hold_free,
&gPlayerAnim_link_normal_jump_climb_hold_free,
&gPlayerAnim_link_normal_jump_climb_hold_free,
},
/* PLAYER_ANIMGROUP_jump_climb_wait */
{
&gPlayerAnim_link_normal_jump_climb_wait_free,
&gPlayerAnim_link_normal_jump_climb_wait,
&gPlayerAnim_link_normal_jump_climb_wait,
&gPlayerAnim_link_normal_jump_climb_wait_free,
&gPlayerAnim_link_normal_jump_climb_wait_free,
&gPlayerAnim_link_normal_jump_climb_wait_free,
},
/* PLAYER_ANIMGROUP_jump_climb_up */
{
&gPlayerAnim_link_normal_jump_climb_up_free,
&gPlayerAnim_link_normal_jump_climb_up,
&gPlayerAnim_link_normal_jump_climb_up,
&gPlayerAnim_link_normal_jump_climb_up_free,
&gPlayerAnim_link_normal_jump_climb_up_free,
&gPlayerAnim_link_normal_jump_climb_up_free,
},
/* PLAYER_ANIMGROUP_down_slope_slip_end */
{
&gPlayerAnim_link_normal_down_slope_slip_end_free,
&gPlayerAnim_link_normal_down_slope_slip_end,
&gPlayerAnim_link_normal_down_slope_slip_end,
&gPlayerAnim_link_normal_down_slope_slip_end_long,
&gPlayerAnim_link_normal_down_slope_slip_end_free,
&gPlayerAnim_link_normal_down_slope_slip_end_free,
},
/* PLAYER_ANIMGROUP_up_slope_slip_end */
{
&gPlayerAnim_link_normal_up_slope_slip_end_free,
&gPlayerAnim_link_normal_up_slope_slip_end,
&gPlayerAnim_link_normal_up_slope_slip_end,
&gPlayerAnim_link_normal_up_slope_slip_end_long,
&gPlayerAnim_link_normal_up_slope_slip_end_free,
&gPlayerAnim_link_normal_up_slope_slip_end_free,
},
/* PLAYER_ANIMGROUP_nwait */
{
&gPlayerAnim_sude_nwait,
&gPlayerAnim_lkt_nwait,
&gPlayerAnim_lkt_nwait,
&gPlayerAnim_sude_nwait,
&gPlayerAnim_sude_nwait,
&gPlayerAnim_sude_nwait,
}
};
static LinkAnimationHeader* D_80853D4C[][3] = {
{ &gPlayerAnim_link_fighter_front_jump, &gPlayerAnim_link_fighter_front_jump_end,
&gPlayerAnim_link_fighter_front_jump_endR },
{ &gPlayerAnim_link_fighter_Lside_jump, &gPlayerAnim_link_fighter_Lside_jump_end,
&gPlayerAnim_link_fighter_Lside_jump_endL },
{ &gPlayerAnim_link_fighter_backturn_jump, &gPlayerAnim_link_fighter_backturn_jump_end,
&gPlayerAnim_link_fighter_backturn_jump_endR },
{ &gPlayerAnim_link_fighter_Rside_jump, &gPlayerAnim_link_fighter_Rside_jump_end,
&gPlayerAnim_link_fighter_Rside_jump_endR },
};
static LinkAnimationHeader* D_80853D7C[][2] = {
{ &gPlayerAnim_link_normal_wait_typeA_20f, &gPlayerAnim_link_normal_waitF_typeA_20f },
{ &gPlayerAnim_link_normal_wait_typeC_20f, &gPlayerAnim_link_normal_waitF_typeC_20f },
{ &gPlayerAnim_link_normal_wait_typeB_20f, &gPlayerAnim_link_normal_waitF_typeB_20f },
{ &gPlayerAnim_link_normal_wait_typeB_20f, &gPlayerAnim_link_normal_waitF_typeB_20f },
{ &gPlayerAnim_link_wait_typeD_20f, &gPlayerAnim_link_waitF_typeD_20f },
{ &gPlayerAnim_link_wait_typeD_20f, &gPlayerAnim_link_waitF_typeD_20f },
{ &gPlayerAnim_link_wait_typeD_20f, &gPlayerAnim_link_waitF_typeD_20f },
{ &gPlayerAnim_link_wait_heat1_20f, &gPlayerAnim_link_waitF_heat1_20f },
{ &gPlayerAnim_link_wait_heat2_20f, &gPlayerAnim_link_waitF_heat2_20f },
{ &gPlayerAnim_link_wait_itemD1_20f, &gPlayerAnim_link_wait_itemD1_20f },
{ &gPlayerAnim_link_wait_itemA_20f, &gPlayerAnim_link_waitF_itemA_20f },
{ &gPlayerAnim_link_wait_itemB_20f, &gPlayerAnim_link_waitF_itemB_20f },
{ &gPlayerAnim_link_wait_itemC_20f, &gPlayerAnim_link_wait_itemC_20f },
{ &gPlayerAnim_link_wait_itemD2_20f, &gPlayerAnim_link_wait_itemD2_20f }
};
static AnimSfxEntry D_80853DEC[] = {
{ NA_SE_VO_LI_SNEEZE, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 8) },
};
static AnimSfxEntry D_80853DF0[] = {
{ NA_SE_VO_LI_SWEAT, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 18) },
};
static AnimSfxEntry D_80853DF4[] = {
{ NA_SE_VO_LI_BREATH_REST, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 13) },
};
static AnimSfxEntry D_80853DF8[] = {
{ NA_SE_VO_LI_BREATH_REST, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 10) },
};
static AnimSfxEntry D_80853DFC[] = {
{ NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 44) }, { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 48) },
{ NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 52) }, { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 56) },
{ NA_SE_PL_CALM_HIT, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 60) },
};
static AnimSfxEntry D_80853E10[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 25) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 30) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 44) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 48) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 52) }, { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_8, 56) },
};
static AnimSfxEntry D_80853E28[] = {
{ NA_SE_IT_SHIELD_POSTURE, ANIMSFX_DATA(ANIMSFX_TYPE_1, 16) },
{ NA_SE_IT_SHIELD_POSTURE, ANIMSFX_DATA(ANIMSFX_TYPE_1, 20) },
{ NA_SE_IT_SHIELD_POSTURE, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 70) },
};
static AnimSfxEntry D_80853E34[] = {
{ NA_SE_IT_HAMMER_SWING, ANIMSFX_DATA(ANIMSFX_TYPE_1, 10) },
{ NA_SE_VO_LI_AUTO_JUMP, ANIMSFX_DATA(ANIMSFX_TYPE_4, 10) },
{ NA_SE_IT_SWORD_SWING, ANIMSFX_DATA(ANIMSFX_TYPE_1, 22) },
{ NA_SE_VO_LI_SWORD_N, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 22) },
};
static AnimSfxEntry D_80853E44[] = {
{ NA_SE_IT_SWORD_SWING, ANIMSFX_DATA(ANIMSFX_TYPE_1, 39) },
{ NA_SE_VO_LI_SWORD_N, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 39) },
};
static AnimSfxEntry D_80853E4C[] = {
{ NA_SE_VO_LI_RELAX, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 20) },
};
static AnimSfxEntry* D_80853E50[] = {
D_80853DEC, D_80853DF0, D_80853DF4, D_80853DF8, D_80853DFC, D_80853E10,
D_80853E28, D_80853E34, D_80853E44, D_80853E4C, NULL,
};
static u8 D_80853E7C[] = {
0, 0, 1, 1, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 3, 3, 4, 4, 8, 8, 5, 5, 6, 6, 7, 7, 9, 9, 0,
};
// Used to map item IDs to item actions
static s8 sItemActions[] = {
PLAYER_IA_DEKU_STICK, // ITEM_DEKU_STICK
PLAYER_IA_DEKU_NUT, // ITEM_DEKU_NUT
PLAYER_IA_BOMB, // ITEM_BOMB
PLAYER_IA_BOW, // ITEM_BOW
PLAYER_IA_BOW_FIRE, // ITEM_ARROW_FIRE
PLAYER_IA_DINS_FIRE, // ITEM_DINS_FIRE
PLAYER_IA_SLINGSHOT, // ITEM_SLINGSHOT
PLAYER_IA_OCARINA_FAIRY, // ITEM_OCARINA_FAIRY
PLAYER_IA_OCARINA_OF_TIME, // ITEM_OCARINA_OF_TIME
PLAYER_IA_BOMBCHU, // ITEM_BOMBCHU
PLAYER_IA_HOOKSHOT, // ITEM_HOOKSHOT
PLAYER_IA_LONGSHOT, // ITEM_LONGSHOT
PLAYER_IA_BOW_ICE, // ITEM_ARROW_ICE
PLAYER_IA_FARORES_WIND, // ITEM_FARORES_WIND
PLAYER_IA_BOOMERANG, // ITEM_BOOMERANG
PLAYER_IA_LENS_OF_TRUTH, // ITEM_LENS_OF_TRUTH
PLAYER_IA_MAGIC_BEAN, // ITEM_MAGIC_BEAN
PLAYER_IA_HAMMER, // ITEM_HAMMER
PLAYER_IA_BOW_LIGHT, // ITEM_ARROW_LIGHT
PLAYER_IA_NAYRUS_LOVE, // ITEM_NAYRUS_LOVE
PLAYER_IA_BOTTLE, // ITEM_BOTTLE_EMPTY
PLAYER_IA_BOTTLE_POTION_RED, // ITEM_BOTTLE_POTION_RED
PLAYER_IA_BOTTLE_POTION_GREEN, // ITEM_BOTTLE_POTION_GREEN
PLAYER_IA_BOTTLE_POTION_BLUE, // ITEM_BOTTLE_POTION_BLUE
PLAYER_IA_BOTTLE_FAIRY, // ITEM_BOTTLE_FAIRY
PLAYER_IA_BOTTLE_FISH, // ITEM_BOTTLE_FISH
PLAYER_IA_BOTTLE_MILK_FULL, // ITEM_BOTTLE_MILK_FULL
PLAYER_IA_BOTTLE_RUTOS_LETTER, // ITEM_BOTTLE_RUTOS_LETTER
PLAYER_IA_BOTTLE_FIRE, // ITEM_BOTTLE_BLUE_FIRE
PLAYER_IA_BOTTLE_BUG, // ITEM_BOTTLE_BUG
PLAYER_IA_BOTTLE_BIG_POE, // ITEM_BOTTLE_BIG_POE
PLAYER_IA_BOTTLE_MILK_HALF, // ITEM_BOTTLE_MILK_HALF
PLAYER_IA_BOTTLE_POE, // ITEM_BOTTLE_POE
PLAYER_IA_WEIRD_EGG, // ITEM_WEIRD_EGG
PLAYER_IA_CHICKEN, // ITEM_CHICKEN
PLAYER_IA_ZELDAS_LETTER, // ITEM_ZELDAS_LETTER
PLAYER_IA_MASK_KEATON, // ITEM_MASK_KEATON
PLAYER_IA_MASK_SKULL, // ITEM_MASK_SKULL
PLAYER_IA_MASK_SPOOKY, // ITEM_MASK_SPOOKY
PLAYER_IA_MASK_BUNNY_HOOD, // ITEM_MASK_BUNNY_HOOD
PLAYER_IA_MASK_GORON, // ITEM_MASK_GORON
PLAYER_IA_MASK_ZORA, // ITEM_MASK_ZORA
PLAYER_IA_MASK_GERUDO, // ITEM_MASK_GERUDO
PLAYER_IA_MASK_TRUTH, // ITEM_MASK_TRUTH
PLAYER_IA_SWORD_MASTER, // ITEM_SOLD_OUT
PLAYER_IA_POCKET_EGG, // ITEM_POCKET_EGG
PLAYER_IA_POCKET_CUCCO, // ITEM_POCKET_CUCCO
PLAYER_IA_COJIRO, // ITEM_COJIRO
PLAYER_IA_ODD_MUSHROOM, // ITEM_ODD_MUSHROOM
PLAYER_IA_ODD_POTION, // ITEM_ODD_POTION
PLAYER_IA_POACHERS_SAW, // ITEM_POACHERS_SAW
PLAYER_IA_BROKEN_GORONS_SWORD, // ITEM_BROKEN_GORONS_SWORD
PLAYER_IA_PRESCRIPTION, // ITEM_PRESCRIPTION
PLAYER_IA_FROG, // ITEM_EYEBALL_FROG
PLAYER_IA_EYEDROPS, // ITEM_EYE_DROPS
PLAYER_IA_CLAIM_CHECK, // ITEM_CLAIM_CHECK
PLAYER_IA_BOW_FIRE, // ITEM_BOW_FIRE
PLAYER_IA_BOW_ICE, // ITEM_BOW_ICE
PLAYER_IA_BOW_LIGHT, // ITEM_BOW_LIGHT
PLAYER_IA_SWORD_KOKIRI, // ITEM_SWORD_KOKIRI
PLAYER_IA_SWORD_MASTER, // ITEM_SWORD_MASTER
PLAYER_IA_SWORD_BIGGORON, // ITEM_SWORD_BIGGORON
};
static u8 sMaskMemory;
u8 gWalkSpeedToggle1;
u8 gWalkSpeedToggle2;
static s32 (*sItemActionUpdateFuncs[])(Player* this, PlayState* play) = {
func_8083485C, // PLAYER_IA_NONE
func_8083485C, // PLAYER_IA_SWORD_CS
func_8083485C, // PLAYER_IA_FISHING_POLE
Player_UpperAction_Sword, // PLAYER_IA_SWORD_MASTER
Player_UpperAction_Sword, // PLAYER_IA_SWORD_KOKIRI
Player_UpperAction_Sword, // PLAYER_IA_SWORD_BIGGORON
func_8083485C, // PLAYER_IA_DEKU_STICK
func_8083485C, // PLAYER_IA_HAMMER
func_8083501C, // PLAYER_IA_BOW
func_8083501C, // PLAYER_IA_BOW_FIRE
func_8083501C, // PLAYER_IA_BOW_ICE
func_8083501C, // PLAYER_IA_BOW_LIGHT
func_8083501C, // PLAYER_IA_BOW_0C
func_8083501C, // PLAYER_IA_BOW_0D
func_8083501C, // PLAYER_IA_BOW_0E
func_8083501C, // PLAYER_IA_SLINGSHOT
func_8083501C, // PLAYER_IA_HOOKSHOT
func_8083501C, // PLAYER_IA_LONGSHOT
Player_UpperAction_CarryActor, // PLAYER_IA_BOMB
Player_UpperAction_CarryActor, // PLAYER_IA_BOMBCHU
func_80835800, // PLAYER_IA_BOOMERANG
func_8083485C, // PLAYER_IA_MAGIC_SPELL_15
func_8083485C, // PLAYER_IA_MAGIC_SPELL_16
func_8083485C, // PLAYER_IA_MAGIC_SPELL_17
func_8083485C, // PLAYER_IA_FARORES_WIND
func_8083485C, // PLAYER_IA_NAYRUS_LOVE
func_8083485C, // PLAYER_IA_DINS_FIRE
func_8083485C, // PLAYER_IA_DEKU_NUT
func_8083485C, // PLAYER_IA_OCARINA_FAIRY
func_8083485C, // PLAYER_IA_OCARINA_OF_TIME
func_8083485C, // PLAYER_IA_BOTTLE
func_8083485C, // PLAYER_IA_BOTTLE_FISH
func_8083485C, // PLAYER_IA_BOTTLE_FIRE
func_8083485C, // PLAYER_IA_BOTTLE_BUG
func_8083485C, // PLAYER_IA_BOTTLE_POE
func_8083485C, // PLAYER_IA_BOTTLE_BIG_POE
func_8083485C, // PLAYER_IA_BOTTLE_RUTOS_LETTER
func_8083485C, // PLAYER_IA_BOTTLE_POTION_RED
func_8083485C, // PLAYER_IA_BOTTLE_POTION_BLUE
func_8083485C, // PLAYER_IA_BOTTLE_POTION_GREEN
func_8083485C, // PLAYER_IA_BOTTLE_MILK_FULL
func_8083485C, // PLAYER_IA_BOTTLE_MILK_HALF
func_8083485C, // PLAYER_IA_BOTTLE_FAIRY
func_8083485C, // PLAYER_IA_ZELDAS_LETTER
func_8083485C, // PLAYER_IA_WEIRD_EGG
func_8083485C, // PLAYER_IA_CHICKEN
func_8083485C, // PLAYER_IA_MAGIC_BEAN
func_8083485C, // PLAYER_IA_POCKET_EGG
func_8083485C, // PLAYER_IA_POCKET_CUCCO
func_8083485C, // PLAYER_IA_COJIRO
func_8083485C, // PLAYER_IA_ODD_MUSHROOM
func_8083485C, // PLAYER_IA_ODD_POTION
func_8083485C, // PLAYER_IA_POACHERS_SAW
func_8083485C, // PLAYER_IA_BROKEN_GORONS_SWORD
func_8083485C, // PLAYER_IA_PRESCRIPTION
func_8083485C, // PLAYER_IA_FROG
func_8083485C, // PLAYER_IA_EYEDROPS
func_8083485C, // PLAYER_IA_CLAIM_CHECK
func_8083485C, // PLAYER_IA_MASK_KEATON
func_8083485C, // PLAYER_IA_MASK_SKULL
func_8083485C, // PLAYER_IA_MASK_SPOOKY
func_8083485C, // PLAYER_IA_MASK_BUNNY_HOOD
func_8083485C, // PLAYER_IA_MASK_GORON
func_8083485C, // PLAYER_IA_MASK_ZORA
func_8083485C, // PLAYER_IA_MASK_GERUDO
func_8083485C, // PLAYER_IA_MASK_TRUTH
func_8083485C, // PLAYER_IA_LENS_OF_TRUTH
};
static void (*sItemActionInitFuncs[])(PlayState* play, Player* this) = {
Player_InitDefaultIA, // PLAYER_IA_NONE
Player_InitDefaultIA, // PLAYER_IA_SWORD_CS
Player_InitDefaultIA, // PLAYER_IA_FISHING_POLE
Player_InitDefaultIA, // PLAYER_IA_SWORD_MASTER
Player_InitDefaultIA, // PLAYER_IA_SWORD_KOKIRI
Player_InitDefaultIA, // PLAYER_IA_SWORD_BIGGORON
Player_InitDekuStickIA, // PLAYER_IA_DEKU_STICK
Player_InitHammerIA, // PLAYER_IA_HAMMER
Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW
Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_FIRE
Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_ICE
Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_LIGHT
Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_0C
Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_0D
Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_0E
Player_InitBowOrSlingshotIA, // PLAYER_IA_SLINGSHOT
Player_InitHookshotIA, // PLAYER_IA_HOOKSHOT
Player_InitHookshotIA, // PLAYER_IA_LONGSHOT
Player_InitExplosiveIA, // PLAYER_IA_BOMB
Player_InitExplosiveIA, // PLAYER_IA_BOMBCHU
Player_InitBoomerangIA, // PLAYER_IA_BOOMERANG
Player_InitDefaultIA, // PLAYER_IA_MAGIC_SPELL_15
Player_InitDefaultIA, // PLAYER_IA_MAGIC_SPELL_16
Player_InitDefaultIA, // PLAYER_IA_MAGIC_SPELL_17
Player_InitDefaultIA, // PLAYER_IA_FARORES_WIND
Player_InitDefaultIA, // PLAYER_IA_NAYRUS_LOVE
Player_InitDefaultIA, // PLAYER_IA_DINS_FIRE
Player_InitDefaultIA, // PLAYER_IA_DEKU_NUT
Player_InitDefaultIA, // PLAYER_IA_OCARINA_FAIRY
Player_InitDefaultIA, // PLAYER_IA_OCARINA_OF_TIME
Player_InitDefaultIA, // PLAYER_IA_BOTTLE
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_FISH
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_FIRE
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_BUG
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_POE
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_BIG_POE
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_RUTOS_LETTER
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_POTION_RED
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_POTION_BLUE
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_POTION_GREEN
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_MILK_FULL
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_MILK_HALF
Player_InitDefaultIA, // PLAYER_IA_BOTTLE_FAIRY
Player_InitDefaultIA, // PLAYER_IA_ZELDAS_LETTER
Player_InitDefaultIA, // PLAYER_IA_WEIRD_EGG
Player_InitDefaultIA, // PLAYER_IA_CHICKEN
Player_InitDefaultIA, // PLAYER_IA_MAGIC_BEAN
Player_InitDefaultIA, // PLAYER_IA_POCKET_EGG
Player_InitDefaultIA, // PLAYER_IA_POCKET_CUCCO
Player_InitDefaultIA, // PLAYER_IA_COJIRO
Player_InitDefaultIA, // PLAYER_IA_ODD_MUSHROOM
Player_InitDefaultIA, // PLAYER_IA_ODD_POTION
Player_InitDefaultIA, // PLAYER_IA_POACHERS_SAW
Player_InitDefaultIA, // PLAYER_IA_BROKEN_GORONS_SWORD
Player_InitDefaultIA, // PLAYER_IA_PRESCRIPTION
Player_InitDefaultIA, // PLAYER_IA_FROG
Player_InitDefaultIA, // PLAYER_IA_EYEDROPS
Player_InitDefaultIA, // PLAYER_IA_CLAIM_CHECK
Player_InitDefaultIA, // PLAYER_IA_MASK_KEATON
Player_InitDefaultIA, // PLAYER_IA_MASK_SKULL
Player_InitDefaultIA, // PLAYER_IA_MASK_SPOOKY
Player_InitDefaultIA, // PLAYER_IA_MASK_BUNNY_HOOD
Player_InitDefaultIA, // PLAYER_IA_MASK_GORON
Player_InitDefaultIA, // PLAYER_IA_MASK_ZORA
Player_InitDefaultIA, // PLAYER_IA_MASK_GERUDO
Player_InitDefaultIA, // PLAYER_IA_MASK_TRUTH
Player_InitDefaultIA, // PLAYER_IA_LENS_OF_TRUTH
};
typedef enum {
/* 0 */ PLAYER_ITEM_CHG_0,
/* 1 */ PLAYER_ITEM_CHG_1,
/* 2 */ PLAYER_ITEM_CHG_2,
/* 3 */ PLAYER_ITEM_CHG_3,
/* 4 */ PLAYER_ITEM_CHG_4,
/* 5 */ PLAYER_ITEM_CHG_5,
/* 6 */ PLAYER_ITEM_CHG_6,
/* 7 */ PLAYER_ITEM_CHG_7,
/* 8 */ PLAYER_ITEM_CHG_8,
/* 9 */ PLAYER_ITEM_CHG_9,
/* 10 */ PLAYER_ITEM_CHG_10,
/* 11 */ PLAYER_ITEM_CHG_11,
/* 12 */ PLAYER_ITEM_CHG_12,
/* 13 */ PLAYER_ITEM_CHG_13,
/* 14 */ PLAYER_ITEM_CHG_MAX
} ItemChangeType;
static ItemChangeInfo sItemChangeInfo[PLAYER_ITEM_CHG_MAX] = {
/* PLAYER_ITEM_CHG_0 */ { &gPlayerAnim_link_normal_free2free, 12 },
/* PLAYER_ITEM_CHG_1 */ { &gPlayerAnim_link_normal_normal2fighter, 6 },
/* PLAYER_ITEM_CHG_2 */ { &gPlayerAnim_link_hammer_normal2long, 8 },
/* PLAYER_ITEM_CHG_3 */ { &gPlayerAnim_link_normal_normal2free, 8 },
/* PLAYER_ITEM_CHG_4 */ { &gPlayerAnim_link_fighter_fighter2long, 8 },
/* PLAYER_ITEM_CHG_5 */ { &gPlayerAnim_link_normal_fighter2free, 10 },
/* PLAYER_ITEM_CHG_6 */ { &gPlayerAnim_link_hammer_long2free, 7 },
/* PLAYER_ITEM_CHG_7 */ { &gPlayerAnim_link_hammer_long2long, 11 },
/* PLAYER_ITEM_CHG_8 */ { &gPlayerAnim_link_normal_free2free, 12 },
/* PLAYER_ITEM_CHG_9 */ { &gPlayerAnim_link_normal_normal2bom, 4 },
/* PLAYER_ITEM_CHG_10 */ { &gPlayerAnim_link_normal_long2bom, 4 },
/* PLAYER_ITEM_CHG_11 */ { &gPlayerAnim_link_normal_free2bom, 4 },
/* PLAYER_ITEM_CHG_12 */ { &gPlayerAnim_link_anchor_anchor2fighter, 5 },
/* PLAYER_ITEM_CHG_13 */ { &gPlayerAnim_link_normal_free2freeB, 13 },
};
// Maps the appropriate ItemChangeType based on current and next animtype.
// A negative type value means the corresponding animation should be played in reverse.
static s8 sItemChangeTypes[PLAYER_ANIMTYPE_MAX][PLAYER_ANIMTYPE_MAX] = {
{ PLAYER_ITEM_CHG_8, -PLAYER_ITEM_CHG_5, -PLAYER_ITEM_CHG_3, -PLAYER_ITEM_CHG_6, PLAYER_ITEM_CHG_8,
PLAYER_ITEM_CHG_11 },
{ PLAYER_ITEM_CHG_5, PLAYER_ITEM_CHG_0, -PLAYER_ITEM_CHG_1, PLAYER_ITEM_CHG_4, PLAYER_ITEM_CHG_5,
PLAYER_ITEM_CHG_9 },
{ PLAYER_ITEM_CHG_3, PLAYER_ITEM_CHG_1, PLAYER_ITEM_CHG_0, PLAYER_ITEM_CHG_2, PLAYER_ITEM_CHG_3,
PLAYER_ITEM_CHG_9 },
{ PLAYER_ITEM_CHG_6, -PLAYER_ITEM_CHG_4, -PLAYER_ITEM_CHG_2, PLAYER_ITEM_CHG_7, PLAYER_ITEM_CHG_6,
PLAYER_ITEM_CHG_10 },
{ PLAYER_ITEM_CHG_8, -PLAYER_ITEM_CHG_5, -PLAYER_ITEM_CHG_3, -PLAYER_ITEM_CHG_6, PLAYER_ITEM_CHG_8,
PLAYER_ITEM_CHG_11 },
{ PLAYER_ITEM_CHG_8, -PLAYER_ITEM_CHG_5, -PLAYER_ITEM_CHG_3, -PLAYER_ITEM_CHG_6, PLAYER_ITEM_CHG_8,
PLAYER_ITEM_CHG_11 },
};
static ExplosiveInfo sExplosiveInfos[] = {
{ ITEM_BOMB, ACTOR_EN_BOM },
{ ITEM_BOMBCHU, ACTOR_EN_BOM_CHU },
};
static struct_80854190 D_80854190[PLAYER_MWA_MAX] = {
/* PLAYER_MWA_FORWARD_SLASH_1H */
{ &gPlayerAnim_link_fighter_normal_kiru, &gPlayerAnim_link_fighter_normal_kiru_end,
&gPlayerAnim_link_fighter_normal_kiru_endR, 1, 4 },
/* PLAYER_MWA_FORWARD_SLASH_2H */
{ &gPlayerAnim_link_fighter_Lnormal_kiru, &gPlayerAnim_link_fighter_Lnormal_kiru_end,
&gPlayerAnim_link_anchor_Lnormal_kiru_endR, 1, 4 },
/* PLAYER_MWA_FORWARD_COMBO_1H */
{ &gPlayerAnim_link_fighter_normal_kiru_finsh, &gPlayerAnim_link_fighter_normal_kiru_finsh_end,
&gPlayerAnim_link_anchor_normal_kiru_finsh_endR, 0, 5 },
/* PLAYER_MWA_FORWARD_COMBO_2H */
{ &gPlayerAnim_link_fighter_Lnormal_kiru_finsh, &gPlayerAnim_link_fighter_Lnormal_kiru_finsh_end,
&gPlayerAnim_link_anchor_Lnormal_kiru_finsh_endR, 1, 7 },
/* PLAYER_MWA_RIGHT_SLASH_1H */
{ &gPlayerAnim_link_fighter_Lside_kiru, &gPlayerAnim_link_fighter_Lside_kiru_end,
&gPlayerAnim_link_anchor_Lside_kiru_endR, 1, 4 },
/* PLAYER_MWA_RIGHT_SLASH_2H */
{ &gPlayerAnim_link_fighter_LLside_kiru, &gPlayerAnim_link_fighter_LLside_kiru_end,
&gPlayerAnim_link_anchor_LLside_kiru_endL, 0, 5 },
/* PLAYER_MWA_RIGHT_COMBO_1H */
{ &gPlayerAnim_link_fighter_Lside_kiru_finsh, &gPlayerAnim_link_fighter_Lside_kiru_finsh_end,
&gPlayerAnim_link_anchor_Lside_kiru_finsh_endR, 2, 8 },
/* PLAYER_MWA_RIGHT_COMBO_2H */
{ &gPlayerAnim_link_fighter_LLside_kiru_finsh, &gPlayerAnim_link_fighter_LLside_kiru_finsh_end,
&gPlayerAnim_link_anchor_LLside_kiru_finsh_endR, 3, 8 },
/* PLAYER_MWA_LEFT_SLASH_1H */
{ &gPlayerAnim_link_fighter_Rside_kiru, &gPlayerAnim_link_fighter_Rside_kiru_end,
&gPlayerAnim_link_anchor_Rside_kiru_endR, 0, 4 },
/* PLAYER_MWA_LEFT_SLASH_2H */
{ &gPlayerAnim_link_fighter_LRside_kiru, &gPlayerAnim_link_fighter_LRside_kiru_end,
&gPlayerAnim_link_anchor_LRside_kiru_endR, 0, 5 },
/* PLAYER_MWA_LEFT_COMBO_1H */
{ &gPlayerAnim_link_fighter_Rside_kiru_finsh, &gPlayerAnim_link_fighter_Rside_kiru_finsh_end,
&gPlayerAnim_link_anchor_Rside_kiru_finsh_endR, 0, 6 },
/* PLAYER_MWA_LEFT_COMBO_2H */
{ &gPlayerAnim_link_fighter_LRside_kiru_finsh, &gPlayerAnim_link_fighter_LRside_kiru_finsh_end,
&gPlayerAnim_link_anchor_LRside_kiru_finsh_endL, 1, 5 },
/* PLAYER_MWA_STAB_1H */
{ &gPlayerAnim_link_fighter_pierce_kiru, &gPlayerAnim_link_fighter_pierce_kiru_end,
&gPlayerAnim_link_anchor_pierce_kiru_endR, 0, 3 },
/* PLAYER_MWA_STAB_2H */
{ &gPlayerAnim_link_fighter_Lpierce_kiru, &gPlayerAnim_link_fighter_Lpierce_kiru_end,
&gPlayerAnim_link_anchor_Lpierce_kiru_endL, 0, 3 },
/* PLAYER_MWA_STAB_COMBO_1H */
{ &gPlayerAnim_link_fighter_pierce_kiru_finsh, &gPlayerAnim_link_fighter_pierce_kiru_finsh_end,
&gPlayerAnim_link_anchor_pierce_kiru_finsh_endR, 1, 9 },
/* PLAYER_MWA_STAB_COMBO_2H */
{ &gPlayerAnim_link_fighter_Lpierce_kiru_finsh, &gPlayerAnim_link_fighter_Lpierce_kiru_finsh_end,
&gPlayerAnim_link_anchor_Lpierce_kiru_finsh_endR, 1, 8 },
/* PLAYER_MWA_FLIPSLASH_START */
{ &gPlayerAnim_link_fighter_jump_rollkiru, &gPlayerAnim_link_fighter_jump_kiru_finsh,
&gPlayerAnim_link_fighter_jump_kiru_finsh, 1, 10 },
/* PLAYER_MWA_JUMPSLASH_START */
{ &gPlayerAnim_link_fighter_Lpower_jump_kiru, &gPlayerAnim_link_fighter_Lpower_jump_kiru_hit,
&gPlayerAnim_link_fighter_Lpower_jump_kiru_hit, 1, 11 },
/* PLAYER_MWA_FLIPSLASH_FINISH */
{ &gPlayerAnim_link_fighter_jump_kiru_finsh, &gPlayerAnim_link_fighter_jump_kiru_finsh_end,
&gPlayerAnim_link_fighter_jump_kiru_finsh_end, 1, 2 },
/* PLAYER_MWA_JUMPSLASH_FINISH */
{ &gPlayerAnim_link_fighter_Lpower_jump_kiru_hit, &gPlayerAnim_link_fighter_Lpower_jump_kiru_end,
&gPlayerAnim_link_fighter_Lpower_jump_kiru_end, 1, 2 },
/* PLAYER_MWA_BACKSLASH_RIGHT */
{ &gPlayerAnim_link_fighter_turn_kiruR, &gPlayerAnim_link_fighter_turn_kiruR_end,
&gPlayerAnim_link_fighter_turn_kiruR_end, 1, 5 },
/* PLAYER_MWA_BACKSLASH_LEFT */
{ &gPlayerAnim_link_fighter_turn_kiruL, &gPlayerAnim_link_fighter_turn_kiruL_end,
&gPlayerAnim_link_fighter_turn_kiruL_end, 1, 4 },
/* PLAYER_MWA_HAMMER_FORWARD */
{ &gPlayerAnim_link_hammer_hit, &gPlayerAnim_link_hammer_hit_end, &gPlayerAnim_link_hammer_hit_endR, 3, 10 },
/* PLAYER_MWA_HAMMER_SIDE */
{ &gPlayerAnim_link_hammer_side_hit, &gPlayerAnim_link_hammer_side_hit_end, &gPlayerAnim_link_hammer_side_hit_endR,
2, 11 },
/* PLAYER_MWA_SPIN_ATTACK_1H */
{ &gPlayerAnim_link_fighter_rolling_kiru, &gPlayerAnim_link_fighter_rolling_kiru_end,
&gPlayerAnim_link_anchor_rolling_kiru_endR, 0, 12 },
/* PLAYER_MWA_SPIN_ATTACK_2H */
{ &gPlayerAnim_link_fighter_Lrolling_kiru, &gPlayerAnim_link_fighter_Lrolling_kiru_end,
&gPlayerAnim_link_anchor_Lrolling_kiru_endR, 0, 15 },
/* PLAYER_MWA_BIG_SPIN_1H */
{ &gPlayerAnim_link_fighter_Wrolling_kiru, &gPlayerAnim_link_fighter_Wrolling_kiru_end,
&gPlayerAnim_link_anchor_rolling_kiru_endR, 0, 16 },
/* PLAYER_MWA_BIG_SPIN_2H */
{ &gPlayerAnim_link_fighter_Wrolling_kiru, &gPlayerAnim_link_fighter_Wrolling_kiru_end,
&gPlayerAnim_link_anchor_Lrolling_kiru_endR, 0, 16 },
};
static LinkAnimationHeader* D_80854350[] = {
&gPlayerAnim_link_fighter_power_kiru_start,
&gPlayerAnim_link_fighter_Lpower_kiru_start,
};
static LinkAnimationHeader* D_80854358[] = {
&gPlayerAnim_link_fighter_power_kiru_startL,
&gPlayerAnim_link_fighter_Lpower_kiru_start,
};
static LinkAnimationHeader* D_80854360[] = {
&gPlayerAnim_link_fighter_power_kiru_wait,
&gPlayerAnim_link_fighter_Lpower_kiru_wait,
};
static LinkAnimationHeader* D_80854368[] = {
&gPlayerAnim_link_fighter_power_kiru_wait_end,
&gPlayerAnim_link_fighter_Lpower_kiru_wait_end,
};
static LinkAnimationHeader* D_80854370[] = {
&gPlayerAnim_link_fighter_power_kiru_walk,
&gPlayerAnim_link_fighter_Lpower_kiru_walk,
};
static LinkAnimationHeader* D_80854378[] = {
&gPlayerAnim_link_fighter_power_kiru_side_walk,
&gPlayerAnim_link_fighter_Lpower_kiru_side_walk,
};
static u8 D_80854380[2] = { PLAYER_MWA_SPIN_ATTACK_1H, PLAYER_MWA_SPIN_ATTACK_2H };
static u8 D_80854384[2] = { PLAYER_MWA_BIG_SPIN_1H, PLAYER_MWA_BIG_SPIN_2H };
static u16 sItemButtons[] = { BTN_B, BTN_CLEFT, BTN_CDOWN, BTN_CRIGHT, BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT };
static u8 sMagicSpellCosts[] = { 12, 24, 24, 12, 24, 12 };
static u16 D_80854398[] = { NA_SE_IT_BOW_DRAW, NA_SE_IT_SLING_DRAW, NA_SE_IT_HOOKSHOT_READY };
static u8 sMagicArrowCosts[] = { 4, 4, 8 };
static LinkAnimationHeader* D_808543A4[] = {
&gPlayerAnim_link_anchor_waitR2defense,
&gPlayerAnim_link_anchor_waitR2defense_long,
};
static LinkAnimationHeader* D_808543AC[] = {
&gPlayerAnim_link_anchor_waitL2defense,
&gPlayerAnim_link_anchor_waitL2defense_long,
};
static LinkAnimationHeader* D_808543B4[] = {
&gPlayerAnim_link_anchor_defense_hit,
&gPlayerAnim_link_anchor_defense_long_hitL,
};
static LinkAnimationHeader* D_808543BC[] = {
&gPlayerAnim_link_anchor_defense_hit,
&gPlayerAnim_link_anchor_defense_long_hitR,
};
static LinkAnimationHeader* D_808543C4[] = {
&gPlayerAnim_link_normal_defense_hit,
&gPlayerAnim_link_fighter_defense_long_hit,
};
static LinkAnimationHeader* D_808543CC[] = {
&gPlayerAnim_link_bow_walk2ready,
&gPlayerAnim_link_hook_walk2ready,
};
static LinkAnimationHeader* D_808543D4[] = {
&gPlayerAnim_link_bow_bow_wait,
&gPlayerAnim_link_hook_wait,
};
void Player_ZeroSpeedXZ(Player* this) {
this->actor.speedXZ = 0.0f;
this->linearVelocity = 0.0f;
}
void func_80832224(Player* this) {
Player_ZeroSpeedXZ(this);
this->unk_6AD = 0;
}
s32 func_8083224C(PlayState* play) {
Player* this = GET_PLAYER(play);
return CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_PLAYER_TALKED_TO);
}
void Player_AnimPlayOnce(PlayState* play, Player* this, LinkAnimationHeader* anim) {
LinkAnimation_PlayOnce(play, &this->skelAnime, anim);
}
void Player_AnimPlayLoop(PlayState* play, Player* this, LinkAnimationHeader* anim) {
LinkAnimation_PlayLoop(play, &this->skelAnime, anim);
}
void Player_AnimPlayLoopAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim) {
LinkAnimation_PlayLoopSetSpeed(play, &this->skelAnime, anim, PLAYER_ANIM_ADJUSTED_SPEED);
}
void Player_AnimPlayOnceAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim) {
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, PLAYER_ANIM_ADJUSTED_SPEED);
}
void func_808322FC(Player* this) {
this->actor.shape.rot.y += this->skelAnime.jointTable[1].y;
this->skelAnime.jointTable[1].y = 0;
}
void func_80832318(Player* this) {
this->stateFlags2 &= ~PLAYER_STATE2_SPIN_ATTACKING;
this->meleeWeaponState = 0;
this->meleeWeaponInfo[0].active = this->meleeWeaponInfo[1].active = this->meleeWeaponInfo[2].active = 0;
}
void func_80832340(PlayState* play, Player* this) {
Camera* subCam;
if (this->subCamId != SUBCAM_NONE) {
subCam = play->cameraPtrs[this->subCamId];
if ((subCam != NULL) && (subCam->csId == 1100)) {
OnePointCutscene_EndCutscene(play, this->subCamId);
this->subCamId = SUBCAM_NONE;
}
}
this->stateFlags2 &= ~(PLAYER_STATE2_UNDERWATER | PLAYER_STATE2_DIVING);
}
void Player_DetachHeldActor(PlayState* play, Player* this) {
Actor* heldActor = this->heldActor;
if ((heldActor != NULL) && !Player_HoldsHookshot(this)) {
this->actor.child = NULL;
this->heldActor = NULL;
this->interactRangeActor = NULL;
heldActor->parent = NULL;
this->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD;
}
if (Player_GetExplosiveHeld(this) >= 0) {
Player_InitItemAction(play, this, PLAYER_IA_NONE);
this->heldItemId = ITEM_NONE_FE;
}
}
void func_80832440(PlayState* play, Player* this) {
if ((this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->heldActor == NULL)) {
if (this->interactRangeActor != NULL) {
if (this->getItemId == GI_NONE) {
this->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD;
this->interactRangeActor = NULL;
}
} else {
this->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD;
}
}
func_80832318(this);
this->unk_6AD = 0;
func_80832340(play, this);
func_8005B1A4(Play_GetCamera(play, 0));
this->stateFlags1 &= ~(PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_FIRST_PERSON | PLAYER_STATE1_CLIMBING_LADDER);
this->stateFlags2 &= ~(PLAYER_STATE2_MOVING_DYNAPOLY | PLAYER_STATE2_GRABBED_BY_ENEMY | PLAYER_STATE2_CRAWLING);
this->actor.shape.rot.x = 0;
this->actor.shape.yOffset = 0.0f;
this->unk_845 = this->unk_844 = 0;
}
s32 func_80832528(PlayState* play, Player* this) {
if (this->heldItemAction >= PLAYER_IA_FISHING_POLE) {
Player_UseItem(play, this, ITEM_NONE);
return 1;
} else {
return 0;
}
}
void func_80832564(PlayState* play, Player* this) {
func_80832440(play, this);
Player_DetachHeldActor(play, this);
}
s32 func_80832594(Player* this, s32 arg1, s32 arg2) {
s16 controlStickAngleDiff = this->prevControlStickAngle - sControlStickAngle;
this->av2.actionVar2 += arg1 + (s16)(ABS(controlStickAngleDiff) * fabsf(sControlStickMagnitude) * 2.5415802156203426e-06f);
if (CHECK_BTN_ANY(sControlInput->press.button, BTN_A | BTN_B)) {
this->av2.actionVar2 += 5;
}
return this->av2.actionVar2 > arg2;
}
void func_80832630(PlayState* play) {
if (play->actorCtx.freezeFlashTimer == 0) {
play->actorCtx.freezeFlashTimer = 1;
}
}
void Player_RequestRumble(Player* this, s32 sourceStrength, s32 duration, s32 decreaseRate, s32 distSq) {
if (this->actor.category == ACTORCAT_PLAYER) {
func_800AA000(distSq, sourceStrength, duration, decreaseRate);
}
}
void func_80832698(Player* this, u16 sfxId) {
if (this->actor.category == ACTORCAT_PLAYER) {
Player_PlaySfx(this, sfxId + this->ageProperties->unk_92);
} else {
func_800F4190(&this->actor.projectedPos, sfxId);
}
}
void func_808326F0(Player* this) {
u16* entry = &D_8085361C[0];
s32 i;
for (i = 0; i < 4; i++) {
Audio_StopSfxById((u16)(*entry + this->ageProperties->unk_92));
entry++;
}
}
u16 func_8083275C(Player* this, u16 sfxId) {
return sfxId + this->floorSfxOffset;
}
void func_80832770(Player* this, u16 sfxId) {
Player_PlaySfx(this, func_8083275C(this, sfxId));
}
u16 func_808327A4(Player* this, u16 sfxId) {
return sfxId + this->floorSfxOffset + this->ageProperties->unk_94;
}
void func_808327C4(Player* this, u16 sfxId) {
Player_PlaySfx(this, func_808327A4(this, sfxId));
}
void func_808327F8(Player* this, f32 arg1) {
s32 sfxId;
if (this->currentBoots == PLAYER_BOOTS_IRON) {
sfxId = NA_SE_PL_WALK_HEAVYBOOTS;
} else {
sfxId = func_808327A4(this, NA_SE_PL_WALK_GROUND);
}
func_800F4010(&this->actor.projectedPos, sfxId, arg1);
// Gameplay stats: Count footsteps
// Only count while game isn't complete and don't count Link's idle animations or crawling in crawlspaces
if (!gSaveContext.sohStats.gameComplete && !(this->stateFlags2 & PLAYER_STATE2_IDLING) &&
!(this->stateFlags2 & PLAYER_STATE2_CRAWLING)) {
gSaveContext.sohStats.count[COUNT_STEPS]++;
}
}
void func_80832854(Player* this) {
s32 sfxId;
if (this->currentBoots == PLAYER_BOOTS_IRON) {
sfxId = NA_SE_PL_JUMP_HEAVYBOOTS;
} else {
sfxId = func_808327A4(this, NA_SE_PL_JUMP);
}
Player_PlaySfx(this, sfxId);
}
void func_808328A0(Player* this) {
s32 sfxId;
if (this->currentBoots == PLAYER_BOOTS_IRON) {
sfxId = NA_SE_PL_LAND_HEAVYBOOTS;
} else {
sfxId = func_808327A4(this, NA_SE_PL_LAND);
}
Player_PlaySfx(this, sfxId);
}
void func_808328EC(Player* this, u16 sfxId) {
Player_PlaySfx(this, sfxId);
this->stateFlags2 |= PLAYER_STATE2_FOOTSTEP;
}
/**
* Process a list of `AnimSfx` entries.
* An `AnimSfx` entry contains a sound effect to play, a frame number that indicates
* when during an animation it should play, and a type value that indicates how it should be played back.
*
* The list will stop being processed after an entry that has a negative value for the `data` field.
*
* Some types do not make use of `sfxId`, the SFX function called will pick a sound on its own.
* The `sfxId` field is not used in this case and can be any value, but 0 is typically used.
*
* @param entry A pointer to the first entry of an `AnimSfx` list.
*/
void Player_ProcessAnimSfxList(Player* this, AnimSfxEntry* entry) {
s32 cont;
s32 pad;
do {
s32 absData = ABS(entry->data);
s32 type = ANIMSFX_GET_TYPE(absData);
if (LinkAnimation_OnFrame(&this->skelAnime, fabsf(ANIMSFX_GET_FRAME(absData)))) {
if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_1)) {
Player_PlaySfx(this, entry->sfxId);
} else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_2)) {
func_80832770(this, entry->sfxId);
} else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_3)) {
func_808327C4(this, entry->sfxId);
} else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_4)) {
func_80832698(this, entry->sfxId);
} else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_5)) {
func_808328A0(this);
} else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_6)) {
func_808327F8(this, 6.0f);
} else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_7)) {
func_80832854(this);
} else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_8)) {
func_808327F8(this, 0.0f);
} else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_9)) {
func_800F4010(&this->actor.projectedPos,
NA_SE_PL_WALK_LADDER + this->ageProperties->unk_94, 0.0f);
}
}
cont = (entry->data >= 0); // stop processing if `data` is negative
entry++;
} while (cont);
}
void Player_AnimChangeOnceMorph(PlayState* play, Player* this, LinkAnimationHeader* anim) {
LinkAnimation_Change(play, &this->skelAnime, anim, 1.0f, 0.0f, Animation_GetLastFrame(anim), ANIMMODE_ONCE, -6.0f);
}
void Player_AnimChangeOnceMorphAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim) {
LinkAnimation_Change(play, &this->skelAnime, anim, PLAYER_ANIM_ADJUSTED_SPEED, 0.0f, Animation_GetLastFrame(anim),
ANIMMODE_ONCE, -6.0f);
}
void Player_AnimChangeLoopMorph(PlayState* play, Player* this, LinkAnimationHeader* anim) {
LinkAnimation_Change(play, &this->skelAnime, anim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -6.0f);
}
void Player_AnimChangeFreeze(PlayState* play, Player* this, LinkAnimationHeader* anim) {
LinkAnimation_Change(play, &this->skelAnime, anim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, 0.0f);
}
void Player_AnimChangeLoopSlowMorph(PlayState* play, Player* this, LinkAnimationHeader* anim) {
LinkAnimation_Change(play, &this->skelAnime, anim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -16.0f);
}
s32 func_80832CB0(PlayState* play, Player* this, LinkAnimationHeader* anim) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimPlayLoop(play, this, anim);
return 1;
} else {
return 0;
}
}
void Player_SkelAnimeResetPrevTranslRot(Player* this) {
this->skelAnime.prevTransl = this->skelAnime.baseTransl;
this->skelAnime.prevRot = this->actor.shape.rot.y;
}
void Player_SkelAnimeResetPrevTranslRotAgeScale(Player* this) {
Player_SkelAnimeResetPrevTranslRot(this);
this->skelAnime.prevTransl.x *= this->ageProperties->unk_08;
this->skelAnime.prevTransl.y *= this->ageProperties->unk_08;
this->skelAnime.prevTransl.z *= this->ageProperties->unk_08;
}
void Player_ZeroRootLimbYaw(Player* this) {
this->skelAnime.jointTable[1].y = 0;
}
void func_80832DBC(Player* this) {
if (this->skelAnime.moveFlags != 0) {
func_808322FC(this);
this->skelAnime.jointTable[0].x = this->skelAnime.baseTransl.x;
this->skelAnime.jointTable[0].z = this->skelAnime.baseTransl.z;
if (this->skelAnime.moveFlags & 8) {
if (this->skelAnime.moveFlags & 2) {
this->skelAnime.jointTable[0].y = this->skelAnime.prevTransl.y;
}
} else {
this->skelAnime.jointTable[0].y = this->skelAnime.baseTransl.y;
}
Player_SkelAnimeResetPrevTranslRot(this);
this->skelAnime.moveFlags = 0;
}
}
void func_80832E48(Player* this, s32 flags) {
Vec3f pos;
this->skelAnime.moveFlags = flags;
this->skelAnime.prevTransl = this->skelAnime.baseTransl;
SkelAnime_UpdateTranslation(&this->skelAnime, &pos, this->actor.shape.rot.y);
if (flags & 1) {
if (!LINK_IS_ADULT) {
pos.x *= 0.64f;
pos.z *= 0.64f;
}
this->actor.world.pos.x += pos.x * this->actor.scale.x;
this->actor.world.pos.z += pos.z * this->actor.scale.z;
}
if (flags & 2) {
if (!(flags & 4)) {
pos.y *= this->ageProperties->unk_08;
}
this->actor.world.pos.y += pos.y * this->actor.scale.y;
}
func_808322FC(this);
}
#define ANIM_REPLACE_APPLY_FLAG_8 (1 << 8)
#define ANIM_REPLACE_APPLY_FLAG_9 (1 << 9)
void Player_AnimReplaceApplyFlags(PlayState* play, Player* this, s32 flags) {
if (flags & ANIM_REPLACE_APPLY_FLAG_9) {
Player_SkelAnimeResetPrevTranslRotAgeScale(this);
} else if ((flags & ANIM_REPLACE_APPLY_FLAG_8) || (this->skelAnime.moveFlags != 0)) {
Player_SkelAnimeResetPrevTranslRot(this);
} else {
this->skelAnime.prevTransl = this->skelAnime.jointTable[0];
this->skelAnime.prevRot = this->actor.shape.rot.y;
}
this->skelAnime.moveFlags = flags;
Player_ZeroSpeedXZ(this);
AnimationContext_DisableQueue(play);
}
void Player_AnimReplacePlayOnceSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags,
f32 playbackSpeed) {
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, playbackSpeed);
Player_AnimReplaceApplyFlags(play, this, flags);
}
void Player_AnimReplacePlayOnce(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags) {
Player_AnimReplacePlayOnceSetSpeed(play, this, anim, flags, 1.0f);
}
void Player_AnimReplacePlayOnceAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags) {
Player_AnimReplacePlayOnceSetSpeed(play, this, anim, flags, PLAYER_ANIM_ADJUSTED_SPEED);
}
void Player_AnimReplaceNormalPlayOnceAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim) {
Player_AnimReplacePlayOnceAdjusted(play, this, anim, 0x1C);
}
void Player_AnimReplacePlayLoopSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags,
f32 playbackSpeed) {
LinkAnimation_PlayLoopSetSpeed(play, &this->skelAnime, anim, playbackSpeed);
Player_AnimReplaceApplyFlags(play, this, flags);
}
void Player_AnimReplacePlayLoop(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags) {
Player_AnimReplacePlayLoopSetSpeed(play, this, anim, flags, 1.0f);
}
void Player_AnimReplacePlayLoopAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags) {
Player_AnimReplacePlayLoopSetSpeed(play, this, anim, flags, PLAYER_ANIM_ADJUSTED_SPEED);
}
void Player_AnimReplaceNormalPlayLoopAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim) {
Player_AnimReplacePlayLoopAdjusted(play, this, anim, 0x1C);
}
void Player_ProcessControlStick(PlayState* play, Player* this) {
s8 phi_v1;
s8 phi_v0;
this->prevControlStickMagnitude = sControlStickMagnitude;
this->prevControlStickAngle = sControlStickAngle;
func_80077D10(&sControlStickMagnitude, &sControlStickAngle, sControlInput);
D_808535DC = Camera_GetInputDirYaw(GET_ACTIVE_CAM(play)) + sControlStickAngle;
this->unk_846 = (this->unk_846 + 1) % 4;
if (sControlStickMagnitude < 55.0f) {
phi_v0 = -1;
phi_v1 = -1;
} else {
phi_v1 = (u16)(sControlStickAngle + 0x2000) >> 9;
phi_v0 = (u16)((s16)(D_808535DC - this->actor.shape.rot.y) + 0x2000) >> 14;
}
this->unk_847[this->unk_846] = phi_v1;
this->unk_84B[this->unk_846] = phi_v0;
}
void func_8083328C(PlayState* play, Player* this, LinkAnimationHeader* linkAnim) {
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, linkAnim, D_808535E8);
}
int func_808332B8(Player* this) {
return (this->stateFlags1 & PLAYER_STATE1_IN_WATER) && (this->currentBoots != PLAYER_BOOTS_IRON);
}
s32 func_808332E4(Player* this) {
return (this->stateFlags1 & PLAYER_STATE1_BOOMERANG_IN_HAND);
}
void func_808332F4(Player* this, PlayState* play) {
GetItemEntry giEntry;
if (this->getItemEntry.objectId == OBJECT_INVALID || (this->getItemId != this->getItemEntry.getItemId)) {
giEntry = ItemTable_Retrieve(this->getItemId);
} else {
giEntry = this->getItemEntry;
}
this->unk_862 = ABS(giEntry.gi);
}
static LinkAnimationHeader* func_80833338(Player* this) {
return GET_PLAYER_ANIM(PLAYER_ANIMGROUP_wait, this->modelAnimType);
}
s32 func_80833350(Player* this) {
LinkAnimationHeader** entry;
s32 i;
if (func_80833338(this) != this->skelAnime.animation) {
for (i = 0, entry = &D_80853D7C[0][0]; i < 28; i++, entry++) {
if (this->skelAnime.animation == *entry) {
return i + 1;
}
}
return 0;
}
return -1;
}
void func_808333FC(Player* this, s32 arg1) {
if (D_80853E7C[arg1] != 0) {
Player_ProcessAnimSfxList(this, D_80853E50[D_80853E7C[arg1] - 1]);
}
}
LinkAnimationHeader* func_80833438(Player* this) {
if (this->unk_890 != 0) {
return GET_PLAYER_ANIM(PLAYER_ANIMGROUP_damage_run, this->modelAnimType);
} else if (!(this->stateFlags1 & (PLAYER_STATE1_IN_WATER | PLAYER_STATE1_IN_CUTSCENE)) &&
(this->currentBoots == PLAYER_BOOTS_IRON)) {
return GET_PLAYER_ANIM(PLAYER_ANIMGROUP_heavy_run, this->modelAnimType);
} else {
return GET_PLAYER_ANIM(PLAYER_ANIMGROUP_run, this->modelAnimType);
}
}
int func_808334B4(Player* this) {
return func_808332E4(this) && (this->unk_834 != 0);
}
LinkAnimationHeader* func_808334E4(Player* this) {
if (func_808334B4(this)) {
return &gPlayerAnim_link_boom_throw_waitR;
} else {
return GET_PLAYER_ANIM(PLAYER_ANIMGROUP_waitR, this->modelAnimType);
}
}
LinkAnimationHeader* func_80833528(Player* this) {
if (func_808334B4(this)) {
return &gPlayerAnim_link_boom_throw_waitL;
} else {
return GET_PLAYER_ANIM(PLAYER_ANIMGROUP_waitL, this->modelAnimType);
}
}
LinkAnimationHeader* func_8083356C(Player* this) {
if (func_8002DD78(this)) {
return &gPlayerAnim_link_bow_side_walk;
} else {
return GET_PLAYER_ANIM(PLAYER_ANIMGROUP_side_walk, this->modelAnimType);
}
}
LinkAnimationHeader* func_808335B0(Player* this) {
if (func_808334B4(this)) {
return &gPlayerAnim_link_boom_throw_side_walkR;
} else {
return GET_PLAYER_ANIM(PLAYER_ANIMGROUP_side_walkR, this->modelAnimType);
}
}
LinkAnimationHeader* func_808335F4(Player* this) {
if (func_808334B4(this)) {
return &gPlayerAnim_link_boom_throw_side_walkL;
} else {
return GET_PLAYER_ANIM(PLAYER_ANIMGROUP_side_walkL, this->modelAnimType);
}
}
void Player_SetUpperActionFunc(Player* this, UpperActionFunc upperActionFunc) {
this->upperActionFunc = upperActionFunc;
this->unk_836 = 0;
this->upperAnimBlendWeight = 0.0f;
func_808326F0(this);
}
void Player_InitItemActionWithAnim(PlayState* play, Player* this, s8 itemAction) {
LinkAnimationHeader* current = this->skelAnime.animation;
LinkAnimationHeader** iter = &D_80853914[0][this->modelAnimType];
u32 animGroup;
this->stateFlags1 &= ~(PLAYER_STATE1_ITEM_IN_HAND | PLAYER_STATE1_BOOMERANG_IN_HAND);
for (animGroup = 0; animGroup < PLAYER_ANIMGROUP_MAX; animGroup++) {
if (current == *iter) {
break;
}
iter += PLAYER_ANIMTYPE_MAX;
}
Player_InitItemAction(play, this, itemAction);
if (animGroup < PLAYER_ANIMGROUP_MAX) {
this->skelAnime.animation = GET_PLAYER_ANIM(animGroup, this->modelAnimType);
}
}
s8 Player_ItemToItemAction(s32 item) {
if (item >= ITEM_NONE_FE) {
return PLAYER_IA_NONE;
} else if (item == ITEM_LAST_USED) {
return PLAYER_IA_LAST_USED;
} else if (item == ITEM_FISHING_POLE) {
return PLAYER_IA_FISHING_POLE;
// #region SOH [Enhancement] Added to prevent crashes with assignable equipment
} else if (item >= ITEM_TUNIC_KOKIRI && item <= ITEM_BOOTS_HOVER) {
return PLAYER_IA_NONE;
// #endregion
} else {
return sItemActions[item];
}
}
void Player_InitDefaultIA(PlayState* play, Player* this) {
}
void Player_InitDekuStickIA(PlayState* play, Player* this) {
this->unk_85C = 1.0f;
}
void Player_InitHammerIA(PlayState* play, Player* this) {
}
void Player_InitBowOrSlingshotIA(PlayState* play, Player* this) {
this->stateFlags1 |= PLAYER_STATE1_ITEM_IN_HAND;
if (this->heldItemAction != PLAYER_IA_SLINGSHOT) {
this->unk_860 = -1;
} else {
this->unk_860 = -2;
}
}
void Player_InitExplosiveIA(PlayState* play, Player* this) {
s32 explosiveType;
ExplosiveInfo* explosiveInfo;
Actor* spawnedActor;
if (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
func_80832528(play, this);
return;
}
explosiveType = Player_GetExplosiveHeld(this);
explosiveInfo = &sExplosiveInfos[explosiveType];
spawnedActor =
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, explosiveInfo->actorId, this->actor.world.pos.x,
this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 0);
if (spawnedActor != NULL) {
if ((explosiveType != 0) && (play->bombchuBowlingStatus != 0)) {
if (!CVarGetInteger("gInfiniteAmmo", 0)) {
play->bombchuBowlingStatus--;
}
if (play->bombchuBowlingStatus == 0) {
play->bombchuBowlingStatus = -1;
}
} else {
Inventory_ChangeAmmo(explosiveInfo->itemId, -1);
}
this->interactRangeActor = spawnedActor;
this->heldActor = spawnedActor;
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
this->unk_3BC.y = spawnedActor->shape.rot.y - this->actor.shape.rot.y;
this->stateFlags1 |= PLAYER_STATE1_ITEM_OVER_HEAD;
}
}
void Player_InitHookshotIA(PlayState* play, Player* this) {
this->stateFlags1 |= PLAYER_STATE1_ITEM_IN_HAND;
this->unk_860 = -3;
this->heldActor =
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_ARMS_HOOK, this->actor.world.pos.x,
this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 0);
}
void Player_InitBoomerangIA(PlayState* play, Player* this) {
this->stateFlags1 |= PLAYER_STATE1_BOOMERANG_IN_HAND;
}
void Player_InitItemAction(PlayState* play, Player* this, s8 itemAction) {
this->unk_860 = 0;
this->unk_85C = 0.0f;
this->unk_858 = 0.0f;
this->heldItemAction = this->itemAction = itemAction;
this->modelGroup = this->nextModelGroup;
this->stateFlags1 &= ~(PLAYER_STATE1_ITEM_IN_HAND | PLAYER_STATE1_BOOMERANG_IN_HAND);
sItemActionInitFuncs[itemAction](play, this);
Player_SetModelGroup(this, this->modelGroup);
}
void func_80833A20(Player* this, s32 newMeleeWeaponState) {
u16 itemSfx;
u16 voiceSfx;
if (this->meleeWeaponState == 0) {
if ((this->heldItemAction == PLAYER_IA_SWORD_BIGGORON) &&
(gSaveContext.swordHealth > 0.0f)) {
itemSfx = NA_SE_IT_HAMMER_SWING;
} else {
itemSfx = NA_SE_IT_SWORD_SWING;
}
voiceSfx = NA_SE_VO_LI_SWORD_N;
if (this->heldItemAction == PLAYER_IA_HAMMER) {
itemSfx = NA_SE_IT_HAMMER_SWING;
} else if (this->meleeWeaponAnimation >= PLAYER_MWA_SPIN_ATTACK_1H) {
itemSfx = 0;
voiceSfx = NA_SE_VO_LI_SWORD_L;
} else if (this->unk_845 >= 3) {
itemSfx = NA_SE_IT_SWORD_SWING_HARD;
voiceSfx = NA_SE_VO_LI_SWORD_L;
}
if (itemSfx != 0) {
func_808328EC(this, itemSfx);
}
if (!((this->meleeWeaponAnimation >= PLAYER_MWA_FLIPSLASH_START) &&
(this->meleeWeaponAnimation <= PLAYER_MWA_JUMPSLASH_FINISH))) {
func_80832698(this, voiceSfx);
}
if (this->heldItemAction >= PLAYER_IA_SWORD_MASTER && this->heldItemAction <= PLAYER_IA_SWORD_BIGGORON) {
gSaveContext.sohStats.count[COUNT_SWORD_SWINGS]++;
}
}
this->meleeWeaponState = newMeleeWeaponState;
}
s32 func_80833B2C(Player* this) {
if (this->stateFlags1 & (PLAYER_STATE1_TARGET_LOCKED | PLAYER_STATE1_TARGET_NOTHING | PLAYER_STATE1_30)) {
return 1;
} else {
return 0;
}
}
s32 func_80833B54(Player* this) {
if ((this->unk_664 != NULL) && CHECK_FLAG_ALL(this->unk_664->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE)) {
this->stateFlags1 |= PLAYER_STATE1_ENEMY_TARGET;
return 1;
}
if (this->stateFlags1 & PLAYER_STATE1_ENEMY_TARGET) {
this->stateFlags1 &= ~PLAYER_STATE1_ENEMY_TARGET;
if (this->linearVelocity == 0.0f) {
this->yaw = this->actor.shape.rot.y;
}
}
return 0;
}
int func_80833BCC(Player* this) {
return func_8008E9C4(this) || func_80833B2C(this);
}
int func_80833C04(Player* this) {
return func_80833B54(this) || func_80833B2C(this);
}
void func_80833C3C(Player* this) {
this->unk_870 = this->unk_874 = 0.0f;
}
s32 Player_ItemIsInUse(Player* this, s32 item) {
if ((item < ITEM_NONE_FE) && (Player_ItemToItemAction(item) == this->itemAction)) {
return true;
} else {
return false;
}
}
s32 Player_ItemIsItemAction(s32 item1, s32 itemAction) {
if ((item1 < ITEM_NONE_FE) && (Player_ItemToItemAction(item1) == itemAction)) {
return true;
} else {
return false;
}
}
s32 Player_GetItemOnButton(PlayState* play, s32 index) {
if (index >= ((CVarGetInteger("gDpadEquips", 0) != 0) ? 8 : 4)) {
return ITEM_NONE;
} else if (play->bombchuBowlingStatus != 0) {
return (play->bombchuBowlingStatus > 0) ? ITEM_BOMBCHU : ITEM_NONE;
} else if (index == 0) {
return B_BTN_ITEM;
} else if (index == 1) {
return C_BTN_ITEM(0);
} else if (index == 2) {
return C_BTN_ITEM(1);
} else if (index == 3) {
return C_BTN_ITEM(2);
} else if (index == 4) {
return DPAD_ITEM(0);
} else if (index == 5) {
return DPAD_ITEM(1);
} else if (index == 6) {
return DPAD_ITEM(2);
} else if (index == 7) {
return DPAD_ITEM(3);
}
}
/**
* Handles the high level item usage and changing process based on the B and C buttons.
*
* Tasks include:
* - Put away a mask if it is not present on any C button
* - Put away an item if it is not present on the B button or any C button
* - Use an item on the B button or any C button if the corresponding button is pressed
* - Keep track of the current item button being held down
*/
void Player_ProcessItemButtons(Player* this, PlayState* play) {
s32 maskItemAction;
s32 item;
s32 i;
if (this->currentMask != PLAYER_MASK_NONE) {
if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) {
s32 maskItem = this->currentMask - PLAYER_MASK_KEATON + ITEM_MASK_KEATON;
bool hasOnDpad = false;
if (CVarGetInteger("gDpadEquips", 0) != 0) {
for (int buttonIndex = 4; buttonIndex < 8; buttonIndex++) {
hasOnDpad |= gSaveContext.equips.buttonItems[buttonIndex] == maskItem;
}
}
if (gSaveContext.equips.buttonItems[0] != maskItem && gSaveContext.equips.buttonItems[1] != maskItem &&
gSaveContext.equips.buttonItems[2] != maskItem && gSaveContext.equips.buttonItems[3] != maskItem &&
!hasOnDpad) {
this->currentMask = sMaskMemory = PLAYER_MASK_NONE;
func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
}
} else {
maskItemAction = this->currentMask - 1 + PLAYER_IA_MASK_KEATON;
bool hasOnDpad = false;
if (CVarGetInteger("gDpadEquips", 0) != 0) {
for (int buttonIndex = 0; buttonIndex < 4; buttonIndex++) {
hasOnDpad |= Player_ItemIsItemAction(DPAD_ITEM(buttonIndex), maskItemAction);
}
}
if (!Player_ItemIsItemAction(C_BTN_ITEM(0), maskItemAction) &&
!Player_ItemIsItemAction(C_BTN_ITEM(1), maskItemAction) &&
!Player_ItemIsItemAction(C_BTN_ITEM(2), maskItemAction) && !hasOnDpad) {
this->currentMask = PLAYER_MASK_NONE;
}
}
}
if (!(this->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE)) && !func_8008F128(this)) {
if (this->itemAction >= PLAYER_IA_FISHING_POLE) {
bool hasOnDpad = false;
if (CVarGetInteger("gDpadEquips", 0) != 0) {
for (int buttonIndex = 0; buttonIndex < 4; buttonIndex++) {
hasOnDpad |= Player_ItemIsInUse(this, DPAD_ITEM(buttonIndex));
}
}
if (!Player_ItemIsInUse(this, B_BTN_ITEM) && !Player_ItemIsInUse(this, C_BTN_ITEM(0)) &&
!Player_ItemIsInUse(this, C_BTN_ITEM(1)) && !Player_ItemIsInUse(this, C_BTN_ITEM(2)) && !hasOnDpad) {
Player_UseItem(play, this, ITEM_NONE);
return;
}
}
for (i = 0; i < ARRAY_COUNT(sItemButtons); i++) {
if (CHECK_BTN_ALL(sControlInput->press.button, sItemButtons[i])) {
break;
}
}
item = Player_GetItemOnButton(play, i);
if (item >= ITEM_NONE_FE) {
for (i = 0; i < ARRAY_COUNT(sItemButtons); i++) {
if (CHECK_BTN_ALL(sControlInput->cur.button, sItemButtons[i])) {
break;
}
}
item = Player_GetItemOnButton(play, i);
if ((item < ITEM_NONE_FE) && (Player_ItemToItemAction(item) == this->heldItemAction)) {
sHeldItemButtonIsHeldDown = true;
}
} else {
this->heldItemButton = i;
Player_UseItem(play, this, item);
}
}
}
void Player_StartChangingHeldItem(Player* this, PlayState* play) {
LinkAnimationHeader* anim;
f32 endFrameTemp;
f32 startFrame;
f32 endFrame;
f32 playSpeed;
s32 itemChangeType;
s8 heldItemAction;
s32 nextAnimType;
heldItemAction = Player_ItemToItemAction(this->heldItemId);
Player_SetUpperActionFunc(this, Player_UpperAction_ChangeHeldItem);
nextAnimType = gPlayerModelTypes[this->nextModelGroup][PLAYER_MODELGROUPENTRY_ANIM];
itemChangeType = sItemChangeTypes[gPlayerModelTypes[this->modelGroup][PLAYER_MODELGROUPENTRY_ANIM]][nextAnimType];
if ((heldItemAction == PLAYER_IA_BOTTLE) || (heldItemAction == PLAYER_IA_BOOMERANG) ||
((heldItemAction == PLAYER_IA_NONE) &&
((this->heldItemAction == PLAYER_IA_BOTTLE) || (this->heldItemAction == PLAYER_IA_BOOMERANG)))) {
itemChangeType = (heldItemAction == PLAYER_IA_NONE) ? -PLAYER_ITEM_CHG_13 : PLAYER_ITEM_CHG_13;
}
this->itemChangeType = ABS(itemChangeType);
anim = sItemChangeInfo[this->itemChangeType].anim;
if ((anim == &gPlayerAnim_link_normal_fighter2free) && (this->currentShield == PLAYER_SHIELD_NONE)) {
anim = &gPlayerAnim_link_normal_free2fighter_free;
}
endFrameTemp = Animation_GetLastFrame(anim);
endFrame = endFrameTemp;
if (itemChangeType >= 0) {
playSpeed = 1.2f;
startFrame = 0.0f;
} else {
endFrame = 0.0f;
playSpeed = -1.2f;
startFrame = endFrameTemp;
}
if (heldItemAction != PLAYER_IA_NONE) {
playSpeed *= 2.0f;
}
LinkAnimation_Change(play, &this->upperSkelAnime, anim, playSpeed, startFrame, endFrame, ANIMMODE_ONCE, 0.0f);
this->stateFlags1 &= ~PLAYER_STATE1_START_PUTAWAY;
}
void Player_UpdateItems(Player* this, PlayState* play) {
if ((this->actor.category == ACTORCAT_PLAYER) && (CVarGetInteger("gQuickPutaway", 0) || !(this->stateFlags1 & PLAYER_STATE1_START_PUTAWAY)) &&
((this->heldItemAction == this->itemAction) || (this->stateFlags1 & PLAYER_STATE1_SHIELDING)) &&
(gSaveContext.health != 0) && (play->csCtx.state == CS_STATE_IDLE) && (this->csAction == 0) &&
(play->shootingGalleryStatus == 0) && (play->activeCamera == MAIN_CAM) &&
(play->transitionTrigger != TRANS_TRIGGER_START) && (gSaveContext.timer1State != 10)) {
Player_ProcessItemButtons(this, play);
}
if (this->stateFlags1 & PLAYER_STATE1_START_PUTAWAY) {
Player_StartChangingHeldItem(this, play);
}
}
// Determine projectile type for bow or slingshot
s32 func_80834380(PlayState* play, Player* this, s32* itemPtr, s32* typePtr) {
bool useBow = LINK_IS_ADULT;
if(CVarGetInteger("gBowSlingShotAmmoFix", 0)){
useBow = this->heldItemAction != PLAYER_IA_SLINGSHOT;
}
if (useBow) {
*itemPtr = ITEM_BOW;
if (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) {
*typePtr = ARROW_NORMAL_HORSE;
} else {
*typePtr = this->heldItemAction - 6;
}
} else {
*itemPtr = ITEM_SLINGSHOT;
*typePtr = ARROW_SEED;
}
if (gSaveContext.minigameState == 1) {
return play->interfaceCtx.hbaAmmo;
} else if (play->shootingGalleryStatus != 0) {
return play->shootingGalleryStatus;
} else {
return AMMO(*itemPtr);
}
}
// The player has pressed the bow or hookshot button
s32 func_8083442C(Player* this, PlayState* play) {
s32 item;
s32 arrowType;
s32 magicArrowType;
if ((this->heldItemAction >= PLAYER_IA_BOW_FIRE) && (this->heldItemAction <= PLAYER_IA_BOW_0E) &&
(gSaveContext.magicState != MAGIC_STATE_IDLE)) {
func_80078884(NA_SE_SY_ERROR);
} else {
Player_SetUpperActionFunc(this, func_808351D4);
this->stateFlags1 |= PLAYER_STATE1_READY_TO_FIRE;
this->unk_834 = 14;
if (this->unk_860 >= 0) {
Player_PlaySfx(this, D_80854398[ABS(this->unk_860) - 1]);
if (!Player_HoldsHookshot(this) && (func_80834380(play, this, &item, &arrowType) > 0)) {
magicArrowType = arrowType - ARROW_FIRE;
if (this->unk_860 >= 0) {
if ((magicArrowType >= 0) && (magicArrowType <= 2) &&
!Magic_RequestChange(play, sMagicArrowCosts[magicArrowType], MAGIC_CONSUME_NOW)) {
arrowType = ARROW_NORMAL;
}
this->heldActor = Actor_SpawnAsChild(
&play->actorCtx, &this->actor, play, ACTOR_EN_ARROW, this->actor.world.pos.x,
this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, arrowType);
}
}
}
return 1;
}
return 0;
}
void Player_FinishItemChange(PlayState* play, Player* this) {
if (this->heldItemAction != PLAYER_IA_NONE) {
if (func_8008F2BC(this, this->heldItemAction) >= 0) {
func_808328EC(this, NA_SE_IT_SWORD_PUTAWAY);
} else {
func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
}
}
Player_UseItem(play, this, this->heldItemId);
if (func_8008F2BC(this, this->heldItemAction) >= 0) {
func_808328EC(this, NA_SE_IT_SWORD_PICKOUT);
} else if (this->heldItemAction != PLAYER_IA_NONE) {
func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
}
}
void func_80834644(PlayState* play, Player* this) {
if (Player_UpperAction_ChangeHeldItem == this->upperActionFunc) {
Player_FinishItemChange(play, this);
}
Player_SetUpperActionFunc(this, sItemActionUpdateFuncs[this->heldItemAction]);
this->unk_834 = 0;
this->unk_6AC = 0;
Player_DetachHeldActor(play, this);
this->stateFlags1 &= ~PLAYER_STATE1_START_PUTAWAY;
}
LinkAnimationHeader* func_808346C4(PlayState* play, Player* this) {
Player_SetUpperActionFunc(this, func_80834B5C);
Player_DetachHeldActor(play, this);
if (this->unk_870 < 0.5f) {
return D_808543A4[Player_HoldsTwoHandedWeapon(this) &&
!(CVarGetInteger("gShieldTwoHanded", 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))];
} else {
return D_808543AC[Player_HoldsTwoHandedWeapon(this) &&
!(CVarGetInteger("gShieldTwoHanded", 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))];
}
}
s32 func_80834758(PlayState* play, Player* this) {
LinkAnimationHeader* anim;
f32 frame;
if (!(this->stateFlags1 & (PLAYER_STATE1_SHIELDING | PLAYER_STATE1_ON_HORSE | PLAYER_STATE1_IN_CUTSCENE)) &&
(play->shootingGalleryStatus == 0) && (this->heldItemAction == this->itemAction) &&
(this->currentShield != PLAYER_SHIELD_NONE) && !Player_IsChildWithHylianShield(this) && func_80833BCC(this) &&
CHECK_BTN_ALL(sControlInput->cur.button, BTN_R)) {
anim = func_808346C4(play, this);
frame = Animation_GetLastFrame(anim);
LinkAnimation_Change(play, &this->upperSkelAnime, anim, 1.0f, frame, frame, ANIMMODE_ONCE, 0.0f);
Player_PlaySfx(this, NA_SE_IT_SHIELD_POSTURE);
return 1;
} else {
return 0;
}
}
s32 func_8083485C(Player* this, PlayState* play) {
if (func_80834758(play, this)) {
return 1;
} else {
return 0;
}
}
void func_80834894(Player* this) {
Player_SetUpperActionFunc(this, func_80834C74);
if (this->itemAction < 0) {
func_8008EC70(this);
}
Animation_Reverse(&this->upperSkelAnime);
Player_PlaySfx(this, NA_SE_IT_SHIELD_REMOVE);
}
void Player_WaitToFinishItemChange(PlayState* play, Player* this) {
ItemChangeInfo* itemChangeEntry = &sItemChangeInfo[this->itemChangeType];
f32 changeFrame;
changeFrame = itemChangeEntry->changeFrame;
changeFrame = (this->upperSkelAnime.playSpeed < 0.0f) ? changeFrame - 1.0f : changeFrame;
if (LinkAnimation_OnFrame(&this->upperSkelAnime, changeFrame)) {
Player_FinishItemChange(play, this);
}
func_80833B54(this);
}
s32 func_8083499C(Player* this, PlayState* play) {
if (this->stateFlags1 & PLAYER_STATE1_START_PUTAWAY) {
Player_StartChangingHeldItem(this, play);
} else {
return 0;
}
return 1;
}
/**
* The actual sword weapon is not handled here. See `Player_ActionChange_7` for melee weapon usage.
* This upper body action allows for shielding or changing held items while a sword is in hand.
*/
s32 Player_UpperAction_Sword(Player* this, PlayState* play) {
if (func_80834758(play, this) || func_8083499C(this, play)) {
return 1;
} else {
return 0;
}
}
s32 Player_UpperAction_ChangeHeldItem(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->upperSkelAnime) ||
((Player_ItemToItemAction(this->heldItemId) == this->heldItemAction) &&
(sUseHeldItem =
(sUseHeldItem || ((this->modelAnimType != PLAYER_ANIMTYPE_3) && (play->shootingGalleryStatus == 0)))))) {
Player_SetUpperActionFunc(this, sItemActionUpdateFuncs[this->heldItemAction]);
this->unk_834 = 0;
this->unk_6AC = 0;
sHeldItemButtonIsHeldDown = sUseHeldItem;
return this->upperActionFunc(this, play);
}
if (func_80833350(this) != 0) {
Player_WaitToFinishItemChange(play, this);
Player_AnimPlayOnce(play, this, func_80833338(this));
this->unk_6AC = 0;
} else {
Player_WaitToFinishItemChange(play, this);
}
return 1;
}
s32 func_80834B5C(Player* this, PlayState* play) {
LinkAnimation_Update(play, &this->upperSkelAnime);
if (!CHECK_BTN_ALL(sControlInput->cur.button, BTN_R)) {
func_80834894(this);
return 1;
} else {
this->stateFlags1 |= PLAYER_STATE1_SHIELDING;
Player_SetModelsForHoldingShield(this);
return 1;
}
}
s32 func_80834BD4(Player* this, PlayState* play) {
LinkAnimationHeader* anim;
f32 frame;
if (LinkAnimation_Update(play, &this->upperSkelAnime)) {
anim = func_808346C4(play, this);
frame = Animation_GetLastFrame(anim);
LinkAnimation_Change(play, &this->upperSkelAnime, anim, 1.0f, frame, frame, ANIMMODE_ONCE, 0.0f);
}
this->stateFlags1 |= PLAYER_STATE1_SHIELDING;
Player_SetModelsForHoldingShield(this);
return 1;
}
s32 func_80834C74(Player* this, PlayState* play) {
sUseHeldItem = sHeldItemButtonIsHeldDown;
if (sUseHeldItem || LinkAnimation_Update(play, &this->upperSkelAnime)) {
Player_SetUpperActionFunc(this, sItemActionUpdateFuncs[this->heldItemAction]);
LinkAnimation_PlayLoop(play, &this->upperSkelAnime,
GET_PLAYER_ANIM(PLAYER_ANIMGROUP_wait, this->modelAnimType));
this->unk_6AC = 0;
this->upperActionFunc(this, play);
return 0;
}
return 1;
}
s32 func_80834D2C(Player* this, PlayState* play) {
LinkAnimationHeader* anim;
if (this->heldItemAction != PLAYER_IA_BOOMERANG) {
if (!func_8083442C(this, play)) {
return 0;
}
if (!Player_HoldsHookshot(this)) {
anim = &gPlayerAnim_link_bow_bow_ready;
} else {
anim = &gPlayerAnim_link_hook_shot_ready;
}
LinkAnimation_PlayOnce(play, &this->upperSkelAnime, anim);
} else {
Player_SetUpperActionFunc(this, func_80835884);
this->unk_834 = 10;
LinkAnimation_PlayOnce(play, &this->upperSkelAnime, &gPlayerAnim_link_boom_throw_wait2waitR);
}
if (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) {
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_uma_anim_walk);
} else if ((this->actor.bgCheckFlags & 1) && !func_80833B54(this)) {
Player_AnimPlayLoop(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_wait, this->modelAnimType));
}
return 1;
}
int func_80834E44(PlayState* play) {
return (play->shootingGalleryStatus > 0) && CHECK_BTN_ALL(sControlInput->press.button, BTN_B);
}
int func_80834E7C(PlayState* play) {
u16 buttonsToCheck = BTN_A | BTN_B | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN;
if (CVarGetInteger("gDpadEquips", 0) != 0) {
buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
}
return (play->shootingGalleryStatus != 0) &&
((play->shootingGalleryStatus < 0) ||
CHECK_BTN_ANY(sControlInput->cur.button, buttonsToCheck));
}
s32 func_80834EB8(Player* this, PlayState* play) {
if ((this->unk_6AD == 0) || (this->unk_6AD == 2)) {
if (func_80833BCC(this) ||
(Camera_CheckValidMode(Play_GetCamera(play, 0), 7) == 0)) {
return 1;
}
this->unk_6AD = 2;
}
return 0;
}
s32 func_80834F2C(Player* this, PlayState* play) {
if ((this->doorType == PLAYER_DOORTYPE_NONE) && !(this->stateFlags1 & PLAYER_STATE1_THREW_BOOMERANG)) {
if (sUseHeldItem || func_80834E44(play)) {
if (func_80834D2C(this, play)) {
return func_80834EB8(this, play);
}
}
}
return 0;
}
s32 func_80834FBC(Player* this) {
if (this->actor.child != NULL) {
if (this->heldActor == NULL) {
this->heldActor = this->actor.child;
Player_RequestRumble(this, 255, 10, 250, 0);
Player_PlaySfx(this, NA_SE_IT_HOOKSHOT_RECEIVE);
}
return 1;
}
return 0;
}
s32 func_8083501C(Player* this, PlayState* play) {
if (this->unk_860 >= 0) {
this->unk_860 = -this->unk_860;
}
if ((!Player_HoldsHookshot(this) || func_80834FBC(this)) && !func_80834758(play, this) &&
!func_80834F2C(this, play)) {
return 0;
} else if (this->rideActor != NULL) {
this->unk_6AD = 2; // OTRTODO: THIS IS A BAD IDEA BUT IT FIXES THE HORSE FIRST PERSON?
}
return 1;
}
// Fire the projectile
s32 func_808350A4(PlayState* play, Player* this) {
s32 item;
s32 arrowType;
if (this->heldActor != NULL) {
if (!Player_HoldsHookshot(this)) {
func_80834380(play, this, &item, &arrowType);
if (gSaveContext.minigameState == 1) {
if (!CVarGetInteger("gInfiniteAmmo", 0)) {
play->interfaceCtx.hbaAmmo--;
}
} else if (play->shootingGalleryStatus != 0) {
if (!CVarGetInteger("gInfiniteAmmo", 0)) {
play->shootingGalleryStatus--;
}
} else {
Inventory_ChangeAmmo(item, -1);
}
if (play->shootingGalleryStatus == 1) {
play->shootingGalleryStatus = -10;
}
Player_RequestRumble(this, 150, 10, 150, 0);
} else {
Player_RequestRumble(this, 255, 20, 150, 0);
}
this->unk_A73 = 4;
this->heldActor->parent = NULL;
this->actor.child = NULL;
this->heldActor = NULL;
return 1;
}
return 0;
}
static u16 D_808543DC[] = { NA_SE_IT_BOW_FLICK, NA_SE_IT_SLING_FLICK };
s32 func_808351D4(Player* this, PlayState* play) {
s32 sp2C;
if (!Player_HoldsHookshot(this)) {
sp2C = 0;
} else {
sp2C = 1;
}
Math_ScaledStepToS(&this->unk_6C0, 1200, 400);
this->unk_6AE |= 0x100;
if ((this->unk_836 == 0) && (func_80833350(this) == 0) &&
(this->skelAnime.animation == &gPlayerAnim_link_bow_side_walk)) {
LinkAnimation_PlayOnce(play, &this->upperSkelAnime, D_808543CC[sp2C]);
this->unk_836 = -1;
} else if (LinkAnimation_Update(play, &this->upperSkelAnime)) {
LinkAnimation_PlayLoop(play, &this->upperSkelAnime, D_808543D4[sp2C]);
this->unk_836 = 1;
} else if (this->unk_836 == 1) {
this->unk_836 = 2;
}
if (this->unk_834 > 10) {
this->unk_834--;
}
func_80834EB8(this, play);
if ((this->unk_836 > 0) && ((this->unk_860 < 0) || (!sHeldItemButtonIsHeldDown && !func_80834E7C(play)))) {
Player_SetUpperActionFunc(this, func_808353D8);
if (this->unk_860 >= 0) {
if (sp2C == 0) {
if (!func_808350A4(play, this)) {
Player_PlaySfx(this, D_808543DC[ABS(this->unk_860) - 1]);
}
} else if (this->actor.bgCheckFlags & 1) {
func_808350A4(play, this);
}
}
this->unk_834 = 10;
Player_ZeroSpeedXZ(this);
} else {
this->stateFlags1 |= PLAYER_STATE1_READY_TO_FIRE;
}
return 1;
}
s32 func_808353D8(Player* this, PlayState* play) {
LinkAnimation_Update(play, &this->upperSkelAnime);
if (Player_HoldsHookshot(this) && !func_80834FBC(this)) {
return 1;
}
if (!func_80834758(play, this) &&
(sUseHeldItem || ((this->unk_860 < 0) && sHeldItemButtonIsHeldDown) || func_80834E44(play))) {
this->unk_860 = ABS(this->unk_860);
if (func_8083442C(this, play)) {
if (Player_HoldsHookshot(this)) {
this->unk_836 = 1;
} else {
LinkAnimation_PlayOnce(play, &this->upperSkelAnime, &gPlayerAnim_link_bow_bow_shoot_next);
}
}
} else {
if (this->unk_834 != 0) {
this->unk_834--;
}
if (func_80833BCC(this) || (this->unk_6AD != 0) || (this->stateFlags1 & PLAYER_STATE1_FIRST_PERSON)) {
if (this->unk_834 == 0) {
this->unk_834++;
}
return 1;
}
if (Player_HoldsHookshot(this)) {
Player_SetUpperActionFunc(this, func_8083501C);
} else {
Player_SetUpperActionFunc(this, func_80835588);
LinkAnimation_PlayOnce(play, &this->upperSkelAnime, &gPlayerAnim_link_bow_bow_shoot_end);
}
this->unk_834 = 0;
}
return 1;
}
s32 func_80835588(Player* this, PlayState* play) {
if (!(this->actor.bgCheckFlags & 1) || LinkAnimation_Update(play, &this->upperSkelAnime)) {
Player_SetUpperActionFunc(this, func_8083501C);
}
return 1;
}
void func_808355DC(Player* this) {
this->stateFlags1 |= PLAYER_STATE1_TARGET_NOTHING;
if (!(this->skelAnime.moveFlags & 0x80) && (this->actor.bgCheckFlags & 0x200) && (sShapeYawToTouchedWall < 0x2000)) {
this->yaw = this->actor.shape.rot.y = this->actor.wallYaw + 0x8000;
}
this->zTargetYaw = this->actor.shape.rot.y;
}
s32 func_80835644(PlayState* play, Player* this, Actor* arg2) {
if (arg2 == NULL) {
func_80832564(play, this);
func_80839F90(this, play);
return 1;
}
return 0;
}
void func_80835688(Player* this, PlayState* play) {
if (!func_80835644(play, this, this->heldActor)) {
Player_SetUpperActionFunc(this, Player_UpperAction_CarryActor);
LinkAnimation_PlayLoop(play, &this->upperSkelAnime, &gPlayerAnim_link_normal_carryB_wait);
}
}
s32 Player_UpperAction_CarryActor(Player* this, PlayState* play) {
Actor* heldActor = this->heldActor;
if (heldActor == NULL) {
func_80834644(play, this);
}
if (func_80834758(play, this)) {
return 1;
}
if (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
if (LinkAnimation_Update(play, &this->upperSkelAnime)) {
LinkAnimation_PlayLoop(play, &this->upperSkelAnime, &gPlayerAnim_link_normal_carryB_wait);
}
if ((heldActor->id == ACTOR_EN_NIW) && (this->actor.velocity.y <= 0.0f)) {
this->actor.minVelocityY = -2.0f;
this->actor.gravity = -0.5f;
this->fallStartHeight = this->actor.world.pos.y;
}
return 1;
}
return func_8083485C(this, play);
}
void func_808357E8(Player* this, Gfx** dLists) {
if (LINK_IS_ADULT && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0))) {
this->leftHandDLists = &dLists[1];
} else {
this->leftHandDLists = &dLists[gSaveContext.linkAge];
}
}
s32 func_80835800(Player* this, PlayState* play) {
if (func_80834758(play, this)) {
return 1;
}
if (this->stateFlags1 & PLAYER_STATE1_THREW_BOOMERANG) {
Player_SetUpperActionFunc(this, func_80835B60);
} else if (func_80834F2C(this, play)) {
return 1;
}
return 0;
}
s32 func_80835884(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->upperSkelAnime)) {
Player_SetUpperActionFunc(this, func_808358F0);
LinkAnimation_PlayLoop(play, &this->upperSkelAnime, &gPlayerAnim_link_boom_throw_waitR);
}
func_80834EB8(this, play);
return 1;
}
s32 func_808358F0(Player* this, PlayState* play) {
LinkAnimationHeader* animSeg = this->skelAnime.animation;
if ((func_808334E4(this) == animSeg) || (func_80833528(this) == animSeg) || (func_808335B0(this) == animSeg) ||
(func_808335F4(this) == animSeg)) {
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable,
this->skelAnime.jointTable);
} else {
LinkAnimation_Update(play, &this->upperSkelAnime);
}
func_80834EB8(this, play);
if (!sHeldItemButtonIsHeldDown) {
Player_SetUpperActionFunc(this, func_808359FC);
LinkAnimation_PlayOnce(play, &this->upperSkelAnime,
(this->unk_870 < 0.5f) ? &gPlayerAnim_link_boom_throwR : &gPlayerAnim_link_boom_throwL);
}
return 1;
}
s32 func_808359FC(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->upperSkelAnime)) {
Player_SetUpperActionFunc(this, func_80835B60);
this->unk_834 = 0;
} else if (LinkAnimation_OnFrame(&this->upperSkelAnime, 6.0f)) {
f32 posX = (Math_SinS(this->actor.shape.rot.y) * 10.0f) + this->actor.world.pos.x;
f32 posZ = (Math_CosS(this->actor.shape.rot.y) * 10.0f) + this->actor.world.pos.z;
s32 yaw = (this->unk_664 != NULL) ? this->actor.shape.rot.y + 14000 : this->actor.shape.rot.y;
EnBoom* boomerang =
(EnBoom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOOM, posX, this->actor.world.pos.y + 30.0f, posZ,
this->actor.focus.rot.x, yaw, 0, 0, true);
this->boomerangActor = &boomerang->actor;
if (boomerang != NULL) {
boomerang->moveTo = this->unk_664;
boomerang->returnTimer = 20;
this->stateFlags1 |= PLAYER_STATE1_THREW_BOOMERANG;
if (!func_8008E9C4(this)) {
func_808355DC(this);
}
this->unk_A73 = 4;
Player_PlaySfx(this, NA_SE_IT_BOOMERANG_THROW);
func_80832698(this, NA_SE_VO_LI_SWORD_N);
}
}
return 1;
}
s32 spawn_boomerang_ivan(EnPartner* this, PlayState* play) {
if (!CVarGetInteger("gIvanCoopModeEnabled", 0)) {
return 0;
}
f32 posX = (Math_SinS(this->actor.shape.rot.y) * 1.0f) + this->actor.world.pos.x;
f32 posZ = (Math_CosS(this->actor.shape.rot.y) * 1.0f) + this->actor.world.pos.z;
s32 yaw = this->actor.shape.rot.y;
EnBoom* boomerang =
(EnBoom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOOM, posX, this->actor.world.pos.y + 7.0f, posZ,
this->actor.focus.rot.x, yaw, 0, 0, true);
this->boomerangActor = &boomerang->actor;
if (boomerang != NULL) {
boomerang->returnTimer = 20;
Audio_PlayActorSound2(&this->actor, NA_SE_IT_BOOMERANG_THROW);
}
return 1;
}
s32 func_80835B60(Player* this, PlayState* play) {
if (func_80834758(play, this)) {
return 1;
}
if (!(this->stateFlags1 & PLAYER_STATE1_THREW_BOOMERANG)) {
Player_SetUpperActionFunc(this, func_80835C08);
LinkAnimation_PlayOnce(play, &this->upperSkelAnime, &gPlayerAnim_link_boom_catch);
func_808357E8(this, gPlayerLeftHandBoomerangDLs);
Player_PlaySfx(this, NA_SE_PL_CATCH_BOOMERANG);
func_80832698(this, NA_SE_VO_LI_SWORD_N);
return 1;
}
if (sUseHeldItem && CVarGetInteger("gFastBoomerang", 0)) {
this->boomerangQuickRecall = true;
}
return 0;
}
s32 func_80835C08(Player* this, PlayState* play) {
if (!func_80835800(this, play) && LinkAnimation_Update(play, &this->upperSkelAnime)) {
Player_SetUpperActionFunc(this, func_80835800);
}
return 1;
}
s32 Player_SetupAction(PlayState* play, Player* this, PlayerActionFunc actionFunc, s32 flags) {
if (actionFunc == this->actionFunc) {
return 0;
}
if (Player_Action_8084E3C4 == this->actionFunc) {
Audio_OcaSetInstrument(0);
this->stateFlags2 &= ~(PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR | PLAYER_STATE2_PLAY_FOR_ACTOR);
} else if (Player_Action_808507F4 == this->actionFunc) {
func_80832340(play, this);
}
this->actionFunc = actionFunc;
if ((this->itemAction != this->heldItemAction) && (!(flags & 1) || !(this->stateFlags1 & PLAYER_STATE1_SHIELDING))) {
func_8008EC70(this);
}
if (!(flags & 1) && !(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) {
func_80834644(play, this);
this->stateFlags1 &= ~PLAYER_STATE1_SHIELDING;
}
func_80832DBC(this);
this->stateFlags1 &= ~(PLAYER_STATE1_HOOKSHOT_FALLING | PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DAMAGED | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE |
PLAYER_STATE1_FLOOR_DISABLED);
this->stateFlags2 &= ~(PLAYER_STATE2_HOPPING | PLAYER_STATE2_OCARINA_PLAYING | PLAYER_STATE2_IDLING);
this->stateFlags3 &= ~(PLAYER_STATE3_MIDAIR | PLAYER_STATE3_FINISHED_ATTACKING | PLAYER_STATE3_HOOKSHOT_TRAVELLING);
this->av1.actionVar1 = 0;
this->av2.actionVar2 = 0;
this->unk_6AC = 0;
func_808326F0(this);
return 1;
}
void func_80835DAC(PlayState* play, Player* this, PlayerActionFunc actionFunc, s32 flags) {
s32 temp;
temp = this->skelAnime.moveFlags;
this->skelAnime.moveFlags = 0;
Player_SetupAction(play, this, actionFunc, flags);
this->skelAnime.moveFlags = temp;
}
void func_80835DE4(PlayState* play, Player* this, PlayerActionFunc actionFunc, s32 flags) {
s32 temp;
if (this->itemAction >= 0) {
temp = this->itemAction;
this->itemAction = this->heldItemAction;
Player_SetupAction(play, this, actionFunc, flags);
this->itemAction = temp;
Player_SetModels(this, Player_ActionToModelGroup(this, this->itemAction));
}
}
void func_80835E44(PlayState* play, s16 camSetting) {
if (!func_800C0CB8(play)) {
if (camSetting == CAM_SET_SCENE_TRANSITION) {
Interface_ChangeAlpha(2);
}
} else {
Camera_ChangeSetting(Play_GetCamera(play, 0), camSetting);
}
}
void func_80835EA4(PlayState* play, s32 arg1) {
func_80835E44(play, CAM_SET_TURN_AROUND);
Camera_SetCameraData(Play_GetCamera(play, 0), 4, NULL, NULL, arg1, 0, 0);
}
void Player_DestroyHookshot(Player* this) {
if (Player_HoldsHookshot(this)) {
Actor* heldActor = this->heldActor;
if (heldActor != NULL) {
Actor_Kill(heldActor);
this->actor.child = NULL;
this->heldActor = NULL;
}
}
}
void Player_UseItem(PlayState* play, Player* this, s32 item) {
s8 itemAction;
s32 temp;
s32 nextAnimType;
itemAction = Player_ItemToItemAction(item);
if (((this->heldItemAction == this->itemAction) &&
(!(this->stateFlags1 & PLAYER_STATE1_SHIELDING) || (Player_ActionToMeleeWeapon(itemAction) != 0) ||
(itemAction == PLAYER_IA_NONE))) ||
((this->itemAction < 0) && ((Player_ActionToMeleeWeapon(itemAction) != 0) || (itemAction == PLAYER_IA_NONE)))) {
if ((itemAction == PLAYER_IA_NONE) || !(this->stateFlags1 & PLAYER_STATE1_IN_WATER) ||
((this->actor.bgCheckFlags & 1) &&
((itemAction == PLAYER_IA_HOOKSHOT) || (itemAction == PLAYER_IA_LONGSHOT)))) {
if ((play->bombchuBowlingStatus == 0) &&
(((itemAction == PLAYER_IA_DEKU_STICK) && (AMMO(ITEM_STICK) == 0)) ||
((itemAction == PLAYER_IA_MAGIC_BEAN) && (AMMO(ITEM_BEAN) == 0)) ||
(temp = Player_ActionToExplosive(this, itemAction),
((temp >= 0) && ((AMMO(sExplosiveInfos[temp].itemId) == 0) ||
(play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].length >= 3 && !CVarGetInteger("gRemoveExplosiveLimit", 0))))))) {
// Prevent some items from being used if player is out of ammo.
// Also prevent explosives from being used if there are 3 or more active (outside of bombchu bowling)
func_80078884(NA_SE_SY_ERROR);
} else if (itemAction == PLAYER_IA_LENS_OF_TRUTH) {
// Handle Lens of Truth
if (Magic_RequestChange(play, 0, MAGIC_CONSUME_LENS)) {
if (play->actorCtx.lensActive) {
Actor_DisableLens(play);
} else {
play->actorCtx.lensActive = true;
}
func_80078884((play->actorCtx.lensActive) ? NA_SE_SY_GLASSMODE_ON : NA_SE_SY_GLASSMODE_OFF);
} else {
func_80078884(NA_SE_SY_ERROR);
}
} else if (itemAction == PLAYER_IA_DEKU_NUT) {
// Handle Deku Nuts
if (AMMO(ITEM_NUT) != 0) {
func_8083C61C(play, this);
} else {
func_80078884(NA_SE_SY_ERROR);
}
} else if ((temp = Player_ActionToMagicSpell(this, itemAction)) >= 0) {
// Handle magic spells
if (((itemAction == PLAYER_IA_FARORES_WIND) && (gSaveContext.respawn[RESPAWN_MODE_TOP].data > 0)) ||
((gSaveContext.magicCapacity != 0) && (gSaveContext.magicState == MAGIC_STATE_IDLE) &&
(gSaveContext.magic >= sMagicSpellCosts[temp]))) {
this->itemAction = itemAction;
this->unk_6AD = 4;
} else {
func_80078884(NA_SE_SY_ERROR);
}
} else if (itemAction >= PLAYER_IA_MASK_KEATON) {
// Handle wearable masks
if (this->currentMask != PLAYER_MASK_NONE) {
this->currentMask = PLAYER_MASK_NONE;
} else {
this->currentMask = itemAction - PLAYER_IA_MASK_KEATON + 1;
}
sMaskMemory = this->currentMask;
func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
} else if (((itemAction >= PLAYER_IA_OCARINA_FAIRY) && (itemAction <= PLAYER_IA_OCARINA_OF_TIME)) ||
(itemAction >= PLAYER_IA_BOTTLE_FISH)) {
// Handle "cutscene items"
if (!func_8008E9C4(this) ||
((itemAction >= PLAYER_IA_BOTTLE_POTION_RED) && (itemAction <= PLAYER_IA_BOTTLE_FAIRY))) {
func_8002D53C(play, &play->actorCtx.titleCtx);
this->unk_6AD = 4;
this->itemAction = itemAction;
}
} else if ((itemAction != this->heldItemAction) ||
((this->heldActor == NULL) && (Player_ActionToExplosive(this, itemAction) >= 0))) {
// Handle using a new held item
this->nextModelGroup = Player_ActionToModelGroup(this, itemAction);
nextAnimType = gPlayerModelTypes[this->nextModelGroup][PLAYER_MODELGROUPENTRY_ANIM];
if ((this->heldItemAction >= 0) && (Player_ActionToMagicSpell(this, itemAction) < 0) &&
(item != this->heldItemId) &&
(sItemChangeTypes[gPlayerModelTypes[this->modelGroup][PLAYER_MODELGROUPENTRY_ANIM]][nextAnimType] !=
PLAYER_ITEM_CHG_0) &&
(!CVarGetInteger("gSeparateArrows", 0) ||
itemAction < PLAYER_IA_BOW || itemAction > PLAYER_IA_BOW_0E ||
this->heldItemAction < PLAYER_IA_BOW || this->heldItemAction > PLAYER_IA_BOW_0E)) {
// Start the held item change process
this->heldItemId = item;
this->stateFlags1 |= PLAYER_STATE1_START_PUTAWAY;
} else {
// Init new held item for use
Player_DestroyHookshot(this);
Player_DetachHeldActor(play, this);
Player_InitItemActionWithAnim(play, this, itemAction);
}
} else {
// Handle using the held item already in hand
sUseHeldItem = sHeldItemButtonIsHeldDown = true;
}
}
}
}
void func_80836448(PlayState* play, Player* this, LinkAnimationHeader* anim) {
s32 cond = func_808332B8(this);
func_80832564(play, this);
Player_SetupAction(play, this, cond ? Player_Action_8084E368 : Player_Action_80843CEC, 0);
this->stateFlags1 |= PLAYER_STATE1_DEAD;
Player_AnimPlayOnce(play, this, anim);
if (anim == &gPlayerAnim_link_derth_rebirth) {
this->skelAnime.endFrame = 84.0f;
}
func_80832224(this);
func_80832698(this, NA_SE_VO_LI_DOWN);
if (this->actor.category == ACTORCAT_PLAYER) {
func_800F47BC();
if (Inventory_ConsumeFairy(play)) {
play->gameOverCtx.state = GAMEOVER_REVIVE_START;
this->av1.actionVar1 = 1;
} else {
play->gameOverCtx.state = GAMEOVER_DEATH_START;
func_800F6AB0(0);
Audio_PlayFanfare(NA_BGM_GAME_OVER);
gSaveContext.seqId = (u8)NA_BGM_DISABLED;
gSaveContext.natureAmbienceId = NATURE_ID_DISABLED;
}
OnePointCutscene_Init(play, 9806, cond ? 120 : 60, &this->actor, MAIN_CAM);
ShrinkWindow_SetVal(0x20);
}
}
s32 Player_CanUpdateItems(Player* this) {
return (!(Player_Action_808458D0 == this->actionFunc) ||
((this->stateFlags1 & PLAYER_STATE1_START_PUTAWAY) &&
((this->heldItemId == ITEM_LAST_USED) || (this->heldItemId == ITEM_NONE)))) &&
(!(Player_UpperAction_ChangeHeldItem == this->upperActionFunc) ||
(Player_ItemToItemAction(this->heldItemId) == this->heldItemAction));
}
s32 Player_UpdateUpperBody(Player* this, PlayState* play) {
if (!(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->actor.parent != NULL) && Player_HoldsHookshot(this)) {
Player_SetupAction(play, this, Player_Action_80850AEC, 1);
this->stateFlags3 |= PLAYER_STATE3_HOOKSHOT_TRAVELLING;
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_hook_fly_start);
Player_AnimReplaceApplyFlags(play, this, 0x9B);
func_80832224(this);
this->yaw = this->actor.shape.rot.y;
this->actor.bgCheckFlags &= ~1;
this->hoverBootsTimer = 0;
this->unk_6AE |= 0x43;
func_80832698(this, NA_SE_VO_LI_LASH);
return 1;
}
if (Player_CanUpdateItems(this)) {
Player_UpdateItems(this, play);
if (Player_Action_8084E604 == this->actionFunc) {
return 1;
}
}
if (!this->upperActionFunc(this, play)) {
return 0;
}
if (this->upperAnimBlendWeight != 0.0f) {
if ((func_80833350(this) == 0) || (this->linearVelocity != 0.0f)) {
AnimationContext_SetCopyFalse(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable,
this->skelAnime.jointTable, sUpperBodyLimbCopyMap);
}
Math_StepToF(&this->upperAnimBlendWeight, 0.0f, 0.25f);
AnimationContext_SetInterp(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable, 1.0f - this->upperAnimBlendWeight);
} else if ((func_80833350(this) == 0) || (this->linearVelocity != 0.0f)) {
AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap);
} else {
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable);
}
return 1;
}
s32 func_80836898(PlayState* play, Player* this, PlayerFuncA74 func) {
this->func_A74 = func;
Player_SetupAction(play, this, Player_Action_808458D0, 0);
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
return func_80832528(play, this);
}
void func_808368EC(Player* this, PlayState* play) {
s16 previousYaw = this->actor.shape.rot.y;
if (!(this->stateFlags2 & (PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS))) {
if ((this->unk_664 != NULL) &&
((play->actorCtx.targetCtx.unk_4B != 0) || (this->actor.category != ACTORCAT_PLAYER))) {
Math_ScaledStepToS(&this->actor.shape.rot.y,
Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_664->focus.pos), 4000);
} else if ((this->stateFlags1 & PLAYER_STATE1_TARGET_NOTHING) &&
!(this->stateFlags2 & (PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS))) {
Math_ScaledStepToS(&this->actor.shape.rot.y, this->zTargetYaw, 4000);
}
} else if (!(this->stateFlags2 & PLAYER_STATE2_DISABLE_ROTATION_ALWAYS)) {
Math_ScaledStepToS(&this->actor.shape.rot.y, this->yaw, 2000);
}
this->unk_87C = this->actor.shape.rot.y - previousYaw;
}
s32 func_808369C8(s16* pValue, s16 arg1, s16 arg2, s16 arg3, s16 arg4, s16 arg5) {
s16 temp1;
s16 temp2;
s16 temp3;
temp1 = temp2 = arg4 - *pValue;
temp2 = CLAMP(temp2, -arg5, arg5);
*pValue += (s16)(temp1 - temp2);
Math_ScaledStepToS(pValue, arg1, arg2);
temp3 = *pValue;
if (*pValue < -arg3) {
*pValue = -arg3;
} else if (*pValue > arg3) {
*pValue = arg3;
}
return temp3 - *pValue;
}
s32 func_80836AB8(Player* this, s32 arg1) {
s16 sp36;
s16 var;
var = this->actor.shape.rot.y;
if (arg1 != 0) {
var = this->actor.focus.rot.y;
this->unk_6BC = this->actor.focus.rot.x;
this->unk_6AE |= 0x41;
} else {
func_808369C8(&this->unk_6BC,
func_808369C8(&this->unk_6B6, this->actor.focus.rot.x, 600, 10000, this->actor.focus.rot.x, 0),
200, 4000, this->unk_6B6, 10000);
sp36 = this->actor.focus.rot.y - var;
func_808369C8(&sp36, 0, 200, 24000, this->unk_6BE, 8000);
var = this->actor.focus.rot.y - sp36;
func_808369C8(&this->unk_6B8, sp36 - this->unk_6BE, 200, 8000, sp36, 8000);
func_808369C8(&this->unk_6BE, sp36, 200, 8000, this->unk_6B8, 8000);
this->unk_6AE |= 0xD9;
}
return var;
}
void func_80836BEC(Player* this, PlayState* play) {
s32 sp1C = 0;
s32 zTrigPressed = CHECK_BTN_ALL(sControlInput->cur.button, BTN_Z);
Actor* actorToTarget;
s32 pad;
s32 holdTarget;
s32 cond;
if (!zTrigPressed) {
this->stateFlags1 &= ~PLAYER_STATE1_30;
}
if ((play->csCtx.state != CS_STATE_IDLE) || (this->csAction != 0) ||
(this->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_CUTSCENE)) || (this->stateFlags3 & PLAYER_STATE3_HOOKSHOT_TRAVELLING)) {
this->unk_66C = 0;
} else if (zTrigPressed || (this->stateFlags2 & PLAYER_STATE2_SWITCH_TARGETING) || (this->unk_684 != NULL)) {
if (this->unk_66C <= 5) {
this->unk_66C = 5;
} else {
this->unk_66C--;
}
} else if (this->stateFlags1 & PLAYER_STATE1_TARGET_NOTHING) {
this->unk_66C = 0;
} else if (this->unk_66C != 0) {
this->unk_66C--;
}
if (this->unk_66C >= 6) {
sp1C = 1;
}
cond = func_8083224C(play);
if (cond || (this->unk_66C != 0) || (this->stateFlags1 & (PLAYER_STATE1_CHARGING_SPIN_ATTACK | PLAYER_STATE1_THREW_BOOMERANG))) {
if (!cond) {
if (!(this->stateFlags1 & PLAYER_STATE1_THREW_BOOMERANG) &&
((this->heldItemAction != PLAYER_IA_FISHING_POLE) || (this->unk_860 == 0)) &&
CHECK_BTN_ALL(sControlInput->press.button, BTN_Z)) {
if (this->actor.category == ACTORCAT_PLAYER) {
actorToTarget = play->actorCtx.targetCtx.arrowPointedActor;
} else {
actorToTarget = &GET_PLAYER(play)->actor;
}
holdTarget = (gSaveContext.zTargetSetting != 0) || (this->actor.category != ACTORCAT_PLAYER);
this->stateFlags1 |= PLAYER_STATE1_TARGETING;
if ((actorToTarget != NULL) && !(actorToTarget->flags & ACTOR_FLAG_NO_LOCKON)) {
if ((actorToTarget == this->unk_664) && (this->actor.category == ACTORCAT_PLAYER)) {
actorToTarget = play->actorCtx.targetCtx.unk_94;
}
if (actorToTarget != this->unk_664) {
if (!holdTarget) {
this->stateFlags2 |= PLAYER_STATE2_SWITCH_TARGETING;
}
this->unk_664 = actorToTarget;
this->unk_66C = 15;
this->stateFlags2 &= ~(PLAYER_STATE2_SPEAK_OR_CHECK | PLAYER_STATE2_NAVI_ALERT);
} else {
if (!holdTarget) {
func_8008EDF0(this);
}
}
this->stateFlags1 &= ~PLAYER_STATE1_30;
} else {
if (!(this->stateFlags1 & (PLAYER_STATE1_TARGET_NOTHING | PLAYER_STATE1_30))) {
func_808355DC(this);
}
}
}
if (this->unk_664 != NULL) {
if ((this->actor.category == ACTORCAT_PLAYER) && (this->unk_664 != this->unk_684) &&
func_8002F0C8(this->unk_664, this, sp1C)) {
func_8008EDF0(this);
this->stateFlags1 |= PLAYER_STATE1_30;
} else if (this->unk_664 != NULL) {
this->unk_664->targetPriority = 40;
}
} else if (this->unk_684 != NULL) {
this->unk_664 = this->unk_684;
}
}
if (this->unk_664 != NULL) {
this->stateFlags1 &= ~(PLAYER_STATE1_TARGET_LOCKED | PLAYER_STATE1_TARGET_NOTHING);
if ((this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) ||
!CHECK_FLAG_ALL(this->unk_664->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE)) {
this->stateFlags1 |= PLAYER_STATE1_TARGET_LOCKED;
}
} else {
if (this->stateFlags1 & PLAYER_STATE1_TARGET_NOTHING) {
this->stateFlags2 &= ~PLAYER_STATE2_SWITCH_TARGETING;
} else {
func_8008EE08(this);
}
}
} else {
func_8008EE08(this);
}
}
/**
* These defines exist to simplify the variable used to toggle the different speed modes.
* While the `speedMode` variable is a float and can contain a non-boolean value,
* `Player_CalcSpeedAndYawFromControlStick` never actually uses the value for anything.
* It simply checks if the value is non-zero to toggle the "curved" mode.
* In practice, 0.0f or 0.018f are the only values passed to this function.
*
* It's clear that this value was intended to mean something in the curved mode calculation at
* some point in development, but was either never implemented or removed.
*
* To see the difference between linear and curved mode, with interactive toggles for
* speed cap and floor pitch, see the following desmos graph: https://www.desmos.com/calculator/hri7dcws4c
*/
// Linear mode is a straight line, increasing target speed at a steady rate relative to the control stick magnitude
#define SPEED_MODE_LINEAR 0.0f
// Curved mode drops any input below 20 units of magnitude, resulting in zero for target speed.
// Beyond 20 units, a gradual curve slowly moves up until around the 40 unit mark
// when target speed ramps up very quickly.
#define SPEED_MODE_CURVED 0.018f
/**
* Calculates target speed and yaw based on input from the control stick.
* See `Player_GetMovementSpeedAndYaw` for detailed argument descriptions.
*
* @return true if the control stick has any magnitude, false otherwise.
*/
s32 Player_CalcSpeedAndYawFromControlStick(PlayState* play, Player* this, f32* outSpeedTarget, s16* outYawTarget,
f32 speedMode) {
f32 temp;
f32 sinFloorPitch;
f32 floorPitchInfluence;
f32 speedCap;
if ((this->unk_6AD != 0) || (play->transitionTrigger == TRANS_TRIGGER_START) ||
(this->stateFlags1 & PLAYER_STATE1_LOADING)) {
*outSpeedTarget = 0.0f;
*outYawTarget = this->actor.shape.rot.y;
} else {
*outSpeedTarget = sControlStickMagnitude;
*outYawTarget = sControlStickAngle;
// The value of `speedMode` is never actually used. It only toggles this condition.
// See the definition of `SPEED_MODE_LINEAR` and `SPEED_MODE_CURVED` for more information.
if (speedMode != SPEED_MODE_LINEAR) {
*outSpeedTarget -= 20.0f;
if (*outSpeedTarget < 0.0f) {
// If control stick magnitude is below 20, return zero speed.
*outSpeedTarget = 0.0f;
} else {
// Cosine of the control stick magnitude isn't exactly meaningful, but
// it happens to give a desirable curve for grounded movement speed relative
// to control stick magnitude.
temp = 1.0f - Math_CosS(*outSpeedTarget * 450.0f);
*outSpeedTarget = (SQ(temp) * 30.0f) + 7.0f;
}
} else {
// Speed increases linearly relative to control stick magnitude
*outSpeedTarget *= 0.8f;
}
if (sControlStickMagnitude != 0.0f) {
sinFloorPitch = Math_SinS(this->floorPitch);
speedCap = this->unk_880;
floorPitchInfluence = CLAMP(sinFloorPitch, 0.0f, 0.6f);
if (this->unk_6C4 != 0.0f) {
speedCap -= (this->unk_6C4 * 0.008f);
speedCap = CLAMP_MIN(speedCap, 2.0f);
}
*outSpeedTarget = (*outSpeedTarget * 0.14f) - (8.0f * floorPitchInfluence * floorPitchInfluence);
*outSpeedTarget = CLAMP(*outSpeedTarget, 0.0f, speedCap);
return true;
}
}
return false;
}
s32 func_8083721C(Player* this) {
return Math_StepToF(&this->linearVelocity, 0.0f, REG(43) / 100.0f);
}
/**
* Gets target speed and yaw values for movement based on control stick input.
* Control stick magnitude and angle are processed in `Player_CalcSpeedAndYawFromControlStick` to get target values.
* Additionally, this function does extra processing on the target yaw value if the control stick is neutral.
*
* @param outSpeedTarget a pointer to the variable that will hold the resulting target speed value
* @param outYawTarget a pointer to the variable that will hold the resulting target yaw value
* @param speedMode toggles between a linear and curved mode for the speed value
*
* @see Player_CalcSpeedAndYawFromControlStick for more information on the linear vs curved speed mode.
*
* @return true if the control stick has any magnitude, false otherwise.
*/
s32 Player_GetMovementSpeedAndYaw(Player* this, f32* outSpeedTarget, s16* outYawTarget, f32 speedMode,
PlayState* play) {
if (!Player_CalcSpeedAndYawFromControlStick(play, this, outSpeedTarget, outYawTarget, speedMode)) {
*outYawTarget = this->actor.shape.rot.y;
if (this->unk_664 != NULL) {
if ((play->actorCtx.targetCtx.unk_4B != 0) && !(this->stateFlags2 & PLAYER_STATE2_DISABLE_ROTATION_ALWAYS)) {
*outYawTarget = Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_664->focus.pos);
return false;
}
} else if (func_80833B2C(this)) {
*outYawTarget = this->zTargetYaw;
}
return false;
} else {
*outYawTarget += Camera_GetInputDirYaw(GET_ACTIVE_CAM(play));
return true;
}
}
typedef enum {
/* 0 */ PLAYER_ACTION_CHG_0,
/* 1 */ PLAYER_ACTION_CHG_1,
/* 2 */ PLAYER_ACTION_CHG_2,
/* 3 */ PLAYER_ACTION_CHG_3,
/* 4 */ PLAYER_ACTION_CHG_4,
/* 5 */ PLAYER_ACTION_CHG_5,
/* 6 */ PLAYER_ACTION_CHG_6,
/* 7 */ PLAYER_ACTION_CHG_7,
/* 8 */ PLAYER_ACTION_CHG_8,
/* 9 */ PLAYER_ACTION_CHG_9,
/* 10 */ PLAYER_ACTION_CHG_10,
/* 11 */ PLAYER_ACTION_CHG_11,
/* 12 */ PLAYER_ACTION_CHG_12,
/* 13 */ PLAYER_ACTION_CHG_13
} ActionChangeIndex;
static s8 sActionChangeList1[] = {
PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9,
PLAYER_ACTION_CHG_10, PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_8, -PLAYER_ACTION_CHG_7,
};
static s8 sActionChangeList2[] = {
PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_1, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_5,
PLAYER_ACTION_CHG_3, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, PLAYER_ACTION_CHG_10,
PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_7, PLAYER_ACTION_CHG_8, -PLAYER_ACTION_CHG_6,
};
static s8 sActionChangeList3[] = {
PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_1, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_3,
PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, PLAYER_ACTION_CHG_10, PLAYER_ACTION_CHG_11,
PLAYER_ACTION_CHG_8, PLAYER_ACTION_CHG_7, -PLAYER_ACTION_CHG_6,
};
static s8 sActionChangeList4[] = {
PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9,
PLAYER_ACTION_CHG_10, PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_8, -PLAYER_ACTION_CHG_7,
};
static s8 sActionChangeList5[] = {
PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, PLAYER_ACTION_CHG_10,
PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_12, PLAYER_ACTION_CHG_8, -PLAYER_ACTION_CHG_7,
};
static s8 sActionChangeList6[] = {
-PLAYER_ACTION_CHG_7,
};
static s8 sActionChangeList7[] = {
PLAYER_ACTION_CHG_0, PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_1, PLAYER_ACTION_CHG_2,
PLAYER_ACTION_CHG_3, PLAYER_ACTION_CHG_5, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9,
PLAYER_ACTION_CHG_8, PLAYER_ACTION_CHG_7, -PLAYER_ACTION_CHG_6,
};
static s8 sActionChangeList8[] = {
PLAYER_ACTION_CHG_0, PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_1, PLAYER_ACTION_CHG_2,
PLAYER_ACTION_CHG_3, PLAYER_ACTION_CHG_12, PLAYER_ACTION_CHG_5, PLAYER_ACTION_CHG_4,
PLAYER_ACTION_CHG_9, PLAYER_ACTION_CHG_8, PLAYER_ACTION_CHG_7, -PLAYER_ACTION_CHG_6,
};
static s8 sActionChangeList9[] = {
PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_1, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_3, PLAYER_ACTION_CHG_12,
PLAYER_ACTION_CHG_5, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, PLAYER_ACTION_CHG_10, PLAYER_ACTION_CHG_11,
PLAYER_ACTION_CHG_8, PLAYER_ACTION_CHG_7, -PLAYER_ACTION_CHG_6,
};
static s8 sActionChangeList10[] = {
PLAYER_ACTION_CHG_10,
PLAYER_ACTION_CHG_8,
-PLAYER_ACTION_CHG_7,
};
static s8 sActionChangeList11[] = {
PLAYER_ACTION_CHG_0,
PLAYER_ACTION_CHG_12,
PLAYER_ACTION_CHG_5,
-PLAYER_ACTION_CHG_4,
};
s32 Player_ActionChange_0(Player* this, PlayState* play);
s32 Player_ActionChange_1(Player* this, PlayState* play);
s32 Player_ActionChange_2(Player* this, PlayState* play);
s32 Player_ActionChange_3(Player* this, PlayState* play);
s32 Player_ActionChange_4(Player* this, PlayState* play);
s32 Player_ActionChange_5(Player* this, PlayState* play);
s32 Player_ActionChange_6(Player* this, PlayState* play);
s32 Player_ActionChange_7(Player* this, PlayState* play);
s32 Player_ActionChange_8(Player* this, PlayState* play);
s32 Player_ActionChange_9(Player* this, PlayState* play);
s32 Player_ActionChange_10(Player* this, PlayState* play);
s32 Player_ActionChange_11(Player* this, PlayState* play);
s32 Player_ActionChange_12(Player* this, PlayState* play);
s32 Player_ActionChange_13(Player* this, PlayState* play);
static s32 (*sActionChangeFuncs[])(Player* this, PlayState* play) = {
/* PLAYER_ACTION_CHG_0 */ Player_ActionChange_0,
/* PLAYER_ACTION_CHG_1 */ Player_ActionChange_1,
/* PLAYER_ACTION_CHG_2 */ Player_ActionChange_2,
/* PLAYER_ACTION_CHG_3 */ Player_ActionChange_3,
/* PLAYER_ACTION_CHG_4 */ Player_ActionChange_4,
/* PLAYER_ACTION_CHG_5 */ Player_ActionChange_5,
/* PLAYER_ACTION_CHG_6 */ Player_ActionChange_6,
/* PLAYER_ACTION_CHG_7 */ Player_ActionChange_7,
/* PLAYER_ACTION_CHG_8 */ Player_ActionChange_8,
/* PLAYER_ACTION_CHG_9 */ Player_ActionChange_9,
/* PLAYER_ACTION_CHG_10 */ Player_ActionChange_10,
/* PLAYER_ACTION_CHG_11 */ Player_ActionChange_11,
/* PLAYER_ACTION_CHG_12 */ Player_ActionChange_12,
/* PLAYER_ACTION_CHG_13 */ Player_ActionChange_13,
};
/**
* This function processes "Action Change Lists", which run various functions that
* check if it is appropriate to change to a new action.
*
* Action Change Lists are a list of indices for the `sActionChangeFuncs` array.
* The functions are ran in order until one of them returns true, or the end of the list is reached.
* An Action Change index having a negative value indicates that it is the last member in the list.
*
* Because these lists are processed sequentially, the order of the indices in the list determines its priority.
*
* If the `updateUpperBody` argument is true, Player's upper body will update before the Action Change List
* is processed. This allows for Item Action functions to run.
*
* @return true if a new action has been chosen
*
*/
s32 Player_TryActionChangeList(PlayState* play, Player* this, s8* actionChangeList, s32 updateUpperBody) {
s32 i;
if (!(this->stateFlags1 & (PLAYER_STATE1_LOADING | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_CUTSCENE))) {
if (updateUpperBody) {
D_808535E0 = Player_UpdateUpperBody(this, play);
if (Player_Action_8084E604 == this->actionFunc) {
return true;
}
}
if (func_8008F128(this)) {
this->unk_6AE |= 0x41;
return true;
}
if (!(this->stateFlags1 & PLAYER_STATE1_START_PUTAWAY) &&
(Player_UpperAction_ChangeHeldItem != this->upperActionFunc)) {
// Process all entries in the Action Change List with a positive index
while (*actionChangeList >= 0) {
if (sActionChangeFuncs[*actionChangeList](this, play)) {
return true;
}
actionChangeList++;
}
// Try the last entry in the list. Negate the index to make it positive again.
if (sActionChangeFuncs[-(*actionChangeList)](this, play)) {
return true;
}
}
}
return false;
}
s32 func_808374A0(PlayState* play, Player* this, SkelAnime* skelAnime, f32 arg3) {
f32 speedTarget;
s16 yawTarget;
if ((skelAnime->endFrame - arg3) <= skelAnime->curFrame) {
if (Player_TryActionChangeList(play, this, sActionChangeList7, true)) {
return 0;
}
if (Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_CURVED, play)) {
return 1;
}
}
return -1;
}
void func_80837530(PlayState* play, Player* this, s32 arg2) {
if (arg2 != 0) {
this->unk_858 = 0.0f;
} else {
this->unk_858 = 0.5f;
}
this->stateFlags1 |= PLAYER_STATE1_CHARGING_SPIN_ATTACK;
if (this->actor.category == ACTORCAT_PLAYER) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_M_THUNDER, this->bodyPartsPos[PLAYER_BODYPART_WAIST].x,
this->bodyPartsPos[PLAYER_BODYPART_WAIST].y, this->bodyPartsPos[PLAYER_BODYPART_WAIST].z, 0, 0, 0,
Player_GetMeleeWeaponHeld(this) | arg2, true);
}
}
s32 func_808375D8(Player* this) {
s8 sp3C[4];
s8* iter;
s8* iter2;
s8 temp1;
s8 temp2;
s32 i;
if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) || Player_HoldsBrokenKnife(this)) {
return 0;
}
iter = &this->unk_847[0];
iter2 = &sp3C[0];
for (i = 0; i < 4; i++, iter++, iter2++) {
if ((*iter2 = *iter) < 0) {
return 0;
}
*iter2 *= 2;
}
temp1 = sp3C[0] - sp3C[1];
if (ABS(temp1) < 10) {
return 0;
}
iter2 = &sp3C[1];
for (i = 1; i < 3; i++, iter2++) {
temp2 = *iter2 - *(iter2 + 1);
if ((ABS(temp2) < 10) || (temp2 * temp1 < 0)) {
return 0;
}
}
return 1;
}
void func_80837704(PlayState* play, Player* this) {
LinkAnimationHeader* anim;
if ((this->meleeWeaponAnimation >= PLAYER_MWA_RIGHT_SLASH_1H) &&
(this->meleeWeaponAnimation <= PLAYER_MWA_RIGHT_COMBO_2H)) {
anim = D_80854358[Player_HoldsTwoHandedWeapon(this)];
} else {
anim = D_80854350[Player_HoldsTwoHandedWeapon(this)];
}
func_80832318(this);
LinkAnimation_Change(play, &this->skelAnime, anim, 1.0f, 8.0f, Animation_GetLastFrame(anim), ANIMMODE_ONCE, -9.0f);
func_80837530(play, this, 0x200);
}
void func_808377DC(PlayState* play, Player* this) {
Player_SetupAction(play, this, Player_Action_80844E68, 1);
func_80837704(play, this);
}
static s8 D_80854480[] = {
PLAYER_MWA_STAB_1H,
PLAYER_MWA_RIGHT_SLASH_1H,
PLAYER_MWA_RIGHT_SLASH_1H,
PLAYER_MWA_LEFT_SLASH_1H,
};
static s8 D_80854484[] = {
PLAYER_MWA_HAMMER_FORWARD,
PLAYER_MWA_HAMMER_SIDE,
PLAYER_MWA_HAMMER_FORWARD,
PLAYER_MWA_HAMMER_SIDE,
};
s32 func_80837818(Player* this) {
s32 sp1C = this->unk_84B[this->unk_846];
s32 sp18;
if (this->heldItemAction == PLAYER_IA_HAMMER) {
if (sp1C < 0) {
sp1C = 0;
}
sp18 = D_80854484[sp1C];
this->unk_845 = 0;
} else {
if (func_808375D8(this)) {
sp18 = PLAYER_MWA_SPIN_ATTACK_1H;
} else {
if (sp1C < 0) {
if (func_80833BCC(this)) {
sp18 = PLAYER_MWA_FORWARD_SLASH_1H;
} else {
sp18 = PLAYER_MWA_RIGHT_SLASH_1H;
}
} else {
sp18 = D_80854480[sp1C];
if (sp18 == PLAYER_MWA_STAB_1H) {
this->stateFlags2 |= PLAYER_STATE2_SWORD_LUNGE;
if (!func_80833BCC(this)) {
sp18 = PLAYER_MWA_FORWARD_SLASH_1H;
}
}
}
if (this->heldItemAction == PLAYER_IA_DEKU_STICK) {
sp18 = PLAYER_MWA_FORWARD_SLASH_1H;
}
}
if (Player_HoldsTwoHandedWeapon(this)) {
sp18++;
}
}
return sp18;
}
void func_80837918(Player* this, s32 quadIndex, u32 dmgFlags) {
this->meleeWeaponQuads[quadIndex].info.toucher.dmgFlags = dmgFlags;
if (dmgFlags == 2) {
this->meleeWeaponQuads[quadIndex].info.toucherFlags = TOUCH_ON | TOUCH_NEAREST | TOUCH_SFX_WOOD;
} else {
this->meleeWeaponQuads[quadIndex].info.toucherFlags = TOUCH_ON | TOUCH_NEAREST;
}
}
static u32 D_80854488[][2] = {
{ 0x00000200, 0x08000000 }, { 0x00000100, 0x02000000 }, { 0x00000400, 0x04000000 },
{ 0x00000002, 0x08000000 }, { 0x00000040, 0x40000000 },
};
void func_80837948(PlayState* play, Player* this, s32 arg2) {
s32 pad;
u32 dmgFlags;
s32 temp;
Player_SetupAction(play, this, Player_Action_808502D0, 0);
this->unk_844 = 8;
if (!((arg2 >= PLAYER_MWA_FLIPSLASH_FINISH) && (arg2 <= PLAYER_MWA_JUMPSLASH_FINISH))) {
func_80832318(this);
}
if ((arg2 != this->meleeWeaponAnimation) || !(this->unk_845 < 3)) {
this->unk_845 = 0;
}
this->unk_845++;
if (this->unk_845 >= 3) {
arg2 += 2;
}
this->meleeWeaponAnimation = arg2;
Player_AnimPlayOnceAdjusted(play, this, D_80854190[arg2].unk_00);
if ((arg2 != PLAYER_MWA_FLIPSLASH_START) && (arg2 != PLAYER_MWA_JUMPSLASH_START)) {
Player_AnimReplaceApplyFlags(play, this, 0x209);
}
this->yaw = this->actor.shape.rot.y;
if (Player_HoldsBrokenKnife(this)) {
temp = 1;
} else {
temp = Player_GetMeleeWeaponHeld(this) - 1;
}
if ((arg2 >= PLAYER_MWA_FLIPSLASH_START) && (arg2 <= PLAYER_MWA_JUMPSLASH_FINISH)) {
if (CVarGetInteger("gRestoreQPA", 1) && temp == -1) {
dmgFlags = 0x16171617;
}
else {
dmgFlags = D_80854488[temp][1];
}
} else {
dmgFlags = D_80854488[temp][0];
}
func_80837918(this, 0, dmgFlags);
func_80837918(this, 1, dmgFlags);
}
void func_80837AE0(Player* this, s32 timer) {
if (this->invincibilityTimer >= 0) {
this->invincibilityTimer = timer;
this->unk_88F = 0;
}
}
void func_80837AFC(Player* this, s32 timer) {
if (this->invincibilityTimer > timer) {
this->invincibilityTimer = timer;
}
this->unk_88F = 0;
}
s32 func_80837B18_modified(PlayState* play, Player* this, s32 damage, u8 modified) {
if ((this->invincibilityTimer != 0) || (this->actor.category != ACTORCAT_PLAYER)) {
return 1;
}
s32 modifiedDamage = damage;
if (modified) {
modifiedDamage *= (1 << CVarGetInteger("gDamageMul", 0));
}
return Health_ChangeBy(play, modifiedDamage);
}
s32 func_80837B18(PlayState* play, Player* this, s32 damage) {
return func_80837B18_modified(play, this, damage, true);
}
void func_80837B60(Player* this) {
this->skelAnime.prevTransl = this->skelAnime.jointTable[0];
func_80832E48(this, 3);
}
void func_80837B9C(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_8084411C, 0);
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_normal_landing_wait);
this->av2.actionVar2 = 1;
if (this->unk_6AD != 3) {
this->unk_6AD = 0;
}
}
static LinkAnimationHeader* D_808544B0[] = {
&gPlayerAnim_link_normal_front_shit, &gPlayerAnim_link_normal_front_shitR, &gPlayerAnim_link_normal_back_shit,
&gPlayerAnim_link_normal_back_shitR, &gPlayerAnim_link_normal_front_hit, &gPlayerAnim_link_anchor_front_hitR,
&gPlayerAnim_link_normal_back_hit, &gPlayerAnim_link_anchor_back_hitR,
};
void func_80837C0C(PlayState* play, Player* this, s32 arg2, f32 arg3, f32 arg4, s16 arg5, s32 arg6) {
LinkAnimationHeader* anim = NULL;
LinkAnimationHeader** sp28;
if (this->stateFlags1 & PLAYER_STATE1_HANGING_OFF_LEDGE) {
func_80837B60(this);
}
this->unk_890 = 0;
Player_PlaySfx(this, NA_SE_PL_DAMAGE);
if (!func_80837B18(play, this, 0 - this->actor.colChkInfo.damage)) {
this->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY;
if (!(this->actor.bgCheckFlags & 1) && !(this->stateFlags1 & PLAYER_STATE1_IN_WATER)) {
func_80837B9C(this, play);
}
return;
}
func_80837AE0(this, arg6);
if (arg2 == 3) {
Player_SetupAction(play, this, Player_Action_8084FB10, 0);
anim = &gPlayerAnim_link_normal_ice_down;
func_80832224(this);
Player_RequestRumble(this, 255, 10, 40, 0);
Player_PlaySfx(this, NA_SE_PL_FREEZE_S);
func_80832698(this, NA_SE_VO_LI_FREEZE);
} else if (arg2 == 4) {
Player_SetupAction(play, this, Player_Action_8084FBF4, 0);
Player_RequestRumble(this, 255, 80, 150, 0);
Player_AnimPlayLoopAdjusted(play, this, &gPlayerAnim_link_normal_electric_shock);
func_80832224(this);
this->av2.actionVar2 = 20;
} else {
arg5 -= this->actor.shape.rot.y;
if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) {
Player_SetupAction(play, this, Player_Action_8084E30C, 0);
Player_RequestRumble(this, 180, 20, 50, 0);
this->linearVelocity = 4.0f;
this->actor.velocity.y = 0.0f;
anim = &gPlayerAnim_link_swimer_swim_hit;
func_80832698(this, NA_SE_VO_LI_DAMAGE_S);
} else if ((arg2 == 1) || (arg2 == 2) || !(this->actor.bgCheckFlags & 1) ||
(this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER))) {
Player_SetupAction(play, this, Player_Action_8084377C, 0);
this->stateFlags3 |= PLAYER_STATE3_MIDAIR;
Player_RequestRumble(this, 255, 20, 150, 0);
func_80832224(this);
if (arg2 == 2) {
this->av2.actionVar2 = 4;
this->actor.speedXZ = 3.0f;
this->linearVelocity = 3.0f;
this->actor.velocity.y = 6.0f;
Player_AnimChangeFreeze(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_damage_run, this->modelAnimType));
func_80832698(this, NA_SE_VO_LI_DAMAGE_S);
} else {
this->actor.speedXZ = arg3;
this->linearVelocity = arg3;
this->actor.velocity.y = arg4;
if (ABS(arg5) > 0x4000) {
anim = &gPlayerAnim_link_normal_front_downA;
} else {
anim = &gPlayerAnim_link_normal_back_downA;
}
if ((this->actor.category != ACTORCAT_PLAYER) && (this->actor.colChkInfo.health == 0)) {
func_80832698(this, NA_SE_VO_BL_DOWN);
} else {
func_80832698(this, NA_SE_VO_LI_FALL_L);
}
}
this->hoverBootsTimer = 0;
this->actor.bgCheckFlags &= ~1;
} else {
if ((this->linearVelocity > 4.0f) && !func_8008E9C4(this)) {
this->unk_890 = 20;
Player_RequestRumble(this, 120, 20, 10, 0);
func_80832698(this, NA_SE_VO_LI_DAMAGE_S);
return;
}
sp28 = D_808544B0;
Player_SetupAction(play, this, Player_Action_8084370C, 0);
func_80833C3C(this);
if (this->actor.colChkInfo.damage < 5) {
Player_RequestRumble(this, 120, 20, 10, 0);
} else {
Player_RequestRumble(this, 180, 20, 100, 0);
this->linearVelocity = 23.0f;
sp28 += 4;
}
if (ABS(arg5) <= 0x4000) {
sp28 += 2;
}
if (func_8008E9C4(this)) {
sp28 += 1;
}
anim = *sp28;
func_80832698(this, NA_SE_VO_LI_DAMAGE_S);
}
this->actor.shape.rot.y += arg5;
this->yaw = this->actor.shape.rot.y;
this->actor.world.rot.y = this->actor.shape.rot.y;
if (ABS(arg5) > 0x4000) {
this->actor.shape.rot.y += 0x8000;
}
}
func_80832564(play, this);
this->stateFlags1 |= PLAYER_STATE1_DAMAGED;
if (anim != NULL) {
Player_AnimPlayOnceAdjusted(play, this, anim);
}
}
s32 func_80838144(s32 arg0) {
s32 temp = arg0 - 2;
if ((temp >= 0) && (temp < 2)) {
return temp;
} else {
return -1;
}
}
s32 func_8083816C(s32 arg0) {
return (arg0 == 4) || (arg0 == 7) || (arg0 == 12);
}
void func_8083819C(Player* this, PlayState* play) {
if (this->currentShield == PLAYER_SHIELD_DEKU && (CVarGetInteger("gFireproofDekuShield", 0) == 0)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_SHIELD, this->actor.world.pos.x, this->actor.world.pos.y,
this->actor.world.pos.z, 0, 0, 0, 1, true);
Inventory_DeleteEquipment(play, EQUIP_TYPE_SHIELD);
Message_StartTextbox(play, 0x305F, NULL);
}
}
void func_8083821C(Player* this) {
s32 i;
// clang-format off
for (i = 0; i < PLAYER_BODYPART_MAX; i++) { this->bodyFlameTimers[i] = Rand_S16Offset(0, 200); }
// clang-format on
this->bodyIsBurning = true;
}
void func_80838280(Player* this) {
if (this->actor.colChkInfo.acHitEffect == 1) {
func_8083821C(this);
}
func_80832698(this, NA_SE_VO_LI_FALL_L);
}
void func_808382BC(Player* this) {
if ((this->invincibilityTimer >= 0) && (this->invincibilityTimer < 20)) {
this->invincibilityTimer = 20;
}
}
s32 func_808382DC(Player* this, PlayState* play) {
s32 pad;
s32 sp68 = false;
s32 sp64;
if (this->unk_A86 != 0) {
if (!Player_InBlockingCsMode(play, this)) {
Player_InflictDamageModified(play, -16 * (1 << CVarGetInteger("gVoidDamageMul", 0)), false);
this->unk_A86 = 0;
}
} else {
sp68 = ((Player_GetHeight(this) - 8.0f) < (this->unk_6C4 * this->actor.scale.y));
if (sp68 || (this->actor.bgCheckFlags & 0x100) || (sFloorType == 9) || (this->stateFlags2 & PLAYER_STATE2_FORCED_VOID_OUT)) {
func_80832698(this, NA_SE_VO_LI_DAMAGE_S);
if (sp68) {
Play_TriggerRespawn(play);
Scene_SetTransitionForNextEntrance(play);
} else {
// Special case for getting crushed in Forest Temple's Checkboard Ceiling Hall or Shadow Temple's
// Falling Spike Trap Room, to respawn the player in a specific place
if (((play->sceneNum == SCENE_FOREST_TEMPLE) && (play->roomCtx.curRoom.num == 15)) ||
((play->sceneNum == SCENE_SHADOW_TEMPLE) && (play->roomCtx.curRoom.num == 10))) {
static SpecialRespawnInfo checkboardCeilingRespawn = { { 1992.0f, 403.0f, -3432.0f }, 0 };
static SpecialRespawnInfo fallingSpikeTrapRespawn = { { 1200.0f, -1343.0f, 3850.0f }, 0 };
SpecialRespawnInfo* respawnInfo;
if (play->sceneNum == SCENE_FOREST_TEMPLE) {
respawnInfo = &checkboardCeilingRespawn;
} else {
respawnInfo = &fallingSpikeTrapRespawn;
}
Play_SetupRespawnPoint(play, RESPAWN_MODE_DOWN, 0xDFF);
gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = respawnInfo->pos;
gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = respawnInfo->yaw;
}
Play_TriggerVoidOut(play);
}
func_80832698(this, NA_SE_VO_LI_TAKEN_AWAY);
play->unk_11DE9 = 1;
func_80078884(NA_SE_OC_ABYSS);
} else if ((this->unk_8A1 != 0) && ((this->unk_8A1 >= 2) || (this->invincibilityTimer == 0))) {
u8 sp5C[] = { 2, 1, 1 };
func_80838280(this);
if (this->unk_8A1 == 3) {
this->bodyShockTimer = 40;
}
this->actor.colChkInfo.damage += this->unk_8A0;
func_80837C0C(play, this, sp5C[this->unk_8A1 - 1], this->unk_8A4, this->unk_8A8, this->unk_8A2, 20);
} else {
sp64 = (this->shieldQuad.base.acFlags & AC_BOUNCED) != 0;
//! @bug The second set of conditions here seems intended as a way for Link to "block" hits by rolling.
// However, `Collider.atFlags` is a byte so the flag check at the end is incorrect and cannot work.
// Additionally, `Collider.atHit` can never be set while already colliding as AC, so it's also bugged.
// This behavior was later fixed in MM, most likely by removing both the `atHit` and `atFlags` checks.
if (sp64 || ((this->invincibilityTimer < 0) && (this->cylinder.base.acFlags & AC_HIT) &&
(this->cylinder.info.atHit != NULL) && (this->cylinder.info.atHit->atFlags & 0x20000000))) {
Player_RequestRumble(this, 180, 20, 100, 0);
if (!Player_IsChildWithHylianShield(this)) {
if (this->invincibilityTimer >= 0) {
LinkAnimationHeader* anim;
s32 sp54 = Player_Action_80843188 == this->actionFunc;
if (!func_808332B8(this)) {
Player_SetupAction(play, this, Player_Action_808435C4, 0);
}
if (!(this->av1.actionVar1 = sp54)) {
Player_SetUpperActionFunc(this, func_80834BD4);
if (this->unk_870 < 0.5f) {
anim = D_808543BC[Player_HoldsTwoHandedWeapon(this) &&
!(CVarGetInteger("gShieldTwoHanded", 0) &&
(this->heldItemAction != PLAYER_IA_DEKU_STICK))];
} else {
anim = D_808543B4[Player_HoldsTwoHandedWeapon(this) &&
!(CVarGetInteger("gShieldTwoHanded", 0) &&
(this->heldItemAction != PLAYER_IA_DEKU_STICK))];
}
LinkAnimation_PlayOnce(play, &this->upperSkelAnime, anim);
} else {
Player_AnimPlayOnce(play, this,
D_808543C4[Player_HoldsTwoHandedWeapon(this) &&
!(CVarGetInteger("gShieldTwoHanded", 0) &&
(this->heldItemAction != PLAYER_IA_DEKU_STICK))]);
}
}
if (!(this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER))) {
this->linearVelocity = -18.0f;
this->yaw = this->actor.shape.rot.y;
}
}
if (sp64 && (this->shieldQuad.info.acHitInfo->toucher.effect == 1)) {
func_8083819C(this, play);
}
return 0;
}
if ((this->unk_A87 != 0) || (this->invincibilityTimer > 0) || (this->stateFlags1 & PLAYER_STATE1_DAMAGED) ||
(this->csAction != 0) || (this->meleeWeaponQuads[0].base.atFlags & AT_HIT) ||
(this->meleeWeaponQuads[1].base.atFlags & AT_HIT)) {
return 0;
}
if (this->cylinder.base.acFlags & AC_HIT) {
Actor* ac = this->cylinder.base.ac;
s32 sp4C;
if (ac->flags & ACTOR_FLAG_PLAY_HIT_SFX) {
Player_PlaySfx(this, NA_SE_PL_BODY_HIT);
}
if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) {
sp4C = 0;
} else if (this->actor.colChkInfo.acHitEffect == 2) {
sp4C = 3;
} else if (this->actor.colChkInfo.acHitEffect == 3) {
sp4C = 4;
} else if (this->actor.colChkInfo.acHitEffect == 4) {
sp4C = 1;
} else {
func_80838280(this);
sp4C = 0;
}
func_80837C0C(play, this, sp4C, 4.0f, 5.0f, Actor_WorldYawTowardActor(ac, &this->actor), 20);
} else if (this->invincibilityTimer != 0) {
return 0;
} else {
static u8 D_808544F4[] = { 120, 60 };
s32 sp48 = func_80838144(sFloorType);
if (((this->actor.wallPoly != NULL) &&
SurfaceType_IsWallDamage(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId)) ||
((sp48 >= 0) &&
SurfaceType_IsWallDamage(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId) &&
(this->floorTypeTimer >= D_808544F4[sp48])) ||
((sp48 >= 0) && ((this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger("gSuperTunic", 0) == 0) ||
(this->floorTypeTimer >= D_808544F4[sp48])))) {
this->floorTypeTimer = 0;
this->actor.colChkInfo.damage = 4;
func_80837C0C(play, this, 0, 4.0f, 5.0f, this->actor.shape.rot.y, 20);
} else {
return 0;
}
}
}
}
return 1;
}
void func_80838940(Player* this, LinkAnimationHeader* anim, f32 arg2, PlayState* play, u16 sfxId) {
Player_SetupAction(play, this, Player_Action_8084411C, 1);
if (anim != NULL) {
Player_AnimPlayOnceAdjusted(play, this, anim);
}
this->actor.velocity.y = arg2 * D_808535E8;
this->hoverBootsTimer = 0;
this->actor.bgCheckFlags &= ~1;
func_80832854(this);
func_80832698(this, sfxId);
this->stateFlags1 |= PLAYER_STATE1_JUMPING;
}
void func_808389E8(Player* this, LinkAnimationHeader* anim, f32 arg2, PlayState* play) {
func_80838940(this, anim, arg2, play, NA_SE_VO_LI_SWORD_N);
}
s32 Player_ActionChange_12(Player* this, PlayState* play) {
s32 sp3C;
LinkAnimationHeader* anim;
f32 sp34;
f32 temp;
f32 wallPolyNormalX;
f32 wallPolyNormalZ;
f32 sp24;
if (!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->ledgeClimbType >= 2) &&
(!(this->stateFlags1 & PLAYER_STATE1_IN_WATER) || (this->ageProperties->unk_14 > this->yDistToLedge))) {
sp3C = 0;
if (func_808332B8(this)) {
if (this->actor.yDistToWater < 50.0f) {
if ((this->ledgeClimbType < 2) || (this->yDistToLedge > this->ageProperties->unk_10)) {
return 0;
}
} else if ((this->currentBoots != PLAYER_BOOTS_IRON) || (this->ledgeClimbType > 2)) {
return 0;
}
} else if (!(this->actor.bgCheckFlags & 1) ||
((this->ageProperties->unk_14 <= this->yDistToLedge) && (this->stateFlags1 & PLAYER_STATE1_IN_WATER))) {
return 0;
}
if ((this->actor.wallBgId != BGCHECK_SCENE) && (sTouchedWallFlags & 0x40)) {
if (this->ledgeClimbDelayTimer >= 6) {
this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_CLIMB;
if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) {
sp3C = 1;
}
}
} else if ((this->ledgeClimbDelayTimer >= 6) || CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) {
sp3C = 1;
}
if (sp3C != 0) {
Player_SetupAction(play, this, Player_Action_80845668, 0);
this->stateFlags1 |= PLAYER_STATE1_JUMPING;
sp34 = this->yDistToLedge;
if (this->ageProperties->unk_14 <= sp34) {
anim = &gPlayerAnim_link_normal_250jump_start;
this->linearVelocity = 1.0f;
} else {
wallPolyNormalX = COLPOLY_GET_NORMAL(this->actor.wallPoly->normal.x);
wallPolyNormalZ = COLPOLY_GET_NORMAL(this->actor.wallPoly->normal.z);
sp24 = this->distToInteractWall + 0.5f;
this->stateFlags1 |= PLAYER_STATE1_CLIMBING_LEDGE;
if (func_808332B8(this)) {
anim = &gPlayerAnim_link_swimer_swim_15step_up;
sp34 -= (60.0f * this->ageProperties->unk_08);
this->stateFlags1 &= ~PLAYER_STATE1_IN_WATER;
} else if (this->ageProperties->unk_18 <= sp34) {
anim = &gPlayerAnim_link_normal_150step_up;
sp34 -= (59.0f * this->ageProperties->unk_08);
} else {
anim = &gPlayerAnim_link_normal_100step_up;
sp34 -= (41.0f * this->ageProperties->unk_08);
}
this->actor.shape.yOffset -= sp34 * 100.0f;
this->actor.world.pos.x -= sp24 * wallPolyNormalX;
this->actor.world.pos.y += this->yDistToLedge;
this->actor.world.pos.z -= sp24 * wallPolyNormalZ;
func_80832224(this);
}
this->actor.bgCheckFlags |= 1;
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 1.3f);
AnimationContext_DisableQueue(play);
this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000;
return 1;
}
} else if ((this->actor.bgCheckFlags & 1) && (this->ledgeClimbType == 1) && (this->ledgeClimbDelayTimer >= 3)) {
temp = (this->yDistToLedge * 0.08f) + 5.5f;
func_808389E8(this, &gPlayerAnim_link_normal_jump, temp, play);
this->linearVelocity = 2.5f;
return 1;
}
return 0;
}
void func_80838E70(PlayState* play, Player* this, f32 arg2, s16 arg3) {
Player_SetupAction(play, this, Player_Action_80845CA4, 0);
func_80832440(play, this);
this->av1.actionVar1 = 1;
this->av2.actionVar2 = 1;
this->unk_450.x = (Math_SinS(arg3) * arg2) + this->actor.world.pos.x;
this->unk_450.z = (Math_CosS(arg3) * arg2) + this->actor.world.pos.z;
Player_AnimPlayOnce(play, this, func_80833338(this));
}
void func_80838F18(PlayState* play, Player* this) {
Player_SetupAction(play, this, Player_Action_8084D610, 0);
Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim_wait);
}
void func_80838F5C(PlayState* play, Player* this) {
Player_SetupAction(play, this, Player_Action_8084F88C, 0);
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE | PLAYER_STATE1_FLOOR_DISABLED;
Camera_ChangeSetting(Play_GetCamera(play, 0), CAM_SET_FREE0);
}
s32 func_80838FB8(PlayState* play, Player* this) {
if ((play->transitionTrigger == TRANS_TRIGGER_OFF) && (this->stateFlags1 & PLAYER_STATE1_FLOOR_DISABLED)) {
func_80838F5C(play, this);
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_normal_landing_wait);
func_80832698(this, NA_SE_VO_LI_FALL_S);
func_800788CC(NA_SE_OC_SECRET_WARP_IN);
return 1;
}
return 0;
}
/**
* The actual entrances each "return entrance" value can map to.
* This is used by scenes that are shared between locations, like child/adult Shooting Gallery or Great Fairy Fountains.
*
* This 1D array is split into groups of entrances.
* The start of each group is indexed by `sReturnEntranceGroupIndices` values.
* The resulting groups are then indexed by the spawn value.
*
* The spawn value (`PlayState.spawn`) is set to a different value depending on the entrance used to enter the
* scene, which allows these dynamic "return entrances" to link back to the previous scene.
*
* Note: grottos and normal fairy fountains use `ENTR_RETURN_GROTTO`
*/
s16 sReturnEntranceGroupData[] = {
// ENTR_RETURN_GREAT_FAIRYS_FOUNTAIN_MAGIC
/* 0 */ ENTR_DEATH_MOUNTAIN_TRAIL_4, // from Magic Fairy Fountain
/* 1 */ ENTR_DEATH_MOUNTAIN_CRATER_3, // from Double Magic Fairy Fountain
/* 2 */ ENTR_HYRULE_CASTLE_2, // from Double Defense Fairy Fountain (as adult)
// ENTR_RETURN_2
/* 3 */ ENTR_KAKARIKO_VILLAGE_9, // from Potion Shop in Kakariko
/* 4 */ ENTR_MARKET_DAY_5, // from Potion Shop in Market
// ENTR_RETURN_BAZAAR
/* 5 */ ENTR_KAKARIKO_VILLAGE_3,
/* 6 */ ENTR_MARKET_DAY_6,
// ENTR_RETURN_4
/* 7 */ ENTR_KAKARIKO_VILLAGE_11, // from House of Skulltulas
/* 8 */ ENTR_BACK_ALLEY_DAY_2, // from Bombchu Shop
// ENTR_RETURN_SHOOTING_GALLERY
/* 9 */ ENTR_KAKARIKO_VILLAGE_10,
/* 10 */ ENTR_MARKET_DAY_8,
// ENTR_RETURN_GREAT_FAIRYS_FOUNTAIN_SPELLS
/* 11 */ ENTR_ZORAS_FOUNTAIN_5, // from Farores Wind Fairy Fountain
/* 12 */ ENTR_HYRULE_CASTLE_2, // from Dins Fire Fairy Fountain (as child)
/* 13 */ ENTR_DESERT_COLOSSUS_7, // from Nayrus Love Fairy Fountain
};
/**
* The values are indices into `sReturnEntranceGroupData` marking the start of each group
*/
u8 sReturnEntranceGroupIndices[] = {
11, // ENTR_RETURN_GREAT_FAIRYS_FOUNTAIN_SPELLS
9, // ENTR_RETURN_SHOOTING_GALLERY
3, // ENTR_RETURN_2
5, // ENTR_RETURN_BAZAAR
7, // ENTR_RETURN_4
0, // ENTR_RETURN_GREAT_FAIRYS_FOUNTAIN_MAGIC
};
s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* poly, u32 bgId) {
s32 exitIndex;
s32 temp;
s32 sp34;
f32 speedXZ;
s32 yaw;
if (this->actor.category == ACTORCAT_PLAYER) {
exitIndex = 0;
if (!(this->stateFlags1 & PLAYER_STATE1_DEAD) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (this->csAction == 0) &&
!(this->stateFlags1 & PLAYER_STATE1_LOADING) &&
(((poly != NULL) && (exitIndex = SurfaceType_GetSceneExitIndex(&play->colCtx, poly, bgId), exitIndex != 0)) ||
(func_8083816C(sFloorType) && (this->floorProperty == 12)))) {
sp34 = this->unk_A84 - (s32)this->actor.world.pos.y;
if (!(this->stateFlags1 & (PLAYER_STATE1_ON_HORSE | PLAYER_STATE1_IN_WATER | PLAYER_STATE1_IN_CUTSCENE)) &&
!(this->actor.bgCheckFlags & 1) && (sp34 < 100) && (sYDistToFloor > 100.0f)) {
return 0;
}
if (exitIndex == 0) {
Play_TriggerVoidOut(play);
Scene_SetTransitionForNextEntrance(play);
} else {
play->nextEntranceIndex = play->setupExitList[exitIndex - 1];
// Main override for entrance rando and entrance skips
if (IS_RANDO) {
play->nextEntranceIndex = Entrance_OverrideNextIndex(play->nextEntranceIndex);
}
if (play->nextEntranceIndex == ENTR_RETURN_GROTTO) {
gSaveContext.respawnFlag = 2;
play->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_RETURN].entranceIndex;
play->transitionType = TRANS_TYPE_FADE_WHITE;
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE;
} else if (play->nextEntranceIndex >= ENTR_RETURN_YOUSEI_IZUMI_YOKO) {
// handle dynamic exits
if (IS_RANDO) {
play->nextEntranceIndex = Entrance_OverrideDynamicExit(sReturnEntranceGroupIndices[play->nextEntranceIndex - ENTR_RETURN_YOUSEI_IZUMI_YOKO] + play->curSpawn);
} else {
play->nextEntranceIndex =
sReturnEntranceGroupData[sReturnEntranceGroupIndices[play->nextEntranceIndex - ENTR_RETURN_YOUSEI_IZUMI_YOKO] + play->curSpawn];
}
Scene_SetTransitionForNextEntrance(play);
} else {
// In Entrance rando, if our respawnFlag is set for a grotto return, we don't want the void out to happen
if (SurfaceType_GetSlope(&play->colCtx, poly, bgId) == 2 &&
(!IS_RANDO || (Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES) && gSaveContext.respawnFlag != 2))) {
gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = play->nextEntranceIndex;
Play_TriggerVoidOut(play);
gSaveContext.respawnFlag = -2;
}
gSaveContext.retainWeatherMode = 1;
Scene_SetTransitionForNextEntrance(play);
}
play->transitionTrigger = TRANS_TRIGGER_START;
}
if (!(this->stateFlags1 & (PLAYER_STATE1_ON_HORSE | PLAYER_STATE1_IN_CUTSCENE)) &&
!(this->stateFlags2 & PLAYER_STATE2_CRAWLING) && !func_808332B8(this) &&
(temp = func_80041D4C(&play->colCtx, poly, bgId), (temp != 10)) &&
((sp34 < 100) || (this->actor.bgCheckFlags & 1))) {
if (temp == 11) {
func_800788CC(NA_SE_OC_SECRET_HOLE_OUT);
func_800F6964(5);
gSaveContext.seqId = (u8)NA_BGM_DISABLED;
gSaveContext.natureAmbienceId = NATURE_ID_DISABLED;
} else {
speedXZ = this->linearVelocity;
if (speedXZ < 0.0f) {
this->actor.world.rot.y += 0x8000;
speedXZ = -speedXZ;
}
if (speedXZ > R_RUN_SPEED_LIMIT / 100.0f) {
gSaveContext.entranceSpeed = R_RUN_SPEED_LIMIT / 100.0f;
} else {
gSaveContext.entranceSpeed = speedXZ;
}
if (sConveyorSpeed != 0) {
yaw = sConveyorYaw;
} else {
yaw = this->actor.world.rot.y;
}
func_80838E70(play, this, 400.0f, yaw);
}
} else {
if (!(this->actor.bgCheckFlags & 1)) {
Player_ZeroSpeedXZ(this);
}
}
this->stateFlags1 |= PLAYER_STATE1_LOADING | PLAYER_STATE1_IN_CUTSCENE;
func_80835E44(play, 0x2F);
return 1;
} else {
if (play->transitionTrigger == TRANS_TRIGGER_OFF) {
if ((this->actor.world.pos.y < -4000.0f) ||
(((this->floorProperty == 5) || (this->floorProperty == 12)) &&
((sYDistToFloor < 100.0f) || (this->fallDistance > 400.0f) ||
((play->sceneNum != SCENE_SHADOW_TEMPLE) && (this->fallDistance > 200.0f)))) ||
((play->sceneNum == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) && (this->fallDistance > 320.0f))) {
if (this->actor.bgCheckFlags & 1) {
if (this->floorProperty == 5) {
Play_TriggerRespawn(play);
} else {
Play_TriggerVoidOut(play);
}
play->transitionType = TRANS_TYPE_FADE_BLACK_FAST;
func_80078884(NA_SE_OC_ABYSS);
} else {
func_80838F5C(play, this);
this->av2.actionVar2 = 9999;
if (this->floorProperty == 5) {
this->av1.actionVar1 = -1;
} else {
this->av1.actionVar1 = 1;
}
}
}
this->unk_A84 = this->actor.world.pos.y;
}
}
}
return 0;
}
/**
* Gets a position relative to player's yaw.
* An offset is applied to the provided base position in the direction of shape y rotation.
* The resulting position is stored in `dest`
*/
void Player_GetRelativePosition(Player* this, Vec3f* base, Vec3f* offset, Vec3f* dest) {
f32 cos = Math_CosS(this->actor.shape.rot.y);
f32 sin = Math_SinS(this->actor.shape.rot.y);
dest->x = base->x + ((offset->x * cos) + (offset->z * sin));
dest->y = base->y + offset->y;
dest->z = base->z + ((offset->z * cos) - (offset->x * sin));
}
Actor* Player_SpawnFairy(PlayState* play, Player* this, Vec3f* arg2, Vec3f* arg3, s32 type) {
Vec3f pos;
Player_GetRelativePosition(this, arg2, arg3, &pos);
return Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, pos.x, pos.y, pos.z, 0, 0, 0, type, true);
}
f32 func_808396F4(PlayState* play, Player* this, Vec3f* arg2, Vec3f* arg3, CollisionPoly** arg4, s32* arg5) {
Player_GetRelativePosition(this, &this->actor.world.pos, arg2, arg3);
return BgCheck_EntityRaycastFloor3(&play->colCtx, arg4, arg5, arg3);
}
f32 func_8083973C(PlayState* play, Player* this, Vec3f* arg2, Vec3f* arg3) {
CollisionPoly* sp24;
s32 sp20;
return func_808396F4(play, this, arg2, arg3, &sp24, &sp20);
}
/**
* Checks if a line between the player's position and the provided `offset` intersect a wall.
*
* Point A of the line is at player's world position offset by the height provided in `offset`.
* Point B of the line is at player's world position offset by the entire `offset` vector.
* Point A and B are always at the same height, meaning this is a horizontal line test.
*/
s32 Player_PosVsWallLineTest(PlayState* play, Player* this, Vec3f* offset, CollisionPoly** wallPoly, s32* bgId,
Vec3f* posResult) {
Vec3f posA;
Vec3f posB;
posA.x = this->actor.world.pos.x;
posA.y = this->actor.world.pos.y + offset->y;
posA.z = this->actor.world.pos.z;
Player_GetRelativePosition(this, &this->actor.world.pos, offset, &posB);
return BgCheck_EntityLineTest1(&play->colCtx, &posA, &posB, posResult, wallPoly, true, false, false, true, bgId);
}
s32 Player_ActionChange_1(Player* this, PlayState* play) {
DoorShutter* doorShutter;
EnDoor* door; // Can also be DoorKiller*
s32 doorDirection;
f32 sp78;
f32 sp74;
Actor* doorActor;
f32 sp6C;
s32 pad3;
s32 frontRoom;
Actor* attachedActor;
LinkAnimationHeader* sp5C;
CollisionPoly* groundPoly;
Vec3f checkPos;
if ((this->doorType != PLAYER_DOORTYPE_NONE) &&
(!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) ||
((this->heldActor != NULL) && (this->heldActor->id == ACTOR_EN_RU1)))) {
// Disable doors in Boss Rush so the player can't leave the boss rooms backwards.
if ((CHECK_BTN_ALL(sControlInput->press.button, BTN_A) || (Player_Action_8084F9A0 == this->actionFunc)) && !IS_BOSS_RUSH) {
doorActor = this->doorActor;
if (this->doorType <= PLAYER_DOORTYPE_AJAR) {
doorActor->textId = 0xD0;
Player_StartTalking(play, doorActor);
return 0;
}
doorDirection = this->doorDirection;
sp78 = Math_CosS(doorActor->shape.rot.y);
sp74 = Math_SinS(doorActor->shape.rot.y);
if (this->doorType == PLAYER_DOORTYPE_SLIDING) {
doorShutter = (DoorShutter*)doorActor;
this->yaw = doorShutter->dyna.actor.home.rot.y;
if (doorDirection > 0) {
this->yaw -= 0x8000;
}
this->actor.shape.rot.y = this->yaw;
if (this->linearVelocity <= 0.0f) {
this->linearVelocity = 0.1f;
}
func_80838E70(play, this, 50.0f, this->actor.shape.rot.y);
this->av1.actionVar1 = 0;
this->unk_447 = this->doorType;
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
this->unk_450.x = this->actor.world.pos.x + ((doorDirection * 20.0f) * sp74);
this->unk_450.z = this->actor.world.pos.z + ((doorDirection * 20.0f) * sp78);
this->unk_45C.x = this->actor.world.pos.x + ((doorDirection * -120.0f) * sp74);
this->unk_45C.z = this->actor.world.pos.z + ((doorDirection * -120.0f) * sp78);
doorShutter->unk_164 = 1;
func_80832224(this);
if (this->doorTimer != 0) {
this->av2.actionVar2 = 0;
Player_AnimChangeOnceMorph(play, this, func_80833338(this));
this->skelAnime.endFrame = 0.0f;
} else {
this->linearVelocity = 0.1f;
}
if (doorShutter->dyna.actor.category == ACTORCAT_DOOR) {
this->doorBgCamIndex = play->transiActorCtx.list[(u16)doorShutter->dyna.actor.params >> 10]
.sides[(doorDirection > 0) ? 0 : 1]
.effects;
Actor_DisableLens(play);
}
} else {
// This actor can be either EnDoor or DoorKiller.
// Don't try to access any struct vars other than `animStyle` and `playerIsOpening`! These two variables
// are common across the two actors' structs however most other variables are not!
door = (EnDoor*)doorActor;
door->animStyle = (doorDirection < 0.0f) ? (LINK_IS_ADULT ? KNOB_ANIM_ADULT_L : KNOB_ANIM_CHILD_L)
: (LINK_IS_ADULT ? KNOB_ANIM_ADULT_R : KNOB_ANIM_CHILD_R);
if (door->animStyle == KNOB_ANIM_ADULT_L) {
sp5C = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_doorA_free, this->modelAnimType);
} else if (door->animStyle == KNOB_ANIM_CHILD_L) {
sp5C = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_doorA, this->modelAnimType);
} else if (door->animStyle == KNOB_ANIM_ADULT_R) {
sp5C = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_doorB_free, this->modelAnimType);
} else {
sp5C = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_doorB, this->modelAnimType);
}
Player_SetupAction(play, this, Player_Action_80845EF8, 0);
func_80832528(play, this);
if (doorDirection < 0) {
this->actor.shape.rot.y = doorActor->shape.rot.y;
} else {
this->actor.shape.rot.y = doorActor->shape.rot.y - 0x8000;
}
this->yaw = this->actor.shape.rot.y;
sp6C = (doorDirection * 22.0f);
this->actor.world.pos.x = doorActor->world.pos.x + sp6C * sp74;
this->actor.world.pos.z = doorActor->world.pos.z + sp6C * sp78;
func_8083328C(play, this, sp5C);
if (this->doorTimer != 0) {
this->skelAnime.endFrame = 0.0f;
}
func_80832224(this);
Player_AnimReplaceApplyFlags(play, this, 0x28F);
if (doorActor->parent != NULL) {
doorDirection = -doorDirection;
}
door->playerIsOpening = 1;
if (this->doorType != PLAYER_DOORTYPE_FAKE) {
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
Actor_DisableLens(play);
if (((doorActor->params >> 7) & 7) == 3) {
checkPos.x = doorActor->world.pos.x - (sp6C * sp74);
checkPos.y = doorActor->world.pos.y + 10.0f;
checkPos.z = doorActor->world.pos.z - (sp6C * sp78);
BgCheck_EntityRaycastFloor1(&play->colCtx, &groundPoly, &checkPos);
//! @bug groundPoly's bgId is not guaranteed to be BGCHECK_SCENE
if (Player_HandleExitsAndVoids(play, this, groundPoly, BGCHECK_SCENE)) {
gSaveContext.entranceSpeed = 2.0f;
gSaveContext.entranceSound = NA_SE_OC_DOOR_OPEN;
}
} else {
Camera_ChangeDoorCam(Play_GetCamera(play, 0), doorActor,
play->transiActorCtx.list[(u16)doorActor->params >> 10]
.sides[(doorDirection > 0) ? 0 : 1]
.effects,
0, 38.0f * D_808535EC, 26.0f * D_808535EC, 10.0f * D_808535EC);
}
}
}
if ((this->doorType != PLAYER_DOORTYPE_FAKE) && (doorActor->category == ACTORCAT_DOOR)) {
frontRoom = play->transiActorCtx.list[(u16)doorActor->params >> 10]
.sides[(doorDirection > 0) ? 0 : 1]
.room;
if ((frontRoom >= 0) && (frontRoom != play->roomCtx.curRoom.num)) {
func_8009728C(play, &play->roomCtx, frontRoom);
}
}
doorActor->room = play->roomCtx.curRoom.num;
if (((attachedActor = doorActor->child) != NULL) || ((attachedActor = doorActor->parent) != NULL)) {
attachedActor->room = play->roomCtx.curRoom.num;
}
return 1;
}
}
return 0;
}
void func_80839E88(Player* this, PlayState* play) {
LinkAnimationHeader* anim;
Player_SetupAction(play, this, Player_Action_80840450, 1);
if (this->unk_870 < 0.5f) {
anim = func_808334E4(this);
this->unk_870 = 0.0f;
} else {
anim = func_80833528(this);
this->unk_870 = 1.0f;
}
this->unk_874 = this->unk_870;
Player_AnimPlayLoop(play, this, anim);
this->yaw = this->actor.shape.rot.y;
}
void func_80839F30(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_808407CC, 1);
Player_AnimChangeOnceMorph(play, this, func_80833338(this));
this->yaw = this->actor.shape.rot.y;
}
void func_80839F90(Player* this, PlayState* play) {
if (func_8008E9C4(this)) {
func_80839E88(this, play);
} else if (func_80833B2C(this)) {
func_80839F30(this, play);
} else {
func_80853080(this, play);
}
}
void func_80839FFC(Player* this, PlayState* play) {
PlayerActionFunc actionFunc;
if (func_8008E9C4(this)) {
actionFunc = Player_Action_80840450;
} else if (func_80833B2C(this)) {
actionFunc = Player_Action_808407CC;
} else {
actionFunc = Player_Action_80840BC8;
}
Player_SetupAction(play, this, actionFunc, 1);
}
void func_8083A060(Player* this, PlayState* play) {
func_80839FFC(this, play);
if (func_8008E9C4(this)) {
this->av2.actionVar2 = 1;
}
}
void func_8083A098(Player* this, LinkAnimationHeader* anim, PlayState* play) {
func_8083A060(this, play);
func_8083328C(play, this, anim);
}
s32 func_8083A0D4(Player* this) {
return (this->interactRangeActor != NULL) && (this->heldActor == NULL);
}
void func_8083A0F4(PlayState* play, Player* this) {
if (func_8083A0D4(this)) {
Actor* interactRangeActor = this->interactRangeActor;
s32 interactActorId = interactRangeActor->id;
if (interactActorId == ACTOR_BG_TOKI_SWD) {
this->interactRangeActor->parent = &this->actor;
Player_SetupAction(play, this, Player_Action_8084F608, 0);
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
sMaskMemory = PLAYER_MASK_NONE;
} else {
LinkAnimationHeader* anim;
if (interactActorId == ACTOR_BG_HEAVY_BLOCK) {
Player_SetupAction(play, this, Player_Action_80846120, 0);
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
anim = &gPlayerAnim_link_normal_heavy_carry;
} else if ((interactActorId == ACTOR_EN_ISHI) && ((interactRangeActor->params & 0xF) == 1)) {
Player_SetupAction(play, this, Player_Action_80846260, 0);
anim = &gPlayerAnim_link_silver_carry;
} else if (((interactActorId == ACTOR_EN_BOMBF) || (interactActorId == ACTOR_EN_KUSA)) &&
(Player_GetStrength() <= PLAYER_STR_NONE)) {
Player_SetupAction(play, this, Player_Action_80846408, 0);
this->actor.world.pos.x =
(Math_SinS(interactRangeActor->yawTowardsPlayer) * 20.0f) + interactRangeActor->world.pos.x;
this->actor.world.pos.z =
(Math_CosS(interactRangeActor->yawTowardsPlayer) * 20.0f) + interactRangeActor->world.pos.z;
this->yaw = this->actor.shape.rot.y = interactRangeActor->yawTowardsPlayer + 0x8000;
anim = &gPlayerAnim_link_normal_nocarry_free;
} else {
Player_SetupAction(play, this, Player_Action_80846050, 0);
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_carryB, this->modelAnimType);
}
// Same actor is used for small and large silver rocks, use actor params to identify large ones
bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1;
if (CVarGetInteger("gFasterHeavyBlockLift", 0) && (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) {
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 5.0f);
} else {
LinkAnimation_PlayOnce(play, &this->skelAnime, anim);
}
}
} else {
func_80839F90(this, play);
this->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD;
}
}
void func_8083A2F8(PlayState* play, Player* this) {
func_80835DAC(play, this, Player_Action_8084B530, 0);
this->stateFlags1 |= PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_IN_CUTSCENE;
if (this->actor.textId != 0) {
Message_StartTextbox(play, this->actor.textId, this->targetActor);
this->unk_664 = this->targetActor;
}
}
void func_8083A360(PlayState* play, Player* this) {
func_80835DAC(play, this, Player_Action_8084CC98, 0);
}
void func_8083A388(PlayState* play, Player* this) {
Player_SetupAction(play, this, Player_Action_8084B78C, 0);
}
void func_8083A3B0(PlayState* play, Player* this) {
s32 sp1C = this->av2.actionVar2;
s32 sp18 = this->av1.actionVar1;
func_80835DAC(play, this, Player_Action_8084BF1C, 0);
this->actor.velocity.y = 0.0f;
this->av2.actionVar2 = sp1C;
this->av1.actionVar1 = sp18;
}
void func_8083A40C(PlayState* play, Player* this) {
func_80835DAC(play, this, Player_Action_8084C760, 0);
}
void func_8083A434(PlayState* play, Player* this) {
func_80835DAC(play, this, Player_Action_8084E6D4, 0);
this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_IN_CUTSCENE;
if (this->getItemId == GI_HEART_CONTAINER_2) {
this->av2.actionVar2 = 20;
} else if (this->getItemId >= 0 || (this->getItemEntry.objectId != OBJECT_INVALID && this->getItemEntry.getItemId >= 0)) {
this->av2.actionVar2 = 1;
} else {
this->getItemId = -this->getItemId;
this->getItemEntry.getItemId = -this->getItemEntry.getItemId;
}
}
s32 func_8083A4A8(Player* this, PlayState* play) {
s16 yawDiff;
LinkAnimationHeader* anim;
f32 temp;
yawDiff = this->yaw - this->actor.shape.rot.y;
if ((ABS(yawDiff) < 0x1000) && (this->linearVelocity > 4.0f)) {
anim = &gPlayerAnim_link_normal_run_jump;
} else {
anim = &gPlayerAnim_link_normal_jump;
}
if (this->linearVelocity > (IREG(66) / 100.0f)) {
temp = IREG(67) / 100.0f;
} else {
temp = (IREG(68) / 100.0f) + ((IREG(69) * this->linearVelocity) / 1000.0f);
}
func_80838940(this, anim, temp, play, NA_SE_VO_LI_AUTO_JUMP);
this->av2.actionVar2 = 1;
return 1;
}
void func_8083A5C4(PlayState* play, Player* this, CollisionPoly* arg2, f32 arg3, LinkAnimationHeader* anim) {
f32 nx = COLPOLY_GET_NORMAL(arg2->normal.x);
f32 nz = COLPOLY_GET_NORMAL(arg2->normal.z);
Player_SetupAction(play, this, Player_Action_8084BBE4, 0);
func_80832564(play, this);
Player_AnimPlayOnce(play, this, anim);
this->actor.world.pos.x -= (arg3 + 1.0f) * nx;
this->actor.world.pos.z -= (arg3 + 1.0f) * nz;
this->actor.shape.rot.y = this->yaw = Math_Atan2S(nz, nx);
func_80832224(this);
Player_SkelAnimeResetPrevTranslRot(this);
}
s32 func_8083A6AC(Player* this, PlayState* play) {
CollisionPoly* sp84;
s32 sp80;
Vec3f sp74;
Vec3f sp68;
f32 temp1;
//! @bug `floorPitch` and `floorPitchAlt` are cleared to 0 before this function is called, because the player
//! left the ground. The angles will always be zero and therefore will always pass these checks.
//! The intention seems to be to prevent ledge hanging or vine grabbing when walking off of a steep enough slope.
if ((this->actor.yDistToWater < -80.0f) && (ABS(this->floorPitch) < 2730) && (ABS(this->floorPitchAlt) < 2730)) {
sp74.x = this->actor.prevPos.x - this->actor.world.pos.x;
sp74.z = this->actor.prevPos.z - this->actor.world.pos.z;
temp1 = sqrtf(SQ(sp74.x) + SQ(sp74.z));
if (temp1 != 0.0f) {
temp1 = 5.0f / temp1;
} else {
temp1 = 0.0f;
}
sp74.x = this->actor.prevPos.x + (sp74.x * temp1);
sp74.y = this->actor.world.pos.y;
sp74.z = this->actor.prevPos.z + (sp74.z * temp1);
if (BgCheck_EntityLineTest1(&play->colCtx, &this->actor.world.pos, &sp74, &sp68, &sp84, true, false, false,
true, &sp80) &&
((ABS(sp84->normal.y) < 600) || (CVarGetInteger("gClimbEverything", 0) != 0))) {
f32 nx = COLPOLY_GET_NORMAL(sp84->normal.x);
f32 ny = COLPOLY_GET_NORMAL(sp84->normal.y);
f32 nz = COLPOLY_GET_NORMAL(sp84->normal.z);
f32 sp54;
s32 sp50;
sp54 = Math3D_UDistPlaneToPos(nx, ny, nz, sp84->dist, &this->actor.world.pos);
sp50 = sPrevFloorProperty == 6;
if (!sp50 && (func_80041DB8(&play->colCtx, sp84, sp80) & 8)) {
sp50 = 1;
}
func_8083A5C4(play, this, sp84, sp54,
sp50 ? &gPlayerAnim_link_normal_Fclimb_startB : &gPlayerAnim_link_normal_fall);
if (sp50) {
func_80836898(play, this, func_8083A3B0);
this->yaw += 0x8000;
this->actor.shape.rot.y = this->yaw;
this->stateFlags1 |= PLAYER_STATE1_CLIMBING_LADDER;
Player_AnimReplaceApplyFlags(play, this, 0x9F);
this->av2.actionVar2 = -1;
this->av1.actionVar1 = sp50;
} else {
this->stateFlags1 |= PLAYER_STATE1_HANGING_OFF_LEDGE;
this->stateFlags1 &= ~PLAYER_STATE1_TARGET_NOTHING;
}
Player_PlaySfx(this, NA_SE_PL_SLIPDOWN);
func_80832698(this, NA_SE_VO_LI_HANG);
return 1;
}
}
return 0;
}
void func_8083A9B8(Player* this, LinkAnimationHeader* anim, PlayState* play) {
Player_SetupAction(play, this, Player_Action_8084BDFC, 0);
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 1.3f);
}
static Vec3f D_8085451C = { 0.0f, 0.0f, 100.0f };
void func_8083AA10(Player* this, PlayState* play) {
s32 sp5C;
CollisionPoly* sp58;
s32 sp54;
WaterBox* sp50;
Vec3f sp44;
f32 sp40;
f32 sp3C;
this->fallDistance = this->fallStartHeight - (s32)this->actor.world.pos.y;
if (!(this->stateFlags1 & (PLAYER_STATE1_IN_WATER | PLAYER_STATE1_IN_CUTSCENE)) && !(this->actor.bgCheckFlags & 1)) {
if (!func_80838FB8(play, this)) {
if (sPrevFloorProperty == 8) {
this->actor.world.pos.x = this->actor.prevPos.x;
this->actor.world.pos.z = this->actor.prevPos.z;
return;
}
if (!(this->stateFlags3 & PLAYER_STATE3_MIDAIR) && !(this->skelAnime.moveFlags & 0x80) &&
(Player_Action_8084411C != this->actionFunc) && (Player_Action_80844A44 != this->actionFunc)) {
if ((sPrevFloorProperty == 7) || (this->meleeWeaponState != 0)) {
Math_Vec3f_Copy(&this->actor.world.pos, &this->actor.prevPos);
Player_ZeroSpeedXZ(this);
return;
}
if (this->hoverBootsTimer != 0) {
this->actor.velocity.y = 1.0f;
sPrevFloorProperty = 9;
return;
}
sp5C = (s16)(this->yaw - this->actor.shape.rot.y);
Player_SetupAction(play, this, Player_Action_8084411C, 1);
func_80832440(play, this);
this->floorSfxOffset = this->prevFloorSfxOffset;
if ((this->actor.bgCheckFlags & 4) && !(this->stateFlags1 & PLAYER_STATE1_IN_WATER) && (sPrevFloorProperty != 6) &&
(sPrevFloorProperty != 9) && (sYDistToFloor > 20.0f) && (this->meleeWeaponState == 0) && (ABS(sp5C) < 0x2000) &&
(this->linearVelocity > 3.0f)) {
if ((sPrevFloorProperty == 11) && !(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) {
sp40 = func_808396F4(play, this, &D_8085451C, &sp44, &sp58, &sp54);
sp3C = this->actor.world.pos.y;
if (WaterBox_GetSurface1(play, &play->colCtx, sp44.x, sp44.z, &sp3C, &sp50) &&
((sp3C - sp40) > 50.0f)) {
func_808389E8(this, &gPlayerAnim_link_normal_run_jump_water_fall, 6.0f, play);
Player_SetupAction(play, this, Player_Action_80844A44, 0);
return;
}
}
func_8083A4A8(this, play);
return;
}
if ((sPrevFloorProperty == 9) || (sYDistToFloor <= this->ageProperties->unk_34) ||
!func_8083A6AC(this, play)) {
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_normal_landing_wait);
return;
}
}
}
} else {
this->fallStartHeight = this->actor.world.pos.y;
}
}
s32 func_8083AD4C(PlayState* play, Player* this) {
s32 cameraMode;
if (this->unk_6AD == 2) {
if (func_8002DD6C(this)) {
bool shouldUseBowCamera = LINK_IS_ADULT;
if(CVarGetInteger("gBowSlingShotAmmoFix", 0)){
shouldUseBowCamera = this->heldItemAction != PLAYER_IA_SLINGSHOT;
}
cameraMode = shouldUseBowCamera ? CAM_MODE_BOWARROW : CAM_MODE_SLINGSHOT;
} else {
cameraMode = CAM_MODE_BOOMERANG;
}
} else {
cameraMode = CAM_MODE_FIRSTPERSON;
}
return Camera_ChangeMode(Play_GetCamera(play, 0), cameraMode);
}
/**
* If appropriate, setup action for performing a `csAction`
*
* @return true if a `csAction` is started, false if not
*/
s32 Player_StartCsAction(PlayState* play, Player* this) {
// unk_6AD will get set to 3 in `Player_UpdateCommon` if `this->csAction` is non-zero
// (with a special case for `PLAYER_CSACTION_7`)
if (this->unk_6AD == 3) {
Player_SetupAction(play, this, Player_Action_CsAction, 0);
if (this->doorBgCamIndex != 0) {
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
}
func_80832318(this);
return 1;
} else {
return 0;
}
}
void func_8083AE40(Player* this, s16 objectId) {
s32 pad;
size_t size;
if (objectId != OBJECT_INVALID) {
this->giObjectLoading = true;
osCreateMesgQueue(&this->giObjectLoadQueue, &this->giObjectLoadMsg, 1);
size = gObjectTable[objectId].vromEnd - gObjectTable[objectId].vromStart;
LOG_HEX("size", size);
assert(size <= 1024 * 8);
DmaMgr_SendRequest2(&this->giObjectDmaRequest, (uintptr_t)this->giObjectSegment,
gObjectTable[objectId].vromStart, size, 0, &this->giObjectLoadQueue, OS_MESG_PTR(NULL),
__FILE__, __LINE__);
}
}
void func_8083AF44(PlayState* play, Player* this, s32 magicSpell) {
func_80835DE4(play, this, Player_Action_808507F4, 0);
this->av1.actionVar1 = magicSpell - 3;
//! @bug `MAGIC_CONSUME_WAIT_PREVIEW` is not guaranteed to succeed.
//! Ideally, the return value of `Magic_RequestChange` should be checked before allowing the process of
//! using a spell to continue. If the magic state change request fails, `gSaveContext.magicTarget` will
//! never be set correctly.
//! When `MAGIC_STATE_CONSUME_SETUP` is set in `Player_Action_808507F4`, magic will eventually be
//! consumed to a stale target value. If that stale target value is higher than the current
//! magic value, it will be consumed to zero.
Magic_RequestChange(play, sMagicSpellCosts[magicSpell], MAGIC_CONSUME_WAIT_PREVIEW);
u8 isFastFarores = CVarGetInteger("gFastFarores", 0) && this->itemAction == PLAYER_IA_FARORES_WIND;
if (isFastFarores) {
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, &gPlayerAnim_link_magic_tame, 0.83f * 2);
return;
} else {
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, &gPlayerAnim_link_magic_tame, 0.83f);
}
if (magicSpell == 5) {
this->subCamId = OnePointCutscene_Init(play, 1100, -101, NULL, MAIN_CAM);
} else {
func_80835EA4(play, 10);
}
}
void func_8083B010(Player* this) {
this->actor.focus.rot.x = this->actor.focus.rot.z = this->unk_6B6 = this->unk_6B8 = this->unk_6BA = this->unk_6BC =
this->unk_6BE = this->unk_6C0 = 0;
this->actor.focus.rot.y = this->actor.shape.rot.y;
}
static u8 D_80854528[] = {
GI_LETTER_ZELDA, GI_WEIRD_EGG, GI_CHICKEN, GI_BEAN, GI_POCKET_EGG, GI_POCKET_CUCCO,
GI_COJIRO, GI_ODD_MUSHROOM, GI_ODD_POTION, GI_SAW, GI_SWORD_BROKEN, GI_PRESCRIPTION,
GI_FROG, GI_EYEDROPS, GI_CLAIM_CHECK, GI_MASK_SKULL, GI_MASK_SPOOKY, GI_MASK_KEATON,
GI_MASK_BUNNY, GI_MASK_TRUTH, GI_MASK_GORON, GI_MASK_ZORA, GI_MASK_GERUDO, GI_LETTER_RUTO,
GI_LETTER_RUTO, GI_LETTER_RUTO, GI_LETTER_RUTO, GI_LETTER_RUTO, GI_LETTER_RUTO,
};
static LinkAnimationHeader* D_80854548[] = {
&gPlayerAnim_link_normal_give_other,
&gPlayerAnim_link_bottle_read,
&gPlayerAnim_link_normal_take_out,
};
s32 Player_ActionChange_13(Player* this, PlayState* play) {
s32 sp2C;
s32 sp28;
GetItemEntry giEntry;
Actor* targetActor;
if ((this->unk_6AD != 0) &&
(func_808332B8(this) || (this->actor.bgCheckFlags & 1) || (this->stateFlags1 & PLAYER_STATE1_ON_HORSE))) {
if (!Player_StartCsAction(play, this)) {
if (this->unk_6AD == 4) {
sp2C = Player_ActionToMagicSpell(this, this->itemAction);
if (sp2C >= 0) {
if ((sp2C != 3) || (gSaveContext.respawn[RESPAWN_MODE_TOP].data <= 0)) {
func_8083AF44(play, this, sp2C);
} else {
Player_SetupAction(play, this, Player_Action_8085063C, 1);
this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
Player_AnimPlayOnce(play, this, func_80833338(this));
func_80835EA4(play, 4);
}
func_80832224(this);
return 1;
}
sp2C = this->itemAction - PLAYER_IA_ZELDAS_LETTER;
if ((sp2C >= 0) ||
(sp28 = Player_ActionToBottle(this, this->itemAction) - 1,
((sp28 >= 0) && (sp28 < 6) &&
((this->itemAction > PLAYER_IA_BOTTLE_POE) ||
((this->targetActor != NULL) &&
(((this->itemAction == PLAYER_IA_BOTTLE_POE) && (this->exchangeItemId == EXCH_ITEM_POE)) ||
(this->exchangeItemId == EXCH_ITEM_BLUE_FIRE))))))) {
if ((play->actorCtx.titleCtx.delayTimer == 0) && (play->actorCtx.titleCtx.alpha == 0)) {
func_80835DE4(play, this, Player_Action_8084F104, 0);
if (sp2C >= 0) {
if (this->getItemEntry.objectId == OBJECT_INVALID) {
giEntry = ItemTable_Retrieve(D_80854528[sp2C]);
} else {
giEntry = this->getItemEntry;
}
func_8083AE40(this, giEntry.objectId);
}
this->stateFlags1 |= PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
if (sp2C >= 0) {
sp2C = sp2C + 1;
} else {
sp2C = sp28 + 0x18;
}
targetActor = this->targetActor;
if ((targetActor != NULL) &&
((this->exchangeItemId == sp2C) || (this->exchangeItemId == EXCH_ITEM_BLUE_FIRE) ||
((this->exchangeItemId == EXCH_ITEM_POE) &&
(this->itemAction == PLAYER_IA_BOTTLE_BIG_POE)) ||
((this->exchangeItemId == EXCH_ITEM_BEAN) &&
(this->itemAction == PLAYER_IA_BOTTLE_BUG))) &&
((this->exchangeItemId != EXCH_ITEM_BEAN) || (this->itemAction == PLAYER_IA_MAGIC_BEAN))) {
if (this->exchangeItemId == EXCH_ITEM_BEAN) {
Inventory_ChangeAmmo(ITEM_BEAN, -1);
func_80835DE4(play, this, Player_Action_8084279C, 0);
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
this->av2.actionVar2 = 0x50;
this->av1.actionVar1 = -1;
}
targetActor->flags |= ACTOR_FLAG_PLAYER_TALKED_TO;
this->unk_664 = this->targetActor;
} else if (sp2C == EXCH_ITEM_LETTER_RUTO) {
this->av1.actionVar1 = 1;
this->actor.textId = 0x4005;
func_80835EA4(play, 1);
} else {
this->av1.actionVar1 = 2;
this->actor.textId = 0xCF;
func_80835EA4(play, 4);
}
this->actor.flags |= ACTOR_FLAG_PLAYER_TALKED_TO;
this->exchangeItemId = sp2C;
if (this->av1.actionVar1 < 0) {
Player_AnimChangeOnceMorph(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_check, this->modelAnimType));
} else {
Player_AnimPlayOnce(play, this, D_80854548[this->av1.actionVar1]);
}
func_80832224(this);
}
return 1;
}
sp2C = Player_ActionToBottle(this, this->itemAction);
if (sp2C >= 0) {
if (sp2C == 0xC) {
func_80835DE4(play, this, Player_Action_8084EED8, 0);
Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_bottle_bug_out);
func_80835EA4(play, 3);
} else if ((sp2C > 0) && (sp2C < 4)) {
func_80835DE4(play, this, Player_Action_8084EFC0, 0);
Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_bottle_fish_out);
func_80835EA4(play, (sp2C == 1) ? 1 : 5);
} else {
func_80835DE4(play, this, Player_Action_8084EAC0, 0);
Player_AnimChangeOnceMorphAdjusted(play, this, &gPlayerAnim_link_bottle_drink_demo_start);
func_80835EA4(play, 2);
}
} else {
func_80835DE4(play, this, Player_Action_8084E3C4, 0);
Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_normal_okarina_start);
this->stateFlags2 |= PLAYER_STATE2_OCARINA_PLAYING;
func_80835EA4(play, (this->unk_6A8 != NULL) ? 0x5B : 0x5A);
if (this->unk_6A8 != NULL) {
this->stateFlags2 |= PLAYER_STATE2_PLAY_FOR_ACTOR;
Camera_SetParam(Play_GetCamera(play, 0), 8, this->unk_6A8);
}
}
} else if (func_8083AD4C(play, this)) {
if (!(this->stateFlags1 & PLAYER_STATE1_ON_HORSE)) {
Player_SetupAction(play, this, Player_Action_8084B1D8, 1);
this->av2.actionVar2 = 13;
func_8083B010(this);
}
this->stateFlags1 |= PLAYER_STATE1_FIRST_PERSON;
func_80078884(NA_SE_SY_CAMERA_ZOOM_UP);
Player_ZeroSpeedXZ(this);
return 1;
} else {
this->unk_6AD = 0;
func_80078884(NA_SE_SY_ERROR);
return 0;
}
this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
}
func_80832224(this);
return 1;
}
return 0;
}
s32 Player_ActionChange_4(Player* this, PlayState* play) {
Actor* sp34 = this->targetActor;
Actor* sp30 = this->unk_664;
Actor* sp2C = NULL;
s32 sp28 = 0;
s32 sp24;
sp24 = (sp30 != NULL) &&
(CHECK_FLAG_ALL(sp30->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_NAVI_HAS_INFO) || (sp30->naviEnemyId != 0xFF));
if (sp24 || (this->naviTextId != 0)) {
sp28 = (this->naviTextId < 0) && ((ABS(this->naviTextId) & 0xFF00) != 0x200);
if (sp28 || !sp24) {
sp2C = this->naviActor;
if (sp28) {
sp30 = NULL;
sp34 = NULL;
}
} else {
sp2C = sp30;
}
}
if ((sp34 != NULL) || (sp2C != NULL)) {
if ((sp30 == NULL) || (sp30 == sp34) || (sp30 == sp2C)) {
if (!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) ||
((this->heldActor != NULL) && (sp28 || (sp34 == this->heldActor) || (sp2C == this->heldActor) ||
((sp34 != NULL) && (sp34->flags & ACTOR_FLAG_WILL_TALK))))) {
if ((this->actor.bgCheckFlags & 1) || (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) ||
(func_808332B8(this) && !(this->stateFlags2 & PLAYER_STATE2_UNDERWATER))) {
if (sp34 != NULL) {
this->stateFlags2 |= PLAYER_STATE2_SPEAK_OR_CHECK;
if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A) || (sp34->flags & ACTOR_FLAG_WILL_TALK)) {
sp2C = NULL;
} else if (sp2C == NULL) {
return 0;
}
}
if (sp2C != NULL) {
if (!sp28) {
this->stateFlags2 |= PLAYER_STATE2_NAVI_ALERT;
}
if (!CHECK_BTN_ALL(sControlInput->press.button, CVarGetInteger("gNaviOnL", 0) ? BTN_L : BTN_CUP) && !sp28) {
return 0;
}
sp34 = sp2C;
this->targetActor = NULL;
if (sp28 || !sp24) {
sp2C->textId = ABS(this->naviTextId);
} else {
if (sp2C->naviEnemyId != 0xFF) {
sp2C->textId = sp2C->naviEnemyId + 0x600;
}
}
}
this->currentMask = D_80858AA4;
Player_StartTalking(play, sp34);
return 1;
}
}
}
}
return 0;
}
s32 func_8083B8F4(Player* this, PlayState* play) {
if (!(this->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_ON_HORSE)) &&
Camera_CheckValidMode(Play_GetCamera(play, 0), 6)) {
if ((this->actor.bgCheckFlags & 1) ||
(func_808332B8(this) && (this->actor.yDistToWater < this->ageProperties->unk_2C))) {
this->unk_6AD = 1;
return 1;
}
}
return 0;
}
s32 Player_ActionChange_0(Player* this, PlayState* play) {
if (this->unk_6AD != 0) {
Player_ActionChange_13(this, play);
return 1;
}
if ((this->unk_664 != NULL) && (CHECK_FLAG_ALL(this->unk_664->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_NAVI_HAS_INFO) ||
(this->unk_664->naviEnemyId != 0xFF))) {
this->stateFlags2 |= PLAYER_STATE2_NAVI_ALERT;
} else if ((this->naviTextId == 0 || CVarGetInteger("gNaviOnL", 0)) && !func_8008E9C4(this) && CHECK_BTN_ALL(sControlInput->press.button, BTN_CUP) &&
(YREG(15) != 0x10) &&
(YREG(15) != 0x20) && !func_8083B8F4(this, play)) {
func_80078884(NA_SE_SY_ERROR);
}
return 0;
}
void func_8083BA90(PlayState* play, Player* this, s32 arg2, f32 xzVelocity, f32 yVelocity) {
func_80837948(play, this, arg2);
Player_SetupAction(play, this, Player_Action_80844AF4, 0);
this->stateFlags3 |= PLAYER_STATE3_MIDAIR;
this->yaw = this->actor.shape.rot.y;
this->linearVelocity = xzVelocity;
this->actor.velocity.y = yVelocity;
this->actor.bgCheckFlags &= ~1;
this->hoverBootsTimer = 0;
func_80832854(this);
func_80832698(this, NA_SE_VO_LI_SWORD_L);
}
s32 func_8083BB20(Player* this) {
if (!(this->stateFlags1 & PLAYER_STATE1_SHIELDING) && (Player_GetMeleeWeaponHeld(this) != 0)) {
if (sUseHeldItem ||
((this->actor.category != ACTORCAT_PLAYER) && CHECK_BTN_ALL(sControlInput->press.button, BTN_B))) {
return 1;
}
}
return 0;
}
s32 func_8083BBA0(Player* this, PlayState* play) {
if (func_8083BB20(this) && (sFloorType != 7)) {
func_8083BA90(play, this, PLAYER_MWA_JUMPSLASH_START, 3.0f, 4.5f);
return 1;
}
return 0;
}
void func_8083BC04(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_80844708, 0);
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime,
GET_PLAYER_ANIM(PLAYER_ANIMGROUP_landing_roll, this->modelAnimType),
1.25f * D_808535E8);
gSaveContext.sohStats.count[COUNT_ROLLS]++;
}
s32 func_8083BC7C(Player* this, PlayState* play) {
if ((this->unk_84B[this->unk_846] == 0) && (sFloorType != 7)) {
func_8083BC04(this, play);
return 1;
}
return 0;
}
void func_8083BCD0(Player* this, PlayState* play, s32 arg2) {
func_80838940(this, D_80853D4C[arg2][0], !(arg2 & 1) ? 5.8f : 3.5f, play, NA_SE_VO_LI_SWORD_N);
if (arg2) {}
this->av2.actionVar2 = 1;
this->av1.actionVar1 = arg2;
this->yaw = this->actor.shape.rot.y + (arg2 << 0xE);
this->linearVelocity = !(arg2 & 1) ? 6.0f : 8.5f;
this->stateFlags2 |= PLAYER_STATE2_HOPPING;
Player_PlaySfx(this, ((arg2 << 0xE) == 0x8000) ? NA_SE_PL_ROLL : NA_SE_PL_SKIP);
}
s32 Player_ActionChange_10(Player* this, PlayState* play) {
s32 sp2C;
if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A) &&
(play->roomCtx.curRoom.behaviorType1 != ROOM_BEHAVIOR_TYPE1_2) && (sFloorType != 7) &&
(SurfaceType_GetSlope(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId) != 1)) {
sp2C = this->unk_84B[this->unk_846];
if (sp2C <= 0) {
if (func_80833BCC(this)) {
if (this->actor.category != ACTORCAT_PLAYER) {
if (sp2C < 0) {
func_808389E8(this, &gPlayerAnim_link_normal_jump, REG(69) / 100.0f, play);
} else {
func_8083BC04(this, play);
}
} else {
if ((Player_GetMeleeWeaponHeld(this) != 0) && Player_CanUpdateItems(this)) {
func_8083BA90(play, this, PLAYER_MWA_JUMPSLASH_START, 5.0f, 5.0f);
} else {
func_8083BC04(this, play);
}
}
return 1;
}
} else {
func_8083BCD0(this, play, sp2C);
if (sp2C == 1 || sp2C == 3) {
gSaveContext.sohStats.count[COUNT_SIDEHOPS]++;
}
if (sp2C == 2) {
gSaveContext.sohStats.count[COUNT_BACKFLIPS]++;
}
return 1;
}
}
return 0;
}
void func_8083BF50(Player* this, PlayState* play) {
LinkAnimationHeader* anim;
f32 sp30;
sp30 = this->unk_868 - 3.0f;
if (sp30 < 0.0f) {
sp30 += 29.0f;
}
if (sp30 < 14.0f) {
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_walk_endL, this->modelAnimType);
sp30 = 11.0f - sp30;
if (sp30 < 0.0f) {
sp30 = 1.375f * -sp30;
}
sp30 /= 11.0f;
} else {
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_walk_endR, this->modelAnimType);
sp30 = 26.0f - sp30;
if (sp30 < 0.0f) {
sp30 = 2 * -sp30;
}
sp30 /= 12.0f;
}
LinkAnimation_Change(play, &this->skelAnime, anim, 1.0f, 0.0f, Animation_GetLastFrame(anim), ANIMMODE_ONCE,
4.0f * sp30);
this->yaw = this->actor.shape.rot.y;
}
void func_8083C0B8(Player* this, PlayState* play) {
func_80839FFC(this, play);
func_8083BF50(this, play);
}
void func_8083C0E8(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_80840BC8, 1);
Player_AnimPlayOnce(play, this, func_80833338(this));
this->yaw = this->actor.shape.rot.y;
}
void func_8083C148(Player* this, PlayState* play) {
if (!(this->stateFlags3 & PLAYER_STATE3_HOOKSHOT_TRAVELLING)) {
func_8083B010(this);
if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) {
func_80838F18(play, this);
} else {
func_80839F90(this, play);
}
if (this->unk_6AD < 4) {
this->unk_6AD = 0;
}
}
this->stateFlags1 &= ~(PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_FIRST_PERSON);
}
s32 Player_ActionChange_6(Player* this, PlayState* play) {
if (!func_80833B54(this) && (D_808535E0 == 0) && !(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) &&
CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) {
if (func_8083BC7C(this, play)) {
return 1;
}
if ((this->unk_837 == 0) && (this->heldItemAction >= PLAYER_IA_SWORD_MASTER)) {
Player_UseItem(play, this, ITEM_NONE);
} else {
this->stateFlags2 ^= PLAYER_STATE2_NAVI_OUT;
}
}
return 0;
}
s32 Player_ActionChange_11(Player* this, PlayState* play) {
LinkAnimationHeader* anim;
f32 frame;
if ((play->shootingGalleryStatus == 0) && (this->currentShield != PLAYER_SHIELD_NONE) &&
CHECK_BTN_ALL(sControlInput->cur.button, BTN_R) &&
(Player_IsChildWithHylianShield(this) || (!func_80833B2C(this) && (this->unk_664 == NULL)))) {
func_80832318(this);
Player_DetachHeldActor(play, this);
if (Player_SetupAction(play, this, Player_Action_80843188, 0)) {
this->stateFlags1 |= PLAYER_STATE1_SHIELDING;
if (!Player_IsChildWithHylianShield(this)) {
Player_SetModelsForHoldingShield(this);
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_defense, this->modelAnimType);
} else {
anim = &gPlayerAnim_clink_normal_defense_ALL;
}
if (anim != this->skelAnime.animation) {
if (func_8008E9C4(this)) {
this->unk_86C = 1.0f;
} else {
this->unk_86C = 0.0f;
func_80833C3C(this);
}
this->unk_6BC = this->unk_6BE = this->unk_6C0 = 0;
}
frame = Animation_GetLastFrame(anim);
LinkAnimation_Change(play, &this->skelAnime, anim, 1.0f, frame, frame, ANIMMODE_ONCE, 0.0f);
if (Player_IsChildWithHylianShield(this)) {
Player_AnimReplaceApplyFlags(play, this, 4);
}
Player_PlaySfx(this, NA_SE_IT_SHIELD_POSTURE);
}
return 1;
}
return 0;
}
s32 func_8083C484(Player* this, f32* arg1, s16* arg2) {
s16 yaw = this->yaw - *arg2;
if (ABS(yaw) > 0x6000) {
if (func_8083721C(this)) {
*arg1 = 0.0f;
*arg2 = this->yaw;
} else {
return 1;
}
}
return 0;
}
void func_8083C50C(Player* this) {
if ((this->unk_844 > 0) && !CHECK_BTN_ALL(sControlInput->cur.button, BTN_B)) {
this->unk_844 = -this->unk_844;
}
}
s32 Player_ActionChange_8(Player* this, PlayState* play) {
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_B)) {
if (!(this->stateFlags1 & PLAYER_STATE1_SHIELDING) && (Player_GetMeleeWeaponHeld(this) != 0) && (this->unk_844 == 1) &&
(this->heldItemAction != PLAYER_IA_DEKU_STICK)) {
if ((this->heldItemAction != PLAYER_IA_SWORD_BIGGORON) || (gSaveContext.swordHealth > 0.0f)) {
func_808377DC(play, this);
return 1;
}
}
} else {
func_8083C50C(this);
}
return 0;
}
s32 func_8083C61C(PlayState* play, Player* this) {
if ((play->roomCtx.curRoom.behaviorType1 != ROOM_BEHAVIOR_TYPE1_2) && (this->actor.bgCheckFlags & 1) &&
(AMMO(ITEM_NUT) != 0)) {
Player_SetupAction(play, this, Player_Action_8084E604, 0);
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_light_bom);
this->unk_6AD = 0;
return 1;
}
return 0;
}
static struct_80854554 D_80854554[] = {
{ &gPlayerAnim_link_bottle_bug_miss, &gPlayerAnim_link_bottle_bug_in, 2, 3 },
{ &gPlayerAnim_link_bottle_fish_miss, &gPlayerAnim_link_bottle_fish_in, 5, 3 },
};
s32 func_8083C6B8(PlayState* play, Player* this) {
Vec3f sp24;
if (sUseHeldItem) {
if (Player_GetBottleHeld(this) >= 0) {
Player_SetupAction(play, this, Player_Action_8084ECA4, 0);
if (this->actor.yDistToWater > 12.0f) {
this->av2.actionVar2 = 1;
}
Player_AnimPlayOnceAdjusted(play, this, D_80854554[this->av2.actionVar2].unk_00);
Player_PlaySfx(this, NA_SE_IT_SWORD_SWING);
func_80832698(this, NA_SE_VO_LI_AUTO_JUMP);
return 1;
}
if (this->heldItemAction == PLAYER_IA_FISHING_POLE) {
sp24 = this->actor.world.pos;
sp24.y += 50.0f;
if (CVarGetInteger("gHoverFishing", 0)
? 0
: !(this->actor.bgCheckFlags & 1) || (this->actor.world.pos.z > 1300.0f) ||
BgCheck_SphVsFirstPoly(&play->colCtx, &sp24, 20.0f)) {
func_80078884(NA_SE_SY_ERROR);
return 0;
}
Player_SetupAction(play, this, Player_Action_80850C68, 0);
this->unk_860 = 1;
Player_ZeroSpeedXZ(this);
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_fishing_throw);
return 1;
} else {
return 0;
}
}
return 0;
}
void func_8083C858(Player* this, PlayState* play) {
PlayerActionFunc actionFunc;
if (func_80833BCC(this)) {
actionFunc = Player_Action_8084227C;
} else {
actionFunc = Player_Action_80842180;
}
Player_SetupAction(play, this, actionFunc, 1);
Player_AnimChangeLoopMorph(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_run, this->modelAnimType));
this->unk_89C = 0;
this->unk_864 = this->unk_868 = 0.0f;
}
void func_8083C8DC(Player* this, PlayState* play, s16 arg2) {
this->actor.shape.rot.y = this->yaw = arg2;
func_8083C858(this, play);
}
s32 func_8083C910(PlayState* play, Player* this, f32 arg2) {
WaterBox* sp2C;
f32 sp28;
sp28 = this->actor.world.pos.y;
if (WaterBox_GetSurface1(play, &play->colCtx, this->actor.world.pos.x, this->actor.world.pos.z, &sp28,
&sp2C) != 0) {
sp28 -= this->actor.world.pos.y;
if (this->ageProperties->unk_24 <= sp28) {
Player_SetupAction(play, this, Player_Action_8084D7C4, 0);
Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim);
this->stateFlags1 |= PLAYER_STATE1_IN_WATER | PLAYER_STATE1_IN_CUTSCENE;
this->av2.actionVar2 = 20;
this->linearVelocity = 2.0f;
Player_SetBootData(play, this);
return 0;
}
}
func_80838E70(play, this, arg2, this->actor.shape.rot.y);
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
return 1;
}
void func_8083CA20(PlayState* play, Player* this) {
if (func_8083C910(play, this, 180.0f)) {
this->av2.actionVar2 = -20;
}
}
void func_8083CA54(PlayState* play, Player* this) {
this->linearVelocity = 2.0f;
gSaveContext.entranceSpeed = 2.0f;
if (func_8083C910(play, this, 120.0f)) {
this->av2.actionVar2 = -15;
}
}
void func_8083CA9C(PlayState* play, Player* this) {
if (gSaveContext.entranceSpeed < 0.1f) {
gSaveContext.entranceSpeed = 0.1f;
}
this->linearVelocity = gSaveContext.entranceSpeed;
if (func_8083C910(play, this, 800.0f)) {
this->av2.actionVar2 = -80 / this->linearVelocity;
if (this->av2.actionVar2 < -20) {
this->av2.actionVar2 = -20;
}
}
}
void func_8083CB2C(Player* this, s16 yaw, PlayState* play) {
Player_SetupAction(play, this, Player_Action_808414F8, 1);
LinkAnimation_CopyJointToMorph(play, &this->skelAnime);
this->unk_864 = this->unk_868 = 0.0f;
this->yaw = yaw;
}
void func_8083CB94(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_80840DE4, 1);
Player_AnimChangeLoopMorph(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_walk, this->modelAnimType));
}
void func_8083CBF0(Player* this, s16 yaw, PlayState* play) {
Player_SetupAction(play, this, Player_Action_808423EC, 1);
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_anchor_back_walk, 2.2f, 0.0f,
Animation_GetLastFrame(&gPlayerAnim_link_anchor_back_walk), ANIMMODE_ONCE, -6.0f);
this->linearVelocity = 8.0f;
this->yaw = yaw;
}
void func_8083CC9C(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_8084193C, 1);
Player_AnimChangeLoopMorph(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_side_walkR, this->modelAnimType));
this->unk_868 = 0.0f;
}
void func_8083CD00(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_8084251C, 1);
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, &gPlayerAnim_link_anchor_back_brake, 2.0f);
}
void func_8083CD54(PlayState* play, Player* this, s16 yaw) {
this->yaw = yaw;
Player_SetupAction(play, this, Player_Action_80841BA8, 1);
this->unk_87E = 1200;
this->unk_87E *= D_808535E8;
LinkAnimation_Change(play, &this->skelAnime, D_80853914[PLAYER_ANIMGROUP_45_turn][this->modelAnimType], 1.0f, 0.0f,
0.0f, ANIMMODE_LOOP, -6.0f);
}
void func_8083CE0C(Player* this, PlayState* play) {
LinkAnimationHeader* anim;
Player_SetupAction(play, this, Player_Action_80840BC8, 1);
if (this->unk_870 < 0.5f) {
anim = D_80853914[PLAYER_ANIMGROUP_waitR2wait][this->modelAnimType];
} else {
anim = D_80853914[PLAYER_ANIMGROUP_waitL2wait][this->modelAnimType];
}
Player_AnimPlayOnce(play, this, anim);
this->yaw = this->actor.shape.rot.y;
}
void func_8083CEAC(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_80840450, 1);
Player_AnimChangeOnceMorph(play, this, D_80853914[PLAYER_ANIMGROUP_wait2waitR][this->modelAnimType]);
this->av2.actionVar2 = 1;
}
void func_8083CF10(Player* this, PlayState* play) {
if (this->linearVelocity != 0.0f) {
func_8083C858(this, play);
} else {
func_8083CE0C(this, play);
}
}
void func_8083CF5C(Player* this, PlayState* play) {
if (this->linearVelocity != 0.0f) {
func_8083C858(this, play);
} else {
func_80839F90(this, play);
}
}
s32 func_8083CFA8(PlayState* play, Player* this, f32 arg2, s32 splashScale) {
f32 sp3C = fabsf(arg2);
WaterBox* sp38;
f32 sp34;
Vec3f splashPos;
s32 splashType;
if (sp3C > 2.0f) {
splashPos.x = this->bodyPartsPos[PLAYER_BODYPART_WAIST].x;
splashPos.z = this->bodyPartsPos[PLAYER_BODYPART_WAIST].z;
sp34 = this->actor.world.pos.y;
if (WaterBox_GetSurface1(play, &play->colCtx, splashPos.x, splashPos.z, &sp34, &sp38)) {
if ((sp34 - this->actor.world.pos.y) < 100.0f) {
splashType = (sp3C <= 10.0f) ? 0 : 1;
splashPos.y = sp34;
EffectSsGSplash_Spawn(play, &splashPos, NULL, NULL, splashType, splashScale);
return 1;
}
}
}
return 0;
}
void func_8083D0A8(PlayState* play, Player* this, f32 arg2) {
this->stateFlags1 |= PLAYER_STATE1_JUMPING;
this->stateFlags1 &= ~PLAYER_STATE1_IN_WATER;
func_80832340(play, this);
if (func_8083CFA8(play, this, arg2, 500)) {
Player_PlaySfx(this, NA_SE_EV_JUMP_OUT_WATER);
}
Player_SetBootData(play, this);
}
s32 func_8083D12C(PlayState* play, Player* this, Input* arg2) {
if (!(this->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) && !(this->stateFlags2 & PLAYER_STATE2_UNDERWATER)) {
if ((arg2 == NULL) || (CHECK_BTN_ALL(arg2->press.button, BTN_A) && (ABS(this->unk_6C2) < 12000) &&
(this->currentBoots != PLAYER_BOOTS_IRON))) {
Player_SetupAction(play, this, Player_Action_8084DC48, 0);
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_swimer_swim_deep_start);
this->unk_6C2 = 0;
this->stateFlags2 |= PLAYER_STATE2_UNDERWATER;
this->actor.velocity.y = 0.0f;
if (arg2 != NULL) {
this->stateFlags2 |= PLAYER_STATE2_DIVING;
Player_PlaySfx(this, NA_SE_PL_DIVE_BUBBLE);
}
return 1;
}
}
if ((this->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) || (this->stateFlags2 & PLAYER_STATE2_UNDERWATER)) {
if (this->actor.velocity.y > 0.0f) {
if (this->actor.yDistToWater < this->ageProperties->unk_30) {
this->stateFlags2 &= ~PLAYER_STATE2_UNDERWATER;
if (arg2 != NULL) {
Player_SetupAction(play, this, Player_Action_8084E1EC, 1);
if (this->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) {
this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE;
}
this->av2.actionVar2 = 2;
}
func_80832340(play, this);
// Skip take breath animation on surface if Link didn't grab an item while underwater and the setting is enabled
if (CVarGetInteger("gSkipSwimDeepEndAnim", 0) && !(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) {
auto lastAnimFrame = Animation_GetLastFrame(&gPlayerAnim_link_swimer_swim_deep_end);
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_swimer_swim_deep_end, 1.0f,
lastAnimFrame, lastAnimFrame, ANIMMODE_ONCE, -6.0f);
} else {
Player_AnimChangeOnceMorph(play, this,
(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) ? &gPlayerAnim_link_swimer_swim_get
: &gPlayerAnim_link_swimer_swim_deep_end);
}
if (func_8083CFA8(play, this, this->actor.velocity.y, 500)) {
Player_PlaySfx(this, NA_SE_PL_FACE_UP);
}
return 1;
}
}
}
return 0;
}
void func_8083D330(PlayState* play, Player* this) {
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_swimer_swim);
this->unk_6C2 = 16000;
this->av2.actionVar2 = 1;
}
void func_8083D36C(PlayState* play, Player* this) {
if ((this->currentBoots != PLAYER_BOOTS_IRON) || !(this->actor.bgCheckFlags & 1)) {
func_80832564(play, this);
if ((this->currentBoots != PLAYER_BOOTS_IRON) && (this->stateFlags2 & PLAYER_STATE2_UNDERWATER)) {
this->stateFlags2 &= ~PLAYER_STATE2_UNDERWATER;
func_8083D12C(play, this, 0);
this->av1.actionVar1 = 1;
} else if (Player_Action_80844A44 == this->actionFunc) {
Player_SetupAction(play, this, Player_Action_8084DC48, 0);
func_8083D330(play, this);
} else {
Player_SetupAction(play, this, Player_Action_8084D610, 1);
Player_AnimChangeOnceMorph(play, this,
(this->actor.bgCheckFlags & 1) ? &gPlayerAnim_link_swimer_wait2swim_wait
: &gPlayerAnim_link_swimer_land2swim_wait);
}
}
if (!(this->stateFlags1 & PLAYER_STATE1_IN_WATER) || (this->actor.yDistToWater < this->ageProperties->unk_2C)) {
if (func_8083CFA8(play, this, this->actor.velocity.y, 500)) {
Player_PlaySfx(this, NA_SE_EV_DIVE_INTO_WATER);
if (this->fallDistance > 800.0f) {
func_80832698(this, NA_SE_VO_LI_CLIMB_END);
}
}
}
this->stateFlags1 |= PLAYER_STATE1_IN_WATER;
this->stateFlags2 |= PLAYER_STATE2_UNDERWATER;
this->stateFlags1 &= ~(PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL);
this->unk_854 = 0.0f;
Player_SetBootData(play, this);
}
void func_8083D53C(PlayState* play, Player* this) {
if (this->actor.yDistToWater < this->ageProperties->unk_2C) {
Audio_SetBaseFilter(0);
this->underwaterTimer = 0;
} else {
Audio_SetBaseFilter(0x20);
if (this->underwaterTimer < 300) {
this->underwaterTimer++;
}
}
if ((Player_Action_80845668 != this->actionFunc) && (Player_Action_8084BDFC != this->actionFunc)) {
if (this->ageProperties->unk_2C < this->actor.yDistToWater) {
if (!(this->stateFlags1 & PLAYER_STATE1_IN_WATER) ||
(!((this->currentBoots == PLAYER_BOOTS_IRON) && (this->actor.bgCheckFlags & 1)) &&
(Player_Action_8084E30C != this->actionFunc) && (Player_Action_8084E368 != this->actionFunc) &&
(Player_Action_8084D610 != this->actionFunc) && (Player_Action_8084D84C != this->actionFunc) &&
(Player_Action_8084DAB4 != this->actionFunc) && (Player_Action_8084DC48 != this->actionFunc) &&
(Player_Action_8084E1EC != this->actionFunc) && (Player_Action_8084D7C4 != this->actionFunc))) {
func_8083D36C(play, this);
return;
}
} else if ((this->stateFlags1 & PLAYER_STATE1_IN_WATER) && (this->actor.yDistToWater < this->ageProperties->unk_24)) {
if ((this->skelAnime.moveFlags == 0) && (this->currentBoots != PLAYER_BOOTS_IRON)) {
func_8083CD54(play, this, this->actor.shape.rot.y);
}
func_8083D0A8(play, this, this->actor.velocity.y);
}
}
}
void func_8083D6EC(PlayState* play, Player* this) {
Vec3f ripplePos;
f32 temp1;
f32 temp2;
f32 temp3;
f32 temp4;
this->actor.minVelocityY = -20.0f;
this->actor.gravity = REG(68) / 100.0f;
if (func_8083816C(sFloorType)) {
temp1 = fabsf(this->linearVelocity) * 20.0f;
temp3 = 0.0f;
if (sFloorType == 4) {
if (this->unk_6C4 > 1300.0f) {
temp2 = this->unk_6C4;
} else {
temp2 = 1300.0f;
}
if (this->currentBoots == PLAYER_BOOTS_HOVER) {
temp1 += temp1;
} else if (this->currentBoots == PLAYER_BOOTS_IRON) {
temp1 *= 0.3f;
}
} else {
temp2 = 20000.0f;
if (this->currentBoots != PLAYER_BOOTS_HOVER) {
temp1 += temp1;
} else if ((sFloorType == 7) || (this->currentBoots == PLAYER_BOOTS_IRON)) {
temp1 = 0;
}
}
if (this->currentBoots != PLAYER_BOOTS_HOVER) {
temp3 = (temp2 - this->unk_6C4) * 0.02f;
temp3 = CLAMP(temp3, 0.0f, 300.0f);
if (this->currentBoots == PLAYER_BOOTS_IRON) {
temp3 += temp3;
}
}
this->unk_6C4 += temp3 - temp1;
this->unk_6C4 = CLAMP(this->unk_6C4, 0.0f, temp2);
this->actor.gravity -= this->unk_6C4 * 0.004f;
} else {
this->unk_6C4 = 0.0f;
}
if (this->actor.bgCheckFlags & 0x20) {
if (this->actor.yDistToWater < 50.0f) {
temp4 = fabsf(this->bodyPartsPos[PLAYER_BODYPART_WAIST].x - this->unk_A88.x) +
fabsf(this->bodyPartsPos[PLAYER_BODYPART_WAIST].y - this->unk_A88.y) +
fabsf(this->bodyPartsPos[PLAYER_BODYPART_WAIST].z - this->unk_A88.z);
if (temp4 > 4.0f) {
temp4 = 4.0f;
}
this->unk_854 += temp4;
if (this->unk_854 > 15.0f) {
this->unk_854 = 0.0f;
ripplePos.x = (Rand_ZeroOne() * 10.0f) + this->actor.world.pos.x;
ripplePos.y = this->actor.world.pos.y + this->actor.yDistToWater;
ripplePos.z = (Rand_ZeroOne() * 10.0f) + this->actor.world.pos.z;
EffectSsGRipple_Spawn(play, &ripplePos, 100, 500, 0);
if ((this->linearVelocity > 4.0f) && !func_808332B8(this) &&
((this->actor.world.pos.y + this->actor.yDistToWater) <
this->bodyPartsPos[PLAYER_BODYPART_WAIST].y)) {
func_8083CFA8(play, this, 20.0f,
(fabsf(this->linearVelocity) * 50.0f) + (this->actor.yDistToWater * 5.0f));
}
}
}
if (this->actor.yDistToWater > 40.0f) {
s32 numBubbles = 0;
s32 i;
if ((this->actor.velocity.y > -1.0f) || (this->actor.bgCheckFlags & 1)) {
if (Rand_ZeroOne() < 0.2f) {
numBubbles = 1;
}
} else {
numBubbles = this->actor.velocity.y * -2.0f;
}
for (i = 0; i < numBubbles; i++) {
EffectSsBubble_Spawn(play, &this->actor.world.pos, 20.0f, 10.0f, 20.0f, 0.13f);
}
}
}
}
s32 func_8083DB98(Player* this, s32 arg1) {
Actor* unk_664 = this->unk_664;
Vec3f sp30;
s16 sp2E;
s16 sp2C;
sp30.x = this->actor.world.pos.x;
sp30.y = this->bodyPartsPos[PLAYER_BODYPART_HEAD].y + 3.0f;
sp30.z = this->actor.world.pos.z;
sp2E = Math_Vec3f_Pitch(&sp30, &unk_664->focus.pos);
sp2C = Math_Vec3f_Yaw(&sp30, &unk_664->focus.pos);
Math_SmoothStepToS(&this->actor.focus.rot.y, sp2C, 4, 10000, 0);
Math_SmoothStepToS(&this->actor.focus.rot.x, sp2E, 4, 10000, 0);
this->unk_6AE |= 2;
return func_80836AB8(this, arg1);
}
static Vec3f D_8085456C = { 0.0f, 100.0f, 40.0f };
void func_8083DC54(Player* this, PlayState* play) {
s16 sp46;
s16 temp2;
f32 temp1;
Vec3f sp34;
if (this->unk_664 != NULL) {
if (func_8002DD78(this) || func_808334B4(this)) {
func_8083DB98(this, 1);
} else {
func_8083DB98(this, 0);
}
return;
}
if (sFloorType == 11) {
Math_SmoothStepToS(&this->actor.focus.rot.x, -20000, 10, 4000, 800);
} else {
sp46 = 0;
temp1 = func_8083973C(play, this, &D_8085456C, &sp34);
if (temp1 > BGCHECK_Y_MIN) {
temp2 = Math_Atan2S(40.0f, this->actor.world.pos.y - temp1);
sp46 = CLAMP(temp2, -4000, 4000);
}
this->actor.focus.rot.y = this->actor.shape.rot.y;
Math_SmoothStepToS(&this->actor.focus.rot.x, sp46, 14, 4000, 30);
}
func_80836AB8(this, func_8002DD78(this) || func_808334B4(this));
}
void func_8083DDC8(Player* this, PlayState* play) {
s16 temp1;
s16 temp2;
if (!func_8002DD78(this) && !func_808334B4(this) && (this->linearVelocity > 5.0f)) {
temp1 = this->linearVelocity * 200.0f;
temp2 = (s16)(this->yaw - this->actor.shape.rot.y) * this->linearVelocity * 0.1f;
temp1 = CLAMP(temp1, -4000, 4000);
temp2 = CLAMP(-temp2, -4000, 4000);
Math_ScaledStepToS(&this->unk_6BC, temp1, 900);
this->unk_6B6 = -(f32)this->unk_6BC * 0.5f;
Math_ScaledStepToS(&this->unk_6BA, temp2, 300);
Math_ScaledStepToS(&this->unk_6C0, temp2, 200);
this->unk_6AE |= 0x168;
} else {
func_8083DC54(this, play);
}
}
void func_8083DF68(Player* this, f32 arg1, s16 arg2) {
Math_AsymStepToF(&this->linearVelocity, arg1, REG(19) / 100.0f, 1.5f);
Math_ScaledStepToS(&this->yaw, arg2, REG(27));
}
void func_8083DFE0(Player* this, f32* arg1, s16* arg2) {
s16 yawDiff = this->yaw - *arg2;
if (this->meleeWeaponState == 0) {
float maxSpeed = R_RUN_SPEED_LIMIT / 100.0f;
int32_t giSpeedModifier = GameInteractor_RunSpeedModifier();
if (giSpeedModifier != 0) {
if (giSpeedModifier > 0) {
maxSpeed *= giSpeedModifier;
} else {
maxSpeed /= abs(giSpeedModifier);
}
}
if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) == BUNNY_HOOD_FAST_AND_JUMP && this->currentMask == PLAYER_MASK_BUNNY) {
maxSpeed *= 1.5f;
}
if (CVarGetInteger("gEnableWalkModify", 0) && !CVarGetInteger("gWalkModifierDoesntChangeJump", 0)) {
if (CVarGetInteger("gWalkSpeedToggle", 0)) {
if (gWalkSpeedToggle1) {
maxSpeed *= CVarGetFloat("gWalkModifierOne", 1.0f);
} else if (gWalkSpeedToggle2) {
maxSpeed *= CVarGetFloat("gWalkModifierTwo", 1.0f);
}
} else {
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER1)) {
maxSpeed *= CVarGetFloat("gWalkModifierOne", 1.0f);
} else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER2)) {
maxSpeed *= CVarGetFloat("gWalkModifierTwo", 1.0f);
}
}
}
this->linearVelocity = CLAMP(this->linearVelocity, -maxSpeed, maxSpeed);
}
if (ABS(yawDiff) > 0x6000) {
if (Math_StepToF(&this->linearVelocity, 0.0f, 1.0f)) {
this->yaw = *arg2;
}
} else {
Math_AsymStepToF(&this->linearVelocity, *arg1, 0.05f, 0.1f);
Math_ScaledStepToS(&this->yaw, *arg2, 200);
}
}
static struct_80854578 D_80854578[] = {
{ &gPlayerAnim_link_uma_left_up, 35.17f, 6.6099997f },
{ &gPlayerAnim_link_uma_right_up, -34.16f, 7.91f },
};
s32 Player_ActionChange_3(Player* this, PlayState* play) {
EnHorse* rideActor = (EnHorse*)this->rideActor;
f32 unk_04;
f32 unk_08;
f32 sp38;
f32 sp34;
s32 temp;
if ((rideActor != NULL) && CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) {
sp38 = Math_CosS(rideActor->actor.shape.rot.y);
sp34 = Math_SinS(rideActor->actor.shape.rot.y);
func_80836898(play, this, func_8083A360);
this->stateFlags1 |= PLAYER_STATE1_ON_HORSE;
this->actor.bgCheckFlags &= ~0x20;
if (this->mountSide < 0) {
temp = 0;
} else {
temp = 1;
}
unk_04 = D_80854578[temp].unk_04;
unk_08 = D_80854578[temp].unk_08;
this->actor.world.pos.x =
rideActor->actor.world.pos.x + rideActor->riderPos.x + ((unk_04 * sp38) + (unk_08 * sp34));
this->actor.world.pos.z =
rideActor->actor.world.pos.z + rideActor->riderPos.z + ((unk_08 * sp38) - (unk_04 * sp34));
this->unk_878 = rideActor->actor.world.pos.y - this->actor.world.pos.y;
this->yaw = this->actor.shape.rot.y = rideActor->actor.shape.rot.y;
Actor_MountHorse(play, this, &rideActor->actor);
Player_AnimPlayOnce(play, this, D_80854578[temp].anim);
Player_AnimReplaceApplyFlags(play, this, 0x9B);
this->actor.parent = this->rideActor;
func_80832224(this);
Actor_DisableLens(play);
return 1;
}
return 0;
}
void Player_GetSlopeDirection(CollisionPoly* floorPoly, Vec3f* slopeNormal, s16* downwardSlopeYaw) {
slopeNormal->x = COLPOLY_GET_NORMAL(floorPoly->normal.x);
slopeNormal->y = COLPOLY_GET_NORMAL(floorPoly->normal.y);
slopeNormal->z = COLPOLY_GET_NORMAL(floorPoly->normal.z);
*downwardSlopeYaw = Math_Atan2S(slopeNormal->z, slopeNormal->x);
}
s32 Player_HandleSlopes(PlayState* play, Player* this, CollisionPoly* floorPoly) {
static LinkAnimationHeader* sSlopeSlipAnims[] = {
&gPlayerAnim_link_normal_down_slope_slip,
&gPlayerAnim_link_normal_up_slope_slip,
};
s32 pad;
s16 playerVelYaw;
Vec3f slopeNormal;
s16 downwardSlopeYaw;
f32 slopeSlowdownSpeed;
f32 slopeSlowdownSpeedStep;
s16 velYawToDownwardSlope;
if (!Player_InBlockingCsMode(play, this) && (Player_Action_8084F390 != this->actionFunc) &&
(SurfaceType_GetSlope(&play->colCtx, floorPoly, this->actor.floorBgId) == 1)) {
playerVelYaw = Math_Atan2S(this->actor.velocity.z, this->actor.velocity.x);
Player_GetSlopeDirection(floorPoly, &slopeNormal, &downwardSlopeYaw);
velYawToDownwardSlope = downwardSlopeYaw - playerVelYaw;
if (ABS(velYawToDownwardSlope) > 0x3E80) { // 87.9 degrees
// moving parallel or upwards on the slope, player does not slip but does slow down
slopeSlowdownSpeed = (1.0f - slopeNormal.y) * 40.0f;
slopeSlowdownSpeedStep = (slopeSlowdownSpeed * slopeSlowdownSpeed) * 0.015f;
if (slopeSlowdownSpeedStep < 1.2f) {
slopeSlowdownSpeedStep = 1.2f;
}
// slows down speed as player is climbing a slope
this->pushedYaw = downwardSlopeYaw;
Math_StepToF(&this->pushedSpeed, slopeSlowdownSpeed, slopeSlowdownSpeedStep);
} else {
// moving downward on the slope, causing player to slip
Player_SetupAction(play, this, Player_Action_8084F390, 0);
func_80832564(play, this);
if (sFloorShapePitch >= 0) {
this->av1.actionVar1 = 1;
}
Player_AnimChangeLoopMorph(play, this, sSlopeSlipAnims[this->av1.actionVar1]);
this->linearVelocity = sqrtf(SQ(this->actor.velocity.x) + SQ(this->actor.velocity.z));
this->yaw = playerVelYaw;
return true;
}
}
return false;
}
// unknown data (unused)
static s32 D_80854598[] = {
0xFFDB0871, 0xF8310000, 0x00940470, 0xF3980000, 0xFFB504A9, 0x0C9F0000, 0x08010402,
};
void func_8083E4C4(PlayState* play, Player* this, GetItemEntry* giEntry) {
s32 sp1C = giEntry->field & 0x1F;
if (!(giEntry->field & 0x80)) {
Item_DropCollectible(play, &this->actor.world.pos, sp1C | 0x8000);
if ((sp1C != 4) && (sp1C != 8) && (sp1C != 9) && (sp1C != 0xA) && (sp1C != 0) && (sp1C != 1) && (sp1C != 2) &&
(sp1C != 0x14) && (sp1C != 0x13)) {
Item_Give(play, giEntry->itemId);
}
} else {
Item_Give(play, giEntry->itemId);
}
func_80078884((this->getItemId < 0 || this->getItemEntry.getItemId < 0) ? NA_SE_SY_GET_BOXITEM : NA_SE_SY_GET_ITEM);
}
// Sets a flag according to which type of flag is specified in player->pendingFlag.flagType
// and which flag is specified in player->pendingFlag.flagID.
void Player_SetPendingFlag(Player* this, PlayState* play) {
switch (this->pendingFlag.flagType) {
case FLAG_SCENE_SWITCH:
Flags_SetSwitch(play, this->pendingFlag.flagID);
break;
case FLAG_SCENE_TREASURE:
Flags_SetTreasure(play, this->pendingFlag.flagID);
break;
case FLAG_SCENE_CLEAR:
Flags_SetClear(play, this->pendingFlag.flagID);
break;
case FLAG_SCENE_COLLECTIBLE:
Flags_SetCollectible(play, this->pendingFlag.flagID);
break;
case FLAG_EVENT_CHECK_INF:
Flags_SetEventChkInf(this->pendingFlag.flagID);
break;
case FLAG_ITEM_GET_INF:
Flags_SetItemGetInf(this->pendingFlag.flagID);
break;
case FLAG_INF_TABLE:
Flags_SetInfTable(this->pendingFlag.flagID);
break;
case FLAG_EVENT_INF:
Flags_SetEventInf(this->pendingFlag.flagID);
break;
case FLAG_RANDOMIZER_INF:
Flags_SetRandomizerInf(this->pendingFlag.flagID);
break;
case FLAG_NONE:
default:
break;
}
this->pendingFlag.flagType = FLAG_NONE;
this->pendingFlag.flagID = 0;
}
s32 Player_ActionChange_2(Player* this, PlayState* play) {
Actor* interactedActor;
if(gSaveContext.pendingIceTrapCount) {
gSaveContext.pendingIceTrapCount--;
GameInteractor_ExecuteOnItemReceiveHooks(ItemTable_RetrieveEntry(MOD_RANDOMIZER, RG_ICE_TRAP));
if (CVarGetInteger("gAddTraps.enabled", 0)) {
return 1;
}
this->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD);
this->actor.colChkInfo.damage = 0;
func_80837C0C(play, this, 3, 0.0f, 0.0f, 0, 20);
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry) GET_ITEM_NONE;
// Gameplay stats: Increment Ice Trap count
gSaveContext.sohStats.count[COUNT_ICE_TRAPS]++;
return 1;
}
if (iREG(67) || (((interactedActor = this->interactRangeActor) != NULL) &&
func_8002D53C(play, &play->actorCtx.titleCtx))) {
if (iREG(67) || (this->getItemId > GI_NONE)) {
if (iREG(67)) {
this->getItemId = iREG(68);
}
GetItemEntry giEntry;
if (this->getItemEntry.objectId == OBJECT_INVALID || (this->getItemId != this->getItemEntry.getItemId)) {
giEntry = ItemTable_Retrieve(this->getItemId);
} else {
giEntry = this->getItemEntry;
}
if (giEntry.collectable) {
if ((interactedActor != &this->actor) && !iREG(67)) {
interactedActor->parent = &this->actor;
}
iREG(67) = false;
if (IS_RANDO && giEntry.getItemId == RG_ICE_TRAP && giEntry.getItemFrom == ITEM_FROM_FREESTANDING) {
this->actor.freezeTimer = 30;
Player_SetPendingFlag(this, play);
Message_StartTextbox(play, 0xF8, NULL);
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
gSaveContext.pendingIceTrapCount++;
return 1;
}
// Show the cutscene for picking up an item. In vanilla, this happens in bombchu bowling alley (because getting bombchus need to show the cutscene)
// and whenever the player doesn't have the item yet. In rando, we're overruling this because we need to keep showing the cutscene
// because those items can be randomized and thus it's important to keep showing the cutscene.
uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY || Item_CheckObtainability(giEntry.itemId) == ITEM_NONE || IS_RANDO;
// Only skip cutscenes for drops when they're items/consumables from bushes/rocks/enemies.
uint8_t isDropToSkip = (interactedActor->id == ACTOR_EN_ITEM00 && interactedActor->params != 6 && interactedActor->params != 17) ||
interactedActor->id == ACTOR_EN_KAREBABA ||
interactedActor->id == ACTOR_EN_DEKUBABA;
// Skip cutscenes from picking up consumables with "Fast Pickup Text" enabled, even when the player never picked it up before.
// But only for bushes/rocks/enemies because otherwise it can lead to softlocks in deku mask theatre and potentially other places.
uint8_t skipItemCutscene = CVarGetInteger("gFastDrops", 0) && isDropToSkip;
// Same as above but for rando. Rando is different because we want to enable cutscenes for items that the player already has because
// those items could be a randomized item coming from scrubs, freestanding PoH's and keys. So we need to once again overrule
// this specifically for items coming from bushes/rocks/enemies when the player has already picked that item up.
uint8_t skipItemCutsceneRando = IS_RANDO && Item_CheckObtainability(giEntry.itemId) != ITEM_NONE && isDropToSkip;
// Show cutscene when picking up a item.
if (showItemCutscene && !skipItemCutscene && !skipItemCutsceneRando) {
Player_DetachHeldActor(play, this);
func_8083AE40(this, giEntry.objectId);
if (!(this->stateFlags2 & PLAYER_STATE2_UNDERWATER) || (this->currentBoots == PLAYER_BOOTS_IRON)) {
func_80836898(play, this, func_8083A434);
Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_demo_get_itemB);
func_80835EA4(play, 9);
}
this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE;
func_80832224(this);
return 1;
}
// Don't show cutscene when picking up an item.
func_8083E4C4(play, this, &giEntry);
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
}
} else if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A) && !(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) &&
!(this->stateFlags2 & PLAYER_STATE2_UNDERWATER)) {
if (this->getItemId != GI_NONE) {
GetItemEntry giEntry;
if (this->getItemEntry.objectId == OBJECT_INVALID) {
giEntry = ItemTable_Retrieve(-this->getItemId);
} else {
giEntry = this->getItemEntry;
}
EnBox* chest = (EnBox*)interactedActor;
if (CVarGetInteger("gFastChests", 0) != 0) {
giEntry.gi = -1 * abs(giEntry.gi);
}
if (giEntry.itemId != ITEM_NONE) {
if (((Item_CheckObtainability(giEntry.itemId) == ITEM_NONE) && (giEntry.field & 0x40)) ||
((Item_CheckObtainability(giEntry.itemId) != ITEM_NONE) && (giEntry.field & 0x20))) {
this->getItemId = -GI_RUPEE_BLUE;
giEntry = ItemTable_Retrieve(GI_RUPEE_BLUE);
}
}
func_80836898(play, this, func_8083A434);
this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE;
func_8083AE40(this, giEntry.objectId);
this->actor.world.pos.x =
chest->dyna.actor.world.pos.x - (Math_SinS(chest->dyna.actor.shape.rot.y) * 29.4343f);
this->actor.world.pos.z =
chest->dyna.actor.world.pos.z - (Math_CosS(chest->dyna.actor.shape.rot.y) * 29.4343f);
this->yaw = this->actor.shape.rot.y = chest->dyna.actor.shape.rot.y;
func_80832224(this);
if ((giEntry.itemId != ITEM_NONE) && (giEntry.gi >= 0) &&
(Item_CheckObtainability(giEntry.itemId) == ITEM_NONE)) {
Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_98);
Player_AnimReplaceApplyFlags(play, this, 0x28F);
chest->unk_1F4 = 1;
Camera_ChangeSetting(Play_GetCamera(play, 0), CAM_SET_SLOW_CHEST_CS);
} else {
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_box_kick);
chest->unk_1F4 = -1;
}
return 1;
}
if ((this->heldActor == NULL) || Player_HoldsHookshot(this)) {
if ((interactedActor->id == ACTOR_BG_TOKI_SWD) && LINK_IS_ADULT) {
s32 sp24 = this->itemAction;
this->itemAction = PLAYER_IA_NONE;
this->modelAnimType = PLAYER_ANIMTYPE_0;
this->heldItemAction = this->itemAction;
func_80836898(play, this, func_8083A0F4);
if (sp24 == PLAYER_IA_SWORD_MASTER) {
this->nextModelGroup = Player_ActionToModelGroup(this, PLAYER_IA_LAST_USED);
Player_InitItemAction(play, this, PLAYER_IA_LAST_USED);
} else {
Player_UseItem(play, this, ITEM_LAST_USED);
}
} else {
s32 strength = Player_GetStrength();
if ((interactedActor->id == ACTOR_EN_ISHI) && ((interactedActor->params & 0xF) == 1) &&
(strength < PLAYER_STR_SILVER_G)) {
return 0;
}
func_80836898(play, this, func_8083A0F4);
}
func_80832224(this);
this->stateFlags1 |= PLAYER_STATE1_ITEM_OVER_HEAD;
return 1;
}
}
}
return 0;
}
void func_8083EA94(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_80846578, 1);
Player_AnimPlayOnce(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_throw, this->modelAnimType));
}
s32 func_8083EAF0(Player* this, Actor* actor) {
if ((actor != NULL) && !(actor->flags & ACTOR_FLAG_ALWAYS_THROWN) &&
((this->linearVelocity < 1.1f) || (actor->id == ACTOR_EN_BOM_CHU))) {
return 0;
}
return 1;
}
s32 Player_ActionChange_9(Player* this, PlayState* play) {
u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN;
if (CVarGetInteger("gDpadEquips", 0) != 0) {
buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
}
if ((this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->heldActor != NULL) &&
CHECK_BTN_ANY(sControlInput->press.button, buttonsToCheck)) {
if (!func_80835644(play, this, this->heldActor)) {
if (!func_8083EAF0(this, this->heldActor)) {
Player_SetupAction(play, this, Player_Action_808464B0, 1);
Player_AnimPlayOnce(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_put, this->modelAnimType));
} else {
func_8083EA94(this, play);
}
}
return 1;
}
return 0;
}
s32 func_8083EC18(Player* this, PlayState* play, u32 wallFlags) {
if (this->yDistToLedge >= 79.0f) {
if (!(this->stateFlags1 & PLAYER_STATE1_IN_WATER) || (this->currentBoots == PLAYER_BOOTS_IRON) ||
(this->actor.yDistToWater < this->ageProperties->unk_2C)) {
s32 sp8C = (wallFlags & 8) ? 2 : 0;
if ((sp8C != 0) || (wallFlags & 2) ||
func_80041E4C(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId)) {
f32 phi_f20;
CollisionPoly* wallPoly = this->actor.wallPoly;
f32 sp80;
f32 sp7C;
f32 phi_f12;
f32 phi_f14;
phi_f20 = phi_f12 = 0.0f;
if (sp8C != 0) {
sp80 = this->actor.world.pos.x;
sp7C = this->actor.world.pos.z;
} else {
Vec3f sp50[3];
s32 i;
f32 sp48;
Vec3f* sp44 = &sp50[0];
s32 pad;
CollisionPoly_GetVerticesByBgId(wallPoly, this->actor.wallBgId, &play->colCtx, sp50);
sp80 = phi_f12 = sp44->x;
sp7C = phi_f14 = sp44->z;
phi_f20 = sp44->y;
for (i = 1; i < 3; i++) {
sp44++;
if (sp80 > sp44->x) {
sp80 = sp44->x;
} else if (phi_f12 < sp44->x) {
phi_f12 = sp44->x;
}
if (sp7C > sp44->z) {
sp7C = sp44->z;
} else if (phi_f14 < sp44->z) {
phi_f14 = sp44->z;
}
if (phi_f20 > sp44->y) {
phi_f20 = sp44->y;
}
}
sp80 = (sp80 + phi_f12) * 0.5f;
sp7C = (sp7C + phi_f14) * 0.5f;
phi_f12 = ((this->actor.world.pos.x - sp80) * COLPOLY_GET_NORMAL(wallPoly->normal.z)) -
((this->actor.world.pos.z - sp7C) * COLPOLY_GET_NORMAL(wallPoly->normal.x));
sp48 = this->actor.world.pos.y - phi_f20;
phi_f20 = ((f32)(s32)((sp48 / 15.000000223517418) + 0.5) * 15.000000223517418) - sp48;
phi_f12 = fabsf(phi_f12);
}
if (phi_f12 < 8.0f) {
f32 wallPolyNormalX = COLPOLY_GET_NORMAL(wallPoly->normal.x);
f32 wallPolyNormalZ = COLPOLY_GET_NORMAL(wallPoly->normal.z);
f32 sp34 = this->distToInteractWall;
LinkAnimationHeader* anim;
func_80836898(play, this, func_8083A3B0);
this->stateFlags1 |= PLAYER_STATE1_CLIMBING_LADDER;
this->stateFlags1 &= ~PLAYER_STATE1_IN_WATER;
if ((sp8C != 0) || (wallFlags & 2)) {
if ((this->av1.actionVar1 = sp8C) != 0) {
if (this->actor.bgCheckFlags & 1) {
anim = &gPlayerAnim_link_normal_Fclimb_startA;
} else {
anim = &gPlayerAnim_link_normal_Fclimb_hold2upL;
}
sp34 = (this->ageProperties->wallCheckRadius - 1.0f) - sp34;
} else {
anim = this->ageProperties->unk_A4;
sp34 = sp34 - 1.0f;
}
this->av2.actionVar2 = -2;
this->actor.world.pos.y += phi_f20;
this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000;
} else {
anim = this->ageProperties->unk_A8;
this->av2.actionVar2 = -4;
this->actor.shape.rot.y = this->yaw = this->actor.wallYaw;
}
this->actor.world.pos.x = (sp34 * wallPolyNormalX) + sp80;
this->actor.world.pos.z = (sp34 * wallPolyNormalZ) + sp7C;
func_80832224(this);
Math_Vec3f_Copy(&this->actor.prevPos, &this->actor.world.pos);
Player_AnimPlayOnce(play, this, anim);
Player_AnimReplaceApplyFlags(play, this, 0x9F);
return true;
}
}
}
}
return false;
}
void func_8083F070(Player* this, LinkAnimationHeader* anim, PlayState* play) {
func_80835DAC(play, this, Player_Action_8084C5F8, 0);
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, (4.0f / 3.0f));
}
/**
* @return true if Player chooses to enter crawlspace
*/
s32 Player_TryEnteringCrawlspace(Player* this, PlayState* play, u32 interactWallFlags) {
CollisionPoly* wallPoly;
Vec3f wallVertices[3];
f32 xVertex1;
f32 xVertex2;
f32 zVertex1;
f32 zVertex2;
s32 i;
if (!LINK_IS_ADULT && !(this->stateFlags1 & PLAYER_STATE1_IN_WATER) && (interactWallFlags & 0x30)) {
wallPoly = this->actor.wallPoly;
CollisionPoly_GetVerticesByBgId(wallPoly, this->actor.wallBgId, &play->colCtx, wallVertices);
// Determines min and max vertices for x & z (edges of the crawlspace hole)
xVertex1 = xVertex2 = wallVertices[0].x;
zVertex1 = zVertex2 = wallVertices[0].z;
for (i = 1; i < 3; i++) {
if (xVertex1 > wallVertices[i].x) {
// Update x min
xVertex1 = wallVertices[i].x;
} else if (xVertex2 < wallVertices[i].x) {
// Update x max
xVertex2 = wallVertices[i].x;
}
if (zVertex1 > wallVertices[i].z) {
// Update z min
zVertex1 = wallVertices[i].z;
} else if (zVertex2 < wallVertices[i].z) {
// Update z max
zVertex2 = wallVertices[i].z;
}
}
// XZ Center of the crawlspace hole
xVertex1 = (xVertex1 + xVertex2) * 0.5f;
zVertex1 = (zVertex1 + zVertex2) * 0.5f;
// Perpendicular (sideways) XZ-Distance from player pos to crawlspace line
// Uses y-component of crossproduct formula for the distance from a point to a line
xVertex2 = ((this->actor.world.pos.x - xVertex1) * COLPOLY_GET_NORMAL(wallPoly->normal.z)) -
((this->actor.world.pos.z - zVertex1) * COLPOLY_GET_NORMAL(wallPoly->normal.x));
if (fabsf(xVertex2) < 8.0f) {
// Give do-action prompt to "Enter on A" for the crawlspace
this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_ENTER;
if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) {
// Enter Crawlspace
f32 wallPolyNormX = COLPOLY_GET_NORMAL(wallPoly->normal.x);
f32 wallPolyNormZ = COLPOLY_GET_NORMAL(wallPoly->normal.z);
f32 distToInteractWall = this->distToInteractWall;
func_80836898(play, this, func_8083A40C);
this->stateFlags2 |= PLAYER_STATE2_CRAWLING;
this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000;
this->actor.world.pos.x = xVertex1 + (distToInteractWall * wallPolyNormX);
this->actor.world.pos.z = zVertex1 + (distToInteractWall * wallPolyNormZ);
func_80832224(this);
this->actor.prevPos = this->actor.world.pos;
// #region SOH [Enhancement]
if (CVarGetInteger("gCrawlSpeed", 1) > 1) {
// increase animation speed when entering a tunnel
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start,
((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f), 0.0f,
Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), ANIMMODE_ONCE,
0.0f);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
// #endregion
} else {
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_start);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
}
return true;
}
}
}
return false;
}
s32 func_8083F360(PlayState* play, Player* this, f32 arg1, f32 arg2, f32 arg3, f32 arg4) {
CollisionPoly* wallPoly;
s32 sp78;
Vec3f sp6C;
Vec3f sp60;
Vec3f sp54;
f32 yawCos;
f32 yawSin;
s32 temp;
f32 temp1;
f32 temp2;
yawCos = Math_CosS(this->actor.shape.rot.y);
yawSin = Math_SinS(this->actor.shape.rot.y);
sp6C.x = this->actor.world.pos.x + (arg4 * yawSin);
sp6C.z = this->actor.world.pos.z + (arg4 * yawCos);
sp60.x = this->actor.world.pos.x + (arg3 * yawSin);
sp60.z = this->actor.world.pos.z + (arg3 * yawCos);
sp60.y = sp6C.y = this->actor.world.pos.y + arg1;
if (BgCheck_EntityLineTest1(&play->colCtx, &sp6C, &sp60, &sp54, &this->actor.wallPoly, true, false, false,
true, &sp78)) {
wallPoly = this->actor.wallPoly;
this->actor.bgCheckFlags |= 0x200;
this->actor.wallBgId = sp78;
sTouchedWallFlags = func_80041DB8(&play->colCtx, wallPoly, sp78);
temp1 = COLPOLY_GET_NORMAL(wallPoly->normal.x);
temp2 = COLPOLY_GET_NORMAL(wallPoly->normal.z);
temp = Math_Atan2S(-temp2, -temp1);
Math_ScaledStepToS(&this->actor.shape.rot.y, temp, 800);
this->yaw = this->actor.shape.rot.y;
this->actor.world.pos.x = sp54.x - (Math_SinS(this->actor.shape.rot.y) * arg2);
this->actor.world.pos.z = sp54.z - (Math_CosS(this->actor.shape.rot.y) * arg2);
return 1;
}
this->actor.bgCheckFlags &= ~0x200;
return 0;
}
s32 func_8083F524(PlayState* play, Player* this) {
return func_8083F360(play, this, 26.0f, this->ageProperties->wallCheckRadius + 5.0f, 30.0f, 0.0f);
}
/**
* Two exit walls are placed at each end of the crawlspace, separate to the two entrance walls used to enter the
* crawlspace. These front and back exit walls are futher into the crawlspace than the front and
* back entrance walls. When player interacts with either of these two interior exit walls, start the leaving-crawlspace
* cutscene and return true. Else, return false
*/
s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) {
s16 temp;
if ((this->linearVelocity != 0.0f) && (this->actor.bgCheckFlags & 8) && (sTouchedWallFlags & 0x30)) {
temp = this->actor.shape.rot.y - this->actor.wallYaw;
if (this->linearVelocity < 0.0f) {
temp += 0x8000;
}
if (ABS(temp) > 0x4000) {
Player_SetupAction(play, this, Player_Action_8084C81C, 0);
if (this->linearVelocity > 0.0f) {
this->actor.shape.rot.y = this->actor.wallYaw + 0x8000;
// #region SOH [Enhancement]
if (CVarGetInteger("gCrawlSpeed", 1) > 1) {
// animation when exiting a tunnel forward
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_end,
((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f), 0.0f,
Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_end), ANIMMODE_ONCE,
0.0f);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
OnePointCutscene_Init(play, 9601, 999, NULL, MAIN_CAM);
// #endregion
} else {
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_end);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
OnePointCutscene_Init(play, 9601, 999, NULL, MAIN_CAM);
}
} else {
this->actor.shape.rot.y = this->actor.wallYaw;
// #region SOH [Enhancement]
// animation when exiting a tunnel backward
if (CVarGetInteger("gCrawlSpeed",1) > 1) {
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start,
-1.0f * ((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f),
Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, 0.0f);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM);
// #endregion
}
else {
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start, -1.0f,
Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, 0.0f);
Player_AnimReplaceApplyFlags(play, this, 0x9D);
OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM);
}
}
this->yaw = this->actor.shape.rot.y;
Player_ZeroSpeedXZ(this);
return 1;
}
}
return 0;
}
void func_8083F72C(Player* this, LinkAnimationHeader* anim, PlayState* play) {
if (!func_80836898(play, this, func_8083A388)) {
Player_SetupAction(play, this, Player_Action_8084B78C, 0);
}
Player_AnimPlayOnce(play, this, anim);
func_80832224(this);
this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000;
}
s32 Player_ActionChange_5(Player* this, PlayState* play) {
DynaPolyActor* wallPolyActor;
if (!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->actor.bgCheckFlags & 0x200) && (sShapeYawToTouchedWall < 0x3000)) {
if (((this->linearVelocity > 0.0f) && func_8083EC18(this, play, sTouchedWallFlags)) ||
Player_TryEnteringCrawlspace(this, play, sTouchedWallFlags)) {
return 1;
}
if (!func_808332B8(this) && ((this->linearVelocity == 0.0f) || !(this->stateFlags2 & PLAYER_STATE2_DO_ACTION_CLIMB)) &&
(sTouchedWallFlags & 0x40) && (this->actor.bgCheckFlags & 1) && (this->yDistToLedge >= 39.0f)) {
this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_GRAB;
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_A)) {
if ((this->actor.wallBgId != BGCHECK_SCENE) &&
((wallPolyActor = DynaPoly_GetActor(&play->colCtx, this->actor.wallBgId)) != NULL)) {
if (wallPolyActor->actor.id == ACTOR_BG_HEAVY_BLOCK) {
if (Player_GetStrength() < PLAYER_STR_GOLD_G) {
return 0;
}
func_80836898(play, this, func_8083A0F4);
this->stateFlags1 |= PLAYER_STATE1_ITEM_OVER_HEAD;
this->interactRangeActor = &wallPolyActor->actor;
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
this->yaw = this->actor.wallYaw + 0x8000;
func_80832224(this);
return 1;
}
this->unk_3C4 = &wallPolyActor->actor;
} else {
this->unk_3C4 = NULL;
}
func_8083F72C(this, &gPlayerAnim_link_normal_push_wait, play);
return 1;
}
}
}
return 0;
}
s32 func_8083F9D0(PlayState* play, Player* this) {
if ((this->actor.bgCheckFlags & 0x200) &&
((this->stateFlags2 & PLAYER_STATE2_MOVING_DYNAPOLY) || CHECK_BTN_ALL(sControlInput->cur.button, BTN_A))) {
DynaPolyActor* wallPolyActor = NULL;
if (this->actor.wallBgId != BGCHECK_SCENE) {
wallPolyActor = DynaPoly_GetActor(&play->colCtx, this->actor.wallBgId);
}
if (&wallPolyActor->actor == this->unk_3C4) {
if (this->stateFlags2 & PLAYER_STATE2_MOVING_DYNAPOLY) {
return 1;
} else {
return 0;
}
}
}
func_80839FFC(this, play);
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_push_wait_end);
this->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY;
return 1;
}
void func_8083FAB8(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_8084B898, 0);
this->stateFlags2 |= PLAYER_STATE2_MOVING_DYNAPOLY;
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_push_start);
}
void func_8083FB14(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_8084B9E4, 0);
this->stateFlags2 |= PLAYER_STATE2_MOVING_DYNAPOLY;
Player_AnimPlayOnce(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_pull_start, this->modelAnimType));
}
void func_8083FB7C(Player* this, PlayState* play) {
this->stateFlags1 &= ~(PLAYER_STATE1_CLIMBING_LADDER | PLAYER_STATE1_IN_WATER);
func_80837B9C(this, play);
this->linearVelocity = -0.4f;
}
s32 func_8083FBC0(Player* this, PlayState* play) {
if (!CHECK_BTN_ALL(sControlInput->press.button, BTN_A) && (this->actor.bgCheckFlags & 0x200) &&
((sTouchedWallFlags & 8) || (sTouchedWallFlags & 2) ||
func_80041E4C(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId))) {
return 0;
}
func_8083FB7C(this, play);
func_80832698(this, NA_SE_VO_LI_AUTO_JUMP);
return 1;
}
s32 func_8083FC68(Player* this, f32 arg1, s16 arg2) {
f32 sp1C = (s16)(arg2 - this->actor.shape.rot.y);
f32 temp;
if (this->unk_664 != NULL) {
func_8083DB98(this, func_8002DD78(this) || func_808334B4(this));
}
temp = fabsf(sp1C) / 32768.0f;
if (arg1 > (((temp * temp) * 50.0f) + 6.0f)) {
return 1;
} else if (arg1 > (((1.0f - temp) * 10.0f) + 6.8f)) {
return -1;
}
return 0;
}
s32 func_8083FD78(Player* this, f32* arg1, s16* arg2, PlayState* play) {
s16 sp2E = *arg2 - this->zTargetYaw;
u16 sp2C = ABS(sp2E);
if ((func_8002DD78(this) || func_808334B4(this)) && (this->unk_664 == NULL)) {
*arg1 *= Math_SinS(sp2C);
if (*arg1 != 0.0f) {
*arg2 = (((sp2E >= 0) ? 1 : -1) << 0xE) + this->actor.shape.rot.y;
} else {
*arg2 = this->actor.shape.rot.y;
}
// #region SOH [Enhancement]
if (CVarGetInteger("gRightStickAiming", 0) || !CVarGetInteger("gInvertZAimingYAxis", 1)) {
if (this->unk_664 != NULL) {
func_8083DB98(this, 1);
} else {
int8_t relStickY;
// preserves simultaneous left/right-stick aiming
if (CVarGetInteger("gRightStickAiming", 0)) {
if ((sControlInput->rel.stick_y + sControlInput->rel.right_stick_y) >= 0) {
relStickY = (((sControlInput->rel.stick_y) > (sControlInput->rel.right_stick_y))
? (sControlInput->rel.stick_y)
: (sControlInput->rel.right_stick_y));
} else {
relStickY = (((sControlInput->rel.stick_y) < (sControlInput->rel.right_stick_y))
? (sControlInput->rel.stick_y)
: (sControlInput->rel.right_stick_y));
}
} else {
relStickY = sControlInput->rel.stick_y;
}
Math_SmoothStepToS(&this->actor.focus.rot.x,
relStickY * (CVarGetInteger("gInvertZAimingYAxis", 1) ? 1 : -1) * 240.0f, 14, 4000, 30);
func_80836AB8(this, 1);
}
// #endregion
} else {
if (this->unk_664 != NULL) {
func_8083DB98(this, 1);
} else {
Math_SmoothStepToS(&this->actor.focus.rot.x, sControlInput->rel.stick_y * 240.0f, 14, 4000, 30);
func_80836AB8(this, 1);
}
}
} else {
if (this->unk_664 != NULL) {
return func_8083FC68(this, *arg1, *arg2);
} else {
func_8083DC54(this, play);
if ((*arg1 != 0.0f) && (sp2C < 6000)) {
return 1;
} else if (*arg1 > Math_SinS((0x4000 - (sp2C >> 1))) * 200.0f) {
return -1;
}
}
}
return 0;
}
s32 func_8083FFB8(Player* this, f32* arg1, s16* arg2) {
s16 temp1 = *arg2 - this->actor.shape.rot.y;
u16 temp2 = ABS(temp1);
f32 temp3 = Math_CosS(temp2);
*arg1 *= temp3;
if (*arg1 != 0.0f) {
if (temp3 > 0) {
return 1;
} else {
return -1;
}
}
return 0;
}
s32 func_80840058(Player* this, f32* arg1, s16* arg2, PlayState* play) {
func_8083DC54(this, play);
if ((*arg1 != 0.0f) || (ABS(this->unk_87C) > 400)) {
s16 temp1 = *arg2 - Camera_GetInputDirYaw(GET_ACTIVE_CAM(play));
u16 temp2 = (ABS(temp1) - 0x2000) & 0xFFFF;
if ((temp2 < 0x4000) || (this->unk_87C != 0)) {
return -1;
} else {
return 1;
}
}
return 0;
}
void func_80840138(Player* this, f32 arg1, s16 arg2) {
s16 temp = arg2 - this->actor.shape.rot.y;
if (arg1 > 0.0f) {
if (temp < 0) {
this->unk_874 = 0.0f;
} else {
this->unk_874 = 1.0f;
}
}
Math_StepToF(&this->unk_870, this->unk_874, 0.3f);
}
void func_808401B0(PlayState* play, Player* this) {
LinkAnimation_BlendToJoint(play, &this->skelAnime, func_808334E4(this), this->unk_868, func_80833528(this),
this->unk_868, this->unk_870, this->blendTable);
}
s32 func_8084021C(f32 arg0, f32 arg1, f32 arg2, f32 arg3) {
f32 temp;
if ((arg3 == 0.0f) && (arg1 > 0.0f)) {
arg3 = arg2;
}
temp = (arg0 + arg1) - arg3;
if (((temp * arg1) >= 0.0f) && (((temp - arg1) * arg1) < 0.0f)) {
return 1;
}
return 0;
}
void func_8084029C(Player* this, f32 arg1) {
f32 updateScale = R_UPDATE_RATE * 0.5f;
arg1 *= updateScale;
if (arg1 < -7.25) {
arg1 = -7.25;
} else if (arg1 > 7.25f) {
arg1 = 7.25f;
}
if ((this->currentBoots == PLAYER_BOOTS_HOVER ||
(CVarGetInteger("gIvanCoopModeEnabled", 0) && this->ivanFloating)) &&
!(this->actor.bgCheckFlags & 1) &&
(this->hoverBootsTimer != 0 || (CVarGetInteger("gIvanCoopModeEnabled", 0) && this->ivanFloating))) {
func_8002F8F0(&this->actor, NA_SE_PL_HOBBERBOOTS_LV - SFX_FLAG);
} else if (func_8084021C(this->unk_868, arg1, 29.0f, 10.0f) || func_8084021C(this->unk_868, arg1, 29.0f, 24.0f)) {
func_808327F8(this, this->linearVelocity);
if (this->linearVelocity > 4.0f) {
this->stateFlags2 |= PLAYER_STATE2_FOOTSTEP;
}
}
this->unk_868 += arg1;
if (this->unk_868 < 0.0f) {
this->unk_868 += 29.0f;
} else if (this->unk_868 >= 29.0f) {
this->unk_868 -= 29.0f;
}
}
void Player_Action_80840450(Player* this, PlayState* play) {
f32 speedTarget;
s16 yawTarget;
s32 temp1;
u32 temp2;
s16 temp3;
s32 temp4;
if (this->stateFlags3 & PLAYER_STATE3_FINISHED_ATTACKING) {
if (Player_GetMeleeWeaponHeld(this)) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
} else {
this->stateFlags3 &= ~PLAYER_STATE3_FINISHED_ATTACKING;
}
}
if (this->av2.actionVar2 != 0) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80832DBC(this);
Player_AnimPlayLoop(play, this, func_808334E4(this));
this->av2.actionVar2 = 0;
this->stateFlags3 &= ~PLAYER_STATE3_FINISHED_ATTACKING;
}
func_80833C3C(this);
} else {
func_808401B0(play, this);
}
func_8083721C(this);
if (!Player_TryActionChangeList(play, this, sActionChangeList1, true)) {
if (!func_80833B54(this) && (!func_80833B2C(this) || (func_80834B5C != this->upperActionFunc))) {
func_8083CF10(this, play);
return;
}
Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play);
temp1 = func_8083FC68(this, speedTarget, yawTarget);
if (temp1 > 0) {
func_8083C8DC(this, play, yawTarget);
return;
}
if (temp1 < 0) {
func_8083CBF0(this, yawTarget, play);
return;
}
if (speedTarget > 4.0f) {
func_8083CC9C(this, play);
return;
}
func_8084029C(this, (this->linearVelocity * 0.3f) + 1.0f);
func_80840138(this, speedTarget, yawTarget);
temp2 = this->unk_868;
if ((temp2 < 6) || ((temp2 - 0xE) < 6)) {
Math_StepToF(&this->linearVelocity, 0.0f, 1.5f);
return;
}
temp3 = yawTarget - this->yaw;
temp4 = ABS(temp3);
if (temp4 > 0x4000) {
if (Math_StepToF(&this->linearVelocity, 0.0f, 1.5f)) {
this->yaw = yawTarget;
}
return;
}
Math_AsymStepToF(&this->linearVelocity, speedTarget * 0.3f, 2.0f, 1.5f);
if (!(this->stateFlags3 & PLAYER_STATE3_FINISHED_ATTACKING)) {
Math_ScaledStepToS(&this->yaw, yawTarget, temp4 * 0.1f);
}
}
}
void Player_Action_808407CC(Player* this, PlayState* play) {
f32 speedTarget;
s16 yawTarget;
s32 temp1;
s16 temp2;
s32 temp3;
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80832DBC(this);
Player_AnimPlayOnce(play, this, func_80833338(this));
}
func_8083721C(this);
if (!Player_TryActionChangeList(play, this, sActionChangeList2, true)) {
if (func_80833B54(this)) {
func_8083CEAC(this, play);
return;
}
if (!func_80833B2C(this)) {
func_80835DAC(play, this, Player_Action_80840BC8, 1);
this->yaw = this->actor.shape.rot.y;
return;
}
if (func_80834B5C == this->upperActionFunc) {
func_8083CEAC(this, play);
return;
}
Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play);
temp1 = func_8083FD78(this, &speedTarget, &yawTarget, play);
if (temp1 > 0) {
func_8083C8DC(this, play, yawTarget);
return;
}
if (temp1 < 0) {
func_8083CB2C(this, yawTarget, play);
return;
}
if (speedTarget > 4.9f) {
func_8083CC9C(this, play);
func_80833C3C(this);
return;
}
if (speedTarget != 0.0f) {
func_8083CB94(this, play);
return;
}
temp2 = yawTarget - this->actor.shape.rot.y;
temp3 = ABS(temp2);
if (temp3 > 800) {
func_8083CD54(play, this, yawTarget);
}
}
}
void func_808409CC(PlayState* play, Player* this) {
LinkAnimationHeader* anim;
LinkAnimationHeader** animPtr;
s32 heathIsCritical;
s32 sp38;
s32 sp34;
if ((this->unk_664 != NULL) ||
(!(heathIsCritical = HealthMeter_IsCritical()) && ((this->unk_6AC = (this->unk_6AC + 1) & 1) != 0))) {
this->stateFlags2 &= ~PLAYER_STATE2_IDLING;
anim = func_80833338(this);
} else {
this->stateFlags2 |= PLAYER_STATE2_IDLING;
if (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
anim = func_80833338(this);
} else {
sp38 = play->roomCtx.curRoom.behaviorType2;
if (heathIsCritical) {
if (this->unk_6AC >= 0) {
sp38 = 7;
this->unk_6AC = -1;
} else {
sp38 = 8;
}
} else {
sp34 = Rand_ZeroOne() * 5.0f;
if (sp34 < 4) {
if (((sp34 != 0) && (sp34 != 3)) || ((this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
((sp34 == 3) || Player_GetMeleeWeaponHeld(this)))) {
if ((sp34 == 1) && Player_HoldsTwoHandedWeapon(this) && CVarGetInteger("gTwoHandedIdle", 0) == 1) {
sp34 = 4;
}
sp38 = sp34 + 9;
}
}
}
animPtr = &D_80853D7C[sp38][0];
if (this->modelAnimType != PLAYER_ANIMTYPE_1) {
animPtr = &D_80853D7C[sp38][1];
}
anim = *animPtr;
}
}
LinkAnimation_Change(play, &this->skelAnime, anim, (2.0f / 3.0f) * D_808535E8, 0.0f,
Animation_GetLastFrame(anim), ANIMMODE_ONCE, -6.0f);
}
void Player_Action_80840BC8(Player* this, PlayState* play) {
s32 sp44;
s32 sp40;
f32 speedTarget;
s16 yawTarget;
s16 temp;
sp44 = func_80833350(this);
sp40 = LinkAnimation_Update(play, &this->skelAnime);
if (sp44 > 0) {
func_808333FC(this, sp44 - 1);
}
if (sp40 != 0) {
if (this->av2.actionVar2 != 0) {
if (DECR(this->av2.actionVar2) == 0) {
this->skelAnime.endFrame = this->skelAnime.animLength - 1.0f;
}
this->skelAnime.jointTable[0].y = (this->skelAnime.jointTable[0].y + ((this->av2.actionVar2 & 1) * 0x50)) - 0x28;
} else {
func_80832DBC(this);
func_808409CC(play, this);
}
}
func_8083721C(this);
if (this->av2.actionVar2 == 0) {
if (!Player_TryActionChangeList(play, this, sActionChangeList7, true)) {
if (func_80833B54(this)) {
func_8083CEAC(this, play);
return;
}
if (func_80833B2C(this)) {
func_80839F30(this, play);
return;
}
Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_CURVED, play);
if (speedTarget != 0.0f) {
func_8083C8DC(this, play, yawTarget);
return;
}
temp = yawTarget - this->actor.shape.rot.y;
if (ABS(temp) > 800) {
func_8083CD54(play, this, yawTarget);
return;
}
Math_ScaledStepToS(&this->actor.shape.rot.y, yawTarget, 1200);
this->yaw = this->actor.shape.rot.y;
if (func_80833338(this) == this->skelAnime.animation) {
func_8083DC54(this, play);
}
}
}
}
void Player_Action_80840DE4(Player* this, PlayState* play) {
f32 frames;
f32 coeff;
f32 speedTarget;
s16 yawTarget;
s32 temp1;
s16 temp2;
s32 temp3;
s32 direction;
this->skelAnime.mode = 0;
LinkAnimation_SetUpdateFunction(&this->skelAnime);
this->skelAnime.animation = func_8083356C(this);
if (this->skelAnime.animation == &gPlayerAnim_link_bow_side_walk) {
frames = 24.0f;
coeff = -(MREG(95) / 100.0f);
} else {
frames = 29.0f;
coeff = MREG(95) / 100.0f;
}
this->skelAnime.animLength = frames;
this->skelAnime.endFrame = frames - 1.0f;
if ((s16)(this->yaw - this->actor.shape.rot.y) >= 0) {
direction = 1;
} else {
direction = -1;
}
this->skelAnime.playSpeed = direction * (this->linearVelocity * coeff);
LinkAnimation_Update(play, &this->skelAnime);
if (LinkAnimation_OnFrame(&this->skelAnime, 0.0f) || LinkAnimation_OnFrame(&this->skelAnime, frames * 0.5f)) {
func_808327F8(this, this->linearVelocity);
}
if (!Player_TryActionChangeList(play, this, sActionChangeList3, true)) {
if (func_80833B54(this)) {
func_8083CEAC(this, play);
return;
}
if (!func_80833B2C(this)) {
func_80853080(this, play);
return;
}
Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play);
temp1 = func_8083FD78(this, &speedTarget, &yawTarget, play);
if (temp1 > 0) {
func_8083C8DC(this, play, yawTarget);
return;
}
if (temp1 < 0) {
func_8083CB2C(this, yawTarget, play);
return;
}
if (speedTarget > 4.9f) {
func_8083CC9C(this, play);
func_80833C3C(this);
return;
}
if ((speedTarget == 0.0f) && (this->linearVelocity == 0.0f)) {
func_80839F30(this, play);
return;
}
temp2 = yawTarget - this->yaw;
temp3 = ABS(temp2);
if (temp3 > 0x4000) {
if (Math_StepToF(&this->linearVelocity, 0.0f, 1.5f)) {
this->yaw = yawTarget;
}
return;
}
Math_AsymStepToF(&this->linearVelocity, speedTarget * 0.4f, 1.5f, 1.5f);
Math_ScaledStepToS(&this->yaw, yawTarget, temp3 * 0.1f);
}
}
void func_80841138(Player* this, PlayState* play) {
f32 temp1;
f32 temp2;
if (this->unk_864 < 1.0f) {
temp1 = R_UPDATE_RATE * 0.5f;
func_8084029C(this, REG(35) / 1000.0f);
LinkAnimation_LoadToJoint(play, &this->skelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_back_walk, this->modelAnimType),
this->unk_868);
this->unk_864 += 1 * temp1;
if (this->unk_864 >= 1.0f) {
this->unk_864 = 1.0f;
}
temp1 = this->unk_864;
} else {
temp2 = this->linearVelocity - (REG(48) / 100.0f);
if (temp2 < 0.0f) {
temp1 = 1.0f;
func_8084029C(this, (REG(35) / 1000.0f) + ((REG(36) / 1000.0f) * this->linearVelocity));
LinkAnimation_LoadToJoint(play, &this->skelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_back_walk, this->modelAnimType),
this->unk_868);
} else {
temp1 = (REG(37) / 1000.0f) * temp2;
if (temp1 < 1.0f) {
func_8084029C(this, (REG(35) / 1000.0f) + ((REG(36) / 1000.0f) * this->linearVelocity));
} else {
temp1 = 1.0f;
func_8084029C(this, 1.2f + ((REG(38) / 1000.0f) * temp2));
}
LinkAnimation_LoadToMorph(play, &this->skelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_back_walk, this->modelAnimType),
this->unk_868);
LinkAnimation_LoadToJoint(play, &this->skelAnime, &gPlayerAnim_link_normal_back_run,
this->unk_868 * (16.0f / 29.0f));
}
}
if (temp1 < 1.0f) {
LinkAnimation_InterpJointMorph(play, &this->skelAnime, 1.0f - temp1);
}
}
void func_8084140C(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_8084170C, 1);
Player_AnimChangeOnceMorph(play, this, &gPlayerAnim_link_normal_back_brake);
}
s32 func_80841458(Player* this, f32* arg1, s16* arg2, PlayState* play) {
if (this->linearVelocity > 6.0f) {
func_8084140C(this, play);
return 1;
}
if (*arg1 != 0.0f) {
if (func_8083721C(this)) {
*arg1 = 0.0f;
*arg2 = this->yaw;
} else {
return 1;
}
}
return 0;
}
void Player_Action_808414F8(Player* this, PlayState* play) {
f32 speedTarget;
s16 yawTarget;
s32 sp2C;
s16 sp2A;
func_80841138(this, play);
if (!Player_TryActionChangeList(play, this, sActionChangeList4, true)) {
if (!func_80833C04(this)) {
func_8083C8DC(this, play, this->yaw);
return;
}
Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play);
sp2C = func_8083FD78(this, &speedTarget, &yawTarget, play);
if (sp2C >= 0) {
if (!func_80841458(this, &speedTarget, &yawTarget, play)) {
if (sp2C != 0) {
func_8083C858(this, play);
} else if (speedTarget > 4.9f) {
func_8083CC9C(this, play);
} else {
func_8083CB94(this, play);
}
}
} else {
sp2A = yawTarget - this->yaw;
Math_AsymStepToF(&this->linearVelocity, speedTarget * 1.5f, 1.5f, 2.0f);
Math_ScaledStepToS(&this->yaw, yawTarget, sp2A * 0.1f);
if ((speedTarget == 0.0f) && (this->linearVelocity == 0.0f)) {
func_80839F30(this, play);
}
}
}
}
void func_808416C0(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_808417FC, 1);
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_back_brake_end);
}
void Player_Action_8084170C(Player* this, PlayState* play) {
s32 sp34;
f32 speedTarget;
s16 yawTarget;
sp34 = LinkAnimation_Update(play, &this->skelAnime);
func_8083721C(this);
if (!Player_TryActionChangeList(play, this, sActionChangeList4, true)) {
Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play);
if (this->linearVelocity == 0.0f) {
this->yaw = this->actor.shape.rot.y;
if (func_8083FD78(this, &speedTarget, &yawTarget, play) > 0) {
func_8083C858(this, play);
} else if ((speedTarget != 0.0f) || (sp34 != 0)) {
func_808416C0(this, play);
}
}
}
}
void Player_Action_808417FC(Player* this, PlayState* play) {
s32 sp1C;
sp1C = LinkAnimation_Update(play, &this->skelAnime);
if (!Player_TryActionChangeList(play, this, sActionChangeList4, true)) {
if (sp1C != 0) {
func_80839F30(this, play);
}
}
}
void func_80841860(PlayState* play, Player* this) {
f32 frame;
// fake match? see Player_InitItemActionWithAnim
LinkAnimationHeader* sp38 = D_80853914[0][this->modelAnimType + PLAYER_ANIMGROUP_side_walkL * ARRAY_COUNT(D_80853914[0])];
LinkAnimationHeader* sp34 = D_80853914[0][this->modelAnimType + PLAYER_ANIMGROUP_side_walkR * ARRAY_COUNT(D_80853914[0])];
this->skelAnime.animation = sp38;
func_8084029C(this, (REG(30) / 1000.0f) + ((REG(32) / 1000.0f) * this->linearVelocity));
frame = this->unk_868 * (16.0f / 29.0f);
LinkAnimation_BlendToJoint(play, &this->skelAnime, sp34, frame, sp38, frame, this->unk_870, this->blendTable);
}
void Player_Action_8084193C(Player* this, PlayState* play) {
f32 speedTarget;
s16 yawTarget;
s32 temp1;
s16 temp2;
s32 temp3;
func_80841860(play, this);
if (!Player_TryActionChangeList(play, this, sActionChangeList5, true)) {
if (!func_80833C04(this)) {
func_8083C858(this, play);
return;
}
Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play);
if (func_80833B2C(this)) {
temp1 = func_8083FD78(this, &speedTarget, &yawTarget, play);
} else {
temp1 = func_8083FC68(this, speedTarget, yawTarget);
}
if (temp1 > 0) {
func_8083C858(this, play);
return;
}
if (temp1 < 0) {
if (func_80833B2C(this)) {
func_8083CB2C(this, yawTarget, play);
} else {
func_8083CBF0(this, yawTarget, play);
}
return;
}
if ((this->linearVelocity < 3.6f) && (speedTarget < 4.0f)) {
if (!func_8008E9C4(this) && func_80833B2C(this)) {
func_8083CB94(this, play);
} else {
func_80839F90(this, play);
}
return;
}
func_80840138(this, speedTarget, yawTarget);
temp2 = yawTarget - this->yaw;
temp3 = ABS(temp2);
if (temp3 > 0x4000) {
if (Math_StepToF(&this->linearVelocity, 0.0f, 3.0f) != 0) {
this->yaw = yawTarget;
}
return;
}
speedTarget *= 0.9f;
Math_AsymStepToF(&this->linearVelocity, speedTarget, 2.0f, 3.0f);
Math_ScaledStepToS(&this->yaw, yawTarget, temp3 * 0.1f);
}
}
void Player_Action_80841BA8(Player* this, PlayState* play) {
f32 sp34;
s16 sp32;
LinkAnimation_Update(play, &this->skelAnime);
if (Player_HoldsTwoHandedWeapon(this)) {
AnimationContext_SetLoadFrame(play, func_80833338(this), 0, this->skelAnime.limbCount,
this->skelAnime.morphTable);
AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->skelAnime.morphTable, sUpperBodyLimbCopyMap);
}
Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_CURVED, play);
if (!Player_TryActionChangeList(play, this, sActionChangeList6, true)) {
if (sp34 != 0.0f) {
this->actor.shape.rot.y = sp32;
func_8083C858(this, play);
} else if (Math_ScaledStepToS(&this->actor.shape.rot.y, sp32, this->unk_87E)) {
func_8083C0E8(this, play);
}
this->yaw = this->actor.shape.rot.y;
}
}
void func_80841CC4(Player* this, s32 arg1, PlayState* play) {
LinkAnimationHeader* anim;
s16 target;
f32 rate;
if (ABS(sFloorShapePitch) < 3640) {
target = 0;
} else {
target = CLAMP(sFloorShapePitch, -10922, 10922);
}
Math_ScaledStepToS(&this->unk_89C, target, 400);
if ((this->modelAnimType == PLAYER_ANIMTYPE_3) || ((this->unk_89C == 0) && (this->unk_6C4 <= 0.0f))) {
if (arg1 == 0) {
LinkAnimation_LoadToJoint(play, &this->skelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_walk, this->modelAnimType),
this->unk_868);
} else {
LinkAnimation_LoadToMorph(play, &this->skelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_walk, this->modelAnimType),
this->unk_868);
}
return;
}
if (this->unk_89C != 0) {
rate = this->unk_89C / 10922.0f;
} else {
rate = this->unk_6C4 * 0.0006f;
}
rate *= fabsf(this->linearVelocity) * 0.5f;
if (rate > 1.0f) {
rate = 1.0f;
}
if (rate < 0.0f) {
anim = &gPlayerAnim_link_normal_climb_down;
rate = -rate;
} else {
anim = &gPlayerAnim_link_normal_climb_up;
}
if (arg1 == 0) {
LinkAnimation_BlendToJoint(play, &this->skelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_walk, this->modelAnimType),
this->unk_868, anim, this->unk_868, rate, this->blendTable);
} else {
LinkAnimation_BlendToMorph(play, &this->skelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_walk, this->modelAnimType),
this->unk_868, anim, this->unk_868, rate, this->blendTable);
}
}
void func_80841EE4(Player* this, PlayState* play) {
f32 temp1;
f32 temp2;
if (this->unk_864 < 1.0f) {
temp1 = R_UPDATE_RATE * 0.5f;
func_8084029C(this, REG(35) / 1000.0f);
LinkAnimation_LoadToJoint(play, &this->skelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_walk, this->modelAnimType),
this->unk_868);
this->unk_864 += 1 * temp1;
if (this->unk_864 >= 1.0f) {
this->unk_864 = 1.0f;
}
temp1 = this->unk_864;
} else {
temp2 = this->linearVelocity - (REG(48) / 100.0f);
if (temp2 < 0.0f) {
temp1 = 1.0f;
func_8084029C(this, (REG(35) / 1000.0f) + ((REG(36) / 1000.0f) * this->linearVelocity));
func_80841CC4(this, 0, play);
} else {
temp1 = (REG(37) / 1000.0f) * temp2;
if (temp1 < 1.0f) {
func_8084029C(this, (REG(35) / 1000.0f) + ((REG(36) / 1000.0f) * this->linearVelocity));
} else {
temp1 = 1.0f;
func_8084029C(this, 1.2f + ((REG(38) / 1000.0f) * temp2));
}
func_80841CC4(this, 1, play);
LinkAnimation_LoadToJoint(play, &this->skelAnime, func_80833438(this),
this->unk_868 * (20.0f / 29.0f));
}
}
if (temp1 < 1.0f) {
LinkAnimation_InterpJointMorph(play, &this->skelAnime, 1.0f - temp1);
}
}
void Player_Action_80842180(Player* this, PlayState* play) {
f32 sp2C;
s16 sp2A;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
func_80841EE4(this, play);
if (!Player_TryActionChangeList(play, this, sActionChangeList8, true)) {
if (func_80833C04(this)) {
func_8083C858(this, play);
return;
}
Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_CURVED, play);
if (!func_8083C484(this, &sp2C, &sp2A)) {
int32_t giSpeedModifier = GameInteractor_RunSpeedModifier();
if (giSpeedModifier != 0) {
if (giSpeedModifier > 0) {
sp2C *= giSpeedModifier;
} else {
sp2C /= abs(giSpeedModifier);
}
}
if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) {
sp2C *= 1.5f;
}
if (CVarGetInteger("gEnableWalkModify", 0)) {
if (CVarGetInteger("gWalkSpeedToggle", 0)) {
if (gWalkSpeedToggle1) {
sp2C *= CVarGetFloat("gWalkModifierOne", 1.0f);
} else if (gWalkSpeedToggle2) {
sp2C *= CVarGetFloat("gWalkModifierTwo", 1.0f);
}
} else {
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER1)) {
sp2C *= CVarGetFloat("gWalkModifierOne", 1.0f);
} else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER2)) {
sp2C *= CVarGetFloat("gWalkModifierTwo", 1.0f);
}
}
}
func_8083DF68(this, sp2C, sp2A);
func_8083DDC8(this, play);
if ((this->linearVelocity == 0.0f) && (sp2C == 0.0f)) {
func_8083C0B8(this, play);
}
}
}
}
void Player_Action_8084227C(Player* this, PlayState* play) {
f32 sp2C;
s16 sp2A;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
func_80841EE4(this, play);
if (!Player_TryActionChangeList(play, this, sActionChangeList9, true)) {
if (!func_80833C04(this)) {
func_8083C858(this, play);
return;
}
Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_LINEAR, play);
if (!func_8083C484(this, &sp2C, &sp2A)) {
if ((func_80833B2C(this) && (sp2C != 0.0f) && (func_8083FD78(this, &sp2C, &sp2A, play) <= 0)) ||
(!func_80833B2C(this) && (func_8083FC68(this, sp2C, sp2A) <= 0))) {
func_80839F90(this, play);
return;
}
func_8083DF68(this, sp2C, sp2A);
func_8083DDC8(this, play);
if ((this->linearVelocity == 0) && (sp2C == 0)) {
func_80839F90(this, play);
}
}
}
}
void Player_Action_808423EC(Player* this, PlayState* play) {
s32 sp34;
f32 sp30;
s16 sp2E;
sp34 = LinkAnimation_Update(play, &this->skelAnime);
if (!Player_TryActionChangeList(play, this, sActionChangeList5, true)) {
if (!func_80833C04(this)) {
func_8083C858(this, play);
return;
}
Player_GetMovementSpeedAndYaw(this, &sp30, &sp2E, SPEED_MODE_LINEAR, play);
if ((this->skelAnime.morphWeight == 0.0f) && (this->skelAnime.curFrame > 5.0f)) {
func_8083721C(this);
if ((this->skelAnime.curFrame > 10.0f) && (func_8083FC68(this, sp30, sp2E) < 0)) {
func_8083CBF0(this, sp2E, play);
return;
}
if (sp34 != 0) {
func_8083CD00(this, play);
}
}
}
}
void Player_Action_8084251C(Player* this, PlayState* play) {
s32 sp34;
f32 speedTarget;
s16 yawTarget;
sp34 = LinkAnimation_Update(play, &this->skelAnime);
func_8083721C(this);
if (!Player_TryActionChangeList(play, this, sActionChangeList10, true)) {
Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play);
if (this->linearVelocity == 0.0f) {
this->yaw = this->actor.shape.rot.y;
if (func_8083FC68(this, speedTarget, yawTarget) > 0) {
func_8083C858(this, play);
return;
}
if ((speedTarget != 0.0f) || (sp34 != 0)) {
func_80839F90(this, play);
}
}
}
}
void func_8084260C(Vec3f* src, Vec3f* dest, f32 arg2, f32 arg3, f32 arg4) {
dest->x = (Rand_ZeroOne() * arg3) + src->x;
dest->y = (Rand_ZeroOne() * arg4) + (src->y + arg2);
dest->z = (Rand_ZeroOne() * arg3) + src->z;
}
static Vec3f D_808545B4 = { 0.0f, 0.0f, 0.0f };
static Vec3f D_808545C0 = { 0.0f, 0.0f, 0.0f };
s32 func_8084269C(PlayState* play, Player* this) {
Vec3f sp2C;
if ((this->floorSfxOffset == 0) || (this->floorSfxOffset == 1)) {
func_8084260C(&this->actor.shape.feetPos[FOOT_LEFT], &sp2C,
this->actor.floorHeight - this->actor.shape.feetPos[FOOT_LEFT].y, 7.0f, 5.0f);
func_800286CC(play, &sp2C, &D_808545B4, &D_808545C0, 50, 30);
func_8084260C(&this->actor.shape.feetPos[FOOT_RIGHT], &sp2C,
this->actor.floorHeight - this->actor.shape.feetPos[FOOT_RIGHT].y, 7.0f, 5.0f);
func_800286CC(play, &this->actor.shape.feetPos[FOOT_RIGHT], &D_808545B4, &D_808545C0, 50, 30);
return 1;
}
return 0;
}
void Player_Action_8084279C(Player* this, PlayState* play) {
func_80832CB0(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_check_wait, this->modelAnimType));
if (DECR(this->av2.actionVar2) == 0) {
if (!Player_ActionChange_13(this, play)) {
func_8083A098(this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_check_end, this->modelAnimType), play);
}
this->actor.flags &= ~ACTOR_FLAG_PLAYER_TALKED_TO;
func_8005B1A4(Play_GetCamera(play, 0));
}
}
s32 func_8084285C(Player* this, f32 arg1, f32 arg2, f32 arg3) {
if ((arg1 <= this->skelAnime.curFrame) && (this->skelAnime.curFrame <= arg3)) {
func_80833A20(this, (arg2 <= this->skelAnime.curFrame) ? 1 : -1);
return 1;
}
func_80832318(this);
return 0;
}
s32 func_808428D8(Player* this, PlayState* play) {
if (Player_IsChildWithHylianShield(this) || !Player_GetMeleeWeaponHeld(this) || !sUseHeldItem) {
return 0;
}
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_defense_kiru);
this->av1.actionVar1 = 1;
this->meleeWeaponAnimation = PLAYER_MWA_STAB_1H;
this->yaw = this->actor.shape.rot.y + this->unk_6BE;
if (!CVarGetInteger("gCrouchStabHammerFix", 0)) {
return 1;
}
u32 swordId;
if (Player_HoldsBrokenKnife(this)) {
swordId = 1;
} else {
swordId = Player_GetMeleeWeaponHeld(this) - 1;
}
if (swordId != 4 && !CVarGetInteger("gCrouchStabFix", 0)) { // 4 = Megaton Hammer
return 1;
}
u32 flags = D_80854488[swordId][0];
func_80837918(this, 0, flags);
func_80837918(this, 1, flags);
return 1;
}
s32 func_80842964(Player* this, PlayState* play) {
return Player_ActionChange_13(this, play) || Player_ActionChange_4(this, play) || Player_ActionChange_2(this, play);
}
void Player_RequestQuake(PlayState* play, s32 speed, s32 y, s32 countdown) {
s32 quakeIndex = Quake_Add(Play_GetCamera(play, 0), 3);
Quake_SetSpeed(quakeIndex, speed);
Quake_SetQuakeValues(quakeIndex, y, 0, 0, 0);
Quake_SetCountdown(quakeIndex, countdown);
}
void func_80842A28(PlayState* play, Player* this) {
Player_RequestQuake(play, 27767, 7, 20);
play->actorCtx.unk_02 = 4;
Player_RequestRumble(this, 255, 20, 150, 0);
Player_PlaySfx(this, NA_SE_IT_HAMMER_HIT);
}
void func_80842A88(PlayState* play, Player* this) {
if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) {
Inventory_ChangeAmmo(ITEM_STICK, -1);
Player_UseItem(play, this, ITEM_NONE);
}
}
s32 func_80842AC4(PlayState* play, Player* this) {
if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && (this->unk_85C > 0.5f)) {
if (AMMO(ITEM_STICK) != 0 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) {
EffectSsStick_Spawn(play, &this->bodyPartsPos[PLAYER_BODYPART_R_HAND],
this->actor.shape.rot.y + 0x8000);
this->unk_85C = 0.5f;
func_80842A88(play, this);
Player_PlaySfx(this, NA_SE_IT_WOODSTICK_BROKEN);
}
return 1;
}
return 0;
}
s32 func_80842B7C(PlayState* play, Player* this) {
if (this->heldItemAction == PLAYER_IA_SWORD_BIGGORON) {
if (!gSaveContext.bgsFlag && (gSaveContext.swordHealth > 0.0f)) {
if ((gSaveContext.swordHealth -= 1.0f) <= 0.0f) {
EffectSsStick_Spawn(play, &this->bodyPartsPos[PLAYER_BODYPART_R_HAND],
this->actor.shape.rot.y + 0x8000);
func_800849EC(play);
Player_PlaySfx(this, NA_SE_IT_MAJIN_SWORD_BROKEN);
}
}
return 1;
}
return 0;
}
void func_80842CF0(PlayState* play, Player* this) {
func_80842AC4(play, this);
func_80842B7C(play, this);
}
static LinkAnimationHeader* D_808545CC[] = {
&gPlayerAnim_link_fighter_rebound,
&gPlayerAnim_link_fighter_rebound_long,
&gPlayerAnim_link_fighter_reboundR,
&gPlayerAnim_link_fighter_rebound_longR,
};
void func_80842D20(PlayState* play, Player* this) {
s32 pad;
s32 sp28;
if (Player_Action_80843188 != this->actionFunc) {
func_80832440(play, this);
Player_SetupAction(play, this, Player_Action_808505DC, 0);
if (func_8008E9C4(this)) {
sp28 = 2;
} else {
sp28 = 0;
}
Player_AnimPlayOnceAdjusted(play, this, D_808545CC[Player_HoldsTwoHandedWeapon(this) + sp28]);
}
Player_RequestRumble(this, 180, 20, 100, 0);
this->linearVelocity = -18.0f;
func_80842CF0(play, this);
}
s32 func_80842DF4(PlayState* play, Player* this) {
f32 phi_f2;
CollisionPoly* sp78;
s32 sp74;
Vec3f sp68;
Vec3f sp5C;
Vec3f sp50;
s32 temp1;
s32 sp48;
if (this->meleeWeaponState > 0) {
if (this->meleeWeaponAnimation < PLAYER_MWA_SPIN_ATTACK_1H) {
if (!(this->meleeWeaponQuads[0].base.atFlags & AT_BOUNCED) && !(this->meleeWeaponQuads[1].base.atFlags & AT_BOUNCED)) {
if (this->skelAnime.curFrame >= 2.0f) {
phi_f2 = Math_Vec3f_DistXYZAndStoreDiff(&this->meleeWeaponInfo[0].tip, &this->meleeWeaponInfo[0].base, &sp50);
if (phi_f2 != 0.0f) {
phi_f2 = (phi_f2 + 10.0f) / phi_f2;
}
sp68.x = this->meleeWeaponInfo[0].tip.x + (sp50.x * phi_f2);
sp68.y = this->meleeWeaponInfo[0].tip.y + (sp50.y * phi_f2);
sp68.z = this->meleeWeaponInfo[0].tip.z + (sp50.z * phi_f2);
if (BgCheck_EntityLineTest1(&play->colCtx, &sp68, &this->meleeWeaponInfo[0].tip, &sp5C, &sp78, true,
false, false, true, &sp74) &&
!SurfaceType_IsIgnoredByEntities(&play->colCtx, sp78, sp74) &&
(func_80041D4C(&play->colCtx, sp78, sp74) != 6) &&
(func_8002F9EC(play, &this->actor, sp78, sp74, &sp5C) == 0)) {
if (this->heldItemAction == PLAYER_IA_HAMMER) {
func_80832630(play);
func_80842A28(play, this);
func_80842D20(play, this);
return 1;
}
if (this->linearVelocity >= 0.0f) {
sp48 = func_80041F10(&play->colCtx, sp78, sp74);
if (sp48 == 0xA) {
CollisionCheck_SpawnShieldParticlesWood(play, &sp5C, &this->actor.projectedPos);
} else {
CollisionCheck_SpawnShieldParticles(play, &sp5C);
if (sp48 == 0xB) {
Player_PlaySfx(this, NA_SE_IT_WALL_HIT_SOFT);
} else {
Player_PlaySfx(this, NA_SE_IT_WALL_HIT_HARD);
}
}
func_80842CF0(play, this);
this->linearVelocity = -14.0f;
Player_RequestRumble(this, 180, 20, 100, 0);
}
}
}
} else {
func_80842D20(play, this);
func_80832630(play);
return 1;
}
}
temp1 = (this->meleeWeaponQuads[0].base.atFlags & AT_HIT) || (this->meleeWeaponQuads[1].base.atFlags & AT_HIT);
if (temp1) {
if (this->meleeWeaponAnimation < PLAYER_MWA_SPIN_ATTACK_1H) {
Actor* at = this->meleeWeaponQuads[temp1 ? 1 : 0].base.at;
if ((at != NULL) && (at->id != ACTOR_EN_KANBAN)) {
func_80832630(play);
}
}
if ((func_80842AC4(play, this) == 0) && (this->heldItemAction != PLAYER_IA_HAMMER)) {
func_80842B7C(play, this);
if (this->actor.colChkInfo.atHitEffect == 1) {
this->actor.colChkInfo.damage = 8;
func_80837C0C(play, this, 4, 0.0f, 0.0f, this->actor.shape.rot.y, 20);
return 1;
}
}
}
}
return 0;
}
void Player_Action_80843188(Player* this, PlayState* play) {
f32 sp54;
f32 sp50;
s16 sp4E;
s16 sp4C;
s16 sp4A;
s16 sp48;
s16 sp46;
f32 sp40;
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (!Player_IsChildWithHylianShield(this)) {
Player_AnimPlayLoop(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_defense_wait, this->modelAnimType));
}
this->av2.actionVar2 = 1;
this->av1.actionVar1 = 0;
}
if (!Player_IsChildWithHylianShield(this)) {
this->stateFlags1 |= PLAYER_STATE1_SHIELDING;
Player_UpdateUpperBody(this, play);
this->stateFlags1 &= ~PLAYER_STATE1_SHIELDING;
}
func_8083721C(this);
if (this->av2.actionVar2 != 0) {
sp54 = sControlInput->rel.stick_y * 100 * (CVarGetInteger("gInvertShieldAimingYAxis", 1) ? 1 : -1);
sp50 = sControlInput->rel.stick_x * (CVarGetInteger("gMirroredWorld", 0) ? 120 : -120) * (CVarGetInteger("gInvertShieldAimingXAxis", 0) ? -1 : 1);
sp4E = this->actor.shape.rot.y - Camera_GetInputDirYaw(GET_ACTIVE_CAM(play));
sp40 = Math_CosS(sp4E);
sp4C = (Math_SinS(sp4E) * sp50) + (sp54 * sp40);
sp40 = Math_CosS(sp4E);
sp4A = (sp50 * sp40) - (Math_SinS(sp4E) * sp54);
if (sp4C > 3500) {
sp4C = 3500;
}
sp48 = ABS(sp4C - this->actor.focus.rot.x) * 0.25f;
if (sp48 < 100) {
sp48 = 100;
}
sp46 = ABS(sp4A - this->unk_6BE) * 0.25f;
if (sp46 < 50) {
sp46 = 50;
}
Math_ScaledStepToS(&this->actor.focus.rot.x, sp4C, sp48);
this->unk_6BC = this->actor.focus.rot.x;
Math_ScaledStepToS(&this->unk_6BE, sp4A, sp46);
if (this->av1.actionVar1 != 0) {
if (!func_80842DF4(play, this)) {
if (this->skelAnime.curFrame < 2.0f) {
func_80833A20(this, 1);
}
} else {
this->av2.actionVar2 = 1;
this->av1.actionVar1 = 0;
}
} else if (!func_80842964(this, play)) {
if (Player_ActionChange_11(this, play)) {
func_808428D8(this, play);
} else {
this->stateFlags1 &= ~PLAYER_STATE1_SHIELDING;
func_80832318(this);
if (Player_IsChildWithHylianShield(this)) {
func_8083A060(this, play);
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_clink_normal_defense_ALL, 1.0f,
Animation_GetLastFrame(&gPlayerAnim_clink_normal_defense_ALL), 0.0f,
ANIMMODE_ONCE, 0.0f);
Player_AnimReplaceApplyFlags(play, this, 4);
} else {
if (this->itemAction < 0) {
func_8008EC70(this);
}
func_8083A098(this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_defense_end, this->modelAnimType), play);
}
Player_PlaySfx(this, NA_SE_IT_SHIELD_REMOVE);
return;
}
} else {
return;
}
}
this->stateFlags1 |= PLAYER_STATE1_SHIELDING;
Player_SetModelsForHoldingShield(this);
this->unk_6AE |= 0xC1;
}
void Player_Action_808435C4(Player* this, PlayState* play) {
s32 temp;
LinkAnimationHeader* anim;
f32 frames;
func_8083721C(this);
if (this->av1.actionVar1 == 0) {
D_808535E0 = Player_UpdateUpperBody(this, play);
if ((func_80834B5C == this->upperActionFunc) || (func_808374A0(play, this, &this->upperSkelAnime, 4.0f) > 0)) {
Player_SetupAction(play, this, Player_Action_80840450, 1);
}
} else {
temp = func_808374A0(play, this, &this->skelAnime, 4.0f);
if ((temp != 0) && ((temp > 0) || LinkAnimation_Update(play, &this->skelAnime))) {
Player_SetupAction(play, this, Player_Action_80843188, 1);
this->stateFlags1 |= PLAYER_STATE1_SHIELDING;
Player_SetModelsForHoldingShield(this);
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_defense, this->modelAnimType);
frames = Animation_GetLastFrame(anim);
LinkAnimation_Change(play, &this->skelAnime, anim, 1.0f, frames, frames, ANIMMODE_ONCE, 0.0f);
}
}
}
void Player_Action_8084370C(Player* this, PlayState* play) {
s32 sp1C;
func_8083721C(this);
sp1C = func_808374A0(play, this, &this->skelAnime, 16.0f);
if ((sp1C != 0) && (LinkAnimation_Update(play, &this->skelAnime) || (sp1C > 0))) {
func_80839F90(this, play);
}
}
void Player_Action_8084377C(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
func_808382BC(this);
if (!(this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) && (this->av2.actionVar2 == 0) && (this->unk_8A1 != 0)) {
s16 temp = this->actor.shape.rot.y - this->unk_8A2;
this->yaw = this->actor.shape.rot.y = this->unk_8A2;
this->linearVelocity = this->unk_8A4;
if (ABS(temp) > 0x4000) {
this->actor.shape.rot.y = this->unk_8A2 + 0x8000;
}
if (this->actor.velocity.y < 0.0f) {
this->actor.gravity = 0.0f;
this->actor.velocity.y = 0.0f;
}
}
if (LinkAnimation_Update(play, &this->skelAnime) && (this->actor.bgCheckFlags & 1)) {
if (this->av2.actionVar2 != 0) {
this->av2.actionVar2--;
if (this->av2.actionVar2 == 0) {
func_80853080(this, play);
}
} else if ((this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) ||
(!(this->cylinder.base.acFlags & AC_HIT) && (this->unk_8A1 == 0))) {
if (this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) {
this->av2.actionVar2++;
} else {
Player_SetupAction(play, this, Player_Action_80843954, 0);
this->stateFlags1 |= PLAYER_STATE1_DAMAGED;
}
Player_AnimPlayOnce(play, this,
(this->yaw != this->actor.shape.rot.y) ? &gPlayerAnim_link_normal_front_downB
: &gPlayerAnim_link_normal_back_downB);
func_80832698(this, NA_SE_VO_LI_FREEZE);
}
}
if (this->actor.bgCheckFlags & 2) {
func_80832770(this, NA_SE_PL_BOUND);
}
}
void Player_Action_80843954(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
func_808382BC(this);
func_8083721C(this);
if (LinkAnimation_Update(play, &this->skelAnime) && (this->linearVelocity == 0.0f)) {
if (this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) {
this->av2.actionVar2++;
} else {
Player_SetupAction(play, this, Player_Action_80843A38, 0);
this->stateFlags1 |= PLAYER_STATE1_DAMAGED;
}
Player_AnimPlayOnceAdjusted(play, this,
(this->yaw != this->actor.shape.rot.y) ? &gPlayerAnim_link_normal_front_down_wake
: &gPlayerAnim_link_normal_back_down_wake);
this->yaw = this->actor.shape.rot.y;
}
}
static AnimSfxEntry D_808545DC[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 20) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_8, 30) },
};
void Player_Action_80843A38(Player* this, PlayState* play) {
s32 sp24;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
func_808382BC(this);
if (this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) {
LinkAnimation_Update(play, &this->skelAnime);
} else {
sp24 = func_808374A0(play, this, &this->skelAnime, 16.0f);
if ((sp24 != 0) && (LinkAnimation_Update(play, &this->skelAnime) || (sp24 > 0))) {
func_80839F90(this, play);
}
}
Player_ProcessAnimSfxList(this, D_808545DC);
}
static Vec3f D_808545E4 = { 0.0f, 0.0f, 5.0f };
void func_80843AE8(PlayState* play, Player* this) {
if (this->av2.actionVar2 != 0) {
if (this->av2.actionVar2 > 0) {
this->av2.actionVar2--;
if (this->av2.actionVar2 == 0) {
if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) {
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_swimer_swim_wait, 1.0f, 0.0f,
Animation_GetLastFrame(&gPlayerAnim_link_swimer_swim_wait), ANIMMODE_ONCE,
-16.0f);
} else {
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_derth_rebirth, 1.0f, 99.0f,
Animation_GetLastFrame(&gPlayerAnim_link_derth_rebirth), ANIMMODE_ONCE, 0.0f);
}
if (CVarGetInteger("gFairyReviveEffect", 0)) {
if (CVarGetInteger("gFairyRevivePercentRestore", 0)) {
gSaveContext.healthAccumulator =
(gSaveContext.healthCapacity * CVarGetInteger("gFairyReviveHealth", 100) / 100 + 15) / 16 * 16;
} else {
gSaveContext.healthAccumulator = CVarGetInteger("gFairyReviveHealth", 20) * 16;
}
} else {
gSaveContext.healthAccumulator = 0x140;
}
this->av2.actionVar2 = -1;
}
} else if (gSaveContext.healthAccumulator == 0) {
this->stateFlags1 &= ~PLAYER_STATE1_DEAD;
if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) {
func_80838F18(play, this);
} else {
func_80853080(this, play);
}
this->unk_A87 = 20;
func_80837AFC(this, -20);
func_800F47FC();
}
} else if (this->av1.actionVar1 != 0) {
this->av2.actionVar2 = 60;
Player_SpawnFairy(play, this, &this->actor.world.pos, &D_808545E4, FAIRY_REVIVE_DEATH);
Player_PlaySfx(this, NA_SE_EV_FIATY_HEAL - SFX_FLAG);
OnePointCutscene_Init(play, 9908, 125, &this->actor, MAIN_CAM);
} else if (play->gameOverCtx.state == GAMEOVER_DEATH_WAIT_GROUND) {
play->gameOverCtx.state = GAMEOVER_DEATH_DELAY_MENU;
sMaskMemory = PLAYER_MASK_NONE;
}
}
static AnimSfxEntry D_808545F0[] = {
{ NA_SE_PL_BOUND, ANIMSFX_DATA(ANIMSFX_TYPE_2, 60) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 140) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 164) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_8, 170) },
};
void Player_Action_80843CEC(Player* this, PlayState* play) {
if (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger("gSuperTunic", 0) == 0) {
if ((play->roomCtx.curRoom.behaviorType2 == ROOM_BEHAVIOR_TYPE2_3) || (sFloorType == 9) ||
((func_80838144(sFloorType) >= 0) &&
!SurfaceType_IsWallDamage(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId))) {
func_8083821C(this);
}
}
func_8083721C(this);
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->actor.category == ACTORCAT_PLAYER) {
func_80843AE8(play, this);
}
return;
}
if (this->skelAnime.animation == &gPlayerAnim_link_derth_rebirth) {
Player_ProcessAnimSfxList(this, D_808545F0);
} else if (this->skelAnime.animation == &gPlayerAnim_link_normal_electric_shock_end) {
if (LinkAnimation_OnFrame(&this->skelAnime, 88.0f)) {
func_80832770(this, NA_SE_PL_BOUND);
}
}
}
void func_80843E14(Player* this, u16 sfxId) {
func_80832698(this, sfxId);
if ((this->heldActor != NULL) && (this->heldActor->id == ACTOR_EN_RU1)) {
Audio_PlayActorSound2(this->heldActor, NA_SE_VO_RT_FALL);
}
}
static FallImpactInfo D_80854600[] = {
{ -8, 180, 40, 100, NA_SE_VO_LI_LAND_DAMAGE_S },
{ -16, 255, 140, 150, NA_SE_VO_LI_LAND_DAMAGE_S },
};
s32 func_80843E64(PlayState* play, Player* this) {
s32 sp34;
if ((sFloorType == 6) || (sFloorType == 9)) {
sp34 = 0;
} else {
sp34 = this->fallDistance;
}
Math_StepToF(&this->linearVelocity, 0.0f, 1.0f);
this->stateFlags1 &= ~(PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL);
if (sp34 >= 400) {
s32 impactIndex;
FallImpactInfo* impactInfo;
if (this->fallDistance < 800) {
impactIndex = 0;
} else {
impactIndex = 1;
}
impactInfo = &D_80854600[impactIndex];
if (Player_InflictDamageModified(play, impactInfo->damage * (1 << CVarGetInteger("gFallDamageMul", 0)),
false)) {
return -1;
}
func_80837AE0(this, 40);
Player_RequestQuake(play, 32967, 2, 30);
Player_RequestRumble(this, impactInfo->rumbleStrength, impactInfo->rumbleDuration, impactInfo->rumbleDecreaseRate, 0);
Player_PlaySfx(this, NA_SE_PL_BODY_HIT);
func_80832698(this, impactInfo->sfxId);
return impactIndex + 1;
}
if (sp34 > 200) {
sp34 *= 2;
if (sp34 > 255) {
sp34 = 255;
}
Player_RequestRumble(this, (u8)sp34, (u8)(sp34 * 0.1f), (u8)sp34, 0);
if (sFloorType == 6) {
func_80832698(this, NA_SE_VO_LI_CLIMB_END);
}
}
func_808328A0(this);
return 0;
}
void func_8084409C(PlayState* play, Player* this, f32 speedXZ, f32 velocityY) {
Actor* heldActor = this->heldActor;
if (!func_80835644(play, this, heldActor)) {
heldActor->world.rot.y = this->actor.shape.rot.y;
heldActor->speedXZ = speedXZ;
heldActor->velocity.y = velocityY;
func_80834644(play, this);
Player_PlaySfx(this, NA_SE_PL_THROW);
func_80832698(this, NA_SE_VO_LI_SWORD_N);
}
}
void Player_Action_8084411C(Player* this, PlayState* play) {
f32 sp4C;
s16 sp4A;
if (gSaveContext.respawn[RESPAWN_MODE_TOP].data > 40) {
this->actor.gravity = 0.0f;
} else if (func_8008E9C4(this)) {
this->actor.gravity = -1.2f;
}
Player_GetMovementSpeedAndYaw(this, &sp4C, &sp4A, SPEED_MODE_LINEAR, play);
if (!(this->actor.bgCheckFlags & 1)) {
if (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
Actor* heldActor = this->heldActor;
u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN;
if (CVarGetInteger("gDpadEquips", 0) != 0) {
buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
}
if (!func_80835644(play, this, heldActor) && (heldActor->id == ACTOR_EN_NIW) &&
CHECK_BTN_ANY(sControlInput->press.button, buttonsToCheck)) {
func_8084409C(play, this, this->linearVelocity + 2.0f, this->actor.velocity.y + 2.0f);
}
}
LinkAnimation_Update(play, &this->skelAnime);
if (!(this->stateFlags2 & PLAYER_STATE2_HOPPING)) {
func_8083DFE0(this, &sp4C, &sp4A);
}
Player_UpdateUpperBody(this, play);
if (((this->stateFlags2 & PLAYER_STATE2_HOPPING) && (this->av1.actionVar1 == 2)) || !func_8083BBA0(this, play)) {
if (this->actor.velocity.y < 0.0f) {
if (this->av2.actionVar2 >= 0) {
if ((this->actor.bgCheckFlags & 8) || (this->av2.actionVar2 == 0) || (this->fallDistance > 0)) {
if ((sYDistToFloor > 800.0f) || (this->stateFlags1 & PLAYER_STATE1_HOOKSHOT_FALLING)) {
func_80843E14(this, NA_SE_VO_LI_FALL_S);
this->stateFlags1 &= ~PLAYER_STATE1_HOOKSHOT_FALLING;
}
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_normal_landing, 1.0f, 0.0f,
0.0f, ANIMMODE_ONCE, 8.0f);
this->av2.actionVar2 = -1;
}
} else {
if ((this->av2.actionVar2 == -1) && (this->fallDistance > 120.0f) && (sYDistToFloor > 280.0f)) {
this->av2.actionVar2 = -2;
func_80843E14(this, NA_SE_VO_LI_FALL_L);
}
if (!GameInteractor_GetDisableLedgeGrabsActive() && (this->actor.bgCheckFlags & 0x200) &&
!(this->stateFlags2 & PLAYER_STATE2_HOPPING) &&
!(this->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_WATER)) && (this->linearVelocity > 0.0f)) {
if ((this->yDistToLedge >= 150.0f) && (this->unk_84B[this->unk_846] == 0)) {
func_8083EC18(this, play, sTouchedWallFlags);
} else if ((this->ledgeClimbType >= 2) && (this->yDistToLedge < 150.0f) &&
(((this->actor.world.pos.y - this->actor.floorHeight) + this->yDistToLedge) >
(70.0f * this->ageProperties->unk_08))) {
AnimationContext_DisableQueue(play);
if (this->stateFlags1 & PLAYER_STATE1_HOOKSHOT_FALLING) {
func_80832698(this, NA_SE_VO_LI_HOOKSHOT_HANG);
} else {
func_80832698(this, NA_SE_VO_LI_HANG);
}
this->actor.world.pos.y += this->yDistToLedge;
func_8083A5C4(play, this, this->actor.wallPoly, this->distToInteractWall,
GET_PLAYER_ANIM(PLAYER_ANIMGROUP_jump_climb_hold, this->modelAnimType));
this->actor.shape.rot.y = this->yaw += 0x8000;
this->stateFlags1 |= PLAYER_STATE1_HANGING_OFF_LEDGE;
}
}
}
}
}
} else {
LinkAnimationHeader* anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_landing, this->modelAnimType);
s32 sp3C;
if (this->stateFlags2 & PLAYER_STATE2_HOPPING) {
if (func_8008E9C4(this)) {
anim = D_80853D4C[this->av1.actionVar1][2];
} else {
anim = D_80853D4C[this->av1.actionVar1][1];
}
} else if (this->skelAnime.animation == &gPlayerAnim_link_normal_run_jump) {
anim = &gPlayerAnim_link_normal_run_jump_end;
} else if (func_8008E9C4(this)) {
anim = &gPlayerAnim_link_anchor_landingR;
func_80833C3C(this);
} else if (this->fallDistance <= 80) {
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_short_landing, this->modelAnimType);
} else if ((this->fallDistance < 800) && (this->unk_84B[this->unk_846] == 0) &&
!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) {
func_8083BC04(this, play);
return;
}
sp3C = func_80843E64(play, this);
if (sp3C > 0) {
func_8083A098(this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_landing, this->modelAnimType), play);
this->skelAnime.endFrame = 8.0f;
if (sp3C == 1) {
this->av2.actionVar2 = 10;
} else {
this->av2.actionVar2 = 20;
}
} else if (sp3C == 0) {
func_8083A098(this, anim, play);
}
}
}
static AnimSfxEntry D_8085460C[] = {
{ NA_SE_VO_LI_SWORD_N, ANIMSFX_DATA(ANIMSFX_TYPE_4, 1) },
{ NA_SE_PL_WALK_GROUND, ANIMSFX_DATA(ANIMSFX_TYPE_3, 6) },
{ NA_SE_PL_ROLL, ANIMSFX_DATA(ANIMSFX_TYPE_1, 6) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_5, 18) },
};
void Player_Action_80844708(Player* this, PlayState* play) {
Actor* cylinderOc;
s32 temp;
s32 sp44;
DynaPolyActor* wallPolyActor;
s32 pad;
f32 sp38;
s16 sp36;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
cylinderOc = NULL;
sp44 = LinkAnimation_Update(play, &this->skelAnime);
if (LinkAnimation_OnFrame(&this->skelAnime, 8.0f)) {
func_80837AFC(this, -10);
}
if (func_80842964(this, play) == 0) {
if (this->av2.actionVar2 != 0) {
Math_StepToF(&this->linearVelocity, 0.0f, 2.0f);
temp = func_808374A0(play, this, &this->skelAnime, 5.0f);
if ((temp != 0) && ((temp > 0) || sp44)) {
func_8083A060(this, play);
}
} else {
f32 rand = Rand_ZeroOne();
uint8_t randomBonk = (rand <= .05) && GameInteractor_GetRandomBonksActive();
if (this->linearVelocity >= 7.0f) {
if (randomBonk || ((this->actor.bgCheckFlags & 0x200) && (sWorldYawToTouchedWall < 0x2000)) ||
((this->cylinder.base.ocFlags1 & OC1_HIT) &&
(cylinderOc = this->cylinder.base.oc,
((cylinderOc->id == ACTOR_EN_WOOD02) &&
(ABS((s16)(this->actor.world.rot.y - cylinderOc->yawTowardsPlayer)) > 0x6000))))) {
if (cylinderOc != NULL) {
cylinderOc->home.rot.y = 1;
} else if (this->actor.wallBgId != BGCHECK_SCENE) {
wallPolyActor = DynaPoly_GetActor(&play->colCtx, this->actor.wallBgId);
if ((wallPolyActor != NULL) && (wallPolyActor->actor.id == ACTOR_OBJ_KIBAKO2)) {
wallPolyActor->actor.home.rot.z = 1;
}
}
Player_AnimPlayOnce(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_hip_down, this->modelAnimType));
this->linearVelocity = -this->linearVelocity;
Player_RequestQuake(play, 33267, 3, 12);
Player_RequestRumble(this, 255, 20, 150, 0);
Player_PlaySfx(this, NA_SE_PL_BODY_HIT);
func_80832698(this, NA_SE_VO_LI_CLIMB_END);
this->av2.actionVar2 = 1;
gSaveContext.sohStats.count[COUNT_BONKS]++;
GameInteractor_ExecuteOnPlayerBonk();
return;
}
}
if ((this->skelAnime.curFrame < 15.0f) || !Player_ActionChange_7(this, play)) {
if (this->skelAnime.curFrame >= 20.0f) {
func_8083A060(this, play);
return;
}
Player_GetMovementSpeedAndYaw(this, &sp38, &sp36, SPEED_MODE_CURVED, play);
sp38 *= 1.5f;
if ((sp38 < 3.0f) || (this->unk_84B[this->unk_846] != 0)) {
sp38 = 3.0f;
}
func_8083DF68(this, sp38, this->actor.shape.rot.y);
if (func_8084269C(play, this)) {
func_8002F8F0(&this->actor, NA_SE_PL_ROLL_DUST - SFX_FLAG);
}
Player_ProcessAnimSfxList(this, D_8085460C);
}
}
}
}
void Player_Action_80844A44(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_normal_run_jump_water_fall_wait);
}
Math_StepToF(&this->linearVelocity, 0.0f, 0.05f);
if (this->actor.bgCheckFlags & 1) {
this->actor.colChkInfo.damage = 0x10;
func_80837C0C(play, this, 1, 4.0f, 5.0f, this->actor.shape.rot.y, 20);
}
}
void Player_Action_80844AF4(Player* this, PlayState* play) {
f32 sp2C;
s16 sp2A;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
this->actor.gravity = -1.2f;
LinkAnimation_Update(play, &this->skelAnime);
if (!func_80842DF4(play, this)) {
func_8084285C(this, 6.0f, 7.0f, 99.0f);
if (!(this->actor.bgCheckFlags & 1)) {
Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_LINEAR, play);
func_8083DFE0(this, &sp2C, &this->yaw);
return;
}
if (func_80843E64(play, this) >= 0) {
this->meleeWeaponAnimation += 2;
func_80837948(play, this, this->meleeWeaponAnimation);
this->unk_845 = 3;
func_808328A0(this);
}
}
}
s32 func_80844BE4(Player* this, PlayState* play) {
s32 temp;
if (Player_StartCsAction(play, this)) {
this->stateFlags2 |= PLAYER_STATE2_SPIN_ATTACKING;
} else {
if (!CHECK_BTN_ALL(sControlInput->cur.button, BTN_B)) {
if ((this->unk_858 >= 0.85f) || func_808375D8(this)) {
temp = D_80854384[Player_HoldsTwoHandedWeapon(this)];
} else {
temp = D_80854380[Player_HoldsTwoHandedWeapon(this)];
}
func_80837948(play, this, temp);
func_80837AFC(this, -8);
this->stateFlags2 |= PLAYER_STATE2_SPIN_ATTACKING;
if (this->unk_84B[this->unk_846] == 0) {
this->stateFlags2 |= PLAYER_STATE2_SWORD_LUNGE;
}
} else {
return 0;
}
}
return 1;
}
void func_80844CF8(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_80845000, 1);
}
void func_80844D30(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_80845308, 1);
}
void func_80844D68(Player* this, PlayState* play) {
func_80839FFC(this, play);
func_80832318(this);
Player_AnimChangeOnceMorph(play, this, D_80854368[Player_HoldsTwoHandedWeapon(this)]);
this->yaw = this->actor.shape.rot.y;
}
void func_80844DC8(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_80844E68, 1);
this->unk_868 = 0.0f;
Player_AnimPlayLoop(play, this, D_80854360[Player_HoldsTwoHandedWeapon(this)]);
this->av2.actionVar2 = 1;
}
void func_80844E3C(Player* this) {
Math_StepToF(&this->unk_858, 1.0f, 0.02f);
}
void Player_Action_80844E68(Player* this, PlayState* play) {
f32 sp34;
s16 sp32;
s32 temp;
this->stateFlags1 |= PLAYER_STATE1_CHARGING_SPIN_ATTACK;
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80832DBC(this);
func_808355DC(this);
this->stateFlags1 &= ~PLAYER_STATE1_TARGET_NOTHING;
Player_AnimPlayLoop(play, this, D_80854360[Player_HoldsTwoHandedWeapon(this)]);
this->av2.actionVar2 = -1;
}
func_8083721C(this);
if (!func_80842964(this, play) && (this->av2.actionVar2 != 0)) {
func_80844E3C(this);
if (this->av2.actionVar2 < 0) {
if (this->unk_858 >= 0.1f) {
this->unk_845 = 0;
this->av2.actionVar2 = 1;
} else if (!CHECK_BTN_ALL(sControlInput->cur.button, BTN_B)) {
func_80844D68(this, play);
}
} else if (!func_80844BE4(this, play)) {
Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_LINEAR, play);
temp = func_80840058(this, &sp34, &sp32, play);
if (temp > 0) {
func_80844CF8(this, play);
} else if (temp < 0) {
func_80844D30(this, play);
}
}
}
}
void Player_Action_80845000(Player* this, PlayState* play) {
s16 temp1;
s32 temp2;
f32 sp5C;
f32 sp58;
f32 sp54;
s16 sp52;
s32 temp4;
s16 temp5;
s32 sp44;
temp1 = this->yaw - this->actor.shape.rot.y;
temp2 = ABS(temp1);
sp5C = fabsf(this->linearVelocity);
sp58 = sp5C * 1.5f;
this->stateFlags1 |= PLAYER_STATE1_CHARGING_SPIN_ATTACK;
if (sp58 < 1.5f) {
sp58 = 1.5f;
}
sp58 = ((temp2 < 0x4000) ? -1.0f : 1.0f) * sp58;
func_8084029C(this, sp58);
sp58 = CLAMP(sp5C * 0.5f, 0.5f, 1.0f);
LinkAnimation_BlendToJoint(play, &this->skelAnime, D_80854360[Player_HoldsTwoHandedWeapon(this)], 0.0f,
D_80854370[Player_HoldsTwoHandedWeapon(this)], this->unk_868 * (21.0f / 29.0f), sp58,
this->blendTable);
if (!func_80842964(this, play) && !func_80844BE4(this, play)) {
func_80844E3C(this);
Player_GetMovementSpeedAndYaw(this, &sp54, &sp52, SPEED_MODE_LINEAR, play);
temp4 = func_80840058(this, &sp54, &sp52, play);
if (temp4 < 0) {
func_80844D30(this, play);
return;
}
if (temp4 == 0) {
sp54 = 0.0f;
sp52 = this->yaw;
}
temp5 = sp52 - this->yaw;
sp44 = ABS(temp5);
if (sp44 > 0x4000) {
if (Math_StepToF(&this->linearVelocity, 0.0f, 1.0f)) {
this->yaw = sp52;
}
return;
}
Math_AsymStepToF(&this->linearVelocity, sp54 * 0.2f, 1.0f, 0.5f);
Math_ScaledStepToS(&this->yaw, sp52, sp44 * 0.1f);
if ((sp54 == 0.0f) && (this->linearVelocity == 0.0f)) {
func_80844DC8(this, play);
}
}
}
void Player_Action_80845308(Player* this, PlayState* play) {
f32 sp5C;
f32 sp58;
f32 sp54;
s16 sp52;
s32 temp4;
s16 temp5;
s32 sp44;
sp5C = fabsf(this->linearVelocity);
this->stateFlags1 |= PLAYER_STATE1_CHARGING_SPIN_ATTACK;
if (sp5C == 0.0f) {
sp5C = ABS(this->unk_87C) * 0.0015f;
if (sp5C < 400.0f) {
sp5C = 0.0f;
}
func_8084029C(this, ((this->unk_87C >= 0) ? 1 : -1) * sp5C);
} else {
sp58 = sp5C * 1.5f;
if (sp58 < 1.5f) {
sp58 = 1.5f;
}
func_8084029C(this, sp58);
}
sp58 = CLAMP(sp5C * 0.5f, 0.5f, 1.0f);
LinkAnimation_BlendToJoint(play, &this->skelAnime, D_80854360[Player_HoldsTwoHandedWeapon(this)], 0.0f,
D_80854378[Player_HoldsTwoHandedWeapon(this)], this->unk_868 * (21.0f / 29.0f), sp58,
this->blendTable);
if (!func_80842964(this, play) && !func_80844BE4(this, play)) {
func_80844E3C(this);
Player_GetMovementSpeedAndYaw(this, &sp54, &sp52, SPEED_MODE_LINEAR, play);
temp4 = func_80840058(this, &sp54, &sp52, play);
if (temp4 > 0) {
func_80844CF8(this, play);
return;
}
if (temp4 == 0) {
sp54 = 0.0f;
sp52 = this->yaw;
}
temp5 = sp52 - this->yaw;
sp44 = ABS(temp5);
if (sp44 > 0x4000) {
if (Math_StepToF(&this->linearVelocity, 0.0f, 1.0f)) {
this->yaw = sp52;
}
return;
}
Math_AsymStepToF(&this->linearVelocity, sp54 * 0.2f, 1.0f, 0.5f);
Math_ScaledStepToS(&this->yaw, sp52, sp44 * 0.1f);
if ((sp54 == 0.0f) && (this->linearVelocity == 0.0f) && (sp5C == 0.0f)) {
func_80844DC8(this, play);
}
}
}
void Player_Action_80845668(Player* this, PlayState* play) {
s32 sp3C;
f32 temp1;
s32 temp2;
f32 temp3;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
sp3C = LinkAnimation_Update(play, &this->skelAnime);
if (this->skelAnime.animation == &gPlayerAnim_link_normal_250jump_start) {
this->linearVelocity = 1.0f;
if (LinkAnimation_OnFrame(&this->skelAnime, 8.0f)) {
temp1 = this->yDistToLedge;
if (temp1 > this->ageProperties->unk_0C) {
temp1 = this->ageProperties->unk_0C;
}
if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) {
temp1 *= 0.085f;
} else {
temp1 *= 0.072f;
}
if (!LINK_IS_ADULT) {
temp1 += 1.0f;
}
func_80838940(this, NULL, temp1, play, NA_SE_VO_LI_AUTO_JUMP);
this->av2.actionVar2 = -1;
return;
}
} else {
temp2 = func_808374A0(play, this, &this->skelAnime, 4.0f);
if (temp2 == 0) {
this->stateFlags1 &= ~(PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_JUMPING);
return;
}
if ((sp3C != 0) || (temp2 > 0)) {
func_8083C0E8(this, play);
this->stateFlags1 &= ~(PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_JUMPING);
return;
}
temp3 = 0.0f;
if (this->skelAnime.animation == &gPlayerAnim_link_swimer_swim_15step_up) {
if (LinkAnimation_OnFrame(&this->skelAnime, 30.0f)) {
func_8083D0A8(play, this, 10.0f);
}
temp3 = 50.0f;
} else if (this->skelAnime.animation == &gPlayerAnim_link_normal_150step_up) {
temp3 = 30.0f;
} else if (this->skelAnime.animation == &gPlayerAnim_link_normal_100step_up) {
temp3 = 16.0f;
}
if (LinkAnimation_OnFrame(&this->skelAnime, temp3)) {
func_808328A0(this);
func_80832698(this, NA_SE_VO_LI_CLIMB_END);
}
if ((this->skelAnime.animation == &gPlayerAnim_link_normal_100step_up) || (this->skelAnime.curFrame > 5.0f)) {
if (this->av2.actionVar2 == 0) {
func_80832854(this);
this->av2.actionVar2 = 1;
}
Math_StepToF(&this->actor.shape.yOffset, 0.0f, 150.0f);
}
}
}
void Player_Action_808458D0(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
LinkAnimation_Update(play, &this->skelAnime);
if (((this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->heldActor != NULL) && (this->getItemId == GI_NONE)) ||
!Player_UpdateUpperBody(this, play)) {
this->func_A74(play, this);
}
}
s32 func_80845964(PlayState* play, Player* this, CsCmdActorAction* arg2, f32 arg3, s16 arg4, s32 arg5) {
if ((arg5 != 0) && (this->linearVelocity == 0.0f)) {
return LinkAnimation_Update(play, &this->skelAnime);
}
if (arg5 != 2) {
f32 sp34 = R_UPDATE_RATE * 0.5f;
f32 selfDistX = arg2->endPos.x - this->actor.world.pos.x;
f32 selfDistZ = arg2->endPos.z - this->actor.world.pos.z;
f32 sp28 = sqrtf(SQ(selfDistX) + SQ(selfDistZ)) / sp34;
s32 sp24 = (arg2->endFrame - play->csCtx.frames) + 1;
arg4 = Math_Atan2S(selfDistZ, selfDistX);
if (arg5 == 1) {
f32 distX = arg2->endPos.x - arg2->startPos.x;
f32 distZ = arg2->endPos.z - arg2->startPos.z;
s32 temp = (((sqrtf(SQ(distX) + SQ(distZ)) / sp34) / (arg2->endFrame - arg2->startFrame)) / 1.5f) * 4.0f;
if (temp >= sp24) {
arg4 = this->actor.shape.rot.y;
arg3 = 0.0f;
} else {
arg3 = sp28 / ((sp24 - temp) + 1);
}
} else {
arg3 = sp28 / sp24;
}
}
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
func_80841EE4(this, play);
func_8083DF68(this, arg3, arg4);
if ((arg3 == 0.0f) && (this->linearVelocity == 0.0f)) {
func_8083BF50(this, play);
}
return 0;
}
s32 func_80845BA0(PlayState* play, Player* this, f32* arg2, s32 arg3) {
f32 dx = this->unk_450.x - this->actor.world.pos.x;
f32 dz = this->unk_450.z - this->actor.world.pos.z;
s32 sp2C = sqrtf(SQ(dx) + SQ(dz));
s16 yaw = Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_450);
if (sp2C < arg3) {
*arg2 = 0.0f;
yaw = this->actor.shape.rot.y;
}
if (func_80845964(play, this, NULL, *arg2, yaw, 2)) {
return 0;
}
return sp2C;
}
s32 func_80845C68(PlayState* play, s32 arg1) {
if (arg1 == 0) {
Play_SetupRespawnPoint(play, RESPAWN_MODE_DOWN, 0xDFF);
}
gSaveContext.respawn[RESPAWN_MODE_DOWN].data = 0;
return arg1;
}
void Player_Action_80845CA4(Player* this, PlayState* play) {
f32 sp3C;
s32 temp;
f32 sp34;
s32 sp30;
s32 pad;
if (!Player_ActionChange_13(this, play)) {
if (this->av2.actionVar2 == 0) {
LinkAnimation_Update(play, &this->skelAnime);
if (DECR(this->doorTimer) == 0) {
this->linearVelocity = 0.1f;
this->av2.actionVar2 = 1;
}
} else if (this->av1.actionVar1 == 0) {
sp3C = 5.0f * D_808535E8;
if (func_80845BA0(play, this, &sp3C, -1) < 30) {
this->av1.actionVar1 = 1;
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
this->unk_450.x = this->unk_45C.x;
this->unk_450.z = this->unk_45C.z;
}
} else {
sp34 = 5.0f;
sp30 = 20;
if (this->stateFlags1 & PLAYER_STATE1_LOADING) {
sp34 = gSaveContext.entranceSpeed;
if (sConveyorSpeed != 0) {
this->unk_450.x = (Math_SinS(sConveyorYaw) * 400.0f) + this->actor.world.pos.x;
this->unk_450.z = (Math_CosS(sConveyorYaw) * 400.0f) + this->actor.world.pos.z;
}
} else if (this->av2.actionVar2 < 0) {
this->av2.actionVar2++;
sp34 = gSaveContext.entranceSpeed;
sp30 = -1;
}
temp = func_80845BA0(play, this, &sp34, sp30);
if ((this->av2.actionVar2 == 0) ||
((temp == 0) && (this->linearVelocity == 0.0f) && (Play_GetCamera(play, 0)->unk_14C & 0x10))) {
func_8005B1A4(Play_GetCamera(play, 0));
func_80845C68(play, gSaveContext.respawn[RESPAWN_MODE_DOWN].data);
if (!Player_ActionChange_4(this, play)) {
func_8083CF5C(this, play);
}
}
}
}
if (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
Player_UpdateUpperBody(this, play);
}
}
void Player_Action_80845EF8(Player* this, PlayState* play) {
s32 sp2C;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
sp2C = LinkAnimation_Update(play, &this->skelAnime);
Player_UpdateUpperBody(this, play);
if (sp2C) {
if (this->av2.actionVar2 == 0) {
if (DECR(this->doorTimer) == 0) {
this->av2.actionVar2 = 1;
this->skelAnime.endFrame = this->skelAnime.animLength - 1.0f;
}
} else {
func_8083C0E8(this, play);
if (play->roomCtx.prevRoom.num >= 0) {
func_80097534(play, &play->roomCtx);
}
func_8005B1A4(Play_GetCamera(play, 0));
Play_SetupRespawnPoint(play, 0, 0xDFF);
}
return;
}
if (!(this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) && LinkAnimation_OnFrame(&this->skelAnime, 15.0f)) {
play->func_11D54(this, play);
}
}
void Player_Action_80846050(Player* this, PlayState* play) {
func_8083721C(this);
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80839F90(this, play);
func_80835688(this, play);
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, 4.0f)) {
Actor* interactRangeActor = this->interactRangeActor;
if (!func_80835644(play, this, interactRangeActor)) {
this->heldActor = interactRangeActor;
this->actor.child = interactRangeActor;
interactRangeActor->parent = &this->actor;
interactRangeActor->bgCheckFlags &= 0xFF00;
this->unk_3BC.y = interactRangeActor->shape.rot.y - this->actor.shape.rot.y;
}
return;
}
Math_ScaledStepToS(&this->unk_3BC.y, 0, 4000);
}
static AnimSfxEntry D_8085461C[] = {
{ NA_SE_VO_LI_SWORD_L, ANIMSFX_DATA(ANIMSFX_TYPE_4, 49) },
{ NA_SE_VO_LI_SWORD_N, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 230) },
};
void Player_Action_80846120(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime) && (this->av2.actionVar2++ > 20)) {
if (!Player_ActionChange_13(this, play)) {
func_8083A098(this, &gPlayerAnim_link_normal_heavy_carry_end, play);
}
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, 41.0f)) {
BgHeavyBlock* heavyBlock = (BgHeavyBlock*)this->interactRangeActor;
this->heldActor = &heavyBlock->dyna.actor;
this->actor.child = &heavyBlock->dyna.actor;
heavyBlock->dyna.actor.parent = &this->actor;
func_8002DBD0(&heavyBlock->dyna.actor, &heavyBlock->unk_164, &this->leftHandPos);
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, 229.0f)) {
Actor* heldActor = this->heldActor;
if (CVarGetInteger("gFasterHeavyBlockLift", 0)) {
// This is the difference in rotation when the animation is sped up 5x
heldActor->shape.rot.x -= 3510;
}
heldActor->speedXZ = Math_SinS(heldActor->shape.rot.x) * 40.0f;
heldActor->velocity.y = Math_CosS(heldActor->shape.rot.x) * 40.0f;
heldActor->gravity = -2.0f;
heldActor->minVelocityY = -30.0f;
Player_DetachHeldActor(play, this);
return;
}
Player_ProcessAnimSfxList(this, D_8085461C);
}
void Player_Action_80846260(Player* this, PlayState* play) {
func_8083721C(this);
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_silver_wait);
this->av2.actionVar2 = 1;
return;
}
u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN;
if (CVarGetInteger("gDpadEquips", 0) != 0) {
buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
}
if (this->av2.actionVar2 == 0) {
if (LinkAnimation_OnFrame(&this->skelAnime, 27.0f)) {
Actor* interactRangeActor = this->interactRangeActor;
this->heldActor = interactRangeActor;
this->actor.child = interactRangeActor;
interactRangeActor->parent = &this->actor;
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, 25.0f)) {
func_80832698(this, NA_SE_VO_LI_SWORD_L);
return;
}
} else if (CHECK_BTN_ANY(sControlInput->press.button, buttonsToCheck)) {
Player_SetupAction(play, this, Player_Action_80846358, 1);
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_silver_throw);
}
}
void Player_Action_80846358(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80839F90(this, play);
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, 6.0f)) {
Actor* heldActor = this->heldActor;
heldActor->world.rot.y = this->actor.shape.rot.y;
heldActor->speedXZ = 10.0f;
heldActor->velocity.y = 20.0f;
func_80834644(play, this);
Player_PlaySfx(this, NA_SE_PL_THROW);
func_80832698(this, NA_SE_VO_LI_SWORD_N);
}
}
void Player_Action_80846408(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_normal_nocarry_free_wait);
this->av2.actionVar2 = 15;
return;
}
if (this->av2.actionVar2 != 0) {
this->av2.actionVar2--;
if (this->av2.actionVar2 == 0) {
func_8083A098(this, &gPlayerAnim_link_normal_nocarry_free_end, play);
this->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD;
func_80832698(this, NA_SE_VO_LI_DAMAGE_S);
}
}
}
void Player_Action_808464B0(Player* this, PlayState* play) {
func_8083721C(this);
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80839F90(this, play);
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, 4.0f)) {
Actor* heldActor = this->heldActor;
if (!func_80835644(play, this, heldActor)) {
heldActor->velocity.y = 0.0f;
heldActor->speedXZ = 0.0f;
func_80834644(play, this);
if (heldActor->id == ACTOR_EN_BOM_CHU && !CVarGetInteger("gDisableFirstPersonChus", 0)) {
func_8083B8F4(this, play);
}
}
}
}
void Player_Action_80846578(Player* this, PlayState* play) {
f32 sp34;
s16 sp32;
func_8083721C(this);
if (LinkAnimation_Update(play, &this->skelAnime) ||
((this->skelAnime.curFrame >= 8.0f) && Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_CURVED, play))) {
func_80839F90(this, play);
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, 3.0f)) {
func_8084409C(play, this, this->linearVelocity + 8.0f, 12.0f);
}
}
static ColliderCylinderInit D_80854624 = {
{
COLTYPE_HIT5,
AT_NONE,
AC_ON | AC_TYPE_ENEMY,
OC1_ON | OC1_TYPE_ALL,
OC2_TYPE_PLAYER,
COLSHAPE_CYLINDER,
},
{
ELEMTYPE_UNK1,
{ 0x00000000, 0x00, 0x00 },
{ 0xFFCFFFFF, 0x00, 0x00 },
TOUCH_NONE,
BUMP_ON,
OCELEM_ON,
},
{ 12, 60, 0, { 0, 0, 0 } },
};
static ColliderQuadInit D_80854650 = {
{
COLTYPE_NONE,
AT_ON | AT_TYPE_PLAYER,
AC_NONE,
OC1_NONE,
OC2_TYPE_PLAYER,
COLSHAPE_QUAD,
},
{
ELEMTYPE_UNK2,
{ 0x00000100, 0x00, 0x01 },
{ 0xFFCFFFFF, 0x00, 0x00 },
TOUCH_ON | TOUCH_SFX_NORMAL,
BUMP_NONE,
OCELEM_NONE,
},
{ { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } },
};
static ColliderQuadInit D_808546A0 = {
{
COLTYPE_METAL,
AT_ON | AT_TYPE_PLAYER,
AC_ON | AC_HARD | AC_TYPE_ENEMY,
OC1_NONE,
OC2_TYPE_PLAYER,
COLSHAPE_QUAD,
},
{
ELEMTYPE_UNK2,
{ 0x00100000, 0x00, 0x00 },
{ 0xDFCFFFFF, 0x00, 0x00 },
TOUCH_ON | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_NONE,
},
{ { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } },
};
void func_8084663C(Actor* thisx, PlayState* play) {
}
void func_80846648(PlayState* play, Player* this) {
this->actor.update = func_8084663C;
this->actor.draw = NULL;
}
void func_80846660(PlayState* play, Player* this) {
Player_SetupAction(play, this, Player_Action_8084F710, 0);
if ((play->sceneNum == SCENE_LAKE_HYLIA) && (gSaveContext.sceneSetupIndex >= 4)) {
this->av1.actionVar1 = 1;
}
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_okarina_warp_goal, 2.0f / 3.0f, 0.0f, 24.0f,
ANIMMODE_ONCE, 0.0f);
this->actor.world.pos.y += 800.0f;
}
static u8 D_808546F0[] = { ITEM_SWORD_MASTER, ITEM_SWORD_KOKIRI };
void func_80846720(PlayState* play, Player* this, s32 arg2) {
s32 item = D_808546F0[(void)0, gSaveContext.linkAge];
s32 itemAction = sItemActions[item];
Player_DestroyHookshot(this);
Player_DetachHeldActor(play, this);
this->heldItemId = item;
this->nextModelGroup = Player_ActionToModelGroup(this, itemAction);
Player_InitItemAction(play, this, itemAction);
func_80834644(play, this);
if (arg2 != 0) {
Player_PlaySfx(this, NA_SE_IT_SWORD_PICKOUT);
}
}
static Vec3f D_808546F4 = { -1.0f, 69.0f, 20.0f };
void func_808467D4(PlayState* play, Player* this) {
Player_SetupAction(play, this, Player_Action_8084E9AC, 0);
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
Math_Vec3f_Copy(&this->actor.world.pos, &D_808546F4);
this->yaw = this->actor.shape.rot.y = -0x8000;
LinkAnimation_Change(play, &this->skelAnime, this->ageProperties->unk_A0, 2.0f / 3.0f, 0.0f, 0.0f,
ANIMMODE_ONCE, 0.0f);
Player_AnimReplaceApplyFlags(play, this, 0x28F);
if (LINK_IS_ADULT) {
func_80846720(play, this, 0);
}
this->av2.actionVar2 = 20;
}
void func_808468A8(PlayState* play, Player* this) {
Player_SetupAction(play, this, Player_Action_8084F9A0, 0);
Player_AnimReplaceApplyFlags(play, this, 0x9B);
}
void func_808468E8(PlayState* play, Player* this) {
func_808389E8(this, &gPlayerAnim_link_normal_jump, 12.0f, play);
Player_SetupAction(play, this, Player_Action_8084F9C0, 0);
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
this->fallStartHeight = this->actor.world.pos.y;
OnePointCutscene_Init(play, 5110, 40, &this->actor, MAIN_CAM);
}
void func_80846978(PlayState* play, Player* this) {
func_80837C0C(play, this, 1, 2.0f, 2.0f, this->actor.shape.rot.y + 0x8000, 0);
}
void func_808469BC(PlayState* play, Player* this) {
Player_SetupAction(play, this, Player_Action_8084F698, 0);
this->actor.draw = NULL;
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
}
static s16 D_80854700[] = { ACTOR_MAGIC_WIND, ACTOR_MAGIC_DARK, ACTOR_MAGIC_FIRE };
Actor* func_80846A00(PlayState* play, Player* this, s32 arg2) {
return Actor_Spawn(&play->actorCtx, play, D_80854700[arg2], this->actor.world.pos.x,
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0, true);
}
void func_80846A68(PlayState* play, Player* this) {
this->actor.draw = NULL;
Player_SetupAction(play, this, Player_Action_8085076C, 0);
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
}
static InitChainEntry sInitChain[] = {
ICHAIN_F32(targetArrowOffset, 500, ICHAIN_STOP),
};
static EffectBlureInit2 blureSword = {
0, 8, 0, { 255, 255, 255, 255 }, { 255, 255, 255, 64 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, 4,
0, 2, 0, { 255, 255, 255, 255 }, { 255, 255, 255, 64 }, 1,
};
static Vec3s D_80854730 = { -57, 3377, 0 };
void Player_InitCommon(Player* this, PlayState* play, FlexSkeletonHeader* skelHeader) {
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
this->ageProperties = &sAgeProperties[gSaveContext.linkAge];
Actor_ProcessInitChain(&this->actor, sInitChain);
this->meleeWeaponEffectIndex = TOTAL_EFFECT_COUNT;
this->yaw = this->actor.world.rot.y;
func_80834644(play, this);
SkelAnime_InitLink(play, &this->skelAnime, skelHeader, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_wait, this->modelAnimType), 9,
this->jointTable, this->morphTable, PLAYER_LIMB_MAX);
this->skelAnime.baseTransl = D_80854730;
SkelAnime_InitLink(play, &this->upperSkelAnime, skelHeader, func_80833338(this), 9, this->upperJointTable,
this->upperMorphTable, PLAYER_LIMB_MAX);
this->upperSkelAnime.baseTransl = D_80854730;
Effect_Add(play, &this->meleeWeaponEffectIndex, EFFECT_BLURE2, 0, 0, &blureSword);
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawFeet, this->ageProperties->unk_04);
this->subCamId = SUBCAM_NONE;
Collider_InitCylinder(play, &this->cylinder);
Collider_SetCylinder(play, &this->cylinder, &this->actor, &D_80854624);
Collider_InitQuad(play, &this->meleeWeaponQuads[0]);
Collider_SetQuad(play, &this->meleeWeaponQuads[0], &this->actor, &D_80854650);
Collider_InitQuad(play, &this->meleeWeaponQuads[1]);
Collider_SetQuad(play, &this->meleeWeaponQuads[1], &this->actor, &D_80854650);
Collider_InitQuad(play, &this->shieldQuad);
Collider_SetQuad(play, &this->shieldQuad, &this->actor, &D_808546A0);
this->ivanDamageMultiplier = 1;
}
static void (*D_80854738[])(PlayState* play, Player* this) = {
func_80846648, func_808467D4, func_80846660, func_808468A8, func_808468E8, func_808469BC,
func_80846A68, func_80846978, func_8083CA54, func_8083CA54, func_8083CA54, func_8083CA54,
func_8083CA54, func_8083CA20, func_8083CA54, func_8083CA9C,
};
static Vec3f D_80854778 = { 0.0f, 50.0f, 0.0f };
void Player_Init(Actor* thisx, PlayState* play2) {
Player* this = (Player*)thisx;
PlayState* play = play2;
SceneTableEntry* scene = play->loadedScene;
u32 titleFileSize;
s32 initMode;
s32 sp50;
s32 sp4C;
// In ER, once Link has spawned we know the scene has loaded, so we can sanitize the last known entrance type
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) {
Grotto_SanitizeEntranceType();
}
play->shootingGalleryStatus = play->bombchuBowlingStatus = 0;
play->playerInit = Player_InitCommon;
play->playerUpdate = Player_UpdateCommon;
play->isPlayerDroppingFish = Player_IsDroppingFish;
play->startPlayerFishing = Player_StartFishing;
play->grabPlayer = func_80852F38;
play->startPlayerCutscene = Player_TryCsAction;
play->func_11D54 = func_80853080;
play->damagePlayer = Player_InflictDamage;
play->talkWithPlayer = Player_StartTalking;
thisx->room = -1;
this->ageProperties = &sAgeProperties[gSaveContext.linkAge];
this->itemAction = this->heldItemAction = -1;
this->heldItemId = ITEM_NONE;
Player_UseItem(play, this, ITEM_NONE);
Player_SetEquipmentData(play, this);
this->prevBoots = this->currentBoots;
if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) {
if (INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_SOLD_OUT) {
sMaskMemory = PLAYER_MASK_NONE;
}
this->currentMask = sMaskMemory;
}
Player_InitCommon(this, play, gPlayerSkelHeaders[((void)0, gSaveContext.linkAge)]);
this->giObjectSegment = (void*)(((uintptr_t)ZELDA_ARENA_MALLOC_DEBUG(0x3008) + 8) & ~0xF);
sp50 = gSaveContext.respawnFlag;
if (sp50 != 0) {
if (sp50 == -3) {
thisx->params = gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams;
} else {
if ((sp50 == 1) || (sp50 == -1)) {
this->unk_A86 = -2;
}
if (sp50 < 0) {
sp4C = 0;
} else {
sp4C = sp50 - 1;
Math_Vec3f_Copy(&thisx->world.pos, &gSaveContext.respawn[sp50 - 1].pos);
Math_Vec3f_Copy(&thisx->home.pos, &thisx->world.pos);
Math_Vec3f_Copy(&thisx->prevPos, &thisx->world.pos);
this->fallStartHeight = thisx->world.pos.y;
this->yaw = thisx->shape.rot.y = gSaveContext.respawn[sp4C].yaw;
thisx->params = gSaveContext.respawn[sp4C].playerParams;
}
play->actorCtx.flags.tempSwch = gSaveContext.respawn[sp4C].tempSwchFlags & 0xFFFFFF;
play->actorCtx.flags.tempCollect = gSaveContext.respawn[sp4C].tempCollectFlags;
}
}
if ((sp50 == 0) || (sp50 < -1)) {
titleFileSize = scene->titleFile.vromEnd - scene->titleFile.vromStart;
if (gSaveContext.showTitleCard) {
if ((gSaveContext.sceneSetupIndex < 4) &&
(gEntranceTable[((void)0, gSaveContext.entranceIndex) + ((void)0, gSaveContext.sceneSetupIndex)].field &
ENTRANCE_INFO_DISPLAY_TITLE_CARD_FLAG) &&
((play->sceneNum != SCENE_DODONGOS_CAVERN) || (Flags_GetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN))) &&
((play->sceneNum != SCENE_BOMBCHU_SHOP) || (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)))) {
TitleCard_InitPlaceName(play, &play->actorCtx.titleCtx, this->giObjectSegment, 160, 120, 144,
24, 20);
}
}
gSaveContext.showTitleCard = true;
}
if (func_80845C68(play, (sp50 == 2) ? 1 : 0) == 0) {
gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = (thisx->params & 0xFF) | 0xD00;
}
gSaveContext.respawn[RESPAWN_MODE_DOWN].data = 1;
if (play->sceneNum <= SCENE_INSIDE_GANONS_CASTLE_COLLAPSE) {
gSaveContext.infTable[26] |= gBitFlags[play->sceneNum];
}
initMode = (thisx->params & 0xF00) >> 8;
if ((initMode == 5) || (initMode == 6)) {
if (gSaveContext.cutsceneIndex >= 0xFFF0) {
initMode = 13;
}
}
D_80854738[initMode](play, this);
if (initMode != 0) {
if ((gSaveContext.gameMode == 0) || (gSaveContext.gameMode == 3)) {
this->naviActor = Player_SpawnFairy(play, this, &thisx->world.pos, &D_80854778, FAIRY_NAVI);
if (gSaveContext.dogParams != 0) {
gSaveContext.dogParams |= 0x8000;
}
}
}
if (gSaveContext.nayrusLoveTimer != 0) {
gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1;
func_80846A00(play, this, 1);
this->stateFlags3 &= ~PLAYER_STATE3_RESTORE_NAYRUS_LOVE;
}
if (gSaveContext.entranceSound != 0) {
Audio_PlayActorSound2(&this->actor, ((void)0, gSaveContext.entranceSound));
gSaveContext.entranceSound = 0;
}
Map_SavePlayerInitialInfo(play);
MREG(64) = 0;
}
void func_808471F4(s16* pValue) {
s16 step;
step = (ABS(*pValue) * 100.0f) / 1000.0f;
step = CLAMP(step, 400, 4000);
Math_ScaledStepToS(pValue, 0, step);
}
void func_80847298(Player* this) {
s16 sp26;
if (!(this->unk_6AE & 2)) {
sp26 = this->actor.focus.rot.y - this->actor.shape.rot.y;
func_808471F4(&sp26);
this->actor.focus.rot.y = this->actor.shape.rot.y + sp26;
}
if (!(this->unk_6AE & 1)) {
func_808471F4(&this->actor.focus.rot.x);
}
if (!(this->unk_6AE & 8)) {
func_808471F4(&this->unk_6B6);
}
if (!(this->unk_6AE & 0x40)) {
func_808471F4(&this->unk_6BC);
}
if (!(this->unk_6AE & 4)) {
func_808471F4(&this->actor.focus.rot.z);
}
if (!(this->unk_6AE & 0x10)) {
func_808471F4(&this->unk_6B8);
}
if (!(this->unk_6AE & 0x20)) {
func_808471F4(&this->unk_6BA);
}
if (!(this->unk_6AE & 0x80)) {
if (this->unk_6B0 != 0) {
func_808471F4(&this->unk_6B0);
} else {
func_808471F4(&this->unk_6BE);
}
}
if (!(this->unk_6AE & 0x100)) {
func_808471F4(&this->unk_6C0);
}
this->unk_6AE = 0;
}
static f32 D_80854784[] = { 120.0f, 240.0f, 360.0f };
static u8 sDiveDoActions[] = { DO_ACTION_1, DO_ACTION_2, DO_ACTION_3, DO_ACTION_4,
DO_ACTION_5, DO_ACTION_6, DO_ACTION_7, DO_ACTION_8 };
void func_808473D4(PlayState* play, Player* this) {
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) && (this->actor.category == ACTORCAT_PLAYER)) {
Actor* heldActor = this->heldActor;
Actor* interactRangeActor = this->interactRangeActor;
s32 sp24;
s32 sp20 = this->unk_84B[this->unk_846];
s32 sp1C = func_808332B8(this);
s32 doAction = DO_ACTION_NONE;
if (!Player_InBlockingCsMode(play, this)) {
if (this->stateFlags1 & PLAYER_STATE1_FIRST_PERSON) {
doAction = DO_ACTION_RETURN;
} else if ((this->heldItemAction == PLAYER_IA_FISHING_POLE) && (this->unk_860 != 0)) {
if (this->unk_860 == 2) {
doAction = DO_ACTION_REEL;
}
} else if ((Player_Action_8084E3C4 != this->actionFunc) && !(this->stateFlags2 & PLAYER_STATE2_CRAWLING)) {
if ((this->doorType != PLAYER_DOORTYPE_NONE) &&
(!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) ||
((heldActor != NULL) && (heldActor->id == ACTOR_EN_RU1)))) {
doAction = DO_ACTION_OPEN;
} else if ((!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) || (heldActor == NULL)) &&
(interactRangeActor != NULL) &&
((!sp1C && (this->getItemId == GI_NONE)) ||
(this->getItemId < 0 && !(this->stateFlags1 & PLAYER_STATE1_IN_WATER)))) {
if (this->getItemId < 0) {
doAction = DO_ACTION_OPEN;
} else if ((interactRangeActor->id == ACTOR_BG_TOKI_SWD) && LINK_IS_ADULT) {
doAction = DO_ACTION_DROP;
} else {
doAction = DO_ACTION_GRAB;
}
} else if (!sp1C && (this->stateFlags2 & PLAYER_STATE2_DO_ACTION_GRAB)) {
doAction = DO_ACTION_GRAB;
} else if ((this->stateFlags2 & PLAYER_STATE2_DO_ACTION_CLIMB) ||
(!(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->rideActor != NULL))) {
doAction = DO_ACTION_CLIMB;
} else if ((this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && !EN_HORSE_CHECK_4((EnHorse*)this->rideActor) &&
(Player_Action_8084D3E4 != this->actionFunc)) {
if ((this->stateFlags2 & PLAYER_STATE2_SPEAK_OR_CHECK) && (this->targetActor != NULL)) {
if (this->targetActor->category == ACTORCAT_NPC) {
doAction = DO_ACTION_SPEAK;
} else {
doAction = DO_ACTION_CHECK;
}
} else if (!func_8002DD78(this) && !(this->stateFlags1 & PLAYER_STATE1_FIRST_PERSON)) {
doAction = DO_ACTION_FASTER;
}
} else if ((this->stateFlags2 & PLAYER_STATE2_SPEAK_OR_CHECK) && (this->targetActor != NULL)) {
if (this->targetActor->category == ACTORCAT_NPC) {
doAction = DO_ACTION_SPEAK;
} else {
doAction = DO_ACTION_CHECK;
}
} else if ((this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LADDER)) ||
((this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->stateFlags2 & PLAYER_STATE2_DO_ACTION_DOWN))) {
doAction = DO_ACTION_DOWN;
} else if (this->stateFlags2 & PLAYER_STATE2_DO_ACTION_ENTER) {
doAction = DO_ACTION_ENTER;
} else if ((this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->getItemId == GI_NONE) &&
(heldActor != NULL)) {
if ((this->actor.bgCheckFlags & 1) || (heldActor->id == ACTOR_EN_NIW)) {
if (func_8083EAF0(this, heldActor) == 0) {
doAction = DO_ACTION_DROP;
} else {
doAction = DO_ACTION_THROW;
}
}
} else if (!(this->stateFlags1 & PLAYER_STATE1_IN_WATER) && func_8083A0D4(this) &&
(this->getItemId < GI_MAX)) {
doAction = DO_ACTION_GRAB;
} else if (this->stateFlags2 & PLAYER_STATE2_DIVING) {
sp24 = (D_80854784[CUR_UPG_VALUE(UPG_SCALE)] - this->actor.yDistToWater) / 40.0f;
sp24 = CLAMP(sp24, 0, 7);
doAction = sDiveDoActions[sp24];
} else if (sp1C && !(this->stateFlags2 & PLAYER_STATE2_UNDERWATER)) {
doAction = DO_ACTION_DIVE;
} else if (!sp1C && (!(this->stateFlags1 & PLAYER_STATE1_SHIELDING) || func_80833BCC(this) ||
!Player_IsChildWithHylianShield(this))) {
if ((!(this->stateFlags1 & PLAYER_STATE1_CLIMBING_LEDGE) && (sp20 <= 0) &&
(func_8008E9C4(this) ||
((sFloorType != 7) && (func_80833B2C(this) ||
((play->roomCtx.curRoom.behaviorType1 != ROOM_BEHAVIOR_TYPE1_2) &&
!(this->stateFlags1 & PLAYER_STATE1_SHIELDING) && (sp20 == 0))))))) {
doAction = DO_ACTION_ATTACK;
} else if ((play->roomCtx.curRoom.behaviorType1 != ROOM_BEHAVIOR_TYPE1_2) &&
func_80833BCC(this) && (sp20 > 0)) {
doAction = DO_ACTION_JUMP;
} else if ((this->heldItemAction >= PLAYER_IA_SWORD_MASTER) ||
((this->stateFlags2 & PLAYER_STATE2_NAVI_OUT) &&
(play->actorCtx.targetCtx.arrowPointedActor == NULL))) {
doAction = DO_ACTION_PUTAWAY;
}
}
}
}
if (doAction != DO_ACTION_PUTAWAY) {
this->unk_837 = 20;
} else if (this->unk_837 != 0) {
if (CVarGetInteger("gInstantPutaway", 0) != 0) {
this->unk_837 = 0;
} else {
doAction = DO_ACTION_NONE;
this->unk_837--;
}
}
Interface_SetDoAction(play, doAction);
if (this->stateFlags2 & PLAYER_STATE2_NAVI_ALERT) {
if (this->unk_664 != NULL) {
Interface_SetNaviCall(play, 0x1E);
} else {
Interface_SetNaviCall(play, 0x1D);
}
Interface_SetNaviCall(play, 0x1E);
} else {
Interface_SetNaviCall(play, 0x1F);
}
}
}
/**
* Updates state related to the Hover Boots.
* Handles a special case where the Hover Boots are able to activate when standing on certain floor types even if the
* player is standing on the ground.
*
* If the player is not on the ground, regardless of the usage of the Hover Boots, various floor related variables are
* reset.
*
* @return true if not on the ground, false otherwise. Note this is independent of the Hover Boots state.
*/
s32 Player_UpdateHoverBoots(Player* this) {
s32 cond;
if ((this->currentBoots == PLAYER_BOOTS_HOVER ||
(CVarGetInteger("gIvanCoopModeEnabled", 0) && this->ivanFloating)) &&
(this->hoverBootsTimer != 0)) {
this->hoverBootsTimer--;
} else {
this->hoverBootsTimer = 0;
}
cond = (this->currentBoots == PLAYER_BOOTS_HOVER ||
(CVarGetInteger("gIvanCoopModeEnabled", 0) && this->ivanFloating)) &&
((this->actor.yDistToWater >= 0.0f) || (func_80838144(sFloorType) >= 0) || func_8083816C(sFloorType));
if (cond && (this->actor.bgCheckFlags & 1) && (this->hoverBootsTimer != 0)) {
this->actor.bgCheckFlags &= ~1;
}
if (this->actor.bgCheckFlags & 1) {
if (!cond) {
this->hoverBootsTimer = 19;
}
return 0;
}
sFloorType = 0;
this->floorPitch = this->floorPitchAlt = sFloorShapePitch = 0;
return 1;
}
/**
* Peforms various tasks related to scene collision.
*
* This includes:
* - Update BgCheckInfo, parameters adjusted due to various state flags
* - Update floor type, floor property and floor sfx offset
* - Update conveyor, reverb and light settings according to the current floor poly
* - Handle exits and voids
* - Update information relating to the "interact wall"
* - Update information for ledge climbing
* - Update hover boots
* - Calculate floor poly angles
*
*/
void Player_ProcessSceneCollision(PlayState* play, Player* this) {
static Vec3f sInteractWallCheckOffset = { 0.0f, 18.0f, 0.0f };
u8 nextLedgeClimbType = 0;
CollisionPoly* floorPoly;
Vec3f unusedWorldPos;
f32 spB0;
f32 spAC;
f32 ceilingCheckHeight;
u32 flags;
sPrevFloorProperty = this->floorProperty;
if (this->stateFlags2 & PLAYER_STATE2_CRAWLING) {
spB0 = 10.0f;
spAC = 15.0f;
ceilingCheckHeight = 30.0f;
} else {
spB0 = this->ageProperties->wallCheckRadius;
spAC = 26.0f;
ceilingCheckHeight = this->ageProperties->ceilingCheckHeight;
}
if (this->stateFlags1 & (PLAYER_STATE1_IN_CUTSCENE | PLAYER_STATE1_FLOOR_DISABLED)) {
if (this->stateFlags1 & PLAYER_STATE1_FLOOR_DISABLED) {
this->actor.bgCheckFlags &= ~1;
flags = 0x38;
} else if ((this->stateFlags1 & PLAYER_STATE1_LOADING) && ((this->unk_A84 - (s32)this->actor.world.pos.y) >= 100)) {
flags = 0x39;
} else if (!(this->stateFlags1 & PLAYER_STATE1_LOADING) &&
((Player_Action_80845EF8 == this->actionFunc) || (Player_Action_80845CA4 == this->actionFunc))) {
this->actor.bgCheckFlags &= ~0x208;
flags = 0x3C;
} else {
flags = 0x3F;
}
} else {
flags = 0x3F;
}
if (this->stateFlags3 & PLAYER_STATE3_IGNORE_CEILING_FLOOR_WATER) {
flags &= ~6;
}
if (flags & 4) {
this->stateFlags3 |= PLAYER_STATE3_CHECK_FLOOR_WATER_COLLISION;
}
Math_Vec3f_Copy(&unusedWorldPos, &this->actor.world.pos);
Actor_UpdateBgCheckInfo(play, &this->actor, spAC, spB0, ceilingCheckHeight, flags);
if (this->actor.bgCheckFlags & 0x10) {
this->actor.velocity.y = 0.0f;
}
sYDistToFloor = this->actor.world.pos.y - this->actor.floorHeight;
sConveyorSpeed = 0;
floorPoly = this->actor.floorPoly;
if (floorPoly != NULL) {
this->floorProperty = func_80041EA4(&play->colCtx, floorPoly, this->actor.floorBgId);
this->prevFloorSfxOffset = this->floorSfxOffset;
if (this->actor.bgCheckFlags & 0x20) {
if (this->actor.yDistToWater < 20.0f) {
this->floorSfxOffset = 4;
} else {
this->floorSfxOffset = 5;
}
} else {
if (this->stateFlags2 & PLAYER_STATE2_SPAWN_DUST) {
this->floorSfxOffset = 1;
} else {
this->floorSfxOffset = SurfaceType_GetSfx(&play->colCtx, floorPoly, this->actor.floorBgId);
}
}
if (this->actor.category == ACTORCAT_PLAYER) {
Audio_SetCodeReverb(SurfaceType_GetEcho(&play->colCtx, floorPoly, this->actor.floorBgId));
if (this->actor.floorBgId == BGCHECK_SCENE) {
func_80074CE8(play,
SurfaceType_GetLightSettingIndex(&play->colCtx, floorPoly, this->actor.floorBgId));
} else {
func_80043508(&play->colCtx, this->actor.floorBgId);
}
}
sConveyorSpeed = SurfaceType_GetConveyorSpeed(&play->colCtx, floorPoly, this->actor.floorBgId);
if (sConveyorSpeed != 0) {
sIsFloorConveyor = SurfaceType_IsConveyor(&play->colCtx, floorPoly, this->actor.floorBgId);
if (((sIsFloorConveyor == 0) && (this->actor.yDistToWater > 20.0f) &&
(this->currentBoots != PLAYER_BOOTS_IRON)) ||
((sIsFloorConveyor != 0) && (this->actor.bgCheckFlags & 1))) {
sConveyorYaw = SurfaceType_GetConveyorDirection(&play->colCtx, floorPoly, this->actor.floorBgId) << 10;
} else {
sConveyorSpeed = 0;
}
}
}
Player_HandleExitsAndVoids(play, this, floorPoly, this->actor.floorBgId);
this->actor.bgCheckFlags &= ~0x200;
if (this->actor.bgCheckFlags & 8) {
CollisionPoly* wallPoly;
s32 wallBgId;
s16 yawDiff;
s32 pad;
sInteractWallCheckOffset.y = 18.0f;
sInteractWallCheckOffset.z = this->ageProperties->wallCheckRadius + 10.0f;
if (!(this->stateFlags2 & PLAYER_STATE2_CRAWLING) &&
Player_PosVsWallLineTest(play, this, &sInteractWallCheckOffset, &wallPoly, &wallBgId, &sInteractWallCheckResult)) {
this->actor.bgCheckFlags |= 0x200;
if (this->actor.wallPoly != wallPoly) {
this->actor.wallPoly = wallPoly;
this->actor.wallBgId = wallBgId;
this->actor.wallYaw = Math_Atan2S(wallPoly->normal.z, wallPoly->normal.x);
}
}
yawDiff = this->actor.shape.rot.y - (s16)(this->actor.wallYaw + 0x8000);
sTouchedWallFlags = func_80041DB8(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId);
// conflicts arise from these two being enabled at once, and with ClimbEverything on, FixVineFall is redundant anyway
if (CVarGetInteger("gFixVineFall", 0) && !CVarGetInteger("gClimbEverything", 0)) {
/* This fixes the "started climbing a wall and then immediately fell off" bug.
* The main idea is if a climbing wall is detected, double-check that it will
* still be valid once climbing begins by doing a second raycast with a small
* margin to make sure it still hits a climbable poly. Then update the flags
* in sTouchedWallFlags again and proceed as normal.
*/
if (sTouchedWallFlags & 8) {
Vec3f checkPosA;
Vec3f checkPosB;
f32 yawCos;
f32 yawSin;
s32 hitWall;
/* Angle the raycast slightly out towards the side based on the angle of
* attack the player takes coming at the climb wall. This is necessary because
* the player's XZ position actually wobbles very slightly while climbing
* due to small rounding errors in the sin/cos lookup tables. This wobble
* can cause wall checks while climbing to be slightly left or right of
* the wall check to start the climb. By adding this buffer it accounts for
* any possible wobble. The end result is the player has to be further than
* some epsilon distance from the edge of the climbing poly to actually
* start the climb. I divide it by 2 to make that epsilon slightly smaller,
* mainly for visuals. Using the full yawDiff leaves a noticeable gap on
* the edges that can't be climbed. But with the half distance it looks like
* the player is climbing right on the edge, and still works.
*/
yawCos = Math_CosS(this->actor.wallYaw - (yawDiff / 2) + 0x8000);
yawSin = Math_SinS(this->actor.wallYaw - (yawDiff / 2) + 0x8000);
checkPosA.x = this->actor.world.pos.x + (-20.0f * yawSin);
checkPosA.z = this->actor.world.pos.z + (-20.0f * yawCos);
checkPosB.x = this->actor.world.pos.x + (50.0f * yawSin);
checkPosB.z = this->actor.world.pos.z + (50.0f * yawCos);
checkPosB.y = checkPosA.y = this->actor.world.pos.y + 26.0f;
hitWall = BgCheck_EntityLineTest1(&play->colCtx, &checkPosA, &checkPosB,
&sInteractWallCheckResult, &wallPoly, true, false, false, true, &wallBgId);
if (hitWall) {
this->actor.wallPoly = wallPoly;
this->actor.wallBgId = wallBgId;
this->actor.wallYaw = Math_Atan2S(wallPoly->normal.z, wallPoly->normal.x);
yawDiff = this->actor.shape.rot.y - (s16)(this->actor.wallYaw + 0x8000);
sTouchedWallFlags = func_80041DB8(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId);
}
}
}
sShapeYawToTouchedWall = ABS(yawDiff);
yawDiff = this->yaw - (s16)(this->actor.wallYaw + 0x8000);
sWorldYawToTouchedWall = ABS(yawDiff);
spB0 = sWorldYawToTouchedWall * 0.00008f;
if (!(this->actor.bgCheckFlags & 1) || spB0 >= 1.0f) {
this->unk_880 = R_RUN_SPEED_LIMIT / 100.0f;
} else {
spAC = (R_RUN_SPEED_LIMIT / 100.0f * spB0);
this->unk_880 = spAC;
if (spAC < 0.1f) {
this->unk_880 = 0.1f;
}
}
if ((this->actor.bgCheckFlags & 0x200) && (sShapeYawToTouchedWall < 0x3000)) {
CollisionPoly* wallPoly = this->actor.wallPoly;
if ((ABS(wallPoly->normal.y) < 600) || (CVarGetInteger("gClimbEverything", 0) != 0)) {
f32 sp8C = COLPOLY_GET_NORMAL(wallPoly->normal.x);
f32 sp88 = COLPOLY_GET_NORMAL(wallPoly->normal.y);
f32 sp84 = COLPOLY_GET_NORMAL(wallPoly->normal.z);
f32 yDistToLedge;
CollisionPoly* sp7C;
CollisionPoly* sp78;
s32 sp74;
Vec3f sp68;
f32 sp64;
f32 sp60;
s32 temp3;
this->distToInteractWall = Math3D_UDistPlaneToPos(sp8C, sp88, sp84, wallPoly->dist, &this->actor.world.pos);
spB0 = this->distToInteractWall + 10.0f;
sp68.x = this->actor.world.pos.x - (spB0 * sp8C);
sp68.z = this->actor.world.pos.z - (spB0 * sp84);
sp68.y = this->actor.world.pos.y + this->ageProperties->unk_0C;
sp64 = BgCheck_EntityRaycastFloor1(&play->colCtx, &sp7C, &sp68);
yDistToLedge = sp64 - this->actor.world.pos.y;
this->yDistToLedge = yDistToLedge;
if ((this->yDistToLedge < 18.0f) ||
BgCheck_EntityCheckCeiling(&play->colCtx, &sp60, &this->actor.world.pos,
(sp64 - this->actor.world.pos.y) + 20.0f, &sp78, &sp74, &this->actor)) {
this->yDistToLedge = 399.96002f;
} else {
sInteractWallCheckOffset.y = (sp64 + 5.0f) - this->actor.world.pos.y;
if (Player_PosVsWallLineTest(play, this, &sInteractWallCheckOffset, &sp78, &sp74, &sInteractWallCheckResult) &&
(temp3 = this->actor.wallYaw - Math_Atan2S(sp78->normal.z, sp78->normal.x),
ABS(temp3) < 0x4000) &&
!func_80041E18(&play->colCtx, sp78, sp74)) {
this->yDistToLedge = 399.96002f;
} else if (func_80041DE4(&play->colCtx, wallPoly, this->actor.wallBgId) == 0) {
if (this->ageProperties->unk_1C <= this->yDistToLedge) {
if (ABS(sp7C->normal.y) > 28000) {
if (this->ageProperties->unk_14 <= this->yDistToLedge) {
nextLedgeClimbType = 4;
} else if (this->ageProperties->unk_18 <= this->yDistToLedge) {
nextLedgeClimbType = 3;
} else {
nextLedgeClimbType = 2;
}
}
} else {
nextLedgeClimbType = 1;
}
}
}
}
}
} else {
this->unk_880 = R_RUN_SPEED_LIMIT / 100.0f;
this->ledgeClimbDelayTimer = 0;
this->yDistToLedge = 0.0f;
}
if (nextLedgeClimbType == this->ledgeClimbType) {
if ((this->linearVelocity != 0.0f) && (this->ledgeClimbDelayTimer < 100)) {
this->ledgeClimbDelayTimer++;
}
} else {
this->ledgeClimbType = nextLedgeClimbType;
this->ledgeClimbDelayTimer = 0;
}
if (this->actor.bgCheckFlags & 1) {
sFloorType = func_80041D4C(&play->colCtx, floorPoly, this->actor.floorBgId);
if (!Player_UpdateHoverBoots(this)) {
f32 sp58;
f32 sp54;
f32 sp50;
f32 sp4C;
s32 pad2;
f32 sp44;
s32 pad3;
if (this->actor.floorBgId != BGCHECK_SCENE) {
func_800434C8(&play->colCtx, this->actor.floorBgId);
}
sp58 = COLPOLY_GET_NORMAL(floorPoly->normal.x);
sp54 = 1.0f / COLPOLY_GET_NORMAL(floorPoly->normal.y);
sp50 = COLPOLY_GET_NORMAL(floorPoly->normal.z);
sp4C = Math_SinS(this->yaw);
sp44 = Math_CosS(this->yaw);
this->floorPitch = Math_Atan2S(1.0f, (-(sp58 * sp4C) - (sp50 * sp44)) * sp54);
this->floorPitchAlt = Math_Atan2S(1.0f, (-(sp58 * sp44) - (sp50 * sp4C)) * sp54);
sp4C = Math_SinS(this->actor.shape.rot.y);
sp44 = Math_CosS(this->actor.shape.rot.y);
sFloorShapePitch = Math_Atan2S(1.0f, (-(sp58 * sp4C) - (sp50 * sp44)) * sp54);
Player_HandleSlopes(play, this, floorPoly);
}
} else {
Player_UpdateHoverBoots(this);
}
if (this->prevFloorType == sFloorType) {
this->floorTypeTimer++;
} else {
this->prevFloorType = sFloorType;
this->floorTypeTimer = 0;
}
}
void Player_UpdateCamAndSeqModes(PlayState* play, Player* this) {
u8 seqMode;
s32 pad;
Actor* unk_664;
s32 camMode;
if (this->actor.category == ACTORCAT_PLAYER) {
seqMode = SEQ_MODE_DEFAULT;
if (this->csAction != 0) {
Camera_ChangeMode(Play_GetCamera(play, 0), CAM_MODE_NORMAL);
} else if (!(this->stateFlags1 & PLAYER_STATE1_FIRST_PERSON)) {
if ((this->actor.parent != NULL) && (this->stateFlags3 & PLAYER_STATE3_HOOKSHOT_TRAVELLING)) {
camMode = CAM_MODE_HOOKSHOT;
Camera_SetParam(Play_GetCamera(play, 0), 8, this->actor.parent);
} else if (Player_Action_8084377C == this->actionFunc) {
camMode = CAM_MODE_STILL;
} else if (this->stateFlags2 & PLAYER_STATE2_GRABBING_DYNAPOLY) {
camMode = CAM_MODE_PUSHPULL;
} else if ((unk_664 = this->unk_664) != NULL) {
if (CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_PLAYER_TALKED_TO)) {
camMode = CAM_MODE_TALK;
} else if (this->stateFlags1 & PLAYER_STATE1_TARGET_LOCKED) {
if (this->stateFlags1 & PLAYER_STATE1_THREW_BOOMERANG) {
camMode = CAM_MODE_FOLLOWBOOMERANG;
} else {
camMode = CAM_MODE_FOLLOWTARGET;
}
} else {
camMode = CAM_MODE_BATTLE;
}
Camera_SetParam(Play_GetCamera(play, 0), 8, unk_664);
} else if (this->stateFlags1 & PLAYER_STATE1_CHARGING_SPIN_ATTACK) {
camMode = CAM_MODE_CHARGE;
} else if (this->stateFlags1 & PLAYER_STATE1_THREW_BOOMERANG) {
camMode = CAM_MODE_FOLLOWBOOMERANG;
Camera_SetParam(Play_GetCamera(play, 0), 8, this->boomerangActor);
} else if (this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE)) {
if (func_80833B2C(this)) {
camMode = CAM_MODE_HANGZ;
} else {
camMode = CAM_MODE_HANG;
}
} else if (this->stateFlags1 & (PLAYER_STATE1_TARGET_NOTHING | PLAYER_STATE1_30)) {
if (func_8002DD78(this) || func_808334B4(this)) {
camMode = CAM_MODE_BOWARROWZ;
} else if (this->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER) {
camMode = CAM_MODE_CLIMBZ;
} else {
camMode = CAM_MODE_TARGET;
}
} else if (this->stateFlags1 & (PLAYER_STATE1_JUMPING | PLAYER_STATE1_CLIMBING_LADDER)) {
if ((Player_Action_80845668 == this->actionFunc) || (this->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER)) {
camMode = CAM_MODE_CLIMB;
} else {
camMode = CAM_MODE_JUMP;
}
} else if (this->stateFlags1 & PLAYER_STATE1_FREEFALL) {
camMode = CAM_MODE_FREEFALL;
} else if ((this->meleeWeaponState != 0) && (this->meleeWeaponAnimation >= PLAYER_MWA_FORWARD_SLASH_1H) &&
(this->meleeWeaponAnimation < PLAYER_MWA_SPIN_ATTACK_1H)) {
camMode = CAM_MODE_STILL;
} else {
camMode = CAM_MODE_NORMAL;
if ((this->linearVelocity == 0.0f) &&
(!(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) || (this->rideActor->speedXZ == 0.0f))) {
// not moving
seqMode = SEQ_MODE_STILL;
}
}
Camera_ChangeMode(Play_GetCamera(play, 0), camMode);
} else {
// First person mode
seqMode = SEQ_MODE_STILL;
}
if (play->actorCtx.targetCtx.bgmEnemy != NULL && !CVarGetInteger("gEnemyBGMDisable", 0)) {
seqMode = SEQ_MODE_ENEMY;
Audio_SetBgmEnemyVolume(sqrtf(play->actorCtx.targetCtx.bgmEnemy->xyzDistToPlayerSq));
}
if (play->sceneNum != SCENE_FISHING_POND) {
Audio_SetSequenceMode(seqMode);
}
}
}
static Vec3f D_808547A4 = { 0.0f, 0.5f, 0.0f };
static Vec3f D_808547B0 = { 0.0f, 0.5f, 0.0f };
static Color_RGBA8 D_808547BC = { 255, 255, 100, 255 };
static Color_RGBA8 D_808547C0 = { 255, 50, 0, 0 };
void func_80848A04(PlayState* play, Player* this) {
f32 temp;
if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) {
f32 temp2 = 1.0f; // Secondary temporary variable to use with the alleged draw flame function
this->unk_860 = 200; // Keeps the stick's flame lit
this->unk_85C = 1.0f; // Ensures the stick is the proper length
func_8002836C(play, &this->meleeWeaponInfo[0].tip, &D_808547A4, &D_808547B0, &D_808547BC, &D_808547C0, temp2 * 200.0f,
0, 8); // I believe this draws the flame effect
}
if (this->unk_85C == 0.0f && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) {
Player_UseItem(play, this, 0xFF);
return;
}
temp = 1.0f;
if (DECR(this->unk_860) == 0 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) {
Inventory_ChangeAmmo(ITEM_STICK, -1);
this->unk_860 = 1;
temp = 0.0f;
this->unk_85C = temp;
} else if (this->unk_860 > 200) {
temp = (210 - this->unk_860) / 10.0f;
} else if (this->unk_860 < 20 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) {
temp = this->unk_860 / 20.0f;
this->unk_85C = temp;
}
func_8002836C(play, &this->meleeWeaponInfo[0].tip, &D_808547A4, &D_808547B0, &D_808547BC, &D_808547C0, temp * 200.0f,
0, 8);
}
void Player_UpdateBodyShock(PlayState* play, Player* this) {
Vec3f shockPos;
Vec3f* randBodyPart;
s32 shockScale;
this->bodyShockTimer--;
this->unk_892 += this->bodyShockTimer;
if (this->unk_892 > 20) {
shockScale = this->bodyShockTimer * 2;
this->unk_892 -= 20;
if (shockScale > 40) {
shockScale = 40;
}
randBodyPart = this->bodyPartsPos + (s32)Rand_ZeroFloat(ARRAY_COUNT(this->bodyPartsPos) - 0.1f);
shockPos.x = (Rand_CenteredFloat(5.0f) + randBodyPart->x) - this->actor.world.pos.x;
shockPos.y = (Rand_CenteredFloat(5.0f) + randBodyPart->y) - this->actor.world.pos.y;
shockPos.z = (Rand_CenteredFloat(5.0f) + randBodyPart->z) - this->actor.world.pos.z;
EffectSsFhgFlash_SpawnShock(play, &this->actor, &shockPos, shockScale, FHGFLASH_SHOCK_PLAYER);
func_8002F8F0(&this->actor, NA_SE_PL_SPARK - SFX_FLAG);
}
}
void Player_UpdateBodyBurn(PlayState* play, Player* this) {
s32 spawnedFlame;
u8* timerPtr;
s32 timerStep;
f32 flameScale;
f32 flameIntensity;
s32 dmgCooldown;
s32 i;
s32 sp58;
s32 sp54;
if (this->currentTunic == PLAYER_TUNIC_GORON || CVarGetInteger("gSuperTunic", 0) != 0) {
sp54 = 20;
} else {
sp54 = (s32)(this->linearVelocity * 0.4f) + 1;
}
spawnedFlame = false;
timerPtr = this->bodyFlameTimers;
if (this->stateFlags2 & PLAYER_STATE2_FOOTSTEP) {
sp58 = 100;
} else {
sp58 = 0;
}
func_8083819C(this, play);
for (i = 0; i < PLAYER_BODYPART_MAX; i++, timerPtr++) {
timerStep = sp58 + sp54;
if (*timerPtr <= timerStep) {
*timerPtr = 0;
} else {
spawnedFlame = true;
*timerPtr -= timerStep;
if (*timerPtr > 20.0f) {
flameIntensity = (*timerPtr - 20.0f) * 0.01f;
flameScale = CLAMP(flameIntensity, 0.19999999f, 0.2f);
} else {
flameScale = *timerPtr * 0.01f;
}
flameIntensity = (*timerPtr - 25.0f) * 0.02f;
flameIntensity = CLAMP(flameIntensity, 0.0f, 1.0f);
EffectSsFireTail_SpawnFlameOnPlayer(play, flameScale, i, flameIntensity);
}
}
if (spawnedFlame) {
Player_PlaySfx(this, NA_SE_EV_TORCH - SFX_FLAG);
if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) {
dmgCooldown = 0;
} else {
dmgCooldown = 7;
}
if ((dmgCooldown & play->gameplayFrames) == 0) {
Player_InflictDamage(play, -1);
}
} else {
this->bodyIsBurning = false;
}
}
void func_80848EF8(Player* this, PlayState* play) {
if (CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)) {
f32 temp = 200000.0f - (this->closestSecretDistSq * 5.0f);
if (temp < 0.0f) {
temp = 0.0f;
}
this->unk_6A0 += temp;
/*Prevent it on horse, while jumping and on title screen.
If you fly around no stone of agony for you! */
Color_RGB8 stoneOfAgonyColor = { 255, 255, 255 };
if (CVarGetInteger("gCosmetics.Hud_StoneOfAgony.Changed", 0)) {
stoneOfAgonyColor = CVarGetColor24("gCosmetics.Hud_StoneOfAgony.Value", stoneOfAgonyColor);
}
if (CVarGetInteger("gVisualAgony", 0) && !this->stateFlags1 && !GameInteractor_NoUIActive()) {
s16 Top_Margins = (CVarGetInteger("gHUDMargin_T", 0) * -1);
s16 Left_Margins = CVarGetInteger("gHUDMargin_L", 0);
s16 Right_Margins = CVarGetInteger("gHUDMargin_R", 0);
s16 X_Margins_VSOA;
s16 Y_Margins_VSOA;
if (CVarGetInteger("gVSOAUseMargins", 0) != 0) {
if (CVarGetInteger("gVSOAPosType", 0) == ORIGINAL_LOCATION) {
X_Margins_VSOA = Left_Margins;
};
Y_Margins_VSOA = Top_Margins;
} else {
X_Margins_VSOA = 0;
Y_Margins_VSOA = 0;
}
s16 PosX_VSOA_ori = OTRGetRectDimensionFromLeftEdge(26) + X_Margins_VSOA;
s16 PosY_VSOA_ori = 60 + Y_Margins_VSOA;
s16 PosX_VSOA;
s16 PosY_VSOA;
if (CVarGetInteger("gVSOAPosType", 0) != ORIGINAL_LOCATION) {
PosY_VSOA = CVarGetInteger("gVSOAPosY", 0) + Y_Margins_VSOA;
if (CVarGetInteger("gVSOAPosType", 0) == ANCHOR_LEFT) {
if (CVarGetInteger("gVSOAUseMargins", 0) != 0) {
X_Margins_VSOA = Left_Margins;
};
PosX_VSOA = OTRGetDimensionFromLeftEdge(CVarGetInteger("gVSOAPosX", 0) + X_Margins_VSOA);
} else if (CVarGetInteger("gVSOAPosType", 0) == ANCHOR_RIGHT) {
if (CVarGetInteger("gVSOAUseMargins", 0) != 0) {
X_Margins_VSOA = Right_Margins;
};
PosX_VSOA = OTRGetDimensionFromRightEdge(CVarGetInteger("gVSOAPosX", 0) + X_Margins_VSOA);
} else if (CVarGetInteger("gVSOAPosType", 0) == ANCHOR_NONE) {
PosX_VSOA = CVarGetInteger("gVSOAPosX", 0);
} else if (CVarGetInteger("gVSOAPosType", 0) == HIDDEN) {
PosX_VSOA = -9999;
}
} else {
PosY_VSOA = PosY_VSOA_ori;
PosX_VSOA = PosX_VSOA_ori;
}
int rectLeft = PosX_VSOA; // Left X Pos
int rectTop = PosY_VSOA; // Top Y Pos
int rectWidth = 24; // Texture Width
int rectHeight = 24; // Texture Heigh
int DefaultIconA = 50; // Default icon alpha (55 on 255)
OPEN_DISPS(play->state.gfxCtx);
gDPPipeSync(OVERLAY_DISP++);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, stoneOfAgonyColor.r, stoneOfAgonyColor.g, stoneOfAgonyColor.b, DefaultIconA);
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
if (this->unk_6A0 > 4000000.0f) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, stoneOfAgonyColor.r, stoneOfAgonyColor.g, stoneOfAgonyColor.b, 255);
} else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, stoneOfAgonyColor.r, stoneOfAgonyColor.g, stoneOfAgonyColor.b, DefaultIconA);
}
if (temp == 0 || temp <= 0.1f) {
/*Fail check, it is used to draw off the icon when
link is standing out range but do not refresh unk_6A0.
Also used to make a default value in my case.*/
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, stoneOfAgonyColor.r, stoneOfAgonyColor.g, stoneOfAgonyColor.b, DefaultIconA);
}
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255);
gDPSetOtherMode(OVERLAY_DISP++,
G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_IA16 | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | G_RM_XLU_SURF | G_RM_XLU_SURF2);
gDPLoadTextureBlock(OVERLAY_DISP++, gQuestIconStoneOfAgonyTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 24, 24, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD);
gDPSetOtherMode(OVERLAY_DISP++,
G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_IA16 | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | G_RM_XLU_SURF | G_RM_XLU_SURF2);
gSPWideTextureRectangle(OVERLAY_DISP++, rectLeft << 2, rectTop << 2, (rectLeft + rectWidth) << 2,
(rectTop + rectHeight) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
CLOSE_DISPS(play->state.gfxCtx);
}
if (this->unk_6A0 > 4000000.0f) {
this->unk_6A0 = 0.0f;
if (CVarGetInteger("gVisualAgony", 0) && !this->stateFlags1 && !GameInteractor_NoUIActive()) {
// This audio is placed here and not in previous CVar check to prevent ears ra.. :)
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_WOMAN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E0);
}
Player_RequestRumble(this, 120, 20, 10, 0);
}
}
}
static s8 D_808547C4[] = {
0, 3, 3, 5, 4, 8, 9, 13, 14, 15, 16, 17, 18, -22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, -35,
30, 36, 38, -39, -40, -41, 42, 43, 45, 46, 0, 0, 0, 67, 48, 47, -50, 51, -52, -53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, -65, -66, 68, 11, 69, 70, 71, 8, 8, 72, 73, 78, 79, 80, 89, 90, 91, 92, 77, 19, 94,
};
static Vec3f D_80854814 = { 0.0f, 0.0f, 200.0f };
static f32 D_80854820[] = { 2.0f, 4.0f, 7.0f };
static f32 D_8085482C[] = { 0.5f, 1.0f, 3.0f };
void Player_UseTunicBoots(Player* this, PlayState* play) {
// Boots and tunics equip despite state
if (
this->stateFlags1 & (PLAYER_STATE1_INPUT_DISABLED | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE | PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD) ||
this->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING
) {
return;
}
s32 i;
for (i = 0; i < ARRAY_COUNT(sItemButtons); i++) {
if (CHECK_BTN_ALL(sControlInput->press.button, sItemButtons[i])) {
break;
}
}
s32 item = Player_GetItemOnButton(play, i);
if (item >= ITEM_TUNIC_KOKIRI && item <= ITEM_BOOTS_HOVER) {
if (item >= ITEM_BOOTS_KOKIRI) {
u16 bootsValue = item - ITEM_BOOTS_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_TYPE_BOOTS) == bootsValue) {
Inventory_ChangeEquipment(EQUIP_TYPE_BOOTS, EQUIP_VALUE_BOOTS_KOKIRI);
} else {
Inventory_ChangeEquipment(EQUIP_TYPE_BOOTS, bootsValue);
}
Player_SetEquipmentData(play, this);
func_808328EC(this, CUR_EQUIP_VALUE(EQUIP_TYPE_BOOTS) == EQUIP_VALUE_BOOTS_IRON ? NA_SE_PL_WALK_HEAVYBOOTS : NA_SE_PL_CHANGE_ARMS);
} else {
u16 tunicValue = item - ITEM_TUNIC_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == tunicValue) {
Inventory_ChangeEquipment(EQUIP_TYPE_TUNIC, EQUIP_VALUE_TUNIC_KOKIRI);
} else {
Inventory_ChangeEquipment(EQUIP_TYPE_TUNIC, tunicValue);
}
Player_SetEquipmentData(play, this);
func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
}
}
}
void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
s32 pad;
sControlInput = input;
if (this->unk_A86 < 0) {
this->unk_A86++;
if (this->unk_A86 == 0) {
this->unk_A86 = 1;
func_80078884(NA_SE_OC_REVENGE);
}
}
Math_Vec3f_Copy(&this->actor.prevPos, &this->actor.home.pos);
if (this->unk_A73 != 0) {
this->unk_A73--;
}
if (this->unk_88E != 0) {
this->unk_88E--;
}
if (this->unk_A87 != 0) {
this->unk_A87--;
}
if (this->invincibilityTimer < 0) {
this->invincibilityTimer++;
} else if (this->invincibilityTimer > 0) {
this->invincibilityTimer--;
}
if (this->unk_890 != 0) {
this->unk_890--;
}
func_808473D4(play, this);
func_80836BEC(this, play);
if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && ((this->unk_860 != 0) || CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE)) {
func_80848A04(play, this);
} else if ((this->heldItemAction == PLAYER_IA_FISHING_POLE) && (this->unk_860 < 0)) {
this->unk_860++;
}
if (this->bodyShockTimer != 0) {
Player_UpdateBodyShock(play, this);
}
if (this->bodyIsBurning) {
Player_UpdateBodyBurn(play, this);
}
if ((this->stateFlags3 & PLAYER_STATE3_RESTORE_NAYRUS_LOVE) && (gSaveContext.nayrusLoveTimer != 0) && (gSaveContext.magicState == MAGIC_STATE_IDLE)) {
gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1;
func_80846A00(play, this, 1);
this->stateFlags3 &= ~PLAYER_STATE3_RESTORE_NAYRUS_LOVE;
}
if (this->stateFlags2 & PLAYER_STATE2_PAUSE_MOST_UPDATING) {
if (!(this->actor.bgCheckFlags & 1)) {
Player_ZeroSpeedXZ(this);
Actor_MoveForward(&this->actor);
}
Player_ProcessSceneCollision(play, this);
} else {
f32 temp_f0;
f32 phi_f12;
if (this->currentBoots != this->prevBoots) {
if (this->currentBoots == PLAYER_BOOTS_IRON) {
if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) {
func_80832340(play, this);
if (this->ageProperties->unk_2C < this->actor.yDistToWater) {
this->stateFlags2 |= PLAYER_STATE2_UNDERWATER;
}
}
} else {
if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) {
if ((this->prevBoots == PLAYER_BOOTS_IRON) || (this->actor.bgCheckFlags & 1)) {
func_8083D36C(play, this);
this->stateFlags2 &= ~PLAYER_STATE2_UNDERWATER;
}
}
}
this->prevBoots = this->currentBoots;
}
if ((this->actor.parent == NULL) && (this->stateFlags1 & PLAYER_STATE1_ON_HORSE)) {
this->actor.parent = this->rideActor;
func_8083A360(play, this);
this->stateFlags1 |= PLAYER_STATE1_ON_HORSE;
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_uma_wait_1);
Player_AnimReplaceApplyFlags(play, this, 0x9B);
this->av2.actionVar2 = 99;
}
if (this->unk_844 == 0) {
this->unk_845 = 0;
} else if (this->unk_844 < 0) {
this->unk_844++;
} else {
this->unk_844--;
}
Math_ScaledStepToS(&this->unk_6C2, 0, 400);
func_80032CB4(this->unk_3A8, 20, 80, 6);
this->actor.shape.face = this->unk_3A8[0] + ((play->gameplayFrames & 32) ? 0 : 3);
if (this->currentMask == PLAYER_MASK_BUNNY) {
Player_UpdateBunnyEars(this);
}
if (func_8002DD6C(this) != 0) {
func_8084FF7C(this);
}
if (!(this->skelAnime.moveFlags & 0x80)) {
if (((this->actor.bgCheckFlags & 1) && (sFloorType == 5) && (this->currentBoots != PLAYER_BOOTS_IRON)) ||
((this->currentBoots == PLAYER_BOOTS_HOVER || GameInteractor_GetSlipperyFloorActive()) &&
!(this->stateFlags1 & (PLAYER_STATE1_IN_WATER | PLAYER_STATE1_IN_CUTSCENE)))) {
f32 sp70 = this->linearVelocity;
s16 sp6E = this->yaw;
s16 yawDiff = this->actor.world.rot.y - sp6E;
s32 pad;
if ((ABS(yawDiff) > 0x6000) && (this->actor.speedXZ != 0.0f)) {
sp70 = 0.0f;
sp6E += 0x8000;
}
if (Math_StepToF(&this->actor.speedXZ, sp70, 0.35f) && (sp70 == 0.0f)) {
this->actor.world.rot.y = this->yaw;
}
if (this->linearVelocity != 0.0f) {
s32 phi_v0;
phi_v0 = (fabsf(this->linearVelocity) * 700.0f) - (fabsf(this->actor.speedXZ) * 100.0f);
phi_v0 = CLAMP(phi_v0, 0, 1350);
Math_ScaledStepToS(&this->actor.world.rot.y, sp6E, phi_v0);
}
if ((this->linearVelocity == 0.0f) && (this->actor.speedXZ != 0.0f)) {
func_800F4138(&this->actor.projectedPos, 0xD0, this->actor.speedXZ);
}
} else {
this->actor.speedXZ = this->linearVelocity;
this->actor.world.rot.y = this->yaw;
}
func_8002D868(&this->actor);
if ((this->pushedSpeed != 0.0f) && !Player_InCsMode(play) &&
!(this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER)) &&
(Player_Action_80845668 != this->actionFunc) && (Player_Action_808507F4 != this->actionFunc)) {
this->actor.velocity.x += this->pushedSpeed * Math_SinS(this->pushedYaw);
this->actor.velocity.z += this->pushedSpeed * Math_CosS(this->pushedYaw);
}
func_8002D7EC(&this->actor);
Player_ProcessSceneCollision(play, this);
} else {
sFloorType = 0;
this->floorProperty = 0;
if (!(this->stateFlags1 & PLAYER_STATE1_LOADING) && (this->stateFlags1 & PLAYER_STATE1_ON_HORSE)) {
EnHorse* rideActor = (EnHorse*)this->rideActor;
CollisionPoly* sp5C;
s32 sp58;
Vec3f sp4C;
if (!(rideActor->actor.bgCheckFlags & 1)) {
func_808396F4(play, this, &D_80854814, &sp4C, &sp5C, &sp58);
} else {
sp5C = rideActor->actor.floorPoly;
sp58 = rideActor->actor.floorBgId;
}
if ((sp5C != NULL) && Player_HandleExitsAndVoids(play, this, sp5C, sp58)) {
if (DREG(25) != 0) {
DREG(25) = 0;
} else {
AREG(6) = 1;
}
}
}
sConveyorSpeed = 0;
this->pushedSpeed = 0.0f;
}
if ((sConveyorSpeed != 0) && (this->currentBoots != PLAYER_BOOTS_IRON)) {
f32 sp48;
sConveyorSpeed--;
if (sIsFloorConveyor == 0) {
sp48 = D_80854820[sConveyorSpeed];
if (!(this->stateFlags1 & PLAYER_STATE1_IN_WATER)) {
sp48 *= 0.25f;
}
} else {
sp48 = D_8085482C[sConveyorSpeed];
}
Math_StepToF(&this->pushedSpeed, sp48, sp48 * 0.1f);
Math_ScaledStepToS(&this->pushedYaw, sConveyorYaw,
((this->stateFlags1 & PLAYER_STATE1_IN_WATER) ? 400.0f : 800.0f) * sp48);
} else if (this->pushedSpeed != 0.0f) {
Math_StepToF(&this->pushedSpeed, 0.0f, (this->stateFlags1 & PLAYER_STATE1_IN_WATER) ? 0.5f : 1.0f);
}
if (!Player_InBlockingCsMode(play, this) && !(this->stateFlags2 & PLAYER_STATE2_CRAWLING)) {
func_8083D53C(play, this);
if ((this->actor.category == ACTORCAT_PLAYER) && (gSaveContext.health == 0)) {
if (this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER)) {
func_80832440(play, this);
func_80837B9C(this, play);
} else if ((this->actor.bgCheckFlags & 1) || (this->stateFlags1 & PLAYER_STATE1_IN_WATER)) {
func_80836448(play, this,
func_808332B8(this) ? &gPlayerAnim_link_swimer_swim_down
: (this->bodyShockTimer != 0) ? &gPlayerAnim_link_normal_electric_shock_end
: &gPlayerAnim_link_derth_rebirth);
}
} else {
if ((this->actor.parent == NULL) &&
((play->transitionTrigger == TRANS_TRIGGER_START) || (this->unk_A87 != 0) || !func_808382DC(this, play))) {
func_8083AA10(this, play);
} else {
this->fallStartHeight = this->actor.world.pos.y;
}
func_80848EF8(this, play);
}
}
if ((play->csCtx.state != CS_STATE_IDLE) && (this->csAction != 6) &&
!(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && !(this->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) &&
(this->actor.category == ACTORCAT_PLAYER)) {
CsCmdActorAction* linkActionCsCmd = play->csCtx.linkAction;
if ((linkActionCsCmd != NULL) && (D_808547C4[linkActionCsCmd->action] != 0)) {
func_8002DF54(play, NULL, 6);
Player_ZeroSpeedXZ(this);
} else if ((this->csAction == 0) && !(this->stateFlags2 & PLAYER_STATE2_UNDERWATER) &&
(play->csCtx.state != CS_STATE_UNSKIPPABLE_INIT)) {
func_8002DF54(play, NULL, 0x31);
Player_ZeroSpeedXZ(this);
}
}
if (this->csAction != 0) {
if ((this->csAction != 7) ||
!(this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER | PLAYER_STATE1_DAMAGED))) {
this->unk_6AD = 3;
} else if (Player_Action_CsAction != this->actionFunc) {
func_80852944(play, this, NULL);
}
} else {
this->prevCsAction = 0;
}
func_8083D6EC(play, this);
if ((this->unk_664 == NULL) && (this->naviTextId == 0)) {
this->stateFlags2 &= ~(PLAYER_STATE2_SPEAK_OR_CHECK | PLAYER_STATE2_NAVI_ALERT);
}
this->stateFlags1 &= ~(PLAYER_STATE1_SWINGING_BOTTLE | PLAYER_STATE1_READY_TO_FIRE | PLAYER_STATE1_CHARGING_SPIN_ATTACK | PLAYER_STATE1_SHIELDING);
this->stateFlags2 &= ~(PLAYER_STATE2_DO_ACTION_GRAB | PLAYER_STATE2_DO_ACTION_CLIMB | PLAYER_STATE2_FOOTSTEP | PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS |
PLAYER_STATE2_GRABBING_DYNAPOLY | PLAYER_STATE2_SPAWN_DUST | PLAYER_STATE2_STATIONARY_LADDER | PLAYER_STATE2_FROZEN |
PLAYER_STATE2_DO_ACTION_ENTER | PLAYER_STATE2_DO_ACTION_DOWN | PLAYER_STATE2_REFLECTION);
this->stateFlags3 &= ~PLAYER_STATE3_CHECK_FLOOR_WATER_COLLISION;
func_80847298(this);
Player_ProcessControlStick(play, this);
if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) {
D_808535E8 = 0.5f;
} else {
D_808535E8 = 1.0f;
}
D_808535EC = 1.0f / D_808535E8;
sUseHeldItem = sHeldItemButtonIsHeldDown = 0;
D_80858AA4 = this->currentMask;
if (!(this->stateFlags3 & PLAYER_STATE3_PAUSE_ACTION_FUNC)) {
this->actionFunc(this, play);
Player_UseTunicBoots(this, play);
}
Player_UpdateCamAndSeqModes(play, this);
if (this->skelAnime.moveFlags & 8) {
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime,
(this->skelAnime.moveFlags & 4) ? 1.0f : this->ageProperties->unk_08);
}
func_808368EC(this, play);
if (CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_PLAYER_TALKED_TO)) {
this->targetActorDistance = 0.0f;
} else {
this->targetActor = NULL;
this->targetActorDistance = FLT_MAX;
this->exchangeItemId = EXCH_ITEM_NONE;
}
if (!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) {
this->interactRangeActor = NULL;
this->getItemDirection = 0x6000;
}
if (this->actor.parent == NULL) {
this->rideActor = NULL;
}
this->naviTextId = 0;
if (!(this->stateFlags2 & PLAYER_STATE2_PLAY_FOR_ACTOR)) {
this->unk_6A8 = NULL;
}
this->stateFlags2 &= ~PLAYER_STATE2_NEAR_OCARINA_ACTOR;
this->closestSecretDistSq = FLT_MAX;
temp_f0 = this->actor.world.pos.y - this->actor.prevPos.y;
this->doorType = PLAYER_DOORTYPE_NONE;
this->unk_8A1 = 0;
this->unk_684 = NULL;
phi_f12 =
((this->bodyPartsPos[PLAYER_BODYPART_L_FOOT].y + this->bodyPartsPos[PLAYER_BODYPART_R_FOOT].y) * 0.5f) +
temp_f0;
temp_f0 += this->bodyPartsPos[PLAYER_BODYPART_HEAD].y + 10.0f;
this->cylinder.dim.height = temp_f0 - phi_f12;
if (this->cylinder.dim.height < 0) {
phi_f12 = temp_f0;
this->cylinder.dim.height = -this->cylinder.dim.height;
}
this->cylinder.dim.yShift = phi_f12 - this->actor.world.pos.y;
if (this->stateFlags1 & PLAYER_STATE1_SHIELDING) {
this->cylinder.dim.height = this->cylinder.dim.height * 0.8f;
}
Collider_UpdateCylinder(&this->actor, &this->cylinder);
if (!(this->stateFlags2 & PLAYER_STATE2_FROZEN)) {
if (!(this->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_ON_HORSE))) {
CollisionCheck_SetOC(play, &play->colChkCtx, &this->cylinder.base);
}
if (!(this->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_DAMAGED)) && (this->invincibilityTimer <= 0)) {
CollisionCheck_SetAC(play, &play->colChkCtx, &this->cylinder.base);
if (this->invincibilityTimer < 0) {
CollisionCheck_SetAT(play, &play->colChkCtx, &this->cylinder.base);
}
}
}
AnimationContext_SetNextQueue(play);
}
Math_Vec3f_Copy(&this->actor.home.pos, &this->actor.world.pos);
Math_Vec3f_Copy(&this->unk_A88, &this->bodyPartsPos[PLAYER_BODYPART_WAIST]);
if (this->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE)) {
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
} else {
this->actor.colChkInfo.mass = 50;
}
this->stateFlags3 &= ~PLAYER_STATE3_PAUSE_ACTION_FUNC;
Collider_ResetCylinderAC(play, &this->cylinder.base);
Collider_ResetQuadAT(play, &this->meleeWeaponQuads[0].base);
Collider_ResetQuadAT(play, &this->meleeWeaponQuads[1].base);
Collider_ResetQuadAC(play, &this->shieldQuad.base);
Collider_ResetQuadAT(play, &this->shieldQuad.base);
}
static Vec3f D_80854838 = { 0.0f, 0.0f, -30.0f };
void Player_Update(Actor* thisx, PlayState* play) {
static Vec3f sDogSpawnPos;
Player* this = (Player*)thisx;
s32 dogParams;
s32 pad;
Input sp44;
Actor* dog;
if (func_8084FCAC(this, play)) {
if (gSaveContext.dogParams < 0) {
// Disable object dependency to prevent losing dog in scenes other than market
if (Object_GetIndex(&play->objectCtx, OBJECT_DOG) < 0 && !CVarGetInteger("gDogFollowsEverywhere", 0)) {
gSaveContext.dogParams = 0;
} else {
gSaveContext.dogParams &= 0x7FFF;
Player_GetRelativePosition(this, &this->actor.world.pos, &D_80854838, &sDogSpawnPos);
dogParams = gSaveContext.dogParams;
dog = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_DOG, sDogSpawnPos.x, sDogSpawnPos.y,
sDogSpawnPos.z, 0, this->actor.shape.rot.y, 0, dogParams | 0x8000, true);
if (dog != NULL) {
// Room -1 allows actor to cross between rooms, similar to Navi
dog->room = CVarGetInteger("gDogFollowsEverywhere", 0) ? -1 : 0;
}
}
}
if ((this->interactRangeActor != NULL) && (this->interactRangeActor->update == NULL)) {
this->interactRangeActor = NULL;
}
if ((this->heldActor != NULL) && (this->heldActor->update == NULL)) {
Player_DetachHeldActor(play, this);
}
if (this->stateFlags1 & (PLAYER_STATE1_INPUT_DISABLED | PLAYER_STATE1_IN_CUTSCENE)) {
memset(&sp44, 0, sizeof(sp44));
} else {
sp44 = play->state.input[0];
if (this->unk_88E != 0) {
sp44.cur.button &= ~(BTN_A | BTN_B | BTN_CUP);
sp44.press.button &= ~(BTN_A | BTN_B | BTN_CUP);
}
}
if (CVarGetInteger("gEnableWalkModify", 0) && CVarGetInteger("gWalkSpeedToggle", 0)) {
if (CHECK_BTN_ALL(sControlInput->press.button, BTN_MODIFIER1)) {
gWalkSpeedToggle1 = !gWalkSpeedToggle1;
}
if (CHECK_BTN_ALL(sControlInput->press.button, BTN_MODIFIER2)) {
gWalkSpeedToggle2 = !gWalkSpeedToggle2;
}
}
Player_UpdateCommon(this, play, &sp44);
}
MREG(52) = this->actor.world.pos.x;
MREG(53) = this->actor.world.pos.y;
MREG(54) = this->actor.world.pos.z;
MREG(55) = this->actor.world.rot.y;
// Make Link normal size when going through doors and crawlspaces and when climbing ladders.
// Otherwise Link can glitch out, being in unloaded rooms or falling OoB.
if (this->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER || this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE ||
this->stateFlags2 & PLAYER_STATE2_CRAWLING) {
this->actor.scale.x = 0.01f;
this->actor.scale.y = 0.01f;
this->actor.scale.z = 0.01f;
} else {
switch (GameInteractor_GetLinkSize()) {
case GI_LINK_SIZE_RESET:
this->actor.scale.x = 0.01f;
this->actor.scale.y = 0.01f;
this->actor.scale.z = 0.01f;
GameInteractor_SetLinkSize(GI_LINK_SIZE_NORMAL);
break;
case GI_LINK_SIZE_GIANT:
this->actor.scale.x = 0.02f;
this->actor.scale.y = 0.02f;
this->actor.scale.z = 0.02f;
break;
case GI_LINK_SIZE_MINISH:
this->actor.scale.x = 0.001f;
this->actor.scale.y = 0.001f;
this->actor.scale.z = 0.001f;
break;
case GI_LINK_SIZE_PAPER:
this->actor.scale.x = 0.001f;
this->actor.scale.y = 0.01f;
this->actor.scale.z = 0.01f;
break;
case GI_LINK_SIZE_SQUISHED:
this->actor.scale.x = 0.015f;
this->actor.scale.y = 0.001f;
this->actor.scale.z = 0.015f;
break;
case GI_LINK_SIZE_NORMAL:
default:
break;
}
}
// Don't apply gravity when Link is in water, otherwise
// it makes him sink instead of float.
if (!(this->stateFlags1 & PLAYER_STATE1_IN_WATER)) {
switch (GameInteractor_GravityLevel()) {
case GI_GRAVITY_LEVEL_HEAVY:
this->actor.gravity = -4.0f;
break;
case GI_GRAVITY_LEVEL_LIGHT:
this->actor.gravity = -0.3f;
break;
default:
break;
}
}
if (GameInteractor_GetRandomWindActive()) {
Player* player = GET_PLAYER(play);
player->pushedSpeed = 3.0f;
// Play fan sound (too annoying)
//func_8002F974(&player->actor, NA_SE_EV_WIND_TRAP - SFX_FLAG);
}
GameInteractor_ExecuteOnPlayerUpdate();
}
typedef struct {
/* 0x0 */ Vec3s rot;
/* 0x6 */ Vec3s angVel;
} BunnyEarKinematics; // size = 0xC
static BunnyEarKinematics sBunnyEarKinematics;
static Vec3s D_80858AD8[25];
static Gfx* sMaskDlists[PLAYER_MASK_MAX - 1] = {
gLinkChildKeatonMaskDL, gLinkChildSkullMaskDL, gLinkChildSpookyMaskDL, gLinkChildBunnyHoodDL,
gLinkChildGoronMaskDL, gLinkChildZoraMaskDL, gLinkChildGerudoMaskDL, gLinkChildMaskOfTruthDL,
};
static Vec3s D_80854864 = { 0, 0, 0 };
void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList, OverrideLimbDrawOpa overrideLimbDraw) {
static s32 D_8085486C = 255;
OPEN_DISPS(play->state.gfxCtx);
gSPSegment(POLY_OPA_DISP++, 0x0C, cullDList);
gSPSegment(POLY_XLU_DISP++, 0x0C, cullDList);
Player_DrawImpl(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, lod,
this->currentTunic, this->currentBoots, this->actor.shape.face, overrideLimbDraw, Player_PostLimbDrawGameplay,
this);
if ((overrideLimbDraw == Player_OverrideLimbDrawGameplayDefault) && (this->currentMask != PLAYER_MASK_NONE)) {
// Fixes a bug in vanilla where ice traps are rendered extremely large while wearing a bunny hood
if (CVarGetInteger("gFixIceTrapWithBunnyHood", 1)) Matrix_Push();
Mtx* bunnyEarMtx = Graph_Alloc(play->state.gfxCtx, 2 * sizeof(Mtx));
if (this->currentMask == PLAYER_MASK_BUNNY) {
Vec3s earRot;
FrameInterpolation_RecordActorPosRotMatrix();
gSPSegment(POLY_OPA_DISP++, 0x0B, bunnyEarMtx);
// Right ear
earRot.x = sBunnyEarKinematics.rot.y + 0x3E2;
earRot.y = sBunnyEarKinematics.rot.z + 0xDBE;
earRot.z = sBunnyEarKinematics.rot.x - 0x348A;
Matrix_SetTranslateRotateYXZ(97.0f, -1203.0f - CVarGetFloat("gCosmetics.BunnyHood_EarLength", 0.0f), -240.0f - CVarGetFloat("gCosmetics.BunnyHood_EarSpread", 0.0f), &earRot);
MATRIX_TOMTX(bunnyEarMtx++);
// Left ear
earRot.x = sBunnyEarKinematics.rot.y - 0x3E2;
earRot.y = -0xDBE - sBunnyEarKinematics.rot.z;
earRot.z = sBunnyEarKinematics.rot.x - 0x348A;
Matrix_SetTranslateRotateYXZ(97.0f, -1203.0f - CVarGetFloat("gCosmetics.BunnyHood_EarLength", 0.0f), 240.0f + CVarGetFloat("gCosmetics.BunnyHood_EarSpread", 0.0f), &earRot);
MATRIX_TOMTX(bunnyEarMtx);
}
if (this->currentMask != PLAYER_MASK_BUNNY || !CVarGetInteger("gHideBunnyHood", 0)) {
gSPDisplayList(POLY_OPA_DISP++, sMaskDlists[this->currentMask - 1]);
}
if (CVarGetInteger("gFixIceTrapWithBunnyHood", 1)) Matrix_Pop();
}
if ((this->currentBoots == PLAYER_BOOTS_HOVER ||
(CVarGetInteger("gIvanCoopModeEnabled", 0) && this->ivanFloating)) &&
!(this->actor.bgCheckFlags & 1) &&
!(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->hoverBootsTimer != 0)) {
s32 sp5C;
s32 hoverBootsTimer = this->hoverBootsTimer;
if (this->hoverBootsTimer < 19) {
if (hoverBootsTimer >= 15) {
D_8085486C = (19 - hoverBootsTimer) * 51.0f;
} else if (hoverBootsTimer < 19) {
sp5C = hoverBootsTimer;
if (sp5C > 9) {
sp5C = 9;
}
D_8085486C = (-sp5C * 4) + 36;
D_8085486C = D_8085486C * D_8085486C;
D_8085486C = (s32)((Math_CosS(D_8085486C) * 100.0f) + 100.0f) + 55.0f;
D_8085486C = D_8085486C * (sp5C * (1.0f / 9.0f));
}
FrameInterpolation_RecordActorPosRotMatrix();
Matrix_SetTranslateRotateYXZ(this->actor.world.pos.x, this->actor.world.pos.y + 2.0f,
this->actor.world.pos.z, &D_80854864);
Matrix_Scale(4.0f, 4.0f, 4.0f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_XLU_DISP++, 0x08,
Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 16, 32, 1, 0,
(play->gameplayFrames * -15) % 128, 16, 32));
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 255, D_8085486C);
gDPSetEnvColor(POLY_XLU_DISP++, 120, 90, 30, 128);
gSPDisplayList(POLY_XLU_DISP++, gHoverBootsCircleDL);
}
}
CLOSE_DISPS(play->state.gfxCtx);
}
void Player_Draw(Actor* thisx, PlayState* play2) {
PlayState* play = play2;
Player* this = (Player*)thisx;
Vec3f pos;
Vec3s rot;
f32 scale;
// OTRTODO: This is crashing randomly, so its temporarily been disabled
// return;
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
pos.x = 2.0f;
pos.y = -130.0f;
pos.z = -150.0f;
scale = 0.046f;
} else if (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) != EQUIP_VALUE_SWORD_MASTER) {
pos.x = 25.0f;
pos.y = -228.0f;
pos.z = 60.0f;
scale = 0.056f;
} else {
pos.x = 20.0f;
pos.y = -180.0f;
pos.z = -40.0f;
scale = 0.047f;
}
rot.y = 32300;
rot.x = rot.z = 0;
OPEN_DISPS(play->state.gfxCtx);
if (!(this->stateFlags2 & PLAYER_STATE2_DISABLE_DRAW)) {
OverrideLimbDrawOpa overrideLimbDraw = Player_OverrideLimbDrawGameplayDefault;
s32 lod;
s32 pad;
if ((this->csAction != 0) || (func_8008E9C4(this) && 0) || (this->actor.projectedPos.z < 160.0f)) {
lod = 0;
} else {
lod = 1;
}
if (CVarGetInteger("gDisableLOD", 0) != 0) {
lod = 0;
}
func_80093C80(play);
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
if (this->invincibilityTimer > 0) {
this->unk_88F += CLAMP(50 - this->invincibilityTimer, 8, 40);
POLY_OPA_DISP =
Gfx_SetFog2(POLY_OPA_DISP, 255, 0, 0, 0, 0, 4000 - (s32)(Math_CosS(this->unk_88F * 256) * 2000.0f));
}
func_8002EBCC(&this->actor, play, 0);
func_8002ED80(&this->actor, play, 0);
if (this->unk_6AD != 0) {
Vec3f projectedHeadPos;
SkinMatrix_Vec3fMtxFMultXYZ(&play->viewProjectionMtxF, &this->actor.focus.pos, &projectedHeadPos);
if (projectedHeadPos.z < -4.0f) {
overrideLimbDraw = Player_OverrideLimbDrawGameplayFirstPerson;
}
} else if (this->stateFlags2 & PLAYER_STATE2_CRAWLING) {
if (this->actor.projectedPos.z < 0.0f) {
overrideLimbDraw = Player_OverrideLimbDrawGameplayCrawling;
}
}
if (this->stateFlags2 & PLAYER_STATE2_REFLECTION) {
f32 sp78 = ((u16)(play->gameplayFrames * 600) * M_PI) / 0x8000;
f32 sp74 = ((u16)(play->gameplayFrames * 1000) * M_PI) / 0x8000;
Matrix_Push();
this->actor.scale.y = -this->actor.scale.y;
Matrix_SetTranslateRotateYXZ(
this->actor.world.pos.x,
(this->actor.floorHeight + (this->actor.floorHeight - this->actor.world.pos.y)) +
(this->actor.shape.yOffset * this->actor.scale.y),
this->actor.world.pos.z, &this->actor.shape.rot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
Matrix_RotateX(sp78, MTXMODE_APPLY);
Matrix_RotateY(sp74, MTXMODE_APPLY);
Matrix_Scale(1.1f, 0.95f, 1.05f, MTXMODE_APPLY);
Matrix_RotateY(-sp74, MTXMODE_APPLY);
Matrix_RotateX(-sp78, MTXMODE_APPLY);
Player_DrawGameplay(play, this, lod, gCullFrontDList, overrideLimbDraw);
this->actor.scale.y = -this->actor.scale.y;
Matrix_Pop();
}
gSPClearGeometryMode(POLY_OPA_DISP++, G_CULL_BOTH);
gSPClearGeometryMode(POLY_XLU_DISP++, G_CULL_BOTH);
Player_DrawGameplay(play, this, lod, gCullBackDList, overrideLimbDraw);
if (this->invincibilityTimer > 0) {
POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP);
}
if (this->stateFlags2 & PLAYER_STATE2_FROZEN) {
f32 scale = (this->av1.actionVar1 >> 1) * 22.0f;
gSPSegment(POLY_XLU_DISP++, 0x08,
Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, (0 - play->gameplayFrames) % 128, 32, 32, 1,
0, (play->gameplayFrames * -2) % 128, 32, 32));
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPSetEnvColor(POLY_XLU_DISP++, 0, 50, 100, 255);
gSPDisplayList(POLY_XLU_DISP++, gEffIceFragment3DL);
}
if (this->unk_862 > 0) {
Player_DrawGetItem(play, this);
}
}
CLOSE_DISPS(play->state.gfxCtx);
}
void Player_Destroy(Actor* thisx, PlayState* play) {
Player* this = (Player*)thisx;
Effect_Delete(play, this->meleeWeaponEffectIndex);
Collider_DestroyCylinder(play, &this->cylinder);
Collider_DestroyQuad(play, &this->meleeWeaponQuads[0]);
Collider_DestroyQuad(play, &this->meleeWeaponQuads[1]);
Collider_DestroyQuad(play, &this->shieldQuad);
Magic_Reset(play);
gSaveContext.linkAge = play->linkAgeOnLoad;
ResourceMgr_UnregisterSkeleton(&this->skelAnime);
ResourceMgr_UnregisterSkeleton(&this->upperSkelAnime);
}
//first person manipulate player actor
s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) {
s32 temp1 = 0;
s16 temp2 = 0;
s16 temp3 = 0;
s8 invertXAxisMulti = ((CVarGetInteger("gInvertAimingXAxis", 0) && !CVarGetInteger("gMirroredWorld", 0)) || (!CVarGetInteger("gInvertAimingXAxis", 0) && CVarGetInteger("gMirroredWorld", 0))) ? -1 : 1;
s8 invertYAxisMulti = CVarGetInteger("gInvertAimingYAxis", 1) ? 1 : -1;
f32 xAxisMulti = CVarGetFloat("gFirstPersonCameraSensitivityX", 1.0f);
f32 yAxisMulti = CVarGetFloat("gFirstPersonCameraSensitivityY", 1.0f);
if (!func_8002DD78(this) && !func_808334B4(this) && (arg2 == 0)) { // First person without weapon
// Y Axis
if (!CVarGetInteger("gMoveWhileFirstPerson", 0)) {
temp2 += sControlInput->rel.stick_y * 240.0f * invertYAxisMulti * yAxisMulti;
}
if (CVarGetInteger("gRightStickAiming", 0) && fabsf(sControlInput->cur.right_stick_y) > 15.0f) {
temp2 += sControlInput->cur.right_stick_y * 240.0f * invertYAxisMulti * yAxisMulti;
}
if (fabsf(sControlInput->cur.gyro_x) > 0.01f) {
temp2 += (-sControlInput->cur.gyro_x) * 750.0f;
}
if (CVarGetInteger("gDisableAutoCenterViewFirstPerson", 0)) {
this->actor.focus.rot.x += temp2 * 0.1f;
this->actor.focus.rot.x = CLAMP(this->actor.focus.rot.x, -14000, 14000);
} else {
Math_SmoothStepToS(&this->actor.focus.rot.x, temp2, 14, 4000, 30);
}
// X Axis
temp2 = 0;
if (!CVarGetInteger("gMoveWhileFirstPerson", 0)) {
temp2 += sControlInput->rel.stick_x * -16.0f * invertXAxisMulti * xAxisMulti;
}
if (CVarGetInteger("gRightStickAiming", 0) && fabsf(sControlInput->cur.right_stick_x) > 15.0f) {
temp2 += sControlInput->cur.right_stick_x * -16.0f * invertXAxisMulti * xAxisMulti;
}
if (fabsf(sControlInput->cur.gyro_y) > 0.01f) {
temp2 += (sControlInput->cur.gyro_y) * 750.0f * invertXAxisMulti;
}
temp2 = CLAMP(temp2, -3000, 3000);
this->actor.focus.rot.y += temp2;
} else { // First person with weapon
// Y Axis
temp1 = (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) ? 3500 : 14000;
if (!CVarGetInteger("gMoveWhileFirstPerson", 0)) {
temp3 += ((sControlInput->rel.stick_y >= 0) ? 1 : -1) *
(s32)((1.0f - Math_CosS(sControlInput->rel.stick_y * 200)) * 1500.0f) * invertYAxisMulti * yAxisMulti;
}
if (CVarGetInteger("gRightStickAiming", 0) && fabsf(sControlInput->cur.right_stick_y) > 15.0f) {
temp3 += ((sControlInput->cur.right_stick_y >= 0) ? 1 : -1) *
(s32)((1.0f - Math_CosS(sControlInput->cur.right_stick_y * 200)) * 1500.0f) * invertYAxisMulti * yAxisMulti;
}
if (fabsf(sControlInput->cur.gyro_x) > 0.01f) {
temp3 += (-sControlInput->cur.gyro_x) * 750.0f;
}
this->actor.focus.rot.x += temp3;
this->actor.focus.rot.x = CLAMP(this->actor.focus.rot.x, -temp1, temp1);
// X Axis
temp1 = 19114;
temp2 = this->actor.focus.rot.y - this->actor.shape.rot.y;
temp3 = 0;
if (!CVarGetInteger("gMoveWhileFirstPerson", 0)) {
temp3 = ((sControlInput->rel.stick_x >= 0) ? 1 : -1) *
(s32)((1.0f - Math_CosS(sControlInput->rel.stick_x * 200)) * -1500.0f) * invertXAxisMulti * xAxisMulti;
}
if (CVarGetInteger("gRightStickAiming", 0) && fabsf(sControlInput->cur.right_stick_x) > 15.0f) {
temp3 += ((sControlInput->cur.right_stick_x >= 0) ? 1 : -1) *
(s32)((1.0f - Math_CosS(sControlInput->cur.right_stick_x * 200)) * -1500.0f) * invertXAxisMulti * xAxisMulti;
}
if (fabsf(sControlInput->cur.gyro_y) > 0.01f) {
temp3 += (sControlInput->cur.gyro_y) * 750.0f * invertXAxisMulti;
}
temp2 += temp3;
this->actor.focus.rot.y = CLAMP(temp2, -temp1, temp1) + this->actor.shape.rot.y;
}
if (CVarGetInteger("gMoveWhileFirstPerson", 0)) {
f32 movementSpeed = LINK_IS_ADULT ? 9.0f : 8.25f;
if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) {
movementSpeed *= 1.5f;
}
f32 relX = (sControlInput->rel.stick_x / 10 * -invertXAxisMulti);
f32 relY = (sControlInput->rel.stick_y / 10);
// Normalize so that diagonal movement isn't faster
f32 relMag = sqrtf((relX * relX) + (relY * relY));
if (relMag > 1.0f) {
relX /= relMag;
relY /= relMag;
}
// Determine what left and right mean based on camera angle
f32 relX2 = relX * Math_CosS(this->actor.focus.rot.y) + relY * Math_SinS(this->actor.focus.rot.y);
f32 relY2 = relY * Math_CosS(this->actor.focus.rot.y) - relX * Math_SinS(this->actor.focus.rot.y);
// Calculate distance for footstep sound
f32 distance = sqrtf((relX2 * relX2) + (relY2 * relY2)) * movementSpeed;
func_8084029C(this, distance / 4.5f);
this->actor.world.pos.x += (relX2 * movementSpeed) + this->actor.colChkInfo.displacement.x;
this->actor.world.pos.z += (relY2 * movementSpeed) + this->actor.colChkInfo.displacement.z;
}
this->unk_6AE |= 2;
return func_80836AB8(this, (play->shootingGalleryStatus != 0) || func_8002DD78(this) || func_808334B4(this)) - arg3;
}
void func_8084AEEC(Player* this, f32* arg1, f32 arg2, s16 arg3) {
f32 temp1;
f32 temp2;
// #region SOH [Enhancement]
f32 swimMod = 1.0f;
if (CVarGetInteger("gEnableWalkModify", 0) == 1) {
if (CVarGetInteger("gWalkSpeedToggle", 0) == 1) {
if (gWalkSpeedToggle1) {
swimMod *= CVarGetFloat("gSwimModifierOne", 1.0f);
} else if (gWalkSpeedToggle2) {
swimMod *= CVarGetFloat("gSwimModifierTwo", 1.0f);
}
} else {
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER1)) {
swimMod *= CVarGetFloat("gSwimModifierOne", 1.0f);
} else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER2)) {
swimMod *= CVarGetFloat("gSwimModifierTwo", 1.0f);
}
}
temp1 = this->skelAnime.curFrame - 10.0f;
temp2 = (R_RUN_SPEED_LIMIT / 100.0f) * 0.8f * swimMod;
if (*arg1 > temp2) {
*arg1 = temp2;
}
if ((0.0f < temp1) && (temp1 < 10.0f)) {
temp1 *= 6.0f;
} else {
temp1 = 0.0f;
arg2 = 0.0f;
}
Math_AsymStepToF(arg1, arg2 * 0.8f * swimMod, temp1, (fabsf(*arg1) * 0.02f) + 0.05f);
Math_ScaledStepToS(&this->yaw, arg3, 1600);
// #endregion
} else {
temp1 = this->skelAnime.curFrame - 10.0f;
temp2 = (R_RUN_SPEED_LIMIT / 100.0f) * 0.8f;
if (*arg1 > temp2) {
*arg1 = temp2;
}
if ((0.0f < temp1) && (temp1 < 10.0f)) {
temp1 *= 6.0f;
} else {
temp1 = 0.0f;
arg2 = 0.0f;
}
Math_AsymStepToF(arg1, arg2 * 0.8f, temp1, (fabsf(*arg1) * 0.02f) + 0.05f);
Math_ScaledStepToS(&this->yaw, arg3, 1600);
}
}
// #region SOH [Enhancement]
//Diving uses function func_8084AEEC to calculate changes both xz and y velocity (via func_8084DBC4)
//Provide original calculation for y velocity when swim speed mod is active
void SurfaceWithoutSwimMod(Player* this, f32* arg1, f32 arg2, s16 arg3) {
f32 temp1;
f32 temp2;
temp1 = this->skelAnime.curFrame - 10.0f;
temp2 = (R_RUN_SPEED_LIMIT / 100.0f) * 0.8f;
if (*arg1 > temp2) {
*arg1 = temp2;
}
if ((0.0f < temp1) && (temp1 < 10.0f)) {
temp1 *= 6.0f;
} else {
temp1 = 0.0f;
arg2 = 0.0f;
}
Math_AsymStepToF(arg1, arg2 * 0.8f, temp1, (fabsf(*arg1) * 0.02f) + 0.05f);
Math_ScaledStepToS(&this->yaw, arg3, 1600);
}
// #endregion
void func_8084B000(Player* this) {
f32 phi_f18;
f32 phi_f16;
f32 phi_f14;
f32 yDistToWater;
phi_f14 = -5.0f;
phi_f16 = this->ageProperties->unk_28;
if (this->actor.velocity.y < 0.0f) {
phi_f16 += 1.0f;
}
if (this->actor.yDistToWater < phi_f16) {
if (this->actor.velocity.y <= 0.0f) {
phi_f16 = 0.0f;
} else {
phi_f16 = this->actor.velocity.y * 0.5f;
}
phi_f18 = -0.1f - phi_f16;
} else {
if (!(this->stateFlags1 & PLAYER_STATE1_DEAD) && (this->currentBoots == PLAYER_BOOTS_IRON) &&
(this->actor.velocity.y >= -3.0f)) {
phi_f18 = -0.2f;
} else {
phi_f14 = 2.0f;
if (this->actor.velocity.y >= 0.0f) {
phi_f16 = 0.0f;
} else {
phi_f16 = this->actor.velocity.y * -0.3f;
}
phi_f18 = phi_f16 + 0.1f;
}
yDistToWater = this->actor.yDistToWater;
if (yDistToWater > 100.0f) {
this->stateFlags2 |= PLAYER_STATE2_UNDERWATER;
}
}
this->actor.velocity.y += phi_f18;
if (((this->actor.velocity.y - phi_f14) * phi_f18) > 0) {
this->actor.velocity.y = phi_f14;
}
this->actor.gravity = 0.0f;
}
void func_8084B158(PlayState* play, Player* this, Input* input, f32 arg3) {
f32 temp;
if ((input != NULL) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_B)) {
temp = 1.0f;
} else {
temp = 0.5f;
}
temp *= arg3;
if (temp < 1.0f) {
temp = 1.0f;
}
this->skelAnime.playSpeed = temp;
LinkAnimation_Update(play, &this->skelAnime);
}
void Player_Action_8084B1D8(Player* this, PlayState* play) {
if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) {
func_8084B000(this);
func_8084AEEC(this, &this->linearVelocity, 0, this->actor.shape.rot.y);
} else {
func_8083721C(this);
}
if ((this->unk_6AD == 2) && (func_8002DD6C(this) || func_808332E4(this))) {
Player_UpdateUpperBody(this, play);
}
u16 buttonsToCheck = BTN_A | BTN_B | BTN_R | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN;
if (CVarGetInteger("gDpadEquips", 0) != 0) {
buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
}
if ((this->csAction != 0) || (this->unk_6AD == 0) || (this->unk_6AD >= 4) || func_80833B54(this) ||
(this->unk_664 != NULL) || !func_8083AD4C(play, this) ||
(((this->unk_6AD == 2) && (CHECK_BTN_ANY(sControlInput->press.button, BTN_A | BTN_B | BTN_R) ||
func_80833B2C(this) || (!func_8002DD78(this) && !func_808334B4(this)))) ||
((this->unk_6AD == 1) && CHECK_BTN_ANY(sControlInput->press.button, buttonsToCheck)))) {
func_8083C148(this, play);
func_80078884(NA_SE_SY_CAMERA_ZOOM_UP);
} else if ((DECR(this->av2.actionVar2) == 0) || (this->unk_6AD != 2)) {
if (func_8008F128(this)) {
this->unk_6AE |= 0x43;
} else {
this->actor.shape.rot.y = func_8084ABD8(play, this, 0, 0);
}
}
this->yaw = this->actor.shape.rot.y;
}
s32 func_8084B3CC(PlayState* play, Player* this) {
if (play->shootingGalleryStatus != 0) {
func_80832564(play, this);
Player_SetupAction(play, this, Player_Action_8084FA54, 0);
if (!func_8002DD6C(this) || Player_HoldsHookshot(this)) {
s32 projectileItemToUse = ITEM_BOW;
if(CVarGetInteger("gBowSlingShotAmmoFix", 0)){
projectileItemToUse = LINK_IS_ADULT ? ITEM_BOW : ITEM_SLINGSHOT;
}
Player_UseItem(play, this, projectileItemToUse);
}
this->stateFlags1 |= PLAYER_STATE1_FIRST_PERSON;
Player_AnimPlayOnce(play, this, func_80833338(this));
Player_ZeroSpeedXZ(this);
func_8083B010(this);
return 1;
}
return 0;
}
void func_8084B498(Player* this) {
this->itemAction =
(INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_OCARINA_FAIRY) ? PLAYER_IA_OCARINA_FAIRY : PLAYER_IA_OCARINA_OF_TIME;
}
s32 func_8084B4D4(PlayState* play, Player* this) {
if (this->stateFlags3 & PLAYER_STATE3_FORCE_PULL_OCARINA) {
this->stateFlags3 &= ~PLAYER_STATE3_FORCE_PULL_OCARINA;
func_8084B498(this);
this->unk_6AD = 4;
Player_ActionChange_13(this, play);
return 1;
}
return 0;
}
void Player_Action_8084B530(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
Player_UpdateUpperBody(this, play);
if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) {
this->actor.flags &= ~ACTOR_FLAG_PLAYER_TALKED_TO;
if (!CHECK_FLAG_ALL(this->targetActor->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE)) {
this->stateFlags2 &= ~PLAYER_STATE2_SWITCH_TARGETING;
}
func_8005B1A4(Play_GetCamera(play, 0));
if (!func_8084B4D4(play, this) && !func_8084B3CC(play, this) && !Player_StartCsAction(play, this)) {
if ((this->targetActor != this->interactRangeActor) || !Player_ActionChange_2(this, play)) {
if (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) {
s32 sp24 = this->av2.actionVar2;
func_8083A360(play, this);
this->av2.actionVar2 = sp24;
} else if (func_808332B8(this)) {
func_80838F18(play, this);
} else {
func_80853080(this, play);
}
}
}
this->unk_88E = 10;
return;
}
if (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) {
Player_Action_8084CC98(this, play);
} else if (func_808332B8(this)) {
Player_Action_8084D610(this, play);
} else if (!func_8008E9C4(this) && LinkAnimation_Update(play, &this->skelAnime)) {
if (this->skelAnime.moveFlags != 0) {
func_80832DBC(this);
if ((this->targetActor->category == ACTORCAT_NPC) &&
(this->heldItemAction != PLAYER_IA_FISHING_POLE)) {
Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_normal_talk_free);
} else {
Player_AnimPlayLoop(play, this, func_80833338(this));
}
} else {
Player_AnimPlayLoopAdjusted(play, this, &gPlayerAnim_link_normal_talk_free_wait);
}
}
if (this->unk_664 != NULL) {
this->yaw = this->actor.shape.rot.y = func_8083DB98(this, 0);
}
}
void Player_Action_8084B78C(Player* this, PlayState* play) {
f32 sp34;
s16 sp32;
s32 temp;
this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_GRAB | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS | PLAYER_STATE2_GRABBING_DYNAPOLY;
func_8083F524(play, this);
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (!func_8083F9D0(play, this)) {
Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_LINEAR, play);
temp = func_8083FFB8(this, &sp34, &sp32);
if (temp > 0) {
func_8083FAB8(this, play);
} else if (temp < 0) {
func_8083FB14(this, play);
}
}
}
}
void func_8084B840(PlayState* play, Player* this, f32 arg2) {
if (this->actor.wallBgId != BGCHECK_SCENE) {
DynaPolyActor* dynaPolyActor = DynaPoly_GetActor(&play->colCtx, this->actor.wallBgId);
if (dynaPolyActor != NULL) {
func_8002DFA4(dynaPolyActor, arg2, this->actor.world.rot.y);
}
}
}
static AnimSfxEntry D_80854870[] = {
{ NA_SE_PL_SLIP, ANIMSFX_DATA(ANIMSFX_TYPE_2, 3) },
{ NA_SE_PL_SLIP, -ANIMSFX_DATA(ANIMSFX_TYPE_2, 21) },
};
void Player_Action_8084B898(Player* this, PlayState* play) {
f32 sp34;
s16 sp32;
s32 temp;
this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_GRAB | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS | PLAYER_STATE2_GRABBING_DYNAPOLY;
if (func_80832CB0(play, this, &gPlayerAnim_link_normal_pushing)) {
this->av2.actionVar2 = 1;
} else if (this->av2.actionVar2 == 0) {
if (LinkAnimation_OnFrame(&this->skelAnime, 11.0f)) {
func_80832698(this, NA_SE_VO_LI_PUSH);
}
}
Player_ProcessAnimSfxList(this, D_80854870);
func_8083F524(play, this);
if (!func_8083F9D0(play, this)) {
Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_LINEAR, play);
temp = func_8083FFB8(this, &sp34, &sp32);
if (temp < 0) {
func_8083FB14(this, play);
} else if (temp == 0) {
func_8083F72C(this, &gPlayerAnim_link_normal_push_end, play);
} else {
this->stateFlags2 |= PLAYER_STATE2_MOVING_DYNAPOLY;
}
}
if (this->stateFlags2 & PLAYER_STATE2_MOVING_DYNAPOLY) {
func_8084B840(play, this, 2.0f);
this->linearVelocity = 2.0f;
}
}
static AnimSfxEntry D_80854878[] = {
{ NA_SE_PL_SLIP, ANIMSFX_DATA(ANIMSFX_TYPE_2, 4) },
{ NA_SE_PL_SLIP, -ANIMSFX_DATA(ANIMSFX_TYPE_2, 24) },
};
static Vec3f D_80854880 = { 0.0f, 26.0f, -40.0f };
void Player_Action_8084B9E4(Player* this, PlayState* play) {
LinkAnimationHeader* anim;
f32 sp70;
s16 sp6E;
s32 temp1;
Vec3f sp5C;
f32 temp2;
CollisionPoly* sp54;
s32 sp50;
Vec3f sp44;
Vec3f sp38;
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_pulling, this->modelAnimType);
this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_GRAB | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS | PLAYER_STATE2_GRABBING_DYNAPOLY;
if (func_80832CB0(play, this, anim)) {
this->av2.actionVar2 = 1;
} else {
if (this->av2.actionVar2 == 0) {
if (LinkAnimation_OnFrame(&this->skelAnime, 11.0f)) {
func_80832698(this, NA_SE_VO_LI_PUSH);
}
} else {
Player_ProcessAnimSfxList(this, D_80854878);
}
}
func_8083F524(play, this);
if (!func_8083F9D0(play, this)) {
Player_GetMovementSpeedAndYaw(this, &sp70, &sp6E, SPEED_MODE_LINEAR, play);
temp1 = func_8083FFB8(this, &sp70, &sp6E);
if (temp1 > 0) {
func_8083FAB8(this, play);
} else if (temp1 == 0) {
func_8083F72C(this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_pull_end, this->modelAnimType), play);
} else {
this->stateFlags2 |= PLAYER_STATE2_MOVING_DYNAPOLY;
}
}
if (this->stateFlags2 & PLAYER_STATE2_MOVING_DYNAPOLY) {
temp2 = func_8083973C(play, this, &D_80854880, &sp5C) - this->actor.world.pos.y;
if (fabsf(temp2) < 20.0f) {
sp44.x = this->actor.world.pos.x;
sp44.z = this->actor.world.pos.z;
sp44.y = sp5C.y;
if (!BgCheck_EntityLineTest1(&play->colCtx, &sp44, &sp5C, &sp38, &sp54, true, false, false, true,
&sp50)) {
func_8084B840(play, this, -2.0f);
return;
}
}
this->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY;
}
}
void Player_Action_8084BBE4(Player* this, PlayState* play) {
f32 sp3C;
s16 sp3A;
LinkAnimationHeader* anim;
f32 temp;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
if (LinkAnimation_Update(play, &this->skelAnime)) {
// clang-format off
anim = (this->av1.actionVar1 > 0) ? &gPlayerAnim_link_normal_fall_wait : GET_PLAYER_ANIM(PLAYER_ANIMGROUP_jump_climb_wait, this->modelAnimType); Player_AnimPlayLoop(play, this, anim);
// clang-format on
} else if (this->av1.actionVar1 == 0) {
if (this->skelAnime.animation == &gPlayerAnim_link_normal_fall) {
temp = 11.0f;
} else {
temp = 1.0f;
}
if (LinkAnimation_OnFrame(&this->skelAnime, temp)) {
func_80832770(this, NA_SE_PL_WALK_GROUND);
if (this->skelAnime.animation == &gPlayerAnim_link_normal_fall) {
this->av1.actionVar1 = 1;
} else {
this->av1.actionVar1 = -1;
}
}
}
Math_ScaledStepToS(&this->actor.shape.rot.y, this->yaw, 0x800);
if (this->av1.actionVar1 != 0) {
Player_GetMovementSpeedAndYaw(this, &sp3C, &sp3A, SPEED_MODE_LINEAR, play);
if (this->unk_847[this->unk_846] >= 0) {
if (this->av1.actionVar1 > 0) {
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_fall_up, this->modelAnimType);
} else {
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_jump_climb_up, this->modelAnimType);
}
func_8083A9B8(this, anim, play);
return;
}
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_A) || (this->actor.shape.feetFloorFlags != 0)) {
func_80837B60(this);
if (this->av1.actionVar1 < 0) {
this->linearVelocity = -0.8f;
} else {
this->linearVelocity = 0.8f;
}
func_80837B9C(this, play);
this->stateFlags1 &= ~(PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE);
}
}
}
void Player_Action_8084BDFC(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80832E48(this, 1);
func_8083C0E8(this, play);
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, this->skelAnime.endFrame - 6.0f)) {
func_808328A0(this);
} else if (LinkAnimation_OnFrame(&this->skelAnime, this->skelAnime.endFrame - 34.0f)) {
this->stateFlags1 &= ~(PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE);
Player_PlaySfx(this, NA_SE_PL_CLIMB_CLIFF);
func_80832698(this, NA_SE_VO_LI_CLIMB_END);
}
}
void func_8084BEE4(Player* this) {
Player_PlaySfx(this, (this->av1.actionVar1 != 0) ? NA_SE_PL_WALK_WALL : NA_SE_PL_WALK_LADDER);
}
void Player_Action_8084BF1C(Player* this, PlayState* play) {
static Vec3f D_8085488C = { 0.0f, 0.0f, 26.0f };
s32 sp84;
s32 sp80;
f32 phi_f0;
f32 phi_f2;
Vec3f sp6C;
s32 sp68;
Vec3f sp5C;
f32 temp_f0;
LinkAnimationHeader* anim1;
LinkAnimationHeader* anim2;
sp84 = sControlInput->rel.stick_y;
sp80 = sControlInput->rel.stick_x;
this->fallStartHeight = this->actor.world.pos.y;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
if ((this->av1.actionVar1 != 0) && (ABS(sp84) < ABS(sp80))) {
phi_f0 = ABS(sp80) * 0.0325f;
sp84 = 0;
} else {
phi_f0 = ABS(sp84) * 0.05f;
sp80 = 0;
}
if (phi_f0 < 1.0f) {
phi_f0 = 1.0f;
} else if (phi_f0 > 3.35f) {
phi_f0 = 3.35f;
}
if (this->skelAnime.playSpeed >= 0.0f) {
phi_f2 = 1.0f;
} else {
phi_f2 = -1.0f;
}
this->skelAnime.playSpeed = phi_f2 * phi_f0 + phi_f2 * CVarGetInteger("gClimbSpeed", 0);
if (this->av2.actionVar2 >= 0) {
if ((this->actor.wallPoly != NULL) && (this->actor.wallBgId != BGCHECK_SCENE)) {
DynaPolyActor* wallPolyActor = DynaPoly_GetActor(&play->colCtx, this->actor.wallBgId);
if (wallPolyActor != NULL) {
Math_Vec3f_Diff(&wallPolyActor->actor.world.pos, &wallPolyActor->actor.prevPos, &sp6C);
Math_Vec3f_Sum(&this->actor.world.pos, &sp6C, &this->actor.world.pos);
}
}
Actor_UpdateBgCheckInfo(play, &this->actor, 26.0f, 6.0f, this->ageProperties->ceilingCheckHeight, 7);
func_8083F360(play, this, 26.0f, this->ageProperties->unk_3C, 50.0f, -20.0f);
}
if ((this->av2.actionVar2 < 0) || !func_8083FBC0(this, play)) {
if (LinkAnimation_Update(play, &this->skelAnime) != 0) {
if (this->av2.actionVar2 < 0) {
this->av2.actionVar2 = ABS(this->av2.actionVar2) & 1;
return;
}
if (sp84 != 0) {
sp68 = this->av1.actionVar1 + this->av2.actionVar2;
if (sp84 > 0) {
D_8085488C.y = this->ageProperties->unk_40;
temp_f0 = func_8083973C(play, this, &D_8085488C, &sp5C);
if (this->actor.world.pos.y < temp_f0) {
if (this->av1.actionVar1 != 0) {
this->actor.world.pos.y = temp_f0;
this->stateFlags1 &= ~PLAYER_STATE1_CLIMBING_LADDER;
func_8083A5C4(play, this, this->actor.wallPoly, this->ageProperties->unk_3C,
&gPlayerAnim_link_normal_jump_climb_up_free);
this->yaw += 0x8000;
this->actor.shape.rot.y = this->yaw;
func_8083A9B8(this, &gPlayerAnim_link_normal_jump_climb_up_free, play);
this->stateFlags1 |= PLAYER_STATE1_CLIMBING_LEDGE;
} else {
func_8083F070(this, this->ageProperties->unk_CC[this->av2.actionVar2], play);
}
} else {
this->skelAnime.prevTransl = this->ageProperties->unk_4A[sp68];
Player_AnimPlayOnce(play, this, this->ageProperties->unk_AC[sp68]);
}
} else {
if ((this->actor.world.pos.y - this->actor.floorHeight) < 15.0f) {
if (this->av1.actionVar1 != 0) {
func_8083FB7C(this, play);
} else {
if (this->av2.actionVar2 != 0) {
this->skelAnime.prevTransl = this->ageProperties->unk_44;
}
func_8083F070(this, this->ageProperties->unk_C4[this->av2.actionVar2], play);
this->av2.actionVar2 = 1;
}
} else {
sp68 ^= 1;
this->skelAnime.prevTransl = this->ageProperties->unk_62[sp68];
anim1 = this->ageProperties->unk_AC[sp68];
LinkAnimation_Change(play, &this->skelAnime, anim1, -1.0f, Animation_GetLastFrame(anim1),
0.0f, ANIMMODE_ONCE, 0.0f);
}
}
this->av2.actionVar2 ^= 1;
} else {
if ((this->av1.actionVar1 != 0) && (sp80 != 0)) {
anim2 = this->ageProperties->unk_BC[this->av2.actionVar2];
if (CVarGetInteger("gMirroredWorld", 0) ? (sp80 < 0) : (sp80 > 0)) {
this->skelAnime.prevTransl = this->ageProperties->unk_7A[this->av2.actionVar2];
Player_AnimPlayOnce(play, this, anim2);
} else {
this->skelAnime.prevTransl = this->ageProperties->unk_86[this->av2.actionVar2];
LinkAnimation_Change(play, &this->skelAnime, anim2, -1.0f, Animation_GetLastFrame(anim2),
0.0f, ANIMMODE_ONCE, 0.0f);
}
} else {
this->stateFlags2 |= PLAYER_STATE2_STATIONARY_LADDER;
}
}
return;
}
}
if (this->av2.actionVar2 < 0) {
if (((this->av2.actionVar2 == -2) &&
(LinkAnimation_OnFrame(&this->skelAnime, 14.0f) || LinkAnimation_OnFrame(&this->skelAnime, 29.0f))) ||
((this->av2.actionVar2 == -4) &&
(LinkAnimation_OnFrame(&this->skelAnime, 22.0f) || LinkAnimation_OnFrame(&this->skelAnime, 35.0f) ||
LinkAnimation_OnFrame(&this->skelAnime, 49.0f) || LinkAnimation_OnFrame(&this->skelAnime, 55.0f)))) {
func_8084BEE4(this);
}
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, (this->skelAnime.playSpeed > 0.0f) ? 20.0f : 0.0f)) {
func_8084BEE4(this);
}
}
static f32 D_80854898[] = { 10.0f, 20.0f };
static f32 D_808548A0[] = { 40.0f, 50.0f };
static AnimSfxEntry D_808548A8[] = {
{ NA_SE_PL_WALK_LADDER, ANIMSFX_DATA(ANIMSFX_TYPE_1, 10) },
{ NA_SE_PL_WALK_LADDER, ANIMSFX_DATA(ANIMSFX_TYPE_1, 20) },
{ NA_SE_PL_WALK_LADDER, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 30) },
};
void Player_Action_8084C5F8(Player* this, PlayState* play) {
s32 temp;
f32* sp38;
CollisionPoly* sp34;
s32 sp30;
Vec3f sp24;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
temp = func_808374A0(play, this, &this->skelAnime, 4.0f);
if (temp == 0) {
this->stateFlags1 &= ~PLAYER_STATE1_CLIMBING_LADDER;
return;
}
if ((temp > 0) || LinkAnimation_Update(play, &this->skelAnime)) {
func_8083C0E8(this, play);
this->stateFlags1 &= ~PLAYER_STATE1_CLIMBING_LADDER;
return;
}
sp38 = D_80854898;
if (this->av2.actionVar2 != 0) {
Player_ProcessAnimSfxList(this, D_808548A8);
sp38 = D_808548A0;
}
if (LinkAnimation_OnFrame(&this->skelAnime, sp38[0]) || LinkAnimation_OnFrame(&this->skelAnime, sp38[1])) {
sp24.x = this->actor.world.pos.x;
sp24.y = this->actor.world.pos.y + 20.0f;
sp24.z = this->actor.world.pos.z;
if (BgCheck_EntityRaycastFloor3(&play->colCtx, &sp34, &sp30, &sp24) != 0.0f) {
this->floorSfxOffset = func_80041F10(&play->colCtx, sp34, sp30);
func_808328A0(this);
}
}
}
static AnimSfxEntry D_808548B4[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 40) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 48) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 56) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 64) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 72) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 80) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 88) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 96) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 104) },
};
void Player_Action_8084C760(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (!(this->stateFlags1 & PLAYER_STATE1_LOADING)) {
if (this->skelAnime.moveFlags != 0) {
this->skelAnime.moveFlags = 0;
return;
}
// player speed in a tunnel
if (!Player_TryLeavingCrawlspace(this, play)) {
// #region SOH [Enhancement]
if (CVarGetInteger("gCrawlSpeed", 1) > 1) {
this->linearVelocity = sControlInput->rel.stick_y * 0.03f * CVarGetInteger("gCrawlSpeed", 1);
// #endregion
} else {
this->linearVelocity = sControlInput->rel.stick_y * 0.03f;
}
}
}
return;
}
Player_ProcessAnimSfxList(this, D_808548B4);
}
static AnimSfxEntry D_808548D8[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 10) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 18) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 26) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 34) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 52) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 60) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 68) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 76) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 84) },
};
void Player_Action_8084C81C(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_8083C0E8(this, play);
this->stateFlags2 &= ~PLAYER_STATE2_CRAWLING;
return;
}
Player_ProcessAnimSfxList(this, D_808548D8);
}
static Vec3f D_808548FC[] = {
{ 40.0f, 0.0f, 0.0f },
{ -40.0f, 0.0f, 0.0f },
};
static Vec3f D_80854914[] = {
{ 60.0f, 20.0f, 0.0f },
{ -60.0f, 20.0f, 0.0f },
};
static Vec3f D_8085492C[] = {
{ 60.0f, -20.0f, 0.0f },
{ -60.0f, -20.0f, 0.0f },
};
s32 func_8084C89C(PlayState* play, Player* this, s32 arg2, f32* arg3) {
EnHorse* rideActor = (EnHorse*)this->rideActor;
f32 sp50;
f32 sp4C;
Vec3f sp40;
Vec3f sp34;
CollisionPoly* sp30;
s32 sp2C;
sp50 = rideActor->actor.world.pos.y + 20.0f;
sp4C = rideActor->actor.world.pos.y - 20.0f;
*arg3 = func_8083973C(play, this, &D_808548FC[arg2], &sp40);
return (sp4C < *arg3) && (*arg3 < sp50) &&
!Player_PosVsWallLineTest(play, this, &D_80854914[arg2], &sp30, &sp2C, &sp34) &&
!Player_PosVsWallLineTest(play, this, &D_8085492C[arg2], &sp30, &sp2C, &sp34);
}
s32 func_8084C9BC(Player* this, PlayState* play) {
EnHorse* rideActor = (EnHorse*)this->rideActor;
s32 sp38;
f32 sp34;
if (this->av2.actionVar2 < 0) {
this->av2.actionVar2 = 99;
} else {
sp38 = (this->mountSide < 0) ? 0 : 1;
if (!func_8084C89C(play, this, sp38, &sp34)) {
sp38 ^= 1;
if (!func_8084C89C(play, this, sp38, &sp34)) {
return 0;
} else {
this->mountSide = -this->mountSide;
}
}
if ((play->csCtx.state == CS_STATE_IDLE) && (play->transitionMode == TRANS_MODE_OFF) &&
(EN_HORSE_CHECK_1(rideActor) || EN_HORSE_CHECK_4(rideActor))) {
this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_DOWN;
if (EN_HORSE_CHECK_1(rideActor) ||
(EN_HORSE_CHECK_4(rideActor) && CHECK_BTN_ALL(sControlInput->press.button, BTN_A))) {
rideActor->actor.child = NULL;
func_80835DAC(play, this, Player_Action_8084D3E4, 0);
this->unk_878 = sp34 - rideActor->actor.world.pos.y;
Player_AnimPlayOnce(play, this,
(this->mountSide < 0) ? &gPlayerAnim_link_uma_left_down
: &gPlayerAnim_link_uma_right_down);
return 1;
}
}
}
return 0;
}
void func_8084CBF4(Player* this, f32 arg1, f32 arg2) {
f32 temp;
f32 dir;
if ((this->unk_878 != 0.0f) && (arg2 <= this->skelAnime.curFrame)) {
if (arg1 < fabsf(this->unk_878)) {
if (this->unk_878 >= 0.0f) {
dir = 1;
} else {
dir = -1;
}
temp = dir * arg1;
} else {
temp = this->unk_878;
}
this->actor.world.pos.y += temp;
this->unk_878 -= temp;
}
}
static LinkAnimationHeader* D_80854944[] = {
&gPlayerAnim_link_uma_anim_stop,
&gPlayerAnim_link_uma_anim_stand,
&gPlayerAnim_link_uma_anim_walk,
&gPlayerAnim_link_uma_anim_slowrun,
&gPlayerAnim_link_uma_anim_fastrun,
&gPlayerAnim_link_uma_anim_jump100,
&gPlayerAnim_link_uma_anim_jump200,
NULL,
NULL,
};
static LinkAnimationHeader* D_80854968[] = {
&gPlayerAnim_link_uma_anim_walk_muti,
&gPlayerAnim_link_uma_anim_walk_muti,
&gPlayerAnim_link_uma_anim_walk_muti,
&gPlayerAnim_link_uma_anim_slowrun_muti,
&gPlayerAnim_link_uma_anim_fastrun_muti,
&gPlayerAnim_link_uma_anim_fastrun_muti,
&gPlayerAnim_link_uma_anim_fastrun_muti,
NULL,
NULL,
};
static LinkAnimationHeader* D_8085498C[] = {
&gPlayerAnim_link_uma_wait_3,
&gPlayerAnim_link_uma_wait_1,
&gPlayerAnim_link_uma_wait_2,
};
static u8 D_80854998[2][2] = {
{ 32, 58 },
{ 25, 42 },
};
static Vec3s D_8085499C = { -69, 7146, -266 };
static AnimSfxEntry D_808549A4[] = {
{ NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 48) }, { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 58) },
{ NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 68) }, { NA_SE_PL_CALM_PAT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 92) },
{ NA_SE_PL_CALM_PAT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 110) }, { NA_SE_PL_CALM_PAT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 126) },
{ NA_SE_PL_CALM_PAT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 132) }, { NA_SE_PL_CALM_PAT, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 136) },
};
void Player_Action_8084CC98(Player* this, PlayState* play) {
EnHorse* rideActor = (EnHorse*)this->rideActor;
u8* arr;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
func_8084CBF4(this, 1.0f, 10.0f);
if (this->av2.actionVar2 == 0) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
this->skelAnime.animation = &gPlayerAnim_link_uma_wait_1;
this->av2.actionVar2 = 99;
return;
}
arr = D_80854998[(this->mountSide < 0) ? 0 : 1];
if (LinkAnimation_OnFrame(&this->skelAnime, arr[0])) {
Player_PlaySfx(this, NA_SE_PL_CLIMB_CLIFF);
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, arr[1])) {
func_8002DE74(play, this);
Player_PlaySfx(this, NA_SE_PL_SIT_ON_HORSE);
return;
}
return;
}
func_8002DE74(play, this);
this->skelAnime.prevTransl = D_8085499C;
if ((rideActor->animationIdx != this->av2.actionVar2) && ((rideActor->animationIdx >= 2) || (this->av2.actionVar2 >= 2))) {
if ((this->av2.actionVar2 = rideActor->animationIdx) < 2) {
f32 rand = Rand_ZeroOne();
s32 temp = 0;
this->av2.actionVar2 = 1;
if (rand < 0.1f) {
temp = 2;
} else if (rand < 0.2f) {
temp = 1;
}
Player_AnimPlayOnce(play, this, D_8085498C[temp]);
} else {
this->skelAnime.animation = D_80854944[this->av2.actionVar2 - 2];
Animation_SetMorph(play, &this->skelAnime, 8.0f);
if (this->av2.actionVar2 < 4) {
func_80834644(play, this);
this->av1.actionVar1 = 0;
}
}
}
if (this->av2.actionVar2 == 1) {
if ((D_808535E0 != 0) || func_8083224C(play)) {
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_uma_wait_3);
} else if (LinkAnimation_Update(play, &this->skelAnime)) {
this->av2.actionVar2 = 99;
} else if (this->skelAnime.animation == &gPlayerAnim_link_uma_wait_1) {
Player_ProcessAnimSfxList(this, D_808549A4);
}
} else {
this->skelAnime.curFrame = rideActor->curFrame;
LinkAnimation_AnimateFrame(play, &this->skelAnime);
}
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.morphTable,
this->skelAnime.jointTable);
if ((play->csCtx.state != CS_STATE_IDLE) || (this->csAction != 0)) {
if (this->csAction == 7) {
this->csAction = 0;
}
this->unk_6AD = 0;
this->av1.actionVar1 = 0;
} else if ((this->av2.actionVar2 < 2) || (this->av2.actionVar2 >= 4)) {
D_808535E0 = Player_UpdateUpperBody(this, play);
if (D_808535E0 != 0) {
this->av1.actionVar1 = 0;
}
}
this->actor.world.pos.x = rideActor->actor.world.pos.x + rideActor->riderPos.x;
this->actor.world.pos.y = (rideActor->actor.world.pos.y + rideActor->riderPos.y) - 27.0f;
this->actor.world.pos.z = rideActor->actor.world.pos.z + rideActor->riderPos.z;
this->yaw = this->actor.shape.rot.y = rideActor->actor.shape.rot.y;
if ((this->csAction != 0) ||
(!func_8083224C(play) && ((rideActor->actor.speedXZ != 0.0f) || !Player_ActionChange_4(this, play)) &&
!Player_ActionChange_6(this, play))) {
if (D_808535E0 == 0) {
if (this->av1.actionVar1 != 0) {
if (LinkAnimation_Update(play, &this->upperSkelAnime)) {
rideActor->stateFlags &= ~ENHORSE_FLAG_8;
this->av1.actionVar1 = 0;
}
if (this->upperSkelAnime.animation == &gPlayerAnim_link_uma_stop_muti) {
if (LinkAnimation_OnFrame(&this->upperSkelAnime, 23.0f)) {
Player_PlaySfx(this, NA_SE_IT_LASH);
func_80832698(this, NA_SE_VO_LI_LASH);
}
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable);
} else {
if (LinkAnimation_OnFrame(&this->upperSkelAnime, 10.0f)) {
Player_PlaySfx(this, NA_SE_IT_LASH);
func_80832698(this, NA_SE_VO_LI_LASH);
}
AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap);
}
} else {
LinkAnimationHeader* anim = NULL;
if (EN_HORSE_CHECK_3(rideActor)) {
anim = &gPlayerAnim_link_uma_stop_muti;
} else if (EN_HORSE_CHECK_2(rideActor)) {
if ((this->av2.actionVar2 >= 2) && (this->av2.actionVar2 != 99)) {
anim = D_80854968[this->av2.actionVar2 - 2];
}
}
if (anim != NULL) {
LinkAnimation_PlayOnce(play, &this->upperSkelAnime, anim);
this->av1.actionVar1 = 1;
}
}
}
if (this->stateFlags1 & PLAYER_STATE1_FIRST_PERSON) {
if (!func_8083AD4C(play, this) || CHECK_BTN_ANY(sControlInput->press.button, BTN_A) ||
func_80833BCC(this)) {
this->unk_6AD = 0;
this->stateFlags1 &= ~PLAYER_STATE1_FIRST_PERSON;
} else {
this->unk_6BE = func_8084ABD8(play, this, 1, -5000) - this->actor.shape.rot.y;
this->unk_6BE += 5000;
this->unk_6B0 = -5000;
}
return;
}
if ((this->csAction != 0) || (!func_8084C9BC(this, play) && !Player_ActionChange_13(this, play))) {
if (this->unk_664 != NULL) {
if (func_8002DD78(this) != 0) {
this->unk_6BE = func_8083DB98(this, 1) - this->actor.shape.rot.y;
this->unk_6BE = CLAMP(this->unk_6BE, -0x4AAA, 0x4AAA);
this->actor.focus.rot.y = this->actor.shape.rot.y + this->unk_6BE;
this->unk_6BE += 5000;
this->unk_6AE |= 0x80;
} else {
func_8083DB98(this, 0);
}
} else {
if (func_8002DD78(this) != 0) {
this->unk_6BE = func_8084ABD8(play, this, 1, -5000) - this->actor.shape.rot.y;
this->unk_6BE += 5000;
this->unk_6B0 = -5000;
}
}
}
}
}
static AnimSfxEntry D_808549C4[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_5, 0) },
{ NA_SE_PL_GET_OFF_HORSE, ANIMSFX_DATA(ANIMSFX_TYPE_1, 10) },
{ NA_SE_PL_SLIPDOWN, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 25) },
};
void Player_Action_8084D3E4(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
func_8084CBF4(this, 1.0f, 10.0f);
if (LinkAnimation_Update(play, &this->skelAnime)) {
EnHorse* rideActor = (EnHorse*)this->rideActor;
func_8083C0E8(this, play);
this->stateFlags1 &= ~PLAYER_STATE1_ON_HORSE;
this->actor.parent = NULL;
AREG(6) = 0;
if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || (DREG(1) != 0)) {
gSaveContext.horseData.pos.x = rideActor->actor.world.pos.x;
gSaveContext.horseData.pos.y = rideActor->actor.world.pos.y;
gSaveContext.horseData.pos.z = rideActor->actor.world.pos.z;
gSaveContext.horseData.angle = rideActor->actor.shape.rot.y;
}
} else {
Camera_ChangeSetting(Play_GetCamera(play, 0), CAM_SET_NORMAL0);
if (this->mountSide < 0) {
D_808549C4[0].data = ANIMSFX_DATA(ANIMSFX_TYPE_5, 40);
} else {
D_808549C4[0].data = ANIMSFX_DATA(ANIMSFX_TYPE_5, 29);
}
Player_ProcessAnimSfxList(this, D_808549C4);
}
}
static AnimSfxEntry D_808549D0[] = {
{ NA_SE_PL_SWIM, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 0) },
};
void func_8084D530(Player* this, f32* arg1, f32 arg2, s16 arg3) {
func_8084AEEC(this, arg1, arg2, arg3);
Player_ProcessAnimSfxList(this, D_808549D0);
}
void func_8084D574(PlayState* play, Player* this, s16 arg2) {
Player_SetupAction(play, this, Player_Action_8084D84C, 0);
this->actor.shape.rot.y = this->yaw = arg2;
Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim);
}
void func_8084D5CC(PlayState* play, Player* this) {
Player_SetupAction(play, this, Player_Action_8084DAB4, 0);
Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim);
}
void Player_Action_8084D610(Player* this, PlayState* play) {
f32 sp34;
s16 sp32;
func_80832CB0(play, this, &gPlayerAnim_link_swimer_swim_wait);
func_8084B000(this);
if (!func_8083224C(play) && !Player_TryActionChangeList(play, this, sActionChangeList11, true) &&
!func_8083D12C(play, this, sControlInput)) {
if (this->unk_6AD != 1) {
this->unk_6AD = 0;
}
if (this->currentBoots == PLAYER_BOOTS_IRON) {
sp34 = 0.0f;
sp32 = this->actor.shape.rot.y;
if (this->actor.bgCheckFlags & 1) {
func_8083A098(this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_short_landing, this->modelAnimType), play);
func_808328A0(this);
}
} else {
Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_LINEAR, play);
if (sp34 != 0.0f) {
s16 temp = this->actor.shape.rot.y - sp32;
if ((ABS(temp) > 0x6000) && !Math_StepToF(&this->linearVelocity, 0.0f, 1.0f)) {
return;
}
if (func_80833C04(this)) {
func_8084D5CC(play, this);
} else {
func_8084D574(play, this, sp32);
}
}
}
func_8084AEEC(this, &this->linearVelocity, sp34, sp32);
}
}
void Player_Action_8084D7C4(Player* this, PlayState* play) {
if (!Player_ActionChange_13(this, play)) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
func_8084B158(play, this, NULL, this->linearVelocity);
func_8084B000(this);
if (DECR(this->av2.actionVar2) == 0) {
func_80838F18(play, this);
}
}
}
void Player_Action_8084D84C(Player* this, PlayState* play) {
f32 sp34;
s16 sp32;
s16 temp;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
func_8084B158(play, this, sControlInput, this->linearVelocity);
func_8084B000(this);
if (!Player_TryActionChangeList(play, this, sActionChangeList11, true) && !func_8083D12C(play, this, sControlInput)) {
Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_LINEAR, play);
temp = this->actor.shape.rot.y - sp32;
if ((sp34 == 0.0f) || (ABS(temp) > 0x6000) || (this->currentBoots == PLAYER_BOOTS_IRON)) {
func_80838F18(play, this);
} else if (func_80833C04(this)) {
func_8084D5CC(play, this);
}
func_8084D530(this, &this->linearVelocity, sp34, sp32);
}
}
s32 func_8084D980(PlayState* play, Player* this, f32* arg2, s16* arg3) {
LinkAnimationHeader* anim;
s16 temp1;
s32 temp2;
temp1 = this->yaw - *arg3;
if (ABS(temp1) > 0x6000) {
anim = &gPlayerAnim_link_swimer_swim_wait;
if (Math_StepToF(&this->linearVelocity, 0.0f, 1.0f)) {
this->yaw = *arg3;
} else {
*arg2 = 0.0f;
*arg3 = this->yaw;
}
} else {
temp2 = func_8083FD78(this, arg2, arg3, play);
if (temp2 > 0) {
anim = &gPlayerAnim_link_swimer_swim;
} else if (temp2 < 0) {
anim = &gPlayerAnim_link_swimer_back_swim;
} else if ((temp1 = this->actor.shape.rot.y - *arg3) > 0) {
anim = &gPlayerAnim_link_swimer_Rside_swim;
} else {
anim = &gPlayerAnim_link_swimer_Lside_swim;
}
}
if (anim != this->skelAnime.animation) {
Player_AnimChangeLoopSlowMorph(play, this, anim);
return 1;
}
return 0;
}
void Player_Action_8084DAB4(Player* this, PlayState* play) {
f32 sp2C;
s16 sp2A;
func_8084B158(play, this, sControlInput, this->linearVelocity);
func_8084B000(this);
if (!Player_TryActionChangeList(play, this, sActionChangeList11, true) && !func_8083D12C(play, this, sControlInput)) {
Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_LINEAR, play);
if (sp2C == 0.0f) {
func_80838F18(play, this);
} else if (!func_80833C04(this)) {
func_8084D574(play, this, sp2A);
} else {
func_8084D980(play, this, &sp2C, &sp2A);
}
func_8084D530(this, &this->linearVelocity, sp2C, sp2A);
}
}
void func_8084DBC4(PlayState* play, Player* this, f32 arg2) {
f32 sp2C;
s16 sp2A;
Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_LINEAR, play);
func_8084AEEC(this, &this->linearVelocity, sp2C * 0.5f, sp2A);
// Original implementation of func_8084AEEC (SurfaceWithoutSwimMod) to prevent velocity increases via swim mod which push Link into the air
// #region SOH [Enhancement]
if (CVarGetInteger("gEnableWalkModify", 0)) {
SurfaceWithoutSwimMod(this, &this->actor.velocity.y, arg2, this->yaw);
// #endregion
} else {
func_8084AEEC(this, &this->actor.velocity.y, arg2, this->yaw);
}
}
void Player_Action_8084DC48(Player* this, PlayState* play) {
f32 sp2C;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
this->actor.gravity = 0.0f;
Player_UpdateUpperBody(this, play);
if (!Player_ActionChange_13(this, play)) {
if (this->currentBoots == PLAYER_BOOTS_IRON) {
func_80838F18(play, this);
return;
}
if (this->av1.actionVar1 == 0) {
if (this->av2.actionVar2 == 0) {
if (LinkAnimation_Update(play, &this->skelAnime) ||
((this->skelAnime.curFrame >= 22.0f) && !CHECK_BTN_ALL(sControlInput->cur.button, BTN_A))) {
func_8083D330(play, this);
} else if (LinkAnimation_OnFrame(&this->skelAnime, 20.0f) != 0) {
this->actor.velocity.y = -2.0f;
}
func_8083721C(this);
return;
}
func_8084B158(play, this, sControlInput, this->actor.velocity.y);
this->unk_6C2 = 16000;
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_A) && !Player_ActionChange_2(this, play) &&
!(this->actor.bgCheckFlags & 1) && (this->actor.yDistToWater < D_80854784[CUR_UPG_VALUE(UPG_SCALE)])) {
func_8084DBC4(play, this, -2.0f);
} else {
this->av1.actionVar1++;
Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim_wait);
}
} else if (this->av1.actionVar1 == 1) {
LinkAnimation_Update(play, &this->skelAnime);
func_8084B000(this);
if (this->unk_6C2 < 10000) {
this->av1.actionVar1++;
this->av2.actionVar2 = this->actor.yDistToWater;
Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim);
}
} else if (!func_8083D12C(play, this, sControlInput)) {
sp2C = (this->av2.actionVar2 * 0.018f) + 4.0f;
if (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
sControlInput = NULL;
}
func_8084B158(play, this, sControlInput, fabsf(this->actor.velocity.y));
Math_ScaledStepToS(&this->unk_6C2, -10000, 800);
if (sp2C > 8.0f) {
sp2C = 8.0f;
}
func_8084DBC4(play, this, sp2C);
}
}
}
void func_8084DF6C(PlayState* play, Player* this) {
this->unk_862 = 0;
this->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD);
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
func_8005B1A4(Play_GetCamera(play, 0));
}
void func_8084DFAC(PlayState* play, Player* this) {
func_8084DF6C(play, this);
func_808322FC(this);
func_8083C0E8(this, play);
this->yaw = this->actor.shape.rot.y;
}
s32 func_8084DFF4(PlayState* play, Player* this) {
GetItemEntry giEntry;
s32 temp1;
s32 temp2;
static s32 equipItem;
static bool equipNow;
if (this->getItemId == GI_NONE && this->getItemEntry.objectId == OBJECT_INVALID) {
return 1;
}
if (this->av1.actionVar1 == 0) {
if (this->getItemEntry.objectId == OBJECT_INVALID || (this->getItemId != this->getItemEntry.getItemId)) {
giEntry = ItemTable_Retrieve(this->getItemId);
} else {
giEntry = this->getItemEntry;
}
this->av1.actionVar1 = 1;
equipItem = giEntry.itemId;
equipNow = CVarGetInteger("gAskToEquip", 0) && giEntry.modIndex == MOD_NONE &&
equipItem >= ITEM_SWORD_KOKIRI && equipItem <= ITEM_TUNIC_ZORA &&
CHECK_AGE_REQ_ITEM(equipItem);
Message_StartTextbox(play, giEntry.textId, &this->actor);
// RANDOTODO: Macro this boolean check.
if (!(giEntry.modIndex == MOD_RANDOMIZER && giEntry.itemId == RG_ICE_TRAP)) {
if (giEntry.modIndex == MOD_NONE) {
// RANDOTOD: Move this into Item_Give() or some other more central location
if (giEntry.getItemId == GI_SWORD_BGS) {
gSaveContext.bgsFlag = true;
gSaveContext.swordHealth = 8;
}
Item_Give(play, giEntry.itemId);
} else {
Randomizer_Item_Give(play, giEntry);
}
Player_SetPendingFlag(this, play);
}
// Use this if we do have a getItemEntry
if (giEntry.modIndex == MOD_NONE) {
if (IS_RANDO) {
Audio_PlayFanfare_Rando(giEntry);
} else if (((giEntry.itemId >= ITEM_RUPEE_GREEN) && (giEntry.itemId <= ITEM_RUPEE_RED)) ||
((giEntry.itemId >= ITEM_RUPEE_PURPLE) && (giEntry.itemId <= ITEM_RUPEE_GOLD)) ||
(giEntry.itemId == ITEM_HEART)) {
Audio_PlaySoundGeneral(NA_SE_SY_GET_BOXITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else {
if ((giEntry.itemId == ITEM_HEART_CONTAINER) ||
((giEntry.itemId == ITEM_HEART_PIECE_2) &&
((gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000))) {
temp1 = NA_BGM_HEART_GET | 0x900;
} else {
temp1 = temp2 =
(giEntry.itemId == ITEM_HEART_PIECE_2) ? NA_BGM_SMALL_ITEM_GET : NA_BGM_ITEM_GET | 0x900;
}
Audio_PlayFanfare(temp1);
}
} else if (giEntry.modIndex == MOD_RANDOMIZER) {
if (IS_RANDO) {
Audio_PlayFanfare_Rando(giEntry);
} else if (giEntry.itemId == RG_DOUBLE_DEFENSE || giEntry.itemId == RG_MAGIC_SINGLE ||
giEntry.itemId == RG_MAGIC_DOUBLE) {
Audio_PlayFanfare(NA_BGM_HEART_GET | 0x900);
} else {
// Just in case something weird happens with MOD_INDEX
Audio_PlayFanfare(NA_BGM_ITEM_GET | 0x900);
}
} else {
// Just in case something weird happens with modIndex.
Audio_PlayFanfare(NA_BGM_ITEM_GET | 0x900);
}
}
else if (equipNow && Message_ShouldAdvanceSilent(play) &&
Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) {
if (play->msgCtx.choiceIndex == 0) { // Equip now? Yes
if (equipItem >= ITEM_SWORD_KOKIRI && equipItem <= ITEM_SWORD_BGS) {
gSaveContext.equips.buttonItems[0] = equipItem;
Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, equipItem - ITEM_SWORD_KOKIRI + 1);
func_808328EC(this, NA_SE_IT_SWORD_PUTAWAY);
} else if (equipItem >= ITEM_SHIELD_DEKU && equipItem <= ITEM_SHIELD_MIRROR) {
Inventory_ChangeEquipment(EQUIP_TYPE_SHIELD, equipItem - ITEM_SHIELD_DEKU + 1);
func_808328EC(&this->actor, NA_SE_IT_SHIELD_REMOVE);
Player_SetEquipmentData(play, this);
} else if (equipItem == ITEM_TUNIC_GORON || equipItem == ITEM_TUNIC_ZORA) {
Inventory_ChangeEquipment(EQUIP_TYPE_TUNIC, equipItem - ITEM_TUNIC_KOKIRI + 1);
func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
Player_SetEquipmentData(play, this);
}
}
equipNow = false;
Message_CloseTextbox(play);
play->msgCtx.msgMode = MSGMODE_TEXT_DONE;
} else {
if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) {
if (this->getItemId == GI_GAUNTLETS_SILVER && !IS_RANDO) {
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0;
play->transitionTrigger = TRANS_TRIGGER_START;
gSaveContext.nextCutsceneIndex = 0xFFF1;
play->transitionType = TRANS_TYPE_SANDSTORM_END;
this->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE;
Player_TryCsAction(play, NULL, 8);
}
// Set unk_862 to 0 early to not have the game draw non-custom colored models for a split second.
// This unk is what the game normally uses to decide what item to draw when holding up an item above Link's head.
// Only do this when the item actually has a custom draw function.
if (this->getItemEntry.drawFunc != NULL) {
this->unk_862 = 0;
}
if (this->getItemEntry.itemId == RG_ICE_TRAP && this->getItemEntry.modIndex == MOD_RANDOMIZER) {
this->unk_862 = 0;
gSaveContext.pendingIceTrapCount++;
Player_SetPendingFlag(this, play);
}
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
}
}
return 0;
}
void Player_Action_8084E1EC(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (!(this->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) || func_8084DFF4(play, this)) {
func_8084DF6C(play, this);
func_80838F18(play, this);
func_80832340(play, this);
}
} else {
if ((this->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) && LinkAnimation_OnFrame(&this->skelAnime, 10.0f)) {
func_808332F4(this, play);
func_80832340(play, this);
func_80835EA4(play, 8);
} else if (LinkAnimation_OnFrame(&this->skelAnime, 5.0f)) {
func_80832698(this, NA_SE_VO_LI_BREATH_DRINK);
}
}
func_8084B000(this);
func_8084AEEC(this, &this->linearVelocity, 0.0f, this->actor.shape.rot.y);
}
void Player_Action_8084E30C(Player* this, PlayState* play) {
func_8084B000(this);
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80838F18(play, this);
}
func_8084AEEC(this, &this->linearVelocity, 0.0f, this->actor.shape.rot.y);
}
void Player_Action_8084E368(Player* this, PlayState* play) {
func_8084B000(this);
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80843AE8(play, this);
}
func_8084AEEC(this, &this->linearVelocity, 0.0f, this->actor.shape.rot.y);
}
static s16 sWarpSongEntrances[] = {
ENTR_SACRED_FOREST_MEADOW_2,
ENTR_DEATH_MOUNTAIN_CRATER_4,
ENTR_LAKE_HYLIA_8,
ENTR_DESERT_COLOSSUS_5,
ENTR_GRAVEYARD_7,
ENTR_TEMPLE_OF_TIME_7,
};
void Player_Action_8084E3C4(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimPlayLoopAdjusted(play, this, &gPlayerAnim_link_normal_okarina_swing);
this->av2.actionVar2 = 1;
if (this->stateFlags2 & (PLAYER_STATE2_NEAR_OCARINA_ACTOR | PLAYER_STATE2_PLAY_FOR_ACTOR)) {
this->stateFlags2 |= PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR;
} else {
func_8010BD58(play, OCARINA_ACTION_FREE_PLAY);
}
return;
}
if (this->av2.actionVar2 == 0) {
return;
}
if (play->msgCtx.ocarinaMode == OCARINA_MODE_04) {
func_8005B1A4(Play_GetCamera(play, 0));
if ((this->targetActor != NULL) && (this->targetActor == this->unk_6A8)) {
Player_StartTalking(play, this->targetActor);
} else if (this->naviTextId < 0) {
this->targetActor = this->naviActor;
this->naviActor->textId = -this->naviTextId;
Player_StartTalking(play, this->targetActor);
} else if (!Player_ActionChange_13(this, play)) {
func_8083A098(this, &gPlayerAnim_link_normal_okarina_end, play);
}
this->stateFlags2 &= ~(PLAYER_STATE2_NEAR_OCARINA_ACTOR | PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR | PLAYER_STATE2_PLAY_FOR_ACTOR);
this->unk_6A8 = NULL;
} else if (play->msgCtx.ocarinaMode == OCARINA_MODE_02) {
gSaveContext.respawn[RESPAWN_MODE_RETURN].entranceIndex = sWarpSongEntrances[play->msgCtx.lastPlayedSong];
gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams = 0x5FF;
gSaveContext.respawn[RESPAWN_MODE_RETURN].data = play->msgCtx.lastPlayedSong;
this->csAction = 0;
this->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE;
Player_TryCsAction(play, NULL, 8);
play->mainCamera.unk_14C &= ~8;
this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
this->stateFlags2 |= PLAYER_STATE2_OCARINA_PLAYING;
if (Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_KANKYO, 0.0f, 0.0f, 0.0f, 0, 0, 0, 0xF, true) == NULL) {
Environment_WarpSongLeave(play);
}
gSaveContext.seqId = (u8)NA_BGM_DISABLED;
gSaveContext.natureAmbienceId = NATURE_ID_DISABLED;
}
}
void Player_Action_8084E604(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_8083A098(this, &gPlayerAnim_link_normal_light_bom_end, play);
} else if (LinkAnimation_OnFrame(&this->skelAnime, 3.0f)) {
Inventory_ChangeAmmo(ITEM_NUT, -1);
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ARROW, this->bodyPartsPos[PLAYER_BODYPART_R_HAND].x,
this->bodyPartsPos[PLAYER_BODYPART_R_HAND].y, this->bodyPartsPos[PLAYER_BODYPART_R_HAND].z, 4000,
this->actor.shape.rot.y, 0, ARROW_NUT, true);
func_80832698(this, NA_SE_VO_LI_SWORD_N);
}
func_8083721C(this);
}
static AnimSfxEntry D_808549E0[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_7, 87) },
{ NA_SE_VO_LI_CLIMB_END, ANIMSFX_DATA(ANIMSFX_TYPE_4, 87) },
{ NA_SE_VO_LI_AUTO_JUMP, ANIMSFX_DATA(ANIMSFX_TYPE_4, 69) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_5, 123) },
};
void Player_Action_8084E6D4(Player* this, PlayState* play) {
s32 cond;
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->av2.actionVar2 != 0) {
if (this->av2.actionVar2 >= 2) {
this->av2.actionVar2--;
}
if (func_8084DFF4(play, this) && (this->av2.actionVar2 == 1)) {
cond = ((this->targetActor != NULL) && (this->exchangeItemId < 0)) ||
(this->stateFlags3 & PLAYER_STATE3_FORCE_PULL_OCARINA);
if (cond || (gSaveContext.healthAccumulator == 0)) {
if (cond) {
func_8084DF6C(play, this);
this->exchangeItemId = EXCH_ITEM_NONE;
if (func_8084B4D4(play, this) == 0) {
Player_StartTalking(play, this->targetActor);
}
} else {
func_8084DFAC(play, this);
}
}
}
} else {
func_80832DBC(this);
if ((this->getItemId == GI_ICE_TRAP && !IS_RANDO) ||
(IS_RANDO && (this->getItemId == RG_ICE_TRAP || this->getItemEntry.getItemId == RG_ICE_TRAP))) {
this->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD);
if ((this->getItemId != GI_ICE_TRAP && !IS_RANDO) ||
(IS_RANDO && (this->getItemId != RG_ICE_TRAP || this->getItemEntry.getItemId != RG_ICE_TRAP))) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x,
this->actor.world.pos.y + 100.0f, this->actor.world.pos.z, 0, 0, 0, 0, true);
func_8083C0E8(this, play);
} else if (IS_RANDO) {
gSaveContext.pendingIceTrapCount++;
Player_SetPendingFlag(this, play);
func_8083C0E8(this, play);
} else {
this->actor.colChkInfo.damage = 0;
func_80837C0C(play, this, 3, 0.0f, 0.0f, 0, 20);
}
return;
}
if (this->skelAnime.animation == &gPlayerAnim_link_normal_box_kick) {
Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_demo_get_itemB);
} else {
Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_demo_get_itemA);
}
this->av2.actionVar2 = 2;
func_80835EA4(play, 9);
}
} else {
if (this->av2.actionVar2 == 0) {
if (!LINK_IS_ADULT) {
Player_ProcessAnimSfxList(this, D_808549E0);
}
return;
}
if (this->skelAnime.animation == &gPlayerAnim_link_demo_get_itemB) {
Math_ScaledStepToS(&this->actor.shape.rot.y, Camera_GetCamDirYaw(GET_ACTIVE_CAM(play)) + 0x8000, 4000);
}
if (LinkAnimation_OnFrame(&this->skelAnime, 21.0f)) {
func_808332F4(this, play);
}
}
}
static AnimSfxEntry D_808549F0[] = {
{ NA_SE_IT_MASTER_SWORD_SWING, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 60) },
};
void func_8084E988(Player* this) {
Player_ProcessAnimSfxList(this, D_808549F0);
}
static AnimSfxEntry D_808549F4[] = {
{ NA_SE_VO_LI_AUTO_JUMP, ANIMSFX_DATA(ANIMSFX_TYPE_4, 5) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_5, 15) },
};
void Player_Action_8084E9AC(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->av1.actionVar1 == 0) {
if (DECR(this->av2.actionVar2) == 0) {
this->av1.actionVar1 = 1;
this->skelAnime.endFrame = this->skelAnime.animLength - 1.0f;
}
} else {
func_8083C0E8(this, play);
}
} else {
if (LINK_IS_ADULT && LinkAnimation_OnFrame(&this->skelAnime, 158.0f)) {
func_80832698(this, NA_SE_VO_LI_SWORD_N);
return;
}
if (!LINK_IS_ADULT) {
Player_ProcessAnimSfxList(this, D_808549F4);
} else {
func_8084E988(this);
}
}
}
static u8 D_808549FC[] = {
0x01, 0x03, 0x02, 0x04, 0x04,
};
void Player_Action_8084EAC0(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->av2.actionVar2 == 0) {
if (this->itemAction == PLAYER_IA_BOTTLE_POE) {
s32 rand = Rand_S16Offset(-1, 3);
if (rand == 0) {
rand = 3;
}
if ((rand < 0) && (gSaveContext.health <= 0x10)) {
rand = 3;
}
if (rand < 0) {
Health_ChangeBy(play, -0x10);
} else {
gSaveContext.healthAccumulator = rand * 0x10;
}
} else {
s32 sp28 = D_808549FC[this->itemAction - PLAYER_IA_BOTTLE_POTION_RED];
if (CVarGetInteger("gRedPotionEffect", 0) && this->itemAction == PLAYER_IA_BOTTLE_POTION_RED) {
if (CVarGetInteger("gRedPercentRestore", 0)) {
gSaveContext.healthAccumulator =
(gSaveContext.healthCapacity * CVarGetInteger("gRedPotionHealth", 100) / 100 + 15) / 16 * 16;
} else {
gSaveContext.healthAccumulator = CVarGetInteger("gRedPotionHealth", 20) * 16;
}
} else if (CVarGetInteger("gBluePotionEffects", 0) &&
this->itemAction == PLAYER_IA_BOTTLE_POTION_BLUE) {
if (CVarGetInteger("gBlueHealthPercentRestore", 0)) {
gSaveContext.healthAccumulator =
(gSaveContext.healthCapacity * CVarGetInteger("gBluePotionHealth", 100) / 100 + 15) / 16 * 16;
} else {
gSaveContext.healthAccumulator = CVarGetInteger("gBluePotionHealth", 20) * 16;
}
if (CVarGetInteger("gBlueManaPercentRestore", 0)) {
if (gSaveContext.magicState != MAGIC_STATE_ADD) {
Magic_Fill(play);
}
Magic_RequestChange(play,
(gSaveContext.magicLevel * 48 * CVarGetInteger("gBluePotionMana", 100) / 100 + 15) /
16 * 16,
MAGIC_ADD);
} else {
if (gSaveContext.magicState != MAGIC_STATE_ADD) {
Magic_Fill(play);
}
Magic_RequestChange(play, CVarGetInteger("gBluePotionMana", 100), MAGIC_ADD);
;
}
} else if (CVarGetInteger("gGreenPotionEffect", 0) &&
this->itemAction == PLAYER_IA_BOTTLE_POTION_GREEN) {
if (CVarGetInteger("gGreenPercentRestore", 0)) {
if (gSaveContext.magicState != MAGIC_STATE_ADD) {
Magic_Fill(play);
}
Magic_RequestChange(play,
(gSaveContext.magicLevel * 48 * CVarGetInteger("gGreenPotionMana", 100) / 100 + 15) /
16 * 16,
MAGIC_ADD);
} else {
if (gSaveContext.magicState != MAGIC_STATE_ADD) {
Magic_Fill(play);
}
Magic_RequestChange(play, CVarGetInteger("gGreenPotionMana", 100), MAGIC_ADD);
;
}
} else if (CVarGetInteger("gMilkEffect", 0) && (this->itemAction == PLAYER_IA_BOTTLE_MILK_FULL ||
this->itemAction == PLAYER_IA_BOTTLE_MILK_HALF)) {
if (CVarGetInteger("gMilkPercentRestore", 0)) {
gSaveContext.healthAccumulator =
(gSaveContext.healthCapacity * CVarGetInteger("gMilkHealth", 100) / 100 + 15) / 16 * 16;
} else {
gSaveContext.healthAccumulator = CVarGetInteger("gMilkHealth", 5) * 16;
}
if (CVarGetInteger("gSeparateHalfMilkEffect", 0) &&
this->itemAction == PLAYER_IA_BOTTLE_MILK_HALF) {
if (CVarGetInteger("gHalfMilkPercentRestore", 0)) {
gSaveContext.healthAccumulator =
(gSaveContext.healthCapacity * CVarGetInteger("gHalfMilkHealth", 100) / 100 + 15) / 16 *
16;
} else {
gSaveContext.healthAccumulator = CVarGetInteger("gHalfMilkHealth", 5) * 16;
}
}
} else {
if (sp28 & 1) {
gSaveContext.healthAccumulator = 0x140;
}
if (sp28 & 2) {
Magic_Fill(play);
}
if (sp28 & 4) {
gSaveContext.healthAccumulator = 0x50;
}
}
}
Player_AnimPlayLoopAdjusted(play, this, &gPlayerAnim_link_bottle_drink_demo_wait);
this->av2.actionVar2 = 1;
return;
}
func_8083C0E8(this, play);
func_8005B1A4(Play_GetCamera(play, 0));
} else if (this->av2.actionVar2 == 1) {
if ((gSaveContext.healthAccumulator == 0) && (gSaveContext.magicState != MAGIC_STATE_FILL)) {
Player_AnimChangeOnceMorphAdjusted(play, this, &gPlayerAnim_link_bottle_drink_demo_end);
this->av2.actionVar2 = 2;
Player_UpdateBottleHeld(play, this, ITEM_BOTTLE, PLAYER_IA_BOTTLE);
}
func_80832698(this, NA_SE_VO_LI_DRINK - SFX_FLAG);
} else if ((this->av2.actionVar2 == 2) && LinkAnimation_OnFrame(&this->skelAnime, 29.0f)) {
func_80832698(this, NA_SE_VO_LI_BREATH_DRINK);
}
}
static BottleCatchInfo D_80854A04[] = {
{ ACTOR_EN_ELF, ITEM_FAIRY, 0x2A, 0x46 },
{ ACTOR_EN_FISH, ITEM_FISH, 0x1F, 0x47 },
{ ACTOR_EN_ICE_HONO, ITEM_BLUE_FIRE, 0x20, 0x5D },
{ ACTOR_EN_INSECT, ITEM_BUG, 0x21, 0x7A },
};
void Player_Action_8084ECA4(Player* this, PlayState* play) {
struct_80854554* sp24;
BottleCatchInfo* catchInfo;
s32 temp;
s32 i;
sp24 = &D_80854554[this->av2.actionVar2];
func_8083721C(this);
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->av1.actionVar1 != 0) {
if (this->av2.actionVar2 == 0) {
if (CVarGetInteger("gFastDrops", 0)) {
this->av1.actionVar1 = 0;
} else {
Message_StartTextbox(play, D_80854A04[this->av1.actionVar1 - 1].textId, &this->actor);
}
Audio_PlayFanfare(NA_BGM_ITEM_GET | 0x900);
this->av2.actionVar2 = 1;
} else if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) {
this->av1.actionVar1 = 0;
func_8005B1A4(Play_GetCamera(play, 0));
}
} else {
func_8083C0E8(this, play);
}
} else {
if (this->av1.actionVar1 == 0) {
temp = this->skelAnime.curFrame - sp24->unk_08;
if (temp >= 0) {
if (sp24->unk_09 >= temp) {
if (this->av2.actionVar2 != 0) {
if (temp == 0) {
Player_PlaySfx(this, NA_SE_IT_SCOOP_UP_WATER);
}
}
if (this->interactRangeActor != NULL) {
catchInfo = &D_80854A04[0];
for (i = 0; i < 4; i++, catchInfo++) {
if (this->interactRangeActor->id == catchInfo->actorId) {
break;
}
}
if (i < 4) {
this->av1.actionVar1 = i + 1;
this->av2.actionVar2 = 0;
this->interactRangeActor->parent = &this->actor;
Player_UpdateBottleHeld(play, this, catchInfo->itemId, ABS(catchInfo->itemAction));
if (!CVarGetInteger("gFastDrops", 0)) {
this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
Player_AnimPlayOnceAdjusted(play, this, sp24->unk_04);
func_80835EA4(play, 4);
}
}
}
}
}
}
}
//! @bug If the animation is changed at any point above (such as by func_8083C0E8() or
//! Player_AnimPlayOnceAdjusted()), it will change the curFrame to 0. This causes this flag to be set for one frame,
//! at a time when it does not look like Player is swinging the bottle.
if (this->skelAnime.curFrame <= 7.0f) {
this->stateFlags1 |= PLAYER_STATE1_SWINGING_BOTTLE;
}
}
static Vec3f D_80854A1C = { 0.0f, 0.0f, 5.0f };
void Player_Action_8084EED8(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_8083C0E8(this, play);
func_8005B1A4(Play_GetCamera(play, 0));
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, 37.0f)) {
Player_SpawnFairy(play, this, &this->leftHandPos, &D_80854A1C, FAIRY_REVIVE_BOTTLE);
Player_UpdateBottleHeld(play, this, ITEM_BOTTLE, PLAYER_IA_BOTTLE);
Player_PlaySfx(this, NA_SE_EV_BOTTLE_CAP_OPEN);
Player_PlaySfx(this, NA_SE_EV_FIATY_HEAL - SFX_FLAG);
} else if (LinkAnimation_OnFrame(&this->skelAnime, 47.0f)) {
if (CVarGetInteger("gFairyEffect", 0)) {
if (CVarGetInteger("gFairyPercentRestore", 0)) {
gSaveContext.healthAccumulator =
(gSaveContext.healthCapacity * CVarGetInteger("gFairyHealth", 100) / 100 + 15) / 16 * 16;
} else {
gSaveContext.healthAccumulator = CVarGetInteger("gFairyHealth", 8) * 16;
}
} else {
gSaveContext.healthAccumulator = 0x140;
}
}
}
static BottleDropInfo D_80854A28[] = {
{ ACTOR_EN_FISH, FISH_DROPPED },
{ ACTOR_EN_ICE_HONO, 0 },
{ ACTOR_EN_INSECT, 2 },
};
static AnimSfxEntry D_80854A34[] = {
{ NA_SE_VO_LI_AUTO_JUMP, ANIMSFX_DATA(ANIMSFX_TYPE_4, 38) },
{ NA_SE_EV_BOTTLE_CAP_OPEN, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 40) },
};
void Player_Action_8084EFC0(Player* this, PlayState* play) {
func_8083721C(this);
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_8083C0E8(this, play);
func_8005B1A4(Play_GetCamera(play, 0));
return;
}
if (LinkAnimation_OnFrame(&this->skelAnime, 76.0f)) {
BottleDropInfo* dropInfo = &D_80854A28[this->itemAction - PLAYER_IA_BOTTLE_FISH];
Actor_Spawn(&play->actorCtx, play, dropInfo->actorId,
(Math_SinS(this->actor.shape.rot.y) * 5.0f) + this->leftHandPos.x, this->leftHandPos.y,
(Math_CosS(this->actor.shape.rot.y) * 5.0f) + this->leftHandPos.z, 0x4000, this->actor.shape.rot.y,
0, dropInfo->actorParams, true);
Player_UpdateBottleHeld(play, this, ITEM_BOTTLE, PLAYER_IA_BOTTLE);
return;
}
Player_ProcessAnimSfxList(this, D_80854A34);
}
static AnimSfxEntry D_80854A3C[] = {
{ NA_SE_PL_PUT_OUT_ITEM, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 30) },
};
void Player_Action_8084F104(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->av2.actionVar2 < 0) {
func_8083C0E8(this, play);
} else if (this->exchangeItemId == EXCH_ITEM_NONE) {
Actor* targetActor = this->targetActor;
this->unk_862 = 0;
if (targetActor->textId != 0xFFFF) {
this->actor.flags |= ACTOR_FLAG_PLAYER_TALKED_TO;
}
Player_StartTalking(play, targetActor);
} else {
GetItemEntry giEntry = ItemTable_Retrieve(D_80854528[this->exchangeItemId - 1]);
if (this->itemAction >= PLAYER_IA_ZELDAS_LETTER) {
if (giEntry.gi >= 0) {
this->unk_862 = giEntry.gi;
} else {
this->unk_862 = -giEntry.gi;
}
}
if (this->av2.actionVar2 == 0) {
Message_StartTextbox(play, this->actor.textId, &this->actor);
if ((this->itemAction == PLAYER_IA_CHICKEN) || (this->itemAction == PLAYER_IA_POCKET_CUCCO)) {
Player_PlaySfx(this, NA_SE_EV_CHICKEN_CRY_M);
}
this->av2.actionVar2 = 1;
} else if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) {
this->actor.flags &= ~ACTOR_FLAG_PLAYER_TALKED_TO;
this->unk_862 = 0;
if (this->av1.actionVar1 == 1) {
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_bottle_read_end);
this->av2.actionVar2 = -1;
} else {
func_8083C0E8(this, play);
}
func_8005B1A4(Play_GetCamera(play, 0));
}
}
} else if (this->av2.actionVar2 >= 0) {
Player_ProcessAnimSfxList(this, D_80854A3C);
}
if ((this->av1.actionVar1 == 0) && (this->unk_664 != NULL)) {
this->yaw = this->actor.shape.rot.y = func_8083DB98(this, 0);
}
}
void func_8084F308(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_normal_re_dead_attack_wait);
}
if (func_80832594(this, 0, 100)) {
func_80839F90(this, play);
this->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY;
}
}
void Player_Action_8084F390(Player* this, PlayState* play) {
CollisionPoly* floorPoly;
f32 sp50;
f32 sp4C;
f32 sp48;
s16 sp46;
s16 sp44;
Vec3f sp38;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;
LinkAnimation_Update(play, &this->skelAnime);
func_8084269C(play, this);
func_800F4138(&this->actor.projectedPos, NA_SE_PL_SLIP_LEVEL - SFX_FLAG, this->actor.speedXZ);
if (Player_ActionChange_13(this, play) == 0) {
floorPoly = this->actor.floorPoly;
if (floorPoly == NULL) {
func_80837B9C(this, play);
return;
}
Player_GetSlopeDirection(floorPoly, &sp38, &sp46);
sp44 = sp46;
if (this->av1.actionVar1 != 0) {
sp44 = sp46 + 0x8000;
}
if (this->linearVelocity < 0) {
sp46 += 0x8000;
}
sp50 = (1.0f - sp38.y) * 40.0f;
sp50 = CLAMP(sp50, 0, 10.0f);
sp4C = (sp50 * sp50) * 0.015f;
sp48 = sp38.y * 0.01f;
if (SurfaceType_GetSlope(&play->colCtx, floorPoly, this->actor.floorBgId) != 1) {
sp50 = 0;
sp48 = sp38.y * 10.0f;
}
if (sp4C < 1.0f) {
sp4C = 1.0f;
}
if (Math_AsymStepToF(&this->linearVelocity, sp50, sp4C, sp48) && (sp50 == 0)) {
LinkAnimationHeader* anim;
if (this->av1.actionVar1 == 0) {
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_down_slope_slip_end, this->modelAnimType);
} else {
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_up_slope_slip_end, this->modelAnimType);
}
func_8083A098(this, anim, play);
}
Math_SmoothStepToS(&this->yaw, sp46, 10, 4000, 800);
Math_ScaledStepToS(&this->actor.shape.rot.y, sp44, 2000);
}
}
void Player_Action_8084F608(Player* this, PlayState* play) {
if ((DECR(this->av2.actionVar2) == 0) && Player_StartCsAction(play, this)) {
func_80852280(play, this, NULL);
Player_SetupAction(play, this, Player_Action_CsAction, 0);
Player_Action_CsAction(this, play);
}
}
void Player_Action_8084F698(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_8084F608, 0);
this->av2.actionVar2 = 40;
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_KANKYO, 0.0f, 0.0f, 0.0f, 0, 0, 0, 0x10, true);
}
void Player_Action_8084F710(Player* this, PlayState* play) {
s32 pad;
if ((this->av1.actionVar1 != 0) && (play->csCtx.frames < 0x131)) {
this->actor.gravity = 0.0f;
this->actor.velocity.y = 0.0f;
} else if (sYDistToFloor < 150.0f) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->av2.actionVar2 == 0) {
if (this->actor.bgCheckFlags & 1) {
this->skelAnime.endFrame = this->skelAnime.animLength - 1.0f;
func_808328A0(this);
this->av2.actionVar2 = 1;
}
} else {
if ((play->sceneNum == SCENE_KOKIRI_FOREST) && Player_StartCsAction(play, this)) {
return;
}
func_80853080(this, play);
}
}
Math_SmoothStepToF(&this->actor.velocity.y, 2.0f, 0.3f, 8.0f, 0.5f);
}
if ((play->sceneNum == SCENE_CHAMBER_OF_THE_SAGES) && Player_StartCsAction(play, this)) {
return;
}
if ((play->csCtx.state != CS_STATE_IDLE) && (play->csCtx.linkAction != NULL)) {
f32 sp28 = this->actor.world.pos.y;
func_808529D0(play, this, play->csCtx.linkAction);
this->actor.world.pos.y = sp28;
}
}
void Player_Action_8084F88C(Player* this, PlayState* play) {
LinkAnimation_Update(play, &this->skelAnime);
if ((this->av2.actionVar2++ > 8) && (play->transitionTrigger == TRANS_TRIGGER_OFF)) {
if (this->av1.actionVar1 != 0) {
if (play->sceneNum == SCENE_ICE_CAVERN) {
Play_TriggerRespawn(play);
play->nextEntranceIndex = ENTR_ICE_CAVERN_0;
} else if (this->av1.actionVar1 < 0) {
Play_TriggerRespawn(play);
// In ER, handle DMT and other special void outs to respawn from last entrance from grotto
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) {
Grotto_ForceRegularVoidOut();
}
} else {
Play_TriggerVoidOut(play);
}
play->transitionType = TRANS_TYPE_FADE_BLACK_FAST;
func_80078884(NA_SE_OC_ABYSS);
} else {
play->transitionType = TRANS_TYPE_FADE_BLACK;
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE;
gSaveContext.seqId = (u8)NA_BGM_DISABLED;
gSaveContext.natureAmbienceId = 0xFF;
}
play->transitionTrigger = TRANS_TRIGGER_START;
}
}
void Player_Action_8084F9A0(Player* this, PlayState* play) {
Player_ActionChange_1(this, play);
}
void Player_Action_8084F9C0(Player* this, PlayState* play) {
this->actor.gravity = -1.0f;
LinkAnimation_Update(play, &this->skelAnime);
if (this->actor.velocity.y < 0.0f) {
func_80837B9C(this, play);
} else if (this->actor.velocity.y < 6.0f) {
Math_StepToF(&this->linearVelocity, 3.0f, 0.5f);
}
}
void Player_Action_8084FA54(Player* this, PlayState* play) {
this->unk_6AD = 2;
func_8083AD4C(play, this);
LinkAnimation_Update(play, &this->skelAnime);
Player_UpdateUpperBody(this, play);
this->unk_6BE = func_8084ABD8(play, this, 1, 0) - this->actor.shape.rot.y;
this->unk_6AE |= 0x80;
if (play->shootingGalleryStatus < 0) {
play->shootingGalleryStatus++;
if (play->shootingGalleryStatus == 0) {
func_8083C148(this, play);
}
}
}
void Player_Action_8084FB10(Player* this, PlayState* play) {
if (this->av1.actionVar1 >= 0) {
if (this->av1.actionVar1 < 6) {
this->av1.actionVar1++;
}
if (func_80832594(this, 1, 100)) {
this->av1.actionVar1 = -1;
EffectSsIcePiece_SpawnBurst(play, &this->actor.world.pos, this->actor.scale.x);
Player_PlaySfx(this, NA_SE_PL_ICE_BROKEN);
} else {
this->stateFlags2 |= PLAYER_STATE2_FROZEN;
}
if ((play->gameplayFrames % 4) == 0) {
Player_InflictDamage(play, -1);
}
} else {
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80839F90(this, play);
func_80837AFC(this, -20);
}
}
}
void Player_Action_8084FBF4(Player* this, PlayState* play) {
LinkAnimation_Update(play, &this->skelAnime);
func_808382BC(this);
if (((this->av2.actionVar2 % 25) != 0) || func_80837B18(play, this, -1)) {
if (DECR(this->av2.actionVar2) == 0) {
func_80839F90(this, play);
}
}
this->bodyShockTimer = 40;
func_8002F8F0(&this->actor, NA_SE_VO_LI_TAKEN_AWAY - SFX_FLAG + this->ageProperties->unk_92);
}
s32 func_8084FCAC(Player* this, PlayState* play) {
sControlInput = &play->state.input[0];
if (CVarGetInteger("gDebugEnabled", 0) &&
((CHECK_BTN_ALL(sControlInput->cur.button, BTN_A | BTN_L | BTN_R) &&
CHECK_BTN_ALL(sControlInput->press.button, BTN_B)) ||
(CHECK_BTN_ALL(sControlInput->cur.button, BTN_L) && CHECK_BTN_ALL(sControlInput->press.button, BTN_DRIGHT)))) {
D_808535D0 ^= 1;
if (D_808535D0) {
Camera_ChangeMode(Play_GetCamera(play, 0), CAM_MODE_BOWARROWZ);
}
}
if (D_808535D0) {
f32 speed;
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_R)) {
speed = 100.0f;
} else {
speed = 20.0f;
}
func_8006375C(3, 2, "DEBUG MODE");
if (!CHECK_BTN_ALL(sControlInput->cur.button, BTN_L)) {
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_B)) {
this->actor.world.pos.y += speed;
} else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_A)) {
this->actor.world.pos.y -= speed;
}
if (CHECK_BTN_ANY(sControlInput->cur.button, BTN_DUP | BTN_DLEFT | BTN_DDOWN | BTN_DRIGHT)) {
s16 angle;
s16 temp;
angle = temp = Camera_GetInputDirYaw(GET_ACTIVE_CAM(play));
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_DDOWN)) {
angle = temp + 0x8000;
} else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_DLEFT)) {
angle = temp + (0x4000 * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1));
} else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_DRIGHT)) {
angle = temp - (0x4000 * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1));
}
this->actor.world.pos.x += speed * Math_SinS(angle);
this->actor.world.pos.z += speed * Math_CosS(angle);
}
}
Player_ZeroSpeedXZ(this);
this->actor.gravity = 0.0f;
this->actor.velocity.z = 0.0f;
this->actor.velocity.y = 0.0f;
this->actor.velocity.x = 0.0f;
if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_L) && CHECK_BTN_ALL(sControlInput->press.button, BTN_DLEFT)) {
Flags_SetTempClear(play, play->roomCtx.curRoom.num);
}
Math_Vec3f_Copy(&this->actor.home.pos, &this->actor.world.pos);
return 0;
}
return 1;
}
void func_8084FF7C(Player* this) {
this->unk_858 += this->unk_85C;
this->unk_85C -= this->unk_858 * 5.0f;
this->unk_85C *= 0.3f;
if (ABS(this->unk_85C) < 0.00001f) {
this->unk_85C = 0.0f;
if (ABS(this->unk_858) < 0.00001f) {
this->unk_858 = 0.0f;
}
}
}
/**
* Updates the Bunny Hood's floppy ears' rotation and velocity.
*/
void Player_UpdateBunnyEars(Player* this) {
Vec3s force;
s16 angle;
// Damping: decay by 1/8 the previous value each frame
sBunnyEarKinematics.angVel.x -= sBunnyEarKinematics.angVel.x >> 3;
sBunnyEarKinematics.angVel.y -= sBunnyEarKinematics.angVel.y >> 3;
// Elastic restorative force
sBunnyEarKinematics.angVel.x += -sBunnyEarKinematics.rot.x >> 2;
sBunnyEarKinematics.angVel.y += -sBunnyEarKinematics.rot.y >> 2;
// Forcing from motion relative to shape frame
angle = this->actor.world.rot.y - this->actor.shape.rot.y;
force.x = (s32)(this->actor.speedXZ * -200.0f * Math_CosS(angle) * (Rand_CenteredFloat(2.0f) + 10.0f)) & 0xFFFF;
force.y = (s32)(this->actor.speedXZ * 100.0f * Math_SinS(angle) * (Rand_CenteredFloat(2.0f) + 10.0f)) & 0xFFFF;
sBunnyEarKinematics.angVel.x += force.x >> 2;
sBunnyEarKinematics.angVel.y += force.y >> 2;
// Clamp both angular velocities to [-6000, 6000]
if (sBunnyEarKinematics.angVel.x > 6000) {
sBunnyEarKinematics.angVel.x = 6000;
} else if (sBunnyEarKinematics.angVel.x < -6000) {
sBunnyEarKinematics.angVel.x = -6000;
}
if (sBunnyEarKinematics.angVel.y > 6000) {
sBunnyEarKinematics.angVel.y = 6000;
} else if (sBunnyEarKinematics.angVel.y < -6000) {
sBunnyEarKinematics.angVel.y = -6000;
}
// Add angular velocity to rotations
sBunnyEarKinematics.rot.x += sBunnyEarKinematics.angVel.x;
sBunnyEarKinematics.rot.y += sBunnyEarKinematics.angVel.y;
// swivel ears outwards if bending backwards
if (sBunnyEarKinematics.rot.x < 0) {
sBunnyEarKinematics.rot.z = sBunnyEarKinematics.rot.x >> 1;
} else {
sBunnyEarKinematics.rot.z = 0;
}
}
s32 Player_ActionChange_7(Player* this, PlayState* play) {
if (func_8083C6B8(play, this) == 0) {
if (func_8083BB20(this) != 0) {
s32 sp24 = func_80837818(this);
func_80837948(play, this, sp24);
if (sp24 >= PLAYER_MWA_SPIN_ATTACK_1H) {
this->stateFlags2 |= PLAYER_STATE2_SPIN_ATTACKING;
func_80837530(play, this, 0);
return 1;
}
} else {
return 0;
}
}
return 1;
}
static Vec3f D_80854A40 = { 0.0f, 40.0f, 45.0f };
void Player_Action_808502D0(Player* this, PlayState* play) {
struct_80854190* sp44 = &D_80854190[this->meleeWeaponAnimation];
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
if (!func_80842DF4(play, this)) {
func_8084285C(this, 0.0f, sp44->unk_0C, sp44->unk_0D);
if ((this->stateFlags2 & PLAYER_STATE2_SWORD_LUNGE) && (this->heldItemAction != PLAYER_IA_HAMMER) &&
LinkAnimation_OnFrame(&this->skelAnime, 0.0f)) {
this->linearVelocity = 15.0f;
this->stateFlags2 &= ~PLAYER_STATE2_SWORD_LUNGE;
}
if (this->linearVelocity > 12.0f) {
func_8084269C(play, this);
}
Math_StepToF(&this->linearVelocity, 0.0f, 5.0f);
func_8083C50C(this);
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (!Player_ActionChange_7(this, play)) {
u8 sp43 = this->skelAnime.moveFlags;
LinkAnimationHeader* sp3C;
if (func_8008E9C4(this)) {
sp3C = sp44->unk_08;
} else {
sp3C = sp44->unk_04;
}
func_80832318(this);
this->skelAnime.moveFlags = 0;
if ((sp3C == &gPlayerAnim_link_fighter_Lpower_jump_kiru_end) &&
(this->modelAnimType != PLAYER_ANIMTYPE_3)) {
sp3C = &gPlayerAnim_link_fighter_power_jump_kiru_end;
}
func_8083A098(this, sp3C, play);
this->skelAnime.moveFlags = sp43;
this->stateFlags3 |= PLAYER_STATE3_FINISHED_ATTACKING;
}
} else if (this->heldItemAction == PLAYER_IA_HAMMER) {
if ((this->meleeWeaponAnimation == PLAYER_MWA_HAMMER_FORWARD) ||
(this->meleeWeaponAnimation == PLAYER_MWA_JUMPSLASH_FINISH)) {
static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
Vec3f shockwavePos;
f32 sp2C;
shockwavePos.y = func_8083973C(play, this, &D_80854A40, &shockwavePos);
sp2C = this->actor.world.pos.y - shockwavePos.y;
Math_ScaledStepToS(&this->actor.focus.rot.x, Math_Atan2S(45.0f, sp2C), 800);
func_80836AB8(this, 1);
if ((((this->meleeWeaponAnimation == PLAYER_MWA_HAMMER_FORWARD) && LinkAnimation_OnFrame(&this->skelAnime, 7.0f)) ||
((this->meleeWeaponAnimation == PLAYER_MWA_JUMPSLASH_FINISH) && LinkAnimation_OnFrame(&this->skelAnime, 2.0f))) &&
(sp2C > -40.0f) && (sp2C < 40.0f)) {
func_80842A28(play, this);
EffectSsBlast_SpawnWhiteShockwave(play, &shockwavePos, &zeroVec, &zeroVec);
}
}
}
}
}
void Player_Action_808505DC(Player* this, PlayState* play) {
LinkAnimation_Update(play, &this->skelAnime);
func_8083721C(this);
if (this->skelAnime.curFrame >= 6.0f) {
func_80839FFC(this, play);
}
}
void Player_Action_8085063C(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
LinkAnimation_Update(play, &this->skelAnime);
Player_UpdateUpperBody(this, play);
if (this->av2.actionVar2 == 0) {
Message_StartTextbox(play, 0x3B, &this->actor);
this->av2.actionVar2 = 1;
return;
}
if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) {
s32 respawnData = gSaveContext.respawn[RESPAWN_MODE_TOP].data;
if (play->msgCtx.choiceIndex == 0) { //Returns to FW
gSaveContext.respawnFlag = 3;
play->transitionTrigger = TRANS_TRIGGER_START;
play->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_TOP].entranceIndex;
play->transitionType = TRANS_TYPE_FADE_WHITE_FAST;
func_80088AF0(play);
return;
}
if (play->msgCtx.choiceIndex == 1) { //Unsets FW
gSaveContext.respawn[RESPAWN_MODE_TOP].data = -respawnData;
gSaveContext.fw.set = 0;
func_80078914(&gSaveContext.respawn[RESPAWN_MODE_TOP].pos, NA_SE_PL_MAGIC_WIND_VANISH);
}
func_80853080(this, play);
func_8005B1A4(Play_GetCamera(play, 0));
}
}
void Player_Action_8085076C(Player* this, PlayState* play) {
s32 respawnData = gSaveContext.respawn[RESPAWN_MODE_TOP].data;
if (this->av2.actionVar2 > 20) {
this->actor.draw = Player_Draw;
this->actor.world.pos.y += 60.0f;
func_80837B9C(this, play);
return;
}
if (this->av2.actionVar2++ == 20) {
gSaveContext.respawn[RESPAWN_MODE_TOP].data = respawnData + 1;
func_80078914(&gSaveContext.respawn[RESPAWN_MODE_TOP].pos, NA_SE_PL_MAGIC_WIND_WARP);
}
}
static LinkAnimationHeader* D_80854A58[] = {
&gPlayerAnim_link_magic_kaze1,
&gPlayerAnim_link_magic_honoo1,
&gPlayerAnim_link_magic_tamashii1,
};
static LinkAnimationHeader* D_80854A64[] = {
&gPlayerAnim_link_magic_kaze2,
&gPlayerAnim_link_magic_honoo2,
&gPlayerAnim_link_magic_tamashii2,
};
static LinkAnimationHeader* D_80854A70[] = {
&gPlayerAnim_link_magic_kaze3,
&gPlayerAnim_link_magic_honoo3,
&gPlayerAnim_link_magic_tamashii3,
};
static u8 D_80854A7C[] = { 70, 10, 10 };
static AnimSfxEntry D_80854A80[] = {
{ NA_SE_PL_SKIP, ANIMSFX_DATA(ANIMSFX_TYPE_1, 20) },
{ NA_SE_VO_LI_SWORD_N, ANIMSFX_DATA(ANIMSFX_TYPE_4, 20) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 26) },
};
static AnimSfxEntry D_80854A8C[][2] = {
{
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 20) },
{ NA_SE_VO_LI_MAGIC_FROL, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 30) },
},
{
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 20) },
{ NA_SE_VO_LI_MAGIC_NALE, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 44) },
},
{
{ NA_SE_VO_LI_MAGIC_ATTACK, ANIMSFX_DATA(ANIMSFX_TYPE_4, 20) },
{ NA_SE_IT_SWORD_SWING_HARD, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 20) },
},
};
void Player_Action_808507F4(Player* this, PlayState* play) {
u8 isFastFarores = CVarGetInteger("gFastFarores", 0) && this->itemAction == PLAYER_IA_FARORES_WIND;
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->av1.actionVar1 < 0) {
if ((this->itemAction == PLAYER_IA_NAYRUS_LOVE) || isFastFarores || (gSaveContext.magicState == MAGIC_STATE_IDLE)) {
func_80839FFC(this, play);
func_8005B1A4(Play_GetCamera(play, 0));
}
} else {
if (this->av2.actionVar2 == 0) {
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, D_80854A58[this->av1.actionVar1], 0.83f * (isFastFarores ? 2 : 1));
if (func_80846A00(play, this, this->av1.actionVar1) != NULL) {
this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
if ((this->av1.actionVar1 != 0) || (gSaveContext.respawn[RESPAWN_MODE_TOP].data <= 0)) {
gSaveContext.magicState = MAGIC_STATE_CONSUME_SETUP;
}
} else {
Magic_Reset(play);
}
} else {
LinkAnimation_PlayLoopSetSpeed(play, &this->skelAnime, D_80854A64[this->av1.actionVar1], 0.83f * (isFastFarores ? 2 : 1));
if (this->av1.actionVar1 == 0) {
this->av2.actionVar2 = -10;
}
}
this->av2.actionVar2++;
}
} else {
if (this->av2.actionVar2 < 0) {
this->av2.actionVar2++;
if (this->av2.actionVar2 == 0) {
gSaveContext.respawn[RESPAWN_MODE_TOP].data = 1;
Play_SetupRespawnPoint(play, RESPAWN_MODE_TOP, 0x6FF);
gSaveContext.fw.set = 1;
gSaveContext.fw.pos.x = gSaveContext.respawn[RESPAWN_MODE_DOWN].pos.x;
gSaveContext.fw.pos.y = gSaveContext.respawn[RESPAWN_MODE_DOWN].pos.y;
gSaveContext.fw.pos.z = gSaveContext.respawn[RESPAWN_MODE_DOWN].pos.z;
gSaveContext.fw.yaw = gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw;
gSaveContext.fw.playerParams = 0x6FF;
gSaveContext.fw.entranceIndex = gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex;
gSaveContext.fw.roomIndex = gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex;
gSaveContext.fw.tempSwchFlags = gSaveContext.respawn[RESPAWN_MODE_DOWN].tempSwchFlags;
gSaveContext.fw.tempCollectFlags = gSaveContext.respawn[RESPAWN_MODE_DOWN].tempCollectFlags;
this->av2.actionVar2 = 2;
}
} else if (this->av1.actionVar1 >= 0) {
if (this->av2.actionVar2 == 0) {
Player_ProcessAnimSfxList(this, D_80854A80);
} else if (this->av2.actionVar2 == 1) {
Player_ProcessAnimSfxList(this, D_80854A8C[this->av1.actionVar1]);
if ((this->av1.actionVar1 == 2) && LinkAnimation_OnFrame(&this->skelAnime, 30.0f)) {
this->stateFlags1 &= ~(PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE);
}
} else if ((isFastFarores ? 10 : D_80854A7C[this->av1.actionVar1]) < this->av2.actionVar2++) {
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, D_80854A70[this->av1.actionVar1], 0.83f * (isFastFarores ? 2 : 1));
this->yaw = this->actor.shape.rot.y;
this->av1.actionVar1 = -1;
}
}
}
func_8083721C(this);
}
void Player_Action_80850AEC(Player* this, PlayState* play) {
f32 temp;
this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET;
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_hook_fly_wait);
}
Math_Vec3f_Sum(&this->actor.world.pos, &this->actor.velocity, &this->actor.world.pos);
if (func_80834FBC(this)) {
Math_Vec3f_Copy(&this->actor.prevPos, &this->actor.world.pos);
Player_ProcessSceneCollision(play, this);
temp = this->actor.world.pos.y - this->actor.floorHeight;
if (temp > 20.0f) {
temp = 20.0f;
}
this->actor.world.rot.x = this->actor.shape.rot.x = 0;
this->actor.world.pos.y -= temp;
this->linearVelocity = 1.0f;
this->actor.velocity.y = 0.0f;
func_80837B9C(this, play);
this->stateFlags2 &= ~PLAYER_STATE2_UNDERWATER;
this->actor.bgCheckFlags |= 1;
this->stateFlags1 |= PLAYER_STATE1_HOOKSHOT_FALLING;
return;
}
if ((this->skelAnime.animation != &gPlayerAnim_link_hook_fly_start) || (4.0f <= this->skelAnime.curFrame)) {
this->actor.gravity = 0.0f;
Math_ScaledStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x, 0x800);
Player_RequestRumble(this, 100, 2, 100, 0);
}
}
void Player_Action_80850C68(Player* this, PlayState* play) {
if ((this->av2.actionVar2 != 0) && ((this->unk_858 != 0.0f) || (this->unk_85C != 0.0f))) {
f32 updateScale = R_UPDATE_RATE * 0.5f;
this->skelAnime.curFrame += this->skelAnime.playSpeed * updateScale;
if (this->skelAnime.curFrame >= this->skelAnime.animLength) {
this->skelAnime.curFrame -= this->skelAnime.animLength;
}
LinkAnimation_BlendToJoint(
play, &this->skelAnime, &gPlayerAnim_link_fishing_wait, this->skelAnime.curFrame,
(this->unk_858 < 0.0f) ? &gPlayerAnim_link_fishing_reel_left : &gPlayerAnim_link_fishing_reel_right, 5.0f,
fabsf(this->unk_858), this->blendTable);
LinkAnimation_BlendToMorph(
play, &this->skelAnime, &gPlayerAnim_link_fishing_wait, this->skelAnime.curFrame,
(this->unk_85C < 0.0f) ? &gPlayerAnim_link_fishing_reel_up : &gPlayerAnim_link_fishing_reel_down, 5.0f,
fabsf(this->unk_85C), D_80858AD8);
LinkAnimation_InterpJointMorph(play, &this->skelAnime, 0.5f);
} else if (LinkAnimation_Update(play, &this->skelAnime)) {
this->unk_860 = 2;
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_fishing_wait);
this->av2.actionVar2 = 1;
}
func_8083721C(this);
if (this->unk_860 == 0) {
func_80853080(this, play);
} else if (this->unk_860 == 3) {
Player_SetupAction(play, this, Player_Action_80850E84, 0);
Player_AnimChangeOnceMorph(play, this, &gPlayerAnim_link_fishing_fish_catch);
}
}
void Player_Action_80850E84(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime) && (this->unk_860 == 0)) {
func_8083A098(this, &gPlayerAnim_link_fishing_fish_catch_end, play);
}
}
static void (*D_80854AA4[])(PlayState*, Player*, void*) = {
NULL, func_80851008, func_80851030, func_80851094, func_808510B4, func_808510D4, func_808510F4,
func_80851114, func_80851134, func_80851154, func_80851174, func_808511D4, func_808511FC, func_80851294,
func_80851050, func_80851194, func_808511B4, func_80851248, func_808512E0,
};
static AnimSfxEntry D_80854AF0[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_5, 34) },
{ NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 45) },
{ NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 51) },
{ NA_SE_PL_CALM_HIT, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 64) },
};
static AnimSfxEntry D_80854B00[] = {
{ NA_SE_VO_LI_SURPRISE, ANIMSFX_DATA(ANIMSFX_TYPE_4, 3) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 15) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 24) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 30) },
{ NA_SE_VO_LI_FALL_L, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 31) },
};
static AnimSfxEntry D_80854B14[] = {
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 10) },
};
static struct_80854B18 D_80854B18[] = {
{ 0, NULL },
{ -1, func_808515A4 },
{ 2, &gPlayerAnim_link_demo_goma_furimuki },
{ 0, NULL },
{ 0, NULL },
{ 3, &gPlayerAnim_link_demo_bikkuri },
{ 0, NULL },
{ 0, NULL },
{ -1, func_808515A4 },
{ 2, &gPlayerAnim_link_demo_furimuki },
{ -1, func_80851788 },
{ 3, &gPlayerAnim_link_demo_warp },
{ -1, func_808518DC },
{ 7, &gPlayerAnim_clink_demo_get1 },
{ 5, &gPlayerAnim_clink_demo_get2 },
{ 5, &gPlayerAnim_clink_demo_get3 },
{ 5, &gPlayerAnim_clink_demo_standup },
{ 7, &gPlayerAnim_clink_demo_standup_wait },
{ -1, func_808519EC },
{ 2, &gPlayerAnim_link_demo_baru_op1 },
{ 2, &gPlayerAnim_link_demo_baru_op3 },
{ 0, NULL },
{ -1, func_80851B90 },
{ 3, &gPlayerAnim_link_demo_jibunmiru },
{ 9, &gPlayerAnim_link_normal_back_downA },
{ 2, &gPlayerAnim_link_normal_back_down_wake },
{ -1, func_80851D2C },
{ 2, &gPlayerAnim_link_normal_okarina_end },
{ 3, &gPlayerAnim_link_demo_get_itemA },
{ -1, func_808515A4 },
{ 2, &gPlayerAnim_link_normal_normal2fighter_free },
{ 0, NULL },
{ 0, NULL },
{ 5, &gPlayerAnim_clink_demo_atozusari },
{ -1, func_80851368 },
{ -1, func_80851E64 },
{ 5, &gPlayerAnim_clink_demo_bashi },
{ 16, &gPlayerAnim_link_normal_hang_up_down },
{ -1, func_80851F84 },
{ -1, func_80851E90 },
{ 6, &gPlayerAnim_clink_op3_okiagari },
{ 6, &gPlayerAnim_clink_op3_tatiagari },
{ -1, func_80852080 },
{ 5, &gPlayerAnim_clink_demo_miokuri },
{ -1, func_808521F4 },
{ -1, func_8085225C },
{ -1, func_80852280 },
{ 5, &gPlayerAnim_clink_demo_nozoki },
{ 5, &gPlayerAnim_clink_demo_koutai },
{ -1, func_808515A4 },
{ 5, &gPlayerAnim_clink_demo_koutai_kennuki },
{ 5, &gPlayerAnim_link_demo_kakeyori },
{ 5, &gPlayerAnim_link_demo_kakeyori_mimawasi },
{ 5, &gPlayerAnim_link_demo_kakeyori_miokuri },
{ 3, &gPlayerAnim_link_demo_furimuki2 },
{ 3, &gPlayerAnim_link_demo_kaoage },
{ 4, &gPlayerAnim_link_demo_kaoage_wait },
{ 3, &gPlayerAnim_clink_demo_mimawasi },
{ 3, &gPlayerAnim_link_demo_nozokikomi },
{ 6, &gPlayerAnim_kolink_odoroki_demo },
{ 6, &gPlayerAnim_link_shagamu_demo },
{ 14, &gPlayerAnim_link_okiru_demo },
{ 3, &gPlayerAnim_link_okiru_demo },
{ 5, &gPlayerAnim_link_fighter_power_kiru_start },
{ 16, &gPlayerAnim_demo_link_nwait },
{ 15, &gPlayerAnim_demo_link_tewatashi },
{ 15, &gPlayerAnim_demo_link_orosuu },
{ 3, &gPlayerAnim_d_link_orooro },
{ 3, &gPlayerAnim_d_link_imanodare },
{ 3, &gPlayerAnim_link_hatto_demo },
{ 6, &gPlayerAnim_o_get_mae },
{ 6, &gPlayerAnim_o_get_ato },
{ 6, &gPlayerAnim_om_get_mae },
{ 6, &gPlayerAnim_nw_modoru },
{ 3, &gPlayerAnim_link_demo_gurad },
{ 3, &gPlayerAnim_link_demo_look_hand },
{ 4, &gPlayerAnim_link_demo_sita_wait },
{ 3, &gPlayerAnim_link_demo_ue },
{ 3, &gPlayerAnim_Link_muku },
{ 3, &gPlayerAnim_Link_miageru },
{ 6, &gPlayerAnim_Link_ha },
{ 3, &gPlayerAnim_L_1kyoro },
{ 3, &gPlayerAnim_L_2kyoro },
{ 3, &gPlayerAnim_L_sagaru },
{ 3, &gPlayerAnim_L_bouzen },
{ 3, &gPlayerAnim_L_kamaeru },
{ 3, &gPlayerAnim_L_hajikareru },
{ 3, &gPlayerAnim_L_ken_miru },
{ 3, &gPlayerAnim_L_mukinaoru },
{ -1, func_808524B0 },
{ 3, &gPlayerAnim_link_wait_itemD1_20f },
{ -1, func_80852544 },
{ -1, func_80852564 },
{ 3, &gPlayerAnim_link_normal_wait_typeB_20f },
{ -1, func_80852608 },
{ 3, &gPlayerAnim_link_demo_kousan },
{ 3, &gPlayerAnim_link_demo_return_to_past },
{ 3, &gPlayerAnim_link_last_hit_motion1 },
{ 3, &gPlayerAnim_link_last_hit_motion2 },
{ 3, &gPlayerAnim_link_demo_zeldamiru },
{ 3, &gPlayerAnim_link_demo_kenmiru1 },
{ 3, &gPlayerAnim_link_demo_kenmiru2 },
{ 3, &gPlayerAnim_link_demo_kenmiru2_modori },
};
static struct_80854B18 D_80854E50[] = {
{ 0, NULL },
{ -1, func_808514C0 },
{ -1, func_8085157C },
{ -1, func_80851998 },
{ -1, func_808519C0 },
{ 11, NULL },
{ -1, func_80852C50 },
{ -1, func_80852944 },
{ -1, func_80851688 },
{ -1, func_80851750 },
{ -1, func_80851828 },
{ -1, func_808521B8 },
{ -1, func_8085190C },
{ 11, NULL },
{ 11, NULL },
{ 11, NULL },
{ 18, D_80854AF0 },
{ 11, NULL },
{ -1, func_80851A50 },
{ 12, &gPlayerAnim_link_demo_baru_op2 },
{ 11, NULL },
{ 0, NULL },
{ -1, func_80851BE8 },
{ 11, NULL },
{ -1, func_80851CA4 },
{ 11, NULL },
{ 17, &gPlayerAnim_link_normal_okarina_swing },
{ 11, NULL },
{ 11, NULL },
{ 11, NULL },
{ -1, func_80851D80 },
{ -1, func_80851DEC },
{ -1, func_80851E28 },
{ 18, D_80854B00 },
{ -1, func_808513BC },
{ 11, NULL },
{ 11, NULL },
{ 11, NULL },
{ 11, NULL },
{ -1, func_80851ECC },
{ -1, func_80851FB0 },
{ -1, func_80852048 },
{ -1, func_80852174 },
{ 13, &gPlayerAnim_clink_demo_miokuri_wait },
{ -1, func_80852234 },
{ 0, NULL },
{ 0, NULL },
{ 11, NULL },
{ -1, func_80852450 },
{ -1, func_80851688 },
{ -1, func_80852298 },
{ 13, &gPlayerAnim_link_demo_kakeyori_wait },
{ -1, func_80852480 },
{ 13, &gPlayerAnim_link_demo_kakeyori_miokuri_wait },
{ -1, func_80852328 },
{ 11, NULL },
{ 11, NULL },
{ 12, &gPlayerAnim_clink_demo_mimawasi_wait },
{ -1, func_80852358 },
{ 11, NULL },
{ 18, D_80854B14 },
{ 11, NULL },
{ 11, NULL },
{ 11, NULL },
{ 11, NULL },
{ -1, func_80852388 },
{ 17, &gPlayerAnim_demo_link_nwait },
{ 12, &gPlayerAnim_d_link_orowait },
{ 12, &gPlayerAnim_demo_link_nwait },
{ 11, NULL },
{ -1, func_808526EC },
{ 17, &gPlayerAnim_sude_nwait },
{ -1, func_808526EC },
{ 17, &gPlayerAnim_sude_nwait },
{ 12, &gPlayerAnim_link_demo_gurad_wait },
{ 12, &gPlayerAnim_link_demo_look_hand_wait },
{ 11, NULL },
{ 12, &gPlayerAnim_link_demo_ue_wait },
{ 12, &gPlayerAnim_Link_m_wait },
{ 13, &gPlayerAnim_Link_ue_wait },
{ 12, &gPlayerAnim_Link_otituku_w },
{ 12, &gPlayerAnim_L_kw },
{ 11, NULL },
{ 11, NULL },
{ 11, NULL },
{ 11, NULL },
{ -1, func_80852648 },
{ 11, NULL },
{ 12, &gPlayerAnim_L_kennasi_w },
{ -1, func_808524D0 },
{ -1, func_80852514 },
{ -1, func_80852554 },
{ -1, func_808525C0 },
{ 11, NULL },
{ 11, NULL },
{ 11, NULL },
{ -1, func_8085283C },
{ -1, func_808528C8 },
{ -1, func_808528C8 },
{ 12, &gPlayerAnim_link_demo_zeldamiru_wait },
{ 12, &gPlayerAnim_link_demo_kenmiru1_wait },
{ 12, &gPlayerAnim_link_demo_kenmiru2_wait },
{ 12, &gPlayerAnim_demo_link_nwait },
};
void Player_AnimChangeOnceMorphZeroRootYawSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim) {
Player_ZeroRootLimbYaw(this);
Player_AnimChangeOnceMorph(play, this, anim);
Player_ZeroSpeedXZ(this);
}
void Player_AnimChangeOnceMorphAdjustedZeroRootYawSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim) {
Player_ZeroRootLimbYaw(this);
LinkAnimation_Change(play, &this->skelAnime, anim, PLAYER_ANIM_ADJUSTED_SPEED, 0.0f, Animation_GetLastFrame(anim),
ANIMMODE_ONCE, -8.0f);
Player_ZeroSpeedXZ(this);
}
void Player_AnimChangeLoopMorphAdjustedZeroRootYawSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim) {
Player_ZeroRootLimbYaw(this);
LinkAnimation_Change(play, &this->skelAnime, anim, PLAYER_ANIM_ADJUSTED_SPEED, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f);
Player_ZeroSpeedXZ(this);
}
void func_80851008(PlayState* play, Player* this, void* anim) {
Player_ZeroSpeedXZ(this);
}
void func_80851030(PlayState* play, Player* this, void* anim) {
Player_AnimChangeOnceMorphZeroRootYawSpeed(play, this, anim);
}
void func_80851050(PlayState* play, Player* this, void* anim) {
Player_ZeroRootLimbYaw(this);
Player_AnimChangeFreeze(play, this, anim);
Player_ZeroSpeedXZ(this);
}
void func_80851094(PlayState* play, Player* this, void* anim) {
Player_AnimChangeOnceMorphAdjustedZeroRootYawSpeed(play, this, anim);
}
void func_808510B4(PlayState* play, Player* this, void* anim) {
Player_AnimChangeLoopMorphAdjustedZeroRootYawSpeed(play, this, anim);
}
void func_808510D4(PlayState* play, Player* this, void* anim) {
Player_AnimReplaceNormalPlayOnceAdjusted(play, this, anim);
}
void func_808510F4(PlayState* play, Player* this, void* anim) {
Player_AnimReplacePlayOnce(play, this, anim, 0x9C);
}
void func_80851114(PlayState* play, Player* this, void* anim) {
Player_AnimReplaceNormalPlayLoopAdjusted(play, this, anim);
}
void func_80851134(PlayState* play, Player* this, void* anim) {
Player_AnimReplacePlayLoop(play, this, anim, 0x9C);
}
void func_80851154(PlayState* play, Player* this, void* anim) {
Player_AnimPlayOnce(play, this, anim);
}
void func_80851174(PlayState* play, Player* this, void* anim) {
Player_AnimPlayLoop(play, this, anim);
}
void func_80851194(PlayState* play, Player* this, void* anim) {
Player_AnimPlayOnceAdjusted(play, this, anim);
}
void func_808511B4(PlayState* play, Player* this, void* anim) {
Player_AnimPlayLoopAdjusted(play, this, anim);
}
void func_808511D4(PlayState* play, Player* this, void* anim) {
LinkAnimation_Update(play, &this->skelAnime);
}
void func_808511FC(PlayState* play, Player* this, void* anim) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimChangeLoopMorphAdjustedZeroRootYawSpeed(play, this, anim);
this->av2.actionVar2 = 1;
}
}
void func_80851248(PlayState* play, Player* this, void* anim) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80832DBC(this);
Player_AnimPlayLoopAdjusted(play, this, anim);
}
}
void func_80851294(PlayState* play, Player* this, void* anim) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimReplaceNormalPlayLoopAdjusted(play, this, anim);
this->av2.actionVar2 = 1;
}
}
void func_808512E0(PlayState* play, Player* this, void* arg2) {
LinkAnimation_Update(play, &this->skelAnime);
Player_ProcessAnimSfxList(this, arg2);
}
void func_80851314(Player* this) {
if ((this->csActor == NULL) || (this->csActor->update == NULL)) {
this->csActor = NULL;
}
this->unk_664 = this->csActor;
if (this->unk_664 != NULL) {
this->actor.shape.rot.y = func_8083DB98(this, 0);
}
}
void func_80851368(PlayState* play, Player* this, CsCmdActorAction* arg2) {
this->stateFlags1 |= PLAYER_STATE1_IN_WATER;
this->stateFlags2 |= PLAYER_STATE2_UNDERWATER;
this->stateFlags1 &= ~(PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL);
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_swimer_swim);
}
void func_808513BC(PlayState* play, Player* this, CsCmdActorAction* arg2) {
this->actor.gravity = 0.0f;
if (this->av1.actionVar1 == 0) {
if (func_8083D12C(play, this, NULL)) {
this->av1.actionVar1 = 1;
} else {
func_8084B158(play, this, NULL, fabsf(this->actor.velocity.y));
Math_ScaledStepToS(&this->unk_6C2, -10000, 800);
func_8084AEEC(this, &this->actor.velocity.y, 4.0f, this->yaw);
}
return;
}
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->av1.actionVar1 == 1) {
Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim_wait);
} else {
Player_AnimPlayLoop(play, this, &gPlayerAnim_link_swimer_swim_wait);
}
}
func_8084B000(this);
func_8084AEEC(this, &this->linearVelocity, 0.0f, this->actor.shape.rot.y);
}
void func_808514C0(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_80851314(this);
if (func_808332B8(this)) {
func_808513BC(play, this, 0);
return;
}
LinkAnimation_Update(play, &this->skelAnime);
if (func_8008F128(this) || (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) {
Player_UpdateUpperBody(this, play);
return;
}
if ((this->interactRangeActor != NULL) && (this->interactRangeActor->textId == 0xFFFF)) {
Player_ActionChange_2(this, play);
}
}
void func_8085157C(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimation_Update(play, &this->skelAnime);
}
void func_808515A4(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimationHeader* anim;
if (func_808332B8(this)) {
func_80851368(play, this, 0);
return;
}
anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_nwait, this->modelAnimType);
if ((this->cueId == 6) || (this->cueId == 0x2E)) {
Player_AnimPlayOnce(play, this, anim);
} else {
Player_ZeroRootLimbYaw(this);
LinkAnimation_Change(play, &this->skelAnime, anim, (2.0f / 3.0f), 0.0f, Animation_GetLastFrame(anim),
ANIMMODE_LOOP, -4.0f);
}
Player_ZeroSpeedXZ(this);
}
void func_80851688(PlayState* play, Player* this, CsCmdActorAction* arg2) {
if (func_8084B3CC(play, this) == 0) {
if ((this->csAction == 0x31) && (play->csCtx.state == CS_STATE_IDLE)) {
func_8002DF54(play, NULL, 7);
return;
}
if (func_808332B8(this) != 0) {
func_808513BC(play, this, 0);
return;
}
LinkAnimation_Update(play, &this->skelAnime);
if (func_8008F128(this) || (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) {
Player_UpdateUpperBody(this, play);
}
}
}
static AnimSfxEntry D_80855188[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 42) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 48) },
};
void func_80851750(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimation_Update(play, &this->skelAnime);
Player_ProcessAnimSfxList(this, D_80855188);
}
void func_80851788(PlayState* play, Player* this, CsCmdActorAction* arg2) {
this->stateFlags1 &= ~PLAYER_STATE1_THREW_BOOMERANG;
this->yaw = this->actor.shape.rot.y = this->actor.world.rot.y =
Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_450);
if (this->linearVelocity <= 0.0f) {
this->linearVelocity = 0.1f;
} else if (this->linearVelocity > 2.5f) {
this->linearVelocity = 2.5f;
}
}
void func_80851828(PlayState* play, Player* this, CsCmdActorAction* arg2) {
f32 sp1C = 2.5f;
func_80845BA0(play, this, &sp1C, 10);
if (play->sceneNum == SCENE_JABU_JABU_BOSS) {
if (this->av2.actionVar2 == 0) {
if (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) {
return;
}
} else {
if (Message_GetState(&play->msgCtx) != TEXT_STATE_NONE) {
return;
}
}
}
this->av2.actionVar2++;
if (this->av2.actionVar2 > 20) {
this->csAction = 0xB;
}
}
void func_808518DC(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_8083CEAC(this, play);
}
void func_8085190C(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_80851314(this);
if (this->av2.actionVar2 != 0) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimPlayLoop(play, this, func_808334E4(this));
this->av2.actionVar2 = 0;
}
func_80833C3C(this);
} else {
func_808401B0(play, this);
}
}
void func_80851998(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_80845964(play, this, arg2, 0.0f, 0, 0);
}
void func_808519C0(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_80845964(play, this, arg2, 0.0f, 0, 1);
}
// unused
static LinkAnimationHeader* D_80855190[] = {
&gPlayerAnim_link_demo_back_to_past,
&gPlayerAnim_clink_demo_goto_future,
};
static Vec3f D_80855198 = { -1.0f, 70.0f, 20.0f };
void func_808519EC(PlayState* play, Player* this, CsCmdActorAction* arg2) {
Math_Vec3f_Copy(&this->actor.world.pos, &D_80855198);
this->actor.shape.rot.y = -0x8000;
Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_9C);
Player_AnimReplaceApplyFlags(play, this, 0x28F);
}
static struct_808551A4 D_808551A4[] = {
{ NA_SE_IT_SWORD_PUTAWAY_STN, 0 },
{ NA_SE_IT_SWORD_STICK_STN, NA_SE_VO_LI_SWORD_N },
};
static AnimSfxEntry D_808551AC[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 29) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_8, 39) },
};
void func_80851A50(PlayState* play, Player* this, CsCmdActorAction* arg2) {
struct_808551A4* sp2C;
Gfx** dLists;
LinkAnimation_Update(play, &this->skelAnime);
if ((LINK_IS_ADULT && LinkAnimation_OnFrame(&this->skelAnime, 70.0f)) ||
(!LINK_IS_ADULT && LinkAnimation_OnFrame(&this->skelAnime, 87.0f))) {
sp2C = &D_808551A4[gSaveContext.linkAge];
this->interactRangeActor->parent = &this->actor;
if (!LINK_IS_ADULT) {
dLists = gPlayerLeftHandBgsDLs;
} else {
dLists = gPlayerLeftHandClosedDLs;
}
this->leftHandDLists = &dLists[gSaveContext.linkAge];
Player_PlaySfx(this, sp2C->unk_00);
if (!LINK_IS_ADULT) {
func_80832698(this, sp2C->unk_02);
}
} else if (LINK_IS_ADULT) {
if (LinkAnimation_OnFrame(&this->skelAnime, 66.0f)) {
func_80832698(this, NA_SE_VO_LI_SWORD_L);
}
} else {
Player_ProcessAnimSfxList(this, D_808551AC);
}
}
void func_80851B90(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_demo_warp, -(2.0f / 3.0f), 12.0f, 12.0f,
ANIMMODE_ONCE, 0.0f);
}
static AnimSfxEntry D_808551B4[] = {
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_5, 30) },
};
void func_80851BE8(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimation_Update(play, &this->skelAnime);
this->av2.actionVar2++;
if (this->av2.actionVar2 >= 180) {
if (this->av2.actionVar2 == 180) {
LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_okarina_warp_goal, (2.0f / 3.0f), 10.0f,
Animation_GetLastFrame(&gPlayerAnim_link_okarina_warp_goal), ANIMMODE_ONCE, -8.0f);
}
Player_ProcessAnimSfxList(this, D_808551B4);
}
}
void func_80851CA4(PlayState* play, Player* this, CsCmdActorAction* arg2) {
if (LinkAnimation_Update(play, &this->skelAnime) && (this->av2.actionVar2 == 0) && (this->actor.bgCheckFlags & 1)) {
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_back_downB);
this->av2.actionVar2 = 1;
}
if (this->av2.actionVar2 != 0) {
func_8083721C(this);
}
}
void func_80851D2C(PlayState* play, Player* this, CsCmdActorAction* arg2) {
Player_AnimChangeOnceMorphAdjustedZeroRootYawSpeed(play, this, &gPlayerAnim_link_normal_okarina_start);
func_8084B498(this);
Player_SetModels(this, Player_ActionToModelGroup(this, this->itemAction));
}
static AnimSfxEntry D_808551B8[] = {
{ NA_SE_IT_SWORD_PICKOUT, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 12) },
};
void func_80851D80(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimation_Update(play, &this->skelAnime);
if (LinkAnimation_OnFrame(&this->skelAnime, 6.0f)) {
func_80846720(play, this, 0);
} else {
Player_ProcessAnimSfxList(this, D_808551B8);
}
}
void func_80851DEC(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimation_Update(play, &this->skelAnime);
Math_StepToS(&this->actor.shape.face, 0, 1);
}
void func_80851E28(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimation_Update(play, &this->skelAnime);
Math_StepToS(&this->actor.shape.face, 2, 1);
}
void func_80851E64(PlayState* play, Player* this, CsCmdActorAction* arg2) {
Player_AnimReplacePlayOnceAdjusted(play, this, &gPlayerAnim_link_swimer_swim_get, 0x98);
}
void func_80851E90(PlayState* play, Player* this, CsCmdActorAction* arg2) {
Player_AnimReplacePlayOnce(play, this, &gPlayerAnim_clink_op3_negaeri, 0x9C);
func_80832698(this, NA_SE_VO_LI_GROAN);
}
void func_80851ECC(PlayState* play, Player* this, CsCmdActorAction* arg2) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimReplacePlayLoop(play, this, &gPlayerAnim_clink_op3_wait2, 0x9C);
}
}
void func_80851F14(PlayState* play, Player* this, LinkAnimationHeader* anim, AnimSfxEntry* arg3) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimPlayLoopAdjusted(play, this, anim);
this->av2.actionVar2 = 1;
} else if (this->av2.actionVar2 == 0) {
Player_ProcessAnimSfxList(this, arg3);
}
}
void func_80851F84(PlayState* play, Player* this, CsCmdActorAction* arg2) {
this->actor.shape.shadowDraw = NULL;
func_80851134(play, this, &gPlayerAnim_clink_op3_wait1);
}
static AnimSfxEntry D_808551BC[] = {
{ NA_SE_VO_LI_RELAX, ANIMSFX_DATA(ANIMSFX_TYPE_4, 35) },
{ NA_SE_PL_SLIPDOWN, ANIMSFX_DATA(ANIMSFX_TYPE_1, 236) },
{ NA_SE_PL_SLIPDOWN, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 256) },
};
void func_80851FB0(PlayState* play, Player* this, CsCmdActorAction* arg2) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimReplacePlayLoop(play, this, &gPlayerAnim_clink_op3_wait3, 0x9C);
this->av2.actionVar2 = 1;
} else if (this->av2.actionVar2 == 0) {
Player_ProcessAnimSfxList(this, D_808551BC);
if (LinkAnimation_OnFrame(&this->skelAnime, 240.0f)) {
this->actor.shape.shadowDraw = ActorShadow_DrawFeet;
}
}
}
static AnimSfxEntry D_808551C8[] = {
{ NA_SE_PL_LAND_LADDER, ANIMSFX_DATA(ANIMSFX_TYPE_1, 67) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_9, 84) },
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_9, 90) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_9, 96) },
};
void func_80852048(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimation_Update(play, &this->skelAnime);
Player_ProcessAnimSfxList(this, D_808551C8);
}
void func_80852080(PlayState* play, Player* this, CsCmdActorAction* arg2) {
Player_AnimReplacePlayOnceAdjusted(play, this, &gPlayerAnim_clink_demo_futtobi, 0x9D);
func_80832698(this, NA_SE_VO_LI_FALL_L);
}
void func_808520BC(PlayState* play, Player* this, CsCmdActorAction* arg2) {
f32 startX = arg2->startPos.x;
f32 startY = arg2->startPos.y;
f32 startZ = arg2->startPos.z;
f32 distX = (arg2->endPos.x - startX);
f32 distY = (arg2->endPos.y - startY);
f32 distZ = (arg2->endPos.z - startZ);
f32 sp4 = (f32)(play->csCtx.frames - arg2->startFrame) / (f32)(arg2->endFrame - arg2->startFrame);
this->actor.world.pos.x = distX * sp4 + startX;
this->actor.world.pos.y = distY * sp4 + startY;
this->actor.world.pos.z = distZ * sp4 + startZ;
}
static AnimSfxEntry D_808551D8[] = {
{ NA_SE_PL_BOUND, ANIMSFX_DATA(ANIMSFX_TYPE_2, 20) },
{ NA_SE_PL_BOUND, -ANIMSFX_DATA(ANIMSFX_TYPE_2, 30) },
};
void func_80852174(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_808520BC(play, this, arg2);
LinkAnimation_Update(play, &this->skelAnime);
Player_ProcessAnimSfxList(this, D_808551D8);
}
void func_808521B8(PlayState* play, Player* this, CsCmdActorAction* arg2) {
if (arg2 != NULL) {
func_808520BC(play, this, arg2);
}
LinkAnimation_Update(play, &this->skelAnime);
}
void func_808521F4(PlayState* play, Player* this, CsCmdActorAction* arg2) {
Player_AnimChangeOnceMorph(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_nwait, this->modelAnimType));
Player_ZeroSpeedXZ(this);
}
void func_80852234(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimation_Update(play, &this->skelAnime);
}
void func_8085225C(PlayState* play, Player* this, CsCmdActorAction* arg2) {
Player_AnimReplaceApplyFlags(play, this, 0x98);
}
void func_80852280(PlayState* play, Player* this, CsCmdActorAction* arg2) {
this->actor.draw = Player_Draw;
}
void func_80852298(PlayState* play, Player* this, CsCmdActorAction* arg2) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimReplaceNormalPlayLoopAdjusted(play, this, &gPlayerAnim_clink_demo_koutai_wait);
this->av2.actionVar2 = 1;
} else if (this->av2.actionVar2 == 0) {
if (LinkAnimation_OnFrame(&this->skelAnime, 10.0f)) {
func_80846720(play, this, 1);
}
}
}
static AnimSfxEntry D_808551E0[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 10) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 24) },
};
void func_80852328(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_80851F14(play, this, &gPlayerAnim_link_demo_furimuki2_wait, D_808551E0);
}
static AnimSfxEntry D_808551E8[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 15) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_8, 35) },
};
void func_80852358(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_80851F14(play, this, &gPlayerAnim_link_demo_nozokikomi_wait, D_808551E8);
}
void func_80852388(PlayState* play, Player* this, CsCmdActorAction* arg2) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
Player_AnimPlayLoopAdjusted(play, this, &gPlayerAnim_demo_link_twait);
this->av2.actionVar2 = 1;
}
if ((this->av2.actionVar2 != 0) && (play->csCtx.frames >= 900)) {
this->rightHandType = PLAYER_MODELTYPE_LH_OPEN;
} else {
this->rightHandType = PLAYER_MODELTYPE_RH_FF;
}
}
void func_80852414(PlayState* play, Player* this, LinkAnimationHeader* anim, AnimSfxEntry* arg3) {
func_80851294(play, this, anim);
if (this->av2.actionVar2 == 0) {
Player_ProcessAnimSfxList(this, arg3);
}
}
static AnimSfxEntry D_808551F0[] = {
{ 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 15) },
{ 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 33) },
};
void func_80852450(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_80852414(play, this, &gPlayerAnim_clink_demo_koutai_wait, D_808551F0);
}
static AnimSfxEntry D_808551F8[] = {
{ NA_SE_PL_KNOCK, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 78) },
};
void func_80852480(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_80852414(play, this, &gPlayerAnim_link_demo_kakeyori_wait, D_808551F8);
}
void func_808524B0(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_80837704(play, this);
}
void func_808524D0(PlayState* play, Player* this, CsCmdActorAction* arg2) {
sControlInput->press.button |= BTN_B;
Player_Action_80844E68(this, play);
}
void func_80852514(PlayState* play, Player* this, CsCmdActorAction* arg2) {
Player_Action_80844E68(this, play);
}
void func_80852544(PlayState* play, Player* this, CsCmdActorAction* arg2) {
}
void func_80852554(PlayState* play, Player* this, CsCmdActorAction* arg2) {
}
void func_80852564(PlayState* play, Player* this, CsCmdActorAction* arg2) {
this->stateFlags3 |= PLAYER_STATE3_MIDAIR;
this->linearVelocity = 2.0f;
this->actor.velocity.y = -1.0f;
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_back_downA);
func_80832698(this, NA_SE_VO_LI_FALL_L);
}
static void (*D_808551FC[])(Player* this, PlayState* play) = {
Player_Action_8084377C,
Player_Action_80843954,
Player_Action_80843A38,
};
void func_808525C0(PlayState* play, Player* this, CsCmdActorAction* arg2) {
D_808551FC[this->av2.actionVar2](this, play);
}
void func_80852608(PlayState* play, Player* this, CsCmdActorAction* arg2) {
func_80846720(play, this, 0);
Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_demo_return_to_past);
}
void func_80852648(PlayState* play, Player* this, CsCmdActorAction* arg2) {
LinkAnimation_Update(play, &this->skelAnime);
if (LinkAnimation_OnFrame(&this->skelAnime, 10.0f)) {
this->heldItemAction = this->itemAction = PLAYER_IA_NONE;
this->heldItemId = ITEM_NONE;
this->modelGroup = this->nextModelGroup = Player_ActionToModelGroup(this, PLAYER_IA_NONE);
this->leftHandDLists = gPlayerLeftHandOpenDLs;
// If MS sword is shuffled and not in the players inventory, then we need to unequip the current sword
// and set swordless flag to mimic Link having his weapon knocked out of his hand in the Ganon fight
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) {
Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_NONE);
gSaveContext.equips.buttonItems[0] = ITEM_NONE;
Flags_SetInfTable(INFTABLE_SWORDLESS);
return;
}
Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_MASTER);
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER;
Inventory_DeleteEquipment(play, EQUIP_TYPE_SWORD);
}
}
static LinkAnimationHeader* D_80855208[] = {
&gPlayerAnim_L_okarina_get,
&gPlayerAnim_om_get,
};
static Vec3s D_80855210[2][2] = {
{ { -200, 700, 100 }, { 800, 600, 800 } },
{ { -200, 500, 0 }, { 600, 400, 600 } },
};
void func_808526EC(PlayState* play, Player* this, CsCmdActorAction* arg2) {
static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
static Color_RGBA8 primColor = { 255, 255, 255, 0 };
static Color_RGBA8 envColor = { 0, 128, 128, 0 };
s32 age = gSaveContext.linkAge;
Vec3f sparklePos;
Vec3f sp34;
Vec3s* ptr;
func_80851294(play, this, D_80855208[age]);
if (this->rightHandType != PLAYER_MODELTYPE_RH_FF) {
this->rightHandType = PLAYER_MODELTYPE_RH_FF;
return;
}
ptr = D_80855210[gSaveContext.linkAge];
sp34.x = ptr[0].x + Rand_CenteredFloat(ptr[1].x);
sp34.y = ptr[0].y + Rand_CenteredFloat(ptr[1].y);
sp34.z = ptr[0].z + Rand_CenteredFloat(ptr[1].z);
SkinMatrix_Vec3fMtxFMultXYZ(&this->shieldMf, &sp34, &sparklePos);
EffectSsKiraKira_SpawnDispersed(play, &sparklePos, &zeroVec, &zeroVec, &primColor, &envColor, 600, -10);
}
void func_8085283C(PlayState* play, Player* this, CsCmdActorAction* arg2) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80852944(play, this, arg2);
} else if (this->av2.actionVar2 == 0) {
Item_Give(play, ITEM_SWORD_MASTER);
func_80846720(play, this, 0);
} else {
func_8084E988(this);
}
}
void func_808528C8(PlayState* play, Player* this, CsCmdActorAction* arg2) {
if (LinkAnimation_Update(play, &this->skelAnime)) {
func_8084285C(this, 0.0f, 99.0f, this->skelAnime.endFrame - 8.0f);
}
if (this->heldItemAction != PLAYER_IA_SWORD_MASTER) {
func_80846720(play, this, 1);
}
}
void func_80852944(PlayState* play, Player* this, CsCmdActorAction* arg2) {
if (func_808332B8(this)) {
func_80838F18(play, this);
func_80832340(play, this);
} else {
func_8083C148(this, play);
if (!Player_ActionChange_4(this, play)) {
Player_ActionChange_2(this, play);
}
}
this->csAction = 0;
this->unk_6AD = 0;
}
void func_808529D0(PlayState* play, Player* this, CsCmdActorAction* arg2) {
this->actor.world.pos.x = arg2->startPos.x;
this->actor.world.pos.y = arg2->startPos.y;
if ((play->sceneNum == SCENE_KOKIRI_FOREST) && !LINK_IS_ADULT) {
this->actor.world.pos.y -= 1.0f;
}
this->actor.world.pos.z = arg2->startPos.z;
this->yaw = this->actor.shape.rot.y = arg2->rot.y;
}
void func_80852A54(PlayState* play, Player* this, CsCmdActorAction* arg2) {
f32 dx = arg2->startPos.x - (s32)this->actor.world.pos.x;
f32 dy = arg2->startPos.y - (s32)this->actor.world.pos.y;
f32 dz = arg2->startPos.z - (s32)this->actor.world.pos.z;
f32 dist = sqrtf(SQ(dx) + SQ(dy) + SQ(dz));
s16 yawDiff = arg2->rot.y - this->actor.shape.rot.y;
if ((this->linearVelocity == 0.0f) && ((dist > 50.0f) || (ABS(yawDiff) > 0x4000))) {
func_808529D0(play, this, arg2);
}
this->skelAnime.moveFlags = 0;
Player_ZeroRootLimbYaw(this);
}
void func_80852B4C(PlayState* play, Player* this, CsCmdActorAction* arg2, struct_80854B18* arg3) {
if (arg3->type > 0) {
D_80854AA4[arg3->type](play, this, arg3->ptr);
} else if (arg3->type < 0) {
arg3->func(play, this, arg2);
}
if ((D_80858AA0 & 4) && !(this->skelAnime.moveFlags & 4)) {
this->skelAnime.morphTable[0].y /= this->ageProperties->unk_08;
D_80858AA0 = 0;
}
}
void func_80852C0C(PlayState* play, Player* this, s32 csAction) {
if ((csAction != 1) && (csAction != 8) && (csAction != 0x31) && (csAction != 7)) {
Player_DetachHeldActor(play, this);
}
}
void func_80852C50(PlayState* play, Player* this, CsCmdActorAction* arg2) {
CsCmdActorAction* linkCsAction = play->csCtx.linkAction;
s32 pad;
s32 sp24;
if (play->csCtx.state == CS_STATE_UNSKIPPABLE_INIT) {
func_8002DF54(play, NULL, 7);
this->cueId = 0;
Player_ZeroSpeedXZ(this);
return;
}
if (linkCsAction == NULL) {
this->actor.flags &= ~ACTOR_FLAG_ACTIVE;
return;
}
if (this->cueId != linkCsAction->action) {
sp24 = D_808547C4[linkCsAction->action];
if (sp24 >= 0) {
if ((sp24 == 3) || (sp24 == 4)) {
func_80852A54(play, this, linkCsAction);
} else {
func_808529D0(play, this, linkCsAction);
}
}
D_80858AA0 = this->skelAnime.moveFlags;
func_80832DBC(this);
osSyncPrintf("TOOL MODE=%d\n", sp24);
func_80852C0C(play, this, ABS(sp24));
func_80852B4C(play, this, linkCsAction, &D_80854B18[ABS(sp24)]);
this->av2.actionVar2 = 0;
this->av1.actionVar1 = 0;
this->cueId = linkCsAction->action;
}
sp24 = D_808547C4[this->cueId];
func_80852B4C(play, this, linkCsAction, &D_80854E50[ABS(sp24)]);
if (CVarGetInteger("gFixEyesOpenWhileSleeping", 0) && (play->csCtx.linkAction->action == 28 || play->csCtx.linkAction->action == 29)) {
this->skelAnime.jointTable[22].x = 8;
}
}
void Player_Action_CsAction(Player* this, PlayState* play) {
if (this->csAction != this->prevCsAction) {
D_80858AA0 = this->skelAnime.moveFlags;
func_80832DBC(this);
this->prevCsAction = this->csAction;
osSyncPrintf("DEMO MODE=%d\n", this->csAction);
func_80852C0C(play, this, this->csAction);
func_80852B4C(play, this, NULL, &D_80854B18[this->csAction]);
}
func_80852B4C(play, this, NULL, &D_80854E50[this->csAction]);
}
int Player_IsDroppingFish(PlayState* play) {
Player* this = GET_PLAYER(play);
return (Player_Action_8084EFC0 == this->actionFunc) && (this->itemAction == PLAYER_IA_BOTTLE_FISH);
}
s32 Player_StartFishing(PlayState* play) {
Player* this = GET_PLAYER(play);
func_80832564(play, this);
Player_UseItem(play, this, ITEM_FISHING_POLE);
return 1;
}
s32 func_80852F38(PlayState* play, Player* this) {
if (!Player_InBlockingCsMode(play, this) && (this->invincibilityTimer >= 0) && !func_8008F128(this) &&
!(this->stateFlags3 & PLAYER_STATE3_HOOKSHOT_TRAVELLING)) {
func_80832564(play, this);
Player_SetupAction(play, this, func_8084F308, 0);
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_re_dead_attack);
this->stateFlags2 |= PLAYER_STATE2_GRABBED_BY_ENEMY;
func_80832224(this);
func_80832698(this, NA_SE_VO_LI_HELD);
return true;
}
return false;
}
/**
* Tries to starts a cutscene action specified by `csAction`.
* A cutscene action will only start if player is not already in another form of cutscene.
*
* No actors will be halted over the duration of the cutscene action.
*
* @return true if successful starting a `csAction`, false if not
*/
s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction) {
Player* this = GET_PLAYER(play);
if (!Player_InBlockingCsMode(play, this)) {
func_80832564(play, this);
Player_SetupAction(play, this, Player_Action_CsAction, 0);
this->csAction = csAction;
this->csActor = actor;
func_80832224(this);
return true;
}
return false;
}
void func_80853080(Player* this, PlayState* play) {
Player_SetupAction(play, this, Player_Action_80840BC8, 1);
Player_AnimChangeOnceMorph(play, this, func_80833338(this));
this->yaw = this->actor.shape.rot.y;
}
s32 Player_InflictDamage(PlayState* play, s32 damage) {
return Player_InflictDamageModified(play, damage, true);
}
s32 Player_InflictDamageModified(PlayState* play, s32 damage, u8 modified) {
Player* this = GET_PLAYER(play);
if (!Player_InBlockingCsMode(play, this) && !func_80837B18_modified(play, this, damage, modified)) {
this->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY;
return 1;
}
return 0;
}
// Start talking with the given actor
void Player_StartTalking(PlayState* play, Actor* actor) {
Player* this = GET_PLAYER(play);
s32 pad;
if ((this->targetActor != NULL) || (actor == this->naviActor) ||
CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_NAVI_HAS_INFO)) {
actor->flags |= ACTOR_FLAG_PLAYER_TALKED_TO;
}
this->targetActor = actor;
this->exchangeItemId = EXCH_ITEM_NONE;
if (actor->textId == 0xFFFF) {
func_8002DF54(play, actor, 1);
actor->flags |= ACTOR_FLAG_PLAYER_TALKED_TO;
func_80832528(play, this);
} else {
if (this->actor.flags & ACTOR_FLAG_PLAYER_TALKED_TO) {
this->actor.textId = 0;
} else {
this->actor.flags |= ACTOR_FLAG_PLAYER_TALKED_TO;
this->actor.textId = actor->textId;
}
if (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) {
s32 sp24 = this->av2.actionVar2;
func_80832528(play, this);
func_8083A2F8(play, this);
this->av2.actionVar2 = sp24;
} else {
if (func_808332B8(this)) {
func_80836898(play, this, func_8083A2F8);
Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim_wait);
} else if ((actor->category != ACTORCAT_NPC) || (this->heldItemAction == PLAYER_IA_FISHING_POLE)) {
func_8083A2F8(play, this);
if (!func_8008E9C4(this)) {
if ((actor != this->naviActor) && (actor->xzDistToPlayer < 40.0f)) {
Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_normal_backspace);
} else {
Player_AnimPlayLoop(play, this, func_80833338(this));
}
}
} else {
func_80836898(play, this, func_8083A2F8);
Player_AnimPlayOnceAdjusted(play, this,
(actor->xzDistToPlayer < 40.0f) ? &gPlayerAnim_link_normal_backspace
: &gPlayerAnim_link_normal_talk_free);
}
if (this->skelAnime.animation == &gPlayerAnim_link_normal_backspace) {
Player_AnimReplaceApplyFlags(play, this, 0x19);
}
func_80832224(this);
}
this->stateFlags1 |= PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_IN_CUTSCENE;
}
if ((this->naviActor == this->targetActor) && ((this->targetActor->textId & 0xFF00) != 0x200)) {
this->naviActor->flags |= ACTOR_FLAG_PLAYER_TALKED_TO;
func_80835EA4(play, 0xB);
}
}