mirror of https://github.com/zeldaret/mm.git
1827 lines
69 KiB
C
1827 lines
69 KiB
C
#include "global.h"
|
|
#include "gfx.h"
|
|
#include "sys_cmpdma.h"
|
|
#include "assets/interface/icon_item_dungeon_static/icon_item_dungeon_static.h"
|
|
#include "assets/interface/parameter_static/parameter_static.h"
|
|
#include "assets/objects/gameplay_keep/gameplay_keep.h"
|
|
#include "overlays/actors/ovl_Door_Shutter/z_door_shutter.h"
|
|
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
|
|
|
|
void MapDisp_DestroyMapI(PlayState* play);
|
|
void MapDisp_InitMapI(PlayState* play);
|
|
|
|
#include "gDPLoadTextureBlock_Runtime.inc.c"
|
|
|
|
static UNK_TYPE4 D_801BEB30[2] = { 0, 0 };
|
|
|
|
static u64 sWhiteSquareTex[] = {
|
|
#include "assets/code/z_map_disp/white_square.i4.inc.c"
|
|
};
|
|
static MapDisp sMapDisp = {
|
|
NULL, -1, 210, 140, 0, 0, NULL, -1, NULL, 0, 0, 0, 0, NULL, NULL, 0,
|
|
0, 0, 0, 0, 0, NULL, 0, 0, 0, NULL, 0, 0, NULL, 0, 0,
|
|
};
|
|
|
|
MapDataRoom sMapDataRooms[ROOM_MAX];
|
|
MapDataChest sMapDataChests[32];
|
|
static MapDataScene sMapDataScene = {
|
|
sMapDataRooms,
|
|
80,
|
|
};
|
|
static s32 sSceneNumRooms = 0; // current scene's no. of rooms
|
|
static s32 sNumChests = 0; // MinimapChest count
|
|
static TransitionActorList sTransitionActorList = { 0, NULL };
|
|
static Color_RGBA8 sMinimapActorCategoryColors[12] = {
|
|
{ 255, 255, 255, 255 }, { 255, 255, 255, 255 }, { 0, 255, 0, 255 }, { 255, 255, 255, 255 },
|
|
{ 255, 255, 255, 255 }, { 255, 0, 0, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 },
|
|
{ 255, 255, 255, 255 }, { 255, 0, 0, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 },
|
|
};
|
|
|
|
TransitionActorEntry sTransitionActors[ROOM_TRANSITION_MAX];
|
|
PauseDungeonMap sPauseDungeonMap;
|
|
|
|
void MapDisp_GetMapITexture(void* dst, s32 mapCompactId) {
|
|
if (MapDisp_GetSizeOfMapITex(mapCompactId) != 0) {
|
|
CmpDma_LoadFile(SEGMENT_ROM_START(map_i_static), mapCompactId, dst, MapDisp_GetSizeOfMapITex(mapCompactId));
|
|
}
|
|
}
|
|
|
|
void MapDisp_InitRoomStoreyRecord(PlayState* play, s16* roomStorey) {
|
|
*roomStorey = -1;
|
|
}
|
|
|
|
void MapDisp_DestroyRoomStoreyRecord(PlayState* play, s16* roomStory) {
|
|
}
|
|
|
|
void func_80102EB4(u32 flag) {
|
|
sMapDisp.unk20 |= flag;
|
|
}
|
|
|
|
void func_80102ED0(u32 flag) {
|
|
sMapDisp.unk20 &= ~flag;
|
|
}
|
|
|
|
s32 MapDisp_CurRoomHasMapI(PlayState* play) {
|
|
MapDataRoom* mapDataRoom;
|
|
s8 curRoom;
|
|
|
|
if (Map_IsInBossScene(play) == true) {
|
|
return true;
|
|
}
|
|
curRoom = play->roomCtx.curRoom.num;
|
|
if (curRoom == -1) {
|
|
return false;
|
|
}
|
|
mapDataRoom = &sMapDisp.mapDataScene->rooms[curRoom];
|
|
if (mapDataRoom->mapId == MAP_DATA_NO_MAP) {
|
|
return false;
|
|
}
|
|
if (MapData_GetMapIId(mapDataRoom->mapId) == MAPDATA_MAP_I_MAX) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Computes the storey containing checkY and returns the floor Y value.
|
|
* @note Only used to check if a chest is on the same storey as the player.
|
|
*/
|
|
f32 MapDisp_GetStoreyY(f32 checkY) {
|
|
s32 i;
|
|
|
|
if ((sMapDisp.storeyYList[sMapDisp.numStoreys - 1] - 80.0f) < checkY) {
|
|
return sMapDisp.storeyYList[sMapDisp.numStoreys - 1];
|
|
}
|
|
for (i = sMapDisp.numStoreys - 2; i >= 0; i--) {
|
|
if (((sMapDisp.storeyYList[i] - 80.0f) < checkY) && (checkY < (sMapDisp.storeyYList[i + 1] + 80.0f))) {
|
|
return sMapDisp.storeyYList[i];
|
|
}
|
|
}
|
|
if (checkY < (sMapDisp.storeyYList[0] + 80.0f)) {
|
|
return sMapDisp.storeyYList[0];
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void MapDisp_GetMapTexDim(MapDataRoom* mapDataRoom, s32* width, s32* height) {
|
|
MapData_GetMapTexDim(mapDataRoom->mapId, width, height);
|
|
}
|
|
|
|
void MapDisp_GetMapScale(MapDataRoom* mapDataRoom, s32* scale) {
|
|
MapData_GetMapScale(mapDataRoom->mapId, scale);
|
|
if (*scale == 0) {
|
|
*scale = 20;
|
|
}
|
|
}
|
|
|
|
void MapDisp_GetMapOffset(MapDataRoom* mapDataRoom, s32* offsetX, s32* offsetY) {
|
|
s32 width;
|
|
s32 height;
|
|
|
|
if (mapDataRoom->mapId == MAP_DATA_NO_MAP) {
|
|
*offsetX = 0;
|
|
*offsetY = 0;
|
|
return;
|
|
}
|
|
MapDisp_GetMapTexDim(mapDataRoom, &width, &height);
|
|
MapData_GetMapTexOffset(mapDataRoom->mapId, offsetX, offsetY);
|
|
if (mapDataRoom->flags & MAP_DATA_ROOM_FLIP_X) {
|
|
s32 temp = (width / 2);
|
|
|
|
*offsetX = ((width / 2) - *offsetX) + (width / 2);
|
|
}
|
|
if (mapDataRoom->flags & MAP_DATA_ROOM_FLIP_Y) {
|
|
s32 temp = (height / 2);
|
|
|
|
*offsetY = (temp - *offsetY) + temp;
|
|
}
|
|
}
|
|
|
|
void MapDisp_DrawMinimapRoom(PlayState* play, TexturePtr texture, s32 x, s32 y, s32 room, f32 intensity) {
|
|
MapDataRoom* mapDataRoom = &sMapDisp.mapDataScene->rooms[room];
|
|
s32 texWidth;
|
|
s32 texHeight;
|
|
s32 dtdy;
|
|
s32 dsdx;
|
|
s32 t;
|
|
s32 s;
|
|
s16 dsdx_temp;
|
|
s16 dtdy_temp;
|
|
Color_RGBA8 color;
|
|
s32 drawType;
|
|
|
|
if ((mapDataRoom->mapId == MAP_DATA_NO_MAP) || (texture == NULL)) {
|
|
return;
|
|
}
|
|
|
|
MapDisp_GetMapTexDim(mapDataRoom, &texWidth, &texHeight);
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
Gfx_SetupDL39_Overlay(play->state.gfxCtx);
|
|
MapData_GetMapColor(MapData_GetMapColorIndex(mapDataRoom->mapId), &color);
|
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, color.r, color.g, color.b,
|
|
(s32)(play->interfaceCtx.minimapAlpha * intensity * color.a / 255.0f));
|
|
MapData_GetDrawType(mapDataRoom->mapId, &drawType);
|
|
|
|
switch (drawType) {
|
|
case MAPDATA_DRAW_1:
|
|
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
|
gDPLoadTextureBlock_4b(OVERLAY_DISP++, texture, G_IM_FMT_IA, texWidth, texHeight, 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);
|
|
break;
|
|
|
|
case MAPDATA_DRAW_3:
|
|
gDPSetCombineLERP(OVERLAY_DISP++, 0, 0, 0, PRIMITIVE, 0, 0, 0, TEXEL0, 0, 0, 0, PRIMITIVE, 0, 0, 0, TEXEL0);
|
|
gDPLoadTextureBlock_4b(OVERLAY_DISP++, texture, G_IM_FMT_I, texWidth, texHeight, 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);
|
|
break;
|
|
|
|
default:
|
|
case MAPDATA_DRAW_0:
|
|
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
|
gDPLoadTextureBlock_4b(OVERLAY_DISP++, texture, G_IM_FMT_I, texWidth, texHeight, 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);
|
|
break;
|
|
}
|
|
|
|
s = (mapDataRoom->flags & MAP_DATA_ROOM_FLIP_X) ? (texWidth - 1) << 5 : 0;
|
|
t = (mapDataRoom->flags & MAP_DATA_ROOM_FLIP_Y) ? 0 : (texHeight - 1) << 5;
|
|
|
|
dsdx_temp = ((mapDataRoom->flags & MAP_DATA_ROOM_FLIP_X) ? -1 : 1) * (1 << 10);
|
|
dtdy_temp = ((mapDataRoom->flags & MAP_DATA_ROOM_FLIP_Y) ? 1 : -1) * (1 << 10);
|
|
|
|
dsdx = (mapDataRoom->flags & MAP_DATA_ROOM_FLIP_X) ? dsdx_temp & 0xFFFF : dsdx_temp;
|
|
dtdy = (mapDataRoom->flags & MAP_DATA_ROOM_FLIP_Y) ? dtdy_temp : dtdy_temp & 0xFFFF;
|
|
|
|
gSPTextureRectangle(OVERLAY_DISP++, x << 2, y << 2, (texWidth + x) << 2, (y + texHeight) << 2, G_TX_RENDERTILE, s,
|
|
t, dsdx, dtdy);
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
// Tests if the map data should be rotated 180 degrees
|
|
// SCENE_35TAKI is the only scene with data flipped in this manner.
|
|
s32 MapDisp_IsDataRotated(PlayState* play) {
|
|
if (play->sceneId == SCENE_35TAKI) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
s32 MapDisp_CanDrawDoors(PlayState* play) {
|
|
if ((gSaveContext.save.entrance == ENTRANCE(ROMANI_RANCH, 0)) && (Cutscene_GetSceneLayer(play) != 0)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void MapDisp_Minimap_DrawActorIcon(PlayState* play, Actor* actor) {
|
|
MapDataRoom* mapDataRoom;
|
|
s32 posX;
|
|
s32 posY;
|
|
s32 texOffsetX;
|
|
s32 texOffsetY;
|
|
s32 texWidth;
|
|
s32 texHeight;
|
|
f32 scaleFrac;
|
|
f32 unused1;
|
|
f32 unused2;
|
|
Player* player = GET_PLAYER(play);
|
|
s32 scale;
|
|
|
|
// inferred from `MapDisp_Minimap_DrawDoorActor`
|
|
unused1 = fabsf(player->actor.world.pos.y - actor->world.pos.y);
|
|
unused2 = 1.0f - (1 / 350.0f) * unused1;
|
|
|
|
if (unused2 < 0.0f) {
|
|
unused2 = 0.0f;
|
|
}
|
|
|
|
mapDataRoom = &sMapDisp.mapDataScene->rooms[sMapDisp.curRoom];
|
|
if (mapDataRoom->mapId == MAP_DATA_NO_MAP) {
|
|
return;
|
|
}
|
|
|
|
MapDisp_GetMapOffset(mapDataRoom, &texOffsetX, &texOffsetY);
|
|
MapDisp_GetMapTexDim(mapDataRoom, &texWidth, &texHeight);
|
|
|
|
scale = sMapDisp.mapDataScene->scale;
|
|
if (sMapDisp.mapDataScene->scale == 0) {
|
|
scale = 20;
|
|
} else if (sMapDisp.mapDataScene->scale == -1) {
|
|
s32 scaleTemp;
|
|
|
|
MapDisp_GetMapScale(mapDataRoom, &scaleTemp);
|
|
scale = scaleTemp;
|
|
}
|
|
|
|
scaleFrac = 1.0f / scale;
|
|
if (!MapDisp_IsDataRotated(play)) {
|
|
posX = (s32)((actor->world.pos.x - mapDataRoom->centerX) * scaleFrac) + sMapDisp.minimapBaseX +
|
|
sMapDisp.minimapCurX - sMapDisp.minimapBaseX + texOffsetX;
|
|
posY = (s32)((actor->world.pos.z - mapDataRoom->centerZ) * scaleFrac) + sMapDisp.minimapBaseY +
|
|
sMapDisp.minimapCurY - sMapDisp.minimapBaseY + texOffsetY;
|
|
} else {
|
|
posX = -(s32)((actor->world.pos.x - mapDataRoom->centerX) * scaleFrac) + sMapDisp.minimapBaseX +
|
|
sMapDisp.minimapCurX - sMapDisp.minimapBaseX + texOffsetX;
|
|
posY = -(s32)((actor->world.pos.z - mapDataRoom->centerZ) * scaleFrac) + sMapDisp.minimapBaseY +
|
|
sMapDisp.minimapCurY - sMapDisp.minimapBaseY + texOffsetY;
|
|
}
|
|
|
|
if ((posX > 0) && (posX < 0x3FF) && (posY > 0) && (posY < 0x3FF)) {
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
if ((actor->category == ACTORCAT_PLAYER) && (actor->flags & ACTOR_FLAG_MINIMAP_ICON_ENABLED)) {
|
|
s16 compassRot;
|
|
|
|
Gfx_SetupDL42_Overlay(play->state.gfxCtx);
|
|
gSPMatrix(OVERLAY_DISP++, &gIdentityMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
|
|
PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
|
|
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, play->interfaceCtx.minimapAlpha);
|
|
gDPSetCombineMode(OVERLAY_DISP++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
|
|
gDPSetRenderMode(OVERLAY_DISP++, G_RM_AA_DEC_LINE, G_RM_NOOP2);
|
|
|
|
Matrix_Translate(posX - 160.0f, 120.0f - posY, 0.0f, MTXMODE_NEW);
|
|
Matrix_RotateXFApply(-1.6f);
|
|
compassRot = (s32)(0x7FFF - actor->focus.rot.y) / 1024;
|
|
if (MapDisp_IsDataRotated(play)) {
|
|
compassRot += 0x7FFF;
|
|
}
|
|
Matrix_RotateYF(compassRot / 10.0f, MTXMODE_APPLY);
|
|
Matrix_Scale(0.4f, 0.4f, 0.4f, MTXMODE_APPLY);
|
|
MATRIX_FINALIZE_AND_LOAD(OVERLAY_DISP++, play->state.gfxCtx);
|
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 255, 0, play->interfaceCtx.minimapAlpha);
|
|
gSPDisplayList(OVERLAY_DISP++, gCompassArrowDL);
|
|
} else if ((actor->id == ACTOR_EN_BOX) && !Flags_GetTreasure(play, actor->params & 0x1F) &&
|
|
(MapDisp_GetStoreyY(player->actor.world.pos.y) == MapDisp_GetStoreyY(actor->world.pos.y))) {
|
|
Gfx_SetupDL39_Overlay(play->state.gfxCtx);
|
|
gDPPipeSync(OVERLAY_DISP++);
|
|
gDPSetTextureLUT(OVERLAY_DISP++, G_TT_NONE);
|
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, play->interfaceCtx.minimapAlpha);
|
|
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, play->interfaceCtx.minimapAlpha);
|
|
gDPPipeSync(OVERLAY_DISP++);
|
|
|
|
gDPLoadTextureBlock_Runtime(OVERLAY_DISP++, gMapChestIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 8, 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);
|
|
|
|
gSPTextureRectangle(OVERLAY_DISP++, (posX - 4) << 2, (posY - 4) << 2, (posX + 4) << 2, (posY + 4) << 2,
|
|
G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
|
|
} else {
|
|
Gfx_SetupDL39_Overlay(play->state.gfxCtx);
|
|
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
|
if (actor->flags & ACTOR_FLAG_MINIMAP_ICON_ENABLED) {
|
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, sMinimapActorCategoryColors[actor->category].r,
|
|
sMinimapActorCategoryColors[actor->category].g,
|
|
sMinimapActorCategoryColors[actor->category].b, play->interfaceCtx.minimapAlpha);
|
|
gSPTextureRectangle(OVERLAY_DISP++, (posX - 1) << 2, (posY - 1) << 2, (posX + 1) << 2, (posY + 1) << 2,
|
|
G_TX_RENDERTILE, 0, 0, 0x0001, 0x0001);
|
|
}
|
|
}
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
}
|
|
|
|
void MapDisp_Minimap_DrawActors(PlayState* play) {
|
|
ActorContext* actorCtx;
|
|
s32 i;
|
|
|
|
if (play->roomCtx.curRoom.num != -1) {
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
gDPLoadTextureBlock_4b(OVERLAY_DISP++, &sWhiteSquareTex, G_IM_FMT_I, 16, 16, 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);
|
|
|
|
actorCtx = &play->actorCtx;
|
|
for (i = 0; i < ACTORCAT_MAX; i++) {
|
|
Actor* actor = actorCtx->actorLists[i].first;
|
|
|
|
while (actor != NULL) {
|
|
if ((actor->update != NULL) && (actor->init == NULL) &&
|
|
Object_IsLoaded(&play->objectCtx, actor->objectSlot) &&
|
|
((actor->id == ACTOR_EN_BOX) || (i == ACTORCAT_PLAYER) ||
|
|
(actor->flags & ACTOR_FLAG_MINIMAP_ICON_ENABLED)) &&
|
|
((sMapDisp.curRoom == actor->room) || (actor->room == -1))) {
|
|
MapDisp_Minimap_DrawActorIcon(play, actor);
|
|
}
|
|
actor = actor->next;
|
|
}
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
}
|
|
|
|
void MapDisp_Minimap_DrawDoorActor(PlayState* play, Actor* actor) {
|
|
MapDataRoom* mapDataRoom;
|
|
s32 posX;
|
|
s32 posY;
|
|
s32 texOffsetX;
|
|
s32 texOffsetY;
|
|
s32 texWidth;
|
|
s32 texHeight;
|
|
Player* player = GET_PLAYER(play);
|
|
f32 scaleFrac;
|
|
f32 yDistFromPlayer = fabsf(player->actor.world.pos.y - actor->world.pos.y);
|
|
s32 scale;
|
|
f32 yDistAlpha = 1.0f - (1.0f / 350.0f) * yDistFromPlayer;
|
|
|
|
if (yDistAlpha < 0.0f) {
|
|
yDistAlpha = 0.0f;
|
|
}
|
|
mapDataRoom = &sMapDisp.mapDataScene->rooms[sMapDisp.curRoom];
|
|
if (mapDataRoom->mapId != MAP_DATA_NO_MAP) {
|
|
MapDisp_GetMapOffset(mapDataRoom, &texOffsetX, &texOffsetY);
|
|
MapDisp_GetMapTexDim(mapDataRoom, &texWidth, &texHeight);
|
|
|
|
scale = sMapDisp.mapDataScene->scale;
|
|
if (sMapDisp.mapDataScene->scale == 0) {
|
|
scale = 20;
|
|
} else if (sMapDisp.mapDataScene->scale == -1) {
|
|
s32 scaleTemp;
|
|
|
|
MapDisp_GetMapScale(mapDataRoom, &scaleTemp);
|
|
scale = scaleTemp;
|
|
}
|
|
scaleFrac = 1.0f / scale;
|
|
if (!MapDisp_IsDataRotated(play)) {
|
|
posX = (((s32)((actor->world.pos.x - mapDataRoom->centerX) * scaleFrac) + sMapDisp.minimapBaseX +
|
|
sMapDisp.minimapCurX) -
|
|
sMapDisp.minimapBaseX) +
|
|
texOffsetX;
|
|
posY = (((s32)((actor->world.pos.z - mapDataRoom->centerZ) * scaleFrac) + sMapDisp.minimapBaseY +
|
|
sMapDisp.minimapCurY) -
|
|
sMapDisp.minimapBaseY) +
|
|
texOffsetY;
|
|
} else {
|
|
posX = (((sMapDisp.minimapBaseX - (s32)((actor->world.pos.x - mapDataRoom->centerX) * scaleFrac)) +
|
|
sMapDisp.minimapCurX) -
|
|
sMapDisp.minimapBaseX) +
|
|
texOffsetX;
|
|
posY = (((sMapDisp.minimapBaseY - (s32)((actor->world.pos.z - mapDataRoom->centerZ) * scaleFrac)) +
|
|
sMapDisp.minimapCurY) -
|
|
sMapDisp.minimapBaseY) +
|
|
texOffsetY;
|
|
}
|
|
if ((posX > 0) && (posX < 0x3FF) && (posY > 0) && (posY < 0x3FF)) {
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
Gfx_SetupDL39_Overlay(play->state.gfxCtx);
|
|
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
|
|
|
if ((actor->category == ACTORCAT_DOOR) && MapDisp_CanDrawDoors(play)) {
|
|
s32 pad;
|
|
|
|
gDPSetPrimColor(
|
|
OVERLAY_DISP++, 0, 0, sMinimapActorCategoryColors[actor->category].r,
|
|
sMinimapActorCategoryColors[actor->category].g, sMinimapActorCategoryColors[actor->category].b,
|
|
(s32)((sMinimapActorCategoryColors[actor->category].a * (1.0f - sMapDisp.swapAnimTimer * 0.05f) *
|
|
yDistAlpha * play->interfaceCtx.minimapAlpha) /
|
|
255.0f));
|
|
|
|
scale = sMapDisp.mapDataScene->scale;
|
|
if (sMapDisp.mapDataScene->scale == 0) {
|
|
scale = 20;
|
|
} else if (sMapDisp.mapDataScene->scale == -1) {
|
|
s32 scaleTemp;
|
|
|
|
MapDisp_GetMapScale(mapDataRoom, &scaleTemp);
|
|
scale = scaleTemp;
|
|
}
|
|
if (scale <= 50) {
|
|
gSPTextureRectangle(OVERLAY_DISP++, (posX - 2) << 2, (posY - 2) << 2, (posX + 2) << 2,
|
|
(posY + 2) << 2, G_TX_RENDERTILE, 0, 0, 0x0001, 0x0001);
|
|
} else {
|
|
gSPTextureRectangle(OVERLAY_DISP++, (posX - 1) << 2, (posY - 1) << 2, (posX + 1) << 2,
|
|
(posY + 1) << 2, G_TX_RENDERTILE, 0, 0, 0x0001, 0x0001);
|
|
}
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MapDisp_Minimap_DrawDoorActors(PlayState* play) {
|
|
s32 i;
|
|
Actor* actor;
|
|
|
|
if (play->roomCtx.curRoom.num != -1) {
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
gDPLoadTextureBlock_4b(OVERLAY_DISP++, &sWhiteSquareTex, G_IM_FMT_I, 16, 16, 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);
|
|
|
|
actor = play->actorCtx.actorLists[ACTORCAT_DOOR].first;
|
|
while (actor != NULL) {
|
|
if ((actor->update != NULL) && (actor->init == NULL) &&
|
|
Object_IsLoaded(&play->objectCtx, actor->objectSlot) &&
|
|
((sMapDisp.curRoom == actor->room) || (actor->room == -1))) {
|
|
MapDisp_Minimap_DrawDoorActor(play, actor);
|
|
}
|
|
actor = actor->next;
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Waits for GAMEPLAY_DANGEON_KEEP to load, if it is a current object depenency
|
|
*
|
|
* @param play
|
|
*/
|
|
void MapDisp_AwaitGameplayDangeonKeep(PlayState* play) {
|
|
s32 objectSlot = Object_GetSlot(&play->objectCtx, GAMEPLAY_DANGEON_KEEP);
|
|
|
|
if (objectSlot <= OBJECT_SLOT_NONE) {
|
|
sMapDisp.unk20 |= 1;
|
|
return;
|
|
}
|
|
|
|
while (true) {
|
|
if (Object_IsLoaded(&play->objectCtx, objectSlot)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MapDisp_Init(PlayState* play) {
|
|
s32 i;
|
|
|
|
sMapDisp.mapDataScene = NULL;
|
|
sMapDisp.curRoom = -1;
|
|
sMapDisp.minimapBaseX = 210;
|
|
sMapDisp.minimapBaseY = 140;
|
|
sMapDisp.minimapCurX = 210;
|
|
sMapDisp.minimapCurY = 140;
|
|
sMapDisp.minimapCurTex = NULL;
|
|
sMapDisp.prevRoom = -1;
|
|
sMapDisp.minimapPrevTex = NULL;
|
|
sMapDisp.minimapPrevX = 0;
|
|
sMapDisp.minimapPrevY = 0;
|
|
sMapDisp.unk20 = 0;
|
|
sMapDisp.swapAnimTimer = 0;
|
|
|
|
if (!Map_IsInBossScene(play)) {
|
|
sSceneNumRooms = play->roomList.count;
|
|
}
|
|
sMapDisp.texBuff0 = THA_AllocTailAlign16(&play->state.tha, 0x4000);
|
|
sMapDisp.texBuff1 = THA_AllocTailAlign16(&play->state.tha, 0x4000);
|
|
MapDisp_AwaitGameplayDangeonKeep(play);
|
|
if (!Map_IsInBossScene(play)) {
|
|
sMapDisp.sceneMinX = 0;
|
|
sMapDisp.sceneMinZ = 0;
|
|
sMapDisp.sceneWidth = 100;
|
|
sMapDisp.sceneHeight = 100;
|
|
sMapDisp.sceneMidX = TRUNCF_BINANG((f32)sMapDisp.sceneMinX + ((f32)sMapDisp.sceneWidth * 0.5f));
|
|
sMapDisp.sceneMidZ = TRUNCF_BINANG((f32)sMapDisp.sceneMinZ + ((f32)sMapDisp.sceneHeight * 0.5f));
|
|
}
|
|
sMapDisp.roomStoreyList = THA_AllocTailAlign16(&play->state.tha, sSceneNumRooms * sizeof(s16));
|
|
|
|
for (i = 0; i < sSceneNumRooms; i++) {
|
|
MapDisp_InitRoomStoreyRecord(play, &sMapDisp.roomStoreyList[i]);
|
|
}
|
|
sMapDisp.storeyYList = THA_AllocTailAlign16(&play->state.tha, ROOM_MAX * sizeof(s16));
|
|
|
|
for (i = 0; i < ROOM_MAX; i++) {
|
|
sMapDisp.storeyYList[i] = FLOOR_MIN_Y;
|
|
}
|
|
MapDisp_InitMapI(play);
|
|
sMapDisp.bossRoomStorey = 0;
|
|
sMapDisp.unk5A = 0;
|
|
if (Map_IsInBossScene(play)) {
|
|
MapDisp_InitMapData(play, NULL);
|
|
MapDisp_InitChestData(play, 0, NULL);
|
|
}
|
|
}
|
|
|
|
typedef struct {
|
|
/* 0x0 */ s16 sceneId;
|
|
/* 0x2 */ s16 bottomStorey;
|
|
} MapCustomBottomStorey; // size = 0x4
|
|
|
|
void MapDisp_InitSceneFloorData(PlayState* play) {
|
|
static MapCustomBottomStorey sCustomBottomStorey[] = {
|
|
{ SCENE_HAKUGIN, -1 }, { SCENE_HAKUGIN_BS, -1 }, { SCENE_SEA, -2 },
|
|
{ SCENE_SEA_BS, -2 }, { SCENE_INISIE_N, -1 },
|
|
};
|
|
s32 i1;
|
|
s32 i2;
|
|
s32 i3;
|
|
s32 storey;
|
|
|
|
// init table
|
|
for (i1 = 0; i1 < ROOM_MAX; i1++) {
|
|
sMapDisp.storeyYList[i1] = FLOOR_MIN_Y;
|
|
}
|
|
|
|
// for all rooms in scene
|
|
for (i2 = 0; i2 < sSceneNumRooms; i2++) {
|
|
MapDataRoom* mapDataRoom = &sMapDisp.mapDataScene->rooms[i2];
|
|
|
|
if (mapDataRoom->mapId == MAP_DATA_NO_MAP) {
|
|
continue;
|
|
}
|
|
// add item to the table if it is a newish value
|
|
for (i1 = 0; i1 < ROOM_MAX; i1++) {
|
|
if (sMapDisp.storeyYList[i1] == FLOOR_MIN_Y) {
|
|
sMapDisp.storeyYList[i1] = mapDataRoom->floorY;
|
|
break;
|
|
} else if (fabsf((f32)sMapDisp.storeyYList[i1] - (f32)mapDataRoom->floorY) < 5.0f) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// sort the table in ascending order
|
|
for (i2 = 0; i2 < sSceneNumRooms; i2++) {
|
|
if (sMapDisp.storeyYList[i2] == FLOOR_MIN_Y) {
|
|
break;
|
|
}
|
|
for (i3 = i2 + 1; i3 < sSceneNumRooms; i3++) {
|
|
if (sMapDisp.storeyYList[i3] == FLOOR_MIN_Y) {
|
|
break;
|
|
}
|
|
if (sMapDisp.storeyYList[i3] < sMapDisp.storeyYList[i2]) {
|
|
s16 swap = sMapDisp.storeyYList[i2];
|
|
|
|
sMapDisp.storeyYList[i2] = sMapDisp.storeyYList[i3];
|
|
sMapDisp.storeyYList[i3] = swap;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i2 = 0; i2 < sSceneNumRooms; i2++) {
|
|
MapDataRoom* mapDataRoom = &sMapDisp.mapDataScene->rooms[i2];
|
|
|
|
sMapDisp.roomStoreyList[i2] = -1;
|
|
|
|
for (storey = 0; storey < sSceneNumRooms; storey++) {
|
|
if (sMapDisp.storeyYList[storey] != FLOOR_MIN_Y) {
|
|
if (fabsf((f32)sMapDisp.storeyYList[storey] - (f32)mapDataRoom->floorY) < 5.0f) {
|
|
sMapDisp.roomStoreyList[i2] = storey;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sMapDisp.numStoreys = 0;
|
|
for (i2 = 0; i2 < sSceneNumRooms; i2++) {
|
|
if (sMapDisp.storeyYList[i2] != FLOOR_MIN_Y) {
|
|
sMapDisp.numStoreys++;
|
|
}
|
|
}
|
|
sMapDisp.bottomStorey = 0;
|
|
for (i2 = 0; i2 < ARRAY_COUNT(sCustomBottomStorey); i2++) {
|
|
if (play->sceneId == sCustomBottomStorey[i2].sceneId) {
|
|
sMapDisp.bottomStorey = sCustomBottomStorey[i2].bottomStorey;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unused result
|
|
* @returns the y position to place the boss room skull icon on the pause map.
|
|
* The result position is the inverse of what it should be, stacking lower rooms above higher ones
|
|
*/
|
|
s32 MapDisp_GetBossIconY(void) {
|
|
s32 dungeonMapFloorIconPosY[5] = { 67, 81, 95, 109, 123 };
|
|
|
|
if ((sMapDisp.mapDataScene == NULL) || (sMapDisp.bossRoomStorey < 0) || (sMapDisp.bossRoomStorey >= 5) ||
|
|
(sSceneNumRooms == 0)) {
|
|
return 123;
|
|
}
|
|
return dungeonMapFloorIconPosY[sMapDisp.bossRoomStorey];
|
|
}
|
|
|
|
s16 MapDisp_GetBossRoomStorey(void) {
|
|
return sMapDisp.bossRoomStorey;
|
|
}
|
|
|
|
// TransitionActor params test
|
|
s32 MapDisp_IsBossDoor(s32 params) {
|
|
if (DOORSHUTTER_PARAMS_GET_TYPE((u16)params) == DOORSHUTTER_TYPE_BOSS_DOOR) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void MapDisp_InitBossRoomStorey(PlayState* play) {
|
|
TransitionActorList* transitionActors = &sTransitionActorList;
|
|
s32 storey;
|
|
s32 i;
|
|
|
|
for (i = 0; i < transitionActors->count; i++) {
|
|
TransitionActorEntry* entry = &sTransitionActors[i];
|
|
|
|
if (MapDisp_IsBossDoor(entry->params)) {
|
|
if (ABS_ALT(entry->id) != ACTOR_EN_HOLL) {
|
|
for (storey = 0; storey < sMapDisp.numStoreys; storey++) {
|
|
if (((storey == sMapDisp.numStoreys - 1) && (entry->pos.y >= (sMapDisp.storeyYList[storey] - 5))) ||
|
|
((storey != sMapDisp.numStoreys - 1) && (entry->pos.y >= (sMapDisp.storeyYList[storey] - 5)) &&
|
|
(entry->pos.y < (sMapDisp.storeyYList[storey + 1] - 5)))) {
|
|
sMapDisp.bossRoomStorey = storey;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sMapDisp.bossRoomStorey = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Initializes the MapData for the current scene
|
|
*
|
|
* @param play
|
|
* @param segmentAddress
|
|
*/
|
|
void MapDisp_InitMapData(PlayState* play, void* segmentAddress) {
|
|
MapDataScene* mapDataScene;
|
|
MapDataRoom* mapDataRooms;
|
|
s32 i;
|
|
|
|
if (!Map_IsInBossScene(play)) {
|
|
sSceneNumRooms = play->roomList.count;
|
|
mapDataScene = Lib_SegmentedToVirtual(segmentAddress);
|
|
sMapDataScene = *mapDataScene;
|
|
mapDataRooms = Lib_SegmentedToVirtual(mapDataScene->rooms);
|
|
|
|
for (i = 0; i < sSceneNumRooms; i++) {
|
|
sMapDataRooms[i] = *mapDataRooms++;
|
|
}
|
|
|
|
sMapDataScene.rooms = sMapDataRooms;
|
|
if (play->colCtx.colHeader != NULL) {
|
|
sMapDisp.sceneMinX = play->colCtx.colHeader->minBounds.x;
|
|
sMapDisp.sceneMinZ = play->colCtx.colHeader->minBounds.z;
|
|
sMapDisp.sceneWidth = play->colCtx.colHeader->maxBounds.x - play->colCtx.colHeader->minBounds.x;
|
|
sMapDisp.sceneHeight = play->colCtx.colHeader->maxBounds.z - play->colCtx.colHeader->minBounds.z;
|
|
sMapDisp.sceneMidX = sMapDisp.sceneMinX + (sMapDisp.sceneWidth * 0.5f);
|
|
sMapDisp.sceneMidZ = sMapDisp.sceneMinZ + (sMapDisp.sceneHeight * 0.5f);
|
|
}
|
|
}
|
|
sMapDisp.mapDataScene = &sMapDataScene;
|
|
MapDisp_InitSceneFloorData(play);
|
|
MapDisp_InitBossRoomStorey(play);
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a deep copy of chest data from the scene data.
|
|
*
|
|
* @param play
|
|
* @param num
|
|
* @param segmentAddress
|
|
* @note If a boss scene is loaded, no data is copied. This allows the scene to borrow the main dungeon scene data
|
|
* instead.
|
|
*/
|
|
void MapDisp_InitChestData(PlayState* play, s32 num, void* segmentAddress) {
|
|
MapDataChest* mapDataChests;
|
|
s32 i;
|
|
|
|
if (!Map_IsInBossScene(play)) {
|
|
mapDataChests = Lib_SegmentedToVirtual(segmentAddress);
|
|
for (i = 0; i < num; mapDataChests++, i++) {
|
|
sMapDataChests[i] = *mapDataChests;
|
|
}
|
|
sNumChests = num;
|
|
}
|
|
sMapDisp.mapDataChests = sMapDataChests;
|
|
sMapDisp.numChests = sNumChests;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a deep copy of transition actors from the scene data.
|
|
*
|
|
* @param play
|
|
* @param num number of transition actors within the list
|
|
* @param transitionActorList pointer to the list of transition actors
|
|
* @note If a boss scene is loaded, no data is copied. This allows the scene to borrow the main dungeon scene data
|
|
* instead.
|
|
*/
|
|
void MapDisp_InitTransitionActorData(PlayState* play, s32 num, TransitionActorEntry* transitionActorList) {
|
|
s32 i;
|
|
|
|
if (!Map_IsInBossScene(play)) {
|
|
sTransitionActorList.count = num;
|
|
for (i = 0; i < num; i++) {
|
|
sTransitionActors[i] = transitionActorList[i];
|
|
}
|
|
sTransitionActorList.list = sTransitionActors;
|
|
}
|
|
}
|
|
|
|
void MapDisp_Destroy(PlayState* play) {
|
|
s32 i;
|
|
|
|
sMapDisp.mapDataScene = NULL;
|
|
sMapDisp.curRoom = -1;
|
|
sMapDisp.minimapCurX = 210;
|
|
sMapDisp.minimapCurY = 140;
|
|
sMapDisp.minimapCurTex = NULL;
|
|
sMapDisp.prevRoom = -1;
|
|
sMapDisp.minimapPrevTex = NULL;
|
|
sMapDisp.minimapPrevX = 0;
|
|
sMapDisp.minimapPrevY = 0;
|
|
sMapDisp.unk20 = 0;
|
|
sMapDisp.swapAnimTimer = 0;
|
|
sMapDisp.texBuff0 = NULL;
|
|
sMapDisp.texBuff1 = NULL;
|
|
|
|
for (i = 0; i < sSceneNumRooms; i++) {
|
|
MapDisp_DestroyRoomStoreyRecord(play, &sMapDisp.roomStoreyList[i]);
|
|
}
|
|
|
|
sMapDisp.roomStoreyList = NULL;
|
|
sMapDisp.numStoreys = 0;
|
|
sMapDisp.pauseMapCurStorey = 0;
|
|
sMapDisp.bottomStorey = 0;
|
|
sMapDisp.timer = 0;
|
|
sMapDisp.storeyYList = NULL;
|
|
sMapDisp.numChests = 0;
|
|
sMapDisp.mapDataChests = NULL;
|
|
MapDisp_DestroyMapI(play);
|
|
sMapDisp.unk5A = 0;
|
|
}
|
|
|
|
void MapDisp_Update(PlayState* play) {
|
|
PauseContext* pauseCtx = &play->pauseCtx;
|
|
s16 currentX;
|
|
s16 currentY;
|
|
s16 targetX;
|
|
s16 targetY;
|
|
|
|
if ((sMapDisp.mapDataScene != NULL) && (sSceneNumRooms != 0)) {
|
|
sMapDisp.pauseMapCurStorey = DUNGEON_FLOOR_INDEX_0 - pauseCtx->cursorMapDungeonItem;
|
|
if (sMapDisp.prevRoom != -1) {
|
|
if (sMapDisp.swapAnimTimer > 0) {
|
|
targetX = sMapDisp.minimapBaseX;
|
|
currentX = sMapDisp.minimapCurX;
|
|
if (targetX != currentX) {
|
|
sMapDisp.minimapCurX =
|
|
TRUNCF_BINANG(((f32)(targetX - currentX) / (f32)sMapDisp.swapAnimTimer) + (f32)currentX);
|
|
}
|
|
targetY = sMapDisp.minimapBaseY;
|
|
currentY = sMapDisp.minimapCurY;
|
|
if (targetY != currentY) {
|
|
sMapDisp.minimapCurY =
|
|
TRUNCF_BINANG(((f32)(targetY - currentY) / (f32)sMapDisp.swapAnimTimer) + (f32)currentY);
|
|
}
|
|
sMapDisp.swapAnimTimer--;
|
|
} else {
|
|
sMapDisp.prevRoom = -1;
|
|
sMapDisp.swapAnimTimer = 0;
|
|
sMapDisp.minimapCurX = sMapDisp.minimapBaseX;
|
|
sMapDisp.minimapCurY = sMapDisp.minimapBaseY;
|
|
}
|
|
} else {
|
|
sMapDisp.swapAnimTimer = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MapDisp_SwapRooms(s16 nextRoom) {
|
|
MapDataRoom* nextMapDataRoom;
|
|
MapDataRoom* prevMapDataRoom;
|
|
s32 minimapBaseX;
|
|
s32 minimapBaseY;
|
|
s32 width;
|
|
s32 height;
|
|
s32 offsetX;
|
|
s32 offsetY;
|
|
|
|
if ((sMapDisp.mapDataScene != NULL) && (sSceneNumRooms != 0) && (nextRoom != -1)) {
|
|
nextMapDataRoom = &sMapDisp.mapDataScene->rooms[nextRoom];
|
|
if ((nextMapDataRoom->mapId < MAPDATA_GAMEPLAY_DANGEON_KEEP_MAX) ||
|
|
((nextMapDataRoom->mapId >= MAPDATA_MAP_GRAND) && (nextMapDataRoom->mapId < MAPDATA_MAP_GRAND_MAX)) ||
|
|
nextMapDataRoom->mapId == MAP_DATA_NO_MAP) {
|
|
|
|
sMapDisp.prevRoom = sMapDisp.curRoom;
|
|
sMapDisp.curRoom = nextRoom;
|
|
sMapDisp.swapAnimTimer = 20;
|
|
|
|
sMapDisp.minimapPrevTex = sMapDisp.minimapCurTex;
|
|
minimapBaseX = sMapDisp.minimapBaseX;
|
|
minimapBaseY = sMapDisp.minimapBaseY;
|
|
|
|
nextMapDataRoom = &sMapDisp.mapDataScene->rooms[sMapDisp.curRoom];
|
|
|
|
if (nextMapDataRoom->mapId == MAP_DATA_NO_MAP) {
|
|
sMapDisp.minimapPrevY = 0;
|
|
sMapDisp.minimapBaseX = 210;
|
|
sMapDisp.minimapBaseY = 140;
|
|
sMapDisp.minimapCurX = 210;
|
|
sMapDisp.minimapCurY = 140;
|
|
sMapDisp.minimapCurTex = NULL;
|
|
sMapDisp.minimapPrevX = sMapDisp.minimapPrevY;
|
|
return;
|
|
}
|
|
MapDisp_GetMapOffset(nextMapDataRoom, &offsetX, &offsetY);
|
|
MapDisp_GetMapTexDim(nextMapDataRoom, &width, &height);
|
|
sMapDisp.minimapBaseX = 295 - width;
|
|
sMapDisp.minimapBaseY = 220 - height;
|
|
if (sMapDisp.prevRoom != -1) {
|
|
prevMapDataRoom = &sMapDisp.mapDataScene->rooms[sMapDisp.prevRoom];
|
|
if (prevMapDataRoom->mapId == MAP_DATA_NO_MAP) {
|
|
sMapDisp.minimapCurTex = NULL;
|
|
sMapDisp.minimapPrevX = sMapDisp.minimapPrevY = 0;
|
|
sMapDisp.minimapCurX = sMapDisp.minimapBaseX;
|
|
sMapDisp.minimapCurY = sMapDisp.minimapBaseY;
|
|
return;
|
|
} else {
|
|
s32 prevOffsetX;
|
|
s32 prevOffsetY;
|
|
s32 scale;
|
|
s32 pad;
|
|
|
|
MapDisp_GetMapOffset(prevMapDataRoom, &prevOffsetX, &prevOffsetY);
|
|
scale = sMapDisp.mapDataScene->scale;
|
|
if (sMapDisp.mapDataScene->scale == 0) {
|
|
scale = 20;
|
|
} else if (sMapDisp.mapDataScene->scale == -1) {
|
|
s32 scaleTemp;
|
|
|
|
MapDisp_GetMapScale(nextMapDataRoom, &scaleTemp);
|
|
scale = scaleTemp;
|
|
}
|
|
sMapDisp.minimapPrevX =
|
|
TRUNCF_BINANG(((f32)offsetX + (((f32)prevMapDataRoom->centerX - (f32)nextMapDataRoom->centerX) *
|
|
(1.0f / scale))) -
|
|
(f32)prevOffsetX);
|
|
sMapDisp.minimapPrevY =
|
|
TRUNCF_BINANG(((f32)offsetY + (((f32)prevMapDataRoom->centerZ - (f32)nextMapDataRoom->centerZ) *
|
|
(1.0f / scale))) -
|
|
(f32)prevOffsetY);
|
|
sMapDisp.minimapCurX = minimapBaseX - sMapDisp.minimapPrevX;
|
|
sMapDisp.minimapCurY = minimapBaseY - sMapDisp.minimapPrevY;
|
|
}
|
|
} else {
|
|
sMapDisp.minimapPrevX = sMapDisp.minimapPrevY = 0;
|
|
sMapDisp.minimapCurX = sMapDisp.minimapBaseX;
|
|
sMapDisp.minimapCurY = sMapDisp.minimapBaseY;
|
|
}
|
|
sMapDisp.minimapCurTex = NULL;
|
|
|
|
switch (MapData_MID_GetType(nextMapDataRoom->mapId)) {
|
|
case MAPDATA_MID_GAMEPLAY_DANGEON_KEEP:
|
|
sMapDisp.minimapCurTex = MapData_GetMapTexGameplayDangeonKeep(nextMapDataRoom->mapId);
|
|
return;
|
|
|
|
case MAPDATA_MID_MAP_GRAND_STATIC:
|
|
if (sMapDisp.minimapPrevTex == sMapDisp.texBuff0) {
|
|
sMapDisp.minimapCurTex = sMapDisp.texBuff1;
|
|
} else {
|
|
sMapDisp.minimapCurTex = sMapDisp.texBuff0;
|
|
}
|
|
if (MapData_GetSizeOfMapGrandTex(nextMapDataRoom->mapId) != 0) {
|
|
CmpDma_LoadFile(SEGMENT_ROM_START(map_grand_static),
|
|
MAPDATA_GET_MAP_GRAND_ID_FROM_MAP_ID(nextMapDataRoom->mapId),
|
|
sMapDisp.minimapCurTex, MapData_GetSizeOfMapGrandTex(nextMapDataRoom->mapId));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MapDisp_Minimap_DrawRedCompassIcon(PlayState* play, s32 x, s32 z, s32 rot) {
|
|
MapDataRoom* mapDataRoom;
|
|
s32 posX;
|
|
s32 posY;
|
|
s32 texOffsetX;
|
|
s32 texOffsetY;
|
|
s32 texWidth;
|
|
s32 texHeight;
|
|
s32 scale;
|
|
f32 scaleFrac;
|
|
|
|
mapDataRoom = &sMapDisp.mapDataScene->rooms[sMapDisp.curRoom];
|
|
if (mapDataRoom->mapId == MAP_DATA_NO_MAP) {
|
|
return;
|
|
}
|
|
|
|
MapDisp_GetMapOffset(mapDataRoom, &texOffsetX, &texOffsetY);
|
|
MapDisp_GetMapTexDim(mapDataRoom, &texWidth, &texHeight);
|
|
scale = sMapDisp.mapDataScene->scale;
|
|
|
|
if (sMapDisp.mapDataScene->scale == 0) {
|
|
scale = 20;
|
|
} else if (sMapDisp.mapDataScene->scale == -1) {
|
|
s32 scaleTemp;
|
|
|
|
MapDisp_GetMapScale(mapDataRoom, &scaleTemp);
|
|
scale = scaleTemp;
|
|
}
|
|
|
|
scaleFrac = 1.0f / scale;
|
|
if (!MapDisp_IsDataRotated(play)) {
|
|
posX = (s32)((x - (f32)mapDataRoom->centerX) * scaleFrac) + sMapDisp.minimapBaseX +
|
|
(sMapDisp.minimapCurX - sMapDisp.minimapBaseX) + texOffsetX;
|
|
posY = (s32)((z - (f32)mapDataRoom->centerZ) * scaleFrac) + sMapDisp.minimapBaseY +
|
|
(sMapDisp.minimapCurY - sMapDisp.minimapBaseY) + texOffsetY;
|
|
} else {
|
|
posX = -(s32)((x - (f32)mapDataRoom->centerX) * scaleFrac) + sMapDisp.minimapBaseX +
|
|
(sMapDisp.minimapCurX - sMapDisp.minimapBaseX) + texOffsetX;
|
|
posY = -(s32)((z - (f32)mapDataRoom->centerZ) * scaleFrac) + sMapDisp.minimapBaseY +
|
|
(sMapDisp.minimapCurY - sMapDisp.minimapBaseY) + texOffsetY;
|
|
}
|
|
|
|
if ((posX > 0) && (posX < 0x3FF) && (posY > 0) && (posY < 0x3FF)) {
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
Gfx_SetupDL42_Overlay(play->state.gfxCtx);
|
|
gSPMatrix(OVERLAY_DISP++, &gIdentityMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
|
|
PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
|
|
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255);
|
|
gDPSetCombineMode(OVERLAY_DISP++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
|
|
gDPSetRenderMode(OVERLAY_DISP++, G_RM_AA_DEC_LINE, G_RM_NOOP2);
|
|
Matrix_Translate(posX - 160.0f, 120.0f - posY, 0.0f, MTXMODE_NEW);
|
|
Matrix_RotateXFApply(-1.6f);
|
|
if (MapDisp_IsDataRotated(play)) {
|
|
rot += 0x7FFF;
|
|
}
|
|
Matrix_RotateYF(rot / 10.0f, MTXMODE_APPLY);
|
|
Matrix_Scale(0.4f, 0.4f, 0.4f, MTXMODE_APPLY);
|
|
MATRIX_FINALIZE_AND_LOAD(OVERLAY_DISP++, play->state.gfxCtx);
|
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 255, 200, 0, 0, play->interfaceCtx.minimapAlpha);
|
|
gSPDisplayList(OVERLAY_DISP++, gCompassArrowDL);
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
}
|
|
|
|
s32 MapDisp_IsLocationRomaniRanchAltScene(PlayState* play) {
|
|
if ((gSaveContext.save.entrance == ENTRANCE(ROMANI_RANCH, 0)) && (Cutscene_GetSceneLayer(play) != 0)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
s32 MapDisp_CanDisplayMinimap(PlayState* play) {
|
|
if ((!Map_CurRoomHasMapI(play) && Inventory_IsMapVisible(play->sceneId)) ||
|
|
(Map_CurRoomHasMapI(play) && CHECK_DUNGEON_ITEM(DUNGEON_MAP, gSaveContext.mapIndex))) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
s32 MapDisp_IsLocationMinimapBlocked(PlayState* play) {
|
|
if (((play->csCtx.state != CS_STATE_IDLE) && !MapDisp_IsLocationRomaniRanchAltScene(play)) ||
|
|
(sMapDisp.unk20 & 2) || Map_IsInBossScene(play)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
s32 MapDisp_IsMinimapToggleBlocked(PlayState* play) {
|
|
if ((MapDisp_IsLocationMinimapBlocked(play) == true) || !MapDisp_CanDisplayMinimap(play)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
s32 MapDisp_AreRoomsSameStorey(s32 curRoom, s32 prevRoom) {
|
|
MapDataRoom* mapDataRoom;
|
|
s16* roomStoreyList;
|
|
|
|
if ((curRoom == -1) || (prevRoom == -1)) {
|
|
return false;
|
|
}
|
|
mapDataRoom = &sMapDisp.mapDataScene->rooms[curRoom];
|
|
roomStoreyList = sMapDisp.roomStoreyList;
|
|
if ((roomStoreyList[curRoom] <= roomStoreyList[prevRoom]) &&
|
|
(roomStoreyList[prevRoom] <= (roomStoreyList[curRoom] + MAP_DATA_ROOM_GET_EXTRA_STOREYS(mapDataRoom)))) {
|
|
return true;
|
|
}
|
|
mapDataRoom = &sMapDisp.mapDataScene->rooms[prevRoom];
|
|
if ((roomStoreyList[prevRoom] <= roomStoreyList[curRoom]) &&
|
|
(roomStoreyList[curRoom] <= (roomStoreyList[prevRoom] + MAP_DATA_ROOM_GET_EXTRA_STOREYS(mapDataRoom)))) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void MapDisp_DrawMinimap(PlayState* play, s32 playerInitX, s32 playerInitZ, s32 playerInitDir) {
|
|
PauseContext* pauseCtx = &play->pauseCtx;
|
|
|
|
if ((sMapDisp.mapDataScene != NULL) && ((s32)pauseCtx->state <= PAUSE_STATE_OPENING_2) && !R_MINIMAP_DISABLED &&
|
|
(play->interfaceCtx.minimapAlpha != 0)) {
|
|
if (!MapDisp_IsLocationMinimapBlocked(play) && (sSceneNumRooms != 0)) {
|
|
if (MapDisp_CanDisplayMinimap(play)) {
|
|
MapDisp_DrawMinimapRoom(play, sMapDisp.minimapCurTex, sMapDisp.minimapCurX, sMapDisp.minimapCurY,
|
|
sMapDisp.curRoom, 1.0f - (sMapDisp.swapAnimTimer * 0.05f));
|
|
if ((sMapDisp.curRoom != sMapDisp.prevRoom) &&
|
|
MapDisp_AreRoomsSameStorey(sMapDisp.curRoom, sMapDisp.prevRoom)) {
|
|
MapDisp_DrawMinimapRoom(play, sMapDisp.minimapPrevTex, sMapDisp.minimapCurX + sMapDisp.minimapPrevX,
|
|
sMapDisp.minimapCurY + sMapDisp.minimapPrevY, sMapDisp.prevRoom,
|
|
sMapDisp.swapAnimTimer * 0.05f);
|
|
}
|
|
MapDisp_Minimap_DrawDoorActors(play);
|
|
}
|
|
if ((!Map_CurRoomHasMapI(play) || CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, gSaveContext.mapIndex)) &&
|
|
(Map_CurRoomHasMapI(play) || Inventory_IsMapVisible(play->sceneId))) {
|
|
if (play->interfaceCtx.minigameState == MINIGAME_STATE_NONE) {
|
|
MapDisp_Minimap_DrawRedCompassIcon(play, playerInitX, playerInitZ, playerInitDir);
|
|
}
|
|
MapDisp_Minimap_DrawActors(play);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MapDisp_ResetMapI(void) {
|
|
s32 i;
|
|
|
|
sPauseDungeonMap.textureCount = 0;
|
|
for (i = 0; i < ROOM_MAX; i++) {
|
|
sPauseDungeonMap.mapI_mapCompactId[i] = 0;
|
|
sPauseDungeonMap.mapI_roomTextures[i] = NULL;
|
|
sPauseDungeonMap.roomSprite[i] = NULL;
|
|
}
|
|
|
|
sPauseDungeonMap.animTimer = 0;
|
|
sMapDisp.unk20 &= ~1;
|
|
}
|
|
|
|
void MapDisp_InitMapI(PlayState* play) {
|
|
MapDisp_ResetMapI();
|
|
}
|
|
|
|
void MapDisp_DestroyMapI(PlayState* play) {
|
|
MapDisp_ResetMapI();
|
|
}
|
|
|
|
// alloc pause screen dungeon map
|
|
void* MapDisp_AllocDungeonMap(PlayState* play, void* heap) {
|
|
void* heapNext;
|
|
s32 dungeonMapRoomIter;
|
|
s32 sceneRoomIter;
|
|
|
|
heapNext = heap;
|
|
if ((sMapDisp.mapDataScene == NULL) || (sSceneNumRooms == 0)) {
|
|
return heapNext;
|
|
}
|
|
sPauseDungeonMap.textureCount = 0;
|
|
|
|
// loop for number of rooms
|
|
for (sceneRoomIter = 0; sceneRoomIter < sSceneNumRooms; sceneRoomIter++) {
|
|
s32 mapCompactId;
|
|
MapDataRoom* mapDataRoom = &sMapDisp.mapDataScene->rooms[sceneRoomIter];
|
|
s32 isDuplicateTexture = false;
|
|
|
|
if (mapDataRoom->mapId == MAP_DATA_NO_MAP) {
|
|
continue;
|
|
}
|
|
mapCompactId = MapData_GetMapCompactId(mapDataRoom->mapId);
|
|
if (mapCompactId == -1) {
|
|
continue;
|
|
}
|
|
// test if the texture reference already exists
|
|
for (dungeonMapRoomIter = 0; dungeonMapRoomIter < sPauseDungeonMap.textureCount; dungeonMapRoomIter++) {
|
|
if (mapCompactId == sPauseDungeonMap.mapI_mapCompactId[dungeonMapRoomIter]) {
|
|
isDuplicateTexture = true;
|
|
break;
|
|
}
|
|
}
|
|
if (isDuplicateTexture == false) {
|
|
sPauseDungeonMap.mapI_mapCompactId[sPauseDungeonMap.textureCount] = mapCompactId;
|
|
sPauseDungeonMap.textureCount++;
|
|
}
|
|
}
|
|
|
|
// fetch all textures from rom
|
|
sPauseDungeonMap.mapI_roomTextures[0] = heap;
|
|
for (dungeonMapRoomIter = 0; dungeonMapRoomIter < sPauseDungeonMap.textureCount; dungeonMapRoomIter++) {
|
|
s32 mapCompactId = sPauseDungeonMap.mapI_mapCompactId[dungeonMapRoomIter];
|
|
|
|
MapDisp_GetMapITexture(sPauseDungeonMap.mapI_roomTextures[dungeonMapRoomIter], mapCompactId);
|
|
if (dungeonMapRoomIter + 1 < sPauseDungeonMap.textureCount) {
|
|
sPauseDungeonMap.mapI_roomTextures[dungeonMapRoomIter + 1] =
|
|
(void*)ALIGN16((uintptr_t)sPauseDungeonMap.mapI_roomTextures[dungeonMapRoomIter] +
|
|
MapData_CPID_GetSizeOfMapTex(mapCompactId));
|
|
} else {
|
|
heapNext = (void*)((uintptr_t)sPauseDungeonMap.mapI_roomTextures[dungeonMapRoomIter] +
|
|
MapData_CPID_GetSizeOfMapTex(mapCompactId));
|
|
}
|
|
}
|
|
|
|
for (sceneRoomIter = 0; sceneRoomIter < sSceneNumRooms; sceneRoomIter++) {
|
|
MapDataRoom* mapDataRoom = &sMapDisp.mapDataScene->rooms[sceneRoomIter];
|
|
s32 foundTexture = false;
|
|
s32 mapCompactId;
|
|
|
|
if (mapDataRoom->mapId == MAP_DATA_NO_MAP) {
|
|
sPauseDungeonMap.roomSprite[sceneRoomIter] = NULL;
|
|
} else {
|
|
mapCompactId = MapData_GetMapCompactId(mapDataRoom->mapId);
|
|
for (dungeonMapRoomIter = 0; dungeonMapRoomIter < sPauseDungeonMap.textureCount; dungeonMapRoomIter++) {
|
|
if (mapCompactId == sPauseDungeonMap.mapI_mapCompactId[dungeonMapRoomIter]) {
|
|
foundTexture = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!foundTexture) {
|
|
sPauseDungeonMap.roomSprite[sceneRoomIter] = NULL;
|
|
} else {
|
|
s32 requiredScopeTemp;
|
|
|
|
sPauseDungeonMap.roomSprite[sceneRoomIter] = sPauseDungeonMap.mapI_roomTextures[dungeonMapRoomIter];
|
|
}
|
|
}
|
|
}
|
|
return heapNext;
|
|
}
|
|
|
|
s32 MapDisp_IsOnStorey(s32 storey, f32 checkY) {
|
|
if (storey == 0) {
|
|
if ((sMapDisp.storeyYList[0] <= checkY) && ((sMapDisp.numStoreys == 1) || (checkY < sMapDisp.storeyYList[1]))) {
|
|
return true;
|
|
}
|
|
} else if (storey >= (sMapDisp.numStoreys - 1)) {
|
|
if (sMapDisp.storeyYList[sMapDisp.numStoreys - 1] <= checkY) {
|
|
return true;
|
|
}
|
|
} else if ((sMapDisp.storeyYList[storey] <= checkY) && (checkY < sMapDisp.storeyYList[storey + 1])) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
s32 MapDisp_ConvertBossSceneToDungeonScene(s32 sceneId) {
|
|
switch (sceneId) {
|
|
case SCENE_MITURIN_BS:
|
|
return SCENE_MITURIN;
|
|
|
|
case SCENE_HAKUGIN_BS:
|
|
return SCENE_HAKUGIN;
|
|
|
|
case SCENE_SEA_BS:
|
|
return SCENE_SEA;
|
|
|
|
case SCENE_INISIE_BS:
|
|
return SCENE_INISIE_N;
|
|
|
|
default:
|
|
return sceneId;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Draws the dungeon room sprites for the pause menu dungeon map
|
|
*
|
|
* @param play
|
|
* @param viewX top left x position of the dungeon map view window
|
|
* @param viewY top left y posiiton of the dungeon map view window
|
|
* @param viewWidth width in pixels of the dungeon map view window
|
|
* @param viewHeight height in pixels of the dungeon map view window
|
|
* @param scaleFrac ratio to convert world space coordinates to map coordinates
|
|
* @param dungeonSceneSharedIndex enum DungeonSceneIndex for retrieving map/compass data
|
|
*/
|
|
void MapDisp_DrawRooms(PlayState* play, s32 viewX, s32 viewY, s32 viewWidth, s32 viewHeight, f32 scaleFrac,
|
|
s32 dungeonSceneSharedIndex) {
|
|
static u16 sUnvisitedRoomPal[16] = {
|
|
0x0000, 0x0000, 0xFFC1, 0x07C1, 0x07FF, 0x003F, 0xFB3F, 0xF305,
|
|
0x0453, 0x0577, 0x0095, 0x82E5, 0xFD27, 0x7A49, 0x94A5, 0x0001,
|
|
}; // palette 0
|
|
static u16 sVisitedRoomPal[16] = {
|
|
0x0000, 0x027F, 0xFFC1, 0x07C1, 0x07FF, 0x003F, 0xFB3F, 0xF305,
|
|
0x0453, 0x0577, 0x0095, 0x82E5, 0xFD27, 0x7A49, 0x94A5, 0x0001,
|
|
}; // palette 1
|
|
static u16 sCurrentRoomPal[16] = {
|
|
0x0000, 0x0623, 0xFFC1, 0x07C1, 0x07FF, 0x003F, 0xFB3F, 0xF305,
|
|
0x0453, 0x0577, 0x0095, 0x82E5, 0xFD27, 0x7A49, 0x94A5, 0x0001,
|
|
}; // palette 2
|
|
PauseContext* pauseCtx = &play->pauseCtx;
|
|
s32 pad[4];
|
|
s32 i;
|
|
s32 green = ((sPauseDungeonMap.animTimer * -120.0f / 40.0f) + 200.0f) * 31.0f / 255.0f;
|
|
s32 blue = ((sPauseDungeonMap.animTimer * 115.0f / 40.0f) + 140.0f) * 31.0f / 255.0f;
|
|
|
|
sCurrentRoomPal[1] = (green << 6) | (blue << 1) | 1;
|
|
|
|
if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, dungeonSceneSharedIndex)) {
|
|
s32 requiredScopeTemp;
|
|
|
|
sUnvisitedRoomPal[15] = 0xAD5F;
|
|
sVisitedRoomPal[15] = 0xAD5F;
|
|
sCurrentRoomPal[15] = 0xAD5F;
|
|
} else {
|
|
sCurrentRoomPal[15] = sVisitedRoomPal[15] = sUnvisitedRoomPal[15] = 0;
|
|
}
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
Gfx_SetupDL39_Opa(play->state.gfxCtx);
|
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha);
|
|
gDPLoadTLUT_pal16(POLY_OPA_DISP++, 0, sUnvisitedRoomPal);
|
|
gDPLoadTLUT_pal16(POLY_OPA_DISP++, 1, sVisitedRoomPal);
|
|
gDPLoadTLUT_pal16(POLY_OPA_DISP++, 2, sCurrentRoomPal);
|
|
gDPSetTextureLUT(POLY_OPA_DISP++, G_TT_RGBA16);
|
|
|
|
for (i = 0; i < sSceneNumRooms; i++) {
|
|
s32 texWidth;
|
|
s32 texHeight;
|
|
s32 offsetX;
|
|
s32 offsetY;
|
|
MapDataRoom* mapDataRoom;
|
|
TexturePtr roomTexture;
|
|
s32 s;
|
|
s32 t;
|
|
s32 dsdx;
|
|
s32 dtdy;
|
|
s32 texPosX;
|
|
s32 texPosY;
|
|
s32 spE8;
|
|
s32 two = 2;
|
|
|
|
mapDataRoom = &sMapDisp.mapDataScene->rooms[i];
|
|
if ((mapDataRoom->mapId == MAP_DATA_NO_MAP) || (mapDataRoom->mapId >= MAPDATA_MAP_GRAND_MAX)) {
|
|
continue;
|
|
}
|
|
|
|
if ((sMapDisp.pauseMapCurStorey < sMapDisp.roomStoreyList[i]) ||
|
|
((sMapDisp.roomStoreyList[i] + MAP_DATA_ROOM_GET_EXTRA_STOREYS(mapDataRoom)) <
|
|
sMapDisp.pauseMapCurStorey)) {
|
|
continue;
|
|
}
|
|
|
|
roomTexture = sPauseDungeonMap.roomSprite[i];
|
|
if (roomTexture == NULL) {
|
|
continue;
|
|
}
|
|
|
|
spE8 = MapData_GetMapCompactId(mapDataRoom->mapId);
|
|
if (spE8 == -1) {
|
|
continue;
|
|
}
|
|
|
|
MapData_CPID_GetTexDim(spE8, &texWidth, &texHeight);
|
|
MapData_CPID_GetTexOffset(spE8, &offsetX, &offsetY);
|
|
|
|
if (mapDataRoom->flags & MAP_DATA_ROOM_FLIP_X) {
|
|
offsetX = ((texWidth / 2) - offsetX) + (texWidth / 2);
|
|
s = (texWidth - 1) << 5;
|
|
dsdx = 0xFC00;
|
|
} else {
|
|
s = 0;
|
|
dsdx = 0x400;
|
|
}
|
|
|
|
if (mapDataRoom->flags & MAP_DATA_ROOM_FLIP_Y) {
|
|
s32 requiredScopeTemp;
|
|
|
|
offsetY = ((texHeight / 2) - offsetY) + (texHeight / 2);
|
|
t = (texHeight - 1) << 5;
|
|
dtdy = 0xFC00;
|
|
} else {
|
|
t = 0;
|
|
dtdy = 0x400;
|
|
}
|
|
|
|
texPosX =
|
|
((mapDataRoom->centerX - (f32)sMapDisp.sceneMidX) * scaleFrac - offsetX) + ((viewWidth / two) + viewX);
|
|
texPosY =
|
|
((mapDataRoom->centerZ - (f32)sMapDisp.sceneMidZ) * scaleFrac - offsetY) + ((viewHeight / two) + viewY);
|
|
|
|
if (i == play->roomCtx.curRoom.num) {
|
|
if (Map_IsInBossScene(play)) {
|
|
gDPLoadTextureBlock_4b(POLY_OPA_DISP++, roomTexture, G_IM_FMT_CI, texWidth, texHeight, 1,
|
|
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
|
|
G_TX_NOLOD, G_TX_NOLOD);
|
|
} else {
|
|
gDPLoadTextureBlock_4b(POLY_OPA_DISP++, roomTexture, G_IM_FMT_CI, texWidth, texHeight, 2,
|
|
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
|
|
G_TX_NOLOD, G_TX_NOLOD);
|
|
}
|
|
} else if (GET_ROOM_VISITED(Play_GetOriginalSceneId(MapDisp_ConvertBossSceneToDungeonScene(play->sceneId)),
|
|
i)) {
|
|
gDPLoadTextureBlock_4b(POLY_OPA_DISP++, roomTexture, G_IM_FMT_CI, texWidth, texHeight, 1,
|
|
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
|
|
G_TX_NOLOD, G_TX_NOLOD);
|
|
} else if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, dungeonSceneSharedIndex)) {
|
|
gDPLoadTextureBlock_4b(POLY_OPA_DISP++, roomTexture, G_IM_FMT_CI, texWidth, texHeight, 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);
|
|
} else {
|
|
continue;
|
|
}
|
|
gSPTextureRectangle(POLY_OPA_DISP++, (texPosX << 2), (texPosY << 2), (texPosX + texWidth) << 2,
|
|
(texPosY + texHeight) << 2, 0, s, t, dsdx, dtdy);
|
|
gDPPipeSync(POLY_OPA_DISP++);
|
|
}
|
|
|
|
gDPSetTextureLUT(POLY_OPA_DISP++, G_TT_NONE);
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* @brief Draws the chests for the pause menu dungeon map
|
|
*
|
|
* @param play
|
|
* @param viewX top left x position of the dungeon map view window
|
|
* @param viewY top left y posiiton of the dungeon map view window
|
|
* @param viewWidth width in pixels of the dungeon map view window
|
|
* @param viewHeight height in pixels of the dungeon map view window
|
|
* @param scaleFrac ratio to convert world space coordinates to map coordinates
|
|
* @param dungeonSceneSharedIndex enum DungeonSceneIndex for retrieving map/compass data
|
|
*/
|
|
void MapDisp_DrawChests(PlayState* play, s32 viewX, s32 viewY, s32 viewWidth, s32 viewHeight, f32 scaleFrac) {
|
|
s32 pad[23];
|
|
MapDataChest* mapDataChests = sMapDisp.mapDataChests;
|
|
s32 room;
|
|
MapDataRoom* mapDataRoom;
|
|
s32 texPosX;
|
|
s32 texPosY;
|
|
s32 i;
|
|
s32 isChestOpen;
|
|
s32 offsetX = 4;
|
|
s32 offsetZ = 4;
|
|
|
|
if (mapDataChests == NULL) {
|
|
return;
|
|
}
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
gDPPipeSync(POLY_OPA_DISP++);
|
|
gDPSetTextureLUT(POLY_OPA_DISP++, G_TT_NONE);
|
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, play->pauseCtx.alpha);
|
|
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
|
|
gDPPipeSync(POLY_OPA_DISP++);
|
|
|
|
gDPLoadTextureBlock_Runtime(POLY_OPA_DISP++, gMapChestIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 8, 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);
|
|
|
|
for (i = 0; i < sMapDisp.numChests; i++) {
|
|
room = mapDataChests[i].room;
|
|
mapDataRoom = &sMapDisp.mapDataScene->rooms[room];
|
|
|
|
switch (play->sceneId) {
|
|
case SCENE_MITURIN_BS:
|
|
isChestOpen = GET_CYCLE_CHEST_OPENED(SCENE_MITURIN, mapDataChests[i].chestFlagId);
|
|
break;
|
|
|
|
case SCENE_HAKUGIN_BS:
|
|
isChestOpen = GET_CYCLE_CHEST_OPENED(SCENE_HAKUGIN, mapDataChests[i].chestFlagId);
|
|
break;
|
|
|
|
case SCENE_SEA_BS:
|
|
isChestOpen = GET_CYCLE_CHEST_OPENED(SCENE_SEA, mapDataChests[i].chestFlagId);
|
|
break;
|
|
|
|
case SCENE_INISIE_BS:
|
|
isChestOpen = GET_CYCLE_CHEST_OPENED(SCENE_INISIE_N, mapDataChests[i].chestFlagId);
|
|
break;
|
|
|
|
default:
|
|
isChestOpen = Flags_GetTreasure(play, mapDataChests[i].chestFlagId);
|
|
break;
|
|
}
|
|
|
|
if ((sMapDisp.pauseMapCurStorey < sMapDisp.roomStoreyList[room]) ||
|
|
((sMapDisp.roomStoreyList[room] + MAP_DATA_ROOM_GET_EXTRA_STOREYS(mapDataRoom)) <
|
|
sMapDisp.pauseMapCurStorey) ||
|
|
(isChestOpen != 0)) {
|
|
continue;
|
|
}
|
|
|
|
if (!MapDisp_IsOnStorey((s32)sMapDisp.pauseMapCurStorey, (f32)mapDataChests[i].y)) {
|
|
continue;
|
|
}
|
|
|
|
texPosX =
|
|
(s32)((((mapDataChests[i].x - (f32)sMapDisp.sceneMidX) * scaleFrac) - offsetX) + ((viewWidth / 2) + viewX));
|
|
texPosY = (s32)((((mapDataChests[i].z - (f32)sMapDisp.sceneMidZ) * scaleFrac) - offsetZ) +
|
|
((viewHeight / 2) + viewY));
|
|
|
|
gSPTextureRectangle(POLY_OPA_DISP++, texPosX << 2, texPosY << 2, (texPosX + 8) << 2, (texPosY + 8) << 2,
|
|
G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
/**
|
|
* @brief Draws the room exit points for the pause menu dungeon map
|
|
*
|
|
* @param play
|
|
* @param viewX top left x position of the dungeon map view window
|
|
* @param viewY top left y posiiton of the dungeon map view window
|
|
* @param viewWidth width in pixels of the dungeon map view window
|
|
* @param viewHeight height in pixels of the dungeon map view window
|
|
* @param scaleFrac ratio to convert world space coordinates to map coordinates
|
|
* @param dungeonSceneSharedIndex enum DungeonSceneIndex for retrieving map/compass data
|
|
*/
|
|
void MapDisp_DrawRoomExits(PlayState* play, s32 viewX, s32 viewY, s32 viewWidth, s32 viewHeight, f32 scaleFrac,
|
|
s32 dungeonSceneSharedIndex) {
|
|
PauseContext* pauseCtx = &play->pauseCtx;
|
|
TransitionActorList* transitionActors = &sTransitionActorList;
|
|
s32 texPosX;
|
|
s32 texPosY;
|
|
s32 i;
|
|
s8 roomA;
|
|
s8 roomB;
|
|
|
|
if (transitionActors->count != 0) {
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
|
gDPLoadTextureBlock_4b(POLY_OPA_DISP++, &sWhiteSquareTex, G_IM_FMT_I, 16, 16, 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);
|
|
for (i = 0; i < transitionActors->count; i++) {
|
|
if (MapDisp_IsOnStorey(sMapDisp.pauseMapCurStorey, sTransitionActors[i].pos.y)) {
|
|
if ((ABS_ALT(sTransitionActors[i].id) != ACTOR_EN_HOLL) &&
|
|
!MapDisp_IsBossDoor(sTransitionActors[i].params)) {
|
|
roomA = sTransitionActors[i].sides[0].room;
|
|
roomB = sTransitionActors[i].sides[1].room;
|
|
if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, gSaveContext.mapIndex) || (roomA < 0) ||
|
|
GET_ROOM_VISITED(Play_GetOriginalSceneId(MapDisp_ConvertBossSceneToDungeonScene(play->sceneId)),
|
|
roomA) ||
|
|
(roomB < 0) ||
|
|
GET_ROOM_VISITED(Play_GetOriginalSceneId(MapDisp_ConvertBossSceneToDungeonScene(play->sceneId)),
|
|
roomB)) {
|
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha);
|
|
|
|
texPosX = ((f32)sTransitionActors[i].pos.x - sMapDisp.sceneMidX) * scaleFrac +
|
|
((viewWidth / 2) + viewX);
|
|
texPosY = ((f32)sTransitionActors[i].pos.z - sMapDisp.sceneMidZ) * scaleFrac +
|
|
((viewHeight / 2) + viewY);
|
|
gSPTextureRectangle(POLY_OPA_DISP++, ((texPosX - 1) << 2), ((texPosY - 1) << 2),
|
|
((texPosX + 1) << 2), ((texPosY + 1) << 2), G_TX_RENDERTILE, 0, 0, 1 << 10,
|
|
1 << 10);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Draws the boss room icon for the pause menu dungeon map.
|
|
*
|
|
* @param play
|
|
* @param viewX top left x position of the dungeon map view window
|
|
* @param viewY top left y posiiton of the dungeon map view window
|
|
* @param viewWidth width in pixels of the dungeon map view window
|
|
* @param viewHeight height in pixels of the dungeon map view window
|
|
* @param scaleFrac ratio to convert world space coordinates to map coordinates
|
|
* @param dungeonSceneSharedIndex enum DungeonSceneIndex for retrieving map/compass data
|
|
*/
|
|
void MapDisp_DrawBossIcon(PlayState* play, s32 viewX, s32 viewY, s32 viewWidth, s32 viewHeight, f32 scaleFrac,
|
|
s32 dungeonSceneSharedIndex) {
|
|
s32 i;
|
|
TransitionActorList* transitionActorList = &sTransitionActorList;
|
|
s32 offsetX = 4;
|
|
s32 offsetZ = 4;
|
|
s32 texPosX;
|
|
s32 texPosY;
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
gDPPipeSync(POLY_OPA_DISP++);
|
|
gDPSetTextureLUT(POLY_OPA_DISP++, G_TT_NONE);
|
|
gDPSetRenderMode(POLY_OPA_DISP++, G_RM_AA_DEC_LINE, G_RM_NOOP2);
|
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, play->pauseCtx.alpha);
|
|
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
|
|
gDPPipeSync(POLY_OPA_DISP++);
|
|
|
|
if (CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, dungeonSceneSharedIndex)) {
|
|
gDPLoadTextureBlock_Runtime(POLY_OPA_DISP++, gMapBossIconTex, G_IM_FMT_IA, G_IM_SIZ_8b, 8, 8, 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);
|
|
|
|
for (i = 0; i < transitionActorList->count; i++) {
|
|
if (!MapDisp_IsBossDoor(sTransitionActors[i].params)) {
|
|
continue;
|
|
}
|
|
if (!MapDisp_IsOnStorey(sMapDisp.pauseMapCurStorey, sTransitionActors[i].pos.y)) {
|
|
continue;
|
|
}
|
|
if (ABS_ALT(sTransitionActors[i].id) == ACTOR_EN_HOLL) {
|
|
continue;
|
|
}
|
|
|
|
texPosX = ((((f32)sTransitionActors[i].pos.x - sMapDisp.sceneMidX) * scaleFrac) - offsetX) +
|
|
((viewWidth / 2) + viewX);
|
|
texPosY = ((((f32)sTransitionActors[i].pos.z - sMapDisp.sceneMidZ) * scaleFrac) - offsetZ) +
|
|
((viewHeight / 2) + viewY);
|
|
gSPTextureRectangle(POLY_OPA_DISP++, texPosX << 2, texPosY << 2, (texPosX + 8) << 2, (texPosY + 8) << 2,
|
|
G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
|
|
}
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
TexturePtr MapDisp_GetDungeonMapFloorTexture(s32 floorNumber) {
|
|
static TexturePtr sDungeonMapFloorTextures[] = {
|
|
gDungeonMap1FButtonTex, gDungeonMap2FButtonTex, gDungeonMap3FButtonTex, gDungeonMap4FButtonTex,
|
|
gDungeonMap5FButtonTex, gDungeonMap6FButtonTex, gDungeonMap7FButtonTex, gDungeonMap8FButtonTex,
|
|
gDungeonMapB1ButtonTex, gDungeonMapB2ButtonTex, gDungeonMapB3ButtonTex, gDungeonMapB4ButtonTex,
|
|
gDungeonMapB5ButtonTex, gDungeonMapB6ButtonTex, gDungeonMapB7ButtonTex, gDungeonMapB8ButtonTex,
|
|
};
|
|
if ((floorNumber >= 0) && (floorNumber < 8)) {
|
|
return sDungeonMapFloorTextures[floorNumber];
|
|
}
|
|
if ((floorNumber >= -8) && (floorNumber < 0)) {
|
|
return sDungeonMapFloorTextures[7 + -floorNumber];
|
|
}
|
|
return gDungeonMapBlankFloorButtonTex;
|
|
}
|
|
|
|
/**
|
|
* @brief Tests if the dungeon map on the Map screen should be drawn.
|
|
*
|
|
* @param play
|
|
* @return true if the map should be drawn, else false.
|
|
*/
|
|
s32 MapDisp_SkipDrawDungeonMap(PlayState* play) {
|
|
PauseContext* pauseCtx = &play->pauseCtx;
|
|
|
|
if (pauseCtx->pageIndex != PAUSE_MAP) {
|
|
return true;
|
|
}
|
|
if ((pauseCtx->state == PAUSE_STATE_SAVEPROMPT) || IS_PAUSE_STATE_GAMEOVER(pauseCtx)) {
|
|
return true;
|
|
}
|
|
if ((pauseCtx->state != PAUSE_STATE_MAIN) || (pauseCtx->mainState != PAUSE_MAIN_STATE_IDLE)) {
|
|
return true;
|
|
}
|
|
if (pauseCtx->alpha == 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void MapDisp_DrawDungeonFloorSelect(PlayState* play) {
|
|
PauseContext* pauseCtx = &play->pauseCtx;
|
|
s32 texULY;
|
|
s32 texLRY;
|
|
s16 texULX;
|
|
s16 texLRX;
|
|
s32 pad;
|
|
s32 storey;
|
|
s32 dungeonSceneSharedIndex = 0;
|
|
|
|
if ((sMapDisp.mapDataScene != NULL) && (sSceneNumRooms != 0) && !MapDisp_SkipDrawDungeonMap(play)) {
|
|
if (Map_IsInBossScene(play)) {
|
|
switch (play->sceneId) {
|
|
case SCENE_MITURIN_BS:
|
|
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_WOODFALL_TEMPLE;
|
|
break;
|
|
|
|
case SCENE_HAKUGIN_BS:
|
|
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_SNOWHEAD_TEMPLE;
|
|
break;
|
|
|
|
case SCENE_SEA_BS:
|
|
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_GREAT_BAY_TEMPLE;
|
|
break;
|
|
|
|
case SCENE_INISIE_BS:
|
|
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_STONE_TOWER_TEMPLE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
dungeonSceneSharedIndex = gSaveContext.mapIndex;
|
|
}
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
Gfx_SetupDL39_Opa(play->state.gfxCtx);
|
|
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 200, pauseCtx->alpha);
|
|
|
|
// Draw unlocked storeys
|
|
for (storey = 0; storey < sMapDisp.numStoreys; storey++) {
|
|
if (GET_DUNGEON_FLOOR_VISITED(
|
|
Play_GetOriginalSceneId(MapDisp_ConvertBossSceneToDungeonScene(play->sceneId)), 4 - storey) ||
|
|
CHECK_DUNGEON_ITEM_ALT(DUNGEON_MAP, dungeonSceneSharedIndex)) {
|
|
gDPLoadTextureBlock(POLY_OPA_DISP++, MapDisp_GetDungeonMapFloorTexture(sMapDisp.bottomStorey + storey),
|
|
G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 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);
|
|
gSPTextureRectangle(POLY_OPA_DISP++, 81 << 2, (125 - storey * 15) << 2, 105 << 2,
|
|
((125 - storey * 15) + 16) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
|
|
}
|
|
}
|
|
gDPPipeSync(POLY_OPA_DISP++);
|
|
|
|
// Draw currently selected storey
|
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 150, 150, 255, pauseCtx->alpha);
|
|
gDPLoadTextureBlock(
|
|
POLY_OPA_DISP++,
|
|
MapDisp_GetDungeonMapFloorTexture((sMapDisp.bottomStorey - pauseCtx->cursorMapDungeonItem) + 8),
|
|
G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 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);
|
|
|
|
texULX = 80;
|
|
texLRX = 106;
|
|
texULY = (5 + (pauseCtx->cursorMapDungeonItem * 0xF));
|
|
texLRY = texULY + 16;
|
|
if ((pauseCtx->cursorSpecialPos == 0) && (pauseCtx->cursorXIndex[1] == 0)) {
|
|
texLRX++;
|
|
texULX--;
|
|
texLRY += 4;
|
|
texULY -= 4;
|
|
gSPTextureRectangle(POLY_OPA_DISP++, texULX << 2, texULY << 2, texLRX << 2, (texLRY) << 2, G_TX_RENDERTILE,
|
|
0, 0, 0x036E, 0x02AA);
|
|
} else {
|
|
gSPTextureRectangle(POLY_OPA_DISP++, (texULX + 1) << 2, texULY << 2, (texLRX - 1) << 2, texLRY << 2,
|
|
G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
|
|
}
|
|
Gfx_SetupDL42_Opa(play->state.gfxCtx);
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
}
|
|
|
|
s32 MapDisp_IsValidStorey(s32 storey) {
|
|
if ((sMapDisp.mapDataScene == NULL) || (sSceneNumRooms == 0)) {
|
|
return false;
|
|
}
|
|
if ((storey < 0) || (storey > 5)) {
|
|
return false;
|
|
}
|
|
if (sMapDisp.storeyYList[storey] != FLOOR_MIN_Y) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
s32 MapDisp_GetPlayerStorey(s16 checkY) {
|
|
s32 i;
|
|
|
|
if ((sMapDisp.mapDataScene == NULL) || (sSceneNumRooms == 0)) {
|
|
return -1;
|
|
}
|
|
if (sMapDisp.numStoreys <= 1) {
|
|
return 0;
|
|
}
|
|
if ((sMapDisp.storeyYList[1] - 5) >= checkY) {
|
|
return 0;
|
|
}
|
|
for (i = 1; i < sMapDisp.numStoreys; i++) {
|
|
if (((sMapDisp.storeyYList[i] - 5) < checkY) && ((sMapDisp.storeyYList[i + 1] - 5) >= checkY)) {
|
|
return i;
|
|
}
|
|
}
|
|
return sMapDisp.numStoreys - 1;
|
|
}
|
|
|
|
typedef struct {
|
|
/* 0x0 */ s16 sceneId;
|
|
/* 0x4 */ s32 offsetX;
|
|
/* 0x8 */ s32 offsetY;
|
|
} MapCustomPosOffset; // size = 0xC
|
|
|
|
/**
|
|
* Draws the dungeon map within the pause menu's Map screen.
|
|
*
|
|
* @param play
|
|
*/
|
|
void MapDisp_DrawDungeonMap(PlayState* play) {
|
|
static MapCustomPosOffset sCustomMapOffset[] = {
|
|
{ SCENE_MITURIN, 0, -10 },
|
|
{ SCENE_MITURIN_BS, 0, -10 },
|
|
};
|
|
MapDataRoom* mapDataRoom;
|
|
f32 scaleFrac;
|
|
s32 scale;
|
|
s32 var_v0;
|
|
s32 dungeonSceneSharedIndex = 0;
|
|
s32 offsetX = 0;
|
|
s32 offsetY = 0;
|
|
|
|
if (MapDisp_SkipDrawDungeonMap(play)) {
|
|
return;
|
|
}
|
|
|
|
if (Map_IsInBossScene(play)) {
|
|
switch (play->sceneId) {
|
|
case SCENE_MITURIN_BS:
|
|
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_WOODFALL_TEMPLE;
|
|
break;
|
|
|
|
case SCENE_HAKUGIN_BS:
|
|
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_SNOWHEAD_TEMPLE;
|
|
break;
|
|
|
|
case SCENE_SEA_BS:
|
|
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_GREAT_BAY_TEMPLE;
|
|
break;
|
|
|
|
case SCENE_INISIE_BS:
|
|
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_STONE_TOWER_TEMPLE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
dungeonSceneSharedIndex = gSaveContext.mapIndex;
|
|
}
|
|
|
|
mapDataRoom = sMapDisp.mapDataScene->rooms;
|
|
if ((mapDataRoom->mapId == MAP_DATA_NO_MAP) || (mapDataRoom->mapId >= MAPDATA_MAP_GRAND_MAX)) {
|
|
return;
|
|
}
|
|
|
|
var_v0 = MapData_GetMapCompactId(mapDataRoom->mapId);
|
|
if (var_v0 == -1) {
|
|
return;
|
|
}
|
|
|
|
scale = MapData_CPID_GetMapScale(var_v0);
|
|
if (scale == 0) {
|
|
scale = 80;
|
|
}
|
|
|
|
for (var_v0 = 0; var_v0 < ARRAY_COUNT(sCustomMapOffset); var_v0++) {
|
|
if (play->sceneId == sCustomMapOffset[var_v0].sceneId) {
|
|
offsetX = sCustomMapOffset[var_v0].offsetX;
|
|
offsetY = sCustomMapOffset[var_v0].offsetY;
|
|
}
|
|
}
|
|
|
|
scaleFrac = 1.0f / scale;
|
|
|
|
MapDisp_DrawRooms(play, offsetX + 144, offsetY + 85, 120, 100, scaleFrac, dungeonSceneSharedIndex);
|
|
MapDisp_DrawRoomExits(play, offsetX + 144, offsetY + 85, 120, 100, scaleFrac, dungeonSceneSharedIndex);
|
|
MapDisp_DrawBossIcon(play, offsetX + 144, offsetY + 85, 120, 100, scaleFrac, dungeonSceneSharedIndex);
|
|
|
|
if (CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, dungeonSceneSharedIndex)) {
|
|
MapDisp_DrawChests(play, offsetX + 144, offsetY + 85, 120, 100, scaleFrac);
|
|
}
|
|
}
|
|
|
|
void MapDisp_UpdateDungeonMap(PlayState* play) {
|
|
sMapDisp.timer++;
|
|
if (!(sMapDisp.unk20 & 1)) {
|
|
sPauseDungeonMap.animTimer++;
|
|
if (sPauseDungeonMap.animTimer > 40) {
|
|
sMapDisp.unk20 |= 1;
|
|
}
|
|
} else {
|
|
sPauseDungeonMap.animTimer--;
|
|
if (sPauseDungeonMap.animTimer < 0) {
|
|
sMapDisp.unk20 &= ~1;
|
|
}
|
|
}
|
|
}
|