2022-03-21 21:51:23 -04:00
|
|
|
|
#include "global.h"
|
|
|
|
|
#include "vt.h"
|
|
|
|
|
|
|
|
|
|
#include "overlays/actors/ovl_Arms_Hook/z_arms_hook.h"
|
|
|
|
|
#include "overlays/actors/ovl_En_Part/z_en_part.h"
|
|
|
|
|
#include "objects/gameplay_keep/gameplay_keep.h"
|
|
|
|
|
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
|
|
|
|
|
#include "objects/object_bdoor/object_bdoor.h"
|
2022-05-13 18:43:55 -04:00
|
|
|
|
#include "soh/frame_interpolation.h"
|
2022-12-06 04:33:50 -05:00
|
|
|
|
#include "soh/Enhancements/enemyrandomizer.h"
|
2023-04-02 04:00:21 -04:00
|
|
|
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
2023-06-27 19:53:35 -04:00
|
|
|
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
2023-08-20 13:59:23 -04:00
|
|
|
|
#include "soh/Enhancements/nametag.h"
|
2023-06-27 19:53:35 -04:00
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
#include "soh/ActorDB.h"
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
2022-05-11 13:18:24 -04:00
|
|
|
|
#if defined(_MSC_VER) || defined(__GNUC__)
|
2022-03-21 21:51:23 -04:00
|
|
|
|
#include "textures/place_title_cards/g_pn_49.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_01.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_02.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_03.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_04.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_05.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_06.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_07.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_08.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_09.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_10.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_11.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_12.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_13.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_14.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_15.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_16.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_17.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_18.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_19.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_20.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_21.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_22.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_23.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_24.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_25.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_26.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_27.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_28.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_29.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_30.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_31.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_32.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_33.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_34.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_35.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_36.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_37.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_38.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_39.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_40.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_41.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_42.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_43.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_44.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_45.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_46.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_47.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_48.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_50.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_51.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_52.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_53.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_54.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_55.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_56.h"
|
|
|
|
|
#include "textures/place_title_cards/g_pn_57.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static CollisionPoly* sCurCeilingPoly;
|
|
|
|
|
static s32 sCurCeilingBgId;
|
|
|
|
|
|
2022-12-20 23:32:01 -05:00
|
|
|
|
// Used for animating the ice trap on the "Get Item" model.
|
|
|
|
|
f32 iceTrapScale;
|
|
|
|
|
|
2023-04-07 15:54:26 -04:00
|
|
|
|
// For Link's voice pitch SFX modifier
|
|
|
|
|
static f32 freqMultiplier = 1;
|
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
void ActorShape_Init(ActorShape* shape, f32 yOffset, ActorShadowFunc shadowDraw, f32 shadowScale) {
|
|
|
|
|
shape->yOffset = yOffset;
|
|
|
|
|
shape->shadowDraw = shadowDraw;
|
|
|
|
|
shape->shadowScale = shadowScale;
|
|
|
|
|
shape->shadowAlpha = 255;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void ActorShadow_Draw(Actor* actor, Lights* lights, PlayState* play, Gfx* dlist, Color_RGBA8* color) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 temp1;
|
|
|
|
|
f32 temp2;
|
|
|
|
|
MtxF sp60;
|
|
|
|
|
|
|
|
|
|
if (actor->floorPoly != NULL) {
|
|
|
|
|
temp1 = actor->world.pos.y - actor->floorHeight;
|
|
|
|
|
|
|
|
|
|
if (temp1 >= -50.0f && temp1 < 500.0f) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-29 18:29:36 -05:00
|
|
|
|
POLY_OPA_DISP = Gfx_SetupDL(POLY_OPA_DISP, 0x2C);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
gDPSetCombineLERP(POLY_OPA_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, COMBINED, 0, 0, 0,
|
|
|
|
|
COMBINED);
|
|
|
|
|
|
|
|
|
|
temp1 = (temp1 < 0.0f) ? 0.0f : ((temp1 > 150.0f) ? 150.0f : temp1);
|
|
|
|
|
temp2 = 1.0f - (temp1 * (1.0f / 350));
|
|
|
|
|
|
|
|
|
|
if (color != NULL) {
|
|
|
|
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, color->r, color->g, color->b,
|
|
|
|
|
(u32)(actor->shape.shadowAlpha * temp2) & 0xFF);
|
|
|
|
|
} else {
|
|
|
|
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 0, 0, (u32)(actor->shape.shadowAlpha * temp2) & 0xFF);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func_80038A28(actor->floorPoly, actor->world.pos.x, actor->floorHeight, actor->world.pos.z, &sp60);
|
|
|
|
|
Matrix_Put(&sp60);
|
|
|
|
|
|
|
|
|
|
if (dlist != gCircleShadowDL) {
|
|
|
|
|
Matrix_RotateY(actor->shape.rot.y * (M_PI / 0x8000), MTXMODE_APPLY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
temp2 = (1.0f - (temp1 * (1.0f / 350))) * actor->shape.shadowScale;
|
|
|
|
|
Matrix_Scale(actor->scale.x * temp2, 1.0f, actor->scale.z * temp2, MTXMODE_APPLY);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_MTX_MODELVIEW | G_MTX_LOAD);
|
|
|
|
|
gSPDisplayList(POLY_OPA_DISP++, dlist);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void ActorShadow_DrawCircle(Actor* actor, Lights* lights, PlayState* play) {
|
|
|
|
|
ActorShadow_Draw(actor, lights, play, gCircleShadowDL, NULL);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void ActorShadow_DrawWhiteCircle(Actor* actor, Lights* lights, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
static Color_RGBA8 white = { 255, 255, 255, 255 };
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
ActorShadow_Draw(actor, lights, play, gCircleShadowDL, &white);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void ActorShadow_DrawHorse(Actor* actor, Lights* lights, PlayState* play) {
|
|
|
|
|
ActorShadow_Draw(actor, lights, play, gHorseShadowDL, NULL);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void ActorShadow_DrawFoot(PlayState* play, Light* light, MtxF* arg2, s32 arg3, f32 arg4, f32 arg5, f32 arg6) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 pad1;
|
|
|
|
|
f32 sp58;
|
|
|
|
|
s32 pad2[2];
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 0, 0,
|
|
|
|
|
(u32)(((arg3 * 0.00005f) > 1.0f ? 1.0f : (arg3 * 0.00005f)) * arg4) & 0xFF);
|
|
|
|
|
|
|
|
|
|
sp58 = Math_FAtan2F(light->l.dir[0], light->l.dir[2]);
|
|
|
|
|
arg6 *= (4.5f - (light->l.dir[1] * 0.035f));
|
|
|
|
|
arg6 = (arg6 < 1.0f) ? 1.0f : arg6;
|
|
|
|
|
Matrix_Put(arg2);
|
|
|
|
|
Matrix_RotateY(sp58, MTXMODE_APPLY);
|
|
|
|
|
Matrix_Scale(arg5, 1.0f, arg5 * arg6, MTXMODE_APPLY);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_MTX_MODELVIEW | G_MTX_LOAD);
|
|
|
|
|
gSPDisplayList(POLY_OPA_DISP++, gFootShadowDL);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void ActorShadow_DrawFeet(Actor* actor, Lights* lights, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 distToFloor = actor->world.pos.y - actor->floorHeight;
|
|
|
|
|
|
|
|
|
|
if (distToFloor > 20.0f) {
|
|
|
|
|
f32 shadowScale = actor->shape.shadowScale;
|
|
|
|
|
u8 shadowAlpha = actor->shape.shadowAlpha;
|
|
|
|
|
f32 alphaRatio;
|
|
|
|
|
|
|
|
|
|
actor->shape.shadowScale *= 0.3f;
|
|
|
|
|
alphaRatio = (distToFloor - 20.0f) * 0.02f;
|
|
|
|
|
actor->shape.shadowAlpha = (f32)actor->shape.shadowAlpha * CLAMP_MAX(alphaRatio, 1.0f);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
ActorShadow_DrawCircle(actor, lights, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->shape.shadowScale = shadowScale;
|
|
|
|
|
actor->shape.shadowAlpha = shadowAlpha;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (distToFloor < 200.0f) {
|
|
|
|
|
MtxF floorMtx;
|
|
|
|
|
f32 floorHeight[2]; // One for each foot
|
|
|
|
|
f32 distToFloor;
|
|
|
|
|
f32 shadowAlpha;
|
|
|
|
|
f32 shadowScaleX;
|
|
|
|
|
f32 shadowScaleZ;
|
|
|
|
|
Light* lightPtr;
|
|
|
|
|
s32 lightNum;
|
|
|
|
|
s32 lightNumMax;
|
|
|
|
|
s32 i;
|
|
|
|
|
s32 j;
|
|
|
|
|
s32 numLights = lights->numLights - 2;
|
|
|
|
|
Light* firstLightPtr = &lights->l.l[0];
|
|
|
|
|
Vec3f* feetPosPtr = actor->shape.feetPos;
|
|
|
|
|
f32* floorHeightPtr = floorHeight;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-29 18:29:36 -05:00
|
|
|
|
POLY_OPA_DISP = Gfx_SetupDL(POLY_OPA_DISP, 0x2C);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
actor->shape.feetFloorFlags = 0;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
|
feetPosPtr->y += 50.0f;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
*floorHeightPtr = func_800BFCB8(play, &floorMtx, feetPosPtr);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
feetPosPtr->y -= 50.0f;
|
|
|
|
|
actor->shape.feetFloorFlags <<= 1;
|
|
|
|
|
distToFloor = feetPosPtr->y - *floorHeightPtr;
|
|
|
|
|
|
|
|
|
|
if ((-1.0f <= distToFloor) && (distToFloor < 500.0f)) {
|
|
|
|
|
if (distToFloor <= 0.0f) {
|
|
|
|
|
actor->shape.feetFloorFlags++;
|
|
|
|
|
}
|
|
|
|
|
distToFloor = CLAMP_MAX(distToFloor, 30.0f);
|
|
|
|
|
shadowAlpha = (f32)actor->shape.shadowAlpha * (1.0f - (distToFloor * (1.0f / 30.0f)));
|
|
|
|
|
distToFloor = CLAMP_MAX(distToFloor, 30.0f);
|
|
|
|
|
shadowScaleZ = 1.0f - (distToFloor * (1.0f / (30.0f + 40.0f)));
|
|
|
|
|
shadowScaleX = shadowScaleZ * actor->shape.shadowScale * actor->scale.x;
|
|
|
|
|
lightNumMax = 0;
|
|
|
|
|
lightPtr = firstLightPtr;
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < numLights; j++) {
|
|
|
|
|
if (lightPtr->l.dir[1] > 0) {
|
|
|
|
|
lightNum =
|
|
|
|
|
(lightPtr->l.col[0] + lightPtr->l.col[1] + lightPtr->l.col[2]) * ABS(lightPtr->l.dir[1]);
|
|
|
|
|
if (lightNum > 0) {
|
|
|
|
|
lightNumMax += lightNum;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
ActorShadow_DrawFoot(play, lightPtr, &floorMtx, lightNum, shadowAlpha, shadowScaleX,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
shadowScaleZ);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lightPtr++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < 2; j++) {
|
|
|
|
|
if (lightPtr->l.dir[1] > 0) {
|
|
|
|
|
lightNum =
|
|
|
|
|
((lightPtr->l.col[0] + lightPtr->l.col[1] + lightPtr->l.col[2]) * ABS(lightPtr->l.dir[1])) -
|
|
|
|
|
(lightNumMax * 8);
|
|
|
|
|
if (lightNum > 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
ActorShadow_DrawFoot(play, lightPtr, &floorMtx, lightNum, shadowAlpha, shadowScaleX,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
shadowScaleZ);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lightPtr++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
feetPosPtr++;
|
|
|
|
|
floorHeightPtr++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(actor->bgCheckFlags & 1)) {
|
|
|
|
|
actor->shape.feetFloorFlags = 0;
|
|
|
|
|
} else if (actor->shape.feetFloorFlags == 3) {
|
|
|
|
|
f32 footDistY = actor->shape.feetPos[FOOT_LEFT].y - actor->shape.feetPos[FOOT_RIGHT].y;
|
|
|
|
|
|
|
|
|
|
if ((floorHeight[0] + footDistY) < (floorHeight[1] - footDistY)) {
|
|
|
|
|
actor->shape.feetFloorFlags = 2;
|
|
|
|
|
} else {
|
|
|
|
|
actor->shape.feetFloorFlags = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_SetFeetPos(Actor* actor, s32 limbIndex, s32 leftFootIndex, Vec3f* leftFootPos, s32 rightFootIndex,
|
|
|
|
|
Vec3f* rightFootPos) {
|
|
|
|
|
if (limbIndex == leftFootIndex) {
|
|
|
|
|
Matrix_MultVec3f(leftFootPos, &actor->shape.feetPos[FOOT_LEFT]);
|
|
|
|
|
} else if (limbIndex == rightFootIndex) {
|
|
|
|
|
Matrix_MultVec3f(rightFootPos, &actor->shape.feetPos[FOOT_RIGHT]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002BE04(PlayState* play, Vec3f* arg1, Vec3f* arg2, f32* arg3) {
|
|
|
|
|
SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, arg1, arg2, arg3);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*arg3 = (*arg3 < 1.0f) ? 1.0f : (1.0f / *arg3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
/* 0x00 */ Color_RGBA8 inner;
|
|
|
|
|
/* 0x04 */ Color_RGBA8 outer;
|
|
|
|
|
} NaviColor; // size = 0x8
|
|
|
|
|
|
|
|
|
|
NaviColor sNaviColorList[] = {
|
|
|
|
|
{ { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } },
|
|
|
|
|
{ { 255, 255, 255, 255 }, { 0, 0, 255, 0 } }, { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } },
|
|
|
|
|
{ { 150, 150, 255, 255 }, { 150, 150, 255, 0 } }, { { 255, 255, 0, 255 }, { 200, 155, 0, 0 } },
|
|
|
|
|
{ { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } },
|
|
|
|
|
{ { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, { { 255, 255, 0, 255 }, { 200, 155, 0, 0 } },
|
|
|
|
|
{ { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } },
|
|
|
|
|
{ { 0, 255, 0, 255 }, { 0, 255, 0, 0 } },
|
|
|
|
|
};
|
|
|
|
|
|
2022-12-08 23:24:39 -05:00
|
|
|
|
static Color_RGBA8 defaultIdlePrimaryColor = { 255, 255, 255, 255 };
|
|
|
|
|
static Color_RGBA8 defaultIdleSecondaryColor = { 0, 0, 255, 0 };
|
|
|
|
|
static Color_RGBA8 defaultNPCPrimaryColor = { 150, 150, 255, 255 };
|
|
|
|
|
static Color_RGBA8 defaultNPCSecondaryColor = { 150, 150, 255, 0 };
|
|
|
|
|
static Color_RGBA8 defaultEnemyPrimaryColor = { 255, 255, 0, 255 };
|
|
|
|
|
static Color_RGBA8 defaultEnemySecondaryColor = { 200, 155, 0, 0 };
|
|
|
|
|
static Color_RGBA8 defaultPropsPrimaryColor = { 0, 255, 0, 255 };
|
|
|
|
|
static Color_RGBA8 defaultPropsSecondaryColor = { 0, 255, 0, 0 };
|
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
// unused
|
|
|
|
|
Gfx D_80115FF0[] = {
|
|
|
|
|
gsSPEndDisplayList(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void func_8002BE64(TargetContext* targetCtx, s32 index, f32 arg2, f32 arg3, f32 arg4) {
|
|
|
|
|
targetCtx->arr_50[index].pos.x = arg2;
|
|
|
|
|
targetCtx->arr_50[index].pos.y = arg3;
|
|
|
|
|
targetCtx->arr_50[index].pos.z = arg4;
|
|
|
|
|
targetCtx->arr_50[index].unk_0C = targetCtx->unk_44;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002BE98(TargetContext* targetCtx, s32 actorCategory, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
TargetContextEntry* entry;
|
|
|
|
|
NaviColor* naviColor;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Math_Vec3f_Copy(&targetCtx->targetCenterPos, &play->view.eye);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
targetCtx->unk_44 = 500.0f;
|
|
|
|
|
targetCtx->unk_48 = 0x100;
|
|
|
|
|
|
|
|
|
|
naviColor = &sNaviColorList[actorCategory];
|
|
|
|
|
|
|
|
|
|
entry = &targetCtx->arr_50[0];
|
|
|
|
|
for (i = 0; i < ARRAY_COUNT(targetCtx->arr_50); i++) {
|
|
|
|
|
func_8002BE64(targetCtx, i, 0.0f, 0.0f, 0.0f);
|
|
|
|
|
entry->color.r = naviColor->inner.r;
|
|
|
|
|
entry->color.g = naviColor->inner.g;
|
|
|
|
|
entry->color.b = naviColor->inner.b;
|
|
|
|
|
entry++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002BF60(TargetContext* targetCtx, Actor* actor, s32 actorCategory, PlayState* play) {
|
2024-04-25 22:41:55 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_COSMETIC("Navi.IdlePrimary.Changed"), 0)) {
|
|
|
|
|
sNaviColorList[ACTORCAT_PLAYER].inner = CVarGetColor(CVAR_COSMETIC("Navi.IdlePrimary.Value"), defaultIdlePrimaryColor);
|
2022-05-21 13:16:28 -04:00
|
|
|
|
} else {
|
2022-12-08 23:24:39 -05:00
|
|
|
|
sNaviColorList[ACTORCAT_PLAYER].inner = defaultIdlePrimaryColor;
|
|
|
|
|
}
|
2024-04-25 22:41:55 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_COSMETIC("Navi.IdleSecondary.Changed"), 0)) {
|
|
|
|
|
sNaviColorList[ACTORCAT_PLAYER].outer = CVarGetColor(CVAR_COSMETIC("Navi.IdleSecondary.Value"), defaultIdleSecondaryColor);
|
2022-12-08 23:24:39 -05:00
|
|
|
|
} else {
|
|
|
|
|
sNaviColorList[ACTORCAT_PLAYER].outer = defaultIdleSecondaryColor;
|
2022-04-26 18:33:18 -04:00
|
|
|
|
}
|
2022-05-21 13:16:28 -04:00
|
|
|
|
|
2024-04-25 22:41:55 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_COSMETIC("Navi.NPCPrimary.Changed"), 0)) {
|
|
|
|
|
sNaviColorList[ACTORCAT_NPC].inner = CVarGetColor(CVAR_COSMETIC("Navi.NPCPrimary.Value"), defaultNPCPrimaryColor);
|
2022-12-08 23:24:39 -05:00
|
|
|
|
} else {
|
|
|
|
|
sNaviColorList[ACTORCAT_NPC].inner = defaultNPCPrimaryColor;
|
|
|
|
|
}
|
2024-04-25 22:41:55 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_COSMETIC("Navi.NPCSecondary.Changed"), 0)) {
|
|
|
|
|
sNaviColorList[ACTORCAT_NPC].outer = CVarGetColor(CVAR_COSMETIC("Navi.NPCSecondary.Value"), defaultNPCSecondaryColor);
|
2022-12-08 23:24:39 -05:00
|
|
|
|
} else {
|
|
|
|
|
sNaviColorList[ACTORCAT_NPC].outer = defaultNPCSecondaryColor;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-25 22:41:55 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_COSMETIC("Navi.EnemyPrimary.Changed"), 0)) {
|
|
|
|
|
sNaviColorList[ACTORCAT_ENEMY].inner = CVarGetColor(CVAR_COSMETIC("Navi.EnemyPrimary.Value"), defaultEnemyPrimaryColor);
|
|
|
|
|
sNaviColorList[ACTORCAT_BOSS].inner = CVarGetColor(CVAR_COSMETIC("Navi.EnemyPrimary.Value"), defaultEnemyPrimaryColor);
|
2022-12-08 23:24:39 -05:00
|
|
|
|
} else {
|
|
|
|
|
sNaviColorList[ACTORCAT_ENEMY].inner = defaultEnemyPrimaryColor;
|
|
|
|
|
sNaviColorList[ACTORCAT_BOSS].inner = defaultEnemyPrimaryColor;
|
|
|
|
|
}
|
2024-04-25 22:41:55 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_COSMETIC("Navi.EnemySecondary.Changed"), 0)) {
|
|
|
|
|
sNaviColorList[ACTORCAT_ENEMY].outer = CVarGetColor(CVAR_COSMETIC("Navi.EnemySecondary.Value"), defaultEnemySecondaryColor);
|
|
|
|
|
sNaviColorList[ACTORCAT_BOSS].outer = CVarGetColor(CVAR_COSMETIC("Navi.EnemySecondary.Value"), defaultEnemySecondaryColor);
|
2022-12-08 23:24:39 -05:00
|
|
|
|
} else {
|
|
|
|
|
sNaviColorList[ACTORCAT_ENEMY].outer = defaultEnemySecondaryColor;
|
|
|
|
|
sNaviColorList[ACTORCAT_BOSS].outer = defaultEnemySecondaryColor;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-25 22:41:55 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_COSMETIC("Navi.PropsPrimary.Changed"), 0)) {
|
|
|
|
|
sNaviColorList[ACTORCAT_PROP].inner = CVarGetColor(CVAR_COSMETIC("Navi.PropsPrimary.Value"), defaultPropsPrimaryColor);
|
2022-12-08 23:24:39 -05:00
|
|
|
|
} else {
|
|
|
|
|
sNaviColorList[ACTORCAT_PROP].inner = defaultPropsPrimaryColor;
|
|
|
|
|
}
|
2024-04-25 22:41:55 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_COSMETIC("Navi.PropsSecondary.Changed"), 0)) {
|
|
|
|
|
sNaviColorList[ACTORCAT_PROP].outer = CVarGetColor(CVAR_COSMETIC("Navi.PropsSecondary.Value"), defaultPropsSecondaryColor);
|
2022-12-08 23:24:39 -05:00
|
|
|
|
} else {
|
|
|
|
|
sNaviColorList[ACTORCAT_PROP].outer = defaultPropsSecondaryColor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NaviColor* naviColor = &sNaviColorList[actorCategory];
|
2022-03-21 21:51:23 -04:00
|
|
|
|
targetCtx->naviRefPos.x = actor->focus.pos.x;
|
|
|
|
|
targetCtx->naviRefPos.y = actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y);
|
|
|
|
|
targetCtx->naviRefPos.z = actor->focus.pos.z;
|
|
|
|
|
targetCtx->naviInner.r = naviColor->inner.r;
|
|
|
|
|
targetCtx->naviInner.g = naviColor->inner.g;
|
|
|
|
|
targetCtx->naviInner.b = naviColor->inner.b;
|
|
|
|
|
targetCtx->naviInner.a = naviColor->inner.a;
|
|
|
|
|
targetCtx->naviOuter.r = naviColor->outer.r;
|
|
|
|
|
targetCtx->naviOuter.g = naviColor->outer.g;
|
|
|
|
|
targetCtx->naviOuter.b = naviColor->outer.b;
|
|
|
|
|
targetCtx->naviOuter.a = naviColor->outer.a;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002C0C0(TargetContext* targetCtx, Actor* actor, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
targetCtx->arrowPointedActor = NULL;
|
|
|
|
|
targetCtx->targetedActor = NULL;
|
|
|
|
|
targetCtx->unk_40 = 0.0f;
|
|
|
|
|
targetCtx->unk_8C = NULL;
|
|
|
|
|
targetCtx->bgmEnemy = NULL;
|
|
|
|
|
targetCtx->unk_4B = 0;
|
|
|
|
|
targetCtx->unk_4C = 0;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002BF60(targetCtx, actor, actor->category, play);
|
|
|
|
|
func_8002BE98(targetCtx, actor->category, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002C124(TargetContext* targetCtx, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor* actor = targetCtx->targetedActor;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (targetCtx->unk_48 != 0) {
|
|
|
|
|
TargetContextEntry* entry;
|
|
|
|
|
Player* player;
|
|
|
|
|
s16 spCE;
|
|
|
|
|
f32 temp1;
|
|
|
|
|
Vec3f spBC;
|
|
|
|
|
s32 spB8;
|
|
|
|
|
f32 spB4;
|
|
|
|
|
s32 spB0;
|
|
|
|
|
s32 spAC;
|
|
|
|
|
f32 var1;
|
|
|
|
|
f32 var2;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
2022-05-13 18:43:55 -04:00
|
|
|
|
FrameInterpolation_RecordOpenChild(actor, 0);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
spCE = 0xFF;
|
|
|
|
|
var1 = 1.0f;
|
|
|
|
|
|
|
|
|
|
if (targetCtx->unk_4B != 0) {
|
|
|
|
|
spB8 = 1;
|
|
|
|
|
} else {
|
|
|
|
|
spB8 = 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actor != NULL) {
|
|
|
|
|
Math_Vec3f_Copy(&targetCtx->targetCenterPos, &actor->focus.pos);
|
|
|
|
|
var1 = (500.0f - targetCtx->unk_44) / 420.0f;
|
|
|
|
|
} else {
|
|
|
|
|
targetCtx->unk_48 -= 120;
|
|
|
|
|
if (targetCtx->unk_48 < 0) {
|
|
|
|
|
targetCtx->unk_48 = 0;
|
|
|
|
|
}
|
|
|
|
|
spCE = targetCtx->unk_48;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002BE04(play, &targetCtx->targetCenterPos, &spBC, &spB4);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
spBC.x = (160 * (spBC.x * spB4)) * var1;
|
|
|
|
|
spBC.x = CLAMP(spBC.x, -320.0f, 320.0f);
|
|
|
|
|
|
|
|
|
|
spBC.y = (120 * (spBC.y * spB4)) * var1;
|
|
|
|
|
spBC.y = CLAMP(spBC.y, -240.0f, 240.0f);
|
|
|
|
|
|
|
|
|
|
spBC.z = spBC.z * var1;
|
|
|
|
|
|
|
|
|
|
targetCtx->unk_4C--;
|
|
|
|
|
if (targetCtx->unk_4C < 0) {
|
|
|
|
|
targetCtx->unk_4C = 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func_8002BE64(targetCtx, targetCtx->unk_4C, spBC.x, spBC.y, spBC.z);
|
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
if ((!(player->stateFlags1 & PLAYER_STATE1_TEXT_ON_SCREEN)) || (actor != player->unk_664)) {
|
2022-11-29 18:29:36 -05:00
|
|
|
|
OVERLAY_DISP = Gfx_SetupDL(OVERLAY_DISP, 0x39);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
for (spB0 = 0, spAC = targetCtx->unk_4C; spB0 < spB8; spB0++, spAC = (spAC + 1) % 3) {
|
|
|
|
|
entry = &targetCtx->arr_50[spAC];
|
|
|
|
|
|
|
|
|
|
if (entry->unk_0C < 500.0f) {
|
|
|
|
|
if (entry->unk_0C <= 120.0f) {
|
|
|
|
|
var2 = 0.15f;
|
|
|
|
|
} else {
|
|
|
|
|
var2 = ((entry->unk_0C - 120.0f) * 0.001f) + 0.15f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrix_Translate(entry->pos.x, entry->pos.y, 0.0f, MTXMODE_NEW);
|
|
|
|
|
Matrix_Scale(var2, 0.15f, 1.0f, MTXMODE_APPLY);
|
|
|
|
|
|
|
|
|
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, entry->color.r, entry->color.g, entry->color.b, (u8)spCE);
|
|
|
|
|
|
|
|
|
|
Matrix_RotateZ((targetCtx->unk_4B & 0x7F) * (M_PI / 64), MTXMODE_APPLY);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
|
Matrix_RotateZ(M_PI / 2, MTXMODE_APPLY);
|
|
|
|
|
Matrix_Push();
|
|
|
|
|
Matrix_Translate(entry->unk_0C, entry->unk_0C, 0.0f, MTXMODE_APPLY);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPMatrix(OVERLAY_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_MTX_MODELVIEW | G_MTX_LOAD);
|
|
|
|
|
gSPDisplayList(OVERLAY_DISP++, gZTargetLockOnTriangleDL);
|
|
|
|
|
Matrix_Pop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
spCE -= 0xFF / 3;
|
|
|
|
|
if (spCE < 0) {
|
|
|
|
|
spCE = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-13 18:43:55 -04:00
|
|
|
|
FrameInterpolation_RecordCloseChild();
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actor = targetCtx->unk_94;
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if ((actor != NULL) && !(actor->flags & ACTOR_FLAG_NO_LOCKON)) {
|
2022-05-13 18:43:55 -04:00
|
|
|
|
FrameInterpolation_RecordOpenChild(actor, 1);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
NaviColor* naviColor = &sNaviColorList[actor->category];
|
|
|
|
|
|
2022-11-29 18:29:36 -05:00
|
|
|
|
POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 0x7);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
Matrix_Translate(actor->focus.pos.x, actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y) + 17.0f,
|
|
|
|
|
actor->focus.pos.z, MTXMODE_NEW);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Matrix_RotateY((f32)((u16)(play->gameplayFrames * 3000)) * (M_PI / 0x8000), MTXMODE_APPLY);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Matrix_Scale((iREG(27) + 35) / 1000.0f, (iREG(28) + 60) / 1000.0f, (iREG(29) + 50) / 1000.0f, MTXMODE_APPLY);
|
|
|
|
|
|
|
|
|
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, naviColor->inner.r, naviColor->inner.g, naviColor->inner.b, 255);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_MTX_MODELVIEW | G_MTX_LOAD);
|
|
|
|
|
gSPDisplayList(POLY_XLU_DISP++, gZTargetArrowDL);
|
2022-05-13 18:43:55 -04:00
|
|
|
|
FrameInterpolation_RecordCloseChild();
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002C7BC(TargetContext* targetCtx, Player* player, Actor* actorArg, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 pad;
|
|
|
|
|
Actor* unkActor;
|
|
|
|
|
s32 actorCategory;
|
|
|
|
|
Vec3f sp50;
|
|
|
|
|
f32 sp4C;
|
|
|
|
|
f32 temp1;
|
|
|
|
|
f32 temp2;
|
|
|
|
|
f32 temp3;
|
|
|
|
|
f32 temp4;
|
|
|
|
|
f32 temp5;
|
|
|
|
|
f32 temp6;
|
|
|
|
|
s32 lockOnSfxId;
|
|
|
|
|
|
|
|
|
|
unkActor = NULL;
|
|
|
|
|
|
|
|
|
|
if ((player->unk_664 != NULL) && (player->unk_84B[player->unk_846] == 2)) {
|
|
|
|
|
targetCtx->unk_94 = NULL;
|
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80032AF0(play, &play->actorCtx, &unkActor, player);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
targetCtx->unk_94 = unkActor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (targetCtx->unk_8C != NULL) {
|
|
|
|
|
unkActor = targetCtx->unk_8C;
|
|
|
|
|
targetCtx->unk_8C = NULL;
|
|
|
|
|
} else if (actorArg != NULL) {
|
|
|
|
|
unkActor = actorArg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unkActor != NULL) {
|
|
|
|
|
actorCategory = unkActor->category;
|
|
|
|
|
} else {
|
|
|
|
|
actorCategory = player->actor.category;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((unkActor != targetCtx->arrowPointedActor) || (actorCategory != targetCtx->activeCategory)) {
|
|
|
|
|
targetCtx->arrowPointedActor = unkActor;
|
|
|
|
|
targetCtx->activeCategory = actorCategory;
|
|
|
|
|
targetCtx->unk_40 = 1.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unkActor == NULL) {
|
|
|
|
|
unkActor = &player->actor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Math_StepToF(&targetCtx->unk_40, 0.0f, 0.25f) == 0) {
|
|
|
|
|
temp1 = 0.25f / targetCtx->unk_40;
|
|
|
|
|
temp2 = unkActor->world.pos.x - targetCtx->naviRefPos.x;
|
|
|
|
|
temp3 = (unkActor->world.pos.y + (unkActor->targetArrowOffset * unkActor->scale.y)) - targetCtx->naviRefPos.y;
|
|
|
|
|
temp4 = unkActor->world.pos.z - targetCtx->naviRefPos.z;
|
|
|
|
|
targetCtx->naviRefPos.x += temp2 * temp1;
|
|
|
|
|
targetCtx->naviRefPos.y += temp3 * temp1;
|
|
|
|
|
targetCtx->naviRefPos.z += temp4 * temp1;
|
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002BF60(targetCtx, unkActor, actorCategory, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((actorArg != NULL) && (targetCtx->unk_4B == 0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002BE04(play, &actorArg->focus.pos, &sp50, &sp4C);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (((sp50.z <= 0.0f) || (1.0f <= fabsf(sp50.x * sp4C))) || (1.0f <= fabsf(sp50.y * sp4C))) {
|
|
|
|
|
actorArg = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actorArg != NULL) {
|
|
|
|
|
if (actorArg != targetCtx->targetedActor) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002BE98(targetCtx, actorArg->category, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
targetCtx->targetedActor = actorArg;
|
|
|
|
|
|
|
|
|
|
if (actorArg->id == ACTOR_EN_BOOM) {
|
|
|
|
|
targetCtx->unk_48 = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-30 15:05:04 -04:00
|
|
|
|
lockOnSfxId = CHECK_FLAG_ALL(actorArg->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE) ? NA_SE_SY_LOCK_ON
|
2022-03-21 21:51:23 -04:00
|
|
|
|
: NA_SE_SY_LOCK_ON_HUMAN;
|
|
|
|
|
func_80078884(lockOnSfxId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
targetCtx->targetCenterPos.x = actorArg->world.pos.x;
|
|
|
|
|
targetCtx->targetCenterPos.y = actorArg->world.pos.y - (actorArg->shape.yOffset * actorArg->scale.y);
|
|
|
|
|
targetCtx->targetCenterPos.z = actorArg->world.pos.z;
|
|
|
|
|
|
|
|
|
|
if (targetCtx->unk_4B == 0) {
|
|
|
|
|
temp5 = (500.0f - targetCtx->unk_44) * 3.0f;
|
|
|
|
|
temp6 = (temp5 < 30.0f) ? 30.0f : ((100.0f < temp5) ? 100.0f : temp5);
|
|
|
|
|
if (Math_StepToF(&targetCtx->unk_44, 80.0f, temp6) != 0) {
|
|
|
|
|
targetCtx->unk_4B++;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
targetCtx->unk_4B = (targetCtx->unk_4B + 3) | 0x80;
|
|
|
|
|
targetCtx->unk_44 = 120.0f;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
targetCtx->targetedActor = NULL;
|
|
|
|
|
Math_StepToF(&targetCtx->unk_44, 500.0f, 80.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests if current scene switch flag is set.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Flags_GetSwitch(PlayState* play, s32 flag) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (flag < 0x20) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
return play->actorCtx.flags.swch & (1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
return play->actorCtx.flags.tempSwch & (1 << (flag - 0x20));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets current scene switch flag.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Flags_SetSwitch(PlayState* play, s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOff = !Flags_GetSwitch(play, flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (flag < 0x20) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.swch |= (1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.tempSwch |= (1 << (flag - 0x20));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOff) {
|
|
|
|
|
LUSLOG_INFO("Switch Flag Set - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnSceneFlagSet(play->sceneNum, FLAG_SCENE_SWITCH, flag);
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Unsets current scene switch flag.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Flags_UnsetSwitch(PlayState* play, s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOn = Flags_GetSwitch(play, flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (flag < 0x20) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.swch &= ~(1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.tempSwch &= ~(1 << (flag - 0x20));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOn) {
|
|
|
|
|
LUSLOG_INFO("Switch Flag Unset - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnSceneFlagUnset(play->sceneNum, FLAG_SCENE_SWITCH, flag);
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-08-16 21:53:28 -04:00
|
|
|
|
* Tests if unknown flag is set.
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Flags_GetUnknown(PlayState* play, s32 flag) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (flag < 0x20) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
return play->actorCtx.flags.unk0 & (1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
return play->actorCtx.flags.unk1 & (1 << (flag - 0x20));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-08-16 21:53:28 -04:00
|
|
|
|
* Sets unknown flag.
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Flags_SetUnknown(PlayState* play, s32 flag) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (flag < 0x20) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.unk0 |= (1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.unk1 |= (1 << (flag - 0x20));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-08-16 21:53:28 -04:00
|
|
|
|
* Unsets unknown flag.
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Flags_UnsetUnknown(PlayState* play, s32 flag) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (flag < 0x20) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.unk0 &= ~(1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.unk1 &= ~(1 << (flag - 0x20));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests if current scene chest flag is set.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Flags_GetTreasure(PlayState* play, s32 flag) {
|
|
|
|
|
return play->actorCtx.flags.chest & (1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets current scene chest flag.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Flags_SetTreasure(PlayState* play, s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOff = !Flags_GetTreasure(play, flag);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.chest |= (1 << flag);
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOff) {
|
|
|
|
|
LUSLOG_INFO("Treasure Flag Set - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnSceneFlagSet(play->sceneNum, FLAG_SCENE_TREASURE, flag);
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests if current scene clear flag is set.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Flags_GetClear(PlayState* play, s32 flag) {
|
|
|
|
|
return play->actorCtx.flags.clear & (1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets current scene clear flag.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Flags_SetClear(PlayState* play, s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOff = !Flags_GetClear(play, flag);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.clear |= (1 << flag);
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOff) {
|
|
|
|
|
LUSLOG_INFO("Clear Flag Set - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnSceneFlagSet(play->sceneNum, FLAG_SCENE_CLEAR, flag);
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Unsets current scene clear flag.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Flags_UnsetClear(PlayState* play, s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOn = Flags_GetClear(play, flag);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.clear &= ~(1 << flag);
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOn) {
|
|
|
|
|
LUSLOG_INFO("Clear Flag Unset - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnSceneFlagUnset(play->sceneNum, FLAG_SCENE_CLEAR, flag);
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests if current scene temp clear flag is set.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Flags_GetTempClear(PlayState* play, s32 flag) {
|
|
|
|
|
return play->actorCtx.flags.tempClear & (1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets current scene temp clear flag.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Flags_SetTempClear(PlayState* play, s32 flag) {
|
|
|
|
|
play->actorCtx.flags.tempClear |= (1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Unsets current scene temp clear flag.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Flags_UnsetTempClear(PlayState* play, s32 flag) {
|
|
|
|
|
play->actorCtx.flags.tempClear &= ~(1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests if current scene collectible flag is set.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Flags_GetCollectible(PlayState* play, s32 flag) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (flag < 0x20) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
return play->actorCtx.flags.collect & (1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
return play->actorCtx.flags.tempCollect & (1 << (flag - 0x20));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets current scene collectible flag.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Flags_SetCollectible(PlayState* play, s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOff = !Flags_GetCollectible(play, flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (flag != 0) {
|
|
|
|
|
if (flag < 0x20) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.collect |= (1 << flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->actorCtx.flags.tempCollect |= (1 << (flag - 0x20));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOff) {
|
|
|
|
|
LUSLOG_INFO("Collectible Flag Set - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnSceneFlagSet(play->sceneNum, FLAG_SCENE_COLLECTIBLE, flag);
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002CDE4(PlayState* play, TitleCardContext* titleCtx) {
|
2022-07-05 20:52:01 -04:00
|
|
|
|
titleCtx->durationTimer = titleCtx->delayTimer = titleCtx->intensityR = titleCtx->alpha = 0;
|
|
|
|
|
titleCtx->durationTimer = titleCtx->delayTimer = titleCtx->intensityG = titleCtx->alpha = 0;
|
|
|
|
|
titleCtx->durationTimer = titleCtx->delayTimer = titleCtx->intensityB = titleCtx->alpha = 0;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void TitleCard_InitBossName(PlayState* play, TitleCardContext* titleCtx, void* texture, s16 x, s16 y, u8 width,
|
Bosses title cards fixes (#247)
* Boss title fixes.
* Proper X/Y/H/W
* Proper x,y,w,h
* Proper X,Y,W,H
* Actually had wrong height (was 32, should be 40)
* one of the last x,y,h,w fix
* WIP really need a better way to check it.
* Fix Ganondorf title card.
* better conditional logic
* No more workaround!
* Add two var in the TitleCardContext structures
* Added hasTranslation to Phantom Ganon's Horse
funny how that the horse that hold the title card.
* Add hasTranslation to Dodongo.
* Revert workaround and add hasTranslation=false
* Added hasTranslation to big piggy Ganon
* Add hasTranslation to Gohma
* Add hasTranslation to Morpha
* Add hasTranslation to Twins first part.
* Add hastranslation to that eletro "dude"
* Add hastranslation to bongo bongo
* Added hasTranslation to airwing v2
* add hasTranslation to TitleCard_InitBossName init
* isBossCard to true now that I can confirm it work
imagine in TitleCard_InitBossName setting isBossCard to false...
* no need to use bool there is seem to not like it
* change bool to s16
2022-05-02 18:27:06 -04:00
|
|
|
|
u8 height, s16 hasTranslation) {
|
2023-04-27 19:20:41 -04:00
|
|
|
|
static char newName[512];
|
|
|
|
|
|
|
|
|
|
if (gSaveContext.language != LANGUAGE_ENG) {
|
|
|
|
|
size_t length = strlen(texture);
|
|
|
|
|
strcpy(newName, texture);
|
|
|
|
|
if (gSaveContext.language == LANGUAGE_FRA) {
|
|
|
|
|
newName[length - 6] = 'F';
|
|
|
|
|
newName[length - 5] = 'R';
|
|
|
|
|
newName[length - 4] = 'A';
|
|
|
|
|
} else if (gSaveContext.language == LANGUAGE_GER) {
|
|
|
|
|
newName[length - 6] = 'G';
|
|
|
|
|
newName[length - 5] = 'E';
|
|
|
|
|
newName[length - 4] = 'R';
|
|
|
|
|
}
|
|
|
|
|
texture = newName;
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
titleCtx->texture = texture;
|
Bosses title cards fixes (#247)
* Boss title fixes.
* Proper X/Y/H/W
* Proper x,y,w,h
* Proper X,Y,W,H
* Actually had wrong height (was 32, should be 40)
* one of the last x,y,h,w fix
* WIP really need a better way to check it.
* Fix Ganondorf title card.
* better conditional logic
* No more workaround!
* Add two var in the TitleCardContext structures
* Added hasTranslation to Phantom Ganon's Horse
funny how that the horse that hold the title card.
* Add hasTranslation to Dodongo.
* Revert workaround and add hasTranslation=false
* Added hasTranslation to big piggy Ganon
* Add hasTranslation to Gohma
* Add hasTranslation to Morpha
* Add hasTranslation to Twins first part.
* Add hastranslation to that eletro "dude"
* Add hastranslation to bongo bongo
* Added hasTranslation to airwing v2
* add hasTranslation to TitleCard_InitBossName init
* isBossCard to true now that I can confirm it work
imagine in TitleCard_InitBossName setting isBossCard to false...
* no need to use bool there is seem to not like it
* change bool to s16
2022-05-02 18:27:06 -04:00
|
|
|
|
titleCtx->isBossCard = true;
|
2022-05-11 13:18:24 -04:00
|
|
|
|
titleCtx->hasTranslation = hasTranslation;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
titleCtx->x = x;
|
|
|
|
|
titleCtx->y = y;
|
|
|
|
|
titleCtx->width = width;
|
|
|
|
|
titleCtx->height = height;
|
|
|
|
|
titleCtx->durationTimer = 80;
|
|
|
|
|
titleCtx->delayTimer = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void TitleCard_InitPlaceName(PlayState* play, TitleCardContext* titleCtx, void* texture, s32 x, s32 y,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 width, s32 height, s32 delay) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
SceneTableEntry* loadedScene = play->loadedScene;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
// size_t size = loadedScene->titleFile.vromEnd - loadedScene->titleFile.vromStart;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
switch (play->sceneNum) {
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_DEKU_TREE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gDekuTreeTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_DODONGOS_CAVERN:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gDodongosCavernTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_JABU_JABU:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gJabuJabuTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_FOREST_TEMPLE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gForestTempleTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_FIRE_TEMPLE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gFireTempleTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_WATER_TEMPLE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gWaterTempleTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_SPIRIT_TEMPLE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gSpiritTempleTitleCardENGTex;
|
2022-04-03 19:45:02 -04:00
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_SHADOW_TEMPLE:
|
2022-04-03 19:45:02 -04:00
|
|
|
|
texture = gShadowTempleTitleCardENGTex;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_BOTTOM_OF_THE_WELL:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gBottomOfTheWellTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_ICE_CAVERN:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gIceCavernTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_GERUDO_TRAINING_GROUND:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gGERudoTrainingGroundTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_THIEVES_HIDEOUT:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gThievesHideoutTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_OUTSIDE_GANONS_CASTLE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gGanonsCastleTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_INSIDE_GANONS_CASTLE:
|
2022-07-07 22:19:41 -04:00
|
|
|
|
texture = gInsideGanonsCastleTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_TREASURE_BOX_SHOP:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gTreasureBoxShopTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_BACK_ALLEY_DAY:
|
|
|
|
|
case SCENE_BACK_ALLEY_NIGHT:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gBackAlleyTitleCardENGTex;
|
|
|
|
|
break;
|
|
|
|
|
case SCENE_MARKET_DAY:
|
|
|
|
|
case SCENE_MARKET_NIGHT:
|
|
|
|
|
case SCENE_MARKET_RUINS:
|
|
|
|
|
texture = gMarketTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_BAZAAR:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gBazaarTitleCardENGTex;
|
|
|
|
|
break;
|
|
|
|
|
case SCENE_KOKIRI_SHOP:
|
|
|
|
|
texture = gKokiriShopTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_GORON_SHOP:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gGoronShopTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_ZORA_SHOP:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gZoraShopTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_BOMBCHU_SHOP:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gBombchuShopTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_POTION_SHOP_KAKARIKO:
|
|
|
|
|
case SCENE_POTION_SHOP_GRANNY:
|
|
|
|
|
case SCENE_POTION_SHOP_MARKET:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gPotionShopTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_HAPPY_MASK_SHOP:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gHappyMaskShopTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_STABLE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gStableTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_LAKESIDE_LABORATORY:
|
2023-02-17 19:23:09 -05:00
|
|
|
|
texture = gLakesideLaboratoryTitleCardENGTex;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_GRAVEKEEPERS_HUT:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gGravekeepersHutTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC:
|
|
|
|
|
case SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gGreatFairysFountainTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_FAIRYS_FOUNTAIN:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gFairysFountainTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_ROYAL_FAMILYS_TOMB:
|
2022-09-18 23:29:24 -04:00
|
|
|
|
texture = gRoyalFamilysTombTitleCardENGTex;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_SHOOTING_GALLERY:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gShootingGalleryTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_TEMPLE_OF_TIME:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gTempleOfTimeTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_CHAMBER_OF_THE_SAGES:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gChamberOfTheSagesTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_CASTLE_COURTYARD_GUARDS_DAY:
|
|
|
|
|
case SCENE_CASTLE_COURTYARD_GUARDS_NIGHT:
|
|
|
|
|
case SCENE_CASTLE_COURTYARD_ZELDA:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
case SCENE_HAIRAL_NIWA2:
|
|
|
|
|
texture = gCastleCourtyardTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_WINDMILL_AND_DAMPES_GRAVE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gQuestionMarkTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_FISHING_POND:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gFishingPondTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_BOMBCHU_BOWLING_ALLEY:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gBombchuBowlingAlleyCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_HOUSE_OF_SKULLTULA:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gHouseOfSkulltulaTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_HYRULE_FIELD:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gHyruleFieldTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_KAKARIKO_VILLAGE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gKakarikoVillageTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_GRAVEYARD:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gGraveyardTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_ZORAS_RIVER:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gZorasRiverTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_KOKIRI_FOREST:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gKokiriForestTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_SACRED_FOREST_MEADOW:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gSacredForestMeadowTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_LAKE_HYLIA:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gLakeHyliaTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_ZORAS_DOMAIN:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gZorasDomainTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_ZORAS_FOUNTAIN:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gZorasFountainTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_GERUDO_VALLEY:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gGERudoValleyTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_LOST_WOODS:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gLostWoodsTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_DESERT_COLOSSUS:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gDesertColossusTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_GERUDOS_FORTRESS:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gGERudosFortressTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_HAUNTED_WASTELAND:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gHauntedWastelandTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_HYRULE_CASTLE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gHyruleCastleTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_DEATH_MOUNTAIN_TRAIL:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gDeathMountainTrailTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_DEATH_MOUNTAIN_CRATER:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gDeathMountainCraterTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_GORON_CITY:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gGoronCityTitleCardENGTex;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_LON_LON_RANCH:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
texture = gLonLonRanchTitleCardENGTex;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
titleCtx->texture = NULL;
|
|
|
|
|
return;
|
2022-05-02 18:26:32 -04:00
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-04-27 19:20:41 -04:00
|
|
|
|
static char newName[512];
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (gSaveContext.language != LANGUAGE_ENG) {
|
|
|
|
|
size_t length = strlen(texture);
|
|
|
|
|
strcpy(newName, texture);
|
|
|
|
|
if (gSaveContext.language == LANGUAGE_FRA) {
|
|
|
|
|
newName[length - 6] = 'F';
|
|
|
|
|
newName[length - 5] = 'R';
|
|
|
|
|
newName[length - 4] = 'A';
|
|
|
|
|
}
|
|
|
|
|
else if (gSaveContext.language == LANGUAGE_GER) {
|
|
|
|
|
newName[length - 6] = 'G';
|
|
|
|
|
newName[length - 5] = 'E';
|
|
|
|
|
newName[length - 4] = 'R';
|
|
|
|
|
}
|
|
|
|
|
texture = newName;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-27 19:20:41 -04:00
|
|
|
|
titleCtx->texture = texture;
|
Bosses title cards fixes (#247)
* Boss title fixes.
* Proper X/Y/H/W
* Proper x,y,w,h
* Proper X,Y,W,H
* Actually had wrong height (was 32, should be 40)
* one of the last x,y,h,w fix
* WIP really need a better way to check it.
* Fix Ganondorf title card.
* better conditional logic
* No more workaround!
* Add two var in the TitleCardContext structures
* Added hasTranslation to Phantom Ganon's Horse
funny how that the horse that hold the title card.
* Add hasTranslation to Dodongo.
* Revert workaround and add hasTranslation=false
* Added hasTranslation to big piggy Ganon
* Add hasTranslation to Gohma
* Add hasTranslation to Morpha
* Add hasTranslation to Twins first part.
* Add hastranslation to that eletro "dude"
* Add hastranslation to bongo bongo
* Added hasTranslation to airwing v2
* add hasTranslation to TitleCard_InitBossName init
* isBossCard to true now that I can confirm it work
imagine in TitleCard_InitBossName setting isBossCard to false...
* no need to use bool there is seem to not like it
* change bool to s16
2022-05-02 18:27:06 -04:00
|
|
|
|
titleCtx->isBossCard = false;
|
|
|
|
|
titleCtx->hasTranslation = false;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
titleCtx->x = x;
|
|
|
|
|
titleCtx->y = y;
|
|
|
|
|
titleCtx->width = width;
|
|
|
|
|
titleCtx->height = height;
|
|
|
|
|
titleCtx->durationTimer = 80;
|
|
|
|
|
titleCtx->delayTimer = delay;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void TitleCard_Update(PlayState* play, TitleCardContext* titleCtx) {
|
2022-08-23 20:20:56 -04:00
|
|
|
|
const Color_RGB8 TitleCard_Colors_ori = {255,255,255};
|
|
|
|
|
Color_RGB8 TitleCard_Colors = {255,255,255};
|
2024-05-05 15:14:55 -04:00
|
|
|
|
if (titleCtx->isBossCard && CVarGetInteger(CVAR_COSMETIC("HUD.TitleCard.Boss.Changed"), 1) == 2) {
|
|
|
|
|
TitleCard_Colors = CVarGetColor24(CVAR_COSMETIC("HUD.TitleCard.Boss.Value"), TitleCard_Colors_ori);
|
|
|
|
|
} else if (!titleCtx->isBossCard && CVarGetInteger(CVAR_COSMETIC("HUD.TitleCard.Map.Changed"), 1) == 2) {
|
|
|
|
|
TitleCard_Colors = CVarGetColor24(CVAR_COSMETIC("HUD.TitleCard.Map.Value"), TitleCard_Colors_ori);
|
2022-08-23 20:20:56 -04:00
|
|
|
|
} else {
|
|
|
|
|
TitleCard_Colors = TitleCard_Colors_ori;
|
|
|
|
|
}
|
2022-07-05 20:52:01 -04:00
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (DECR(titleCtx->delayTimer) == 0) {
|
2023-03-02 03:27:28 -05:00
|
|
|
|
if (titleCtx->durationTimer == 80) {
|
|
|
|
|
GameInteractor_ExecuteOnPresentTitleCard();
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (DECR(titleCtx->durationTimer) == 0) {
|
|
|
|
|
Math_StepToS(&titleCtx->alpha, 0, 30);
|
2022-07-05 20:52:01 -04:00
|
|
|
|
Math_StepToS(&titleCtx->intensityR, 0, 70);
|
|
|
|
|
Math_StepToS(&titleCtx->intensityG, 0, 70);
|
|
|
|
|
Math_StepToS(&titleCtx->intensityB, 0, 70);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
|
|
|
|
Math_StepToS(&titleCtx->alpha, 255, 10);
|
2022-08-23 20:20:56 -04:00
|
|
|
|
Math_StepToS(&titleCtx->intensityR, TitleCard_Colors.r, 20);
|
|
|
|
|
Math_StepToS(&titleCtx->intensityG, TitleCard_Colors.g, 20);
|
|
|
|
|
Math_StepToS(&titleCtx->intensityB, TitleCard_Colors.b, 20);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void TitleCard_Draw(PlayState* play, TitleCardContext* titleCtx) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 width;
|
|
|
|
|
s32 height;
|
|
|
|
|
s32 titleX;
|
|
|
|
|
s32 doubleWidth;
|
|
|
|
|
s32 titleY;
|
|
|
|
|
|
|
|
|
|
if (titleCtx->alpha != 0) {
|
|
|
|
|
width = titleCtx->width;
|
|
|
|
|
height = titleCtx->height;
|
2024-04-25 22:41:55 -04:00
|
|
|
|
s16 TitleCard_PosX_Modifier = (titleCtx->isBossCard ? CVarGetInteger(CVAR_COSMETIC("TitleCard.Boss.PosX"), 0) : CVarGetInteger(CVAR_COSMETIC("TitleCard.Map.PosX"), 0));
|
|
|
|
|
s16 TitleCard_PosY_Modifier = (titleCtx->isBossCard ? CVarGetInteger(CVAR_COSMETIC("TitleCard.Boss.PosY"), 0) : CVarGetInteger(CVAR_COSMETIC("TitleCard.Map.PosY"), 0));
|
|
|
|
|
s16 TitleCard_PosType_Checker = (titleCtx->isBossCard ? CVarGetInteger(CVAR_COSMETIC("TitleCard.Boss.PosType"), 0) : CVarGetInteger(CVAR_COSMETIC("TitleCard.Map.PosType"), 0));
|
|
|
|
|
s16 TitleCard_Margin_Checker = (titleCtx->isBossCard ? CVarGetInteger(CVAR_COSMETIC("TitleCard.Boss.UseMargins"), 0) : CVarGetInteger(CVAR_COSMETIC("TitleCard.Map.UseMargins"), 0));
|
2022-07-05 20:52:01 -04:00
|
|
|
|
s16 TitleCard_MarginX = 0;
|
|
|
|
|
s16 TitleCard_PosX = titleCtx->x;
|
|
|
|
|
s16 TitleCard_PosY = titleCtx->y;
|
|
|
|
|
if (TitleCard_PosType_Checker != 0) {
|
|
|
|
|
TitleCard_PosY = TitleCard_PosY_Modifier;
|
|
|
|
|
if (TitleCard_PosType_Checker == 1) {//Anchor Left
|
2024-05-05 15:14:55 -04:00
|
|
|
|
if (TitleCard_Margin_Checker != 0) {TitleCard_MarginX = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0)*-1;};
|
2022-07-05 20:52:01 -04:00
|
|
|
|
TitleCard_PosX = OTRGetDimensionFromLeftEdge(TitleCard_PosX_Modifier+TitleCard_MarginX)-11;
|
|
|
|
|
} else if (TitleCard_PosType_Checker == 2) {//Anchor Right
|
2024-05-05 15:14:55 -04:00
|
|
|
|
if (TitleCard_Margin_Checker != 0) {TitleCard_MarginX = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.R"), 0);};
|
2022-07-05 20:52:01 -04:00
|
|
|
|
TitleCard_PosX = OTRGetDimensionFromRightEdge(TitleCard_PosX_Modifier+TitleCard_MarginX);
|
|
|
|
|
} else if (TitleCard_PosType_Checker == 3) {//Anchor None
|
|
|
|
|
TitleCard_PosX = TitleCard_PosX_Modifier;
|
|
|
|
|
} else if (TitleCard_PosType_Checker == 4) {//Hidden
|
|
|
|
|
TitleCard_PosX = -9999;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
titleX = (TitleCard_PosX * 4) - (width * 2);
|
|
|
|
|
titleY = (TitleCard_PosY * 4) - (height * 2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
doubleWidth = width * 2;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-10-10 19:45:11 -04:00
|
|
|
|
OVERLAY_DISP = Gfx_SetupDL_52NoCD(OVERLAY_DISP);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-10-10 19:45:11 -04:00
|
|
|
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, (u8)titleCtx->intensityR, (u8)titleCtx->intensityG, (u8)titleCtx->intensityB,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
(u8)titleCtx->alpha);
|
|
|
|
|
|
2024-10-10 19:45:11 -04:00
|
|
|
|
gDPLoadTextureBlock(OVERLAY_DISP++, (uintptr_t)titleCtx->texture, G_IM_FMT_IA,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_IM_SIZ_8b,
|
|
|
|
|
width, height, 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);
|
2024-10-10 19:45:11 -04:00
|
|
|
|
gSPWideTextureRectangle(OVERLAY_DISP++, titleX, titleY, ((doubleWidth * 2) + titleX) - 4, titleY + (height * 4),
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
|
|
|
|
|
|
|
|
|
|
height = titleCtx->height - height;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_8002D53C(PlayState* play, TitleCardContext* titleCtx) {
|
|
|
|
|
if ((play->actorCtx.titleCtx.delayTimer != 0) || (play->actorCtx.titleCtx.alpha != 0)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
titleCtx->durationTimer = 0;
|
|
|
|
|
titleCtx->delayTimer = 0;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_Kill(Actor* actor) {
|
2023-09-10 13:23:43 -04:00
|
|
|
|
GameInteractor_ExecuteOnActorKill(actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->draw = NULL;
|
|
|
|
|
actor->update = NULL;
|
2023-05-30 15:05:04 -04:00
|
|
|
|
actor->flags &= ~ACTOR_FLAG_TARGETABLE;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_SetWorldToHome(Actor* actor) {
|
|
|
|
|
actor->world = actor->home;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_SetFocus(Actor* actor, f32 yOffset) {
|
|
|
|
|
actor->focus.pos.x = actor->world.pos.x;
|
|
|
|
|
actor->focus.pos.y = actor->world.pos.y + yOffset;
|
|
|
|
|
actor->focus.pos.z = actor->world.pos.z;
|
|
|
|
|
|
|
|
|
|
actor->focus.rot.x = actor->world.rot.x;
|
|
|
|
|
actor->focus.rot.y = actor->world.rot.y;
|
|
|
|
|
actor->focus.rot.z = actor->world.rot.z;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_SetWorldRotToShape(Actor* actor) {
|
|
|
|
|
actor->world.rot = actor->shape.rot;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_SetShapeRotToWorld(Actor* actor) {
|
|
|
|
|
actor->shape.rot = actor->world.rot;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_SetScale(Actor* actor, f32 scale) {
|
|
|
|
|
actor->scale.z = scale;
|
|
|
|
|
actor->scale.y = scale;
|
|
|
|
|
actor->scale.x = scale;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_SetObjectDependency(PlayState* play, Actor* actor) {
|
|
|
|
|
gSegments[6] = VIRTUAL_TO_PHYSICAL(play->objectCtx.status[actor->objBankIndex].segment);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_Init(Actor* actor, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor_SetWorldToHome(actor);
|
|
|
|
|
Actor_SetShapeRotToWorld(actor);
|
|
|
|
|
Actor_SetFocus(actor, 0.0f);
|
|
|
|
|
Math_Vec3f_Copy(&actor->prevPos, &actor->world.pos);
|
|
|
|
|
Actor_SetScale(actor, 0.01f);
|
|
|
|
|
actor->targetMode = 3;
|
|
|
|
|
actor->minVelocityY = -20.0f;
|
|
|
|
|
actor->xyzDistToPlayerSq = FLT_MAX;
|
|
|
|
|
actor->naviEnemyId = 0xFF;
|
|
|
|
|
actor->uncullZoneForward = 1000.0f;
|
|
|
|
|
actor->uncullZoneScale = 350.0f;
|
|
|
|
|
actor->uncullZoneDownward = 700.0f;
|
|
|
|
|
CollisionCheck_InitInfo(&actor->colChkInfo);
|
|
|
|
|
actor->floorBgId = BGCHECK_SCENE;
|
|
|
|
|
ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f);
|
2024-01-15 10:30:20 -05:00
|
|
|
|
if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
|
2024-04-19 09:41:04 -04:00
|
|
|
|
Actor_SetObjectDependency(play, actor);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
actor->init(actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->init = NULL;
|
2023-07-12 21:55:24 -04:00
|
|
|
|
|
2023-08-20 13:59:23 -04:00
|
|
|
|
GameInteractor_ExecuteOnActorInit(actor);
|
|
|
|
|
|
2023-07-12 21:55:24 -04:00
|
|
|
|
// For enemy health bar we need to know the max health during init
|
|
|
|
|
if (actor->category == ACTORCAT_ENEMY) {
|
|
|
|
|
actor->maximumHealth = actor->colChkInfo.health;
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_Destroy(Actor* actor, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (actor->destroy != NULL) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
actor->destroy(actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->destroy = NULL;
|
|
|
|
|
} else {
|
|
|
|
|
// "No Actor class destruct [%s]"
|
2023-06-01 21:39:50 -04:00
|
|
|
|
osSyncPrintf("Actorクラス デストラクトがありません [%s]\n" VT_RST, ActorDB_Retrieve(actor->id)->name);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
2023-08-20 13:59:23 -04:00
|
|
|
|
|
|
|
|
|
NameTag_RemoveAllForActor(actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002D7EC(Actor* actor) {
|
|
|
|
|
f32 speedRate = R_UPDATE_RATE * 0.5f;
|
|
|
|
|
|
|
|
|
|
actor->world.pos.x += (actor->velocity.x * speedRate) + actor->colChkInfo.displacement.x;
|
|
|
|
|
actor->world.pos.y += (actor->velocity.y * speedRate) + actor->colChkInfo.displacement.y;
|
|
|
|
|
actor->world.pos.z += (actor->velocity.z * speedRate) + actor->colChkInfo.displacement.z;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002D868(Actor* actor) {
|
|
|
|
|
actor->velocity.x = Math_SinS(actor->world.rot.y) * actor->speedXZ;
|
|
|
|
|
actor->velocity.z = Math_CosS(actor->world.rot.y) * actor->speedXZ;
|
|
|
|
|
|
|
|
|
|
actor->velocity.y += actor->gravity;
|
|
|
|
|
if (actor->velocity.y < actor->minVelocityY) {
|
|
|
|
|
actor->velocity.y = actor->minVelocityY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_MoveForward(Actor* actor) {
|
|
|
|
|
func_8002D868(actor);
|
|
|
|
|
func_8002D7EC(actor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002D908(Actor* actor) {
|
|
|
|
|
f32 sp24 = Math_CosS(actor->world.rot.x) * actor->speedXZ;
|
|
|
|
|
|
|
|
|
|
actor->velocity.x = Math_SinS(actor->world.rot.y) * sp24;
|
|
|
|
|
actor->velocity.y = Math_SinS(actor->world.rot.x) * actor->speedXZ;
|
|
|
|
|
actor->velocity.z = Math_CosS(actor->world.rot.y) * sp24;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002D97C(Actor* actor) {
|
|
|
|
|
func_8002D908(actor);
|
|
|
|
|
func_8002D7EC(actor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002D9A4(Actor* actor, f32 arg1) {
|
|
|
|
|
actor->speedXZ = Math_CosS(actor->world.rot.x) * arg1;
|
|
|
|
|
actor->velocity.y = -Math_SinS(actor->world.rot.x) * arg1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002D9F8(Actor* actor, SkelAnime* skelAnime) {
|
|
|
|
|
Vec3f sp1C;
|
|
|
|
|
|
|
|
|
|
SkelAnime_UpdateTranslation(skelAnime, &sp1C, actor->shape.rot.y);
|
|
|
|
|
actor->world.pos.x += sp1C.x * actor->scale.x;
|
|
|
|
|
actor->world.pos.y += sp1C.y * actor->scale.y;
|
|
|
|
|
actor->world.pos.z += sp1C.z * actor->scale.z;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s16 Actor_WorldYawTowardActor(Actor* actorA, Actor* actorB) {
|
|
|
|
|
return Math_Vec3f_Yaw(&actorA->world.pos, &actorB->world.pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s16 Actor_FocusYawTowardActor(Actor* actorA, Actor* actorB) {
|
|
|
|
|
return Math_Vec3f_Yaw(&actorA->focus.pos, &actorB->focus.pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s16 Actor_WorldYawTowardPoint(Actor* actor, Vec3f* refPoint) {
|
|
|
|
|
return Math_Vec3f_Yaw(&actor->world.pos, refPoint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s16 Actor_WorldPitchTowardActor(Actor* actorA, Actor* actorB) {
|
|
|
|
|
return Math_Vec3f_Pitch(&actorA->world.pos, &actorB->world.pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s16 Actor_FocusPitchTowardActor(Actor* actorA, Actor* actorB) {
|
|
|
|
|
return Math_Vec3f_Pitch(&actorA->focus.pos, &actorB->focus.pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s16 Actor_WorldPitchTowardPoint(Actor* actor, Vec3f* refPoint) {
|
|
|
|
|
return Math_Vec3f_Pitch(&actor->world.pos, refPoint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 Actor_WorldDistXYZToActor(Actor* actorA, Actor* actorB) {
|
|
|
|
|
return Math_Vec3f_DistXYZ(&actorA->world.pos, &actorB->world.pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 Actor_WorldDistXYZToPoint(Actor* actor, Vec3f* refPoint) {
|
|
|
|
|
return Math_Vec3f_DistXYZ(&actor->world.pos, refPoint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 Actor_WorldDistXZToActor(Actor* actorA, Actor* actorB) {
|
|
|
|
|
return Math_Vec3f_DistXZ(&actorA->world.pos, &actorB->world.pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 Actor_WorldDistXZToPoint(Actor* actor, Vec3f* refPoint) {
|
|
|
|
|
return Math_Vec3f_DistXZ(&actor->world.pos, refPoint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002DBD0(Actor* actor, Vec3f* result, Vec3f* arg2) {
|
|
|
|
|
f32 cosRot2Y;
|
|
|
|
|
f32 sinRot2Y;
|
|
|
|
|
f32 deltaX;
|
|
|
|
|
f32 deltaZ;
|
|
|
|
|
|
|
|
|
|
cosRot2Y = Math_CosS(actor->shape.rot.y);
|
|
|
|
|
sinRot2Y = Math_SinS(actor->shape.rot.y);
|
|
|
|
|
deltaX = arg2->x - actor->world.pos.x;
|
|
|
|
|
deltaZ = arg2->z - actor->world.pos.z;
|
|
|
|
|
|
|
|
|
|
result->x = (deltaX * cosRot2Y) - (deltaZ * sinRot2Y);
|
|
|
|
|
result->z = (deltaX * sinRot2Y) + (deltaZ * cosRot2Y);
|
|
|
|
|
result->y = arg2->y - actor->world.pos.y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 Actor_HeightDiff(Actor* actorA, Actor* actorB) {
|
|
|
|
|
return actorB->world.pos.y - actorA->world.pos.y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 Player_GetHeight(Player* player) {
|
2024-02-15 20:17:28 -05:00
|
|
|
|
f32 offset = (player->stateFlags1 & PLAYER_STATE1_ON_HORSE) ? 32.0f : 0.0f;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (LINK_IS_ADULT) {
|
|
|
|
|
return offset + 68.0f;
|
|
|
|
|
} else {
|
|
|
|
|
return offset + 44.0f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 func_8002DCE4(Player* player) {
|
2024-02-15 20:17:28 -05:00
|
|
|
|
if (player->stateFlags1 & PLAYER_STATE1_ON_HORSE) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return 8.0f;
|
2024-02-15 20:17:28 -05:00
|
|
|
|
} else if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return (R_RUN_SPEED_LIMIT / 100.0f) * 0.6f;
|
|
|
|
|
} else {
|
|
|
|
|
return R_RUN_SPEED_LIMIT / 100.0f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 func_8002DD6C(Player* player) {
|
2024-02-15 20:17:28 -05:00
|
|
|
|
return player->stateFlags1 & PLAYER_STATE1_ITEM_IN_HAND;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 func_8002DD78(Player* player) {
|
|
|
|
|
return func_8002DD6C(player) && player->unk_834;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_8002DDA8(PlayState* play) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
return (player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) || func_8002DD78(player);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_8002DDE4(PlayState* play) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
return player->stateFlags2 & PLAYER_STATE2_FOOTSTEP;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_8002DDF4(PlayState* play) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
return player->stateFlags2 & PLAYER_STATE2_STATIONARY_LADDER;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002DE04(PlayState* play, Actor* actorA, Actor* actorB) {
|
|
|
|
|
ArmsHook* hookshot = (ArmsHook*)Actor_Find(&play->actorCtx, ACTOR_ARMS_HOOK, ACTORCAT_ITEMACTION);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
hookshot->grabbed = actorB;
|
|
|
|
|
hookshot->grabbedDistDiff.x = 0.0f;
|
|
|
|
|
hookshot->grabbedDistDiff.y = 0.0f;
|
|
|
|
|
hookshot->grabbedDistDiff.z = 0.0f;
|
2023-05-30 15:05:04 -04:00
|
|
|
|
actorB->flags |= ACTOR_FLAG_HOOKSHOT_ATTACHED;
|
|
|
|
|
actorA->flags &= ~ACTOR_FLAG_HOOKSHOT_ATTACHED;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002DE74(PlayState* play, Player* player) {
|
|
|
|
|
if ((play->roomCtx.curRoom.behaviorType1 != ROOM_BEHAVIOR_TYPE1_4) && func_800C0CB8(play)) {
|
|
|
|
|
Camera_ChangeSetting(Play_GetCamera(play, MAIN_CAM), CAM_SET_HORSE);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_MountHorse(PlayState* play, Player* player, Actor* horse) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
player->rideActor = horse;
|
2024-02-15 20:17:28 -05:00
|
|
|
|
player->stateFlags1 |= PLAYER_STATE1_ON_HORSE;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
horse->child = &player->actor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 func_8002DEEC(Player* player) {
|
2024-02-15 20:17:28 -05:00
|
|
|
|
return (player->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_CUTSCENE)) || (player->csAction != 0);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002DF18(PlayState* play, Player* player) {
|
|
|
|
|
func_8006DC68(play, player);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-26 11:54:54 -05:00
|
|
|
|
s32 func_8002DF38(PlayState* play, Actor* actor, u8 csAction) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-11-26 11:54:54 -05:00
|
|
|
|
player->csAction = csAction;
|
|
|
|
|
player->csActor = actor;
|
2022-11-29 18:28:57 -05:00
|
|
|
|
player->doorBgCamIndex = 0;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-03 21:07:42 -04:00
|
|
|
|
s32 Player_SetCsActionWithHaltedActors(PlayState* play, Actor* actor, u8 csAction) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-11-26 11:54:54 -05:00
|
|
|
|
func_8002DF38(play, actor, csAction);
|
2022-11-29 18:28:57 -05:00
|
|
|
|
player->doorBgCamIndex = 1;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002DF90(DynaPolyActor* dynaActor) {
|
|
|
|
|
dynaActor->unk_154 = 0.0f;
|
|
|
|
|
dynaActor->unk_150 = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002DFA4(DynaPolyActor* dynaActor, f32 arg1, s16 arg2) {
|
|
|
|
|
dynaActor->unk_150 += arg1;
|
|
|
|
|
dynaActor->unk_158 = arg2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Chcek if the player is facing the specified actor.
|
|
|
|
|
* The maximum angle difference that qualifies as "facing" is specified by `maxAngle`.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Player_IsFacingActor(Actor* actor, s16 maxAngle, PlayState* play) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s16 yawDiff = (s16)(actor->yawTowardsPlayer + 0x8000) - player->actor.shape.rot.y;
|
|
|
|
|
|
|
|
|
|
if (ABS(yawDiff) < maxAngle) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Chcek if `actorB` is facing `actorA`.
|
|
|
|
|
* The maximum angle difference that qualifies as "facing" is specified by `maxAngle`.
|
|
|
|
|
*
|
|
|
|
|
* This function is unused in the original game.
|
|
|
|
|
*/
|
|
|
|
|
s32 Actor_ActorBIsFacingActorA(Actor* actorA, Actor* actorB, s16 maxAngle) {
|
|
|
|
|
s16 yawDiff = (s16)(Actor_WorldYawTowardActor(actorA, actorB) + 0x8000) - actorB->shape.rot.y;
|
|
|
|
|
|
|
|
|
|
if (ABS(yawDiff) < maxAngle) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Chcek if the specified actor is facing the player.
|
|
|
|
|
* The maximum angle difference that qualifies as "facing" is specified by `maxAngle`.
|
|
|
|
|
*/
|
|
|
|
|
s32 Actor_IsFacingPlayer(Actor* actor, s16 maxAngle) {
|
|
|
|
|
s16 yawDiff = actor->yawTowardsPlayer - actor->shape.rot.y;
|
|
|
|
|
|
|
|
|
|
if (ABS(yawDiff) < maxAngle) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Chcek if `actorA` is facing `actorB`.
|
|
|
|
|
* The maximum angle difference that qualifies as "facing" is specified by `maxAngle`.
|
|
|
|
|
*
|
|
|
|
|
* This function is unused in the original game.
|
|
|
|
|
*/
|
|
|
|
|
s32 Actor_ActorAIsFacingActorB(Actor* actorA, Actor* actorB, s16 maxAngle) {
|
|
|
|
|
s16 yawDiff = Actor_WorldYawTowardActor(actorA, actorB) - actorA->shape.rot.y;
|
|
|
|
|
|
|
|
|
|
if (ABS(yawDiff) < maxAngle) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Chcek if the specified actor is facing the player and is nearby.
|
|
|
|
|
* The maximum angle difference that qualifies as "facing" is specified by `maxAngle`.
|
|
|
|
|
* The minimum distance that qualifies as "nearby" is specified by `range`.
|
|
|
|
|
*/
|
|
|
|
|
s32 Actor_IsFacingAndNearPlayer(Actor* actor, f32 range, s16 maxAngle) {
|
|
|
|
|
s16 yawDiff = actor->yawTowardsPlayer - actor->shape.rot.y;
|
|
|
|
|
|
|
|
|
|
if (ABS(yawDiff) < maxAngle) {
|
|
|
|
|
f32 xyzDistanceFromLink = sqrtf(SQ(actor->xzDistToPlayer) + SQ(actor->yDistToPlayer));
|
|
|
|
|
|
|
|
|
|
if (xyzDistanceFromLink < range) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Chcek if `actorA` is facing `actorB` and is nearby.
|
|
|
|
|
* The maximum angle difference that qualifies as "facing" is specified by `maxAngle`.
|
|
|
|
|
* The minimum distance that qualifies as "nearby" is specified by `range`.
|
|
|
|
|
*/
|
|
|
|
|
s32 Actor_ActorAIsFacingAndNearActorB(Actor* actorA, Actor* actorB, f32 range, s16 maxAngle) {
|
|
|
|
|
if (Actor_WorldDistXYZToActor(actorA, actorB) < range) {
|
|
|
|
|
s16 yawDiff = Actor_WorldYawTowardActor(actorA, actorB) - actorA->shape.rot.y;
|
|
|
|
|
|
|
|
|
|
if (ABS(yawDiff) < maxAngle) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 func_8002E234(Actor* actor, f32 arg1, s32 arg2) {
|
|
|
|
|
if ((actor->bgCheckFlags & 0x1) && (arg1 < -11.0f)) {
|
|
|
|
|
actor->bgCheckFlags &= ~0x1;
|
|
|
|
|
actor->bgCheckFlags |= 0x4;
|
|
|
|
|
|
|
|
|
|
if ((actor->velocity.y < 0.0f) && (arg2 & 0x10)) {
|
|
|
|
|
actor->velocity.y = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_8002E2AC(PlayState* play, Actor* actor, Vec3f* arg2, s32 arg3) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 floorHeightDiff;
|
|
|
|
|
s32 floorBgId;
|
|
|
|
|
|
|
|
|
|
arg2->y += 50.0f;
|
|
|
|
|
|
|
|
|
|
actor->floorHeight =
|
2022-11-06 03:24:34 -05:00
|
|
|
|
BgCheck_EntityRaycastFloor5(play, &play->colCtx, &actor->floorPoly, &floorBgId, actor, arg2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->bgCheckFlags &= ~0x0086;
|
|
|
|
|
|
|
|
|
|
if (actor->floorHeight <= BGCHECK_Y_MIN) {
|
|
|
|
|
return func_8002E234(actor, BGCHECK_Y_MIN, arg3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
floorHeightDiff = actor->floorHeight - actor->world.pos.y;
|
|
|
|
|
actor->floorBgId = floorBgId;
|
|
|
|
|
|
|
|
|
|
if (floorHeightDiff >= 0.0f) { // actor is on or below the ground
|
|
|
|
|
actor->bgCheckFlags |= 0x80;
|
|
|
|
|
|
|
|
|
|
if (actor->bgCheckFlags & 0x10) {
|
|
|
|
|
if (floorBgId != sCurCeilingBgId) {
|
|
|
|
|
if (floorHeightDiff > 15.0f) {
|
|
|
|
|
actor->bgCheckFlags |= 0x100;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
actor->world.pos.x = actor->prevPos.x;
|
|
|
|
|
actor->world.pos.z = actor->prevPos.z;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actor->world.pos.y = actor->floorHeight;
|
|
|
|
|
|
|
|
|
|
if (actor->velocity.y <= 0.0f) {
|
|
|
|
|
if (!(actor->bgCheckFlags & 0x1)) {
|
|
|
|
|
actor->bgCheckFlags |= 0x2;
|
|
|
|
|
} else if ((arg3 & 0x8) && (actor->gravity < 0.0f)) {
|
|
|
|
|
actor->velocity.y = -4.0f;
|
|
|
|
|
} else {
|
|
|
|
|
actor->velocity.y = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actor->bgCheckFlags |= 0x1;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80043334(&play->colCtx, actor, actor->floorBgId);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
} else { // actor is above ground
|
|
|
|
|
if ((actor->bgCheckFlags & 0x1) && (floorHeightDiff >= -11.0f)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80043334(&play->colCtx, actor, actor->floorBgId);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return func_8002E234(actor, floorHeightDiff, arg3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_UpdateBgCheckInfo(PlayState* play, Actor* actor, f32 wallCheckHeight, f32 wallCheckRadius,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 ceilingCheckHeight, s32 flags) {
|
|
|
|
|
f32 sp74;
|
|
|
|
|
s32 pad;
|
|
|
|
|
Vec3f sp64;
|
|
|
|
|
s32 bgId;
|
|
|
|
|
CollisionPoly* wallPoly;
|
|
|
|
|
f32 sp58;
|
|
|
|
|
WaterBox* waterBox;
|
|
|
|
|
f32 waterBoxYSurface;
|
|
|
|
|
Vec3f ripplePos;
|
|
|
|
|
|
|
|
|
|
sp74 = actor->world.pos.y - actor->prevPos.y;
|
|
|
|
|
|
|
|
|
|
if ((actor->floorBgId != BGCHECK_SCENE) && (actor->bgCheckFlags & 1)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_800433A4(&play->colCtx, actor->floorBgId, actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flags & 1) {
|
|
|
|
|
if ((!(flags & 0x80) &&
|
2022-11-06 03:24:34 -05:00
|
|
|
|
BgCheck_EntitySphVsWall3(&play->colCtx, &sp64, &actor->world.pos, &actor->prevPos, wallCheckRadius,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
&actor->wallPoly, &bgId, actor, wallCheckHeight)) ||
|
|
|
|
|
((flags & 0x80) &&
|
2022-11-06 03:24:34 -05:00
|
|
|
|
BgCheck_EntitySphVsWall4(&play->colCtx, &sp64, &actor->world.pos, &actor->prevPos, wallCheckRadius,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
&actor->wallPoly, &bgId, actor, wallCheckHeight))) {
|
|
|
|
|
wallPoly = actor->wallPoly;
|
|
|
|
|
Math_Vec3f_Copy(&actor->world.pos, &sp64);
|
|
|
|
|
actor->wallYaw = Math_Atan2S(wallPoly->normal.z, wallPoly->normal.x);
|
|
|
|
|
actor->bgCheckFlags |= 8;
|
|
|
|
|
actor->wallBgId = bgId;
|
|
|
|
|
} else {
|
|
|
|
|
actor->bgCheckFlags &= ~8;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sp64.x = actor->world.pos.x;
|
|
|
|
|
sp64.z = actor->world.pos.z;
|
|
|
|
|
|
|
|
|
|
if (flags & 2) {
|
|
|
|
|
sp64.y = actor->prevPos.y + 10.0f;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (BgCheck_EntityCheckCeiling(&play->colCtx, &sp58, &sp64, (ceilingCheckHeight + sp74) - 10.0f,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
&sCurCeilingPoly, &sCurCeilingBgId, actor)) {
|
|
|
|
|
actor->bgCheckFlags |= 0x10;
|
|
|
|
|
actor->world.pos.y = (sp58 + sp74) - 10.0f;
|
|
|
|
|
} else {
|
|
|
|
|
actor->bgCheckFlags &= ~0x10;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flags & 4) {
|
|
|
|
|
sp64.y = actor->prevPos.y;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002E2AC(play, actor, &sp64, flags);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
waterBoxYSurface = actor->world.pos.y;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (WaterBox_GetSurface1(play, &play->colCtx, actor->world.pos.x, actor->world.pos.z,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
&waterBoxYSurface, &waterBox)) {
|
|
|
|
|
actor->yDistToWater = waterBoxYSurface - actor->world.pos.y;
|
|
|
|
|
if (actor->yDistToWater < 0.0f) {
|
|
|
|
|
actor->bgCheckFlags &= ~0x60;
|
|
|
|
|
} else {
|
|
|
|
|
if (!(actor->bgCheckFlags & 0x20)) {
|
|
|
|
|
actor->bgCheckFlags |= 0x40;
|
|
|
|
|
if (!(flags & 0x40)) {
|
|
|
|
|
ripplePos.x = actor->world.pos.x;
|
|
|
|
|
ripplePos.y = waterBoxYSurface;
|
|
|
|
|
ripplePos.z = actor->world.pos.z;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
EffectSsGRipple_Spawn(play, &ripplePos, 100, 500, 0);
|
|
|
|
|
EffectSsGRipple_Spawn(play, &ripplePos, 100, 500, 4);
|
|
|
|
|
EffectSsGRipple_Spawn(play, &ripplePos, 100, 500, 8);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
actor->bgCheckFlags |= 0x20;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
actor->bgCheckFlags &= ~0x60;
|
|
|
|
|
actor->yDistToWater = BGCHECK_Y_MIN;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mtx D_8015BBA8;
|
|
|
|
|
|
|
|
|
|
Gfx* func_8002E830(Vec3f* object, Vec3f* eye, Vec3f* lightDir, GraphicsContext* gfxCtx, Gfx* gfx, Hilite** hilite) {
|
|
|
|
|
LookAt* lookAt;
|
|
|
|
|
f32 correctedEyeX;
|
|
|
|
|
|
|
|
|
|
lookAt = Graph_Alloc(gfxCtx, sizeof(LookAt));
|
|
|
|
|
|
|
|
|
|
correctedEyeX = (eye->x == object->x) && (eye->z == object->z) ? eye->x + 0.001f : eye->x;
|
|
|
|
|
|
|
|
|
|
*hilite = Graph_Alloc(gfxCtx, sizeof(Hilite));
|
|
|
|
|
|
|
|
|
|
if (HREG(80) == 6) {
|
|
|
|
|
osSyncPrintf("z_actor.c 3529 eye=[%f(%f) %f %f] object=[%f %f %f] light_direction=[%f %f %f]\n", correctedEyeX,
|
|
|
|
|
eye->x, eye->y, eye->z, object->x, object->y, object->z, lightDir->x, lightDir->y, lightDir->z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func_800ABE74(correctedEyeX, eye->y, eye->z);
|
|
|
|
|
guLookAtHilite(&D_8015BBA8, lookAt, *hilite, correctedEyeX, eye->y, eye->z, object->x, object->y, object->z, 0.0f,
|
|
|
|
|
1.0f, 0.0f, lightDir->x, lightDir->y, lightDir->z, lightDir->x, lightDir->y, lightDir->z, 0x10,
|
|
|
|
|
0x10);
|
|
|
|
|
|
|
|
|
|
gSPLookAt(gfx++, lookAt);
|
|
|
|
|
gDPSetHilite1Tile(gfx++, 1, *hilite, 0x10, 0x10);
|
|
|
|
|
|
|
|
|
|
return gfx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Hilite* func_8002EABC(Vec3f* object, Vec3f* eye, Vec3f* lightDir, GraphicsContext* gfxCtx) {
|
|
|
|
|
Hilite* hilite;
|
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
|
OPEN_DISPS(gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
POLY_OPA_DISP = func_8002E830(object, eye, lightDir, gfxCtx, POLY_OPA_DISP, &hilite);
|
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
|
CLOSE_DISPS(gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
return hilite;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Hilite* func_8002EB44(Vec3f* object, Vec3f* eye, Vec3f* lightDir, GraphicsContext* gfxCtx) {
|
|
|
|
|
Hilite* hilite;
|
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
|
OPEN_DISPS(gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
POLY_XLU_DISP = func_8002E830(object, eye, lightDir, gfxCtx, POLY_XLU_DISP, &hilite);
|
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
|
CLOSE_DISPS(gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
return hilite;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002EBCC(Actor* actor, PlayState* play, s32 flag) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Hilite* hilite;
|
|
|
|
|
Vec3f lightDir;
|
|
|
|
|
Gfx* displayListHead;
|
|
|
|
|
Gfx* displayList;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
lightDir.x = play->envCtx.dirLight1.params.dir.x;
|
|
|
|
|
lightDir.y = play->envCtx.dirLight1.params.dir.y;
|
|
|
|
|
lightDir.z = play->envCtx.dirLight1.params.dir.z;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (HREG(80) == 6) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
osSyncPrintf("z_actor.c 3637 game_play->view.eye=[%f(%f) %f %f]\n", play->view.eye.x,
|
|
|
|
|
play->view.eye.y, play->view.eye.z);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
hilite = func_8002EABC(&actor->world.pos, &play->view.eye, &lightDir, play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (flag != 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
displayList = Graph_Alloc(play->state.gfxCtx, 2 * sizeof(Gfx));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
displayListHead = displayList;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
gDPSetHilite1Tile(displayListHead++, 1, hilite, 0x10, 0x10);
|
|
|
|
|
gSPEndDisplayList(displayListHead);
|
|
|
|
|
gSPSegment(POLY_OPA_DISP++, 0x07, displayList);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002ED80(Actor* actor, PlayState* play, s32 flag) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Hilite* hilite;
|
|
|
|
|
Vec3f lightDir;
|
|
|
|
|
Gfx* displayListHead;
|
|
|
|
|
Gfx* displayList;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
lightDir.x = play->envCtx.dirLight1.params.dir.x;
|
|
|
|
|
lightDir.y = play->envCtx.dirLight1.params.dir.y;
|
|
|
|
|
lightDir.z = play->envCtx.dirLight1.params.dir.z;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
hilite = func_8002EB44(&actor->world.pos, &play->view.eye, &lightDir, play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (flag != 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
displayList = Graph_Alloc(play->state.gfxCtx, 2 * sizeof(Gfx));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
displayListHead = displayList;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
gDPSetHilite1Tile(displayListHead++, 1, hilite, 0x10, 0x10);
|
|
|
|
|
gSPEndDisplayList(displayListHead);
|
|
|
|
|
gSPSegment(POLY_XLU_DISP++, 0x07, displayList);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PosRot* Actor_GetFocus(PosRot* dest, Actor* actor) {
|
|
|
|
|
*dest = actor->focus;
|
|
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PosRot* Actor_GetWorld(PosRot* dest, Actor* actor) {
|
|
|
|
|
*dest = actor->world;
|
|
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PosRot* Actor_GetWorldPosShapeRot(PosRot* arg0, Actor* actor) {
|
|
|
|
|
PosRot sp1C;
|
|
|
|
|
|
|
|
|
|
Math_Vec3f_Copy(&sp1C.pos, &actor->world.pos);
|
|
|
|
|
sp1C.rot = actor->shape.rot;
|
|
|
|
|
*arg0 = sp1C;
|
|
|
|
|
|
|
|
|
|
return arg0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 func_8002EFC0(Actor* actor, Player* player, s16 arg2) {
|
|
|
|
|
s16 yawTemp = (s16)(actor->yawTowardsPlayer - 0x8000) - arg2;
|
|
|
|
|
s16 yawTempAbs = ABS(yawTemp);
|
|
|
|
|
|
|
|
|
|
if (player->unk_664 != NULL) {
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if ((yawTempAbs > 0x4000) || (actor->flags & ACTOR_FLAG_NO_LOCKON)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return FLT_MAX;
|
|
|
|
|
} else {
|
|
|
|
|
f32 ret =
|
|
|
|
|
actor->xyzDistToPlayerSq - actor->xyzDistToPlayerSq * 0.8f * ((0x4000 - yawTempAbs) * (1.0f / 0x8000));
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (yawTempAbs > 0x2AAA) {
|
|
|
|
|
return FLT_MAX;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return actor->xyzDistToPlayerSq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
/* 0x0 */ f32 rangeSq;
|
|
|
|
|
/* 0x4 */ f32 leashScale;
|
|
|
|
|
} TargetRangeParams; // size = 0x8
|
|
|
|
|
|
|
|
|
|
#define TARGET_RANGE(range, leash) \
|
|
|
|
|
{ SQ(range), (f32)range / leash }
|
|
|
|
|
|
|
|
|
|
TargetRangeParams D_80115FF8[] = {
|
|
|
|
|
TARGET_RANGE(70, 140), TARGET_RANGE(170, 255), TARGET_RANGE(280, 5600), TARGET_RANGE(350, 525),
|
|
|
|
|
TARGET_RANGE(700, 1050), TARGET_RANGE(1000, 1500), TARGET_RANGE(100, 105.36842), TARGET_RANGE(140, 163.33333),
|
|
|
|
|
TARGET_RANGE(240, 576), TARGET_RANGE(280, 280000),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
u32 func_8002F090(Actor* actor, f32 arg1) {
|
|
|
|
|
return arg1 < D_80115FF8[actor->targetMode].rangeSq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 func_8002F0C8(Actor* actor, Player* player, s32 flag) {
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if ((actor->update == NULL) || !(actor->flags & ACTOR_FLAG_TARGETABLE)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!flag) {
|
|
|
|
|
s16 var = (s16)(actor->yawTowardsPlayer - 0x8000) - player->actor.shape.rot.y;
|
|
|
|
|
s16 abs_var = ABS(var);
|
|
|
|
|
f32 dist;
|
|
|
|
|
|
|
|
|
|
if ((player->unk_664 == NULL) && (abs_var > 0x2AAA)) {
|
|
|
|
|
dist = FLT_MAX;
|
|
|
|
|
} else {
|
|
|
|
|
dist = actor->xyzDistToPlayerSq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return !func_8002F090(actor, D_80115FF8[actor->targetMode].leashScale * dist);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
u32 Actor_ProcessTalkRequest(Actor* actor, PlayState* play) {
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if (actor->flags & ACTOR_FLAG_PLAYER_TALKED_TO) {
|
|
|
|
|
actor->flags &= ~ACTOR_FLAG_PLAYER_TALKED_TO;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_8002F1C4(Actor* actor, PlayState* play, f32 arg2, f32 arg3, u32 exchangeItemId) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
// This is convoluted but it seems like it must be a single if statement to match
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if ((player->actor.flags & ACTOR_FLAG_PLAYER_TALKED_TO) || ((exchangeItemId != EXCH_ITEM_NONE) && Player_InCsMode(play)) ||
|
2022-03-21 21:51:23 -04:00
|
|
|
|
(!actor->isTargeted &&
|
|
|
|
|
((arg3 < fabsf(actor->yDistToPlayer)) || (player->targetActorDistance < actor->xzDistToPlayer) ||
|
|
|
|
|
(arg2 < actor->xzDistToPlayer)))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
player->targetActor = actor;
|
|
|
|
|
player->targetActorDistance = actor->xzDistToPlayer;
|
|
|
|
|
player->exchangeItemId = exchangeItemId;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_8002F298(Actor* actor, PlayState* play, f32 arg2, u32 exchangeItemId) {
|
|
|
|
|
return func_8002F1C4(actor, play, arg2, arg2, exchangeItemId);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_8002F2CC(Actor* actor, PlayState* play, f32 arg2) {
|
|
|
|
|
return func_8002F298(actor, play, arg2, EXCH_ITEM_NONE);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_8002F2F4(Actor* actor, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 var1 = 50.0f + actor->colChkInfo.cylRadius;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
return func_8002F2CC(actor, play, var1);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
u32 Actor_TextboxIsClosing(Actor* actor, PlayState* play) {
|
|
|
|
|
if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s8 func_8002F368(PlayState* play) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
return player->exchangeItemId;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_GetScreenPos(PlayState* play, Actor* actor, s16* x, s16* y) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Vec3f projectedPos;
|
|
|
|
|
f32 w;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002BE04(play, &actor->focus.pos, &projectedPos, &w);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*x = projectedPos.x * w * (SCREEN_WIDTH / 2) + (SCREEN_WIDTH / 2);
|
|
|
|
|
*y = projectedPos.y * w * -(SCREEN_HEIGHT / 2) + (SCREEN_HEIGHT / 2);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
u32 Actor_HasParent(Actor* actor, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (actor->parent != NULL) {
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-23 20:11:38 -04:00
|
|
|
|
/**
|
|
|
|
|
* Uses the given `GetItemEntry` to prepare the player to receive an item via the animation
|
|
|
|
|
* where Link holds an item over his head. This function does not require an actor for giving
|
|
|
|
|
* the player an item, instead setting the player as their own interactRangeActor and getItemDirection.
|
|
|
|
|
*
|
2022-11-06 03:24:34 -05:00
|
|
|
|
* \param play the Global Context
|
2022-08-23 20:11:38 -04:00
|
|
|
|
* \param getItemEntry the GetItemEntry for the item you want the player to receive.
|
|
|
|
|
* \return true if the player can receive an item, false if not.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 GiveItemEntryWithoutActor(PlayState* play, GetItemEntry getItemEntry) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
testing out item replacement (#416)
* skip learning song of storms
* don't set flag when getting goron tunic as child
* Initiates prelude check when master sword unloads.
Not quite how N64 rando does it but so far it's the only way I've found to make it trigger without also triggering the time travel again.
* Stops Shadow Temple lore prompts from appearing in rando.
* Skips cutscene of royal tomb explosion in rando.
Explosion sound doesn't play correctly and I think the debris appears in the wrong place, but the functionality is here.
* Improves visual of exploding gravestone.
* Adds some comments explaining the rando differences
* Skip ruto text box in jabu blue warp
For rando
* skip intro cutscene in dodongo's cavern
* load spoiler files on boot, fix spoilerfile existing check when making new saves
* name entry dropped spoiler logic
* make sure to actually init the cvar
* no chime on load
* uncomment
* Skip ganondrof cutscene
Skip to scream part of the death animation, skipping the text boxes etc. For rando
* Update z_boss_ganondrof.c
* skip owl flight cutscenes in rando
* Fixes skipped text so it only applies to shadow temple.
Earlier fix inadvertently applied to some other text as well, changed logic so that only specified sceneNums and textIds can have this enabled, and text skipped by sceneNum can have the skip overriden by textId if needed. Currently there are no overrides so the textId section of the logic is commented out to avoid compilation errors.
* Adds a default to the switch case statements that leaves the randoSkipText variable unchanged, just in case.
* TEST: Text for item
* Adding ganon flavor text
* ADD: AMMO Count
* format ganon text/hint text
* Autoskip the tower cutscene if settings call for tower collapse.
* ganon hint text logic
* Improved prelude after time travel fix
* swapped the sizes between ganon hint text and ganon text, as they were set to the wrong things.
* this is all i did
* not the cleanest code ever but it's working
* ADD: GS Count
* ADD: Wallter (crash for now)
* TWEAK: Wallet check
* FIX: Use DrawItem instread of DrawUpgrade... b-baka!
* Fixes some vanilla bugs introduced by rando code.
* Added cutscene skip for zelda escaping
Using the debug cutscene skipping function. Also added a conditional so the bridge doesn't spawn closed when cutscene is ready to trigger
* ADD: X Spacing + Placeholders for song
* ADD: default case for items
* TWEAK: Spacing
* FIX: Light Arrow
* ADD: Ammo Option
* use groups instead
* ADD: More spacing logic
* songs and names
* TWEAK: Color on wallet
* colors
* Added flags cutscene before nabooru fight
* ADD: ChromaKey text
* First attempt skip cs after nabooru defeat
* Better implementation for specific rando cutscene skips
* use pulseaudio defaults
* spaces/tabs
* move color push/pop to stop crash
* make the colors work again
* the real bottle fix
* pulseaudio values tuned for n64 audio at 44.1khz
* update tlength
* remove one hardcoded samplerate
* Cleaned up and fixed zelda escape skip
The if statement is a freaking monster, but unless we want to skip more cutscenes in the same way later, this is the most compact way of doing it that I know of.
* Revert one line to match original
nothing functional
* another hint line that breaks autonewline logic
* don't autospawn epona if we don't have the song/ocarina
* Trying to use iron knuckle death effects
not working yet
* Streamlined OoT cutscene skip for future additions
Also cleaned up if statement in general
* Made if statement more readable
Also added clarity for what cutscene was skipped
* Fixed typo in comment
* Janky nabooru defeat cs skip
* altar text formatting (gonna need help shortening some of the french ones)
* more altar text formatting
* english altar text formatting complete
* make gtg blocking guard check for card not bridge
* FIX: Typo!
* FIX: Uppercases
* FIX: Typo
* TWEAK: Alter + some names
* TWEAK: More caps!
* ADD: Missing string
TWEAK more uppercases and namefixe
s
* Hide nabooru death by covering her in flames
* bandaid fix for death crash issue
* Twinrova defeat cs skip
Skips the animation and manually calls the function to show the "beam" around the sisters
* fix crash
* fix caps to match
* fix great fairy reward mashing/shielding issue
* TWEAK : Typo clé to Clé
* TWEAK: Some Altar hints
TWEAK: Some capitals
* TWEAK: Unmatching text + some cap again
* TWEAK: More tweaks
* fix build
* remove extra json.hpp, add hint
* Update randomizer_item_tracker.cpp
* TWEAK: Double Defense with RedParticles instead of white
* make sure we don't optimize out the check to ensure a spoilerfile exists
* vanilla ganon boss key hint formatting
* TWEAK: FR- better way of the hero text
* fix
* and again
* Initializes dungeonsDone items in gSaveContext to 0.
* Replaces sizeof calculation with a NUM_DUNGEONS constant.
* Fixes Saria's Gift on the LW Bridge from getting killed when holding shield.
* More airtight fix for Saria's Gift on the Bridge.
* Lifts one of the conditions in the if statement a little higher to prevent unnecessary lookups of getItemId.
* Invalidate text box icon before drawing
* Fixes the case where Saria's gift is an Ice Trap.
We still get the Ice Trap once, but never again. This does mean you can now hold R while walking in to avoid the ice trap, but everything else seems to work fine.
* Initial commit
Might need changing when we change the settings in the future
* Fixes Door of Time opening cutscene after warping with prelude.
* Initial waterfall skip
Very rudimentary way of doing things but it seems to work so :shrug:
* inital rework
* fixed default rotation for 2D sprites
* fix tab/space issues
* 3d drops rando merge fix again
* Allows Impa to appear in the Lullaby check post drawbridge escape.
* Changes Ganon's Trials Count setting to a checkbox
The checkbox is whether or not to skip all of them. Leaving the box unchecked will mean doing all of them. Eventually this will be switched back to a slider once we implement the logic for which trials start out completed.
* Sets all Ganon's Trials to incomplete in new saves.
Fixes https://github.com/briaguya-ai/rando-issue-tracker/issues/131
* fix castle guards when oot throw cutscene has already played in rando
* Properly removes the beams when trials are cleared.
* Removes Question Mark from Skip Ganon's Trials UI.
* Adds a todo comment about when to change back to slider.
* make deku seeds check for bullet bag
* Various tweaks
TWEAK: Altar Text
TWEAK: Hint names
TWEAK: Replace more problematic œ to oe
* upgrade ocarina on both child and adult equips
* FIX: Jabu Item
* update equipped hookshot/longshot when obtained as other age
* add hint
* don't give the bgs check without the claim check
* Skips Darunia Cutscene in Fire Temple
* Added a TODO note about not skipping the cutscene.
There is a setting we will want to have eventually that will require this cutscene to not be skipped since it is used during a glitch.
* remove todo
* restore fast ocarina option in imgui that was lost in merge
* Fixes grey screen issue + tooltip for 2 handed shield
* update to use dg instead of g for textures in item tracker
* TWEAK: Default color for cosmetic RAND button was not the corect one
* fix texture crash, remove unused item tracker code
* don't open mask shop until we get zelda's letter
* Update README.md
* Prevents "correct" chime under incorrect conditions.
* Fixes typo in conditional and adds "bonk" sound effect.
"Bonk" sound is NA_SE_SY_OCARINA_ERROR and it plays when conditions for the Door of Time have not been met after playing Song of Time. This is only possible in rando's "Intended" Door of Time option, in which the Ocarina of Time and all 3 spritual stones are required to open the door, instead of the vanilla requirements of just having the song of time.
* remove modify dpad equips toggle, replace with checks for dpad menu
* remove extra check
* add ability to hold c-up to assign to dpad when dpad menuing is enabled
* disable d-pad navigation on item menu when holding c-up to equip
* dpad+c-up stuff for equipment menu
* ADD: Checbox for songs colors
* TWEAK: RandoColors for normal songs
* kind of quick and dirty but it works
* TWEAK: Clarity of the tooltip
Co-authored-by: briaguya <briaguya@alice>
Co-authored-by: Christopher Leggett <chris@leggett.dev>
Co-authored-by: aMannus <mannusmenting@gmail.com>
Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com>
Co-authored-by: Dog <5172592+Dog@users.noreply.github.com>
Co-authored-by: Vague Rant <vaguerant@users.noreply.github.com>
Co-authored-by: Baoulettes <perlouzerie@hotmail.fr>
Co-authored-by: Ada <60364512+GreatArgorath@users.noreply.github.com>
2022-07-11 20:11:07 -04:00
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
if (!(player->stateFlags1 &
|
|
|
|
|
(PLAYER_STATE1_DEAD | PLAYER_STATE1_CHARGING_SPIN_ATTACK | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE |
|
|
|
|
|
PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_FIRST_PERSON | PLAYER_STATE1_CLIMBING_LADDER)) &&
|
|
|
|
|
Player_GetExplosiveHeld(player) < 0) {
|
2022-08-23 20:11:38 -04:00
|
|
|
|
if (((player->heldActor != NULL) && ((getItemEntry.getItemId > GI_NONE) && (getItemEntry.getItemId < GI_MAX)) ||
|
2023-09-26 10:20:33 -04:00
|
|
|
|
(IS_RANDO && (getItemEntry.getItemId > RG_NONE) && (getItemEntry.getItemId < RG_MAX))) ||
|
2024-02-15 20:17:28 -05:00
|
|
|
|
(!(player->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE)))) {
|
2022-08-23 20:11:38 -04:00
|
|
|
|
if ((getItemEntry.getItemId != GI_NONE)) {
|
|
|
|
|
player->getItemEntry = getItemEntry;
|
|
|
|
|
player->getItemId = getItemEntry.getItemId;
|
testing out item replacement (#416)
* skip learning song of storms
* don't set flag when getting goron tunic as child
* Initiates prelude check when master sword unloads.
Not quite how N64 rando does it but so far it's the only way I've found to make it trigger without also triggering the time travel again.
* Stops Shadow Temple lore prompts from appearing in rando.
* Skips cutscene of royal tomb explosion in rando.
Explosion sound doesn't play correctly and I think the debris appears in the wrong place, but the functionality is here.
* Improves visual of exploding gravestone.
* Adds some comments explaining the rando differences
* Skip ruto text box in jabu blue warp
For rando
* skip intro cutscene in dodongo's cavern
* load spoiler files on boot, fix spoilerfile existing check when making new saves
* name entry dropped spoiler logic
* make sure to actually init the cvar
* no chime on load
* uncomment
* Skip ganondrof cutscene
Skip to scream part of the death animation, skipping the text boxes etc. For rando
* Update z_boss_ganondrof.c
* skip owl flight cutscenes in rando
* Fixes skipped text so it only applies to shadow temple.
Earlier fix inadvertently applied to some other text as well, changed logic so that only specified sceneNums and textIds can have this enabled, and text skipped by sceneNum can have the skip overriden by textId if needed. Currently there are no overrides so the textId section of the logic is commented out to avoid compilation errors.
* Adds a default to the switch case statements that leaves the randoSkipText variable unchanged, just in case.
* TEST: Text for item
* Adding ganon flavor text
* ADD: AMMO Count
* format ganon text/hint text
* Autoskip the tower cutscene if settings call for tower collapse.
* ganon hint text logic
* Improved prelude after time travel fix
* swapped the sizes between ganon hint text and ganon text, as they were set to the wrong things.
* this is all i did
* not the cleanest code ever but it's working
* ADD: GS Count
* ADD: Wallter (crash for now)
* TWEAK: Wallet check
* FIX: Use DrawItem instread of DrawUpgrade... b-baka!
* Fixes some vanilla bugs introduced by rando code.
* Added cutscene skip for zelda escaping
Using the debug cutscene skipping function. Also added a conditional so the bridge doesn't spawn closed when cutscene is ready to trigger
* ADD: X Spacing + Placeholders for song
* ADD: default case for items
* TWEAK: Spacing
* FIX: Light Arrow
* ADD: Ammo Option
* use groups instead
* ADD: More spacing logic
* songs and names
* TWEAK: Color on wallet
* colors
* Added flags cutscene before nabooru fight
* ADD: ChromaKey text
* First attempt skip cs after nabooru defeat
* Better implementation for specific rando cutscene skips
* use pulseaudio defaults
* spaces/tabs
* move color push/pop to stop crash
* make the colors work again
* the real bottle fix
* pulseaudio values tuned for n64 audio at 44.1khz
* update tlength
* remove one hardcoded samplerate
* Cleaned up and fixed zelda escape skip
The if statement is a freaking monster, but unless we want to skip more cutscenes in the same way later, this is the most compact way of doing it that I know of.
* Revert one line to match original
nothing functional
* another hint line that breaks autonewline logic
* don't autospawn epona if we don't have the song/ocarina
* Trying to use iron knuckle death effects
not working yet
* Streamlined OoT cutscene skip for future additions
Also cleaned up if statement in general
* Made if statement more readable
Also added clarity for what cutscene was skipped
* Fixed typo in comment
* Janky nabooru defeat cs skip
* altar text formatting (gonna need help shortening some of the french ones)
* more altar text formatting
* english altar text formatting complete
* make gtg blocking guard check for card not bridge
* FIX: Typo!
* FIX: Uppercases
* FIX: Typo
* TWEAK: Alter + some names
* TWEAK: More caps!
* ADD: Missing string
TWEAK more uppercases and namefixe
s
* Hide nabooru death by covering her in flames
* bandaid fix for death crash issue
* Twinrova defeat cs skip
Skips the animation and manually calls the function to show the "beam" around the sisters
* fix crash
* fix caps to match
* fix great fairy reward mashing/shielding issue
* TWEAK : Typo clé to Clé
* TWEAK: Some Altar hints
TWEAK: Some capitals
* TWEAK: Unmatching text + some cap again
* TWEAK: More tweaks
* fix build
* remove extra json.hpp, add hint
* Update randomizer_item_tracker.cpp
* TWEAK: Double Defense with RedParticles instead of white
* make sure we don't optimize out the check to ensure a spoilerfile exists
* vanilla ganon boss key hint formatting
* TWEAK: FR- better way of the hero text
* fix
* and again
* Initializes dungeonsDone items in gSaveContext to 0.
* Replaces sizeof calculation with a NUM_DUNGEONS constant.
* Fixes Saria's Gift on the LW Bridge from getting killed when holding shield.
* More airtight fix for Saria's Gift on the Bridge.
* Lifts one of the conditions in the if statement a little higher to prevent unnecessary lookups of getItemId.
* Invalidate text box icon before drawing
* Fixes the case where Saria's gift is an Ice Trap.
We still get the Ice Trap once, but never again. This does mean you can now hold R while walking in to avoid the ice trap, but everything else seems to work fine.
* Initial commit
Might need changing when we change the settings in the future
* Fixes Door of Time opening cutscene after warping with prelude.
* Initial waterfall skip
Very rudimentary way of doing things but it seems to work so :shrug:
* inital rework
* fixed default rotation for 2D sprites
* fix tab/space issues
* 3d drops rando merge fix again
* Allows Impa to appear in the Lullaby check post drawbridge escape.
* Changes Ganon's Trials Count setting to a checkbox
The checkbox is whether or not to skip all of them. Leaving the box unchecked will mean doing all of them. Eventually this will be switched back to a slider once we implement the logic for which trials start out completed.
* Sets all Ganon's Trials to incomplete in new saves.
Fixes https://github.com/briaguya-ai/rando-issue-tracker/issues/131
* fix castle guards when oot throw cutscene has already played in rando
* Properly removes the beams when trials are cleared.
* Removes Question Mark from Skip Ganon's Trials UI.
* Adds a todo comment about when to change back to slider.
* make deku seeds check for bullet bag
* Various tweaks
TWEAK: Altar Text
TWEAK: Hint names
TWEAK: Replace more problematic œ to oe
* upgrade ocarina on both child and adult equips
* FIX: Jabu Item
* update equipped hookshot/longshot when obtained as other age
* add hint
* don't give the bgs check without the claim check
* Skips Darunia Cutscene in Fire Temple
* Added a TODO note about not skipping the cutscene.
There is a setting we will want to have eventually that will require this cutscene to not be skipped since it is used during a glitch.
* remove todo
* restore fast ocarina option in imgui that was lost in merge
* Fixes grey screen issue + tooltip for 2 handed shield
* update to use dg instead of g for textures in item tracker
* TWEAK: Default color for cosmetic RAND button was not the corect one
* fix texture crash, remove unused item tracker code
* don't open mask shop until we get zelda's letter
* Update README.md
* Prevents "correct" chime under incorrect conditions.
* Fixes typo in conditional and adds "bonk" sound effect.
"Bonk" sound is NA_SE_SY_OCARINA_ERROR and it plays when conditions for the Door of Time have not been met after playing Song of Time. This is only possible in rando's "Intended" Door of Time option, in which the Ocarina of Time and all 3 spritual stones are required to open the door, instead of the vanilla requirements of just having the song of time.
* remove modify dpad equips toggle, replace with checks for dpad menu
* remove extra check
* add ability to hold c-up to assign to dpad when dpad menuing is enabled
* disable d-pad navigation on item menu when holding c-up to equip
* dpad+c-up stuff for equipment menu
* ADD: Checbox for songs colors
* TWEAK: RandoColors for normal songs
* kind of quick and dirty but it works
* TWEAK: Clarity of the tooltip
Co-authored-by: briaguya <briaguya@alice>
Co-authored-by: Christopher Leggett <chris@leggett.dev>
Co-authored-by: aMannus <mannusmenting@gmail.com>
Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com>
Co-authored-by: Dog <5172592+Dog@users.noreply.github.com>
Co-authored-by: Vague Rant <vaguerant@users.noreply.github.com>
Co-authored-by: Baoulettes <perlouzerie@hotmail.fr>
Co-authored-by: Ada <60364512+GreatArgorath@users.noreply.github.com>
2022-07-11 20:11:07 -04:00
|
|
|
|
player->interactRangeActor = &player->actor;
|
|
|
|
|
player->getItemDirection = player->actor.shape.rot.y;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-23 20:11:38 -04:00
|
|
|
|
/**
|
|
|
|
|
* Uses the given `GetItemEntry` to prepare the player to receive an item via the animation
|
|
|
|
|
* where Link holds an item over his head. This uses data from the actor link is receiving
|
|
|
|
|
* the item from to set the player's interactRangeActor and getItemDirection. It also checks
|
|
|
|
|
* a range from which Link must be from said actor in order to receive the item.
|
|
|
|
|
*
|
|
|
|
|
* \param actor the actor link is receiving an item from. Will usually be a chest but can also
|
|
|
|
|
* be an npc.
|
2022-11-06 03:24:34 -05:00
|
|
|
|
* \param play the Global Context
|
2022-08-23 20:11:38 -04:00
|
|
|
|
* \param getItemEntry the GetItemEntry for the item you want the player to receive.
|
|
|
|
|
* \param xzRange the distance on the x and z axes that the player can be from the target
|
|
|
|
|
* actor to receive the item.
|
|
|
|
|
* \param yRange the distance on the y axis that the player can be from the target actor
|
|
|
|
|
* to receive the item.
|
|
|
|
|
* \return true if the player can receive an item, false if not.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 GiveItemEntryFromActor(Actor* actor, PlayState* play, GetItemEntry getItemEntry, f32 xzRange, f32 yRange) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-08-23 20:11:38 -04:00
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
if (!(player->stateFlags1 &
|
|
|
|
|
(PLAYER_STATE1_DEAD | PLAYER_STATE1_CHARGING_SPIN_ATTACK | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE |
|
|
|
|
|
PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_FIRST_PERSON | PLAYER_STATE1_CLIMBING_LADDER)) &&
|
|
|
|
|
Player_GetExplosiveHeld(player) < 0) {
|
2022-08-23 20:11:38 -04:00
|
|
|
|
if ((((player->heldActor != NULL) || (actor == player->targetActor)) &&
|
2023-09-26 10:20:33 -04:00
|
|
|
|
((!IS_RANDO && ((getItemEntry.getItemId > GI_NONE) && (getItemEntry.getItemId < GI_MAX))) ||
|
|
|
|
|
(IS_RANDO && ((getItemEntry.getItemId > RG_NONE) && (getItemEntry.getItemId < RG_MAX))))) ||
|
2024-02-15 20:17:28 -05:00
|
|
|
|
(!(player->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE)))) {
|
2022-08-23 20:11:38 -04:00
|
|
|
|
if ((actor->xzDistToPlayer < xzRange) && (fabsf(actor->yDistToPlayer) < yRange)) {
|
|
|
|
|
s16 yawDiff = actor->yawTowardsPlayer - player->actor.shape.rot.y;
|
|
|
|
|
s32 absYawDiff = ABS(yawDiff);
|
|
|
|
|
|
|
|
|
|
if ((getItemEntry.getItemId != GI_NONE) || (player->getItemDirection < absYawDiff)) {
|
2022-12-20 23:32:01 -05:00
|
|
|
|
iceTrapScale = 0.0f;
|
2022-08-23 20:11:38 -04:00
|
|
|
|
player->getItemEntry = getItemEntry;
|
|
|
|
|
player->getItemId = getItemEntry.getItemId;
|
|
|
|
|
player->interactRangeActor = actor;
|
|
|
|
|
player->getItemDirection = absYawDiff;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Uses the given `GetItemEntry` to prepare the player to receive an item via the animation
|
|
|
|
|
* where Link holds an item over his head. This is a wrapper function around `GiveItemEntryFromActor`
|
|
|
|
|
* that supplies a fixed xzRange of 50.0f and a fixed yRange of 10.0f.
|
|
|
|
|
*
|
|
|
|
|
* \param actor the target actor that link is receiving an item from.
|
2022-11-06 03:24:34 -05:00
|
|
|
|
* \param play the Global Context
|
2022-08-23 20:11:38 -04:00
|
|
|
|
* \param getItemEntry the GetItemEntry for the item you want the player to receive.
|
|
|
|
|
*/
|
2024-01-14 13:16:32 -05:00
|
|
|
|
s32 GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemEntry getItemEntry) {
|
|
|
|
|
return GiveItemEntryFromActor(actor, play, getItemEntry, 50.0f, 10.0f);
|
2022-08-23 20:11:38 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If you're doing something for randomizer, you're probably looking for GiveItemEntryFromActor
|
2024-04-03 21:07:42 -04:00
|
|
|
|
s32 Actor_OfferGetItem(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
if (!(player->stateFlags1 &
|
|
|
|
|
(PLAYER_STATE1_DEAD | PLAYER_STATE1_CHARGING_SPIN_ATTACK | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE |
|
|
|
|
|
PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_FIRST_PERSON | PLAYER_STATE1_CLIMBING_LADDER)) &&
|
|
|
|
|
Player_GetExplosiveHeld(player) < 0) {
|
2022-08-23 20:11:38 -04:00
|
|
|
|
if ((((player->heldActor != NULL) || (actor == player->targetActor)) &&
|
2023-09-26 10:20:33 -04:00
|
|
|
|
((!IS_RANDO && ((getItemId > GI_NONE) && (getItemId < GI_MAX))) || (IS_RANDO && ((getItemId > RG_NONE) && (getItemId < RG_MAX))))) ||
|
2024-02-15 20:17:28 -05:00
|
|
|
|
(!(player->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE)))) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if ((actor->xzDistToPlayer < xzRange) && (fabsf(actor->yDistToPlayer) < yRange)) {
|
|
|
|
|
s16 yawDiff = actor->yawTowardsPlayer - player->actor.shape.rot.y;
|
|
|
|
|
s32 absYawDiff = ABS(yawDiff);
|
|
|
|
|
|
|
|
|
|
if ((getItemId != GI_NONE) || (player->getItemDirection < absYawDiff)) {
|
|
|
|
|
player->getItemId = getItemId;
|
|
|
|
|
player->interactRangeActor = actor;
|
|
|
|
|
player->getItemDirection = absYawDiff;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-23 20:11:38 -04:00
|
|
|
|
// TODO: Rename to GiveItemIdFromActorWithFixedRange or similar
|
|
|
|
|
// If you're doing something for randomizer, you're probably looking for GiveItemEntryFromActorWithFixedRange
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002F554(Actor* actor, PlayState* play, s32 getItemId) {
|
2024-04-03 21:07:42 -04:00
|
|
|
|
Actor_OfferGetItem(actor, play, getItemId, 50.0f, 10.0f);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002F580(Actor* actor, PlayState* play) {
|
|
|
|
|
func_8002F554(actor, play, GI_NONE);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
u32 Actor_HasNoParent(Actor* actor, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (actor->parent == NULL) {
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002F5C4(Actor* actorA, Actor* actorB, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor* parent = actorA->parent;
|
|
|
|
|
|
|
|
|
|
if (parent->id == ACTOR_PLAYER) {
|
|
|
|
|
Player* player = (Player*)parent;
|
|
|
|
|
|
|
|
|
|
player->heldActor = actorB;
|
|
|
|
|
player->interactRangeActor = actorB;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parent->child = actorB;
|
|
|
|
|
actorB->parent = parent;
|
|
|
|
|
actorA->parent = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002F5F0(Actor* actor, PlayState* play) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-11-26 11:54:54 -05:00
|
|
|
|
if (actor->xyzDistToPlayerSq < player->closestSecretDistSq) {
|
|
|
|
|
player->closestSecretDistSq = actor->xyzDistToPlayerSq;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Actor_IsMounted(PlayState* play, Actor* horse) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (horse->child != NULL) {
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
u32 Actor_SetRideActor(PlayState* play, Actor* horse, s32 mountSide) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
if (!(player->stateFlags1 &
|
|
|
|
|
(PLAYER_STATE1_DEAD | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_CHARGING_SPIN_ATTACK | PLAYER_STATE1_HANGING_OFF_LEDGE |
|
|
|
|
|
PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_FIRST_PERSON | PLAYER_STATE1_CLIMBING_LADDER))) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
player->rideActor = horse;
|
|
|
|
|
player->mountSide = mountSide;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Actor_NotMounted(PlayState* play, Actor* horse) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (horse->child == NULL) {
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002F698(PlayState* play, Actor* actor, f32 arg2, s16 arg3, f32 arg4, u32 arg5, u32 arg6) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
player->unk_8A0 = arg6;
|
|
|
|
|
player->unk_8A1 = arg5;
|
|
|
|
|
player->unk_8A2 = arg3;
|
|
|
|
|
player->unk_8A4 = arg2;
|
|
|
|
|
player->unk_8A8 = arg4;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002F6D4(PlayState* play, Actor* actor, f32 arg2, s16 arg3, f32 arg4, u32 arg5) {
|
|
|
|
|
func_8002F698(play, actor, arg2, arg3, arg4, 2, arg5);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002F71C(PlayState* play, Actor* actor, f32 arg2, s16 arg3, f32 arg4) {
|
|
|
|
|
func_8002F6D4(play, actor, arg2, arg3, arg4, 0);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002F758(PlayState* play, Actor* actor, f32 arg2, s16 arg3, f32 arg4, u32 arg5) {
|
|
|
|
|
func_8002F698(play, actor, arg2, arg3, arg4, 1, arg5);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002F7A0(PlayState* play, Actor* actor, f32 arg2, s16 arg3, f32 arg4) {
|
|
|
|
|
func_8002F758(play, actor, arg2, arg3, arg4, 0);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-09-15 14:39:46 -04:00
|
|
|
|
void Player_PlaySfx(Actor* actor, u16 sfxId) {
|
2023-04-07 15:54:26 -04:00
|
|
|
|
if (actor->id != ACTOR_PLAYER || sfxId < NA_SE_VO_LI_SWORD_N || sfxId > NA_SE_VO_LI_ELECTRIC_SHOCK_LV_KID) {
|
|
|
|
|
Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &D_801333E0 , &D_801333E0, &D_801333E8);
|
|
|
|
|
} else {
|
2024-05-05 15:14:55 -04:00
|
|
|
|
freqMultiplier = CVarGetFloat(CVAR_AUDIO("LinkVoiceFreqMultiplier"), 1.0);
|
2023-04-07 15:54:26 -04:00
|
|
|
|
if (freqMultiplier <= 0) {
|
|
|
|
|
freqMultiplier = 1;
|
|
|
|
|
}
|
|
|
|
|
// Authentic behavior uses D_801333E0 for both freqScale and a4
|
|
|
|
|
// Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &D_801333E0 , &D_801333E0, &D_801333E8);
|
|
|
|
|
Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &freqMultiplier, &D_801333E0, &D_801333E8);
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Audio_PlayActorSound2(Actor* actor, u16 sfxId) {
|
|
|
|
|
func_80078914(&actor->projectedPos, sfxId);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002F850(PlayState* play, Actor* actor) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 sfxId;
|
|
|
|
|
|
|
|
|
|
if (actor->bgCheckFlags & 0x20) {
|
|
|
|
|
if (actor->yDistToWater < 20.0f) {
|
|
|
|
|
sfxId = NA_SE_PL_WALK_WATER0 - SFX_FLAG;
|
|
|
|
|
} else {
|
|
|
|
|
sfxId = NA_SE_PL_WALK_WATER1 - SFX_FLAG;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
sfxId = SurfaceType_GetSfx(&play->colCtx, actor->floorPoly, actor->floorBgId);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func_80078914(&actor->projectedPos, NA_SE_EV_BOMB_BOUND);
|
|
|
|
|
func_80078914(&actor->projectedPos, sfxId + SFX_FLAG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002F8F0(Actor* actor, u16 sfxId) {
|
|
|
|
|
actor->sfx = sfxId;
|
2023-05-30 15:05:04 -04:00
|
|
|
|
actor->flags |= ACTOR_FLAG_SFX_AT_POS;
|
|
|
|
|
actor->flags &= ~(ACTOR_FLAG_SFX_AT_CENTER | ACTOR_FLAG_SFX_AT_CENTER2 | ACTOR_FLAG_SFX_AS_TIMER);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002F91C(Actor* actor, u16 sfxId) {
|
|
|
|
|
actor->sfx = sfxId;
|
2023-05-30 15:05:04 -04:00
|
|
|
|
actor->flags |= ACTOR_FLAG_SFX_AT_CENTER;
|
|
|
|
|
actor->flags &= ~(ACTOR_FLAG_SFX_AT_POS | ACTOR_FLAG_SFX_AT_CENTER2 | ACTOR_FLAG_SFX_AS_TIMER);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002F948(Actor* actor, u16 sfxId) {
|
|
|
|
|
actor->sfx = sfxId;
|
2023-05-30 15:05:04 -04:00
|
|
|
|
actor->flags |= ACTOR_FLAG_SFX_AT_CENTER2;
|
|
|
|
|
actor->flags &= ~(ACTOR_FLAG_SFX_AT_POS | ACTOR_FLAG_SFX_AT_CENTER | ACTOR_FLAG_SFX_AS_TIMER);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002F974(Actor* actor, u16 sfxId) {
|
2023-05-30 15:05:04 -04:00
|
|
|
|
actor->flags &= ~(ACTOR_FLAG_SFX_AT_POS | ACTOR_FLAG_SFX_AT_CENTER | ACTOR_FLAG_SFX_AT_CENTER2 | ACTOR_FLAG_SFX_AS_TIMER);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->sfx = sfxId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_8002F994(Actor* actor, s32 arg1) {
|
2023-05-30 15:05:04 -04:00
|
|
|
|
actor->flags |= ACTOR_FLAG_SFX_AS_TIMER;
|
|
|
|
|
actor->flags &= ~(ACTOR_FLAG_SFX_AT_POS | ACTOR_FLAG_SFX_AT_CENTER | ACTOR_FLAG_SFX_AT_CENTER2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (arg1 < 40) {
|
|
|
|
|
actor->sfx = NA_SE_PL_WALK_DIRT - SFX_FLAG;
|
|
|
|
|
} else if (arg1 < 100) {
|
|
|
|
|
actor->sfx = NA_SE_PL_WALK_CONCRETE - SFX_FLAG;
|
|
|
|
|
} else {
|
|
|
|
|
actor->sfx = NA_SE_PL_WALK_SAND - SFX_FLAG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests if something hit Jabu Jabu surface, displaying hit splash and playing sfx if true
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_8002F9EC(PlayState* play, Actor* actor, CollisionPoly* poly, s32 bgId, Vec3f* pos) {
|
|
|
|
|
if (func_80041D4C(&play->colCtx, poly, bgId) == 8) {
|
|
|
|
|
play->roomCtx.unk_74[0] = 1;
|
|
|
|
|
CollisionCheck_BlueBlood(play, NULL, pos);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Audio_PlayActorSound2(actor, NA_SE_IT_WALL_HIT_BUYO);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Local data used for Farore's Wind light (stored in BSS, possibly a struct?)
|
|
|
|
|
LightInfo D_8015BC00;
|
|
|
|
|
LightNode* D_8015BC10;
|
|
|
|
|
s32 D_8015BC14;
|
|
|
|
|
f32 D_8015BC18;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8002FA60(PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Vec3f lightPos;
|
|
|
|
|
|
|
|
|
|
if (gSaveContext.fw.set) {
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].data = 0x28;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].pos.x = gSaveContext.fw.pos.x;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].pos.y = gSaveContext.fw.pos.y;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].pos.z = gSaveContext.fw.pos.z;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].yaw = gSaveContext.fw.yaw;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].playerParams = gSaveContext.fw.playerParams;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].entranceIndex = gSaveContext.fw.entranceIndex;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].roomIndex = gSaveContext.fw.roomIndex;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].tempSwchFlags = gSaveContext.fw.tempSwchFlags;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].tempCollectFlags = gSaveContext.fw.tempCollectFlags;
|
|
|
|
|
} else {
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].data = 0;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].pos.x = 0.0f;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].pos.y = 0.0f;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].pos.z = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lightPos.x = gSaveContext.respawn[RESPAWN_MODE_TOP].pos.x;
|
|
|
|
|
lightPos.y = gSaveContext.respawn[RESPAWN_MODE_TOP].pos.y + 80.0f;
|
|
|
|
|
lightPos.z = gSaveContext.respawn[RESPAWN_MODE_TOP].pos.z;
|
|
|
|
|
|
|
|
|
|
Lights_PointNoGlowSetInfo(&D_8015BC00, lightPos.x, lightPos.y, lightPos.z, 0xFF, 0xFF, 0xFF, -1);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
D_8015BC10 = LightContext_InsertLight(play, &play->lightCtx, &D_8015BC00);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
D_8015BC14 = 0;
|
|
|
|
|
D_8015BC18 = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_DrawFaroresWindPointer(PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 lightRadius = -1;
|
|
|
|
|
s32 params;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
params = gSaveContext.respawn[RESPAWN_MODE_TOP].data;
|
|
|
|
|
|
|
|
|
|
if (params) {
|
|
|
|
|
f32 yOffset = LINK_IS_ADULT ? 80.0f : 60.0f;
|
|
|
|
|
f32 ratio = 1.0f;
|
|
|
|
|
s32 alpha = 255;
|
|
|
|
|
s32 temp = params - 40;
|
|
|
|
|
|
|
|
|
|
if (temp < 0) {
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].data = ++params;
|
|
|
|
|
ratio = ABS(params) * 0.025f;
|
|
|
|
|
D_8015BC14 = 60;
|
|
|
|
|
D_8015BC18 = 1.0f;
|
|
|
|
|
} else if (D_8015BC14) {
|
2024-04-25 20:31:28 -04:00
|
|
|
|
D_8015BC14-= CVarGetInteger(CVAR_ENHANCEMENT("FastFarores"), 0) ? 5 : 1;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else if (D_8015BC18 > 0.0f) {
|
|
|
|
|
static Vec3f effectVel = { 0.0f, -0.05f, 0.0f };
|
|
|
|
|
static Vec3f effectAccel = { 0.0f, -0.025f, 0.0f };
|
|
|
|
|
static Color_RGBA8 effectPrimCol = { 255, 255, 255, 0 };
|
|
|
|
|
static Color_RGBA8 effectEnvCol = { 100, 200, 0, 0 };
|
|
|
|
|
Vec3f* curPos = &gSaveContext.respawn[RESPAWN_MODE_TOP].pos;
|
|
|
|
|
Vec3f* nextPos = &gSaveContext.respawn[RESPAWN_MODE_DOWN].pos;
|
|
|
|
|
f32 prevNum = D_8015BC18;
|
|
|
|
|
Vec3f dist;
|
|
|
|
|
f32 diff = Math_Vec3f_DistXYZAndStoreDiff(nextPos, curPos, &dist);
|
|
|
|
|
Vec3f effectPos;
|
|
|
|
|
f32 factor;
|
|
|
|
|
f32 length;
|
|
|
|
|
f32 dx;
|
|
|
|
|
f32 speed;
|
|
|
|
|
|
|
|
|
|
if (diff < 20.0f) {
|
|
|
|
|
D_8015BC18 = 0.0f;
|
|
|
|
|
Math_Vec3f_Copy(curPos, nextPos);
|
|
|
|
|
} else {
|
|
|
|
|
length = diff * (1.0f / D_8015BC18);
|
|
|
|
|
speed = 20.0f / length;
|
|
|
|
|
speed = CLAMP_MIN(speed, 0.05f);
|
|
|
|
|
Math_StepToF(&D_8015BC18, 0.0f, speed);
|
|
|
|
|
factor = (diff * (D_8015BC18 / prevNum)) / diff;
|
|
|
|
|
curPos->x = nextPos->x + (dist.x * factor);
|
|
|
|
|
curPos->y = nextPos->y + (dist.y * factor);
|
|
|
|
|
curPos->z = nextPos->z + (dist.z * factor);
|
|
|
|
|
length *= 0.5f;
|
|
|
|
|
dx = diff - length;
|
|
|
|
|
yOffset += sqrtf(SQ(length) - SQ(dx)) * 0.2f;
|
|
|
|
|
osSyncPrintf("-------- DISPLAY Y=%f\n", yOffset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
effectPos.x = curPos->x + Rand_CenteredFloat(6.0f);
|
|
|
|
|
effectPos.y = curPos->y + 80.0f + (6.0f * Rand_ZeroOne());
|
|
|
|
|
effectPos.z = curPos->z + Rand_CenteredFloat(6.0f);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
EffectSsKiraKira_SpawnDispersed(play, &effectPos, &effectVel, &effectAccel, &effectPrimCol,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
&effectEnvCol, 1000, 16);
|
|
|
|
|
|
|
|
|
|
if (D_8015BC18 == 0.0f) {
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP] = gSaveContext.respawn[RESPAWN_MODE_DOWN];
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].playerParams = 0x06FF;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].data = 40;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].pos = *curPos;
|
|
|
|
|
} else if (temp > 0) {
|
|
|
|
|
Vec3f* curPos = &gSaveContext.respawn[RESPAWN_MODE_TOP].pos;
|
|
|
|
|
f32 nextRatio = 1.0f - temp * 0.1f;
|
|
|
|
|
f32 curRatio = 1.0f - (f32)(temp - 1) * 0.1f;
|
|
|
|
|
Vec3f eye;
|
|
|
|
|
Vec3f dist;
|
|
|
|
|
f32 diff;
|
|
|
|
|
|
|
|
|
|
if (nextRatio > 0.0f) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
eye.x = play->view.eye.x;
|
|
|
|
|
eye.y = play->view.eye.y - yOffset;
|
|
|
|
|
eye.z = play->view.eye.z;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
diff = Math_Vec3f_DistXYZAndStoreDiff(&eye, curPos, &dist);
|
|
|
|
|
diff = (diff * (nextRatio / curRatio)) / diff;
|
|
|
|
|
curPos->x = eye.x + (dist.x * diff);
|
|
|
|
|
curPos->y = eye.y + (dist.y * diff);
|
|
|
|
|
curPos->z = eye.z + (dist.z * diff);
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].pos = *curPos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
alpha = 255 - (temp * 30);
|
|
|
|
|
|
|
|
|
|
if (alpha < 0) {
|
|
|
|
|
gSaveContext.fw.set = 0;
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].data = 0;
|
|
|
|
|
alpha = 0;
|
|
|
|
|
} else {
|
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_TOP].data = ++params;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ratio = 1.0f + ((f32)temp * 0.2); // required to match
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lightRadius = 500.0f * ratio;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if ((play->csCtx.state == CS_STATE_IDLE) &&
|
2022-03-21 21:51:23 -04:00
|
|
|
|
(((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].entranceIndex) ==
|
|
|
|
|
((void)0, gSaveContext.entranceIndex)) &&
|
2022-11-06 03:24:34 -05:00
|
|
|
|
(((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].roomIndex) == play->roomCtx.curRoom.num)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 scale = 0.025f * ratio;
|
|
|
|
|
|
2022-11-29 18:29:36 -05:00
|
|
|
|
POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 0x19);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
Matrix_Translate(((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].pos.x),
|
|
|
|
|
((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].pos.y) + yOffset,
|
|
|
|
|
((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].pos.z), MTXMODE_NEW);
|
|
|
|
|
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Matrix_Push();
|
|
|
|
|
|
|
|
|
|
gDPPipeSync(POLY_XLU_DISP++);
|
|
|
|
|
gDPSetPrimColor(POLY_XLU_DISP++, 128, 128, 255, 255, 200, alpha);
|
|
|
|
|
gDPSetEnvColor(POLY_XLU_DISP++, 100, 200, 0, 255);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Matrix_RotateZ(((play->gameplayFrames * 1500) & 0xFFFF) * M_PI / 32768.0f, MTXMODE_APPLY);
|
|
|
|
|
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
|
|
|
|
|
gSPDisplayList(POLY_XLU_DISP++, gEffFlash1DL);
|
|
|
|
|
|
|
|
|
|
Matrix_Pop();
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Matrix_RotateZ(~((play->gameplayFrames * 1200) & 0xFFFF) * M_PI / 32768.0f, MTXMODE_APPLY);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
|
|
|
|
|
gSPDisplayList(POLY_XLU_DISP++, gEffFlash1DL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Lights_PointNoGlowSetInfo(&D_8015BC00, ((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].pos.x),
|
|
|
|
|
((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].pos.y) + yOffset,
|
|
|
|
|
((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].pos.z), 255, 255, 255, lightRadius);
|
|
|
|
|
|
|
|
|
|
}
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80030488(PlayState* play) {
|
|
|
|
|
LightContext_RemoveLight(play, &play->lightCtx, D_8015BC10);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_DisableLens(PlayState* play) {
|
|
|
|
|
if (play->actorCtx.lensActive) {
|
|
|
|
|
play->actorCtx.lensActive = false;
|
2023-10-19 19:13:33 -04:00
|
|
|
|
Magic_Reset(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Actor_InitContext
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_800304DC(PlayState* play, ActorContext* actorCtx, ActorEntry* actorEntry) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
SavedSceneFlags* savedSceneFlags;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
savedSceneFlags = &gSaveContext.sceneFlags[play->sceneNum];
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
memset(actorCtx, 0, sizeof(*actorCtx));
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Matrix_MtxFCopy(&play->billboardMtxF, &gMtxFClear);
|
|
|
|
|
Matrix_MtxFCopy(&play->viewProjectionMtxF, &gMtxFClear);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
actorCtx->flags.chest = savedSceneFlags->chest;
|
|
|
|
|
actorCtx->flags.swch = savedSceneFlags->swch;
|
|
|
|
|
actorCtx->flags.clear = savedSceneFlags->clear;
|
|
|
|
|
actorCtx->flags.collect = savedSceneFlags->collect;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002CDE4(play, &actorCtx->titleCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
actorCtx->absoluteSpace = NULL;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_SpawnEntry(actorCtx, actorEntry, play);
|
|
|
|
|
func_8002C0C0(&actorCtx->targetCtx, actorCtx->actorLists[ACTORCAT_PLAYER].head, play);
|
|
|
|
|
func_8002FA60(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-08-16 21:53:28 -04:00
|
|
|
|
u32 D_80116068[ACTORCAT_MAX] = {
|
2024-02-15 20:17:28 -05:00
|
|
|
|
PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS,
|
|
|
|
|
PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS,
|
|
|
|
|
0,
|
|
|
|
|
PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS,
|
|
|
|
|
PLAYER_STATE1_DEAD,
|
|
|
|
|
PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE,
|
|
|
|
|
PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS,
|
|
|
|
|
0,
|
|
|
|
|
PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE,
|
|
|
|
|
PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS,
|
|
|
|
|
0,
|
|
|
|
|
PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
};
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor* refActor;
|
|
|
|
|
Actor* actor;
|
|
|
|
|
Player* player;
|
|
|
|
|
u32* sp80;
|
|
|
|
|
u32 unkFlag;
|
|
|
|
|
u32 unkCondition;
|
|
|
|
|
Actor* sp74;
|
|
|
|
|
ActorEntry* actorEntry;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
sp74 = NULL;
|
|
|
|
|
unkFlag = 0;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (play->numSetupActors != 0) {
|
|
|
|
|
actorEntry = &play->setupActorList[0];
|
|
|
|
|
for (i = 0; i < play->numSetupActors; i++) {
|
|
|
|
|
Actor_SpawnEntry(&play->actorCtx, actorEntry++, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->numSetupActors = 0;
|
2023-04-02 21:11:08 -04:00
|
|
|
|
GameInteractor_ExecuteOnSceneSpawnActors();
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actorCtx->unk_02 != 0) {
|
|
|
|
|
actorCtx->unk_02--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (KREG(0) == -100) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
refActor = &GET_PLAYER(play)->actor;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
KREG(0) = 0;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, refActor->world.pos.x,
|
2022-12-06 04:33:50 -05:00
|
|
|
|
refActor->world.pos.y + 100.0f, refActor->world.pos.z, 0, 0, 0, 1, true);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sp80 = &D_80116068[0];
|
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
if (player->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING) {
|
2023-05-30 15:05:04 -04:00
|
|
|
|
unkFlag = ACTOR_FLAG_NO_FREEZE_OCARINA;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
if ((player->stateFlags1 & PLAYER_STATE1_TEXT_ON_SCREEN) && ((player->actor.textId & 0xFF00) != 0x600)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
sp74 = player->targetActor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_COUNT(actorCtx->actorLists); i++, sp80++) {
|
|
|
|
|
unkCondition = (*sp80 & player->stateFlags1);
|
|
|
|
|
|
|
|
|
|
actor = actorCtx->actorLists[i].head;
|
|
|
|
|
while (actor != NULL) {
|
|
|
|
|
if (actor->world.pos.y < -25000.0f) {
|
|
|
|
|
actor->world.pos.y = -25000.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actor->sfx = 0;
|
|
|
|
|
|
|
|
|
|
if (actor->init != NULL) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex))
|
2022-03-21 21:51:23 -04:00
|
|
|
|
{
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_SetObjectDependency(play, actor);
|
|
|
|
|
actor->init(actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->init = NULL;
|
2024-04-19 09:41:04 -04:00
|
|
|
|
|
|
|
|
|
GameInteractor_ExecuteOnActorInit(actor);
|
|
|
|
|
|
|
|
|
|
// For enemy health bar we need to know the max health during init
|
|
|
|
|
if (actor->category == ACTORCAT_ENEMY) {
|
|
|
|
|
actor->maximumHealth = actor->colChkInfo.health;
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
actor = actor->next;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
} else if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor_Kill(actor);
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
} else if ((unkFlag && !(actor->flags & unkFlag)) ||
|
|
|
|
|
(!unkFlag && unkCondition && (sp74 != actor) && (actor != player->naviActor) &&
|
|
|
|
|
(actor != player->heldActor) && (&player->actor != actor->parent))) {
|
|
|
|
|
CollisionCheck_ResetDamage(&actor->colChkInfo);
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
} else if (actor->update == NULL) {
|
|
|
|
|
if (!actor->isDrawn) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
actor = Actor_Delete(&play->actorCtx, actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_Destroy(actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Math_Vec3f_Copy(&actor->prevPos, &actor->world.pos);
|
|
|
|
|
actor->xzDistToPlayer = Actor_WorldDistXZToActor(actor, &player->actor);
|
|
|
|
|
actor->yDistToPlayer = Actor_HeightDiff(actor, &player->actor);
|
|
|
|
|
actor->xyzDistToPlayerSq = SQ(actor->xzDistToPlayer) + SQ(actor->yDistToPlayer);
|
|
|
|
|
|
|
|
|
|
actor->yawTowardsPlayer = Actor_WorldYawTowardActor(actor, &player->actor);
|
2023-05-30 15:05:04 -04:00
|
|
|
|
actor->flags &= ~ACTOR_FLAG_PLAY_HIT_SFX;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if ((DECR(actor->freezeTimer) == 0) && (actor->flags & (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_ACTIVE))) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (actor == player->unk_664) {
|
|
|
|
|
actor->isTargeted = true;
|
|
|
|
|
} else {
|
|
|
|
|
actor->isTargeted = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((actor->targetPriority != 0) && (player->unk_664 == NULL)) {
|
|
|
|
|
actor->targetPriority = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_SetObjectDependency(play, actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (actor->colorFilterTimer != 0) {
|
|
|
|
|
actor->colorFilterTimer--;
|
|
|
|
|
}
|
2022-11-06 03:24:34 -05:00
|
|
|
|
actor->update(actor, play);
|
2023-06-27 19:53:35 -04:00
|
|
|
|
GameInteractor_ExecuteOnActorUpdate(actor);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8003F8EC(play, &play->colCtx.dyna, actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CollisionCheck_ResetDamage(&actor->colChkInfo);
|
|
|
|
|
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i == ACTORCAT_BG) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
DynaPoly_Setup(play, &play->colCtx.dyna);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actor = player->unk_664;
|
|
|
|
|
|
|
|
|
|
if ((actor != NULL) && (actor->update == NULL)) {
|
|
|
|
|
actor = NULL;
|
|
|
|
|
func_8008EDF0(player);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((actor == NULL) || (player->unk_66C < 5)) {
|
|
|
|
|
actor = NULL;
|
|
|
|
|
if (actorCtx->targetCtx.unk_4B != 0) {
|
|
|
|
|
actorCtx->targetCtx.unk_4B = 0;
|
|
|
|
|
func_80078884(NA_SE_SY_LOCK_OFF);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002C7BC(&actorCtx->targetCtx, player, actor, play);
|
|
|
|
|
TitleCard_Update(play, &actorCtx->titleCtx);
|
|
|
|
|
DynaPoly_UpdateBgActorTransforms(play, &play->colCtx.dyna);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_FaultPrint(Actor* actor, char* command) {
|
|
|
|
|
char* name;
|
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
if (actor == NULL) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
FaultDrawer_SetCursor(48, 24);
|
|
|
|
|
FaultDrawer_Printf("ACTOR NAME is NULL");
|
2023-06-01 21:39:50 -04:00
|
|
|
|
return;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
name = ActorDB_Retrieve(actor->id)->name;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
osSyncPrintf("アクターの名前(%08x:%s)\n", actor, name); // "Actor name (%08x:%s)"
|
|
|
|
|
|
|
|
|
|
if (command != NULL) {
|
|
|
|
|
osSyncPrintf("コメント:%s\n", command); // "Command:%s"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FaultDrawer_SetCursor(48, 24);
|
|
|
|
|
FaultDrawer_Printf("ACTOR NAME %08x:%s", actor, name);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_Draw(PlayState* play, Actor* actor) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
FaultClient faultClient;
|
|
|
|
|
Lights* lights;
|
|
|
|
|
|
|
|
|
|
Fault_AddClient(&faultClient, Actor_FaultPrint, actor, "Actor_draw");
|
|
|
|
|
|
2022-05-13 18:43:55 -04:00
|
|
|
|
FrameInterpolation_RecordOpenChild(actor, 0);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
lights = LightContext_NewLights(&play->lightCtx, play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-05-30 15:05:04 -04:00
|
|
|
|
Lights_BindAll(lights, play->lightCtx.listHead, (actor->flags & ACTOR_FLAG_IGNORE_POINTLIGHTS) ? NULL : &actor->world.pos);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Lights_Draw(lights, play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-05-13 18:43:55 -04:00
|
|
|
|
FrameInterpolation_RecordActorPosRotMatrix();
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if (actor->flags & ACTOR_FLAG_IGNORE_QUAKE) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Matrix_SetTranslateRotateYXZ(
|
2022-11-06 03:24:34 -05:00
|
|
|
|
actor->world.pos.x + play->mainCamera.skyboxOffset.x,
|
|
|
|
|
actor->world.pos.y + (f32)((actor->shape.yOffset * actor->scale.y) + play->mainCamera.skyboxOffset.y),
|
|
|
|
|
actor->world.pos.z + play->mainCamera.skyboxOffset.z, &actor->shape.rot);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
|
|
|
|
Matrix_SetTranslateRotateYXZ(actor->world.pos.x, actor->world.pos.y + (actor->shape.yOffset * actor->scale.y),
|
|
|
|
|
actor->world.pos.z, &actor->shape.rot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrix_Scale(actor->scale.x, actor->scale.y, actor->scale.z, MTXMODE_APPLY);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_SetObjectDependency(play, actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPSegment(POLY_OPA_DISP++, 0x06, play->objectCtx.status[actor->objBankIndex].segment);
|
|
|
|
|
gSPSegment(POLY_XLU_DISP++, 0x06, play->objectCtx.status[actor->objBankIndex].segment);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (actor->colorFilterTimer != 0) {
|
|
|
|
|
Color_RGBA8 color = { 0, 0, 0, 255 };
|
|
|
|
|
|
|
|
|
|
if (actor->colorFilterParams & 0x8000) {
|
|
|
|
|
color.r = color.g = color.b = ((actor->colorFilterParams & 0x1F00) >> 5) | 7;
|
|
|
|
|
} else if (actor->colorFilterParams & 0x4000) {
|
|
|
|
|
color.r = ((actor->colorFilterParams & 0x1F00) >> 5) | 7;
|
|
|
|
|
} else {
|
|
|
|
|
color.b = ((actor->colorFilterParams & 0x1F00) >> 5) | 7;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actor->colorFilterParams & 0x2000) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80026860(play, &color, actor->colorFilterTimer, actor->colorFilterParams & 0xFF);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80026400(play, &color, actor->colorFilterTimer, actor->colorFilterParams & 0xFF);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
actor->draw(actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (actor->colorFilterTimer != 0) {
|
|
|
|
|
if (actor->colorFilterParams & 0x2000) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80026A6C(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80026608(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actor->shape.shadowDraw != NULL) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
actor->shape.shadowDraw(actor, lights, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-05-13 18:43:55 -04:00
|
|
|
|
FrameInterpolation_RecordCloseChild();
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
Fault_RemoveClient(&faultClient);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_80030ED8(Actor* actor) {
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if (actor->flags & ACTOR_FLAG_SFX_AT_POS) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Audio_PlaySoundGeneral(actor->sfx, &actor->projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
2023-05-30 15:05:04 -04:00
|
|
|
|
} else if (actor->flags & ACTOR_FLAG_SFX_AT_CENTER) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
func_80078884(actor->sfx);
|
2023-05-30 15:05:04 -04:00
|
|
|
|
} else if (actor->flags & ACTOR_FLAG_SFX_AT_CENTER2) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
func_800788CC(actor->sfx);
|
2023-05-30 15:05:04 -04:00
|
|
|
|
} else if (actor->flags & ACTOR_FLAG_SFX_AS_TIMER) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
func_800F4C58(&D_801333D4, NA_SE_SY_TIMER - SFX_FLAG, (s8)(actor->sfx - 1));
|
|
|
|
|
} else {
|
|
|
|
|
func_80078914(&actor->projectedPos, actor->sfx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-16 21:53:28 -04:00
|
|
|
|
#define LENS_MASK_WIDTH 64
|
|
|
|
|
#define LENS_MASK_HEIGHT 64
|
|
|
|
|
// 26 and 6 are for padding between the mask texture and the screen borders
|
|
|
|
|
#define LENS_MASK_OFFSET_S ((SCREEN_WIDTH / 2 - LENS_MASK_WIDTH) - 26)
|
|
|
|
|
#define LENS_MASK_OFFSET_T ((SCREEN_HEIGHT / 2 - LENS_MASK_HEIGHT) - 6)
|
|
|
|
|
|
|
|
|
|
void Actor_DrawLensOverlay(GraphicsContext* gfxCtx) {
|
2022-07-05 19:29:34 -04:00
|
|
|
|
OPEN_DISPS(gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-08-16 21:53:28 -04:00
|
|
|
|
gDPLoadTextureBlock(POLY_XLU_DISP++, gLensOfTruthMaskTex, G_IM_FMT_I, G_IM_SIZ_8b, LENS_MASK_WIDTH,
|
|
|
|
|
LENS_MASK_HEIGHT, 0, G_TX_MIRROR | G_TX_CLAMP, G_TX_MIRROR | G_TX_CLAMP, 6, 6, G_TX_NOLOD,
|
|
|
|
|
G_TX_NOLOD);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-05-02 18:26:32 -04:00
|
|
|
|
s32 x = OTRGetRectDimensionFromLeftEdge(0) << 2;
|
|
|
|
|
s32 w = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH) << 2;
|
|
|
|
|
|
2022-08-16 21:53:28 -04:00
|
|
|
|
gDPSetTileSize(POLY_XLU_DISP++, G_TX_RENDERTILE, (SCREEN_WIDTH / 2 - LENS_MASK_WIDTH) << 2,
|
|
|
|
|
(SCREEN_HEIGHT / 2 - LENS_MASK_HEIGHT) << 2, (SCREEN_WIDTH / 2 + LENS_MASK_WIDTH - 1) << 2,
|
|
|
|
|
(SCREEN_HEIGHT / 2 + LENS_MASK_HEIGHT - 1) << 2);
|
|
|
|
|
gSPWideTextureRectangle(POLY_XLU_DISP++, x, 0, x + abs(x), SCREEN_HEIGHT << 2, G_TX_RENDERTILE, 0, 0, 0, 0);
|
|
|
|
|
gSPWideTextureRectangle(POLY_XLU_DISP++, 0, 0, w, SCREEN_HEIGHT << 2, G_TX_RENDERTILE,
|
|
|
|
|
LENS_MASK_OFFSET_S << 5, LENS_MASK_OFFSET_T << 5,
|
|
|
|
|
(1 << 10) * (SCREEN_WIDTH - 2 * LENS_MASK_OFFSET_S) / SCREEN_WIDTH,
|
|
|
|
|
(1 << 10) * (SCREEN_HEIGHT - 2 * LENS_MASK_OFFSET_T) / SCREEN_HEIGHT);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gDPPipeSync(POLY_XLU_DISP++);
|
2022-07-05 19:29:34 -04:00
|
|
|
|
CLOSE_DISPS(gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_DrawLensActors(PlayState* play, s32 numInvisibleActors, Actor** invisibleActors) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor** invisibleActor;
|
|
|
|
|
GraphicsContext* gfxCtx;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gfxCtx = play->state.gfxCtx;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
|
OPEN_DISPS(gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
gDPNoOpString(POLY_OPA_DISP++, "魔法のメガネ START", 0); // "Magic lens START"
|
|
|
|
|
|
|
|
|
|
gDPPipeSync(POLY_XLU_DISP++);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (play->roomCtx.curRoom.lensMode == LENS_MODE_HIDE_ACTORS) {
|
2022-08-16 21:53:28 -04:00
|
|
|
|
// Update both the color frame buffer and the z-buffer
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gDPSetOtherMode(POLY_XLU_DISP++,
|
|
|
|
|
G_AD_DISABLE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE |
|
|
|
|
|
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
|
|
|
|
|
G_AC_THRESHOLD | G_ZS_PRIM | Z_UPD | G_RM_CLD_SURF | G_RM_CLD_SURF2);
|
2022-08-16 21:53:28 -04:00
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gDPSetCombineMode(POLY_XLU_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
|
|
|
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 0, 0, 255);
|
2022-08-16 21:53:28 -04:00
|
|
|
|
|
|
|
|
|
// the z-buffer will later only allow drawing inside the lens circle
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-08-16 21:53:28 -04:00
|
|
|
|
// Update the z-buffer but not the color frame buffer
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gDPSetOtherMode(POLY_XLU_DISP++,
|
|
|
|
|
G_AD_DISABLE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE |
|
|
|
|
|
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
|
|
|
|
|
G_AC_THRESHOLD | G_ZS_PRIM | Z_UPD | IM_RD | CVG_DST_SAVE | ZMODE_OPA | FORCE_BL |
|
|
|
|
|
GBL_c1(G_BL_CLR_BL, G_BL_0, G_BL_CLR_MEM, G_BL_1MA) |
|
|
|
|
|
GBL_c2(G_BL_CLR_BL, G_BL_0, G_BL_CLR_MEM, G_BL_1MA));
|
2022-08-16 21:53:28 -04:00
|
|
|
|
|
|
|
|
|
// inverts the mask image, which initially is 0 inner and 74 outer,
|
|
|
|
|
// by setting the combiner to draw 74 - image instead of the image
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gDPSetCombineLERP(POLY_XLU_DISP++, PRIMITIVE, TEXEL0, PRIM_LOD_FRAC, 0, PRIMITIVE, TEXEL0, PRIM_LOD_FRAC, 0,
|
|
|
|
|
PRIMITIVE, TEXEL0, PRIM_LOD_FRAC, 0, PRIMITIVE, TEXEL0, PRIM_LOD_FRAC, 0);
|
|
|
|
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0xFF, 74, 74, 74, 74);
|
2022-08-16 21:53:28 -04:00
|
|
|
|
|
|
|
|
|
// the z-buffer will later only allow drawing outside the lens circle
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-08-16 21:53:28 -04:00
|
|
|
|
// Together with the depth source set above, this sets the depth to the closest.
|
|
|
|
|
// For a pixel with such a depth value, the z-buffer will reject drawing to that pixel.
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gDPSetPrimDepth(POLY_XLU_DISP++, 0, 0);
|
|
|
|
|
|
2022-08-16 21:53:28 -04:00
|
|
|
|
// The z-buffer will be updated where the mask is not fully transparent.
|
|
|
|
|
Actor_DrawLensOverlay(gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
// "Magic lens invisible Actor display START"
|
|
|
|
|
gDPNoOpString(POLY_OPA_DISP++, "魔法のメガネ 見えないActor表示 START", numInvisibleActors);
|
|
|
|
|
|
|
|
|
|
invisibleActor = &invisibleActors[0];
|
|
|
|
|
for (i = 0; i < numInvisibleActors; i++) {
|
|
|
|
|
// "Magic lens invisible Actor display"
|
|
|
|
|
gDPNoOpString(POLY_OPA_DISP++, "魔法のメガネ 見えないActor表示", i);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_Draw(play, *(invisibleActor++));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// "Magic lens invisible Actor display END"
|
|
|
|
|
gDPNoOpString(POLY_OPA_DISP++, "魔法のメガネ 見えないActor表示 END", numInvisibleActors);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (play->roomCtx.curRoom.lensMode != LENS_MODE_HIDE_ACTORS) {
|
2022-08-16 21:53:28 -04:00
|
|
|
|
// Draw the lens overlay to the color frame buffer
|
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gDPNoOpString(POLY_OPA_DISP++, "青い眼鏡(外側)", 0); // "Blue spectacles (exterior)"
|
|
|
|
|
|
|
|
|
|
gDPPipeSync(POLY_XLU_DISP++);
|
|
|
|
|
|
|
|
|
|
gDPSetOtherMode(POLY_XLU_DISP++,
|
|
|
|
|
G_AD_DISABLE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE |
|
|
|
|
|
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
|
|
|
|
|
G_AC_THRESHOLD | G_ZS_PRIM | G_RM_CLD_SURF | G_RM_CLD_SURF2);
|
|
|
|
|
gDPSetCombineMode(POLY_XLU_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
|
|
|
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 0, 0, 255);
|
|
|
|
|
|
2022-08-16 21:53:28 -04:00
|
|
|
|
Actor_DrawLensOverlay(gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
gDPNoOpString(POLY_OPA_DISP++, "青い眼鏡(外側)", 1); // "Blue spectacles (exterior)"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gDPNoOpString(POLY_OPA_DISP++, "魔法のメガネ END", 0); // "Magic lens END"
|
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
|
CLOSE_DISPS(gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_800314B0(PlayState* play, Actor* actor) {
|
|
|
|
|
return func_800314D4(play, actor, &actor->projectedPos, actor->projectedW);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 var;
|
|
|
|
|
|
2024-08-12 19:39:44 -04:00
|
|
|
|
if ((arg2->z > -actor->uncullZoneScale) && (arg2->z < (actor->uncullZoneForward + actor->uncullZoneScale))) {
|
|
|
|
|
var = (arg3 < 1.0f) ? 1.0f : 1.0f / arg3;
|
|
|
|
|
|
|
|
|
|
if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < 1.0f) &&
|
|
|
|
|
(((arg2->y + actor->uncullZoneDownward) * var) > -1.0f) &&
|
|
|
|
|
(((arg2->y - actor->uncullZoneScale) * var) < 1.0f)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// #region SOH [Enhancements] Allows us to increase the draw and update distance independently,
|
|
|
|
|
// mostly a modified version of the function above and additional tweaks for some specfic actors
|
|
|
|
|
s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw,
|
|
|
|
|
bool* shouldUpdate) {
|
|
|
|
|
f32 clampedProjectedW;
|
|
|
|
|
|
|
|
|
|
// Check if the actor passes its original/vanilla culling requirements
|
|
|
|
|
if (func_800314D4(play, actor, projectedPos, projectedW)) {
|
|
|
|
|
*shouldUpdate = true;
|
|
|
|
|
*shouldDraw = true;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-12 19:39:44 -04:00
|
|
|
|
// Skip cutscne actors that depend on culling to hide from camera pans
|
|
|
|
|
if (actor->id == ACTOR_EN_VIEWER) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-08-13 01:09:49 -04:00
|
|
|
|
s32 multiplier = CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1);
|
2024-08-12 19:39:44 -04:00
|
|
|
|
multiplier = MAX(multiplier, 1);
|
|
|
|
|
|
|
|
|
|
// Some actors have a really short forward value, so we need to add to it before the multiplier to increase the
|
|
|
|
|
// final strength of the forward culling
|
|
|
|
|
f32 adder = (actor->uncullZoneForward < 500) ? 1000.0f : 0.0f;
|
|
|
|
|
|
|
|
|
|
if ((projectedPos->z > -actor->uncullZoneScale) &&
|
|
|
|
|
(projectedPos->z < (((actor->uncullZoneForward + adder) * multiplier) + actor->uncullZoneScale))) {
|
|
|
|
|
clampedProjectedW = (projectedW < 1.0f) ? 1.0f : 1.0f / projectedW;
|
|
|
|
|
|
|
|
|
|
f32 ratioAdjusted = 1.0f;
|
|
|
|
|
|
2024-08-13 01:09:49 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_ENHANCEMENT("WidescreenActorCulling"), 0)) {
|
2024-08-12 19:39:44 -04:00
|
|
|
|
f32 originalAspectRatio = 4.0f / 3.0f;
|
|
|
|
|
f32 currentAspectRatio = OTRGetAspectRatio();
|
|
|
|
|
ratioAdjusted = MAX(currentAspectRatio / originalAspectRatio, 1.0f);
|
2024-02-01 20:58:08 -05:00
|
|
|
|
}
|
|
|
|
|
|
2024-08-12 19:39:44 -04:00
|
|
|
|
if ((((fabsf(projectedPos->x) - actor->uncullZoneScale) * (clampedProjectedW / ratioAdjusted)) < 1.0f) &&
|
|
|
|
|
(((projectedPos->y + actor->uncullZoneDownward) * clampedProjectedW) > -1.0f) &&
|
|
|
|
|
(((projectedPos->y - actor->uncullZoneScale) * clampedProjectedW) < 1.0f)) {
|
|
|
|
|
|
2024-08-13 01:09:49 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_ENHANCEMENT("ExtendedCullingExcludeGlitchActors"), 0)) {
|
2024-08-12 19:39:44 -04:00
|
|
|
|
// These actors are safe to draw without impacting glitches
|
|
|
|
|
if ((actor->id == ACTOR_OBJ_BOMBIWA || actor->id == ACTOR_OBJ_HAMISHI ||
|
|
|
|
|
actor->id == ACTOR_EN_ISHI) || // Boulders (hookshot through collision)
|
|
|
|
|
actor->id == ACTOR_EN_GS || // Gossip stones (text delay)
|
|
|
|
|
actor->id == ACTOR_EN_GE1 || // White gerudos (gate clip/archery room transition)
|
|
|
|
|
actor->id == ACTOR_EN_KZ || // King Zora (unfreeze glitch)
|
|
|
|
|
actor->id == ACTOR_EN_DU || // Darunia (Fire temple BK skip)
|
|
|
|
|
actor->id == ACTOR_DOOR_WARP1 // Blue warps (wrong warps)
|
|
|
|
|
) {
|
|
|
|
|
*shouldDraw = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Skip these actors entirely as their draw funcs impacts glitches
|
|
|
|
|
if ((actor->id == ACTOR_EN_SW &&
|
|
|
|
|
(((actor->params & 0xE000) >> 0xD) == 1 ||
|
|
|
|
|
((actor->params & 0xE000) >> 0xD) == 2)) // Gold Skulltulas (hitbox at 0,0)
|
|
|
|
|
) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*shouldDraw = true;
|
|
|
|
|
*shouldUpdate = true;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2024-08-12 19:39:44 -04:00
|
|
|
|
// #endregion
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_800315AC(PlayState* play, ActorContext* actorCtx) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 invisibleActorCounter;
|
|
|
|
|
Actor* invisibleActors[INVISIBLE_ACTOR_MAX];
|
|
|
|
|
ActorListEntry* actorListEntry;
|
|
|
|
|
Actor* actor;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
|
|
invisibleActorCounter = 0;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
actorListEntry = &actorCtx->actorLists[0];
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_COUNT(actorCtx->actorLists); i++, actorListEntry++) {
|
|
|
|
|
actor = actorListEntry->head;
|
|
|
|
|
|
|
|
|
|
while (actor != NULL) {
|
2023-06-01 21:39:50 -04:00
|
|
|
|
char* actorName = ActorDB_Retrieve(actor->id)->name;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
gDPNoOpString(POLY_OPA_DISP++, actorName, i);
|
|
|
|
|
gDPNoOpString(POLY_XLU_DISP++, actorName, i);
|
|
|
|
|
|
|
|
|
|
HREG(66) = i;
|
|
|
|
|
|
|
|
|
|
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(68) == 0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &actor->world.pos, &actor->projectedPos,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
&actor->projectedW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(69) == 0)) {
|
|
|
|
|
if (actor->sfx != 0) {
|
|
|
|
|
func_80030ED8(actor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-12 19:39:44 -04:00
|
|
|
|
// #region SOH [Enhancement] Extended culling updates
|
|
|
|
|
bool shipShouldDraw = false;
|
|
|
|
|
bool shipShouldUpdate = false;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(70) == 0)) {
|
2024-08-13 01:09:49 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1) > 1 ||
|
|
|
|
|
CVarGetInteger(CVAR_ENHANCEMENT("WidescreenActorCulling"), 0)) {
|
2024-08-12 19:39:44 -04:00
|
|
|
|
Ship_CalcShouldDrawAndUpdate(play, actor, &actor->projectedPos, actor->projectedW, &shipShouldDraw,
|
|
|
|
|
&shipShouldUpdate);
|
|
|
|
|
|
|
|
|
|
if (shipShouldUpdate) {
|
|
|
|
|
actor->flags |= ACTOR_FLAG_ACTIVE;
|
|
|
|
|
} else {
|
|
|
|
|
actor->flags &= ~ACTOR_FLAG_ACTIVE;
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2024-08-12 19:39:44 -04:00
|
|
|
|
if (func_800314B0(play, actor)) {
|
|
|
|
|
actor->flags |= ACTOR_FLAG_ACTIVE;
|
|
|
|
|
} else {
|
|
|
|
|
actor->flags &= ~ACTOR_FLAG_ACTIVE;
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actor->isDrawn = false;
|
|
|
|
|
|
|
|
|
|
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(71) == 0)) {
|
2024-08-12 19:39:44 -04:00
|
|
|
|
if ((actor->init == NULL) && (actor->draw != NULL) &&
|
|
|
|
|
((actor->flags & (ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_ACTIVE)) || shipShouldDraw)) {
|
|
|
|
|
// #endregion
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if ((actor->flags & ACTOR_FLAG_LENS) &&
|
2022-11-06 03:24:34 -05:00
|
|
|
|
((play->roomCtx.curRoom.lensMode == LENS_MODE_HIDE_ACTORS) ||
|
|
|
|
|
play->actorCtx.lensActive || (actor->room != play->roomCtx.curRoom.num))) {
|
2023-06-27 19:53:35 -04:00
|
|
|
|
assert(invisibleActorCounter < INVISIBLE_ACTOR_MAX);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
invisibleActors[invisibleActorCounter] = actor;
|
|
|
|
|
invisibleActorCounter++;
|
|
|
|
|
} else {
|
|
|
|
|
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(72) == 0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_Draw(play, actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->isDrawn = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((HREG(64) != 1) || (HREG(73) != 0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Effect_DrawAll(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((HREG(64) != 1) || (HREG(74) != 0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
EffectSs_DrawAll(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((HREG(64) != 1) || (HREG(72) != 0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (play->actorCtx.lensActive) {
|
|
|
|
|
Actor_DrawLensActors(play, invisibleActorCounter, invisibleActors);
|
|
|
|
|
if ((play->csCtx.state != CS_STATE_IDLE) || Player_InCsMode(play)) {
|
|
|
|
|
Actor_DisableLens(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_DrawFaroresWindPointer(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (IREG(32) == 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Lights_DrawGlow(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((HREG(64) != 1) || (HREG(75) != 0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
TitleCard_Draw(play, &actorCtx->titleCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((HREG(64) != 1) || (HREG(76) != 0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CollisionCheck_DrawCollision(play, &play->colChkCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80031A28(PlayState* play, ActorContext* actorCtx) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor* actor;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_COUNT(actorCtx->actorLists); i++) {
|
|
|
|
|
actor = actorCtx->actorLists[i].head;
|
|
|
|
|
while (actor != NULL) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor_Kill(actor);
|
|
|
|
|
}
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 sEnemyActorCategories[] = { ACTORCAT_ENEMY, ACTORCAT_BOSS };
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_FreezeAllEnemies(PlayState* play, ActorContext* actorCtx, s32 duration) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor* actor;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_COUNT(sEnemyActorCategories); i++) {
|
|
|
|
|
actor = actorCtx->actorLists[sEnemyActorCategories[i]].head;
|
|
|
|
|
while (actor != NULL) {
|
|
|
|
|
actor->freezeTimer = duration;
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80031B14(PlayState* play, ActorContext* actorCtx) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor* actor;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_COUNT(actorCtx->actorLists); i++) {
|
|
|
|
|
actor = actorCtx->actorLists[i].head;
|
|
|
|
|
while (actor != NULL) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if ((actor->room >= 0) && (actor->room != play->roomCtx.curRoom.num) &&
|
|
|
|
|
(actor->room != play->roomCtx.prevRoom.num)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (!actor->isDrawn) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
actor = Actor_Delete(actorCtx, actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
|
|
|
|
Actor_Kill(actor);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_Destroy(actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CollisionCheck_ClearContext(play, &play->colChkCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actorCtx->flags.tempClear = 0;
|
|
|
|
|
actorCtx->flags.tempSwch &= 0xFFFFFF;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
play->msgCtx.unk_E3F4 = 0;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Actor_CleanupContext
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80031C3C(ActorContext* actorCtx, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor* actor;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_COUNT(actorCtx->actorLists); i++) {
|
|
|
|
|
actor = actorCtx->actorLists[i].head;
|
|
|
|
|
while (actor != NULL) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_Delete(actorCtx, actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor = actorCtx->actorLists[i].head;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (HREG(20) != 0) {
|
|
|
|
|
osSyncPrintf("絶対魔法領域解放\n"); // "Absolute magic field deallocation"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actorCtx->absoluteSpace != NULL) {
|
2022-07-05 19:29:34 -04:00
|
|
|
|
ZELDA_ARENA_FREE_DEBUG(actorCtx->absoluteSpace);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actorCtx->absoluteSpace = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Play_SaveSceneFlags(play);
|
|
|
|
|
func_80030488(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds a given actor instance at the front of the actor list of the specified category.
|
|
|
|
|
* Also sets the actor instance as being of that category.
|
|
|
|
|
*/
|
|
|
|
|
void Actor_AddToCategory(ActorContext* actorCtx, Actor* actorToAdd, u8 actorCategory) {
|
|
|
|
|
Actor* prevHead;
|
|
|
|
|
|
|
|
|
|
actorToAdd->category = actorCategory;
|
|
|
|
|
|
|
|
|
|
actorCtx->total++;
|
|
|
|
|
actorCtx->actorLists[actorCategory].length++;
|
|
|
|
|
prevHead = actorCtx->actorLists[actorCategory].head;
|
|
|
|
|
|
|
|
|
|
if (prevHead != NULL) {
|
|
|
|
|
prevHead->prev = actorToAdd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actorCtx->actorLists[actorCategory].head = actorToAdd;
|
|
|
|
|
actorToAdd->next = prevHead;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Removes a given actor instance from its actor list.
|
|
|
|
|
* Also sets the temp clear flag of the current room if the actor removed was the last enemy loaded.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* Actor_RemoveFromCategory(PlayState* play, ActorContext* actorCtx, Actor* actorToRemove) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor* newHead;
|
|
|
|
|
|
|
|
|
|
actorCtx->total--;
|
|
|
|
|
actorCtx->actorLists[actorToRemove->category].length--;
|
|
|
|
|
|
|
|
|
|
if (actorToRemove->prev != NULL) {
|
|
|
|
|
actorToRemove->prev->next = actorToRemove->next;
|
|
|
|
|
} else {
|
|
|
|
|
actorCtx->actorLists[actorToRemove->category].head = actorToRemove->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newHead = actorToRemove->next;
|
|
|
|
|
|
|
|
|
|
if (newHead != NULL) {
|
|
|
|
|
newHead->prev = actorToRemove->prev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actorToRemove->next = NULL;
|
|
|
|
|
actorToRemove->prev = NULL;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if ((actorToRemove->room == play->roomCtx.curRoom.num) && (actorToRemove->category == ACTORCAT_ENEMY) &&
|
2022-03-21 21:51:23 -04:00
|
|
|
|
(actorCtx->actorLists[ACTORCAT_ENEMY].length == 0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Flags_SetTempClear(play, play->roomCtx.curRoom.num);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return newHead;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
void Actor_FreeOverlay(ActorDBEntry* dbEntry) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
osSyncPrintf(VT_FGCOL(CYAN));
|
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
if (dbEntry->numLoaded == 0) {
|
2022-05-02 18:26:32 -04:00
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
if (dbEntry->reset != NULL) {
|
|
|
|
|
dbEntry->reset();
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (HREG(20) != 0) {
|
|
|
|
|
osSyncPrintf("アクタークライアントが0になりました\n"); // "Actor client is now 0"
|
|
|
|
|
}
|
|
|
|
|
} else if (HREG(20) != 0) {
|
|
|
|
|
// "%d of actor client remains"
|
2023-06-01 21:39:50 -04:00
|
|
|
|
osSyncPrintf("アクタークライアントはあと %d 残っています\n", dbEntry->numLoaded);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
osSyncPrintf(VT_RST);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-15 10:30:20 -05:00
|
|
|
|
// SoH: Flag to check if actors are being spawned from the actor entry list
|
|
|
|
|
// This flag is checked against to allow actors which dont have an objectBankIndex in the objectCtx slot/status array to spawn
|
|
|
|
|
// An example of what this fixes, is that it allows hookshot to be used as child
|
2022-03-21 21:51:23 -04:00
|
|
|
|
int gMapLoading = 0;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ,
|
2022-12-06 04:33:50 -05:00
|
|
|
|
s16 rotX, s16 rotY, s16 rotZ, s16 params, s16 canRandomize) {
|
|
|
|
|
|
2024-04-25 20:31:28 -04:00
|
|
|
|
uint8_t tryRandomizeEnemy = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2 && canRandomize;
|
2022-12-06 04:33:50 -05:00
|
|
|
|
|
|
|
|
|
if (tryRandomizeEnemy) {
|
|
|
|
|
if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, ¶ms)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor* actor;
|
|
|
|
|
s32 objBankIndex;
|
|
|
|
|
u32 temp;
|
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
ActorDBEntry* dbEntry = ActorDB_Retrieve(actorId);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-06-27 19:53:35 -04:00
|
|
|
|
assert(dbEntry->valid);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (HREG(20) != 0) {
|
|
|
|
|
// "Actor class addition [%d:%s]"
|
2023-06-01 21:39:50 -04:00
|
|
|
|
osSyncPrintf("アクタークラス追加 [%d:%s]\n", actorId, dbEntry->name);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actorCtx->total > ACTOR_NUMBER_MAX) {
|
|
|
|
|
// "Actor set number exceeded"
|
|
|
|
|
osSyncPrintf(VT_COL(YELLOW, BLACK) "Actorセット数オーバー\n" VT_RST);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
objBankIndex = Object_GetIndex(&gPlayState->objectCtx, dbEntry->objectId);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-04-25 20:31:28 -04:00
|
|
|
|
if (objBankIndex < 0 && (!gMapLoading || CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0))) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
objBankIndex = 0;
|
2022-12-06 04:33:50 -05:00
|
|
|
|
}
|
2022-05-02 18:26:32 -04:00
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if ((objBankIndex < 0) ||
|
2023-06-01 21:39:50 -04:00
|
|
|
|
((dbEntry->category == ACTORCAT_ENEMY) && Flags_GetClear(play, play->roomCtx.curRoom.num))) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
// "No data bank!! <data bank=%d> (profilep->bank=%d)"
|
|
|
|
|
osSyncPrintf(VT_COL(RED, WHITE) "データバンク無し!!<データバンク=%d>(profilep->bank=%d)\n" VT_RST,
|
2023-06-01 21:39:50 -04:00
|
|
|
|
objBankIndex, dbEntry->objectId);
|
|
|
|
|
Actor_FreeOverlay(dbEntry);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
actor = ZELDA_ARENA_MALLOC_DEBUG(dbEntry->instanceSize);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (actor == NULL) {
|
|
|
|
|
// "Actor class cannot be reserved! %s <size=%d bytes>"
|
2023-06-01 21:39:50 -04:00
|
|
|
|
osSyncPrintf(VT_COL(RED, WHITE) "Actorクラス確保できません! %s <サイズ=%dバイト>\n", VT_RST,
|
|
|
|
|
dbEntry->name, dbEntry->instanceSize);
|
|
|
|
|
Actor_FreeOverlay(dbEntry);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-27 19:53:35 -04:00
|
|
|
|
assert(dbEntry->numLoaded < 255);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
dbEntry->numLoaded++;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (HREG(20) != 0) {
|
|
|
|
|
// "Actor client No. %d"
|
2023-06-01 21:39:50 -04:00
|
|
|
|
osSyncPrintf("アクタークライアントは %d 個目です\n", dbEntry->numLoaded);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
memset((u8*)actor, 0, dbEntry->instanceSize);
|
|
|
|
|
actor->id = dbEntry->id;
|
|
|
|
|
actor->flags = dbEntry->flags;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
if (dbEntry->id == ACTOR_EN_PART) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->objBankIndex = rotZ;
|
|
|
|
|
rotZ = 0;
|
|
|
|
|
} else {
|
|
|
|
|
actor->objBankIndex = objBankIndex;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
actor->init = dbEntry->init;
|
|
|
|
|
actor->destroy = dbEntry->destroy;
|
|
|
|
|
actor->update = dbEntry->update;
|
|
|
|
|
actor->draw = dbEntry->draw;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
actor->room = play->roomCtx.curRoom.num;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->home.pos.x = posX;
|
|
|
|
|
actor->home.pos.y = posY;
|
|
|
|
|
actor->home.pos.z = posZ;
|
|
|
|
|
actor->home.rot.x = rotX;
|
|
|
|
|
actor->home.rot.y = rotY;
|
|
|
|
|
actor->home.rot.z = rotZ;
|
|
|
|
|
actor->params = params;
|
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
Actor_AddToCategory(actorCtx, actor, dbEntry->category);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
temp = gSegments[6];
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_Init(actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gSegments[6] = temp;
|
|
|
|
|
|
|
|
|
|
return actor;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* Actor_SpawnAsChild(ActorContext* actorCtx, Actor* parent, PlayState* play, s16 actorId, f32 posX,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 posY, f32 posZ, s16 rotX, s16 rotY, s16 rotZ, s16 params) {
|
2022-12-06 04:33:50 -05:00
|
|
|
|
Actor* spawnedActor = Actor_Spawn(actorCtx, play, actorId, posX, posY, posZ, rotX, rotY, rotZ, params, true);
|
2022-08-16 21:53:28 -04:00
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (spawnedActor == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-23 22:25:38 -05:00
|
|
|
|
// The following enemies break when the parent actor isn't the same as what would happen in authentic gameplay.
|
|
|
|
|
// As such, don't assign a parent to them at all when spawned with Enemy Randomizer.
|
|
|
|
|
// Gohma (z_boss_goma.c), the Stalchildren spawner (z_en_encount1.c) and the falling platform spawning Stalfos in
|
|
|
|
|
// Forest Temple (z_bg_mori_bigst.c) that normally rely on this behaviour are changed when
|
|
|
|
|
// Enemy Rando is on so they still work properly even without assigning a parent.
|
2024-04-25 20:31:28 -04:00
|
|
|
|
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && (spawnedActor->id == ACTOR_EN_FLOORMAS || spawnedActor->id == ACTOR_EN_PEEHAT)) {
|
2022-12-23 22:25:38 -05:00
|
|
|
|
return spawnedActor;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-21 21:51:23 -04:00
|
|
|
|
parent->child = spawnedActor;
|
|
|
|
|
spawnedActor->parent = parent;
|
|
|
|
|
|
|
|
|
|
if (spawnedActor->room >= 0) {
|
|
|
|
|
spawnedActor->room = parent->room;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return spawnedActor;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_SpawnTransitionActors(PlayState* play, ActorContext* actorCtx) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
TransitionActorEntry* transitionActor;
|
|
|
|
|
u8 numActors;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
transitionActor = play->transiActorCtx.list;
|
|
|
|
|
numActors = play->transiActorCtx.numActors;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
for (i = 0; i < numActors; i++) {
|
|
|
|
|
if (transitionActor->id >= 0) {
|
|
|
|
|
if (((transitionActor->sides[0].room >= 0) &&
|
2022-11-06 03:24:34 -05:00
|
|
|
|
((transitionActor->sides[0].room == play->roomCtx.curRoom.num) ||
|
|
|
|
|
(transitionActor->sides[0].room == play->roomCtx.prevRoom.num))) ||
|
2022-03-21 21:51:23 -04:00
|
|
|
|
((transitionActor->sides[1].room >= 0) &&
|
2022-11-06 03:24:34 -05:00
|
|
|
|
((transitionActor->sides[1].room == play->roomCtx.curRoom.num) ||
|
|
|
|
|
(transitionActor->sides[1].room == play->roomCtx.prevRoom.num)))) {
|
|
|
|
|
Actor_Spawn(actorCtx, play, (s16)(transitionActor->id & 0x1FFF), transitionActor->pos.x,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
transitionActor->pos.y, transitionActor->pos.z, 0, transitionActor->rotY, 0,
|
2022-12-06 04:33:50 -05:00
|
|
|
|
(i << 0xA) + transitionActor->params, true);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
transitionActor->id = -transitionActor->id;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
numActors = play->transiActorCtx.numActors;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
transitionActor++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* Actor_SpawnEntry(ActorContext* actorCtx, ActorEntry* actorEntry, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gMapLoading = 1;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* ret = Actor_Spawn(actorCtx, play, actorEntry->id, actorEntry->pos.x, actorEntry->pos.y, actorEntry->pos.z,
|
2022-12-06 04:33:50 -05:00
|
|
|
|
actorEntry->rot.x, actorEntry->rot.y, actorEntry->rot.z, actorEntry->params, true);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gMapLoading = 0;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Player* player;
|
|
|
|
|
Actor* newHead;
|
2023-06-01 21:39:50 -04:00
|
|
|
|
ActorDBEntry* dbEntry;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
dbEntry = ActorDB_Retrieve(actor->id);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (HREG(20) != 0) {
|
2023-06-01 21:39:50 -04:00
|
|
|
|
osSyncPrintf("アクタークラス削除 [%s]\n", dbEntry->name); // "Actor class deleted [%s]"
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((player != NULL) && (actor == player->unk_664)) {
|
|
|
|
|
func_8008EDF0(player);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Camera_ChangeMode(Play_GetCamera(play, Play_GetActiveCamId(play)), 0);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actor == actorCtx->targetCtx.arrowPointedActor) {
|
|
|
|
|
actorCtx->targetCtx.arrowPointedActor = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actor == actorCtx->targetCtx.unk_8C) {
|
|
|
|
|
actorCtx->targetCtx.unk_8C = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actor == actorCtx->targetCtx.bgmEnemy) {
|
|
|
|
|
actorCtx->targetCtx.bgmEnemy = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Audio_StopSfxByPos(&actor->projectedPos);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_Destroy(actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
newHead = Actor_RemoveFromCategory(play, actorCtx, actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
|
ZELDA_ARENA_FREE_DEBUG(actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-06-01 21:39:50 -04:00
|
|
|
|
dbEntry->numLoaded--;
|
|
|
|
|
Actor_FreeOverlay(dbEntry);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
return newHead;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_80032880(PlayState* play, Actor* actor) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s16 sp1E;
|
|
|
|
|
s16 sp1C;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_GetScreenPos(play, actor, &sp1E, &sp1C);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
return (sp1E > -20) && (sp1E < 340) && (sp1C > -160) && (sp1C < 400);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Actor* D_8015BBE8;
|
|
|
|
|
Actor* D_8015BBEC;
|
|
|
|
|
f32 D_8015BBF0;
|
|
|
|
|
f32 sbgmEnemyDistSq;
|
|
|
|
|
s32 D_8015BBF8;
|
|
|
|
|
s16 D_8015BBFC;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_800328D4(PlayState* play, ActorContext* actorCtx, Player* player, u32 actorCategory) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 var;
|
|
|
|
|
Actor* actor;
|
|
|
|
|
Actor* sp84;
|
|
|
|
|
CollisionPoly* sp80;
|
|
|
|
|
s32 sp7C;
|
|
|
|
|
Vec3f sp70;
|
|
|
|
|
|
|
|
|
|
actor = actorCtx->actorLists[actorCategory].head;
|
|
|
|
|
sp84 = player->unk_664;
|
|
|
|
|
|
|
|
|
|
while (actor != NULL) {
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if ((actor->update != NULL) && ((Player*)actor != player) && CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_TARGETABLE)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
// This block below is for determining the closest actor to player in determining the volume
|
|
|
|
|
// used while playing enemy bgm music
|
2023-05-30 15:05:04 -04:00
|
|
|
|
if ((actorCategory == ACTORCAT_ENEMY) && CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE) &&
|
2022-03-21 21:51:23 -04:00
|
|
|
|
(actor->xyzDistToPlayerSq < SQ(500.0f)) && (actor->xyzDistToPlayerSq < sbgmEnemyDistSq)) {
|
|
|
|
|
actorCtx->targetCtx.bgmEnemy = actor;
|
|
|
|
|
sbgmEnemyDistSq = actor->xyzDistToPlayerSq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actor != sp84) {
|
|
|
|
|
var = func_8002EFC0(actor, player, D_8015BBFC);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if ((var < D_8015BBF0) && func_8002F090(actor, var) && func_80032880(play, actor) &&
|
|
|
|
|
(!BgCheck_CameraLineTest1(&play->colCtx, &player->actor.focus.pos, &actor->focus.pos, &sp70,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
&sp80, 1, 1, 1, 1, &sp7C) ||
|
2022-11-06 03:24:34 -05:00
|
|
|
|
SurfaceType_IsIgnoredByProjectiles(&play->colCtx, sp80, sp7C))) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (actor->targetPriority != 0) {
|
|
|
|
|
if (actor->targetPriority < D_8015BBF8) {
|
|
|
|
|
D_8015BBEC = actor;
|
|
|
|
|
D_8015BBF8 = actor->targetPriority;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
D_8015BBE8 = actor;
|
|
|
|
|
D_8015BBF0 = var;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 D_801160A0[] = {
|
|
|
|
|
ACTORCAT_BOSS, ACTORCAT_ENEMY, ACTORCAT_BG, ACTORCAT_EXPLOSIVE, ACTORCAT_NPC, ACTORCAT_ITEMACTION,
|
|
|
|
|
ACTORCAT_CHEST, ACTORCAT_SWITCH, ACTORCAT_PROP, ACTORCAT_MISC, ACTORCAT_DOOR, ACTORCAT_SWITCH,
|
|
|
|
|
};
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* func_80032AF0(PlayState* play, ActorContext* actorCtx, Actor** actorPtr, Player* player) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 i;
|
|
|
|
|
u8* entry;
|
|
|
|
|
|
|
|
|
|
D_8015BBE8 = D_8015BBEC = NULL;
|
|
|
|
|
D_8015BBF0 = sbgmEnemyDistSq = FLT_MAX;
|
|
|
|
|
D_8015BBF8 = 0x7FFFFFFF;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (!Player_InCsMode(play)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
entry = &D_801160A0[0];
|
|
|
|
|
|
|
|
|
|
actorCtx->targetCtx.bgmEnemy = NULL;
|
|
|
|
|
D_8015BBFC = player->actor.shape.rot.y;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_800328D4(play, actorCtx, player, *entry);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
entry++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (D_8015BBE8 == NULL) {
|
|
|
|
|
for (; i < ARRAY_COUNT(D_801160A0); i++) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_800328D4(play, actorCtx, player, *entry);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
entry++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (D_8015BBE8 == 0) {
|
|
|
|
|
*actorPtr = D_8015BBEC;
|
|
|
|
|
} else {
|
|
|
|
|
*actorPtr = D_8015BBE8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return *actorPtr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Finds the first actor instance of a specified ID and category if there is one.
|
|
|
|
|
*/
|
|
|
|
|
Actor* Actor_Find(ActorContext* actorCtx, s32 actorId, s32 actorCategory) {
|
|
|
|
|
Actor* actor = actorCtx->actorLists[actorCategory].head;
|
|
|
|
|
|
|
|
|
|
while (actor != NULL) {
|
|
|
|
|
if (actorId == actor->id) {
|
|
|
|
|
return actor;
|
|
|
|
|
}
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Play the death sound effect and flash the screen white for 4 frames.
|
|
|
|
|
* While the screen flashes, the game freezes.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Enemy_StartFinishingBlow(PlayState* play, Actor* actor) {
|
|
|
|
|
play->actorCtx.freezeFlashTimer = 5;
|
|
|
|
|
SoundSource_PlaySfxAtFixedWorldPos(play, &actor->world.pos, 20, NA_SE_EN_LAST_DAMAGE);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s16 func_80032CB4(s16* arg0, s16 arg1, s16 arg2, s16 arg3) {
|
|
|
|
|
if (DECR(arg0[1]) == 0) {
|
|
|
|
|
arg0[1] = Rand_S16Offset(arg1, arg2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((arg0[1] - arg3) > 0) {
|
|
|
|
|
arg0[0] = 0;
|
|
|
|
|
} else if (((arg0[1] - arg3) > -2) || (arg0[1] < 2)) {
|
|
|
|
|
arg0[0] = 1;
|
|
|
|
|
} else {
|
|
|
|
|
arg0[0] = 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return arg0[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s16 func_80032D60(s16* arg0, s16 arg1, s16 arg2, s16 arg3) {
|
|
|
|
|
if (DECR(arg0[1]) == 0) {
|
|
|
|
|
arg0[1] = Rand_S16Offset(arg1, arg2);
|
|
|
|
|
arg0[0]++;
|
|
|
|
|
|
|
|
|
|
if ((arg0[0] % 3) == 0) {
|
|
|
|
|
arg0[0] = (s32)(Rand_ZeroOne() * arg3) * 3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return arg0[0];
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void BodyBreak_Alloc(BodyBreak* bodyBreak, s32 count, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
u32 matricesSize;
|
|
|
|
|
u32 dListsSize;
|
|
|
|
|
u32 objectIdsSize;
|
|
|
|
|
|
|
|
|
|
matricesSize = (count + 1) * sizeof(*bodyBreak->matrices);
|
2022-07-05 19:29:34 -04:00
|
|
|
|
bodyBreak->matrices = ZELDA_ARENA_MALLOC_DEBUG(matricesSize);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (bodyBreak->matrices != NULL) {
|
|
|
|
|
dListsSize = (count + 1) * sizeof(*bodyBreak->dLists);
|
2022-07-05 19:29:34 -04:00
|
|
|
|
bodyBreak->dLists = ZELDA_ARENA_MALLOC_DEBUG(dListsSize);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (bodyBreak->dLists != NULL) {
|
|
|
|
|
objectIdsSize = (count + 1) * sizeof(*bodyBreak->objectIds);
|
2022-07-05 19:29:34 -04:00
|
|
|
|
bodyBreak->objectIds = ZELDA_ARENA_MALLOC_DEBUG(objectIdsSize);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (bodyBreak->objectIds != NULL) {
|
|
|
|
|
memset((u8*)bodyBreak->matrices,0, matricesSize);
|
|
|
|
|
memset((u8*)bodyBreak->dLists, 0, dListsSize);
|
|
|
|
|
memset((u8*)bodyBreak->objectIds, 0, objectIdsSize);
|
|
|
|
|
bodyBreak->val = 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bodyBreak->matrices != NULL) {
|
2022-07-05 19:29:34 -04:00
|
|
|
|
ZELDA_ARENA_FREE_DEBUG(bodyBreak->matrices);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bodyBreak->dLists != NULL) {
|
2022-07-05 19:29:34 -04:00
|
|
|
|
ZELDA_ARENA_FREE_DEBUG(bodyBreak->dLists);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bodyBreak->objectIds != NULL) {
|
2022-07-05 19:29:34 -04:00
|
|
|
|
ZELDA_ARENA_FREE_DEBUG(bodyBreak->objectIds);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BodyBreak_SetInfo(BodyBreak* bodyBreak, s32 limbIndex, s32 minLimbIndex, s32 maxLimbIndex, u32 count, Gfx** dList,
|
|
|
|
|
s16 objectId) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
PlayState* play = Effect_GetPlayState();
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if ((play->actorCtx.freezeFlashTimer == 0) && (bodyBreak->val > 0)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if ((limbIndex >= minLimbIndex) && (limbIndex <= maxLimbIndex) && (*dList != NULL)) {
|
|
|
|
|
bodyBreak->dLists[bodyBreak->val] = *dList;
|
|
|
|
|
Matrix_Get(&bodyBreak->matrices[bodyBreak->val]);
|
|
|
|
|
bodyBreak->objectIds[bodyBreak->val] = objectId;
|
|
|
|
|
bodyBreak->val++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (limbIndex != bodyBreak->prevLimbIndex) {
|
|
|
|
|
bodyBreak->count++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((u32)bodyBreak->count >= count) {
|
|
|
|
|
bodyBreak->count = bodyBreak->val - 1;
|
|
|
|
|
bodyBreak->val = BODYBREAK_STATUS_READY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bodyBreak->prevLimbIndex = limbIndex;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 BodyBreak_SpawnParts(Actor* actor, BodyBreak* bodyBreak, PlayState* play, s16 type) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
EnPart* spawnedEnPart;
|
|
|
|
|
MtxF* mtx;
|
|
|
|
|
s16 objBankIndex;
|
|
|
|
|
|
|
|
|
|
if (bodyBreak->val != BODYBREAK_STATUS_READY) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (bodyBreak->count > 0) {
|
|
|
|
|
Matrix_Put(&bodyBreak->matrices[bodyBreak->count]);
|
|
|
|
|
Matrix_Scale(1.0f / actor->scale.x, 1.0f / actor->scale.y, 1.0f / actor->scale.z, MTXMODE_APPLY);
|
|
|
|
|
Matrix_Get(&bodyBreak->matrices[bodyBreak->count]);
|
|
|
|
|
|
|
|
|
|
if (1) {
|
|
|
|
|
if (bodyBreak->objectIds[bodyBreak->count] >= 0) {
|
|
|
|
|
objBankIndex = bodyBreak->objectIds[bodyBreak->count];
|
|
|
|
|
} else {
|
|
|
|
|
objBankIndex = actor->objBankIndex;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mtx = &bodyBreak->matrices[bodyBreak->count];
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
spawnedEnPart = (EnPart*)Actor_SpawnAsChild(&play->actorCtx, actor, play, ACTOR_EN_PART, mtx->xw,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
mtx->yw, mtx->zw, 0, 0, objBankIndex, type);
|
|
|
|
|
|
|
|
|
|
if (spawnedEnPart != NULL) {
|
|
|
|
|
Matrix_MtxFToYXZRotS(&bodyBreak->matrices[bodyBreak->count], &spawnedEnPart->actor.shape.rot, 0);
|
|
|
|
|
spawnedEnPart->displayList = bodyBreak->dLists[bodyBreak->count];
|
|
|
|
|
spawnedEnPart->actor.scale = actor->scale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bodyBreak->count--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bodyBreak->val = BODYBREAK_STATUS_FINISHED;
|
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
|
ZELDA_ARENA_FREE_DEBUG(bodyBreak->matrices);
|
|
|
|
|
ZELDA_ARENA_FREE_DEBUG(bodyBreak->dLists);
|
|
|
|
|
ZELDA_ARENA_FREE_DEBUG(bodyBreak->objectIds);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_SpawnFloorDustRing(PlayState* play, Actor* actor, Vec3f* posXZ, f32 radius, s32 amountMinusOne,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 randAccelWeight, s16 scale, s16 scaleStep, u8 useLighting) {
|
|
|
|
|
Vec3f pos;
|
|
|
|
|
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
|
|
|
|
|
Vec3f accel = { 0.0f, 0.3f, 0.0f };
|
|
|
|
|
f32 angle;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
|
|
angle = (Rand_ZeroOne() - 0.5f) * (2.0f * 3.14f);
|
|
|
|
|
pos.y = actor->floorHeight;
|
|
|
|
|
accel.y += (Rand_ZeroOne() - 0.5f) * 0.2f;
|
|
|
|
|
|
|
|
|
|
for (i = amountMinusOne; i >= 0; i--) {
|
|
|
|
|
pos.x = Math_SinF(angle) * radius + posXZ->x;
|
|
|
|
|
pos.z = Math_CosF(angle) * radius + posXZ->z;
|
|
|
|
|
accel.x = (Rand_ZeroOne() - 0.5f) * randAccelWeight;
|
|
|
|
|
accel.z = (Rand_ZeroOne() - 0.5f) * randAccelWeight;
|
|
|
|
|
|
|
|
|
|
if (scale == 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002857C(play, &pos, &velocity, &accel);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
|
|
|
|
if (useLighting) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_800286CC(play, &pos, &velocity, &accel, scale, scaleStep);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002865C(play, &pos, &velocity, &accel, scale, scaleStep);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
angle += (2.0f * 3.14f) / (amountMinusOne + 1.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80033480(PlayState* play, Vec3f* posBase, f32 randRangeDiameter, s32 amountMinusOne, s16 scaleBase,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s16 scaleStep, u8 arg6) {
|
|
|
|
|
Vec3f pos;
|
|
|
|
|
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
|
|
|
|
|
Vec3f accel = { 0.0f, 0.3f, 0.0f };
|
|
|
|
|
s16 scale;
|
|
|
|
|
u32 var2;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
|
|
for (i = amountMinusOne; i >= 0; i--) {
|
|
|
|
|
pos.x = posBase->x + ((Rand_ZeroOne() - 0.5f) * randRangeDiameter);
|
|
|
|
|
pos.y = posBase->y + ((Rand_ZeroOne() - 0.5f) * randRangeDiameter);
|
|
|
|
|
pos.z = posBase->z + ((Rand_ZeroOne() - 0.5f) * randRangeDiameter);
|
|
|
|
|
|
|
|
|
|
scale = (s16)((Rand_ZeroOne() * scaleBase) * 0.2f) + scaleBase;
|
|
|
|
|
var2 = arg6;
|
|
|
|
|
|
|
|
|
|
if (var2 != 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_800286CC(play, &pos, &velocity, &accel, scale, scaleStep);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002865C(play, &pos, &velocity, &accel, scale, scaleStep);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* Actor_GetCollidedExplosive(PlayState* play, Collider* collider) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if ((collider->acFlags & AC_HIT) && (collider->ac->category == ACTORCAT_EXPLOSIVE)) {
|
|
|
|
|
collider->acFlags &= ~AC_HIT;
|
|
|
|
|
return collider->ac;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* func_80033684(PlayState* play, Actor* explosiveActor) {
|
|
|
|
|
Actor* actor = play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].head;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
while (actor != NULL) {
|
|
|
|
|
if ((actor == explosiveActor) || (actor->params != 1)) {
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
} else {
|
|
|
|
|
if (Actor_WorldDistXYZToActor(explosiveActor, actor) <= (actor->shape.rot.z * 10) + 80.0f) {
|
|
|
|
|
return actor;
|
|
|
|
|
} else {
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Dynamically changes the category of a given actor instance.
|
|
|
|
|
* This is done by moving it to the corresponding category list and setting its category variable accordingly.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_ChangeCategory(PlayState* play, ActorContext* actorCtx, Actor* actor, u8 actorCategory) {
|
|
|
|
|
Actor_RemoveFromCategory(play, actorCtx, actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor_AddToCategory(actorCtx, actor, actorCategory);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks if a hookshot or arrow actor is going to collide with the cylinder denoted by the
|
|
|
|
|
* actor's `cylRadius` and `cylHeight`.
|
|
|
|
|
* The check is only peformed if the projectile actor is within the provided sphere radius.
|
|
|
|
|
*
|
|
|
|
|
* Returns the actor if there will be collision, NULL otherwise.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* Actor_GetProjectileActor(PlayState* play, Actor* refActor, f32 radius) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Actor* actor;
|
|
|
|
|
Vec3f spA8;
|
|
|
|
|
f32 deltaX;
|
|
|
|
|
f32 deltaY;
|
|
|
|
|
f32 deltaZ;
|
|
|
|
|
Vec3f sp90;
|
|
|
|
|
Vec3f sp84;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
actor = play->actorCtx.actorLists[ACTORCAT_ITEMACTION].head;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
while (actor != NULL) {
|
|
|
|
|
if (((actor->id != ACTOR_ARMS_HOOK) && (actor->id != ACTOR_EN_ARROW)) || (actor == refActor)) {
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
} else {
|
|
|
|
|
//! @bug The projectile actor gets unsafely casted to a hookshot to check its timer, even though
|
|
|
|
|
// it can also be an arrow.
|
|
|
|
|
// Luckily, the field at the same offset in the arrow actor is the x component of a vector
|
|
|
|
|
// which will rarely ever be 0. So it's very unlikely for this bug to cause an issue.
|
|
|
|
|
if ((Math_Vec3f_DistXYZ(&refActor->world.pos, &actor->world.pos) > radius) ||
|
|
|
|
|
(((ArmsHook*)actor)->timer == 0)) {
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
} else {
|
|
|
|
|
deltaX = Math_SinS(actor->world.rot.y) * (actor->speedXZ * 10.0f);
|
|
|
|
|
deltaY = actor->velocity.y + (actor->gravity * 10.0f);
|
|
|
|
|
deltaZ = Math_CosS(actor->world.rot.y) * (actor->speedXZ * 10.0f);
|
|
|
|
|
|
|
|
|
|
spA8.x = actor->world.pos.x + deltaX;
|
|
|
|
|
spA8.y = actor->world.pos.y + deltaY;
|
|
|
|
|
spA8.z = actor->world.pos.z + deltaZ;
|
|
|
|
|
|
|
|
|
|
if (CollisionCheck_CylSideVsLineSeg(refActor->colChkInfo.cylRadius, refActor->colChkInfo.cylHeight,
|
|
|
|
|
0.0f, &refActor->world.pos, &actor->world.pos, &spA8, &sp90,
|
|
|
|
|
&sp84)) {
|
|
|
|
|
return actor;
|
|
|
|
|
} else {
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the actor's text id with a dynamic prefix based on the current scene.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_SetTextWithPrefix(PlayState* play, Actor* actor, s16 baseTextId) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s16 prefix;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
switch (play->sceneNum) {
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_DEKU_TREE:
|
|
|
|
|
case SCENE_DEKU_TREE_BOSS:
|
|
|
|
|
case SCENE_FOREST_TEMPLE_BOSS:
|
|
|
|
|
case SCENE_KNOW_IT_ALL_BROS_HOUSE:
|
|
|
|
|
case SCENE_TWINS_HOUSE:
|
|
|
|
|
case SCENE_MIDOS_HOUSE:
|
|
|
|
|
case SCENE_SARIAS_HOUSE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
case SCENE_KOKIRI_SHOP:
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_LINKS_HOUSE:
|
|
|
|
|
case SCENE_KOKIRI_FOREST:
|
|
|
|
|
case SCENE_SACRED_FOREST_MEADOW:
|
|
|
|
|
case SCENE_LOST_WOODS:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
case 112:
|
|
|
|
|
prefix = 0x1000;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_STABLE:
|
|
|
|
|
case SCENE_HYRULE_FIELD:
|
|
|
|
|
case SCENE_LON_LON_RANCH:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
prefix = 0x2000;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_FIRE_TEMPLE:
|
|
|
|
|
case SCENE_DODONGOS_CAVERN_BOSS:
|
|
|
|
|
case SCENE_FIRE_TEMPLE_BOSS:
|
|
|
|
|
case SCENE_DEATH_MOUNTAIN_TRAIL:
|
|
|
|
|
case SCENE_DEATH_MOUNTAIN_CRATER:
|
|
|
|
|
case SCENE_GORON_CITY:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
prefix = 0x3000;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_JABU_JABU:
|
|
|
|
|
case SCENE_JABU_JABU_BOSS:
|
|
|
|
|
case SCENE_ZORAS_RIVER:
|
|
|
|
|
case SCENE_ZORAS_DOMAIN:
|
|
|
|
|
case SCENE_ZORAS_FOUNTAIN:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
prefix = 0x4000;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_SHADOW_TEMPLE:
|
|
|
|
|
case SCENE_SHADOW_TEMPLE_BOSS:
|
|
|
|
|
case SCENE_KAKARIKO_CENTER_GUEST_HOUSE:
|
|
|
|
|
case SCENE_BACK_ALLEY_HOUSE:
|
|
|
|
|
case SCENE_DOG_LADY_HOUSE:
|
|
|
|
|
case SCENE_GRAVEKEEPERS_HUT:
|
|
|
|
|
case SCENE_REDEAD_GRAVE:
|
|
|
|
|
case SCENE_WINDMILL_AND_DAMPES_GRAVE:
|
|
|
|
|
case SCENE_KAKARIKO_VILLAGE:
|
|
|
|
|
case SCENE_GRAVEYARD:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
prefix = 0x5000;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_SPIRIT_TEMPLE:
|
|
|
|
|
case SCENE_SPIRIT_TEMPLE_BOSS:
|
|
|
|
|
case SCENE_IMPAS_HOUSE:
|
|
|
|
|
case SCENE_CARPENTERS_TENT:
|
|
|
|
|
case SCENE_LAKE_HYLIA:
|
|
|
|
|
case SCENE_GERUDO_VALLEY:
|
|
|
|
|
case SCENE_DESERT_COLOSSUS:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
prefix = 0x6000;
|
|
|
|
|
break;
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_MARKET_ENTRANCE_DAY:
|
|
|
|
|
case SCENE_BACK_ALLEY_DAY:
|
|
|
|
|
case SCENE_BACK_ALLEY_NIGHT:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
case SCENE_MARKET_DAY:
|
|
|
|
|
case SCENE_MARKET_NIGHT:
|
|
|
|
|
case SCENE_MARKET_RUINS:
|
2023-09-01 12:46:19 -04:00
|
|
|
|
case SCENE_HYRULE_CASTLE:
|
2022-03-21 21:51:23 -04:00
|
|
|
|
prefix = 0x7000;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
prefix = 0x0000;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actor->textId = prefix | baseTextId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks if a given actor will be standing on the ground after being translated
|
|
|
|
|
* by the provided distance and angle.
|
|
|
|
|
*
|
|
|
|
|
* Returns true if the actor will be standing on ground.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s16 Actor_TestFloorInDirection(Actor* actor, PlayState* play, f32 distance, s16 angle) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s16 ret;
|
|
|
|
|
s16 prevBgCheckFlags;
|
|
|
|
|
f32 dx;
|
|
|
|
|
f32 dz;
|
|
|
|
|
Vec3f prevActorPos;
|
|
|
|
|
|
|
|
|
|
Math_Vec3f_Copy(&prevActorPos, &actor->world.pos);
|
|
|
|
|
prevBgCheckFlags = actor->bgCheckFlags;
|
|
|
|
|
|
|
|
|
|
dx = Math_SinS(angle) * distance;
|
|
|
|
|
dz = Math_CosS(angle) * distance;
|
|
|
|
|
actor->world.pos.x += dx;
|
|
|
|
|
actor->world.pos.z += dz;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_UpdateBgCheckInfo(play, actor, 0.0f, 0.0f, 0.0f, 4);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
Math_Vec3f_Copy(&actor->world.pos, &prevActorPos);
|
|
|
|
|
|
|
|
|
|
ret = actor->bgCheckFlags & 1;
|
|
|
|
|
actor->bgCheckFlags = prevBgCheckFlags;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if the player is targeting the provided actor
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Actor_IsTargeted(PlayState* play, Actor* actor) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
if ((player->stateFlags1 & PLAYER_STATE1_ENEMY_TARGET) && actor->isTargeted) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if the player is targeting an actor other than the provided actor
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 Actor_OtherIsTargeted(PlayState* play, Actor* actor) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2024-02-15 20:17:28 -05:00
|
|
|
|
if ((player->stateFlags1 & PLAYER_STATE1_ENEMY_TARGET) && !actor->isTargeted) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 func_80033AEC(Vec3f* arg0, Vec3f* arg1, f32 arg2, f32 arg3, f32 arg4, f32 arg5) {
|
|
|
|
|
f32 ret = 0.0f;
|
|
|
|
|
|
|
|
|
|
if (arg4 <= Math_Vec3f_DistXYZ(arg0, arg1)) {
|
|
|
|
|
ret = Math_SmoothStepToF(&arg1->x, arg0->x, arg2, arg3, 0.0f);
|
|
|
|
|
ret += Math_SmoothStepToF(&arg1->y, arg0->y, arg2, arg3, 0.0f);
|
|
|
|
|
ret += Math_SmoothStepToF(&arg1->z, arg0->z, arg2, arg3, 0.0f);
|
|
|
|
|
} else if (arg5 < Math_Vec3f_DistXYZ(arg0, arg1)) {
|
|
|
|
|
ret = Math_SmoothStepToF(&arg1->x, arg0->x, arg2, arg3, 0.0f);
|
|
|
|
|
ret += Math_SmoothStepToF(&arg1->y, arg0->y, arg2, arg3, 0.0f);
|
|
|
|
|
ret += Math_SmoothStepToF(&arg1->z, arg0->z, arg2, arg3, 0.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80033C30(Vec3f* arg0, Vec3f* arg1, u8 alpha, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
MtxF sp60;
|
|
|
|
|
f32 var;
|
|
|
|
|
Vec3f sp50;
|
|
|
|
|
CollisionPoly* sp4C;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-29 18:29:36 -05:00
|
|
|
|
POLY_OPA_DISP = Gfx_SetupDL(POLY_OPA_DISP, 0x2C);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 0, 0, alpha);
|
|
|
|
|
|
|
|
|
|
sp50.x = arg0->x;
|
|
|
|
|
sp50.y = arg0->y + 1.0f;
|
|
|
|
|
sp50.z = arg0->z;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
var = BgCheck_EntityRaycastFloor2(play, &play->colCtx, &sp4C, &sp50);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if (sp4C != NULL) {
|
|
|
|
|
func_80038A28(sp4C, arg0->x, var, arg0->z, &sp60);
|
|
|
|
|
Matrix_Put(&sp60);
|
|
|
|
|
} else {
|
|
|
|
|
Matrix_Translate(arg0->x, arg0->y, arg0->z, MTXMODE_NEW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrix_Scale(arg1->x, 1.0f, arg1->z, MTXMODE_APPLY);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_MTX_MODELVIEW | G_MTX_LOAD);
|
|
|
|
|
gSPDisplayList(POLY_OPA_DISP++, gCircleShadowDL);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80033DB8(PlayState* play, s16 arg1, s16 arg2) {
|
|
|
|
|
s16 var = Quake_Add(&play->mainCamera, 3);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
Quake_SetSpeed(var, 20000);
|
|
|
|
|
Quake_SetQuakeValues(var, arg1, 0, 0, 0);
|
|
|
|
|
Quake_SetCountdown(var, arg2);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80033E1C(PlayState* play, s16 arg1, s16 arg2, s16 arg3) {
|
|
|
|
|
s16 var = Quake_Add(&play->mainCamera, 3);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
Quake_SetSpeed(var, arg3);
|
|
|
|
|
Quake_SetQuakeValues(var, arg1, 0, 0, 0);
|
|
|
|
|
Quake_SetCountdown(var, arg2);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80033E88(Actor* actor, PlayState* play, s16 arg2, s16 arg3) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (arg2 >= 5) {
|
|
|
|
|
func_800AA000(actor->xyzDistToPlayerSq, 0xFF, 0x14, 0x96);
|
|
|
|
|
} else {
|
|
|
|
|
func_800AA000(actor->xyzDistToPlayerSq, 0xB4, 0x14, 0x64);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80033DB8(play, arg2, arg3);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 Rand_ZeroFloat(f32 f) {
|
|
|
|
|
return Rand_ZeroOne() * f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f32 Rand_CenteredFloat(f32 f) {
|
|
|
|
|
return (Rand_ZeroOne() - 0.5f) * f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
/* 0x00 */ f32 chainAngle;
|
|
|
|
|
/* 0x04 */ f32 chainLength;
|
|
|
|
|
/* 0x08 */ f32 yShift;
|
|
|
|
|
/* 0x0C */ f32 chainsScale;
|
|
|
|
|
/* 0x10 */ f32 chainsRotZInit;
|
|
|
|
|
/* 0x14 */ Gfx* chainDL;
|
|
|
|
|
/* 0x18 */ Gfx* lockDL;
|
|
|
|
|
} DoorLockInfo; // size = 0x1C
|
|
|
|
|
|
|
|
|
|
static DoorLockInfo sDoorLocksInfo[] = {
|
2023-09-10 13:21:56 -04:00
|
|
|
|
/* DOORLOCK_NORMAL */ { 0.54f, 6000.0f, 5000.0f, 1.0f, 0.0f, gDoorChainDL, gDoorLockDL },
|
|
|
|
|
/* DOORLOCK_BOSS */ { 0.644f, 12000.0f, 8000.0f, 1.0f, 0.0f, gBossDoorChainDL, gBossDoorLockDL },
|
|
|
|
|
/* DOORLOCK_NORMAL_SPIRIT */ { 0.64000005f, 8500.0f, 8000.0f, 1.75f, 0.1f, gDoorChainDL, gDoorLockDL },
|
2022-03-21 21:51:23 -04:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Draws chains and lock of a locked door, of the specified `type` (see `DoorLockType`).
|
|
|
|
|
* `frame` can be 0 to 10, where 0 is "open" and 10 is "closed", the chains slide accordingly.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_DrawDoorLock(PlayState* play, s32 frame, s32 type) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
DoorLockInfo* entry;
|
|
|
|
|
s32 i;
|
|
|
|
|
MtxF baseMtxF;
|
|
|
|
|
f32 chainRotZ;
|
|
|
|
|
f32 chainsTranslateX;
|
|
|
|
|
f32 chainsTranslateY;
|
|
|
|
|
f32 rotZStep;
|
|
|
|
|
|
|
|
|
|
entry = &sDoorLocksInfo[type];
|
|
|
|
|
chainRotZ = entry->chainsRotZInit;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
Matrix_Translate(0.0f, entry->yShift, 500.0f, MTXMODE_APPLY);
|
|
|
|
|
Matrix_Get(&baseMtxF);
|
|
|
|
|
|
|
|
|
|
chainsTranslateX = sinf(entry->chainAngle - chainRotZ) * -(10 - frame) * 0.1f * entry->chainLength;
|
|
|
|
|
chainsTranslateY = cosf(entry->chainAngle - chainRotZ) * (10 - frame) * 0.1f * entry->chainLength;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
2022-08-14 23:18:12 -04:00
|
|
|
|
FrameInterpolation_RecordOpenChild(entry, i);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Matrix_Put(&baseMtxF);
|
|
|
|
|
Matrix_RotateZ(chainRotZ, MTXMODE_APPLY);
|
|
|
|
|
Matrix_Translate(chainsTranslateX, chainsTranslateY, 0.0f, MTXMODE_APPLY);
|
|
|
|
|
|
|
|
|
|
if (entry->chainsScale != 1.0f) {
|
|
|
|
|
Matrix_Scale(entry->chainsScale, entry->chainsScale, entry->chainsScale, MTXMODE_APPLY);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_MTX_MODELVIEW | G_MTX_LOAD);
|
|
|
|
|
gSPDisplayList(POLY_OPA_DISP++, entry->chainDL);
|
|
|
|
|
|
|
|
|
|
if (i % 2) {
|
|
|
|
|
rotZStep = 2.0f * entry->chainAngle;
|
|
|
|
|
} else {
|
|
|
|
|
rotZStep = M_PI - (2.0f * entry->chainAngle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chainRotZ += rotZStep;
|
2022-08-03 22:36:13 -04:00
|
|
|
|
FrameInterpolation_RecordCloseChild();
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrix_Put(&baseMtxF);
|
|
|
|
|
Matrix_Scale(frame * 0.1f, frame * 0.1f, frame * 0.1f, MTXMODE_APPLY);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
|
G_MTX_MODELVIEW | G_MTX_LOAD);
|
|
|
|
|
gSPDisplayList(POLY_OPA_DISP++, entry->lockDL);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8003424C(PlayState* play, Vec3f* arg1) {
|
|
|
|
|
CollisionCheck_SpawnShieldParticlesMetal(play, arg1);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_SetColorFilter(Actor* actor, s16 colorFlag, s16 colorIntensityMax, s16 xluFlag, s16 duration) {
|
|
|
|
|
if ((colorFlag == 0x8000) && !(colorIntensityMax & 0x8000)) {
|
|
|
|
|
Audio_PlayActorSound2(actor, NA_SE_EN_LIGHT_ARROW_HIT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actor->colorFilterParams = colorFlag | xluFlag | ((colorIntensityMax & 0xF8) << 5) | duration;
|
|
|
|
|
actor->colorFilterTimer = duration;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Hilite* func_800342EC(Vec3f* object, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Vec3f lightDir;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
lightDir.x = play->envCtx.dirLight1.params.dir.x;
|
|
|
|
|
lightDir.y = play->envCtx.dirLight1.params.dir.y;
|
|
|
|
|
lightDir.z = play->envCtx.dirLight1.params.dir.z;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
return func_8002EABC(object, &play->view.eye, &lightDir, play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Hilite* func_8003435C(Vec3f* object, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Vec3f lightDir;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
lightDir.x = play->envCtx.dirLight1.params.dir.x;
|
|
|
|
|
lightDir.y = play->envCtx.dirLight1.params.dir.y;
|
|
|
|
|
lightDir.z = play->envCtx.dirLight1.params.dir.z;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
return func_8002EB44(object, &play->view.eye, &lightDir, play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
/**
|
|
|
|
|
* Updates NPC talking state. Checks for a talk request and updates
|
|
|
|
|
* the talkState parameter when a dialog is ongoing. Otherwise checks if
|
|
|
|
|
* the actor is onscreen, advertises the interaction in a range and sets
|
|
|
|
|
* the current text id if necessary.
|
|
|
|
|
*
|
|
|
|
|
* The talk state values are defined in the NpcTalkState enum.
|
|
|
|
|
*
|
|
|
|
|
* @see NpcTalkState
|
|
|
|
|
*
|
|
|
|
|
* @param[in,out] talkState Talk state
|
|
|
|
|
* @param interactRange The interact (talking) range for the actor
|
|
|
|
|
* @param getTextId Callback for getting the next text id
|
|
|
|
|
* @param updateTalkState Callback for getting the next talkState value
|
|
|
|
|
* @return True if a new dialog was started (player talked to the actor). False otherwise.
|
|
|
|
|
*/
|
|
|
|
|
s32 Npc_UpdateTalking(PlayState* play, Actor* actor, s16* talkState, f32 interactRange, NpcGetTextIdFunc getTextId,
|
|
|
|
|
NpcUpdateTalkStateFunc updateTalkState) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s16 x;
|
|
|
|
|
s16 y;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (Actor_ProcessTalkRequest(actor, play)) {
|
2023-01-19 02:38:04 -05:00
|
|
|
|
*talkState = NPC_TALK_STATE_TALKING;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
if (*talkState != NPC_TALK_STATE_IDLE) {
|
|
|
|
|
*talkState = updateTalkState(play, actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_GetScreenPos(play, actor, &x, &y);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if ((x < 0) || (x > SCREEN_WIDTH) || (y < 0) || (y > SCREEN_HEIGHT)) {
|
2023-01-19 02:38:04 -05:00
|
|
|
|
// Actor is offscreen
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (!func_8002F2CC(actor, play, interactRange)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
actor->textId = getTextId(play, actor);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2023-01-19 02:38:04 -05:00
|
|
|
|
/* 0x00 */ s16 maxHeadYaw;
|
|
|
|
|
/* 0x02 */ s16 minHeadPitch;
|
|
|
|
|
/* 0x04 */ s16 maxHeadPitch;
|
|
|
|
|
/* 0x06 */ s16 maxTorsoYaw;
|
|
|
|
|
/* 0x08 */ s16 minTorsoPitch;
|
|
|
|
|
/* 0x0A */ s16 maxTorsoPitch;
|
|
|
|
|
/* 0x0C */ u8 rotateYaw;
|
|
|
|
|
} NpcTrackingRotLimits; // size = 0x10
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
typedef struct {
|
2023-01-19 02:38:04 -05:00
|
|
|
|
/* 0x00 */ NpcTrackingRotLimits rotLimits;
|
|
|
|
|
// Fields specific to NPC_TRACKING_PLAYER_AUTO_TURN mode
|
|
|
|
|
/* 0x10 */ f32 autoTurnDistanceRange; // Max distance to player to enable tracking and auto-turn
|
|
|
|
|
/* 0x14 */ s16 maxYawForPlayerTracking; // Player is tracked if within this yaw
|
|
|
|
|
} NpcTrackingParams; // size = 0x18
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Npc tracking angle limit presets to use with Npc_TrackPoint.
|
|
|
|
|
*
|
|
|
|
|
* @see Npc_TrackPoint
|
|
|
|
|
*/
|
|
|
|
|
static NpcTrackingParams sNpcTrackingPresets[] = {
|
|
|
|
|
{ { 0x2AA8, -0x0E38, 0x18E2, 0x1554, 0x0000, 0x0000, true }, 170.0f, 0x3FFC },
|
|
|
|
|
{ { 0x2AA8, -0x1554, 0x1554, 0x1554, -0x071C, 0x0E38, true }, 170.0f, 0x3FFC },
|
|
|
|
|
{ { 0x31C4, -0x1C70, 0x0E38, 0x0E38, -0x0E38, 0x071C, true }, 170.0f, 0x3FFC },
|
|
|
|
|
{ { 0x1554, -0x0E38, 0x0000, 0x071C, -0x071C, 0x0000, true }, 170.0f, 0x3FFC },
|
|
|
|
|
{ { 0x2AA8, -0x071C, 0x071C, 0x0E38, -0x2AA8, 0x2AA8, true }, 170.0f, 0x3FFC },
|
|
|
|
|
{ { 0x0000, -0x1C70, 0x2AA8, 0x3FFC, -0x0E38, 0x0E38, true }, 170.0f, 0x3FFC },
|
|
|
|
|
{ { 0x2AA8, -0x0E38, 0x0E38, 0x0E38, 0x0000, 0x0000, true }, 0.0f, 0x0000 },
|
|
|
|
|
{ { 0x2AA8, -0x0E38, 0x0000, 0x0E38, 0x0000, 0x1C70, true }, 0.0f, 0x0000 },
|
|
|
|
|
{ { 0x2AA8, -0x0E38, -0x0E38, 0x0000, 0x0000, 0x0000, true }, 0.0f, 0x0000 },
|
|
|
|
|
{ { 0x071C, -0x0E38, 0x0E38, 0x1C70, 0x0000, 0x0000, true }, 0.0f, 0x0000 },
|
|
|
|
|
{ { 0x0E38, -0x0E38, 0x0000, 0x1C70, 0x0000, 0x0E38, true }, 0.0f, 0x0000 },
|
|
|
|
|
{ { 0x2AA8, -0x1C70, 0x1C70, 0x0E38, -0x0E38, 0x0E38, true }, 0.0f, 0x0000 },
|
|
|
|
|
{ { 0x18E2, -0x0E38, 0x0E38, 0x0E38, 0x0000, 0x0000, true }, 0.0f, 0x0000 },
|
2022-03-21 21:51:23 -04:00
|
|
|
|
};
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
/**
|
|
|
|
|
* Smoothly turns the actor's whole body and updates torso and head rotations in
|
|
|
|
|
* NpcInteractInfo so that the actor tracks the point specified in NpcInteractInfo.trackPos.
|
|
|
|
|
* Rotations are limited to specified angles.
|
|
|
|
|
*
|
|
|
|
|
* Head and torso rotation angles are determined by calculating the pitch and yaw
|
|
|
|
|
* from the actor position to the given target position.
|
|
|
|
|
*
|
|
|
|
|
* The y position of the actor is offset by NpcInteractInfo.yOffset
|
|
|
|
|
* before calculating the angles. It can be used to configure the height difference
|
|
|
|
|
* between the actor and the target.
|
|
|
|
|
*
|
|
|
|
|
* @param maxHeadYaw maximum head yaw difference from neutral position
|
|
|
|
|
* @param maxHeadPitch maximum head pitch angle
|
|
|
|
|
* @param minHeadPitch minimum head pitch angle
|
|
|
|
|
* @param maxTorsoYaw maximum torso yaw difference from neutral position
|
|
|
|
|
* @param maxTorsoPitch maximum torso pitch angle
|
|
|
|
|
* @param minTorsoPitch minimum torso pitch angle
|
|
|
|
|
* @param rotateYaw if true, the actor's yaw (shape.rot.y) is updated to turn the actor's whole body
|
|
|
|
|
*/
|
|
|
|
|
void Npc_TrackPointWithLimits(Actor* actor, NpcInteractInfo* interactInfo, s16 maxHeadYaw, s16 maxHeadPitch,
|
|
|
|
|
s16 minHeadPitch, s16 maxTorsoYaw, s16 maxTorsoPitch, s16 minTorsoPitch, u8 rotateYaw) {
|
|
|
|
|
s16 pitchTowardsTarget;
|
|
|
|
|
s16 yawTowardsTarget;
|
|
|
|
|
s16 torsoPitch;
|
|
|
|
|
s16 bodyYawDiff;
|
|
|
|
|
s16 temp;
|
|
|
|
|
Vec3f offsetActorPos;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
offsetActorPos.x = actor->world.pos.x;
|
|
|
|
|
offsetActorPos.y = actor->world.pos.y + interactInfo->yOffset;
|
|
|
|
|
offsetActorPos.z = actor->world.pos.z;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
pitchTowardsTarget = Math_Vec3f_Pitch(&offsetActorPos, &interactInfo->trackPos);
|
|
|
|
|
yawTowardsTarget = Math_Vec3f_Yaw(&offsetActorPos, &interactInfo->trackPos);
|
|
|
|
|
bodyYawDiff = Math_Vec3f_Yaw(&actor->world.pos, &interactInfo->trackPos) - actor->shape.rot.y;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
temp = CLAMP(bodyYawDiff, -maxHeadYaw, maxHeadYaw);
|
|
|
|
|
Math_SmoothStepToS(&interactInfo->headRot.y, temp, 6, 2000, 1);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
temp = (ABS(bodyYawDiff) >= 0x8000) ? 0 : ABS(bodyYawDiff);
|
|
|
|
|
interactInfo->headRot.y = CLAMP(interactInfo->headRot.y, -temp, temp);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
bodyYawDiff -= interactInfo->headRot.y;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
temp = CLAMP(bodyYawDiff, -maxTorsoYaw, maxTorsoYaw);
|
|
|
|
|
Math_SmoothStepToS(&interactInfo->torsoRot.y, temp, 6, 2000, 1);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
temp = (ABS(bodyYawDiff) >= 0x8000) ? 0 : ABS(bodyYawDiff);
|
|
|
|
|
interactInfo->torsoRot.y = CLAMP(interactInfo->torsoRot.y, -temp, temp);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
if (rotateYaw) {
|
|
|
|
|
Math_SmoothStepToS(&actor->shape.rot.y, yawTowardsTarget, 6, 2000, 1);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
temp = CLAMP(pitchTowardsTarget, minHeadPitch, (s16)(u16)maxHeadPitch);
|
|
|
|
|
Math_SmoothStepToS(&interactInfo->headRot.x, temp, 6, 2000, 1);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
torsoPitch = pitchTowardsTarget - interactInfo->headRot.x;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
temp = CLAMP(torsoPitch, minTorsoPitch, maxTorsoPitch);
|
|
|
|
|
Math_SmoothStepToS(&interactInfo->torsoRot.x, temp, 6, 2000, 1);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
s16 Npc_GetTrackingPresetMaxPlayerYaw(s16 presetIndex) {
|
|
|
|
|
return sNpcTrackingPresets[presetIndex].maxYawForPlayerTracking;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
/**
|
|
|
|
|
* Handles NPC tracking modes and auto-turning towards the player when
|
|
|
|
|
* NPC_TRACKING_PLAYER_AUTO_TURN tracking mode is used.
|
|
|
|
|
*
|
|
|
|
|
* Returns a tracking mode that will determine which actor limbs
|
|
|
|
|
* will be rotated towards the target.
|
|
|
|
|
*
|
|
|
|
|
* When the player is behind the actor (i.e. not in the yaw range in front of the actor
|
|
|
|
|
* defined by maxYawForPlayerTracking), the actor will start an auto-turn sequence:
|
|
|
|
|
* - look forward for 30-60 frames
|
|
|
|
|
* - turn head to look at the player for 10-20 frames
|
|
|
|
|
* - look forward for 30-60 frames
|
|
|
|
|
* - turn the entire body to face the player
|
|
|
|
|
*
|
|
|
|
|
* @param distanceRange Max distance to player that tracking and auto-turning will be active for
|
|
|
|
|
* @param maxYawForPlayerTracking Maximum angle for tracking the player.
|
|
|
|
|
* @param trackingMode The tracking mode selected by the actor. If this is not
|
|
|
|
|
* NPC_TRACKING_PLAYER_AUTO_TURN this function does nothing
|
|
|
|
|
*
|
|
|
|
|
* @return The tracking mode (NpcTrackingMode) to use for the current frame.
|
|
|
|
|
*/
|
|
|
|
|
s16 Npc_UpdateAutoTurn(Actor* actor, NpcInteractInfo* interactInfo, f32 distanceRange, s16 maxYawForPlayerTracking,
|
|
|
|
|
s16 trackingMode) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 pad;
|
2023-01-19 02:38:04 -05:00
|
|
|
|
s16 yaw;
|
|
|
|
|
s16 yawDiff;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
if (trackingMode != NPC_TRACKING_PLAYER_AUTO_TURN) {
|
|
|
|
|
return trackingMode;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
if (interactInfo->talkState != NPC_TALK_STATE_IDLE) {
|
|
|
|
|
// When talking, always fully turn to face the player
|
|
|
|
|
return NPC_TRACKING_FULL_BODY;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
if (distanceRange < Math_Vec3f_DistXYZ(&actor->world.pos, &interactInfo->trackPos)) {
|
|
|
|
|
// Player is too far away, do not track
|
|
|
|
|
interactInfo->autoTurnTimer = 0;
|
|
|
|
|
interactInfo->autoTurnState = 0;
|
|
|
|
|
return NPC_TRACKING_NONE;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
yaw = Math_Vec3f_Yaw(&actor->world.pos, &interactInfo->trackPos);
|
|
|
|
|
yawDiff = ABS((s16)((f32)yaw - actor->shape.rot.y));
|
|
|
|
|
if (maxYawForPlayerTracking >= yawDiff) {
|
|
|
|
|
// Player is in front of the actor, track with the head and the torso
|
|
|
|
|
interactInfo->autoTurnTimer = 0;
|
|
|
|
|
interactInfo->autoTurnState = 0;
|
|
|
|
|
return NPC_TRACKING_HEAD_AND_TORSO;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
// Player is behind the actor, run the auto-turn sequence.
|
|
|
|
|
if (DECR(interactInfo->autoTurnTimer) != 0) {
|
|
|
|
|
// While the timer is still running, return the previous tracking mode
|
|
|
|
|
return interactInfo->trackingMode;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
switch (interactInfo->autoTurnState) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
case 0:
|
|
|
|
|
case 2:
|
2023-01-19 02:38:04 -05:00
|
|
|
|
// Just stand still, not tracking the player
|
|
|
|
|
interactInfo->autoTurnTimer = Rand_S16Offset(30, 30);
|
|
|
|
|
interactInfo->autoTurnState++;
|
|
|
|
|
return NPC_TRACKING_NONE;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
case 1:
|
2023-01-19 02:38:04 -05:00
|
|
|
|
// Glance at the player by only turning the head
|
|
|
|
|
interactInfo->autoTurnTimer = Rand_S16Offset(10, 10);
|
|
|
|
|
interactInfo->autoTurnState++;
|
|
|
|
|
return NPC_TRACKING_HEAD;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
// Auto-turn sequence complete, turn towards the player
|
|
|
|
|
return NPC_TRACKING_FULL_BODY;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 02:38:04 -05:00
|
|
|
|
/**
|
|
|
|
|
* Rotates the actor's whole body, torso and head tracking the point specified in NpcInteractInfo.trackPos.
|
|
|
|
|
* Uses angle limits from a preset selected from from sNpcTrackingPresets.
|
|
|
|
|
*
|
|
|
|
|
* The trackingMode parameter controls whether the head and torso are turned towards the target.
|
|
|
|
|
* If not, they are smoothly turned towards zero. Setting the parameter to NPC_TRACKING_FULL_BODY
|
|
|
|
|
* causes the actor's whole body to be rotated to face the target.
|
|
|
|
|
*
|
|
|
|
|
* If NPC_TRACKING_PLAYER_AUTO_TURN is used, the actor will track the player with its head and torso as long
|
|
|
|
|
* as the player is in front of the actor (within a yaw angle specified in the option preset).
|
|
|
|
|
* If the player is outside of this angle, the actor will turn to face the player after a while.
|
|
|
|
|
*
|
|
|
|
|
* @see Npc_UpdateAutoTurn
|
|
|
|
|
* @see sNpcTrackingPresets
|
|
|
|
|
* @see NpcTrackingMode
|
|
|
|
|
*
|
|
|
|
|
* @param presetIndex The index to a preset in sNpcTrackingPresets
|
|
|
|
|
* @param trackingMode A value from NpcTrackingMode enum
|
|
|
|
|
*/
|
|
|
|
|
void Npc_TrackPoint(Actor* actor, NpcInteractInfo* interactInfo, s16 presetIndex, s16 trackingMode) {
|
|
|
|
|
NpcTrackingRotLimits rotLimits;
|
|
|
|
|
|
|
|
|
|
interactInfo->trackingMode =
|
|
|
|
|
Npc_UpdateAutoTurn(actor, interactInfo, sNpcTrackingPresets[presetIndex].autoTurnDistanceRange,
|
|
|
|
|
sNpcTrackingPresets[presetIndex].maxYawForPlayerTracking, trackingMode);
|
|
|
|
|
|
|
|
|
|
rotLimits = sNpcTrackingPresets[presetIndex].rotLimits;
|
|
|
|
|
|
|
|
|
|
switch (interactInfo->trackingMode) {
|
|
|
|
|
case NPC_TRACKING_NONE:
|
|
|
|
|
rotLimits.maxHeadYaw = 0;
|
|
|
|
|
rotLimits.maxHeadPitch = 0;
|
|
|
|
|
rotLimits.minHeadPitch = 0;
|
|
|
|
|
case NPC_TRACKING_HEAD:
|
|
|
|
|
rotLimits.maxTorsoYaw = 0;
|
|
|
|
|
rotLimits.maxTorsoPitch = 0;
|
|
|
|
|
rotLimits.minTorsoPitch = 0;
|
|
|
|
|
case NPC_TRACKING_HEAD_AND_TORSO:
|
|
|
|
|
rotLimits.rotateYaw = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Npc_TrackPointWithLimits(actor, interactInfo, rotLimits.maxHeadYaw, rotLimits.maxHeadPitch, rotLimits.minHeadPitch,
|
|
|
|
|
rotLimits.maxTorsoYaw, rotLimits.maxTorsoPitch, rotLimits.minTorsoPitch,
|
|
|
|
|
rotLimits.rotateYaw);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gfx* func_80034B28(GraphicsContext* gfxCtx) {
|
|
|
|
|
Gfx* displayList;
|
|
|
|
|
|
|
|
|
|
displayList = Graph_Alloc(gfxCtx, sizeof(Gfx));
|
|
|
|
|
gSPEndDisplayList(displayList);
|
|
|
|
|
|
|
|
|
|
return displayList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gfx* func_80034B54(GraphicsContext* gfxCtx) {
|
|
|
|
|
Gfx* displayListHead;
|
|
|
|
|
Gfx* displayList;
|
|
|
|
|
|
|
|
|
|
displayList = displayListHead = Graph_Alloc(gfxCtx, 2 * sizeof(Gfx));
|
|
|
|
|
|
|
|
|
|
gDPSetRenderMode(displayListHead++, G_RM_FOG_SHADE_A,
|
|
|
|
|
AA_EN | Z_CMP | Z_UPD | IM_RD | CLR_ON_CVG | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
|
|
|
|
|
GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA));
|
|
|
|
|
|
|
|
|
|
gSPEndDisplayList(displayListHead++);
|
|
|
|
|
|
|
|
|
|
return displayList;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80034BA0(PlayState* play, SkelAnime* skelAnime, OverrideLimbDraw overrideLimbDraw,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
PostLimbDraw postLimbDraw, Actor* actor, s16 alpha) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-29 18:29:36 -05:00
|
|
|
|
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
gDPPipeSync(POLY_OPA_DISP++);
|
|
|
|
|
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, alpha);
|
|
|
|
|
gDPPipeSync(POLY_OPA_DISP++);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPSegment(POLY_OPA_DISP++, 0x0C, func_80034B28(play->state.gfxCtx));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
POLY_OPA_DISP = SkelAnime_DrawFlex(play, skelAnime->skeleton, skelAnime->jointTable, skelAnime->dListCount,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
overrideLimbDraw, postLimbDraw, actor, POLY_OPA_DISP);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80034CC4(PlayState* play, SkelAnime* skelAnime, OverrideLimbDraw overrideLimbDraw,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
PostLimbDraw postLimbDraw, Actor* actor, s16 alpha) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-29 18:29:36 -05:00
|
|
|
|
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
gDPPipeSync(POLY_XLU_DISP++);
|
|
|
|
|
gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, alpha);
|
2022-11-06 03:24:34 -05:00
|
|
|
|
gSPSegment(POLY_XLU_DISP++, 0x0C, func_80034B54(play->state.gfxCtx));
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
POLY_XLU_DISP = SkelAnime_DrawFlex(play, skelAnime->skeleton, skelAnime->jointTable, skelAnime->dListCount,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
overrideLimbDraw, postLimbDraw, actor, POLY_XLU_DISP);
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s16 func_80034DD4(Actor* actor, PlayState* play, s16 arg2, f32 arg3) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
f32 var;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if ((play->csCtx.state != CS_STATE_IDLE) || (gDbgCamEnabled)) {
|
|
|
|
|
var = Math_Vec3f_DistXYZ(&actor->world.pos, &play->view.eye) * 0.25f;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
|
|
|
|
var = Math_Vec3f_DistXYZ(&actor->world.pos, &player->actor.world.pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (arg3 < var) {
|
2023-05-30 15:05:04 -04:00
|
|
|
|
actor->flags &= ~ACTOR_FLAG_TARGETABLE;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Math_SmoothStepToS(&arg2, 0, 6, 0x14, 1);
|
|
|
|
|
} else {
|
2023-05-30 15:05:04 -04:00
|
|
|
|
actor->flags |= ACTOR_FLAG_TARGETABLE;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Math_SmoothStepToS(&arg2, 0xFF, 6, 0x14, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return arg2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Animation_ChangeByInfo(SkelAnime* skelAnime, AnimationInfo* animationInfo, s32 index) {
|
|
|
|
|
f32 frameCount;
|
|
|
|
|
|
|
|
|
|
animationInfo += index;
|
|
|
|
|
|
|
|
|
|
if (animationInfo->frameCount > 0.0f) {
|
|
|
|
|
frameCount = animationInfo->frameCount;
|
|
|
|
|
} else {
|
|
|
|
|
frameCount = Animation_GetLastFrame(animationInfo->animation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Animation_Change(skelAnime, animationInfo->animation, animationInfo->playSpeed, animationInfo->startFrame,
|
|
|
|
|
frameCount, animationInfo->mode, animationInfo->morphFrames);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80034F54(PlayState* play, s16* arg1, s16* arg2, s32 arg3) {
|
|
|
|
|
u32 frames = play->gameplayFrames;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < arg3; i++) {
|
|
|
|
|
arg1[i] = (0x814 + 50 * i) * frames;
|
|
|
|
|
arg2[i] = (0x940 + 50 * i) * frames;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void Actor_Noop(Actor* actor, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_80035124(Actor* actor, PlayState* play) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 ret = 0;
|
|
|
|
|
|
|
|
|
|
switch (actor->params) {
|
|
|
|
|
case 0:
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (Actor_HasParent(actor, play)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->params = 1;
|
|
|
|
|
} else if (!(actor->bgCheckFlags & 1)) {
|
|
|
|
|
Actor_MoveForward(actor);
|
|
|
|
|
Math_SmoothStepToF(&actor->speedXZ, 0.0f, 1.0f, 0.1f, 0.0f);
|
|
|
|
|
} else if ((actor->bgCheckFlags & 2) && (actor->velocity.y < -4.0f)) {
|
|
|
|
|
ret = 1;
|
|
|
|
|
} else {
|
|
|
|
|
actor->shape.rot.x = actor->shape.rot.z = 0;
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_8002F580(actor, play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (Actor_HasNoParent(actor, play)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->params = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_UpdateBgCheckInfo(play, actor, actor->colChkInfo.cylHeight, actor->colChkInfo.cylRadius,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->colChkInfo.cylRadius, 0x1D);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
u8 func_800353E8(PlayState* play) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
return player->unk_845;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Finds the first actor instance of a specified ID and category within a given range from
|
|
|
|
|
* an actor if there is one. If the ID provided is -1, this will look for any actor of the
|
|
|
|
|
* specified category rather than a specific ID.
|
|
|
|
|
*/
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor* Actor_FindNearby(PlayState* play, Actor* refActor, s16 actorId, u8 actorCategory, f32 range) {
|
|
|
|
|
Actor* actor = play->actorCtx.actorLists[actorCategory].head;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
while (actor != NULL) {
|
|
|
|
|
if (actor == refActor || ((actorId != -1) && (actorId != actor->id))) {
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
} else {
|
|
|
|
|
if (Actor_WorldDistXYZToActor(refActor, actor) <= range) {
|
|
|
|
|
return actor;
|
|
|
|
|
} else {
|
|
|
|
|
actor = actor->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_800354B4(PlayState* play, Actor* actor, f32 range, s16 arg3, s16 arg4, s16 arg5) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s16 var1;
|
|
|
|
|
s16 var2;
|
|
|
|
|
|
|
|
|
|
var1 = (s16)(actor->yawTowardsPlayer + 0x8000) - player->actor.shape.rot.y;
|
|
|
|
|
var2 = actor->yawTowardsPlayer - arg5;
|
|
|
|
|
|
2023-09-15 14:39:46 -04:00
|
|
|
|
if ((actor->xzDistToPlayer <= range) && (player->meleeWeaponState != 0) && (arg4 >= ABS(var1)) && (arg3 >= ABS(var2))) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_8003555C(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Color_RGBA8 color1;
|
|
|
|
|
Color_RGBA8 color2;
|
|
|
|
|
|
|
|
|
|
color1.r = 200;
|
|
|
|
|
color1.g = 160;
|
|
|
|
|
color1.b = 120;
|
|
|
|
|
|
|
|
|
|
color2.r = 130;
|
|
|
|
|
color2.g = 90;
|
|
|
|
|
color2.b = 50;
|
|
|
|
|
|
|
|
|
|
//! @bug color1 and color2 alpha components not set before being passed on
|
2022-11-06 03:24:34 -05:00
|
|
|
|
EffectSsKiraKira_SpawnSmall(play, pos, velocity, accel, &color1, &color2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Vec3f D_80116268 = { 0.0f, -1.5f, 0.0f };
|
|
|
|
|
Vec3f D_80116274 = { 0.0f, -0.2f, 0.0f };
|
|
|
|
|
|
|
|
|
|
Gfx D_80116280[] = {
|
|
|
|
|
gsDPSetRenderMode(G_RM_FOG_SHADE_A, AA_EN | Z_CMP | Z_UPD | IM_RD | CLR_ON_CVG | CVG_DST_WRAP | ZMODE_XLU |
|
|
|
|
|
FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)),
|
|
|
|
|
gsDPSetAlphaCompare(G_AC_THRESHOLD),
|
|
|
|
|
gsSPEndDisplayList(),
|
|
|
|
|
};
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_800355B8(PlayState* play, Vec3f* pos) {
|
|
|
|
|
func_8003555C(play, pos, &D_80116268, &D_80116274);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
u8 func_800355E4(PlayState* play, Collider* collider) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
2023-09-15 14:39:46 -04:00
|
|
|
|
if ((collider->acFlags & AC_TYPE_PLAYER) && (player->meleeWeaponState != 0) && (player->meleeWeaponAnimation == 0x16)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 Actor_ApplyDamage(Actor* actor) {
|
|
|
|
|
if (actor->colChkInfo.damage >= actor->colChkInfo.health) {
|
|
|
|
|
actor->colChkInfo.health = 0;
|
|
|
|
|
} else {
|
|
|
|
|
actor->colChkInfo.health -= actor->colChkInfo.damage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return actor->colChkInfo.health;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_SetDropFlag(Actor* actor, ColliderInfo* colInfo, s32 freezeFlag) {
|
|
|
|
|
if (colInfo->acHitInfo == NULL) {
|
|
|
|
|
actor->dropFlag = 0x00;
|
|
|
|
|
} else if (freezeFlag && (colInfo->acHitInfo->toucher.dmgFlags & 0x10060000)) {
|
|
|
|
|
actor->freezeTimer = colInfo->acHitInfo->toucher.damage;
|
|
|
|
|
actor->dropFlag = 0x00;
|
|
|
|
|
} else if (colInfo->acHitInfo->toucher.dmgFlags & 0x0800) {
|
|
|
|
|
actor->dropFlag = 0x01;
|
|
|
|
|
} else if (colInfo->acHitInfo->toucher.dmgFlags & 0x1000) {
|
|
|
|
|
actor->dropFlag = 0x02;
|
|
|
|
|
} else if (colInfo->acHitInfo->toucher.dmgFlags & 0x4000) {
|
|
|
|
|
actor->dropFlag = 0x04;
|
|
|
|
|
} else if (colInfo->acHitInfo->toucher.dmgFlags & 0x8000) {
|
|
|
|
|
actor->dropFlag = 0x08;
|
|
|
|
|
} else if (colInfo->acHitInfo->toucher.dmgFlags & 0x10000) {
|
|
|
|
|
actor->dropFlag = 0x10;
|
|
|
|
|
} else if (colInfo->acHitInfo->toucher.dmgFlags & 0x2000) {
|
|
|
|
|
actor->dropFlag = 0x20;
|
|
|
|
|
} else if (colInfo->acHitInfo->toucher.dmgFlags & 0x80000) {
|
|
|
|
|
if (freezeFlag) {
|
|
|
|
|
actor->freezeTimer = colInfo->acHitInfo->toucher.damage;
|
|
|
|
|
}
|
|
|
|
|
actor->dropFlag = 0x40;
|
|
|
|
|
} else {
|
|
|
|
|
actor->dropFlag = 0x00;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Actor_SetDropFlagJntSph(Actor* actor, ColliderJntSph* jntSph, s32 freezeFlag) {
|
|
|
|
|
ColliderInfo* curColInfo;
|
|
|
|
|
s32 flag;
|
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
|
|
actor->dropFlag = 0x00;
|
|
|
|
|
|
|
|
|
|
for (i = jntSph->count - 1; i >= 0; i--) {
|
|
|
|
|
curColInfo = &jntSph->elements[i].info;
|
|
|
|
|
if (curColInfo->acHitInfo == NULL) {
|
|
|
|
|
flag = 0x00;
|
|
|
|
|
} else if (freezeFlag && (curColInfo->acHitInfo->toucher.dmgFlags & 0x10060000)) {
|
|
|
|
|
actor->freezeTimer = curColInfo->acHitInfo->toucher.damage;
|
|
|
|
|
flag = 0x00;
|
|
|
|
|
} else if (curColInfo->acHitInfo->toucher.dmgFlags & 0x0800) {
|
|
|
|
|
flag = 0x01;
|
|
|
|
|
} else if (curColInfo->acHitInfo->toucher.dmgFlags & 0x1000) {
|
|
|
|
|
flag = 0x02;
|
|
|
|
|
} else if (curColInfo->acHitInfo->toucher.dmgFlags & 0x4000) {
|
|
|
|
|
flag = 0x04;
|
|
|
|
|
} else if (curColInfo->acHitInfo->toucher.dmgFlags & 0x8000) {
|
|
|
|
|
flag = 0x08;
|
|
|
|
|
} else if (curColInfo->acHitInfo->toucher.dmgFlags & 0x10000) {
|
|
|
|
|
flag = 0x10;
|
|
|
|
|
} else if (curColInfo->acHitInfo->toucher.dmgFlags & 0x2000) {
|
|
|
|
|
flag = 0x20;
|
|
|
|
|
} else if (curColInfo->acHitInfo->toucher.dmgFlags & 0x80000) {
|
|
|
|
|
if (freezeFlag) {
|
|
|
|
|
actor->freezeTimer = curColInfo->acHitInfo->toucher.damage;
|
|
|
|
|
}
|
|
|
|
|
flag = 0x40;
|
|
|
|
|
} else {
|
|
|
|
|
flag = 0x00;
|
|
|
|
|
}
|
|
|
|
|
actor->dropFlag |= flag;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_80035844(Vec3f* arg0, Vec3f* arg1, Vec3s* arg2, s32 arg3) {
|
|
|
|
|
f32 dx = arg1->x - arg0->x;
|
|
|
|
|
f32 dz = arg1->z - arg0->z;
|
|
|
|
|
f32 dy = arg3 ? (arg1->y - arg0->y) : (arg0->y - arg1->y);
|
|
|
|
|
|
|
|
|
|
arg2->y = Math_Atan2S(dz, dx);
|
|
|
|
|
arg2->x = Math_Atan2S(sqrtf(SQ(dx) + SQ(dz)), dy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Spawns En_Part (Dissipating Flames) actor as a child of the given actor.
|
|
|
|
|
*/
|
|
|
|
|
Actor* func_800358DC(Actor* actor, Vec3f* spawnPos, Vec3s* spawnRot, f32* arg3, s32 timer, s16* unused,
|
2022-11-06 03:24:34 -05:00
|
|
|
|
PlayState* play, s16 params, s32 arg8) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
EnPart* spawnedEnPart;
|
|
|
|
|
|
|
|
|
|
spawnedEnPart =
|
2022-11-06 03:24:34 -05:00
|
|
|
|
(EnPart*)Actor_SpawnAsChild(&play->actorCtx, actor, play, ACTOR_EN_PART, spawnPos->x, spawnPos->y,
|
2022-03-21 21:51:23 -04:00
|
|
|
|
spawnPos->z, spawnRot->x, spawnRot->y, actor->objBankIndex, params);
|
|
|
|
|
if (spawnedEnPart != NULL) {
|
|
|
|
|
spawnedEnPart->actor.scale = actor->scale;
|
|
|
|
|
spawnedEnPart->actor.speedXZ = arg3[0];
|
|
|
|
|
spawnedEnPart->displayList = arg8;
|
|
|
|
|
spawnedEnPart->action = 2;
|
|
|
|
|
spawnedEnPart->timer = timer;
|
|
|
|
|
spawnedEnPart->rotZ = arg3[1];
|
|
|
|
|
spawnedEnPart->rotZSpeed = arg3[2];
|
|
|
|
|
return &spawnedEnPart->actor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_800359B8(Actor* actor, s16 arg1, Vec3s* arg2) {
|
|
|
|
|
f32 sp44;
|
|
|
|
|
f32 sp40;
|
|
|
|
|
f32 sp3C;
|
|
|
|
|
f32 sp38;
|
|
|
|
|
f32 sp34;
|
|
|
|
|
f32 sp30;
|
|
|
|
|
f32 sp2C;
|
|
|
|
|
f32 sp28;
|
|
|
|
|
f32 sp24;
|
|
|
|
|
CollisionPoly* floorPoly;
|
|
|
|
|
s32 pad;
|
|
|
|
|
|
|
|
|
|
if (actor->floorPoly != NULL) {
|
|
|
|
|
floorPoly = actor->floorPoly;
|
|
|
|
|
sp44 = COLPOLY_GET_NORMAL(floorPoly->normal.x);
|
|
|
|
|
sp40 = COLPOLY_GET_NORMAL(floorPoly->normal.y);
|
|
|
|
|
sp3C = COLPOLY_GET_NORMAL(floorPoly->normal.z);
|
|
|
|
|
|
|
|
|
|
sp38 = Math_SinS(arg1);
|
|
|
|
|
sp34 = Math_CosS(arg1);
|
|
|
|
|
sp28 = (-(sp44 * sp38) - (sp3C * sp34));
|
|
|
|
|
arg2->x = -(s16)(Math_FAtan2F(sp28 * sp40, 1.0f) * (32768 / M_PI));
|
|
|
|
|
|
|
|
|
|
sp2C = Math_SinS(arg1 - 16375);
|
|
|
|
|
sp30 = Math_CosS(arg1 - 16375);
|
|
|
|
|
sp24 = (-(sp44 * sp2C) - (sp3C * sp30));
|
|
|
|
|
arg2->z = -(s16)(Math_FAtan2F(sp24 * sp40, 1.0f) * (32768 / M_PI));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
void func_80035B18(PlayState* play, Actor* actor, u16 textId) {
|
|
|
|
|
Message_ContinueTextbox(play, textId);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
actor->textId = textId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-06-20 11:54:02 -04:00
|
|
|
|
* Tests if "eventChkInf" flag is set.
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*/
|
|
|
|
|
s32 Flags_GetEventChkInf(s32 flag) {
|
|
|
|
|
return gSaveContext.eventChkInf[flag >> 4] & (1 << (flag & 0xF));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-06-20 11:54:02 -04:00
|
|
|
|
* Sets "eventChkInf" flag.
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*/
|
|
|
|
|
void Flags_SetEventChkInf(s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOff = !Flags_GetEventChkInf(flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gSaveContext.eventChkInf[flag >> 4] |= (1 << (flag & 0xF));
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOff) {
|
|
|
|
|
LUSLOG_INFO("EventChkInf Flag Set - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, flag);
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-06-20 11:54:02 -04:00
|
|
|
|
* Unsets "eventChkInf" flag.
|
|
|
|
|
*/
|
|
|
|
|
void Flags_UnsetEventChkInf(s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOn = Flags_GetEventChkInf(flag);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
gSaveContext.eventChkInf[flag >> 4] &= ~(1 << (flag & 0xF));
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOn) {
|
|
|
|
|
LUSLOG_INFO("EventChkInf Flag Unset - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnFlagUnset(FLAG_EVENT_CHECK_INF, flag);
|
|
|
|
|
}
|
2023-06-20 11:54:02 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests if "itemGetInf" flag is set.
|
|
|
|
|
*/
|
|
|
|
|
s32 Flags_GetItemGetInf(s32 flag) {
|
|
|
|
|
return gSaveContext.itemGetInf[flag >> 4] & (1 << (flag & 0xF));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets "itemGetInf" flag.
|
|
|
|
|
*/
|
|
|
|
|
void Flags_SetItemGetInf(s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOff = !Flags_GetItemGetInf(flag);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
gSaveContext.itemGetInf[flag >> 4] |= (1 << (flag & 0xF));
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOff) {
|
|
|
|
|
LUSLOG_INFO("ItemGetInf Flag Set - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnFlagSet(FLAG_ITEM_GET_INF, flag);
|
|
|
|
|
}
|
2023-06-20 11:54:02 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Unsets "itemGetInf" flag.
|
|
|
|
|
*/
|
|
|
|
|
void Flags_UnsetItemGetInf(s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOn = Flags_GetItemGetInf(flag);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
gSaveContext.itemGetInf[flag >> 4] &= ~(1 << (flag & 0xF));
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOn) {
|
|
|
|
|
LUSLOG_INFO("ItemGetInf Flag Unset - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnFlagUnset(FLAG_ITEM_GET_INF, flag);
|
|
|
|
|
}
|
2023-06-20 11:54:02 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests if "infTable" flag is set.
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*/
|
|
|
|
|
s32 Flags_GetInfTable(s32 flag) {
|
|
|
|
|
return gSaveContext.infTable[flag >> 4] & (1 << (flag & 0xF));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-06-20 11:54:02 -04:00
|
|
|
|
* Sets "infTable" flag.
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*/
|
|
|
|
|
void Flags_SetInfTable(s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOff = !Flags_GetInfTable(flag);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
gSaveContext.infTable[flag >> 4] |= (1 << (flag & 0xF));
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOff) {
|
|
|
|
|
LUSLOG_INFO("InfTable Flag Set - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnFlagSet(FLAG_INF_TABLE, flag);
|
|
|
|
|
}
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 11:54:02 -04:00
|
|
|
|
/**
|
|
|
|
|
* Unsets "infTable" flag.
|
|
|
|
|
*/
|
|
|
|
|
void Flags_UnsetInfTable(s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOn = Flags_GetInfTable(flag);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
gSaveContext.infTable[flag >> 4] &= ~(1 << (flag & 0xF));
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOn) {
|
|
|
|
|
LUSLOG_INFO("InfTable Flag Unset - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnFlagUnset(FLAG_INF_TABLE, flag);
|
|
|
|
|
}
|
2023-06-20 11:54:02 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests if "eventInf" flag is set.
|
|
|
|
|
*/
|
|
|
|
|
s32 Flags_GetEventInf(s32 flag) {
|
|
|
|
|
return gSaveContext.eventInf[flag >> 4] & (1 << (flag & 0xF));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets "eventInf" flag.
|
|
|
|
|
*/
|
|
|
|
|
void Flags_SetEventInf(s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOff = !Flags_GetEventInf(flag);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
gSaveContext.eventInf[flag >> 4] |= (1 << (flag & 0xF));
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOff) {
|
|
|
|
|
LUSLOG_INFO("EventInf Flag Set - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_INF, flag);
|
|
|
|
|
}
|
2023-06-20 11:54:02 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Unsets "eventInf" flag.
|
|
|
|
|
*/
|
|
|
|
|
void Flags_UnsetEventInf(s32 flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOn = Flags_GetEventInf(flag);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
gSaveContext.eventInf[flag >> 4] &= ~(1 << (flag & 0xF));
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOn) {
|
|
|
|
|
LUSLOG_INFO("EventInf Flag Unset - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnFlagUnset(FLAG_EVENT_INF, flag);
|
|
|
|
|
}
|
2023-06-20 11:54:02 -04:00
|
|
|
|
}
|
|
|
|
|
|
Randomizer v2 (#1065)
* Revert changes to GetItemFromGet
* Fixes Ganon's Boss Key shuffled while regular boss Keys aren't.
* Enum + combo box
* Add obtainability checks correctly
* combobox title rename + no number tracking
* Fix repeatable purchases and bottles rendering incorrectly
* Move shopsanity option in GUI
* Struct instead of ImVec + basic comportment for all case
* Attempt to fix odd build issue
* Cast randoGet for ganons boss key
* Remove redundancy in KD room
* Update logic Cvar names
* Fix Ganons Trials coming from old save files. Fixes #1365
* Fixes crash when entering Ganon's Castle lobby on linux.
* Makes `Item_Give` safe to use with a NULL globalCtx.
This should allow it's use for giving items to Link's Pocket
during rando save initialization.
* Converts Song from Impa to use `Item_Give`
* Adds more options for Link's starting item.
* Removes unneeded `GiveLinkItem` functions.
* and make it build
* bring back new rando dropdown
* gSaveContext access in GameMenuBar.cpp
* Implement Skip Scarecrow's Song
* Reimplement progressive Bombchus
* Rando-next: Deku Nut and Seed ammo gives a blue rupee
Fixes #1390
* Fixes Link starting with BGS
* Persist item tracker notes
* Adjust Hooks include
* Use SohImGui::RequestCvarSaveOnNextTick
* Fix issues from LUS refactor
* Fix for overriding deku scrub messages
* Fix mistake from merge
oops
* Restore checkboxes to enhancements menu
These got lost in the merge
* Update location access logic
Including MQ locations in Spirit and GC now
* Implement rando bombchu drops
* Missing break
* Simplify mudwall collision check
There was no need to have a second collider specifically for Ice Arrow hits
* Update settings.cpp
* Simplify mudwall collision check
* Restore checkboxes in menu
Accidentally lost these during merge
* Clean up bool
* Update logic Cvar name
* Fixed capacity on ammmo tracking
* Fix for beans obtainability
* Hook into file delete and clear notes
* Incorporate magic arrows in rando settings
* Update tooltip
To inform the player that they might have to reload the room if they're enabling this for the first time.
* Update tooltip
* Add line break in tooltip
* Tooltip wording + line break
* tweak on main logic
* All color logic for all types
* Fix: changes to please new LUS
* Ensure itemTrackerNotes vector is not fully empty
* Implement's Tycoon Wallet.
* Refactor DrawItemCount and Use EnhancementCombobox for tracker capacity options
* small tweaks and rename
* always display XX/YY when in ammo/capacity mode
* Move all merchant messages to be generated on file load
* added hovertext for the number display
* Swap german and french translations for shop messages
* Set key colors to be on by default
* Add another flag to skip mask shop
* Fix Sold Out bug
* Fix gerudo keys, add disabled checkbox
* tooltip line break
* Add trials required and merchant prices to save file instead of loading from active spoiler log
* Remove trialsRequired persisting in save manager
* Adds slotIndex to girla (shop item actor) and uses that for IdentifyShopItem.
* Fix issue when merchantPrices is empty
* Fix for a single zeroed merchantPrice entry
* Fix #1417
* Implements items selling out and fixes issues with purchasing some items.
* Fixes order of operations so Rupees will be spent.
* Fixes sold out items not getting overwritten by the randomized info.
* Clarify var names and comments
Also preserve chain platform cutscene in spirit based on Link's position
* Remove !=0 from cvar check
* Clarify var names and comments
* Rename randomizerMerchantPrices to merchantPrices
* Handle shop items in SaveManager
* Fix merge mistake
* Base whats in the bazaar shop on entranceIndex instead of age
* Tidy up chain platform cutscene check
* Fix merge error
Didn't mean to have Zhora changes in here yet
* Use 3drando item table for parsing spoiler names
* Use another nested method instead of one at the top level to fetch the table
* Add missing newline
* Remove log
* Respect custom draw functions
* Fix issues with rendering songs
* Fix localized item names for shopsanity
* Implements a larger array of Sprites for the Icon Hash.
* Uses the hash instead of seed for spoilerfile name and icons.
* Removes some unused functions and variables in `spoiler_log.cpp`
* Prevents leading 0s added to hash from being in file name
* Changes filename format to icon indexes separated by dashes
* Hopefully makes Jenkins happy
* Hopefully makes Jenkins happy
* [Rando] Child Gerudo Fortress 37th Heartpiece randomized
Fixes #1071
* Add descriptions to save editor flags editor, and added randomizer flags (#1386)
* Add descriptions to save editor flags editor, and added randomizer flags
* Hide randomizer flags when not on a randomizer save
* Move flag descriptions to header file
* Update soh/soh/Enhancements/debugger/debugSaveEditor.h
* Update soh/soh/Enhancements/debugger/debugSaveEditor.h
* Fix merge error
* crash on pause menu on linux (only in appimage)
Fixes #1437
* Applies fix to Song from Impa as well.
* Allow buying tunics as child when shopsanity is on
* Fix for custom draw methods overriding sold out sign
* Simplify logic around shopsanity and fix some issues
* Fix dungeon reward stone rotation and add particles
* Fix some issues with ice traps
* Fix adult wallet having its own max capacity
* Fix amount of keys given for BotW
* format
* Use EnGirlAShopItem enum instead of raw hex values
* [#1434] Renders non-warp songs more consistently with warp songs
* A few changes around merchant messages
* Various changes from PR feedback
* Rando: Junk Hint missing french translation
* Typo
* Fix free scrub being at 0 instead of TEXT_SCRUB_RANDOM
* Replace magic numbers in message handler
* Update soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
* Update soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
* Fix BGS softlock for shopsanity
* Support tycoon wallet on tracker
* Revert "Fix BGS softlock for shopsanity"
This reverts commit 5fdb961ea460fb9a035cf0bb6ae77bfeedc1de0f.
* [#1053] Resolves an issue with shop items and bombchu bowling where BGS would display two message boxes
* Implements some necessary plumbing and resolves several Ice Trap Softlocks.
Adds a way for an item entry to tell what type of check it came from (NPC vs Chest vs Freestanding, etc.)
Sets this value from chests and item00 actors.
Relocates pendingIceTraps to save context so it can persist through cutscenes and get stored on save init for Link's Pocket and Song from Impa.
Restructures pendingIceTraps into a counter rather than a true or false, so that we can be frozen multiple times in a row if applicable (atm that should only be at the start of a run if Link's Pocket and Song from Impa were both Ice Traps).
Adds a textbox for Ice Traps and a special case of holding up nothing in the get item process. This fixes all the cases where Ice Traps would softlock due to the actor giving the item expecting a closing textbox. After holding the item above his head Link increments the pendingIceTraps counter by one and sets whatever flag he has pending.
None of the above plumbing applies to Ice Traps from chests, those work exactly the same as before, as do freestanding item00 ice traps (thanks to the additional check for ITEM_FROM_FREESTANDING.
OoT and Ruto's Letter count as NPC's, so they get the FOWL text box and set a pending ice trap rather than immediately freezing, since Link weill be in the water. Link will get frozen the next time he touches land, which in the case of OoT is after the fade to white and right before the Song of Time check.
Fixes all the other softlocks I'm aware of, including Fishing, Bombchu Bowling, Skull Kid, and losing the second Gerudo Archery check.
* fix bgs check in player
* move bgs logic for tokensanity into MOD_NONE check
* set bgs flag before `Item_Give`ing
* move bgs flag into `MOD_NONE` check in girla
* use existing check in `z_player`
* Adds comment explaining the decision to default ITEM_FROM_NPC.
* Rename pendingIceTraps to pendingIceTrapCount
* Adds some RANDOTODO comments about cleaning up a couple things.
* Merge branch 'develop-zhora' into ztornn
* manually restore changes to `z_player.c`
* Fix after some ice trap prepwork from earlier
* Actual fix
* Woops
* More rupee names
* Actually fix it
* Add back comment
* Fix Skip Scarecrow Song
* Fix ruto's letter and LH sun stick rendering
* Also fixes it for treasure chest game
* Tweak: Rando French Wallet
* ADD: French Tycoon
* Hide dungeon items/notes by default
* [#1301] Fix issue with UI not restoring after getting an item from biggoron
* Update soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c
* Update soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c
* Fix random crash that only affected one person for some reason
Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
Co-authored-by: Christopher Leggett <chris@leggett.dev>
Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com>
Co-authored-by: Sarge-117 <adam_branston@outlook.com>
Co-authored-by: briaguya <briaguya@alice>
Co-authored-by: aMannus <mannusmenting@gmail.com>
Co-authored-by: lil David <1337lilDavid@gmail.com>
Co-authored-by: Sarge-117 <108380086+Sarge-117@users.noreply.github.com>
Co-authored-by: louist103 <35883445+louist103@users.noreply.github.com>
2022-09-21 00:50:22 -04:00
|
|
|
|
/**
|
|
|
|
|
* Tests if "randomizerInf" flag is set.
|
|
|
|
|
*/
|
|
|
|
|
s32 Flags_GetRandomizerInf(RandomizerInf flag) {
|
|
|
|
|
return gSaveContext.randomizerInf[flag >> 4] & (1 << (flag & 0xF));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets "randomizerInf" flag.
|
|
|
|
|
*/
|
|
|
|
|
void Flags_SetRandomizerInf(RandomizerInf flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOff = !Flags_GetRandomizerInf(flag);
|
Randomizer v2 (#1065)
* Revert changes to GetItemFromGet
* Fixes Ganon's Boss Key shuffled while regular boss Keys aren't.
* Enum + combo box
* Add obtainability checks correctly
* combobox title rename + no number tracking
* Fix repeatable purchases and bottles rendering incorrectly
* Move shopsanity option in GUI
* Struct instead of ImVec + basic comportment for all case
* Attempt to fix odd build issue
* Cast randoGet for ganons boss key
* Remove redundancy in KD room
* Update logic Cvar names
* Fix Ganons Trials coming from old save files. Fixes #1365
* Fixes crash when entering Ganon's Castle lobby on linux.
* Makes `Item_Give` safe to use with a NULL globalCtx.
This should allow it's use for giving items to Link's Pocket
during rando save initialization.
* Converts Song from Impa to use `Item_Give`
* Adds more options for Link's starting item.
* Removes unneeded `GiveLinkItem` functions.
* and make it build
* bring back new rando dropdown
* gSaveContext access in GameMenuBar.cpp
* Implement Skip Scarecrow's Song
* Reimplement progressive Bombchus
* Rando-next: Deku Nut and Seed ammo gives a blue rupee
Fixes #1390
* Fixes Link starting with BGS
* Persist item tracker notes
* Adjust Hooks include
* Use SohImGui::RequestCvarSaveOnNextTick
* Fix issues from LUS refactor
* Fix for overriding deku scrub messages
* Fix mistake from merge
oops
* Restore checkboxes to enhancements menu
These got lost in the merge
* Update location access logic
Including MQ locations in Spirit and GC now
* Implement rando bombchu drops
* Missing break
* Simplify mudwall collision check
There was no need to have a second collider specifically for Ice Arrow hits
* Update settings.cpp
* Simplify mudwall collision check
* Restore checkboxes in menu
Accidentally lost these during merge
* Clean up bool
* Update logic Cvar name
* Fixed capacity on ammmo tracking
* Fix for beans obtainability
* Hook into file delete and clear notes
* Incorporate magic arrows in rando settings
* Update tooltip
To inform the player that they might have to reload the room if they're enabling this for the first time.
* Update tooltip
* Add line break in tooltip
* Tooltip wording + line break
* tweak on main logic
* All color logic for all types
* Fix: changes to please new LUS
* Ensure itemTrackerNotes vector is not fully empty
* Implement's Tycoon Wallet.
* Refactor DrawItemCount and Use EnhancementCombobox for tracker capacity options
* small tweaks and rename
* always display XX/YY when in ammo/capacity mode
* Move all merchant messages to be generated on file load
* added hovertext for the number display
* Swap german and french translations for shop messages
* Set key colors to be on by default
* Add another flag to skip mask shop
* Fix Sold Out bug
* Fix gerudo keys, add disabled checkbox
* tooltip line break
* Add trials required and merchant prices to save file instead of loading from active spoiler log
* Remove trialsRequired persisting in save manager
* Adds slotIndex to girla (shop item actor) and uses that for IdentifyShopItem.
* Fix issue when merchantPrices is empty
* Fix for a single zeroed merchantPrice entry
* Fix #1417
* Implements items selling out and fixes issues with purchasing some items.
* Fixes order of operations so Rupees will be spent.
* Fixes sold out items not getting overwritten by the randomized info.
* Clarify var names and comments
Also preserve chain platform cutscene in spirit based on Link's position
* Remove !=0 from cvar check
* Clarify var names and comments
* Rename randomizerMerchantPrices to merchantPrices
* Handle shop items in SaveManager
* Fix merge mistake
* Base whats in the bazaar shop on entranceIndex instead of age
* Tidy up chain platform cutscene check
* Fix merge error
Didn't mean to have Zhora changes in here yet
* Use 3drando item table for parsing spoiler names
* Use another nested method instead of one at the top level to fetch the table
* Add missing newline
* Remove log
* Respect custom draw functions
* Fix issues with rendering songs
* Fix localized item names for shopsanity
* Implements a larger array of Sprites for the Icon Hash.
* Uses the hash instead of seed for spoilerfile name and icons.
* Removes some unused functions and variables in `spoiler_log.cpp`
* Prevents leading 0s added to hash from being in file name
* Changes filename format to icon indexes separated by dashes
* Hopefully makes Jenkins happy
* Hopefully makes Jenkins happy
* [Rando] Child Gerudo Fortress 37th Heartpiece randomized
Fixes #1071
* Add descriptions to save editor flags editor, and added randomizer flags (#1386)
* Add descriptions to save editor flags editor, and added randomizer flags
* Hide randomizer flags when not on a randomizer save
* Move flag descriptions to header file
* Update soh/soh/Enhancements/debugger/debugSaveEditor.h
* Update soh/soh/Enhancements/debugger/debugSaveEditor.h
* Fix merge error
* crash on pause menu on linux (only in appimage)
Fixes #1437
* Applies fix to Song from Impa as well.
* Allow buying tunics as child when shopsanity is on
* Fix for custom draw methods overriding sold out sign
* Simplify logic around shopsanity and fix some issues
* Fix dungeon reward stone rotation and add particles
* Fix some issues with ice traps
* Fix adult wallet having its own max capacity
* Fix amount of keys given for BotW
* format
* Use EnGirlAShopItem enum instead of raw hex values
* [#1434] Renders non-warp songs more consistently with warp songs
* A few changes around merchant messages
* Various changes from PR feedback
* Rando: Junk Hint missing french translation
* Typo
* Fix free scrub being at 0 instead of TEXT_SCRUB_RANDOM
* Replace magic numbers in message handler
* Update soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
* Update soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
* Fix BGS softlock for shopsanity
* Support tycoon wallet on tracker
* Revert "Fix BGS softlock for shopsanity"
This reverts commit 5fdb961ea460fb9a035cf0bb6ae77bfeedc1de0f.
* [#1053] Resolves an issue with shop items and bombchu bowling where BGS would display two message boxes
* Implements some necessary plumbing and resolves several Ice Trap Softlocks.
Adds a way for an item entry to tell what type of check it came from (NPC vs Chest vs Freestanding, etc.)
Sets this value from chests and item00 actors.
Relocates pendingIceTraps to save context so it can persist through cutscenes and get stored on save init for Link's Pocket and Song from Impa.
Restructures pendingIceTraps into a counter rather than a true or false, so that we can be frozen multiple times in a row if applicable (atm that should only be at the start of a run if Link's Pocket and Song from Impa were both Ice Traps).
Adds a textbox for Ice Traps and a special case of holding up nothing in the get item process. This fixes all the cases where Ice Traps would softlock due to the actor giving the item expecting a closing textbox. After holding the item above his head Link increments the pendingIceTraps counter by one and sets whatever flag he has pending.
None of the above plumbing applies to Ice Traps from chests, those work exactly the same as before, as do freestanding item00 ice traps (thanks to the additional check for ITEM_FROM_FREESTANDING.
OoT and Ruto's Letter count as NPC's, so they get the FOWL text box and set a pending ice trap rather than immediately freezing, since Link weill be in the water. Link will get frozen the next time he touches land, which in the case of OoT is after the fade to white and right before the Song of Time check.
Fixes all the other softlocks I'm aware of, including Fishing, Bombchu Bowling, Skull Kid, and losing the second Gerudo Archery check.
* fix bgs check in player
* move bgs logic for tokensanity into MOD_NONE check
* set bgs flag before `Item_Give`ing
* move bgs flag into `MOD_NONE` check in girla
* use existing check in `z_player`
* Adds comment explaining the decision to default ITEM_FROM_NPC.
* Rename pendingIceTraps to pendingIceTrapCount
* Adds some RANDOTODO comments about cleaning up a couple things.
* Merge branch 'develop-zhora' into ztornn
* manually restore changes to `z_player.c`
* Fix after some ice trap prepwork from earlier
* Actual fix
* Woops
* More rupee names
* Actually fix it
* Add back comment
* Fix Skip Scarecrow Song
* Fix ruto's letter and LH sun stick rendering
* Also fixes it for treasure chest game
* Tweak: Rando French Wallet
* ADD: French Tycoon
* Hide dungeon items/notes by default
* [#1301] Fix issue with UI not restoring after getting an item from biggoron
* Update soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c
* Update soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c
* Fix random crash that only affected one person for some reason
Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
Co-authored-by: Christopher Leggett <chris@leggett.dev>
Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com>
Co-authored-by: Sarge-117 <adam_branston@outlook.com>
Co-authored-by: briaguya <briaguya@alice>
Co-authored-by: aMannus <mannusmenting@gmail.com>
Co-authored-by: lil David <1337lilDavid@gmail.com>
Co-authored-by: Sarge-117 <108380086+Sarge-117@users.noreply.github.com>
Co-authored-by: louist103 <35883445+louist103@users.noreply.github.com>
2022-09-21 00:50:22 -04:00
|
|
|
|
gSaveContext.randomizerInf[flag >> 4] |= (1 << (flag & 0xF));
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOff) {
|
|
|
|
|
LUSLOG_INFO("RandomizerInf Flag Set - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnFlagSet(FLAG_RANDOMIZER_INF, flag);
|
|
|
|
|
}
|
Randomizer v2 (#1065)
* Revert changes to GetItemFromGet
* Fixes Ganon's Boss Key shuffled while regular boss Keys aren't.
* Enum + combo box
* Add obtainability checks correctly
* combobox title rename + no number tracking
* Fix repeatable purchases and bottles rendering incorrectly
* Move shopsanity option in GUI
* Struct instead of ImVec + basic comportment for all case
* Attempt to fix odd build issue
* Cast randoGet for ganons boss key
* Remove redundancy in KD room
* Update logic Cvar names
* Fix Ganons Trials coming from old save files. Fixes #1365
* Fixes crash when entering Ganon's Castle lobby on linux.
* Makes `Item_Give` safe to use with a NULL globalCtx.
This should allow it's use for giving items to Link's Pocket
during rando save initialization.
* Converts Song from Impa to use `Item_Give`
* Adds more options for Link's starting item.
* Removes unneeded `GiveLinkItem` functions.
* and make it build
* bring back new rando dropdown
* gSaveContext access in GameMenuBar.cpp
* Implement Skip Scarecrow's Song
* Reimplement progressive Bombchus
* Rando-next: Deku Nut and Seed ammo gives a blue rupee
Fixes #1390
* Fixes Link starting with BGS
* Persist item tracker notes
* Adjust Hooks include
* Use SohImGui::RequestCvarSaveOnNextTick
* Fix issues from LUS refactor
* Fix for overriding deku scrub messages
* Fix mistake from merge
oops
* Restore checkboxes to enhancements menu
These got lost in the merge
* Update location access logic
Including MQ locations in Spirit and GC now
* Implement rando bombchu drops
* Missing break
* Simplify mudwall collision check
There was no need to have a second collider specifically for Ice Arrow hits
* Update settings.cpp
* Simplify mudwall collision check
* Restore checkboxes in menu
Accidentally lost these during merge
* Clean up bool
* Update logic Cvar name
* Fixed capacity on ammmo tracking
* Fix for beans obtainability
* Hook into file delete and clear notes
* Incorporate magic arrows in rando settings
* Update tooltip
To inform the player that they might have to reload the room if they're enabling this for the first time.
* Update tooltip
* Add line break in tooltip
* Tooltip wording + line break
* tweak on main logic
* All color logic for all types
* Fix: changes to please new LUS
* Ensure itemTrackerNotes vector is not fully empty
* Implement's Tycoon Wallet.
* Refactor DrawItemCount and Use EnhancementCombobox for tracker capacity options
* small tweaks and rename
* always display XX/YY when in ammo/capacity mode
* Move all merchant messages to be generated on file load
* added hovertext for the number display
* Swap german and french translations for shop messages
* Set key colors to be on by default
* Add another flag to skip mask shop
* Fix Sold Out bug
* Fix gerudo keys, add disabled checkbox
* tooltip line break
* Add trials required and merchant prices to save file instead of loading from active spoiler log
* Remove trialsRequired persisting in save manager
* Adds slotIndex to girla (shop item actor) and uses that for IdentifyShopItem.
* Fix issue when merchantPrices is empty
* Fix for a single zeroed merchantPrice entry
* Fix #1417
* Implements items selling out and fixes issues with purchasing some items.
* Fixes order of operations so Rupees will be spent.
* Fixes sold out items not getting overwritten by the randomized info.
* Clarify var names and comments
Also preserve chain platform cutscene in spirit based on Link's position
* Remove !=0 from cvar check
* Clarify var names and comments
* Rename randomizerMerchantPrices to merchantPrices
* Handle shop items in SaveManager
* Fix merge mistake
* Base whats in the bazaar shop on entranceIndex instead of age
* Tidy up chain platform cutscene check
* Fix merge error
Didn't mean to have Zhora changes in here yet
* Use 3drando item table for parsing spoiler names
* Use another nested method instead of one at the top level to fetch the table
* Add missing newline
* Remove log
* Respect custom draw functions
* Fix issues with rendering songs
* Fix localized item names for shopsanity
* Implements a larger array of Sprites for the Icon Hash.
* Uses the hash instead of seed for spoilerfile name and icons.
* Removes some unused functions and variables in `spoiler_log.cpp`
* Prevents leading 0s added to hash from being in file name
* Changes filename format to icon indexes separated by dashes
* Hopefully makes Jenkins happy
* Hopefully makes Jenkins happy
* [Rando] Child Gerudo Fortress 37th Heartpiece randomized
Fixes #1071
* Add descriptions to save editor flags editor, and added randomizer flags (#1386)
* Add descriptions to save editor flags editor, and added randomizer flags
* Hide randomizer flags when not on a randomizer save
* Move flag descriptions to header file
* Update soh/soh/Enhancements/debugger/debugSaveEditor.h
* Update soh/soh/Enhancements/debugger/debugSaveEditor.h
* Fix merge error
* crash on pause menu on linux (only in appimage)
Fixes #1437
* Applies fix to Song from Impa as well.
* Allow buying tunics as child when shopsanity is on
* Fix for custom draw methods overriding sold out sign
* Simplify logic around shopsanity and fix some issues
* Fix dungeon reward stone rotation and add particles
* Fix some issues with ice traps
* Fix adult wallet having its own max capacity
* Fix amount of keys given for BotW
* format
* Use EnGirlAShopItem enum instead of raw hex values
* [#1434] Renders non-warp songs more consistently with warp songs
* A few changes around merchant messages
* Various changes from PR feedback
* Rando: Junk Hint missing french translation
* Typo
* Fix free scrub being at 0 instead of TEXT_SCRUB_RANDOM
* Replace magic numbers in message handler
* Update soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
* Update soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
* Fix BGS softlock for shopsanity
* Support tycoon wallet on tracker
* Revert "Fix BGS softlock for shopsanity"
This reverts commit 5fdb961ea460fb9a035cf0bb6ae77bfeedc1de0f.
* [#1053] Resolves an issue with shop items and bombchu bowling where BGS would display two message boxes
* Implements some necessary plumbing and resolves several Ice Trap Softlocks.
Adds a way for an item entry to tell what type of check it came from (NPC vs Chest vs Freestanding, etc.)
Sets this value from chests and item00 actors.
Relocates pendingIceTraps to save context so it can persist through cutscenes and get stored on save init for Link's Pocket and Song from Impa.
Restructures pendingIceTraps into a counter rather than a true or false, so that we can be frozen multiple times in a row if applicable (atm that should only be at the start of a run if Link's Pocket and Song from Impa were both Ice Traps).
Adds a textbox for Ice Traps and a special case of holding up nothing in the get item process. This fixes all the cases where Ice Traps would softlock due to the actor giving the item expecting a closing textbox. After holding the item above his head Link increments the pendingIceTraps counter by one and sets whatever flag he has pending.
None of the above plumbing applies to Ice Traps from chests, those work exactly the same as before, as do freestanding item00 ice traps (thanks to the additional check for ITEM_FROM_FREESTANDING.
OoT and Ruto's Letter count as NPC's, so they get the FOWL text box and set a pending ice trap rather than immediately freezing, since Link weill be in the water. Link will get frozen the next time he touches land, which in the case of OoT is after the fade to white and right before the Song of Time check.
Fixes all the other softlocks I'm aware of, including Fishing, Bombchu Bowling, Skull Kid, and losing the second Gerudo Archery check.
* fix bgs check in player
* move bgs logic for tokensanity into MOD_NONE check
* set bgs flag before `Item_Give`ing
* move bgs flag into `MOD_NONE` check in girla
* use existing check in `z_player`
* Adds comment explaining the decision to default ITEM_FROM_NPC.
* Rename pendingIceTraps to pendingIceTrapCount
* Adds some RANDOTODO comments about cleaning up a couple things.
* Merge branch 'develop-zhora' into ztornn
* manually restore changes to `z_player.c`
* Fix after some ice trap prepwork from earlier
* Actual fix
* Woops
* More rupee names
* Actually fix it
* Add back comment
* Fix Skip Scarecrow Song
* Fix ruto's letter and LH sun stick rendering
* Also fixes it for treasure chest game
* Tweak: Rando French Wallet
* ADD: French Tycoon
* Hide dungeon items/notes by default
* [#1301] Fix issue with UI not restoring after getting an item from biggoron
* Update soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c
* Update soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c
* Fix random crash that only affected one person for some reason
Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
Co-authored-by: Christopher Leggett <chris@leggett.dev>
Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com>
Co-authored-by: Sarge-117 <adam_branston@outlook.com>
Co-authored-by: briaguya <briaguya@alice>
Co-authored-by: aMannus <mannusmenting@gmail.com>
Co-authored-by: lil David <1337lilDavid@gmail.com>
Co-authored-by: Sarge-117 <108380086+Sarge-117@users.noreply.github.com>
Co-authored-by: louist103 <35883445+louist103@users.noreply.github.com>
2022-09-21 00:50:22 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 11:54:02 -04:00
|
|
|
|
/**
|
|
|
|
|
* Unsets "randomizerInf" flag.
|
|
|
|
|
*/
|
|
|
|
|
void Flags_UnsetRandomizerInf(RandomizerInf flag) {
|
2023-12-28 09:23:03 -05:00
|
|
|
|
u8 previouslyOn = Flags_GetRandomizerInf(flag);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
gSaveContext.randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF));
|
2023-12-28 09:23:03 -05:00
|
|
|
|
if (previouslyOn) {
|
|
|
|
|
LUSLOG_INFO("RandomizerInf Flag Unset - %#x", flag);
|
|
|
|
|
GameInteractor_ExecuteOnFlagUnset(FLAG_RANDOMIZER_INF, flag);
|
|
|
|
|
}
|
2023-06-20 11:54:02 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
u32 func_80035BFC(PlayState* play, s16 arg1) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
u16 retTextId = 0;
|
|
|
|
|
|
|
|
|
|
switch (arg1) {
|
|
|
|
|
case 0:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_05)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1048;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1047;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_FIRST_SPOKE_TO_MIDO)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_03)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1032;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1031;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_01)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1003;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1002;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1001;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_10)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1046;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1045;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_COMPLAINED_ABOUT_MIDO)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_0E)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1034;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1033;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_0C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1030;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x102F;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_19)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1071;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1070;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_0B)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_17)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1068;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1067;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_15)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1061;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1060;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1042;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1004;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1072;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_41)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1055;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1056;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1043;
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_1E)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1006;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1005;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1073;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x105A;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1042;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1007;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1072;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_47)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x105E;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x105D;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1044;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_22)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1009;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1008;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1075;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x105B;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1042;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_24)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x100B;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x100A;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1056;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x105F;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1043;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_26)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x100D;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x100C;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1057;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1057;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1043;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_28)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1019;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x100E;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1077;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_51)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1058;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1059;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 9:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1049;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1035;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1079;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x104E;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x104A;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1038;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1079;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_59)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1050;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x104F;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 11:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x104B;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x103C;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x107B;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1051;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 12:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x104C;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x103D;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x107C;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1052;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 13:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x104D;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x103E;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x106E;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_61)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1053;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1054;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 15:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_5C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1078;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_66)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x1066;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x1062;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 16:
|
2023-09-01 12:46:19 -04:00
|
|
|
|
if (play->sceneNum == SCENE_HYRULE_CASTLE) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7002;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_6A)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7004;
|
|
|
|
|
} else if ((gSaveContext.dayTime >= 0x4000) && (gSaveContext.dayTime < 0xC556)) {
|
|
|
|
|
retTextId = 0x7002;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x7003;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 17:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_6C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7008;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x7007;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 19:
|
|
|
|
|
retTextId = 0x702D;
|
|
|
|
|
break;
|
|
|
|
|
case 18:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7006;
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_71)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7072;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x7071;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x7029;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 20:
|
|
|
|
|
case 21:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_42)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x2012;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_41)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x2011;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x2010;
|
|
|
|
|
}
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x200F;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x200E;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 24:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7044;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x7015;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 25:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7045;
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_GetInfTable(INFTABLE_C2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7016;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 26:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7046;
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_GetInfTable(INFTABLE_C2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7018;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 27:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7047;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x701A;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_C6)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x701C;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x701B;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x701A;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 28:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7048;
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_GetInfTable(INFTABLE_CA);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x701D;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 29:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7049;
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_GetInfTable(INFTABLE_CC);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x701F;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 30:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x704A;
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_GetInfTable(INFTABLE_CE);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7021;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 31:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x704B;
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_GetInfTable(INFTABLE_D0);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7023;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 32:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x704C;
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_GetInfTable(INFTABLE_D2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7025;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 33:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x704D;
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_GetInfTable(INFTABLE_D4);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x7027;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 34:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_GetInfTable(INFTABLE_D6);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x403C;
|
|
|
|
|
break;
|
|
|
|
|
case 35:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_D8)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x5029;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x5028;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 37:
|
|
|
|
|
retTextId = 0x5002;
|
|
|
|
|
break;
|
|
|
|
|
case 38:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3027;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_BOMBED_DODONGOS_CAVERN_ENTRANCE)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3021;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_E0)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x302A;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x3008;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_20)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x4043;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x302A;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 39:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3027;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_BOMBED_DODONGOS_CAVERN_ENTRANCE)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3026;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x3009;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_2A)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x4043;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x302A;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 40:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3027;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_BOMBED_DODONGOS_CAVERN_ENTRANCE)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3026;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_EB)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x302B;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x300A;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_2B)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x4043;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x302A;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 41:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3027;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_F0)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3015;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x3014;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_2C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x4043;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x302A;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 42:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3027;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_F4)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3017;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x3016;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_2C)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x4043;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x302A;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 43:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3027;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_F8)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3019;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x3018;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_2D)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x4043;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x302A;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 48:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x3029;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_20) && Flags_GetEventChkInf(EVENTCHKINF_21)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x301B;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x301A;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 49:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x402D;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_A_ZORA)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x4007;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x4006;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 50:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x402E;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_A_ZORA)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_124)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x4009;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x4008;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x4006;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 51:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x402D;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_12A)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x400B;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x402F;
|
|
|
|
|
}
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_A_ZORA)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x400A;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x4006;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 52:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x402E;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_A_ZORA)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x400C;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x4006;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 53:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x402D;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x4010;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_A_ZORA)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x400F;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x4006;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 54:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x402E;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_A_ZORA)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x4011;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x4006;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 55:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x402B;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER)) {
|
|
|
|
|
if (Flags_GetInfTable(INFTABLE_138)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x401C;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x401B;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x401A;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 58:
|
|
|
|
|
retTextId = 0x500F;
|
|
|
|
|
break;
|
|
|
|
|
case 59:
|
|
|
|
|
retTextId = 0x5010;
|
|
|
|
|
break;
|
|
|
|
|
case 60:
|
|
|
|
|
retTextId = 0x5012;
|
|
|
|
|
break;
|
|
|
|
|
case 61:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_166)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x5001;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x5000;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 62:
|
|
|
|
|
retTextId = 0x5012;
|
|
|
|
|
break;
|
|
|
|
|
case 63:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_16A)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x5001;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x5000;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 71:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x2049;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x2048;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x2047;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG) && !Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x2044;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET)) {
|
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x2043;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x2042;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x2041;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 72:
|
|
|
|
|
if (!LINK_IS_ADULT) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x2040;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_94)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x2040;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x203F;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (!Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
if (!IS_DAY) {
|
|
|
|
|
retTextId = 0x204E;
|
2023-06-20 11:54:02 -04:00
|
|
|
|
} else if (Flags_GetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
retTextId = 0x2031;
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0x2030;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
retTextId = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (retTextId == 0) {
|
|
|
|
|
retTextId = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return retTextId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void func_80036E50(u16 textId, s16 arg1) {
|
|
|
|
|
switch (arg1) {
|
|
|
|
|
case 0:
|
|
|
|
|
switch (textId) {
|
|
|
|
|
case 0x1001:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return;
|
|
|
|
|
case 0x1002:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_01);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return;
|
|
|
|
|
case 0x1031:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_COMPLAINED_ABOUT_MIDO);
|
|
|
|
|
Flags_SetInfTable(INFTABLE_03);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return;
|
|
|
|
|
case 0x1047:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_05);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 1:
|
|
|
|
|
switch (textId) {
|
|
|
|
|
case 0x102F:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_FIRST_SPOKE_TO_MIDO);
|
|
|
|
|
Flags_SetInfTable(INFTABLE_0C);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return;
|
|
|
|
|
case 0x1033:
|
|
|
|
|
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0,
|
|
|
|
|
&D_801333E8);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
|
|
|
|
|
Flags_SetInfTable(INFTABLE_0E);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return;
|
|
|
|
|
case 0x1045:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_10);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return;
|
|
|
|
|
case 0x1060:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_15);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return;
|
|
|
|
|
case 0x1067:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SARIAS_SONG_FOR_MIDO_AS_ADULT);
|
|
|
|
|
Flags_SetInfTable(INFTABLE_17);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return;
|
|
|
|
|
case 0x1070:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_19);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 2:
|
|
|
|
|
if (textId == 0x1056) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_41);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 3:
|
|
|
|
|
if (textId == 0x1005) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_1E);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 4:
|
|
|
|
|
if (textId == 0x105D) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_47);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 5:
|
|
|
|
|
if (textId == 0x1008) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_22);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 6:
|
|
|
|
|
if (textId == 0x100A) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_24);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 7:
|
|
|
|
|
if (textId == 0x100C) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_26);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 8:
|
|
|
|
|
if (textId == 0x100E) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_28);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (textId == 0x1059) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_51);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 10:
|
|
|
|
|
if (textId == 0x104F) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_59);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 13:
|
|
|
|
|
if (textId == 0x1054) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_61);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 15:
|
|
|
|
|
if (textId == 0x1062) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_66);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 16:
|
|
|
|
|
if (textId == 0x7002) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_6A);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (textId == 0x7003) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_6A);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 17:
|
|
|
|
|
if (textId == 0x7007) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_6C);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 18:
|
|
|
|
|
if (textId == 0x7071) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_71);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 20:
|
|
|
|
|
case 21:
|
|
|
|
|
if (textId == 0x2010) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 25:
|
|
|
|
|
if (textId == 0x7016) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_C2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 26:
|
|
|
|
|
if (textId == 0x7018) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_C4);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 28:
|
|
|
|
|
if (textId == 0x701D) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_CA);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 29:
|
|
|
|
|
if (textId == 0x701F) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_CC);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 30:
|
|
|
|
|
if (textId == 0x7021) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_CE);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 31:
|
|
|
|
|
if (textId == 0x7023) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_D0);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 32:
|
|
|
|
|
if (textId == 0x7025) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_D2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 33:
|
|
|
|
|
if (textId == 0x7027) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_D4);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 34:
|
|
|
|
|
if (textId == 0x403C) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_D6);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 35:
|
|
|
|
|
if (textId == 0x5028) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_D8);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 38:
|
|
|
|
|
if (textId == 0x3008) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_E0);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 40:
|
|
|
|
|
if (textId == 0x300B) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_EB);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 41:
|
|
|
|
|
if (textId == 0x3014) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_F0);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 42:
|
|
|
|
|
if (textId == 0x3016) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_F4);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 43:
|
|
|
|
|
if (textId == 0x3018) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_20);
|
|
|
|
|
Flags_SetInfTable(INFTABLE_F8);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 48:
|
|
|
|
|
if (textId == 0x3020) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_22);
|
|
|
|
|
Flags_SetInfTable(INFTABLE_113);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 49:
|
|
|
|
|
case 52:
|
|
|
|
|
case 53:
|
|
|
|
|
case 54:
|
|
|
|
|
if (textId == 0x4006) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_A_ZORA);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 50:
|
|
|
|
|
if (textId == 0x4006) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_A_ZORA);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (textId == 0x4008) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_124);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 51:
|
|
|
|
|
if (textId == 0x4006) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_A_ZORA);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (textId == 0x400A) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_32);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (textId == 0x402F) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_12A);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 55:
|
|
|
|
|
if (textId == 0x401B) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED);
|
|
|
|
|
Flags_SetInfTable(INFTABLE_138);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 61:
|
|
|
|
|
if (textId == 0x5000) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_166);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 63:
|
|
|
|
|
if (textId == 0x5013) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_16A);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 71:
|
|
|
|
|
if (textId == 0x2041) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (textId == 0x2044) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (textId == 0x2047) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (textId == 0x2048) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 72:
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_800374E0(PlayState* play, Actor* actor, u16 textId) {
|
|
|
|
|
MessageContext* msgCtx = &play->msgCtx;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 ret = 1;
|
|
|
|
|
|
|
|
|
|
switch (textId) {
|
|
|
|
|
case 0x1035:
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_2A)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1036);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1041);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_2B)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1037);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1041);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x1038:
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_2E)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1039);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1041);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_2F)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x103A);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1041);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 2) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_30)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x103B);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1041);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x103E:
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x103F);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1040);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x1041:
|
|
|
|
|
if (msgCtx->choiceTextId == 0x1035) {
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1036);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_2A);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1037);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_2B);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceTextId == 0x1038) {
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1039);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_2E);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x103A);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_2F);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 2) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x103B);
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_30);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x1062:
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1063);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x1064);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x2030:
|
|
|
|
|
case 0x2031:
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
|
|
|
|
if (gSaveContext.rupees >= 10) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x2034);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Rupees_ChangeBy(-10);
|
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x2032);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x2032);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
2023-06-20 11:54:02 -04:00
|
|
|
|
Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x2036:
|
|
|
|
|
case 0x2037:
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x201F);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x205A);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x2038:
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x205A);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x2034:
|
|
|
|
|
if (msgCtx->choiceIndex != 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x2035);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x2043:
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
break;
|
|
|
|
|
}
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x2044);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x205A:
|
|
|
|
|
break;
|
|
|
|
|
case 0x300A:
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetEventChkInf(EVENTCHKINF_22)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x300B);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x300C);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x300D);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x301B:
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x301D);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2023-06-20 11:54:02 -04:00
|
|
|
|
if (Flags_GetInfTable(INFTABLE_113)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x301F);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x301E);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x301E:
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x3020);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x400C:
|
|
|
|
|
if (msgCtx->choiceIndex == 0) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x400D);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
if (msgCtx->choiceIndex == 1) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x400E);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x7007:
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x703E);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x703E:
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x703F);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x703F:
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80035B18(play, actor, 0x7042);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
u16 func_80037C30(PlayState* play, s16 arg1) {
|
|
|
|
|
return func_80035BFC(play, arg1);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_80037C5C(PlayState* play, s16 arg1, u16 textId) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
func_80036E50(textId, arg1);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_80037C94(PlayState* play, Actor* actor, s32 arg2) {
|
|
|
|
|
return func_800374E0(play, actor, actor->textId);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_80037CB8(PlayState* play, Actor* actor, s16 arg2) {
|
|
|
|
|
MessageContext* msgCtx = &play->msgCtx;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 ret = false;
|
|
|
|
|
|
|
|
|
|
switch (Message_GetState(msgCtx)) {
|
|
|
|
|
case TEXT_STATE_CLOSING:
|
2022-11-06 03:24:34 -05:00
|
|
|
|
func_80037C5C(play, arg2, actor->textId);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
ret = true;
|
|
|
|
|
break;
|
|
|
|
|
case TEXT_STATE_CHOICE:
|
|
|
|
|
case TEXT_STATE_EVENT:
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (Message_ShouldAdvance(play) && func_80037C94(play, actor, arg2)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
|
|
|
|
msgCtx->msgMode = MSGMODE_TEXT_CLOSING;
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_80037D98(PlayState* play, Actor* actor, s16 arg2, s32* arg3) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s16 var;
|
|
|
|
|
s16 sp2C;
|
|
|
|
|
s16 sp2A;
|
|
|
|
|
s16 abs_var;
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (Actor_ProcessTalkRequest(actor, play)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*arg3 = 1;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*arg3 == 1) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (func_80037CB8(play, actor, arg2)) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
*arg3 = 0;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
Actor_GetScreenPos(play, actor, &sp2C, &sp2A);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
|
|
if ((sp2C < 0) || (sp2C > SCREEN_WIDTH) || (sp2A < 0) || (sp2A > SCREEN_HEIGHT)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var = actor->yawTowardsPlayer - actor->shape.rot.y;
|
|
|
|
|
abs_var = ABS(var);
|
|
|
|
|
|
|
|
|
|
if (abs_var >= 0x4300) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((actor->xyzDistToPlayerSq > SQ(160.0f)) && !actor->isTargeted) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actor->xyzDistToPlayerSq <= SQ(80.0f)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (func_8002F2CC(actor, play, 80.0f)) {
|
|
|
|
|
actor->textId = func_80037C30(play, arg2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
if (func_8002F2F4(actor, play)) {
|
|
|
|
|
actor->textId = func_80037C30(play, arg2);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 func_80037F30(Vec3s* arg0, Vec3s* arg1) {
|
|
|
|
|
Math_SmoothStepToS(&arg0->y, 0, 6, 6200, 100);
|
|
|
|
|
Math_SmoothStepToS(&arg0->x, 0, 6, 6200, 100);
|
|
|
|
|
Math_SmoothStepToS(&arg1->y, 0, 6, 6200, 100);
|
|
|
|
|
Math_SmoothStepToS(&arg1->x, 0, 6, 6200, 100);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 func_80037FC8(Actor* actor, Vec3f* arg1, Vec3s* arg2, Vec3s* arg3) {
|
|
|
|
|
s16 sp36;
|
|
|
|
|
s16 sp34;
|
|
|
|
|
s16 var;
|
|
|
|
|
|
|
|
|
|
sp36 = Math_Vec3f_Pitch(&actor->focus.pos, arg1);
|
|
|
|
|
sp34 = Math_Vec3f_Yaw(&actor->focus.pos, arg1) - actor->world.rot.y;
|
|
|
|
|
|
|
|
|
|
Math_SmoothStepToS(&arg2->x, sp36, 6, 2000, 1);
|
|
|
|
|
arg2->x = (arg2->x < -6000) ? -6000 : ((arg2->x > 6000) ? 6000 : arg2->x);
|
|
|
|
|
|
|
|
|
|
var = Math_SmoothStepToS(&arg2->y, sp34, 6, 2000, 1);
|
|
|
|
|
arg2->y = (arg2->y < -8000) ? -8000 : ((arg2->y > 8000) ? 8000 : arg2->y);
|
|
|
|
|
|
|
|
|
|
if (var && (ABS(arg2->y) < 8000)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Math_SmoothStepToS(&arg3->y, sp34 - arg2->y, 4, 2000, 1);
|
|
|
|
|
arg3->y = (arg3->y < -12000) ? -12000 : ((arg3->y > 12000) ? 12000 : arg3->y);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_80038154(PlayState* play, Actor* actor, Vec3s* arg2, Vec3s* arg3, f32 arg4) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 pad;
|
|
|
|
|
Vec3f sp2C;
|
|
|
|
|
s16 var;
|
|
|
|
|
s16 abs_var;
|
|
|
|
|
|
|
|
|
|
actor->focus.pos = actor->world.pos;
|
|
|
|
|
actor->focus.pos.y += arg4;
|
|
|
|
|
|
2023-11-19 14:29:56 -05:00
|
|
|
|
if (!(((play->csCtx.state != CS_STATE_IDLE) || (gDbgCamEnabled)) && (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0))) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
var = actor->yawTowardsPlayer - actor->shape.rot.y;
|
|
|
|
|
abs_var = ABS(var);
|
|
|
|
|
if (abs_var >= 0x4300) {
|
|
|
|
|
func_80037F30(arg2, arg3);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-19 14:29:56 -05:00
|
|
|
|
if (((play->csCtx.state != CS_STATE_IDLE) || (gDbgCamEnabled)) && (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
sp2C = play->view.eye;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
|
|
|
|
sp2C = player->actor.focus.pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func_80037FC8(actor, &sp2C, arg2, arg3);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 03:24:34 -05:00
|
|
|
|
s32 func_80038290(PlayState* play, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f arg4) {
|
|
|
|
|
Player* player = GET_PLAYER(play);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
s32 pad;
|
|
|
|
|
Vec3f sp24;
|
|
|
|
|
s16 var;
|
|
|
|
|
s16 abs_var;
|
|
|
|
|
|
|
|
|
|
actor->focus.pos = arg4;
|
|
|
|
|
|
2023-11-19 14:29:56 -05:00
|
|
|
|
if (!(((play->csCtx.state != CS_STATE_IDLE) || (gDbgCamEnabled)) && (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0))) {
|
2022-03-21 21:51:23 -04:00
|
|
|
|
var = actor->yawTowardsPlayer - actor->shape.rot.y;
|
|
|
|
|
abs_var = ABS(var);
|
|
|
|
|
if (abs_var >= 0x4300) {
|
|
|
|
|
func_80037F30(arg2, arg3);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-19 14:29:56 -05:00
|
|
|
|
if (((play->csCtx.state != CS_STATE_IDLE) || (gDbgCamEnabled)) && (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0)) {
|
2022-11-06 03:24:34 -05:00
|
|
|
|
sp24 = play->view.eye;
|
2022-03-21 21:51:23 -04:00
|
|
|
|
} else {
|
|
|
|
|
sp24 = player->actor.focus.pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func_80037FC8(actor, &sp24, arg2, arg3);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|