diff --git a/assets/xml/objects/object_ikana_obj.xml b/assets/xml/objects/object_ikana_obj.xml
index 6040495ab8..e0490a3495 100644
--- a/assets/xml/objects/object_ikana_obj.xml
+++ b/assets/xml/objects/object_ikana_obj.xml
@@ -17,15 +17,15 @@
-
+
-
-
+
+
-
+
-
-
+
+
@@ -39,7 +39,7 @@
-
+
@@ -51,11 +51,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/spec b/spec
index 251581be37..eda0cfe476 100644
--- a/spec
+++ b/spec
@@ -4137,8 +4137,7 @@ beginseg
name "ovl_Bg_Ikana_Mirror"
compress
include "build/src/overlays/actors/ovl_Bg_Ikana_Mirror/z_bg_ikana_mirror.o"
- include "build/data/ovl_Bg_Ikana_Mirror/ovl_Bg_Ikana_Mirror.data.o"
- include "build/data/ovl_Bg_Ikana_Mirror/ovl_Bg_Ikana_Mirror.reloc.o"
+ include "build/src/overlays/actors/ovl_Bg_Ikana_Mirror/ovl_Bg_Ikana_Mirror_reloc.o"
endseg
beginseg
diff --git a/src/overlays/actors/ovl_Bg_Ikana_Mirror/z_bg_ikana_mirror.c b/src/overlays/actors/ovl_Bg_Ikana_Mirror/z_bg_ikana_mirror.c
index 0a3b7b4456..cfa67eb1de 100644
--- a/src/overlays/actors/ovl_Bg_Ikana_Mirror/z_bg_ikana_mirror.c
+++ b/src/overlays/actors/ovl_Bg_Ikana_Mirror/z_bg_ikana_mirror.c
@@ -2,9 +2,15 @@
* File: z_bg_ikana_mirror.c
* Overlay: ovl_Bg_Ikana_Mirror
* Description: Stone Tower Temple - Mirror
+ *
+ * This mirror absorbs light reflected by the mirror shield or by another mirror of the same kind for a
+ * maximum of 400 frames (20 seconds) to then release light for the same number of frames it was charged. This number
+ * of frames is stored in the actor struct's lightRayCharge field and is updated in the BgIkanaMirror_Wait and
+ * BgIkanaMirror_EmitLight functions both described below.
*/
#include "z_bg_ikana_mirror.h"
+#include "objects/object_ikana_obj/object_ikana_obj.h"
#define FLAGS (ACTOR_FLAG_10)
@@ -15,7 +21,11 @@ void BgIkanaMirror_Destroy(Actor* thisx, PlayState* play);
void BgIkanaMirror_Update(Actor* thisx, PlayState* play);
void BgIkanaMirror_Draw(Actor* thisx, PlayState* play);
-#if 0
+void BgIkanaMirror_SetupWait(BgIkanaMirror* this);
+void BgIkanaMirror_Wait(BgIkanaMirror* this, PlayState* play);
+void BgIkanaMirror_SetupEmitLight(BgIkanaMirror* this);
+void BgIkanaMirror_EmitLight(BgIkanaMirror* this, PlayState* play);
+
const ActorInit Bg_Ikana_Mirror_InitVars = {
ACTOR_BG_IKANA_MIRROR,
ACTORCAT_PROP,
@@ -28,99 +38,371 @@ const ActorInit Bg_Ikana_Mirror_InitVars = {
(ActorFunc)BgIkanaMirror_Draw,
};
-// static ColliderTrisElementInit sTrisElementsInit[9] = {
-static ColliderTrisElementInit D_80B7FF50[9] = {
+static ColliderTrisElementInit sMirrorColliderElementsInit[] = {
{
- { ELEMTYPE_UNK4, { 0x00000000, 0x00, 0x00 }, { 0x00200000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { { { 0.0f, 21.600000381469727f, 13.699999809265137f }, { -25.299999237060547f, 6.0f, 8.399999618530273f }, { 25.299999237060547f, 6.0f, 8.399999618530273f } } },
+ {
+ ELEMTYPE_UNK4,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00200000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { { { 0.0f, 21.6f, 13.7f }, { -25.3f, 6.0f, 8.4f }, { 25.3f, 6.0f, 8.4f } } },
},
{
- { ELEMTYPE_UNK4, { 0x00000000, 0x00, 0x00 }, { 0x00200000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { { { 0.0f, 45.0f, 13.699999809265137f }, { -25.299999237060547f, 6.0f, 8.399999618530273f }, { 0.0f, 21.600000381469727f, 13.699999809265137f } } },
+ {
+ ELEMTYPE_UNK4,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00200000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { { { 0.0f, 45.0f, 13.7f }, { -25.3f, 6.0f, 8.4f }, { 0.0f, 21.6f, 13.7f } } },
},
{
- { ELEMTYPE_UNK4, { 0x00000000, 0x00, 0x00 }, { 0x00200000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { { { 0.0f, 45.0f, 13.699999809265137f }, { 0.0f, 21.600000381469727f, 13.699999809265137f }, { 25.299999237060547f, 6.0f, 8.399999618530273f } } },
+ {
+ ELEMTYPE_UNK4,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00200000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { { { 0.0f, 45.0f, 13.7f }, { 0.0f, 21.6f, 13.7f }, { 25.3f, 6.0f, 8.4f } } },
},
{
- { ELEMTYPE_UNK4, { 0x00000000, 0x00, 0x00 }, { 0x00200000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { { { 0.0f, 45.0f, 13.699999809265137f }, { -25.299999237060547f, 45.0f, 8.399999618530273f }, { -25.299999237060547f, 6.0f, 8.399999618530273f } } },
+ {
+ ELEMTYPE_UNK4,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00200000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { { { 0.0f, 45.0f, 13.7f }, { -25.3f, 45.0f, 8.4f }, { -25.3f, 6.0f, 8.4f } } },
},
{
- { ELEMTYPE_UNK4, { 0x00000000, 0x00, 0x00 }, { 0x00200000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { { { 0.0f, 45.0f, 13.699999809265137f }, { 25.299999237060547f, 6.0f, 8.399999618530273f }, { 25.299999237060547f, 45.0f, 8.399999618530273f } } },
+ {
+ ELEMTYPE_UNK4,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00200000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { { { 0.0f, 45.0f, 13.7f }, { 25.3f, 6.0f, 8.4f }, { 25.3f, 45.0f, 8.4f } } },
},
{
- { ELEMTYPE_UNK4, { 0x00000000, 0x00, 0x00 }, { 0x00200000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { { { 0.0f, 45.0f, 13.699999809265137f }, { -17.899999618530273f, 64.0999984741211f, 8.399999618530273f }, { -25.299999237060547f, 45.0f, 8.399999618530273f } } },
+ {
+ ELEMTYPE_UNK4,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00200000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { { { 0.0f, 45.0f, 13.7f }, { -17.9f, 64.1f, 8.4f }, { -25.3f, 45.0f, 8.4f } } },
},
{
- { ELEMTYPE_UNK4, { 0x00000000, 0x00, 0x00 }, { 0x00200000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { { { 0.0f, 45.0f, 13.699999809265137f }, { 25.299999237060547f, 45.0f, 8.399999618530273f }, { 17.899999618530273f, 64.0999984741211f, 8.399999618530273f } } },
+ {
+ ELEMTYPE_UNK4,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00200000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { { { 0.0f, 45.0f, 13.7f }, { 25.3f, 45.0f, 8.4f }, { 17.9f, 64.1f, 8.4f } } },
},
{
- { ELEMTYPE_UNK4, { 0x00000000, 0x00, 0x00 }, { 0x00200000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { { { 0.0f, 45.0f, 13.699999809265137f }, { 0.0f, 72.0f, 8.399999618530273f }, { -17.899999618530273f, 64.0999984741211f, 8.399999618530273f } } },
+ {
+ ELEMTYPE_UNK4,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00200000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { { { 0.0f, 45.0f, 13.7f }, { 0.0f, 72.0f, 8.4f }, { -17.9f, 64.1f, 8.4f } } },
},
{
- { ELEMTYPE_UNK4, { 0x00000000, 0x00, 0x00 }, { 0x00200000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { { { 0.0f, 45.0f, 13.699999809265137f }, { 17.899999618530273f, 64.0999984741211f, 8.399999618530273f }, { 0.0f, 72.0f, 8.399999618530273f } } },
+ {
+ ELEMTYPE_UNK4,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00200000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { { { 0.0f, 45.0f, 13.7f }, { 17.9f, 64.1f, 8.4f }, { 0.0f, 72.0f, 8.4f } } },
},
};
-// static ColliderTrisInit sTrisInit = {
-static ColliderTrisInit D_80B8016C = {
- { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER | AC_TYPE_OTHER, OC1_NONE, OC2_NONE, COLSHAPE_TRIS, },
- 9, D_80B7FF50, // sTrisElementsInit,
+static ColliderTrisInit sMirrorColliderInit = {
+ {
+ COLTYPE_NONE,
+ AT_NONE,
+ AC_ON | AC_TYPE_PLAYER | AC_TYPE_OTHER,
+ OC1_NONE,
+ OC2_NONE,
+ COLSHAPE_TRIS,
+ },
+ ARRAY_COUNT(sMirrorColliderElementsInit),
+ sMirrorColliderElementsInit,
};
-// static ColliderQuadInit sQuadInit = {
-static ColliderQuadInit D_80B8017C = {
- { COLTYPE_NONE, AT_ON | AT_TYPE_OTHER, AC_NONE, OC1_NONE, OC2_NONE, COLSHAPE_QUAD, },
- { ELEMTYPE_UNK0, { 0x00200000, 0x00, 0x00 }, { 0x00000000, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NONE, BUMP_NONE, OCELEM_NONE, },
- { { { 0.0f, 72.0f, 20.0f }, { 0.0f, 72.0f, 240.0f }, { 0.0f, 6.0f, 20.0f }, { 0.0f, 6.0f, 240.0f } } },
+static ColliderQuadInit sLightRaysCollidersInit[] = {
+ {
+ {
+ COLTYPE_NONE,
+ AT_ON | AT_TYPE_OTHER,
+ AC_NONE,
+ OC1_NONE,
+ OC2_NONE,
+ COLSHAPE_QUAD,
+ },
+ {
+ ELEMTYPE_UNK0,
+ { 0x00200000, 0x00, 0x00 },
+ { 0x00000000, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NONE,
+ BUMP_NONE,
+ OCELEM_NONE,
+ },
+ { { { 0.0f, 72.0f, 20.0f }, { 0.0f, 72.0f, 240.0f }, { 0.0f, 6.0f, 20.0f }, { 0.0f, 6.0f, 240.0f } } },
+ },
+ {
+ {
+ COLTYPE_NONE,
+ AT_ON | AT_TYPE_OTHER,
+ AC_NONE,
+ OC1_NONE,
+ OC2_NONE,
+ COLSHAPE_QUAD,
+ },
+ {
+ ELEMTYPE_UNK0,
+ { 0x00200000, 0x00, 0x00 },
+ { 0x00000000, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NONE,
+ BUMP_NONE,
+ OCELEM_NONE,
+ },
+ { { { 25.3f, 20.0f, 20.0f }, { 25.3f, 20.0f, 240.0f }, { -25.3f, 20.0f, 20.0f }, { -25.3f, 20.0f, 240.0f } } },
+ }
};
-// static ColliderQuadInit sQuadInit = {
-static ColliderQuadInit D_80B801FC = {
- { 0x41, AT_NONE | AT_TYPE_OTHER, AC_NONE, OC1_NONE, OC2_FIRST_ONLY | OC2_UNK1 | OC2_HIT_PLAYER, 0x70, },
- { 0xC1, { 0x41A00000, 0x41, 0xA0 }, { 0xC1CA6666, 0x41, 0xA0 }, TOUCH_ON | TOUCH_HIT | TOUCH_SFX_NORMAL | TOUCH_DREW_HITMARK, BUMP_NONE | BUMP_NO_DAMAGE | BUMP_NO_SWORD_SFX | BUMP_NO_HITMARK, OCELEM_NONE, },
- { { { -1.8339854079840734e-09f, -1.8626939990440405e-09f, -1.9208972190654094e-09f }, { 221185.5625f, 0.0f, 0.003921568859368563f }, { 0.0f, 0.0f, 0.0f }, { 2.8698592549372254e-42f, 1.0761972206014595e-42f, 2.2420775429197073e-44f } } },
-};
-
-// static InitChainEntry sInitChain[] = {
-static InitChainEntry D_80B8021C[] = {
+static InitChainEntry sInitChain[] = {
ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneScale, 220, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneDownward, 200, ICHAIN_CONTINUE),
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP),
};
-#endif
+void BgIkanaMirror_SetQuadVertices(BgIkanaMirror* this) {
+ ColliderQuadDimInit* dim;
+ ColliderQuad* lightRaysCollider;
+ Vec3f v0;
+ Vec3f v1;
+ Vec3f v2;
+ Vec3f v3;
+ s32 i;
-extern ColliderTrisElementInit D_80B7FF50[9];
-extern ColliderTrisInit D_80B8016C;
-extern ColliderQuadInit D_80B8017C;
-extern ColliderQuadInit D_80B801FC;
-extern InitChainEntry D_80B8021C[];
+ Matrix_Push();
+ Matrix_SetTranslateRotateYXZ(this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y,
+ this->dyna.actor.world.pos.z, &this->dyna.actor.shape.rot);
+ for (i = 0; i < ARRAY_COUNT(this->lightRaysColliders); i++) {
+ dim = &sLightRaysCollidersInit[i].dim;
+ Matrix_MultVec3f(&dim->quad[0], &v0);
+ Matrix_MultVec3f(&dim->quad[1], &v1);
+ Matrix_MultVec3f(&dim->quad[2], &v2);
+ Matrix_MultVec3f(&dim->quad[3], &v3);
+ lightRaysCollider = &this->lightRaysColliders[i];
+ Collider_SetQuadVertices(lightRaysCollider, &v0, &v1, &v2, &v3);
+ }
-extern UNK_TYPE D_06001E18;
-extern UNK_TYPE D_06002358;
+ Matrix_Pop();
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Mirror/func_80B7F730.s")
+void BgIkanaMirror_Init(Actor* thisx, PlayState* play2) {
+ PlayState* play = play2;
+ BgIkanaMirror* this = THIS;
+ ColliderTrisElementInit* element;
+ Vec3f vertices[3];
+ s32 i;
+ s32 j;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Mirror/BgIkanaMirror_Init.s")
+ Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
+ DynaPolyActor_Init(&this->dyna, 0);
+ DynaPolyActor_LoadMesh(play, &this->dyna, &gStoneTowerTempleMirrorCol);
+ Collider_InitTris(play, &this->mirrorCollider);
+ Collider_SetTris(play, &this->mirrorCollider, &this->dyna.actor, &sMirrorColliderInit,
+ this->mirrorColliderElements);
+ Matrix_SetTranslateRotateYXZ(this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y,
+ this->dyna.actor.world.pos.z, &this->dyna.actor.shape.rot);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Mirror/BgIkanaMirror_Destroy.s")
+ for (i = 0; i < ARRAY_COUNT(sMirrorColliderElementsInit); i++) {
+ element = &sMirrorColliderInit.elements[i];
+ for (j = 0; j < 3; j++) {
+ Matrix_MultVec3f(&element->dim.vtx[j], &vertices[j]);
+ }
+ Collider_SetTrisVertices(&this->mirrorCollider, i, &vertices[0], &vertices[1], &vertices[2]);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Mirror/func_80B7FA84.s")
+ for (i = 0; i < ARRAY_COUNT(this->lightRaysColliders); i++) {
+ Collider_InitQuad(play, &this->lightRaysColliders[i]);
+ Collider_SetQuad(play, &this->lightRaysColliders[i], &this->dyna.actor, &sLightRaysCollidersInit[i]);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Mirror/func_80B7FA9C.s")
+ BgIkanaMirror_SetQuadVertices(this);
+ this->lightAbsorptionTexScroll = Lib_SegmentedToVirtual(&gStoneTowerTempleMirrorLightAbsorptionTexAnim);
+ this->lightEmissionTexScroll = Lib_SegmentedToVirtual(&gStoneTowerTempleMirrorLightEmissionTexAnim);
+ BgIkanaMirror_SetupWait(this);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Mirror/func_80B7FB84.s")
+void BgIkanaMirror_Destroy(Actor* thisx, PlayState* play) {
+ BgIkanaMirror* this = THIS;
+ s32 i;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Mirror/func_80B7FBA4.s")
+ DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, this->dyna.bgId);
+ Collider_DestroyTris(play, &this->mirrorCollider);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Mirror/BgIkanaMirror_Update.s")
+ for (i = 0; i < ARRAY_COUNT(this->lightRaysColliders); i++) {
+ Collider_DestroyQuad(play, &this->lightRaysColliders[i]);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Mirror/BgIkanaMirror_Draw.s")
+void BgIkanaMirror_SetupWait(BgIkanaMirror* this) {
+ this->isEmittingLight = 0;
+ this->actionFunc = BgIkanaMirror_Wait;
+}
+
+/**
+ * Charges the mirror with light, increment the alpha value for the light absorption textures and decrement the alpha
+ * value for the light emission textures.
+ */
+void BgIkanaMirror_Wait(BgIkanaMirror* this, PlayState* play) {
+ s8 isEmittingLight;
+ s32 startEmittingLight = false;
+
+ // The light emission texture gradually fades.
+ if (this->lightEmissionAlpha > 100) {
+ this->lightEmissionAlpha -= 100;
+ } else {
+ this->lightEmissionAlpha = 0;
+ }
+
+ // This checks if light is touching the mirror.
+ if (this->mirrorCollider.base.acFlags & AC_HIT) {
+ this->mirrorCollider.base.acFlags &= ~AC_HIT;
+ this->isEmittingLight = 0;
+
+ if (this->lightRayCharge < 400) {
+ this->lightRayCharge++;
+ }
+
+ if (this->lightAbsorptionAlpha < 195) {
+ this->lightAbsorptionAlpha += 60;
+ } else {
+ this->lightAbsorptionAlpha = 255;
+ }
+
+ } else {
+ isEmittingLight = this->isEmittingLight;
+
+ if (isEmittingLight > 0) {
+ startEmittingLight = true;
+ } else if (this->lightRayCharge > 0) {
+ this->isEmittingLight = isEmittingLight + 1;
+ }
+ }
+
+ if (startEmittingLight) {
+ BgIkanaMirror_SetupEmitLight(this);
+ } else {
+ CollisionCheck_SetAC(play, &play->colChkCtx, &this->mirrorCollider.base);
+ }
+}
+
+void BgIkanaMirror_SetupEmitLight(BgIkanaMirror* this) {
+ this->dyna.actor.flags |= ACTOR_FLAG_20;
+ this->actionFunc = BgIkanaMirror_EmitLight;
+}
+
+/**
+ * Depletes the mirror's light and release it, increase alpha value for the light
+ * emission textures and decrease the alpha value for the light absorption textures.
+ */
+void BgIkanaMirror_EmitLight(BgIkanaMirror* this, PlayState* play) {
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(this->lightRaysColliders); i++) {
+ if (this->lightRaysColliders[i].base.atFlags & AT_HIT) {
+ this->lightRaysColliders[i].base.atFlags &= ~AT_HIT;
+ }
+ }
+
+ if (this->lightEmissionAlpha < 155) {
+ this->lightEmissionAlpha += 100;
+ } else {
+ this->lightEmissionAlpha = 255;
+ }
+
+ if (this->lightAbsorptionAlpha > 60) {
+ this->lightAbsorptionAlpha -= 60;
+ } else {
+ this->lightAbsorptionAlpha = 0;
+ }
+
+ if (this->lightRayCharge > 0) {
+ this->lightRayCharge--;
+
+ for (i = 0; i < ARRAY_COUNT(this->lightRaysColliders); i++) {
+ CollisionCheck_SetAT(play, &play->colChkCtx, &this->lightRaysColliders[i].base);
+ }
+
+ } else {
+ this->dyna.actor.flags &= ~ACTOR_FLAG_20;
+ BgIkanaMirror_SetupWait(this);
+ }
+}
+
+void BgIkanaMirror_Update(Actor* thisx, PlayState* play) {
+ BgIkanaMirror* this = THIS;
+
+ this->actionFunc(this, play);
+}
+
+void BgIkanaMirror_Draw(Actor* thisx, PlayState* play) {
+ s32 pad;
+ BgIkanaMirror* this = THIS;
+
+ OPEN_DISPS(play->state.gfxCtx);
+ func_8012C28C(play->state.gfxCtx);
+ func_8012C2DC(play->state.gfxCtx);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, gStoneTowerTempleMirrorDL);
+
+ if (this->lightAbsorptionAlpha > 0) {
+ AnimatedMat_Draw(play, this->lightAbsorptionTexScroll);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 255, this->lightAbsorptionAlpha);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, gStoneTowerTempleMirrorLightAbsorptionDL);
+ }
+
+ if (this->lightEmissionAlpha > 0) {
+ f32 alphaFraction = this->lightEmissionAlpha * (1.0f / 255.0f);
+ s32 primColorAlpha = (s32)(alphaFraction * 123.0f);
+ s32 envColorAlpha = (s32)(alphaFraction * 185.0f);
+
+ AnimatedMat_Draw(play, this->lightEmissionTexScroll);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 255, primColorAlpha);
+ gDPSetEnvColor(POLY_XLU_DISP++, 215, 215, 255, envColorAlpha);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, gStoneTowerTempleMirrorLightEmissionDL);
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
diff --git a/src/overlays/actors/ovl_Bg_Ikana_Mirror/z_bg_ikana_mirror.h b/src/overlays/actors/ovl_Bg_Ikana_Mirror/z_bg_ikana_mirror.h
index c9f8812084..5bd2724804 100644
--- a/src/overlays/actors/ovl_Bg_Ikana_Mirror/z_bg_ikana_mirror.h
+++ b/src/overlays/actors/ovl_Bg_Ikana_Mirror/z_bg_ikana_mirror.h
@@ -8,12 +8,17 @@ struct BgIkanaMirror;
typedef void (*BgIkanaMirrorActionFunc)(struct BgIkanaMirror*, PlayState*);
typedef struct BgIkanaMirror {
- /* 0x0000 */ Actor actor;
- /* 0x0144 */ char unk_144[0x474];
- /* 0x05B8 */ BgIkanaMirrorActionFunc actionFunc;
- /* 0x05BC */ char unk_5BC[0x10];
+ /* 0x000 */ DynaPolyActor dyna;
+ /* 0x15C */ ColliderTris mirrorCollider;
+ /* 0x17C */ ColliderTrisElement mirrorColliderElements[9];
+ /* 0x4B8 */ ColliderQuad lightRaysColliders[2];
+ /* 0x5B8 */ BgIkanaMirrorActionFunc actionFunc;
+ /* 0x5BC */ AnimatedMaterial* lightAbsorptionTexScroll;
+ /* 0x5C0 */ AnimatedMaterial* lightEmissionTexScroll;
+ /* 0x5C4 */ s16 lightRayCharge;
+ /* 0x5C6 */ u8 lightAbsorptionAlpha;
+ /* 0x5C7 */ u8 lightEmissionAlpha;
+ /* 0x5C8 */ s8 isEmittingLight;
} BgIkanaMirror; // size = 0x5CC
-extern const ActorInit Bg_Ikana_Mirror_InitVars;
-
#endif // Z_BG_IKANA_MIRROR_H
diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt
index f861588a5f..2ad13737b6 100644
--- a/tools/disasm/functions.txt
+++ b/tools/disasm/functions.txt
@@ -14574,13 +14574,13 @@
0x80B7F398:("func_80B7F398",),
0x80B7F474:("BgIkanaBlock_Update",),
0x80B7F564:("func_80B7F564",),
- 0x80B7F730:("func_80B7F730",),
+ 0x80B7F730:("BgIkanaMirror_SetQuadVertices",),
0x80B7F850:("BgIkanaMirror_Init",),
0x80B7FA00:("BgIkanaMirror_Destroy",),
- 0x80B7FA84:("func_80B7FA84",),
- 0x80B7FA9C:("func_80B7FA9C",),
- 0x80B7FB84:("func_80B7FB84",),
- 0x80B7FBA4:("func_80B7FBA4",),
+ 0x80B7FA84:("BgIkanaMirror_SetupWait",),
+ 0x80B7FA9C:("BgIkanaMirror_Wait",),
+ 0x80B7FB84:("BgIkanaMirror_SetupEmitLight",),
+ 0x80B7FBA4:("BgIkanaMirror_EmitLight",),
0x80B7FCB8:("BgIkanaMirror_Update",),
0x80B7FCDC:("BgIkanaMirror_Draw",),
0x80B802E0:("func_80B802E0",),