summaryrefslogtreecommitdiff
path: root/src/code
diff options
context:
space:
mode:
Diffstat (limited to 'src/code')
-rw-r--r--src/code/z_actor.c771
-rw-r--r--src/code/z_en_a_keep.c4
-rw-r--r--src/code/z_en_hy_code.c4
-rw-r--r--src/code/z_parameter.c2
-rw-r--r--src/code/z_player_call.c6
-rw-r--r--src/code/z_player_lib.c11
-rw-r--r--src/code/z_sub_s.c2
7 files changed, 446 insertions, 354 deletions
diff --git a/src/code/z_actor.c b/src/code/z_actor.c
index 5debc583d..f88f511b5 100644
--- a/src/code/z_actor.c
+++ b/src/code/z_actor.c
@@ -3,6 +3,7 @@
* Description:
*/
+#include "prevent_bss_reordering.h"
#include "global.h"
#include "fault.h"
#include "sys_cfb.h"
@@ -18,21 +19,26 @@
#include "objects/object_bdoor/object_bdoor.h"
// bss
-extern FaultClient sActorFaultClient; // 2 funcs
-extern CollisionPoly* D_801ED8B0; // 1 func
-extern s32 D_801ED8B4; // 2 funcs
-extern Actor* D_801ED8B8; // 2 funcs
-extern Actor* D_801ED8BC; // 2 funcs
-extern Actor* D_801ED8C0; // 2 funcs
-extern Actor* D_801ED8C4; // 2 funcs
-extern f32 D_801ED8C8; // 2 funcs
-extern f32 sBgmEnemyDistSq; // 2 funcs
-extern f32 D_801ED8D0; // 2 funcs
-extern s32 D_801ED8D4; // 2 funcs
-extern s32 D_801ED8D8; // 2 funcs
-extern s16 D_801ED8DC; // 2 funcs
-extern Mtx D_801ED8E0; // 1 func
-extern Actor* D_801ED920; // 2 funcs. 1 out of z_actor
+FaultClient sActorFaultClient; // 2 funcs
+
+CollisionPoly* D_801ED8B0; // 1 func
+s32 D_801ED8B4; // 2 funcs
+
+Actor* sTargetableNearestActor;
+Actor* sTargetablePrioritizedActor;
+Actor* D_801ED8C0;
+Actor* D_801ED8C4;
+
+f32 sTargetableNearestActorDistSq;
+f32 sBgmEnemyDistSq;
+f32 D_801ED8D0;
+s32 sTargetablePrioritizedPriority;
+s32 D_801ED8D8;
+s16 sTargetPlayerRotY;
+
+Mtx sActorHiliteMtx;
+
+Actor* D_801ED920; // 2 funcs. 1 out of z_actor
#define ACTOR_AUDIO_FLAG_SFX_ACTOR_POS (1 << 0)
#define ACTOR_AUDIO_FLAG_SFX_CENTERED_1 (1 << 1)
@@ -52,7 +58,7 @@ extern Actor* D_801ED920; // 2 funcs. 1 out of z_actor
void Actor_KillAllOnHalfDayChange(PlayState* play, ActorContext* actorCtx);
Actor* Actor_SpawnEntry(ActorContext* actorCtx, ActorEntry* actorEntry, PlayState* play);
Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play);
-void func_800BB8EC(GameState* gameState, ActorContext* actorCtx, Actor** arg2, Actor** arg3, Player* player);
+void Target_GetTargetActor(PlayState* play, ActorContext* actorCtx, Actor** targetableP, Actor** arg3, Player* player);
s32 func_800BA2FC(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW);
void Actor_AddToCategory(ActorContext* actorCtx, Actor* actor, u8 actorCategory);
Actor* Actor_RemoveFromCategory(PlayState* play, ActorContext* actorCtx, Actor* actorToRemove);
@@ -415,11 +421,11 @@ void Actor_GetProjectedPos(PlayState* play, Vec3f* worldPos, Vec3f* projectedPos
*invW = (*invW < 1.0f) ? 1.0f : (1.0f / *invW);
}
-void Target_SetPos(TargetContext* targetCtx, s32 index, f32 x, f32 y, f32 z) {
- targetCtx->unk50[index].pos.x = x;
- targetCtx->unk50[index].pos.y = y;
- targetCtx->unk50[index].pos.z = z;
- targetCtx->unk50[index].unkC = targetCtx->unk44;
+void Target_SetLockOnPos(TargetContext* targetCtx, s32 index, f32 x, f32 y, f32 z) {
+ targetCtx->lockOnTriangleSets[index].pos.x = x;
+ targetCtx->lockOnTriangleSets[index].pos.y = y;
+ targetCtx->lockOnTriangleSets[index].pos.z = z;
+ targetCtx->lockOnTriangleSets[index].radius = targetCtx->lockOnRadius;
}
typedef struct {
@@ -427,282 +433,293 @@ typedef struct {
/* 0x4 */ Color_RGBA8 outer;
} TatlColor; // size = 0x8
+// For whatever reason it has an extra entry
TatlColor sTatlColorList[] = {
- { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } },
- { { 255, 255, 230, 255 }, { 220, 160, 80, 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 } },
+ { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, // ACTORCAT_SWITCH
+ { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, // ACTORCAT_BG
+ { { 255, 255, 230, 255 }, { 220, 160, 80, 0 } }, // ACTORCAT_PLAYER
+ { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, // ACTORCAT_EXPLOSIVES
+ { { 150, 150, 255, 255 }, { 150, 150, 255, 0 } }, // ACTORCAT_NPC
+ { { 255, 255, 0, 255 }, { 200, 155, 0, 0 } }, // ACTORCAT_ENEMY
+ { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, // ACTORCAT_PROP
+ { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, // ACTORCAT_ITEMACTION
+ { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, // ACTORCAT_MISC
+ { { 255, 255, 0, 255 }, { 200, 155, 0, 0 } }, // ACTORCAT_BOSS
+ { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, // ACTORCAT_DOOR
+ { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, // ACTORCAT_CHEST
+ { { 0, 255, 0, 255 }, { 0, 255, 0, 0 } }, // ACTORCAT_MAX
};
-void func_800B4F78(TargetContext* targetCtx, s32 type, PlayState* play) {
+void Target_InitLockOn(TargetContext* targetCtx, ActorType type, PlayState* play) {
TatlColor* tatlColorEntry;
s32 i;
- TargetContextEntry* targetEntry;
+ LockOnTriangleSet* triangleSet;
- Math_Vec3f_Copy(&targetCtx->targetCenterPos, &play->view.eye);
- targetCtx->unk48 = 0x100;
+ Math_Vec3f_Copy(&targetCtx->lockOnPos, &play->view.eye);
+ targetCtx->lockOnAlpha = 256;
tatlColorEntry = &sTatlColorList[type];
- targetCtx->unk44 = 500.0f;
+ targetCtx->lockOnRadius = 500.0f;
- targetEntry = targetCtx->unk50;
- for (i = 0; i < ARRAY_COUNT(targetCtx->unk50); i++, targetEntry++) {
- Target_SetPos(targetCtx, i, 0.0f, 0.0f, 0.0f);
+ triangleSet = targetCtx->lockOnTriangleSets;
+ for (i = 0; i < ARRAY_COUNT(targetCtx->lockOnTriangleSets); i++, triangleSet++) {
+ Target_SetLockOnPos(targetCtx, i, 0.0f, 0.0f, 0.0f);
- targetEntry->color.r = tatlColorEntry->inner.r;
- targetEntry->color.g = tatlColorEntry->inner.g;
- targetEntry->color.b = tatlColorEntry->inner.b;
+ triangleSet->color.r = tatlColorEntry->inner.r;
+ triangleSet->color.g = tatlColorEntry->inner.g;
+ triangleSet->color.b = tatlColorEntry->inner.b;
}
}
-void Target_SetColors(TargetContext* targetCtx, Actor* actor, s32 type, PlayState* play) {
- targetCtx->unk0.x = actor->focus.pos.x;
- targetCtx->unk0.y = actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y);
- targetCtx->unk0.z = actor->focus.pos.z;
+void Target_SetFairyState(TargetContext* targetCtx, Actor* actor, ActorType type, PlayState* play) {
+ targetCtx->fairyPos.x = actor->focus.pos.x;
+ targetCtx->fairyPos.y = actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y);
+ targetCtx->fairyPos.z = actor->focus.pos.z;
- targetCtx->fairyInner.r = sTatlColorList[type].inner.r;
- targetCtx->fairyInner.g = sTatlColorList[type].inner.g;
- targetCtx->fairyInner.b = sTatlColorList[type].inner.b;
- targetCtx->fairyInner.a = sTatlColorList[type].inner.a;
- targetCtx->fairyOuter.r = sTatlColorList[type].outer.r;
- targetCtx->fairyOuter.g = sTatlColorList[type].outer.g;
- targetCtx->fairyOuter.b = sTatlColorList[type].outer.b;
- targetCtx->fairyOuter.a = sTatlColorList[type].outer.a;
+ targetCtx->fairyInnerColor.r = sTatlColorList[type].inner.r;
+ targetCtx->fairyInnerColor.g = sTatlColorList[type].inner.g;
+ targetCtx->fairyInnerColor.b = sTatlColorList[type].inner.b;
+ targetCtx->fairyInnerColor.a = sTatlColorList[type].inner.a;
+ targetCtx->fairyOuterColor.r = sTatlColorList[type].outer.r;
+ targetCtx->fairyOuterColor.g = sTatlColorList[type].outer.g;
+ targetCtx->fairyOuterColor.b = sTatlColorList[type].outer.b;
+ targetCtx->fairyOuterColor.a = sTatlColorList[type].outer.a;
}
-void Actor_TargetContextInit(TargetContext* targetCtx, Actor* actor, PlayState* play) {
+void Target_Init(TargetContext* targetCtx, Actor* actor, PlayState* play) {
targetCtx->bgmEnemy = NULL;
- targetCtx->unk8C = NULL;
- targetCtx->targetedActor = NULL;
- targetCtx->arrowPointedActor = NULL;
- targetCtx->unk4B = 0;
- targetCtx->unk4C = 0;
- targetCtx->unk40 = 0.0f;
- Target_SetColors(targetCtx, actor, actor->category, play);
- func_800B4F78(targetCtx, actor->category, play);
+ targetCtx->forcedTargetActor = NULL;
+ targetCtx->lockOnActor = NULL;
+ targetCtx->fairyActor = NULL;
+ targetCtx->rotZTick = 0;
+ targetCtx->lockOnIndex = 0;
+ targetCtx->fairyMoveProgressFactor = 0.0f;
+ Target_SetFairyState(targetCtx, actor, actor->category, play);
+ Target_InitLockOn(targetCtx, actor->category, play);
}
-void Actor_DrawZTarget(TargetContext* targetCtx, PlayState* play) {
+void Target_Draw(TargetContext* targetCtx, PlayState* play) {
Player* player = GET_PLAYER(play);
+ Actor* actor;
- if (!(player->stateFlags1 & (PLAYER_STATE1_2 | PLAYER_STATE1_40 | PLAYER_STATE1_80 | PLAYER_STATE1_200 |
- PLAYER_STATE1_400 | PLAYER_STATE1_10000000 | PLAYER_STATE1_20000000))) {
- Actor* actor = targetCtx->targetedActor;
+ if (player->stateFlags1 & (PLAYER_STATE1_2 | PLAYER_STATE1_40 | PLAYER_STATE1_80 | PLAYER_STATE1_200 |
+ PLAYER_STATE1_400 | PLAYER_STATE1_10000000 | PLAYER_STATE1_20000000)) {
+ return;
+ }
- OPEN_DISPS(play->state.gfxCtx);
+ actor = targetCtx->lockOnActor;
- if (targetCtx->unk48 != 0) {
- TargetContextEntry* entry;
- s16 alpha = 255;
- f32 var1 = 1.0f;
- Vec3f projectedPos;
- s32 spB8;
- f32 invW;
- s32 spB0;
- s32 spAC;
- f32 var2;
- s32 i;
-
- if (targetCtx->unk4B != 0) {
- spB8 = 1;
- } else {
- spB8 = 3;
- }
+ OPEN_DISPS(play->state.gfxCtx);
- if (actor != NULL) {
- Math_Vec3f_Copy(&targetCtx->targetCenterPos, &actor->focus.pos);
- var1 = (500.0f - targetCtx->unk44) / 420.0f;
- } else {
- targetCtx->unk48 -= 120;
- if (targetCtx->unk48 < 0) {
- targetCtx->unk48 = 0;
- }
- alpha = targetCtx->unk48;
+ if (targetCtx->lockOnAlpha != 0) {
+ LockOnTriangleSet* entry;
+ s16 alpha = 255;
+ f32 projectdPosScale = 1.0f;
+ Vec3f projectedPos;
+ s32 totalEntries;
+ f32 invW;
+ s32 i;
+ s32 index;
+ f32 lockOnScaleX;
+
+ if (targetCtx->rotZTick != 0) {
+ totalEntries = 1;
+ } else {
+ // Use multiple entries for the movement effect when the triangles are getting closer to the actor from the
+ // margin of the screen
+ totalEntries = ARRAY_COUNT(targetCtx->lockOnTriangleSets);
+ }
+
+ if (actor != NULL) {
+ Math_Vec3f_Copy(&targetCtx->lockOnPos, &actor->focus.pos);
+ projectdPosScale = (500.0f - targetCtx->lockOnRadius) / 420.0f;
+ } else {
+ targetCtx->lockOnAlpha -= 120;
+ if (targetCtx->lockOnAlpha < 0) {
+ targetCtx->lockOnAlpha = 0;
}
+ alpha = targetCtx->lockOnAlpha;
+ }
- Actor_GetProjectedPos(play, &targetCtx->targetCenterPos, &projectedPos, &invW);
+ Actor_GetProjectedPos(play, &targetCtx->lockOnPos, &projectedPos, &invW);
- projectedPos.x = ((SCREEN_WIDTH / 2) * (projectedPos.x * invW)) * var1;
- projectedPos.x = CLAMP(projectedPos.x, -SCREEN_WIDTH, SCREEN_WIDTH);
+ projectedPos.x = ((SCREEN_WIDTH / 2) * (projectedPos.x * invW)) * projectdPosScale;
+ projectedPos.x = CLAMP(projectedPos.x, -SCREEN_WIDTH, SCREEN_WIDTH);
- projectedPos.y = ((SCREEN_HEIGHT / 2) * (projectedPos.y * invW)) * var1;
- projectedPos.y = CLAMP(projectedPos.y, -SCREEN_HEIGHT, SCREEN_HEIGHT);
+ projectedPos.y = ((SCREEN_HEIGHT / 2) * (projectedPos.y * invW)) * projectdPosScale;
+ projectedPos.y = CLAMP(projectedPos.y, -SCREEN_HEIGHT, SCREEN_HEIGHT);
- projectedPos.z = projectedPos.z * var1;
+ projectedPos.z *= projectdPosScale;
- targetCtx->unk4C--;
- if (targetCtx->unk4C < 0) {
- targetCtx->unk4C = 2;
- }
+ targetCtx->lockOnIndex--;
+ if (targetCtx->lockOnIndex < 0) {
+ targetCtx->lockOnIndex = ARRAY_COUNT(targetCtx->lockOnTriangleSets) - 1;
+ }
- Target_SetPos(targetCtx, targetCtx->unk4C, projectedPos.x, projectedPos.y, projectedPos.z);
+ Target_SetLockOnPos(targetCtx, targetCtx->lockOnIndex, projectedPos.x, projectedPos.y, projectedPos.z);
- if ((!(player->stateFlags1 & PLAYER_STATE1_40)) || (actor != player->targetedActor)) {
- OVERLAY_DISP = Gfx_SetupDL(OVERLAY_DISP, SETUPDL_57);
+ if (!(player->stateFlags1 & PLAYER_STATE1_40) || (actor != player->lockOnActor)) {
+ OVERLAY_DISP = Gfx_SetupDL(OVERLAY_DISP, SETUPDL_57);
- for (spB0 = 0, spAC = targetCtx->unk4C; spB0 < spB8; spB0++, spAC = (spAC + 1) % 3) {
- entry = &targetCtx->unk50[spAC];
+ for (i = 0, index = targetCtx->lockOnIndex; i < totalEntries;
+ i++, index = (index + 1) % ARRAY_COUNT(targetCtx->lockOnTriangleSets)) {
+ entry = &targetCtx->lockOnTriangleSets[index];
- if (entry->unkC < 500.0f) {
- if (entry->unkC <= 120.0f) {
- var2 = 0.15f;
- } else {
- var2 = ((entry->unkC - 120.0f) * 0.001f) + 0.15f;
- }
+ if (entry->radius < 500.0f) {
+ s32 triangleIndex;
- Matrix_Translate(entry->pos.x, entry->pos.y, 0.0f, MTXMODE_NEW);
- Matrix_Scale(var2, 0.15f, 1.0f, MTXMODE_APPLY);
+ if (entry->radius <= 120.0f) {
+ lockOnScaleX = 0.15f;
+ } else {
+ lockOnScaleX = ((entry->radius - 120.0f) * 0.001f) + 0.15f;
+ }
- gDPSetPrimColor(OVERLAY_DISP++, 0, 0, entry->color.r, entry->color.g, entry->color.b,
- (u8)alpha);
+ Matrix_Translate(entry->pos.x, entry->pos.y, 0.0f, MTXMODE_NEW);
+ Matrix_Scale(lockOnScaleX, 0.15f, 1.0f, MTXMODE_APPLY);
- Matrix_RotateZS((targetCtx->unk4B * 512), MTXMODE_APPLY);
+ gDPSetPrimColor(OVERLAY_DISP++, 0, 0, entry->color.r, entry->color.g, entry->color.b, (u8)alpha);
- for (i = 0; i < 4; i++) {
- Matrix_RotateZS(0x4000, MTXMODE_APPLY);
- Matrix_Push();
- Matrix_Translate(entry->unkC, entry->unkC, 0.0f, MTXMODE_APPLY);
- gSPMatrix(OVERLAY_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD);
- gSPDisplayList(OVERLAY_DISP++, gZTargetLockOnTriangleDL);
- Matrix_Pop();
- }
- }
+ Matrix_RotateZS(targetCtx->rotZTick * 0x200, MTXMODE_APPLY);
- alpha -= 255 / 3;
- if (alpha < 0) {
- alpha = 0;
+ // Draw the 4 lock-on triangles
+ for (triangleIndex = 0; triangleIndex < 4; triangleIndex++) {
+ Matrix_RotateZS(0x10000 / 4, MTXMODE_APPLY);
+ Matrix_Push();
+ Matrix_Translate(entry->radius, entry->radius, 0.0f, MTXMODE_APPLY);
+ gSPMatrix(OVERLAY_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(OVERLAY_DISP++, gZTargetLockOnTriangleDL);
+ Matrix_Pop();
}
}
+
+ alpha -= 255 / ARRAY_COUNT(targetCtx->lockOnTriangleSets);
+ if (alpha < 0) {
+ alpha = 0;
+ }
}
}
+ }
- actor = targetCtx->unk_94;
- if ((actor != NULL) && !(actor->flags & ACTOR_FLAG_CANT_LOCK_ON)) {
- TatlColor* color = &sTatlColorList[actor->category];
-
- POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, SETUPDL_7);
+ actor = targetCtx->arrowPointedActor;
+ if ((actor != NULL) && !(actor->flags & ACTOR_FLAG_CANT_LOCK_ON)) {
+ TatlColor* color = &sTatlColorList[actor->category];
- Matrix_Translate(actor->focus.pos.x,
- actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y) + 17.0f,
- actor->focus.pos.z, MTXMODE_NEW);
- Matrix_RotateYS((play->gameplayFrames * 3000), MTXMODE_APPLY);
- Matrix_Scale((iREG(27) + 35) / 1000.0f, (iREG(28) + 60) / 1000.0f, (iREG(29) + 50) / 1000.0f,
- MTXMODE_APPLY);
+ POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, SETUPDL_7);
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, color->inner.r, color->inner.g, color->inner.b, 255);
- gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD);
- gSPDisplayList(POLY_XLU_DISP++, gZTargetArrowDL);
- }
+ Matrix_Translate(actor->focus.pos.x, actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y) + 17.0f,
+ actor->focus.pos.z, MTXMODE_NEW);
+ Matrix_RotateYS(play->gameplayFrames * 0xBB8, MTXMODE_APPLY);
+ Matrix_Scale((iREG(27) + 35) / 1000.0f, (iREG(28) + 60) / 1000.0f, (iREG(29) + 50) / 1000.0f, MTXMODE_APPLY);
- CLOSE_DISPS(play->state.gfxCtx);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, color->inner.r, color->inner.g, color->inner.b, 255);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(POLY_XLU_DISP++, gZTargetArrowDL);
}
+
+ CLOSE_DISPS(play->state.gfxCtx);
}
// OoT: func_8002C7BC
-void func_800B5814(TargetContext* targetCtx, Player* player, Actor* actor, GameState* gameState) {
- PlayState* play = (PlayState*)gameState;
- Actor* sp68 = NULL;
+void Target_Update(TargetContext* targetCtx, Player* player, Actor* lockOnActor, PlayState* play) {
+ s32 pad;
+ Actor* actor = NULL;
s32 category;
Vec3f projectedPos;
f32 invW;
- if ((player->targetedActor != NULL) && (player->unk_AE3[player->unk_ADE] == 2)) {
- targetCtx->unk_94 = NULL;
+ // If currently not locked on to an actor and not pressing down on the analog stick then try to find a targetable
+ // actor
+ if ((player->lockOnActor != NULL) && (player->unk_AE3[player->unk_ADE] == 2)) {
+ targetCtx->arrowPointedActor = NULL;
} else {
- func_800BB8EC(gameState, &play->actorCtx, &sp68, &D_801ED920, player);
- targetCtx->unk_94 = sp68;
+ Target_GetTargetActor(play, &play->actorCtx, &actor, &D_801ED920, player);
+ targetCtx->arrowPointedActor = actor;
}
- if (targetCtx->unk8C != NULL) {
- sp68 = targetCtx->unk8C;
- targetCtx->unk8C = NULL;
- } else if (actor != NULL) {
- sp68 = actor;
+ if (targetCtx->forcedTargetActor != NULL) {
+ actor = targetCtx->forcedTargetActor;
+ targetCtx->forcedTargetActor = NULL;
+ } else if (lockOnActor != NULL) {
+ actor = lockOnActor;
}
- if (sp68 != NULL) {
- category = sp68->category;
+ if (actor != NULL) {
+ category = actor->category;
} else {
category = player->actor.category;
}
- if ((sp68 != targetCtx->arrowPointedActor) || (category != targetCtx->unk4A)) {
- targetCtx->arrowPointedActor = sp68;
- targetCtx->unk4A = category;
- targetCtx->unk40 = 1.0f;
+ if ((actor != targetCtx->fairyActor) || (category != targetCtx->fairyActorCategory)) {
+ targetCtx->fairyActor = actor;
+ targetCtx->fairyActorCategory = category;
+ targetCtx->fairyMoveProgressFactor = 1.0f;
}
- if (sp68 == NULL) {
- sp68 = &player->actor;
+ if (actor == NULL) {
+ actor = &player->actor;
}
- if (!Math_StepToF(&targetCtx->unk40, 0.0f, 0.25f)) {
- f32 temp_f0;
- f32 x;
- f32 y;
- f32 z;
-
- temp_f0 = 0.25f / targetCtx->unk40;
-
- x = sp68->focus.pos.x - targetCtx->unk0.x;
- y = (sp68->focus.pos.y + (sp68->targetArrowOffset * sp68->scale.y)) - targetCtx->unk0.y;
- z = sp68->focus.pos.z - targetCtx->unk0.z;
+ if (!Math_StepToF(&targetCtx->fairyMoveProgressFactor, 0.0f, 0.25f)) {
+ f32 fairyMoveScale = 0.25f / targetCtx->fairyMoveProgressFactor;
+ f32 x = actor->focus.pos.x - targetCtx->fairyPos.x;
+ f32 y = (actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y)) - targetCtx->fairyPos.y;
+ f32 z = actor->focus.pos.z - targetCtx->fairyPos.z;
- targetCtx->unk0.x += x * temp_f0;
- targetCtx->unk0.y += y * temp_f0;
- targetCtx->unk0.z += z * temp_f0;
+ targetCtx->fairyPos.x += x * fairyMoveScale;
+ targetCtx->fairyPos.y += y * fairyMoveScale;
+ targetCtx->fairyPos.z += z * fairyMoveScale;
} else {
- Target_SetColors(targetCtx, sp68, category, play);
+ Target_SetFairyState(targetCtx, actor, category, play);
}
- if ((actor != NULL) && (targetCtx->unk4B == 0)) {
- Actor_GetProjectedPos(play, &actor->focus.pos, &projectedPos, &invW);
+ if ((lockOnActor != NULL) && (targetCtx->rotZTick == 0)) {
+ Actor_GetProjectedPos(play, &lockOnActor->focus.pos, &projectedPos, &invW);
if ((projectedPos.z <= 0.0f) || (fabsf(projectedPos.x * invW) >= 1.0f) ||
(fabsf(projectedPos.y * invW) >= 1.0f)) {
- actor = NULL;
+ lockOnActor = NULL;
}
}
- if (actor != NULL) {
- if (actor != targetCtx->targetedActor) {
+ if (lockOnActor != NULL) {
+ if (lockOnActor != targetCtx->lockOnActor) {
s32 sfxId;
- func_800B4F78(targetCtx, actor->category, play);
+ // Lock On entries need to be re-initialized when changing the targeted actor
+ Target_InitLockOn(targetCtx, lockOnActor->category, play);
- targetCtx->targetedActor = actor;
+ targetCtx->lockOnActor = lockOnActor;
- if (actor->id == ACTOR_EN_BOOM) {
- targetCtx->unk48 = 0;
+ if (lockOnActor->id == ACTOR_EN_BOOM) {
+ // Avoid drawing the lock on triangles on a zora boomerang
+ targetCtx->lockOnAlpha = 0;
}
- sfxId =
- CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_4 | ACTOR_FLAG_1) ? NA_SE_SY_LOCK_ON : NA_SE_SY_LOCK_ON_HUMAN;
+ sfxId = CHECK_FLAG_ALL(lockOnActor->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY)
+ ? NA_SE_SY_LOCK_ON
+ : NA_SE_SY_LOCK_ON_HUMAN;
Audio_PlaySfx(sfxId);
}
- targetCtx->targetCenterPos.x = actor->world.pos.x;
- targetCtx->targetCenterPos.y = actor->world.pos.y - (actor->shape.yOffset * actor->scale.y);
- targetCtx->targetCenterPos.z = actor->world.pos.z;
+ targetCtx->lockOnPos.x = lockOnActor->world.pos.x;
+ targetCtx->lockOnPos.y = lockOnActor->world.pos.y - (lockOnActor->shape.yOffset * lockOnActor->scale.y);
+ targetCtx->lockOnPos.z = lockOnActor->world.pos.z;
- if (targetCtx->unk4B == 0) {
- f32 temp_f0_2;
- f32 clampedFloat;
+ if (targetCtx->rotZTick == 0) {
+ f32 lockOnStep = (500.0f - targetCtx->lockOnRadius) * 3.0f;
- temp_f0_2 = (500.0f - targetCtx->unk44) * 3.0f;
- clampedFloat = CLAMP(temp_f0_2, 30.0f, 100.0f);
+ lockOnStep = CLAMP(lockOnStep, 30.0f, 100.0f);
- if (Math_StepToF(&targetCtx->unk44, 80.0f, clampedFloat)) {
- targetCtx->unk4B++;
+ if (Math_StepToF(&targetCtx->lockOnRadius, 80.0f, lockOnStep)) {
+ targetCtx->rotZTick++;
}
} else {
- targetCtx->unk4B = (targetCtx->unk4B + 3) | 0x80;
- targetCtx->unk44 = 120.0f;
+ // 0x80 is or'd to avoid getting this value be set to zero
+ // This rotation value gets multiplied by 0x200, which multiplied by 0x80 gives a full turn (0x10000)
+ targetCtx->rotZTick = (targetCtx->rotZTick + 3) | 0x80;
+ targetCtx->lockOnRadius = 120.0f;
}
} else {
- targetCtx->targetedActor = NULL;
- Math_StepToF(&targetCtx->unk44, 500.0f, 80.0f);
+ targetCtx->lockOnActor = NULL;
+ Math_StepToF(&targetCtx->lockOnRadius, 500.0f, 80.0f);
}
}
@@ -1048,7 +1065,7 @@ void* Actor_FindSharedMemoryEntry(PlayState* play, s16 id) {
void Actor_Kill(Actor* actor) {
actor->draw = NULL;
actor->update = NULL;
- actor->flags &= ~ACTOR_FLAG_1;
+ actor->flags &= ~ACTOR_FLAG_TARGETABLE;
}
void Actor_SetWorldToHome(Actor* actor) {
@@ -1089,7 +1106,7 @@ void Actor_Init(Actor* actor, PlayState* play) {
Actor_SetFocus(actor, 0.0f);
Math_Vec3f_Copy(&actor->prevPos, &actor->world.pos);
Actor_SetScale(actor, 0.01f);
- actor->targetMode = 3;
+ actor->targetMode = TARGET_MODE_3;
actor->terminalVelocity = -20.0f;
actor->xyzDistToPlayerSq = FLT_MAX;
@@ -1702,18 +1719,18 @@ void Actor_UpdateBgCheckInfo(PlayState* play, Actor* actor, f32 wallCheckHeight,
}
}
-Gfx* Hilite_Draw(Vec3f* object, Vec3f* eye, Vec3f* lightDir, GraphicsContext* gfxCtx, Gfx* dl, Hilite** hilite) {
+Gfx* Hilite_Draw(Vec3f* object, Vec3f* eye, Vec3f* lightDir, GraphicsContext* gfxCtx, Gfx* dl, Hilite** hiliteP) {
LookAt* lookAt = GRAPH_ALLOC(gfxCtx, sizeof(LookAt));
f32 correctedEyeX = (eye->x == object->x) && (eye->z == object->z) ? eye->x + 0.001f : eye->x;
- *hilite = GRAPH_ALLOC(gfxCtx, sizeof(Hilite));
+ *hiliteP = GRAPH_ALLOC(gfxCtx, sizeof(Hilite));
- guLookAtHilite(&D_801ED8E0, 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,
+ guLookAtHilite(&sActorHiliteMtx, lookAt, *hiliteP, 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(dl++, lookAt);
- gDPSetHilite1Tile(dl++, 1, *hilite, 0x10, 0x10);
+ gDPSetHilite1Tile(dl++, 1, *hiliteP, 0x10, 0x10);
return dl;
}
@@ -1803,56 +1820,86 @@ PosRot* Actor_GetWorldPosShapeRot(PosRot* dest, Actor* actor) {
return dest;
}
-f32 func_800B82EC(Actor* actor, Player* player, s16 angle) {
- f32 temp_f12;
- s16 temp_v0 = BINANG_SUB(BINANG_SUB(actor->yawTowardsPlayer, 0x8000), angle);
- s16 yaw = ABS_ALT(temp_v0);
+/**
+ * Returns the squared xyz distance from the actor to Player.
+ *
+ * This distance will be adjusted smaller if Player is already targeting an actor. The more Player is facing the actor,
+ * the smaller the distance is adjusted.
+ */
+f32 Target_GetAdjustedDistSq(Actor* actor, Player* player, s16 playerShapeYaw) {
+ f32 adjDistSq;
+ s16 yawDiff;
- if (player->targetedActor != NULL) {
- if ((yaw > 0x4000) || ((actor->flags & ACTOR_FLAG_CANT_LOCK_ON))) {
+ // The yaw, with player as the origin, from where player is facing to where the actor is positioned
+ yawDiff = ABS_ALT(BINANG_SUB(BINANG_SUB(actor->yawTowardsPlayer, 0x8000), playerShapeYaw));
+
+ if (player->lockOnActor != NULL) {
+ if ((yawDiff > 0x4000) || (actor->flags & ACTOR_FLAG_CANT_LOCK_ON)) {
return FLT_MAX;
}
- temp_f12 = actor->xyzDistToPlayerSq - ((actor->xyzDistToPlayerSq * 0.8f) * ((0x4000 - yaw) * (1.0f / 0x8000)));
- return temp_f12;
+ // Linear scaling, yaw being 90 degree means it will return the original distance, 0 degree will adjust to 60%
+ // of the distance
+ adjDistSq =
+ actor->xyzDistToPlayerSq - ((actor->xyzDistToPlayerSq * 0.8f) * ((0x4000 - yawDiff) * (1.0f / 0x8000)));
+ return adjDistSq;
}
- if (yaw >= 0x2AAB) {
+ if (yawDiff > (0x10000 / 6)) {
return FLT_MAX;
}
return actor->xyzDistToPlayerSq;
}
#define TARGET_RANGE(range, leash) \
- { SQ(range), (f32)range / leash }
-
-TargetRangeParams gTargetRanges[] = {
- 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), TARGET_RANGE(2500, 3750),
+ { SQ(range), (f32)(range) / (leash) }
+
+TargetRangeParams gTargetRanges[TARGET_MODE_MAX] = {
+ TARGET_RANGE(70, 140), // TARGET_MODE_0
+ TARGET_RANGE(170, 255), // TARGET_MODE_1
+ TARGET_RANGE(280, 5600), // TARGET_MODE_2
+ TARGET_RANGE(350, 525), // TARGET_MODE_3
+ TARGET_RANGE(700, 1050), // TARGET_MODE_4
+ TARGET_RANGE(1000, 1500), // TARGET_MODE_5
+ TARGET_RANGE(100, 105.36842), // TARGET_MODE_6
+ TARGET_RANGE(140, 163.33333), // TARGET_MODE_7
+ TARGET_RANGE(240, 576), // TARGET_MODE_8
+ TARGET_RANGE(280, 280000), // TARGET_MODE_9
+ TARGET_RANGE(2500, 3750), // TARGET_MODE_10
};
-s32 func_800B83BC(Actor* actor, f32 arg1) {
- return arg1 < gTargetRanges[actor->targetMode].rangeSq;
+/**
+ * Checks if an actor at distance `distSq` is inside the range specified by its targetMode
+ */
+s32 Target_IsActorInRange(Actor* actor, f32 distSq) {
+ return distSq < gTargetRanges[actor->targetMode].rangeSq;
}
-s32 func_800B83F8(Actor* actor, Player* player, s32 flag) {
- if ((actor->update == NULL) || !(actor->flags & ACTOR_FLAG_1) || (actor->flags & ACTOR_FLAG_CANT_LOCK_ON)) {
+/**
+ * Returns true if the actor is outside the leash distance to player.
+ *
+ * Passing true to ignoreLeash avoids the distance and yaw checks, and considers the actor inside the leash distance.
+ */
+s32 Target_OutsideLeashRange(Actor* actor, Player* player, s32 ignoreLeash) {
+ if ((actor->update == NULL) || !(actor->flags & ACTOR_FLAG_TARGETABLE) ||
+ (actor->flags & ACTOR_FLAG_CANT_LOCK_ON)) {
return true;
}
- if (!flag) {
- s16 yaw = BINANG_SUB(actor->yawTowardsPlayer, 0x8000) - player->actor.shape.rot.y;
- s16 phi_v1 = ABS_ALT(yaw);
- f32 dist;
+ if (!ignoreLeash) {
+ s16 yawDiff;
+ f32 distSq;
- if ((player->targetedActor == NULL) && (phi_v1 >= 0x2AAB)) {
- dist = FLT_MAX;
+ // The yaw, with player as the origin, from where player is facing to where the actor is positioned
+ yawDiff = ABS_ALT(BINANG_SUB(BINANG_SUB(actor->yawTowardsPlayer, 0x8000), player->actor.shape.rot.y));
+
+ if ((player->lockOnActor == NULL) && (yawDiff > (0x10000 / 6))) {
+ distSq = FLT_MAX;
} else {
- dist = actor->xyzDistToPlayerSq;
+ distSq = actor->xyzDistToPlayerSq;
}
- return !func_800B83BC(actor, gTargetRanges[actor->targetMode].leashScale * dist);
+ return !Target_IsActorInRange(actor, gTargetRanges[actor->targetMode].leashScale * distSq);
}
return false;
@@ -1911,7 +1958,7 @@ s32 Actor_OfferTalkExchange(Actor* actor, PlayState* play, f32 xzRange, f32 yRan
if ((player->actor.flags & ACTOR_FLAG_TALK_REQUESTED) ||
((exchangeItemAction > PLAYER_IA_NONE) && Player_InCsMode(play)) ||
- (!actor->isTargeted &&
+ (!actor->isLockedOn &&
((fabsf(actor->playerHeightRel) > fabsf(yRange)) || (actor->xzDistToPlayer > player->talkActorDistance) ||
(xzRange < actor->xzDistToPlayer)))) {
return false;
@@ -1971,7 +2018,7 @@ s32 Actor_ChangeFocus(Actor* actor1, PlayState* play, Actor* actor2) {
if ((player->actor.flags & ACTOR_FLAG_TALK_REQUESTED) && (talkActor != NULL)) {
player->talkActor = actor2;
- player->targetedActor = actor2;
+ player->lockOnActor = actor2;
return true;
}
@@ -2372,7 +2419,7 @@ void Actor_InitContext(PlayState* play, ActorContext* actorCtx, ActorEntry* acto
actorCtx->absoluteSpace = NULL;
Actor_SpawnEntry(actorCtx, actorEntry, play);
- Actor_TargetContextInit(&actorCtx->targetContext, actorCtx->actorLists[ACTORCAT_PLAYER].first, play);
+ Target_Init(&actorCtx->targetCtx, actorCtx->actorLists[ACTORCAT_PLAYER].first, play);
Actor_InitHalfDaysBit(actorCtx);
Fault_AddClient(&sActorFaultClient, (void*)Actor_PrintLists, actorCtx, NULL);
Actor_SpawnHorse(play, (Player*)actorCtx->actorLists[ACTORCAT_PLAYER].first);
@@ -2473,13 +2520,13 @@ Actor* Actor_UpdateActor(UpdateActor_Params* params) {
actor->flags &= ~ACTOR_FLAG_1000000;
if ((DECR(actor->freezeTimer) == 0) && (actor->flags & params->unk_18)) {
- if (actor == params->player->targetedActor) {
- actor->isTargeted = true;
+ if (actor == params->player->lockOnActor) {
+ actor->isLockedOn = true;
} else {
- actor->isTargeted = false;
+ actor->isLockedOn = false;
}
- if ((actor->targetPriority != 0) && (params->player->targetedActor == NULL)) {
+ if ((actor->targetPriority != 0) && (params->player->lockOnActor == NULL)) {
actor->targetPriority = 0;
}
@@ -2604,22 +2651,22 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
}
}
- actor = player->targetedActor;
+ actor = player->lockOnActor;
if ((actor != NULL) && (actor->update == NULL)) {
actor = NULL;
- func_80123DA4(player);
+ Player_Untarget(player);
}
if ((actor == NULL) || (player->unk_738 < 5)) {
actor = NULL;
- if (actorCtx->targetContext.unk4B != 0) {
- actorCtx->targetContext.unk4B = 0;
+ if (actorCtx->targetCtx.rotZTick != 0) {
+ actorCtx->targetCtx.rotZTick = 0;
Audio_PlaySfx(NA_SE_SY_LOCK_OFF);
}
}
if (!(player->stateFlags1 & PLAYER_STATE1_2)) {
- func_800B5814(&actorCtx->targetContext, player, actor, &play->state);
+ Target_Update(&actorCtx->targetCtx, player, actor, play);
}
TitleCard_Update(&play->state, &actorCtx->titleCtxt);
@@ -3396,21 +3443,21 @@ Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) {
Actor* newHead;
ActorOverlay* overlayEntry = actor->overlayEntry;
- if ((player != NULL) && (actor == player->targetedActor)) {
- func_80123DA4(player);
+ if ((player != NULL) && (actor == player->lockOnActor)) {
+ Player_Untarget(player);
Camera_ChangeMode(Play_GetCamera(play, Play_GetActiveCamId(play)), CAM_MODE_NORMAL);
}
- if (actor == actorCtx->targetContext.arrowPointedActor) {
- actorCtx->targetContext.arrowPointedActor = NULL;
+ if (actor == actorCtx->targetCtx.fairyActor) {
+ actorCtx->targetCtx.fairyActor = NULL;
}
- if (actor == actorCtx->targetContext.unk8C) {
- actorCtx->targetContext.unk8C = NULL;
+ if (actor == actorCtx->targetCtx.forcedTargetActor) {
+ actorCtx->targetCtx.forcedTargetActor = NULL;
}
- if (actor == actorCtx->targetContext.bgmEnemy) {
- actorCtx->targetContext.bgmEnemy = NULL;
+ if (actor == actorCtx->targetCtx.bgmEnemy) {
+ actorCtx->targetCtx.bgmEnemy = NULL;
}
AudioSfx_StopByPos(&actor->projectedPos);
@@ -3427,7 +3474,7 @@ Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) {
return newHead;
}
-s32 func_800BB59C(PlayState* play, Actor* actor) {
+s32 Target_InTargetableScreenRegion(PlayState* play, Actor* actor) {
s16 x;
s16 y;
@@ -3436,110 +3483,156 @@ s32 func_800BB59C(PlayState* play, Actor* actor) {
return (x > -20) && (x < gScreenWidth + 20) && (y > -160) && (y < gScreenHeight + 160);
}
-void func_800BB604(GameState* gameState, ActorContext* actorCtx, Player* player, s32 actorCategory) {
- PlayState* play = (PlayState*)gameState;
- f32 temp_f0_2;
- Actor* targetedActor;
- Actor* actor;
- s32 phi_s2;
- CollisionPoly* sp80;
- s32 sp7C;
- Vec3f sp70;
+/**
+ * Search for targetable actors of the `actorCategory` category.
+ *
+ * Looks for the actor of said category with higher targetPriority and the one that is nearest to player. This actor
+ * must be within the range (relative to player) speicified by its targetMode.
+ *
+ * The actor must be on-screen
+ *
+ * The highest priority actor is stored in `sTargetablePrioritizedActor`, while the nearest actor is stored in
+ * `sTargetableNearestActor`. The higher priority / smaller distance of those actors are stored in
+ * `sTargetablePrioritizedPriority` and `sTargetableNearestActorDistSq`.
+ *
+ * There is not much info to infer anything about ACTOR_FLAG_40000000, D_801ED8C4/D_801ED8C0, D_801ED8D8/D_801ED8D0.
+ * All appear unused in any meaningful way.
+ *
+ * For an actor to be taken in consideration by this function it needs:
+ * - Non-NULL update function (maybe obvious?)
+ * - Not be Player itself.
+ * - It must be targetable or ACTOR_FLAG_40000000
+ * - Not be the already targeted actor, unless it has the ACTOR_FLAG_80000 flag
+ * - Be withing the range specified by its targetMode.
+ * - It must be on-screen (within a margin)
+ * - Must not be blocked by a surface (?)
+ *
+ * This function also checks for the nearest enemy actor, which allows determining if enemy background music should be
+ * played. This actor is stored in `targetContext.bgmEnemy` and its distance is stored in `sBgmEnemyDistSq`
+ *
+ * This function is expected to be called with almost every actor category in each cycle. On a new cycle its global
+ * variables must be reset by the caller, otherwise the information of the previous cycle will be retained on this one.
+ */
+void Target_FindTargetableActorForCategory(PlayState* play, ActorContext* actorCtx, Player* player,
+ ActorType actorCategory) {
+ f32 distSq;
+ Actor* actor = actorCtx->actorLists[actorCategory].first;
+ Actor* lockOnActor = player->lockOnActor;
+ s32 isNearestTargetableActor;
s32 phi_s2_2;
- actor = actorCtx->actorLists[actorCategory].first;
- targetedActor = player->targetedActor;
- while (actor != NULL) {
- if ((actor->update != NULL) && ((Player*)actor != player)) {
- if (actor->flags & (ACTOR_FLAG_40000000 | ACTOR_FLAG_1)) {
- if ((actorCategory == ACTORCAT_ENEMY) && CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_4 | ACTOR_FLAG_1)) {
- if ((actor->xyzDistToPlayerSq < SQ(500.0f)) && (actor->xyzDistToPlayerSq < sBgmEnemyDistSq)) {
- actorCtx->targetContext.bgmEnemy = actor;
- sBgmEnemyDistSq = actor->xyzDistToPlayerSq;
- }
- }
+ for (; actor != NULL; actor = actor->next) {
+ if ((actor->update == NULL) || ((Player*)actor == player)) {
+ continue;
+ }
- if ((actor != targetedActor) || (actor->flags & ACTOR_FLAG_80000)) {
- temp_f0_2 = func_800B82EC(actor, player, D_801ED8DC);
- phi_s2_2 = (actor->flags & ACTOR_FLAG_1) != 0;
- if (phi_s2_2) {
- phi_s2_2 = temp_f0_2 < D_801ED8C8;
- }
- phi_s2 = phi_s2_2;
- phi_s2_2 = (actor->flags & ACTOR_FLAG_40000000) != 0;
- if (phi_s2_2) {
- phi_s2_2 = temp_f0_2 < D_801ED8D0;
- }
+ // Actor must be at least either targetable or ACTOR_FLAG_40000000
+ if (!(actor->flags & (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_40000000))) {
+ continue;
+ }
- if (((phi_s2) || (phi_s2_2)) && (func_800B83BC(actor, temp_f0_2))) {
- if (func_800BB59C(play, actor)) {
- if (((!BgCheck_CameraLineTest1(&play->colCtx, &player->actor.focus.pos, &actor->focus.pos,
- &sp70, &sp80, true, true, true, true, &sp7C)) ||
- (SurfaceType_IsIgnoredByProjectiles(&play->colCtx, sp80, sp7C)))) {
- if (actor->targetPriority != 0) {
- if ((phi_s2 != 0) && (actor->targetPriority < D_801ED8D4)) {
- D_801ED8BC = actor;
- D_801ED8D4 = actor->targetPriority;
- }
- if ((phi_s2_2 != 0) && (actor->targetPriority < D_801ED8D8)) {
- D_801ED8C4 = actor;
- D_801ED8D8 = actor->targetPriority;
- }
- } else {
- if (phi_s2 != 0) {
- D_801ED8B8 = actor;
- D_801ED8C8 = temp_f0_2;
- }
- if (phi_s2_2 != 0) {
- D_801ED8C0 = actor;
- D_801ED8D0 = temp_f0_2;
- }
- }
- }
- }
- }
- }
+ // Determine the closest enemy actor to player within a range. Used for playing enemy background music.
+ if ((actorCategory == ACTORCAT_ENEMY) &&
+ CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY)) {
+ if ((actor->xyzDistToPlayerSq < SQ(500.0f)) && (actor->xyzDistToPlayerSq < sBgmEnemyDistSq)) {
+ actorCtx->targetCtx.bgmEnemy = actor;
+ sBgmEnemyDistSq = actor->xyzDistToPlayerSq;
}
}
- actor = actor->next;
+ // If this actor is the currently targeted one, then ignore it unless it has the ACTOR_FLAG_80000 flag
+ if ((actor == lockOnActor) && !(actor->flags & ACTOR_FLAG_80000)) {
+ continue;
+ }
+
+ distSq = Target_GetAdjustedDistSq(actor, player, sTargetPlayerRotY);
+
+ isNearestTargetableActor = (actor->flags & ACTOR_FLAG_TARGETABLE) && (distSq < sTargetableNearestActorDistSq);
+ phi_s2_2 = (actor->flags & ACTOR_FLAG_40000000) && (distSq < D_801ED8D0);
+
+ if (!isNearestTargetableActor && !phi_s2_2) {
+ continue;
+ }
+
+ if (Target_IsActorInRange(actor, distSq) && Target_InTargetableScreenRegion(play, actor)) {
+ CollisionPoly* poly;
+ s32 bgId;
+ Vec3f posResult;
+
+ if (BgCheck_CameraLineTest1(&play->colCtx, &player->actor.focus.pos, &actor->focus.pos, &posResult, &poly,
+ true, true, true, true, &bgId)) {
+ if (!SurfaceType_IsIgnoredByProjectiles(&play->colCtx, poly, bgId)) {
+ continue;
+ }
+ }
+
+ if (actor->targetPriority != 0) {
+ if (isNearestTargetableActor && (actor->targetPriority < sTargetablePrioritizedPriority)) {
+ sTargetablePrioritizedActor = actor;
+ sTargetablePrioritizedPriority = actor->targetPriority;
+ }
+ if (phi_s2_2 && (actor->targetPriority < D_801ED8D8)) {
+ D_801ED8C4 = actor;
+ D_801ED8D8 = actor->targetPriority;
+ }
+ } else {
+ if (isNearestTargetableActor) {
+ sTargetableNearestActor = actor;
+ sTargetableNearestActorDistSq = distSq;
+ }
+ if (phi_s2_2) {
+ D_801ED8C0 = actor;
+ D_801ED8D0 = distSq;
+ }
+ }
+ }
}
}
-u8 D_801AED8C[] = {
+u8 sTargetableActorCategories[] = {
ACTORCAT_BOSS, ACTORCAT_ENEMY, ACTORCAT_BG, ACTORCAT_EXPLOSIVES, ACTORCAT_NPC, ACTORCAT_ITEMACTION,
ACTORCAT_CHEST, ACTORCAT_SWITCH, ACTORCAT_PROP, ACTORCAT_MISC, ACTORCAT_DOOR, ACTORCAT_SWITCH,
};
-void func_800BB8EC(GameState* gameState, ActorContext* actorCtx, Actor** arg2, Actor** arg3, Player* player) {
+/**
+ * Search for the nearest targetable actor.
+ *
+ * The specific criteria is specified in Target_FindTargetableActorForCategory.
+ *
+ * The actor found is stored in the targetableP parameter. It may be NULL if no actor that fulfills the criteria is
+ * found.
+ */
+void Target_GetTargetActor(PlayState* play, ActorContext* actorCtx, Actor** targetableP, Actor** arg3, Player* player) {
u8* actorCategories;
s32 i;
- D_801ED8B8 = D_801ED8BC = D_801ED8C0 = D_801ED8C4 = NULL;
- D_801ED8C8 = D_801ED8D0 = sBgmEnemyDistSq = FLT_MAX;
- D_801ED8D4 = D_801ED8D8 = INT32_MAX;
+ sTargetableNearestActor = sTargetablePrioritizedActor = D_801ED8C0 = D_801ED8C4 = NULL;
+ sTargetableNearestActorDistSq = D_801ED8D0 = sBgmEnemyDistSq = FLT_MAX;
+ sTargetablePrioritizedPriority = D_801ED8D8 = INT32_MAX;
- actorCtx->targetContext.bgmEnemy = NULL;
- D_801ED8DC = player->actor.shape.rot.y;
+ actorCtx->targetCtx.bgmEnemy = NULL;
+ sTargetPlayerRotY = player->actor.shape.rot.y;
- actorCategories = D_801AED8C;
+ actorCategories = sTargetableActorCategories;
+ // Try to search for a targetable actor that's a Boss, Enemy or Bg first
for (i = 0; i < 3; i++) {
- func_800BB604(gameState, actorCtx, player, *actorCategories);
+ Target_FindTargetableActorForCategory(play, actorCtx, player, *actorCategories);
actorCategories++;
}
- if (D_801ED8B8 == NULL) {
- for (; i < ARRAY_COUNT(D_801AED8C); i++) {
- func_800BB604(gameState, actorCtx, player, *actorCategories);
+ // If no actor in the above categories was found then try to search for one in every other category
+ if (sTargetableNearestActor == NULL) {
+ for (; i < ARRAY_COUNT(sTargetableActorCategories); i++) {
+ Target_FindTargetableActorForCategory(play, actorCtx, player, *actorCategories);
actorCategories++;
}
}
- if (D_801ED8B8 == NULL) {
- *arg2 = D_801ED8BC;
+ if (sTargetableNearestActor == NULL) {
+ *targetableP = sTargetablePrioritizedActor;
} else {
- *arg2 = D_801ED8B8;
+ *targetableP = sTargetableNearestActor;
}
if (D_801ED8C0 == NULL) {
@@ -3810,7 +3903,7 @@ s16 Actor_TestFloorInDirection(Actor* actor, PlayState* play, f32 distance, s16
s32 Actor_IsTargeted(PlayState* play, Actor* actor) {
Player* player = GET_PLAYER(play);
- if ((player->stateFlags3 & PLAYER_STATE3_80000000) && actor->isTargeted) {
+ if ((player->stateFlags3 & PLAYER_STATE3_80000000) && actor->isLockedOn) {
return true;
}
@@ -3823,7 +3916,7 @@ s32 Actor_IsTargeted(PlayState* play, Actor* actor) {
s32 Actor_OtherIsTargeted(PlayState* play, Actor* actor) {
Player* player = GET_PLAYER(play);
- if ((player->stateFlags3 & PLAYER_STATE3_80000000) && !actor->isTargeted) {
+ if ((player->stateFlags3 & PLAYER_STATE3_80000000) && !actor->isLockedOn) {
return true;
}
@@ -4481,10 +4574,10 @@ s16 func_800BDB6C(Actor* actor, PlayState* play, s16 arg2, f32 arg3) {
}
if (arg3 < phi_f2) {
- actor->flags &= ~ACTOR_FLAG_1;
+ actor->flags &= ~ACTOR_FLAG_TARGETABLE;
Math_SmoothStepToS(&arg2, 0, 6, 0x14, 1);
} else {
- actor->flags |= ACTOR_FLAG_1;
+ actor->flags |= ACTOR_FLAG_TARGETABLE;
Math_SmoothStepToS(&arg2, 0xFF, 6, 0x14, 1);
}
diff --git a/src/code/z_en_a_keep.c b/src/code/z_en_a_keep.c
index 3f9f6b90e..1fa4d4cf2 100644
--- a/src/code/z_en_a_keep.c
+++ b/src/code/z_en_a_keep.c
@@ -1,7 +1,7 @@
#include "global.h"
#include "assets/objects/gameplay_keep/gameplay_keep.h"
-#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_8)
+#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
#define THIS ((EnAObj*)thisx)
@@ -46,7 +46,7 @@ static ColliderCylinderInit sCylinderInit = {
};
static InitChainEntry sInitChain[] = {
- ICHAIN_U8(targetMode, 0, ICHAIN_STOP),
+ ICHAIN_U8(targetMode, TARGET_MODE_0, ICHAIN_STOP),
};
void EnAObj_Init(Actor* thisx, PlayState* play) {
diff --git a/src/code/z_en_hy_code.c b/src/code/z_en_hy_code.c
index 02666fc4c..e2f31c404 100644
--- a/src/code/z_en_hy_code.c
+++ b/src/code/z_en_hy_code.c
@@ -231,7 +231,7 @@ s32 func_800F0DD4(EnHy* enHy, PlayState* play, s16 arg2, s16 arg3) {
enHy->actor.shape.rot.y = Math_Vec3f_Yaw(&enHy->actor.world.pos, &door->knobDoor.dyna.actor.world.pos);
enHy->actor.world.rot.y = enHy->actor.shape.rot.y;
enHy->actor.gravity = 0.0f;
- enHy->actor.flags &= ~ACTOR_FLAG_1;
+ enHy->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
}
}
return ret;
@@ -239,7 +239,7 @@ s32 func_800F0DD4(EnHy* enHy, PlayState* play, s16 arg2, s16 arg3) {
s32 EnHy_SetPointFowards(EnHy* enHy, PlayState* play, f32 gravity, s16 animIndex) {
enHy->actor.gravity = gravity;
- enHy->actor.flags |= ACTOR_FLAG_1;
+ enHy->actor.flags |= ACTOR_FLAG_TARGETABLE;
EnHy_ChangeObjectAndAnim(enHy, play, animIndex);
enHy->curPoint++;
return false;
diff --git a/src/code/z_parameter.c b/src/code/z_parameter.c
index cd458e331..3ba6a9e99 100644
--- a/src/code/z_parameter.c
+++ b/src/code/z_parameter.c
@@ -6400,7 +6400,7 @@ void Interface_Draw(PlayState* play) {
Minimap_Draw(play);
if ((R_PAUSE_BG_PRERENDER_STATE != 2) && (R_PAUSE_BG_PRERENDER_STATE != 3)) {
- Actor_DrawZTarget(&play->actorCtx.targetContext, play);
+ Target_Draw(&play->actorCtx.targetCtx, play);
}
Gfx_SetupDL39_Overlay(play->state.gfxCtx);
diff --git a/src/code/z_player_call.c b/src/code/z_player_call.c
index a109dab17..44427d54c 100644
--- a/src/code/z_player_call.c
+++ b/src/code/z_player_call.c
@@ -1,9 +1,9 @@
#include "prevent_bss_reordering.h"
#include "global.h"
-#define FLAGS \
- (ACTOR_FLAG_1 | ACTOR_FLAG_8 | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_200000 | ACTOR_FLAG_2000000 | \
- ACTOR_FLAG_CAN_PRESS_SWITCH | ACTOR_FLAG_80000000)
+#define FLAGS \
+ (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_200000 | \
+ ACTOR_FLAG_2000000 | ACTOR_FLAG_CAN_PRESS_SWITCH | ACTOR_FLAG_80000000)
ActorFunc sPlayerCallInitFunc;
ActorFunc sPlayerCallDestroyFunc;
diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c
index cd91ee42d..e272bbfea 100644
--- a/src/code/z_player_lib.c
+++ b/src/code/z_player_lib.c
@@ -518,7 +518,7 @@ s32 func_80123448(PlayState* play) {
Player* player = GET_PLAYER(play);
return (player->stateFlags1 & PLAYER_STATE1_400000) &&
- (player->transformation != PLAYER_FORM_HUMAN || (!func_80123434(player) && player->targetedActor == NULL));
+ (player->transformation != PLAYER_FORM_HUMAN || (!func_80123434(player) && player->lockOnActor == NULL));
}
// TODO: Player_IsGoronOrDeku is a temporary name until we have more info on this function.
@@ -1315,9 +1315,8 @@ void Player_UpdateBottleHeld(PlayState* play, Player* player, ItemId itemId, Pla
player->itemAction = itemAction;
}
-// Player_Untarget / Player_StopTargeting?
-void func_80123DA4(Player* player) {
- player->targetedActor = NULL;
+void Player_Untarget(Player* player) {
+ player->lockOnActor = NULL;
player->stateFlags2 &= ~PLAYER_STATE2_2000;
}
@@ -1335,14 +1334,14 @@ void func_80123DC0(Player* player) {
~(PLAYER_STATE1_8000 | PLAYER_STATE1_10000 | PLAYER_STATE1_20000 | PLAYER_STATE1_40000000);
}
- func_80123DA4(player);
+ Player_Untarget(player);
}
void func_80123E90(PlayState* play, Actor* actor) {
Player* player = GET_PLAYER(play);
func_80123DC0(player);
- player->targetedActor = actor;
+ player->lockOnActor = actor;
player->unk_A78 = actor;
player->stateFlags1 |= PLAYER_STATE1_10000;
Camera_SetViewParam(Play_GetCamera(play, CAM_ID_MAIN), CAM_VIEW_TARGET, actor);
diff --git a/src/code/z_sub_s.c b/src/code/z_sub_s.c
index 427cc85d0..4baff41ce 100644
--- a/src/code/z_sub_s.c
+++ b/src/code/z_sub_s.c
@@ -865,7 +865,7 @@ s32 SubS_Offer(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, s32 itemI
case SUBS_OFFER_MODE_AUTO_TARGETED:
//! @bug: Both x and y conditionals are always true, || should be an &&
if (((x >= 0) || (x < SCREEN_WIDTH)) && ((y >= 0) || (y < SCREEN_HEIGHT)) &&
- (fabsf(actor->playerHeightRel) <= yRange) && (actor->xzDistToPlayer <= xzRange) && actor->isTargeted) {
+ (fabsf(actor->playerHeightRel) <= yRange) && (actor->xzDistToPlayer <= xzRange) && actor->isLockedOn) {
actor->flags |= ACTOR_FLAG_10000;
canAccept = Actor_OfferTalkExchange(actor, play, xzRange, yRange, itemId);
}