Shipwright/soh/src/overlays/actors/ovl_En_Changer/z_en_changer.c

300 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* File: z_en_changer.c
* Overlay: ovl_En_Changer
* Description: Treasure Box Shop Minigame
*/
#include "z_en_changer.h"
#include "vt.h"
#include "overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h"
#include "overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h"
#define FLAGS 0
typedef enum {
/* 0 */ CHEST_LEFT,
/* 1 */ CHEST_RIGHT
} ChangerChestSide;
void EnChanger_Init(Actor* thisx, PlayState* play);
void EnChanger_Destroy(Actor* thisx, PlayState* play);
void EnChanger_Update(Actor* thisx, PlayState* play);
void EnChanger_Wait(EnChanger* this, PlayState* play);
void EnChanger_OpenChests(EnChanger* this, PlayState* play);
void EnChanger_SetHeartPieceFlag(EnChanger* this, PlayState* play);
const ActorInit En_Changer_InitVars = {
ACTOR_EN_CHANGER,
ACTORCAT_PROP,
FLAGS,
OBJECT_GAMEPLAY_KEEP,
sizeof(EnChanger),
(ActorFunc)EnChanger_Init,
(ActorFunc)EnChanger_Destroy,
(ActorFunc)EnChanger_Update,
NULL,
NULL,
};
static Vec3f sLeftChestPos[] = {
{ 0.0f, 0.0f, 0.0f }, { -100.0f, 20.0f, -245.0f }, { -100.0f, 20.0f, -685.0f },
{ -100.0f, 20.0f, -1125.0f }, { -100.0f, 20.0f, -1565.0f }, { -100.0f, 20.0f, -2005.0f },
};
static Vec3f sRightChestPos[] = {
{ 0.0f, 0.0f, 0.0f }, { 140.0f, 20.0f, -245.0f }, { 140.0f, 20.0f, -685.0f },
{ 140.0f, 20.0f, -1125.0f }, { 140.0f, 20.0f, -1565.0f }, { 140.0f, 20.0f, -2005.0f },
};
static s32 sLoserGetItemIds[] = {
GI_NONE, GI_RUPEE_GREEN_LOSE, GI_RUPEE_GREEN_LOSE, GI_RUPEE_BLUE_LOSE, GI_RUPEE_BLUE_LOSE, GI_RUPEE_RED_LOSE,
};
static s32 sItemEtcTypes[] = {
0,
ITEM_ETC_RUPEE_GREEN_CHEST_GAME,
ITEM_ETC_RUPEE_GREEN_CHEST_GAME,
ITEM_ETC_RUPEE_BLUE_CHEST_GAME,
ITEM_ETC_RUPEE_BLUE_CHEST_GAME,
ITEM_ETC_RUPEE_RED_CHEST_GAME,
};
static s32 sTreasureFlags[] = { 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A };
void EnChanger_Destroy(Actor* thisx, PlayState* play) {
}
void EnChanger_Init(Actor* thisx, PlayState* play2) {
EnChanger* this = (EnChanger*)thisx;
PlayState* play = play2;
s16 leftChestParams;
s16 rightChestParams;
s16 rewardChestParams;
s16 minigameRoomNum;
s16 rightChestItem;
s16 leftChestItem;
s16 temp_v1_3;
s16 new_var;
s32 rewardParams;
minigameRoomNum = play->roomCtx.curRoom.num - 1;
if (minigameRoomNum < 0) {
minigameRoomNum = 0;
}
if (Flags_GetTreasure(play, sTreasureFlags[minigameRoomNum])) {
this->roomChestsOpened = true;
}
osSyncPrintf("\n\n");
// "Treasure generation (which room is it?)"
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 宝発生(部屋はどれ?) %d\n" VT_RST, play->roomCtx.curRoom.num);
// "How is the Bit?"
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ ビットは? \t %x\n" VT_RST, play->actorCtx.flags.chest);
// "How is the Save BIT?"
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ セーブBITは? %x\n" VT_RST, sTreasureFlags[minigameRoomNum]);
// "Is it already a zombie?"
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ もう、ゾンビ?\t %d\n" VT_RST, this->roomChestsOpened);
osSyncPrintf("\n\n");
minigameRoomNum *= 2;
// Spawn Heart Piece in chest (or Purple Rupee if won Heart Piece)
if (play->roomCtx.curRoom.num >= 6) {
rewardChestParams = ((gSaveContext.itemGetInf[1] & 0x800) ? (0x4EA0) : (0x4EC0));
rewardChestParams = sTreasureFlags[5] | rewardChestParams;
this->finalChest = (EnBox*)Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_BOX,
20.0f, 20.0f, -2500.0f, 0, 0x7FFF, 0, rewardChestParams);
if (this->finalChest != NULL) {
if (this->roomChestsOpened) {
Flags_SetTreasure(play, rewardChestParams & 0x1F);
Actor_Kill(&this->actor);
return;
} else {
rewardParams = ((gSaveContext.itemGetInf[1] & 0x800) ? (ITEM_ETC_RUPEE_PURPLE_CHEST_GAME)
: (ITEM_ETC_HEART_PIECE_CHEST_GAME)) &
0xFF;
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_ETCETERA, 20.0f, 20.0f, -2500.0f, 0, 0, 0,
((sTreasureFlags[5] & 0x1F) << 8) + rewardParams, true);
// "Central treasure instance/occurrence (GREAT)"
osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ 中央宝発生() ☆☆☆☆☆ %x\n" VT_RST, rewardChestParams);
this->actionFunc = EnChanger_SetHeartPieceFlag;
return;
}
}
}
temp_v1_3 = minigameRoomNum;
// Set up items in chests, swap them round with probability 1/2
leftChestParams = (sLoserGetItemIds[play->roomCtx.curRoom.num] << 5) | 0x4000;
new_var = temp_v1_3;
this->leftChestNum = new_var;
this->leftChestGetItemId = sLoserGetItemIds[play->roomCtx.curRoom.num];
leftChestItem = sItemEtcTypes[play->roomCtx.curRoom.num];
leftChestParams |= new_var;
rightChestParams = new_var | 0x4E21;
this->rightChestNum = new_var | 1;
this->rightChestGetItemId = GI_DOOR_KEY;
rightChestItem = ITEM_ETC_KEY_SMALL_CHEST_GAME;
if (Rand_ZeroFloat(1.99f) < 1.0f) {
rightChestParams = (sLoserGetItemIds[play->roomCtx.curRoom.num] << 5) | 0x4000;
this->rightChestNum = new_var;
this->rightChestGetItemId = sLoserGetItemIds[play->roomCtx.curRoom.num];
rightChestItem = sItemEtcTypes[play->roomCtx.curRoom.num];
leftChestParams = new_var | 0x4E21;
rightChestParams |= new_var;
this->leftChestNum = temp_v1_3 | 1;
this->leftChestGetItemId = GI_DOOR_KEY;
leftChestItem = ITEM_ETC_KEY_SMALL_CHEST_GAME;
}
this->leftChest = (EnBox*)Actor_SpawnAsChild(
&play->actorCtx, &this->actor, play, ACTOR_EN_BOX, sLeftChestPos[play->roomCtx.curRoom.num].x,
sLeftChestPos[play->roomCtx.curRoom.num].y, sLeftChestPos[play->roomCtx.curRoom.num].z, 0, -0x3FFF, 0,
leftChestParams);
if (this->leftChest != NULL) {
// "Left treasure generation (what does it contain?)"
osSyncPrintf(VT_FGCOL(PURPLE) "☆☆☆☆☆ 左宝発生(ナニがはいってるの?) ☆☆☆☆☆ %x\n" VT_RST, leftChestParams);
// "What is the room number?"
osSyncPrintf(VT_FGCOL(PURPLE) "☆☆☆☆☆ 部屋番号は? %x\n" VT_RST, play->roomCtx.curRoom.num);
// "What is the bit?"
osSyncPrintf(VT_FGCOL(PURPLE) "☆☆☆☆☆ ビットはなぁに? %x\n" VT_RST, this->rightChestNum);
// "Sukesuke-kun" (something to do with being invisible)
osSyncPrintf(VT_FGCOL(PURPLE) "☆☆☆☆☆ すけすけ君? %x\n" VT_RST, rightChestItem);
osSyncPrintf("\n\n");
if (this->roomChestsOpened) {
Flags_SetTreasure(play, this->leftChestNum & 0x1F);
} else {
Actor_Spawn(
&play->actorCtx, play, ACTOR_ITEM_ETCETERA, sLeftChestPos[play->roomCtx.curRoom.num].x,
sLeftChestPos[play->roomCtx.curRoom.num].y, sLeftChestPos[play->roomCtx.curRoom.num].z, 0, 0,
0, ((this->leftChestNum & 0x1F) << 8) + (leftChestItem & 0xFF), true);
}
}
this->rightChest = (EnBox*)Actor_SpawnAsChild(
&play->actorCtx, &this->actor, play, ACTOR_EN_BOX, sRightChestPos[play->roomCtx.curRoom.num].x,
sRightChestPos[play->roomCtx.curRoom.num].y, sRightChestPos[play->roomCtx.curRoom.num].z, 0, 0x3FFF,
0, rightChestParams);
if (this->rightChest != NULL) {
// "Right treasure generation (what does it contain?)"
osSyncPrintf(VT_FGCOL(CYAN) "☆☆☆☆☆ 右宝発生(ナニがはいってるの?) ☆☆☆☆☆ %x\n" VT_RST, rightChestParams);
// "What is the room number?"
osSyncPrintf(VT_FGCOL(CYAN) "☆☆☆☆☆ 部屋番号は? %d\n" VT_RST, play->roomCtx.curRoom.num);
// "What is the bit?"
osSyncPrintf(VT_FGCOL(CYAN) "☆☆☆☆☆ ビットはなぁに? %x\n" VT_RST, this->leftChestNum);
// "Sukesuke-kun" (something to do with being invisible)
osSyncPrintf(VT_FGCOL(CYAN) "☆☆☆☆☆ すけすけ君? %x\n" VT_RST, leftChestItem);
osSyncPrintf("\n\n");
if (this->roomChestsOpened) {
Flags_SetTreasure(play, this->rightChestNum & 0x1F);
Actor_Kill(&this->actor);
return;
}
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_ETCETERA,
sRightChestPos[play->roomCtx.curRoom.num].x, sRightChestPos[play->roomCtx.curRoom.num].y,
sRightChestPos[play->roomCtx.curRoom.num].z, 0, 0, 0,
((this->rightChestNum & 0x1F) << 8) + (rightChestItem & 0xFF), true);
}
this->actor.flags &= ~ACTOR_FLAG_0;
this->actionFunc = EnChanger_Wait;
}
void EnChanger_Wait(EnChanger* this, PlayState* play) {
if (this->leftChest->unk_1F4 != 0) {
this->timer = 80;
Flags_SetTreasure(play, this->rightChestNum & 0x1F);
this->actionFunc = EnChanger_OpenChests;
} else if (this->rightChest->unk_1F4 != 0) {
this->chestOpened = CHEST_RIGHT;
this->timer = 80;
Flags_SetTreasure(play, this->leftChestNum & 0x1F);
this->actionFunc = EnChanger_OpenChests;
}
}
// Spawns the EnExItem showing what was in the other chest
void EnChanger_OpenChests(EnChanger* this, PlayState* play) {
f32 zPos;
f32 yPos;
f32 xPos;
s16 temp_s0;
s16 temp_s0_2;
EnBox* left;
EnBox* right;
left = this->leftChest;
right = this->rightChest;
if (this->timer == 0) {
temp_s0_2 = temp_s0 = this->chestOpened; // Required to use the right registers
switch (temp_s0_2) {
case CHEST_LEFT:
xPos = right->dyna.actor.world.pos.x;
yPos = right->dyna.actor.world.pos.y;
zPos = right->dyna.actor.world.pos.z;
if (this->rightChestGetItemId == GI_DOOR_KEY) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, 0xF, true);
Flags_SetSwitch(play, 0x32);
} else {
temp_s0_2 = (s16)(this->rightChestGetItemId - GI_RUPEE_GREEN_LOSE) + EXITEM_CHEST;
// "Open right treasure (chest)"
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 右宝開く ☆☆☆☆☆ %d\n" VT_RST, temp_s0_2);
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0,
temp_s0_2, true);
}
break;
case CHEST_RIGHT:
xPos = left->dyna.actor.world.pos.x;
yPos = left->dyna.actor.world.pos.y;
zPos = left->dyna.actor.world.pos.z;
if (this->leftChestGetItemId == GI_DOOR_KEY) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0, 0xF, true);
Flags_SetSwitch(play, 0x32);
} else {
temp_s0_2 = (s16)(this->leftChestGetItemId - 0x72) + 0xA;
// "Open left treasure (chest)"
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 左宝開く ☆☆☆☆☆ %d\n" VT_RST, temp_s0_2);
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_EX_ITEM, xPos, yPos, zPos, 0, 0, 0,
temp_s0_2, true);
}
break;
}
Actor_Kill(&this->actor);
}
}
void EnChanger_SetHeartPieceFlag(EnChanger* this, PlayState* play) {
if (this->finalChest->unk_1F4 != 0) {
if (!(gSaveContext.itemGetInf[1] & 0x800)) {
gSaveContext.itemGetInf[1] |= 0x800;
}
Actor_Kill(&this->actor);
}
}
void EnChanger_Update(Actor* thisx, PlayState* play) {
EnChanger* this = (EnChanger*)thisx;
this->actionFunc(this, play);
if (this->timer != 0) {
this->timer--;
}
if (BREG(0)) {
DebugDisplay_AddObject(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z,
this->actor.world.rot.x, this->actor.world.rot.y, this->actor.world.rot.z, 1.0f, 1.0f,
1.0f, 255, 0, 255, 255, 4, play->state.gfxCtx);
}
}