1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2024-11-25 09:45:02 +00:00

Document Magic (#1199)

* Magic docs WIP

* More docs, first round finished

* Better docs

* More renaming

* Simpler name

* Another small adjustment

* rm if(1)

* Better names again after in-game testing

* Change comments

* change comment

* Big rename based on all the suggestions

* Small touch-up

* More PR Suggestions

* RESTORE_IDLE -> RESET

* More docs

* Capitalization

* PR suggestions

* Make declaration consistent

* Health_ChangeBy (amount)

* PR Suggestions

* Missed one

* More PR Suggestions

* Change comment

* Add another clarity comment

* Discord discussions on `magicFillTarget`

* Comments

* grammar

* More comment clarity

* Another bad comment

* PR suggestions, improved comments

* One more comment

* one more thing

* bar -> meter
This commit is contained in:
engineer124 2022-05-24 02:52:01 +10:00 committed by GitHub
parent 2e6279bc8e
commit e68f321777
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 327 additions and 249 deletions

View file

@ -53,8 +53,8 @@
<Texture Name="gAmmoDigit8Tex" OutName="ammo_digit_8" Format="ia8" Width="8" Height="8" Offset="0x37C0"/> <Texture Name="gAmmoDigit8Tex" OutName="ammo_digit_8" Format="ia8" Width="8" Height="8" Offset="0x37C0"/>
<Texture Name="gAmmoDigit9Tex" OutName="ammo_digit_9" Format="ia8" Width="8" Height="8" Offset="0x3800"/> <Texture Name="gAmmoDigit9Tex" OutName="ammo_digit_9" Format="ia8" Width="8" Height="8" Offset="0x3800"/>
<Texture Name="gUnusedAmmoDigitHalfTex" OutName="unused_ammo_digit_half" Format="ia8" Width="16" Height="8" Offset="0x3840"/> <Texture Name="gUnusedAmmoDigitHalfTex" OutName="unused_ammo_digit_half" Format="ia8" Width="16" Height="8" Offset="0x3840"/>
<Texture Name="gMagicBarEndTex" OutName="magic_bar_end" Format="ia8" Width="8" Height="16" Offset="0x38C0"/> <Texture Name="gMagicMeterEndTex" OutName="magic_meter_end" Format="ia8" Width="8" Height="16" Offset="0x38C0"/>
<Texture Name="gMagicBarMidTex" OutName="magic_bar_mid" Format="ia8" Width="24" Height="16" Offset="0x3940"/> <Texture Name="gMagicMeterMidTex" OutName="magic_meter_mid" Format="ia8" Width="24" Height="16" Offset="0x3940"/>
<Texture Name="gMagicBarFillTex" OutName="magic_bar_fill" Format="ia8" Width="8" Height="8" Offset="0x3AC0"/> <Texture Name="gMagicMeterFillTex" OutName="magic_meter_fill" Format="ia8" Width="8" Height="8" Offset="0x3AC0"/>
</File> </File>
</Root> </Root>

View file

@ -1026,12 +1026,12 @@ s32 Inventory_ConsumeFairy(PlayState* play);
void Interface_SetDoAction(PlayState* play, u16 action); void Interface_SetDoAction(PlayState* play, u16 action);
void Interface_SetNaviCall(PlayState* play, u16 naviCallState); void Interface_SetNaviCall(PlayState* play, u16 naviCallState);
void Interface_LoadActionLabelB(PlayState* play, u16 action); void Interface_LoadActionLabelB(PlayState* play, u16 action);
s32 Health_ChangeBy(PlayState* play, s16 healthChange); s32 Health_ChangeBy(PlayState* play, s16 amount);
void Rupees_ChangeBy(s16 rupeeChange); void Rupees_ChangeBy(s16 rupeeChange);
void Inventory_ChangeAmmo(s16 item, s16 ammoChange); void Inventory_ChangeAmmo(s16 item, s16 ammoChange);
void Magic_Fill(PlayState* play); void Magic_Fill(PlayState* play);
void func_800876C8(PlayState* play); void Magic_Reset(PlayState* play);
s32 func_80087708(PlayState* play, s16 arg1, s16 arg2); s32 Magic_RequestChange(PlayState* play, s16 amount, s16 type);
void func_80088AA0(s16 arg0); void func_80088AA0(s16 arg0);
void func_80088AF0(PlayState* play); void func_80088AF0(PlayState* play);
void func_80088B34(s16 arg0); void func_80088B34(s16 arg0);

View file

@ -95,9 +95,9 @@
#define R_A_ICON_Y XREG(19) #define R_A_ICON_Y XREG(19)
#define R_A_ICON_X XREG(20) #define R_A_ICON_X XREG(20)
#define R_A_BTN_COLOR(i) XREG(22 + i) #define R_A_BTN_COLOR(i) XREG(22 + i)
#define R_MAGIC_BAR_SMALL_Y XREG(48) #define R_MAGIC_METER_Y_HIGHER XREG(48)
#define R_MAGIC_BAR_X XREG(49) #define R_MAGIC_METER_X XREG(49)
#define R_MAGIC_BAR_LARGE_Y XREG(50) #define R_MAGIC_METER_Y_LOWER XREG(50)
#define R_MAGIC_FILL_X XREG(51) #define R_MAGIC_FILL_X XREG(51)
#define R_ENV_LIGHT1_DIR(i) cREG(3 + i) #define R_ENV_LIGHT1_DIR(i) cREG(3 + i)
#define R_ENV_LIGHT2_DIR(i) cREG(6 + i) #define R_ENV_LIGHT2_DIR(i) cREG(6 + i)

View file

@ -610,7 +610,7 @@ typedef struct {
/* 0x022A */ s16 beatingHeartOscillator; /* 0x022A */ s16 beatingHeartOscillator;
/* 0x022C */ s16 beatingHeartOscillatorDirection; /* 0x022C */ s16 beatingHeartOscillatorDirection;
/* 0x022E */ s16 unk_22E; /* 0x022E */ s16 unk_22E;
/* 0x0230 */ s16 unk_230; /* 0x0230 */ s16 lensMagicConsumptionTimer; // When lens is active, 1 unit of magic is consumed every time the timer reaches 0
/* 0x0232 */ s16 counterDigits[4]; // used for key and rupee counters /* 0x0232 */ s16 counterDigits[4]; // used for key and rupee counters
/* 0x023A */ u8 numHorseBoosts; /* 0x023A */ u8 numHorseBoosts;
/* 0x023C */ u16 unk_23C; /* 0x023C */ u16 unk_23C;

View file

@ -4,6 +4,32 @@
#include "ultra64.h" #include "ultra64.h"
#include "z64math.h" #include "z64math.h"
typedef enum {
/* 0x0 */ MAGIC_STATE_IDLE, // Regular gameplay
/* 0x1 */ MAGIC_STATE_CONSUME_SETUP, // Sets the speed at which magic border flashes
/* 0x2 */ MAGIC_STATE_CONSUME, // Consume magic until target is reached or no more magic is available
/* 0x3 */ MAGIC_STATE_METER_FLASH_1, // Flashes border and freezes Dark Link
/* 0x4 */ MAGIC_STATE_METER_FLASH_2, // Flashes border and draws yellow magic to preview target consumption
/* 0x5 */ MAGIC_STATE_RESET, // Reset colors and return to idle
/* 0x6 */ MAGIC_STATE_METER_FLASH_3, // Flashes border with no additional behaviour
/* 0x7 */ MAGIC_STATE_CONSUME_LENS, // Magic slowly consumed by lens.
/* 0x8 */ MAGIC_STATE_STEP_CAPACITY, // Step `magicCapacity` to full capacity
/* 0x9 */ MAGIC_STATE_FILL, // Add magic until magicFillTarget is reached.
/* 0xA */ MAGIC_STATE_ADD // Add requested magic
} MagicState;
typedef enum {
/* 0 */ MAGIC_CONSUME_NOW, // Consume Magic immediately without preview
/* 1 */ MAGIC_CONSUME_WAIT_NO_PREVIEW, // Sets consume target but waits to consume. No yellow magic preview to target consumption. Unused
/* 2 */ MAGIC_CONSUME_NOW_ALT, // Identical behaviour to MAGIC_CONSUME_NOW. Unused
/* 3 */ MAGIC_CONSUME_LENS, // Lens consumption
/* 4 */ MAGIC_CONSUME_WAIT_PREVIEW, // Sets consume target but waits to consume. Draws yellow magic to target consumption
/* 5 */ MAGIC_ADD // Sets a target to add magic
} MagicChangeType;
#define MAGIC_NORMAL_METER 0x30
#define MAGIC_DOUBLE_METER (2 * MAGIC_NORMAL_METER)
typedef struct { typedef struct {
/* 0x00 */ u8 buttonItems[4]; /* 0x00 */ u8 buttonItems[4];
/* 0x04 */ u8 cButtonSlots[3]; /* 0x04 */ u8 cButtonSlots[3];
@ -87,14 +113,14 @@ typedef struct {
/* 0x002C */ s16 n64ddFlag; /* 0x002C */ s16 n64ddFlag;
/* 0x002E */ s16 healthCapacity; // "max_life" /* 0x002E */ s16 healthCapacity; // "max_life"
/* 0x0030 */ s16 health; // "now_life" /* 0x0030 */ s16 health; // "now_life"
/* 0x0032 */ s8 magicLevel; /* 0x0032 */ s8 magicLevel; // 0 for no magic/new load, 1 for magic, 2 for double magic
/* 0x0033 */ s8 magic; /* 0x0033 */ s8 magic; // current magic available for use
/* 0x0034 */ s16 rupees; /* 0x0034 */ s16 rupees;
/* 0x0036 */ u16 swordHealth; /* 0x0036 */ u16 swordHealth;
/* 0x0038 */ u16 naviTimer; /* 0x0038 */ u16 naviTimer;
/* 0x003A */ u8 magicAcquired; /* 0x003A */ u8 isMagicAcquired;
/* 0x003B */ char unk_3B[0x01]; /* 0x003B */ char unk_3B[0x01];
/* 0x003C */ u8 doubleMagic; /* 0x003C */ u8 isDoubleMagicAcquired;
/* 0x003D */ u8 doubleDefense; /* 0x003D */ u8 doubleDefense;
/* 0x003E */ u8 bgsFlag; /* 0x003E */ u8 bgsFlag;
/* 0x003F */ u8 ocarinaGameRoundNum; /* 0x003F */ u8 ocarinaGameRoundNum;
@ -156,11 +182,11 @@ typedef struct {
/* 0x13EA */ u16 unk_13EA; // also alpha type? /* 0x13EA */ u16 unk_13EA; // also alpha type?
/* 0x13EC */ u16 unk_13EC; // alpha type counter? /* 0x13EC */ u16 unk_13EC; // alpha type counter?
/* 0x13EE */ u16 unk_13EE; // previous alpha type? /* 0x13EE */ u16 unk_13EE; // previous alpha type?
/* 0x13F0 */ s16 unk_13F0; // magic related /* 0x13F0 */ s16 magicState; // determines magic meter behavior on each frame
/* 0x13F2 */ s16 unk_13F2; // magic related /* 0x13F2 */ s16 prevMagicState; // used to resume the previous state after adding or filling magic
/* 0x13F4 */ s16 unk_13F4; // magic related /* 0x13F4 */ s16 magicCapacity; // maximum magic available
/* 0x13F6 */ s16 unk_13F6; // magic related /* 0x13F6 */ s16 magicFillTarget; // target used to fill magic. Target can either be full capacity (Magic_Fill, magic upgrades), or the saved magic amount (loading a file, game over)
/* 0x13F8 */ s16 unk_13F8; // magic related /* 0x13F8 */ s16 magicTarget; // target for magic to step to when adding or consuming magic
/* 0x13FA */ u16 eventInf[4]; // "event_inf" /* 0x13FA */ u16 eventInf[4]; // "event_inf"
/* 0x1402 */ u16 mapIndex; // intended for maps/minimaps but commonly used as the dungeon index /* 0x1402 */ u16 mapIndex; // intended for maps/minimaps but commonly used as the dungeon index
/* 0x1404 */ u16 minigameState; /* 0x1404 */ u16 minigameState;

View file

@ -1950,7 +1950,7 @@ void func_80030488(PlayState* play) {
void Actor_DisableLens(PlayState* play) { void Actor_DisableLens(PlayState* play) {
if (play->actorCtx.lensActive) { if (play->actorCtx.lensActive) {
play->actorCtx.lensActive = false; play->actorCtx.lensActive = false;
func_800876C8(play); Magic_Reset(play);
} }
} }

View file

@ -18,7 +18,7 @@ void func_801109B0(PlayState* play) {
interfaceCtx->unk_1FA = interfaceCtx->unk_261 = interfaceCtx->unk_1FC = 0; interfaceCtx->unk_1FA = interfaceCtx->unk_261 = interfaceCtx->unk_1FC = 0;
interfaceCtx->unk_1EC = interfaceCtx->unk_1EE = interfaceCtx->unk_1F0 = 0; interfaceCtx->unk_1EC = interfaceCtx->unk_1EE = interfaceCtx->unk_1F0 = 0;
interfaceCtx->unk_22E = 0; interfaceCtx->unk_22E = 0;
interfaceCtx->unk_230 = 16; interfaceCtx->lensMagicConsumptionTimer = 16;
interfaceCtx->unk_1F4 = 0.0f; interfaceCtx->unk_1F4 = 0.0f;
interfaceCtx->unk_228 = XREG(95); interfaceCtx->unk_228 = XREG(95);
interfaceCtx->minimapAlpha = 0; interfaceCtx->minimapAlpha = 0;
@ -382,9 +382,9 @@ void func_80111070(void) {
XREG(45) = 36; XREG(45) = 36;
XREG(46) = 16; XREG(46) = 16;
XREG(47) = 8; XREG(47) = 8;
R_MAGIC_BAR_SMALL_Y = 34; R_MAGIC_METER_Y_HIGHER = 34;
R_MAGIC_BAR_X = 18; R_MAGIC_METER_X = 18;
R_MAGIC_BAR_LARGE_Y = 42; R_MAGIC_METER_Y_LOWER = 42;
R_MAGIC_FILL_X = 26; R_MAGIC_FILL_X = 26;
XREG(52) = 0; XREG(52) = 0;
XREG(53) = 1; XREG(53) = 1;

View file

@ -54,7 +54,7 @@ u32 ElfMessage_CheckCondition(ElfMessage* msg) {
return ((msg->byte0 & 1) == 1) == return ((msg->byte0 & 1) == 1) ==
(CHECK_QUEST_ITEM(msg->byte3 - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST) != 0); (CHECK_QUEST_ITEM(msg->byte3 - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST) != 0);
case (ELF_MSG_CONDITION_MAGIC << 4): case (ELF_MSG_CONDITION_MAGIC << 4):
return ((msg->byte0 & 1) == 1) == (((void)0, gSaveContext.magicAcquired) != 0); return ((msg->byte0 & 1) == 1) == (((void)0, gSaveContext.isMagicAcquired) != 0);
} }
} }

View file

@ -15,7 +15,8 @@ void KaleidoSetup_Update(PlayState* play) {
if (pauseCtx->state == 0 && pauseCtx->debugState == 0 && play->gameOverCtx.state == GAMEOVER_INACTIVE && if (pauseCtx->state == 0 && pauseCtx->debugState == 0 && play->gameOverCtx.state == GAMEOVER_INACTIVE &&
play->transitionTrigger == TRANS_TRIGGER_OFF && play->transitionMode == TRANS_MODE_OFF && play->transitionTrigger == TRANS_TRIGGER_OFF && play->transitionMode == TRANS_MODE_OFF &&
gSaveContext.cutsceneIndex < 0xFFF0 && gSaveContext.nextCutsceneIndex < 0xFFF0 && !Play_InCsMode(play) && gSaveContext.cutsceneIndex < 0xFFF0 && gSaveContext.nextCutsceneIndex < 0xFFF0 && !Play_InCsMode(play) &&
play->shootingGalleryStatus <= 1 && gSaveContext.unk_13F0 != 8 && gSaveContext.unk_13F0 != 9 && play->shootingGalleryStatus <= 1 && gSaveContext.magicState != MAGIC_STATE_STEP_CAPACITY &&
gSaveContext.magicState != MAGIC_STATE_FILL &&
(play->sceneNum != SCENE_BOWLING || !Flags_GetSwitch(play, 0x38))) { (play->sceneNum != SCENE_BOWLING || !Flags_GetSwitch(play, 0x38))) {
if (CHECK_BTN_ALL(input->cur.button, BTN_L) && CHECK_BTN_ALL(input->press.button, BTN_CUP)) { if (CHECK_BTN_ALL(input->cur.button, BTN_L) && CHECK_BTN_ALL(input->press.button, BTN_CUP)) {

View file

@ -1696,11 +1696,14 @@ u8 Item_Give(PlayState* play, u8 item) {
Health_ChangeBy(play, 0x10); Health_ChangeBy(play, 0x10);
return item; return item;
} else if (item == ITEM_MAGIC_SMALL) { } else if (item == ITEM_MAGIC_SMALL) {
if (gSaveContext.unk_13F0 != 10) { if (gSaveContext.magicState != MAGIC_STATE_ADD) {
// This function is only used to store the magicState.
// Setting the state to FILL gets immediately overwritten in Magic_RequestChange.
// I.e. magic is added not filled
Magic_Fill(play); Magic_Fill(play);
} }
func_80087708(play, 12, 5); Magic_RequestChange(play, 12, MAGIC_ADD);
if (!GET_INFTABLE(INFTABLE_198)) { if (!GET_INFTABLE(INFTABLE_198)) {
SET_INFTABLE(INFTABLE_198); SET_INFTABLE(INFTABLE_198);
@ -1709,11 +1712,14 @@ u8 Item_Give(PlayState* play, u8 item) {
return item; return item;
} else if (item == ITEM_MAGIC_LARGE) { } else if (item == ITEM_MAGIC_LARGE) {
if (gSaveContext.unk_13F0 != 10) { if (gSaveContext.magicState != MAGIC_STATE_ADD) {
// This function is only used to store the magicState.
// Setting the state to FILL gets immediately overwritten in Magic_RequestChange.
// I.e. magic is added not filled.
Magic_Fill(play); Magic_Fill(play);
} }
func_80087708(play, 24, 5); Magic_RequestChange(play, 24, MAGIC_ADD);
if (!GET_INFTABLE(INFTABLE_198)) { if (!GET_INFTABLE(INFTABLE_198)) {
SET_INFTABLE(INFTABLE_198); SET_INFTABLE(INFTABLE_198);
@ -2149,25 +2155,27 @@ void Interface_LoadActionLabelB(PlayState* play, u16 action) {
interfaceCtx->unk_1FA = true; interfaceCtx->unk_1FA = true;
} }
s32 Health_ChangeBy(PlayState* play, s16 healthChange) { /**
* @return false if player is out of health
*/
s32 Health_ChangeBy(PlayState* play, s16 amount) {
u16 heartCount; u16 heartCount;
u16 healthLevel; u16 healthLevel;
// " Fluctuation=%d (now=%d, max=%d) " // " Fluctuation=%d (now=%d, max=%d) "
osSyncPrintf(" 増減=%d (now=%d, max=%d) ", healthChange, gSaveContext.health, osSyncPrintf(" 増減=%d (now=%d, max=%d) ", amount, gSaveContext.health,
gSaveContext.healthCapacity); gSaveContext.healthCapacity);
// clang-format off // clang-format off
if (healthChange > 0) { Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &gSfxDefaultPos, 4, if (amount > 0) { Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
&gSfxDefaultReverb); } else if (gSaveContext.doubleDefense && (amount < 0)) {
} else if (gSaveContext.doubleDefense && (healthChange < 0)) { amount >>= 1;
healthChange >>= 1; osSyncPrintf("ハート減少半分!!=%d\n", amount); // "Heart decrease halved!!%d"
osSyncPrintf("ハート減少半分!!=%d\n", healthChange); // "Heart decrease halved!!%d"
} }
// clang-format on // clang-format on
gSaveContext.health += healthChange; gSaveContext.health += amount;
if (gSaveContext.health > gSaveContext.healthCapacity) { if (gSaveContext.health > gSaveContext.healthCapacity) {
gSaveContext.health = gSaveContext.healthCapacity; gSaveContext.health = gSaveContext.healthCapacity;
@ -2265,115 +2273,133 @@ void Inventory_ChangeAmmo(s16 item, s16 ammoChange) {
} }
void Magic_Fill(PlayState* play) { void Magic_Fill(PlayState* play) {
if (gSaveContext.magicAcquired) { if (gSaveContext.isMagicAcquired) {
gSaveContext.unk_13F2 = gSaveContext.unk_13F0; gSaveContext.prevMagicState = gSaveContext.magicState;
gSaveContext.unk_13F6 = (gSaveContext.doubleMagic * 0x30) + 0x30; gSaveContext.magicFillTarget = (gSaveContext.isDoubleMagicAcquired + 1) * MAGIC_NORMAL_METER;
gSaveContext.unk_13F0 = 9; gSaveContext.magicState = MAGIC_STATE_FILL;
} }
} }
void func_800876C8(PlayState* play) { void Magic_Reset(PlayState* play) {
if ((gSaveContext.unk_13F0 != 8) && (gSaveContext.unk_13F0 != 9)) { if ((gSaveContext.magicState != MAGIC_STATE_STEP_CAPACITY) && (gSaveContext.magicState != MAGIC_STATE_FILL)) {
if (gSaveContext.unk_13F0 == 10) { if (gSaveContext.magicState == MAGIC_STATE_ADD) {
gSaveContext.unk_13F2 = gSaveContext.unk_13F0; gSaveContext.prevMagicState = gSaveContext.magicState;
} }
gSaveContext.unk_13F0 = 5; gSaveContext.magicState = MAGIC_STATE_RESET;
} }
} }
s32 func_80087708(PlayState* play, s16 arg1, s16 arg2) { /**
if (!gSaveContext.magicAcquired) { * Request to either increase or consume magic.
return 0; * @param amount the positive-valued amount to either increase or decrease magic by
* @param type how the magic is increased or consumed.
* @return false if the request failed
*/
s32 Magic_RequestChange(PlayState* play, s16 amount, s16 type) {
if (!gSaveContext.isMagicAcquired) {
return false;
} }
if ((arg2 != 5) && (gSaveContext.magic - arg1) < 0) { if ((type != MAGIC_ADD) && (gSaveContext.magic - amount) < 0) {
if (gSaveContext.unk_13F4 != 0) { if (gSaveContext.magicCapacity != 0) {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} }
return 0; return false;
} }
switch (arg2) { switch (type) {
case 0: case MAGIC_CONSUME_NOW:
case 2: case MAGIC_CONSUME_NOW_ALT:
if ((gSaveContext.unk_13F0 == 0) || (gSaveContext.unk_13F0 == 7)) { // Consume magic immediately
if (gSaveContext.unk_13F0 == 7) { if ((gSaveContext.magicState == MAGIC_STATE_IDLE) ||
(gSaveContext.magicState == MAGIC_STATE_CONSUME_LENS)) {
if (gSaveContext.magicState == MAGIC_STATE_CONSUME_LENS) {
play->actorCtx.lensActive = false; play->actorCtx.lensActive = false;
} }
gSaveContext.unk_13F8 = gSaveContext.magic - arg1; gSaveContext.magicTarget = gSaveContext.magic - amount;
gSaveContext.unk_13F0 = 1; gSaveContext.magicState = MAGIC_STATE_CONSUME_SETUP;
return 1; return true;
} else { } else {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
return 0; return false;
} }
case 1:
if ((gSaveContext.unk_13F0 == 0) || (gSaveContext.unk_13F0 == 7)) { case MAGIC_CONSUME_WAIT_NO_PREVIEW:
if (gSaveContext.unk_13F0 == 7) { // Sets consume target but waits to consume.
// No yellow magic to preview target consumption.
// Unused
if ((gSaveContext.magicState == MAGIC_STATE_IDLE) ||
(gSaveContext.magicState == MAGIC_STATE_CONSUME_LENS)) {
if (gSaveContext.magicState == MAGIC_STATE_CONSUME_LENS) {
play->actorCtx.lensActive = false; play->actorCtx.lensActive = false;
} }
gSaveContext.unk_13F8 = gSaveContext.magic - arg1; gSaveContext.magicTarget = gSaveContext.magic - amount;
gSaveContext.unk_13F0 = 6; gSaveContext.magicState = MAGIC_STATE_METER_FLASH_3;
return 1; return true;
} else { } else {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
return 0; return false;
} }
case 3:
if (gSaveContext.unk_13F0 == 0) { case MAGIC_CONSUME_LENS:
if (gSaveContext.magicState == MAGIC_STATE_IDLE) {
if (gSaveContext.magic != 0) { if (gSaveContext.magic != 0) {
play->interfaceCtx.unk_230 = 80; play->interfaceCtx.lensMagicConsumptionTimer = 80;
gSaveContext.unk_13F0 = 7; gSaveContext.magicState = MAGIC_STATE_CONSUME_LENS;
return 1; return true;
} else { } else {
return 0; return false;
} }
} else if (gSaveContext.magicState == MAGIC_STATE_CONSUME_LENS) {
return true;
} else { } else {
if (gSaveContext.unk_13F0 == 7) { return false;
return 1;
} else {
return 0;
}
} }
case 4:
if ((gSaveContext.unk_13F0 == 0) || (gSaveContext.unk_13F0 == 7)) { case MAGIC_CONSUME_WAIT_PREVIEW:
if (gSaveContext.unk_13F0 == 7) { // Sets consume target but waits to consume.
// Preview consumption with a yellow bar
if ((gSaveContext.magicState == MAGIC_STATE_IDLE) ||
(gSaveContext.magicState == MAGIC_STATE_CONSUME_LENS)) {
if (gSaveContext.magicState == MAGIC_STATE_CONSUME_LENS) {
play->actorCtx.lensActive = false; play->actorCtx.lensActive = false;
} }
gSaveContext.unk_13F8 = gSaveContext.magic - arg1; gSaveContext.magicTarget = gSaveContext.magic - amount;
gSaveContext.unk_13F0 = 4; gSaveContext.magicState = MAGIC_STATE_METER_FLASH_2;
return 1; return true;
} else { } else {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
return 0; return false;
} }
case 5:
if (gSaveContext.unk_13F4 >= gSaveContext.magic) {
gSaveContext.unk_13F8 = gSaveContext.magic + arg1;
if (gSaveContext.unk_13F8 >= gSaveContext.unk_13F4) { case MAGIC_ADD:
gSaveContext.unk_13F8 = gSaveContext.unk_13F4; // Sets target for magic to increase to
if (gSaveContext.magic <= gSaveContext.magicCapacity) {
gSaveContext.magicTarget = gSaveContext.magic + amount;
if (gSaveContext.magicTarget >= gSaveContext.magicCapacity) {
gSaveContext.magicTarget = gSaveContext.magicCapacity;
} }
gSaveContext.unk_13F0 = 10; gSaveContext.magicState = MAGIC_STATE_ADD;
return 1; return true;
} }
break; break;
} }
return 0; return false;
} }
void Interface_UpdateMagicBar(PlayState* play) { void Magic_Update(PlayState* play) {
static s16 sMagicBorderColors[][3] = { static s16 sMagicBorderColors[][3] = {
{ 255, 255, 255 }, { 255, 255, 255 },
{ 150, 150, 150 }, { 150, 150, 150 },
{ 255, 255, 150 }, { 255, 255, 150 }, // unused
{ 255, 255, 50 }, { 255, 255, 50 }, // unused
}; };
static s16 sMagicBorderIndices[] = { 0, 1, 1, 0 }; static s16 sMagicBorderIndices[] = { 0, 1, 1, 0 };
static s16 sMagicBorderRatio = 2; static s16 sMagicBorderRatio = 2;
@ -2383,29 +2409,34 @@ void Interface_UpdateMagicBar(PlayState* play) {
s16 borderChangeR; s16 borderChangeR;
s16 borderChangeG; s16 borderChangeG;
s16 borderChangeB; s16 borderChangeB;
s16 temp; s16 temp; // target for magicCapacity, or magicBorderIndex
switch (gSaveContext.unk_13F0) { switch (gSaveContext.magicState) {
case 8: case MAGIC_STATE_STEP_CAPACITY:
temp = gSaveContext.magicLevel * 0x30; // Step magicCapacity to the capacity determined by magicLevel
if (gSaveContext.unk_13F4 != temp) { // This changes the width of the magic meter drawn
if (gSaveContext.unk_13F4 < temp) { temp = gSaveContext.magicLevel * MAGIC_NORMAL_METER;
gSaveContext.unk_13F4 += 8; if (gSaveContext.magicCapacity != temp) {
if (gSaveContext.unk_13F4 > temp) { if (gSaveContext.magicCapacity < temp) {
gSaveContext.unk_13F4 = temp; gSaveContext.magicCapacity += 8;
if (gSaveContext.magicCapacity > temp) {
gSaveContext.magicCapacity = temp;
} }
} else { } else {
gSaveContext.unk_13F4 -= 8; gSaveContext.magicCapacity -= 8;
if (gSaveContext.unk_13F4 <= temp) { if (gSaveContext.magicCapacity <= temp) {
gSaveContext.unk_13F4 = temp; gSaveContext.magicCapacity = temp;
} }
} }
} else { } else {
gSaveContext.unk_13F0 = 9; // Once the capacity has reached its target,
// follow up by filling magic to magicFillTarget
gSaveContext.magicState = MAGIC_STATE_FILL;
} }
break; break;
case 9: case MAGIC_STATE_FILL:
// Add magic until magicFillTarget is reached
gSaveContext.magic += 4; gSaveContext.magic += 4;
if (gSaveContext.gameMode == 0 && gSaveContext.sceneSetupIndex < 4) { if (gSaveContext.gameMode == 0 && gSaveContext.sceneSetupIndex < 4) {
@ -2414,32 +2445,36 @@ void Interface_UpdateMagicBar(PlayState* play) {
} }
// "Storage MAGIC_NOW=%d (%d)" // "Storage MAGIC_NOW=%d (%d)"
osSyncPrintf("蓄電 MAGIC_NOW=%d (%d)\n", gSaveContext.magic, gSaveContext.unk_13F6); osSyncPrintf("蓄電 MAGIC_NOW=%d (%d)\n", gSaveContext.magic, gSaveContext.magicFillTarget);
if (gSaveContext.magic >= gSaveContext.unk_13F6) {
gSaveContext.magic = gSaveContext.unk_13F6; if (gSaveContext.magic >= gSaveContext.magicFillTarget) {
gSaveContext.unk_13F0 = gSaveContext.unk_13F2; gSaveContext.magic = gSaveContext.magicFillTarget;
gSaveContext.unk_13F2 = 0; gSaveContext.magicState = gSaveContext.prevMagicState;
gSaveContext.prevMagicState = MAGIC_STATE_IDLE;
} }
break; break;
case 1: case MAGIC_STATE_CONSUME_SETUP:
// Sets the speed at which magic border flashes
sMagicBorderRatio = 2; sMagicBorderRatio = 2;
gSaveContext.unk_13F0 = 2; gSaveContext.magicState = MAGIC_STATE_CONSUME;
break; break;
case 2: case MAGIC_STATE_CONSUME:
// Consume magic until target is reached or no more magic is available
gSaveContext.magic -= 2; gSaveContext.magic -= 2;
if (gSaveContext.magic <= 0) { if (gSaveContext.magic <= 0) {
gSaveContext.magic = 0; gSaveContext.magic = 0;
gSaveContext.unk_13F0 = 3; gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1;
sMagicBorderR = sMagicBorderG = sMagicBorderB = 255; sMagicBorderR = sMagicBorderG = sMagicBorderB = 255;
} else if (gSaveContext.magic == gSaveContext.unk_13F8) { } else if (gSaveContext.magic == gSaveContext.magicTarget) {
gSaveContext.unk_13F0 = 3; gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1;
sMagicBorderR = sMagicBorderG = sMagicBorderB = 255; sMagicBorderR = sMagicBorderG = sMagicBorderB = 255;
} }
case 3: // fallthrough (flash border while magic is being consumed)
case 4: case MAGIC_STATE_METER_FLASH_1:
case 6: case MAGIC_STATE_METER_FLASH_2:
case MAGIC_STATE_METER_FLASH_3:
temp = sMagicBorderIndices[sMagicBorderStep]; temp = sMagicBorderIndices[sMagicBorderStep];
borderChangeR = ABS(sMagicBorderR - sMagicBorderColors[temp][0]) / sMagicBorderRatio; borderChangeR = ABS(sMagicBorderR - sMagicBorderColors[temp][0]) / sMagicBorderRatio;
borderChangeG = ABS(sMagicBorderG - sMagicBorderColors[temp][1]) / sMagicBorderRatio; borderChangeG = ABS(sMagicBorderG - sMagicBorderColors[temp][1]) / sMagicBorderRatio;
@ -2476,12 +2511,13 @@ void Interface_UpdateMagicBar(PlayState* play) {
} }
break; break;
case 5: case MAGIC_STATE_RESET:
sMagicBorderR = sMagicBorderG = sMagicBorderB = 255; sMagicBorderR = sMagicBorderG = sMagicBorderB = 255;
gSaveContext.unk_13F0 = 0; gSaveContext.magicState = MAGIC_STATE_IDLE;
break; break;
case 7: case MAGIC_STATE_CONSUME_LENS:
// Slowly consume magic while lens is on
if ((play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0) && (msgCtx->msgMode == MSGMODE_NONE) && if ((play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0) && (msgCtx->msgMode == MSGMODE_NONE) &&
(play->gameOverCtx.state == GAMEOVER_INACTIVE) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->gameOverCtx.state == GAMEOVER_INACTIVE) && (play->transitionTrigger == TRANS_TRIGGER_OFF) &&
(play->transitionMode == TRANS_MODE_OFF) && !Play_InCsMode(play)) { (play->transitionMode == TRANS_MODE_OFF) && !Play_InCsMode(play)) {
@ -2490,18 +2526,19 @@ void Interface_UpdateMagicBar(PlayState* play) {
(gSaveContext.equips.buttonItems[2] != ITEM_LENS) && (gSaveContext.equips.buttonItems[2] != ITEM_LENS) &&
(gSaveContext.equips.buttonItems[3] != ITEM_LENS)) || (gSaveContext.equips.buttonItems[3] != ITEM_LENS)) ||
!play->actorCtx.lensActive) { !play->actorCtx.lensActive) {
// Force lens off and set magic meter state to idle
play->actorCtx.lensActive = false; play->actorCtx.lensActive = false;
Audio_PlaySoundGeneral(NA_SE_SY_GLASSMODE_OFF, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySoundGeneral(NA_SE_SY_GLASSMODE_OFF, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
gSaveContext.unk_13F0 = 0; gSaveContext.magicState = MAGIC_STATE_IDLE;
sMagicBorderR = sMagicBorderG = sMagicBorderB = 255; sMagicBorderR = sMagicBorderG = sMagicBorderB = 255;
break; break;
} }
interfaceCtx->unk_230--; interfaceCtx->lensMagicConsumptionTimer--;
if (interfaceCtx->unk_230 == 0) { if (interfaceCtx->lensMagicConsumptionTimer == 0) {
gSaveContext.magic--; gSaveContext.magic--;
interfaceCtx->unk_230 = 80; interfaceCtx->lensMagicConsumptionTimer = 80;
} }
} }
@ -2541,34 +2578,35 @@ void Interface_UpdateMagicBar(PlayState* play) {
} }
break; break;
case 10: case MAGIC_STATE_ADD:
// Add magic until target is reached
gSaveContext.magic += 4; gSaveContext.magic += 4;
Audio_PlaySoundGeneral(NA_SE_SY_GAUGE_UP - SFX_FLAG, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySoundGeneral(NA_SE_SY_GAUGE_UP - SFX_FLAG, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
if (gSaveContext.magic >= gSaveContext.unk_13F8) { if (gSaveContext.magic >= gSaveContext.magicTarget) {
gSaveContext.magic = gSaveContext.unk_13F8; gSaveContext.magic = gSaveContext.magicTarget;
gSaveContext.unk_13F0 = gSaveContext.unk_13F2; gSaveContext.magicState = gSaveContext.prevMagicState;
gSaveContext.unk_13F2 = 0; gSaveContext.prevMagicState = MAGIC_STATE_IDLE;
} }
break; break;
default: default:
gSaveContext.unk_13F0 = 0; gSaveContext.magicState = MAGIC_STATE_IDLE;
break; break;
} }
} }
void Interface_DrawMagicBar(PlayState* play) { void Magic_DrawMeter(PlayState* play) {
InterfaceContext* interfaceCtx = &play->interfaceCtx; InterfaceContext* interfaceCtx = &play->interfaceCtx;
s16 magicBarY; s16 magicMeterY;
OPEN_DISPS(play->state.gfxCtx, "../z_parameter.c", 2650); OPEN_DISPS(play->state.gfxCtx, "../z_parameter.c", 2650);
if (gSaveContext.magicLevel != 0) { if (gSaveContext.magicLevel != 0) {
if (gSaveContext.healthCapacity > 0xA0) { if (gSaveContext.healthCapacity > 0xA0) {
magicBarY = R_MAGIC_BAR_LARGE_Y; magicMeterY = R_MAGIC_METER_Y_LOWER; // two rows of hearts
} else { } else {
magicBarY = R_MAGIC_BAR_SMALL_Y; magicMeterY = R_MAGIC_METER_Y_HIGHER; // one row of hearts
} }
func_80094520(play->state.gfxCtx); func_80094520(play->state.gfxCtx);
@ -2576,55 +2614,55 @@ void Interface_DrawMagicBar(PlayState* play) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, sMagicBorderR, sMagicBorderG, sMagicBorderB, interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, sMagicBorderR, sMagicBorderG, sMagicBorderB, interfaceCtx->magicAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 100, 50, 50, 255); gDPSetEnvColor(OVERLAY_DISP++, 100, 50, 50, 255);
OVERLAY_DISP = OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gMagicMeterEndTex, 8, 16, R_MAGIC_METER_X, magicMeterY, 8, 16,
Gfx_TextureIA8(OVERLAY_DISP, gMagicBarEndTex, 8, 16, R_MAGIC_BAR_X, magicBarY, 8, 16, 1 << 10, 1 << 10); 1 << 10, 1 << 10);
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gMagicBarMidTex, 24, 16, R_MAGIC_BAR_X + 8, magicBarY, OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gMagicMeterMidTex, 24, 16, R_MAGIC_METER_X + 8, magicMeterY,
gSaveContext.unk_13F4, 16, 1 << 10, 1 << 10); gSaveContext.magicCapacity, 16, 1 << 10, 1 << 10);
gDPLoadTextureBlock(OVERLAY_DISP++, gMagicBarEndTex, G_IM_FMT_IA, G_IM_SIZ_8b, 8, 16, 0, gDPLoadTextureBlock(OVERLAY_DISP++, gMagicMeterEndTex, G_IM_FMT_IA, G_IM_SIZ_8b, 8, 16, 0,
G_TX_MIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 3, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); G_TX_MIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 3, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gSPTextureRectangle(OVERLAY_DISP++, ((R_MAGIC_BAR_X + gSaveContext.unk_13F4) + 8) << 2, magicBarY << 2, gSPTextureRectangle(OVERLAY_DISP++, ((R_MAGIC_METER_X + gSaveContext.magicCapacity) + 8) << 2, magicMeterY << 2,
((R_MAGIC_BAR_X + gSaveContext.unk_13F4) + 16) << 2, (magicBarY + 16) << 2, G_TX_RENDERTILE, ((R_MAGIC_METER_X + gSaveContext.magicCapacity) + 16) << 2, (magicMeterY + 16) << 2,
256, 0, 1 << 10, 1 << 10); G_TX_RENDERTILE, 256, 0, 1 << 10, 1 << 10);
gDPPipeSync(OVERLAY_DISP++); gDPPipeSync(OVERLAY_DISP++);
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, PRIMITIVE, PRIMITIVE, gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, PRIMITIVE, PRIMITIVE,
ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, PRIMITIVE); ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, PRIMITIVE);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255);
if (gSaveContext.unk_13F0 == 4) { if (gSaveContext.magicState == MAGIC_STATE_METER_FLASH_2) {
// Yellow part of the bar indicating the amount of magic to be subtracted // Yellow part of the meter indicating the amount of magic to be subtracted
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 250, 250, 0, interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 250, 250, 0, interfaceCtx->magicAlpha);
gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicBarFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0, gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicMeterFillTex, 0, G_TX_RENDERTILE, 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_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD); G_TX_NOLOD, G_TX_NOLOD);
gSPTextureRectangle(OVERLAY_DISP++, R_MAGIC_FILL_X << 2, (magicBarY + 3) << 2, gSPTextureRectangle(OVERLAY_DISP++, R_MAGIC_FILL_X << 2, (magicMeterY + 3) << 2,
(R_MAGIC_FILL_X + gSaveContext.magic) << 2, (magicBarY + 10) << 2, G_TX_RENDERTILE, 0, (R_MAGIC_FILL_X + gSaveContext.magic) << 2, (magicMeterY + 10) << 2, G_TX_RENDERTILE, 0,
0, 1 << 10, 1 << 10); 0, 1 << 10, 1 << 10);
// Fill the rest of the bar with the normal magic color // Fill the rest of the meter with the normal magic color
gDPPipeSync(OVERLAY_DISP++); gDPPipeSync(OVERLAY_DISP++);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2),
interfaceCtx->magicAlpha); interfaceCtx->magicAlpha);
gSPTextureRectangle(OVERLAY_DISP++, R_MAGIC_FILL_X << 2, (magicBarY + 3) << 2, gSPTextureRectangle(OVERLAY_DISP++, R_MAGIC_FILL_X << 2, (magicMeterY + 3) << 2,
(R_MAGIC_FILL_X + gSaveContext.unk_13F8) << 2, (magicBarY + 10) << 2, G_TX_RENDERTILE, (R_MAGIC_FILL_X + gSaveContext.magicTarget) << 2, (magicMeterY + 10) << 2,
0, 0, 1 << 10, 1 << 10); G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
} else { } else {
// Fill the whole bar with the normal magic color // Fill the whole meter with the normal magic color
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2),
interfaceCtx->magicAlpha); interfaceCtx->magicAlpha);
gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicBarFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0, gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicMeterFillTex, 0, G_TX_RENDERTILE, 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_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD); G_TX_NOLOD, G_TX_NOLOD);
gSPTextureRectangle(OVERLAY_DISP++, R_MAGIC_FILL_X << 2, (magicBarY + 3) << 2, gSPTextureRectangle(OVERLAY_DISP++, R_MAGIC_FILL_X << 2, (magicMeterY + 3) << 2,
(R_MAGIC_FILL_X + gSaveContext.magic) << 2, (magicBarY + 10) << 2, G_TX_RENDERTILE, 0, (R_MAGIC_FILL_X + gSaveContext.magic) << 2, (magicMeterY + 10) << 2, G_TX_RENDERTILE, 0,
0, 1 << 10, 1 << 10); 0, 1 << 10, 1 << 10);
} }
} }
@ -3161,7 +3199,7 @@ void Interface_Draw(PlayState* play) {
16, svar3, 206, 8, 16, 1 << 10, 1 << 10); 16, svar3, 206, 8, 16, 1 << 10, 1 << 10);
} }
Interface_DrawMagicBar(play); Magic_DrawMeter(play);
Minimap_Draw(play); Minimap_Draw(play);
if ((R_PAUSE_MENU_MODE != 2) && (R_PAUSE_MENU_MODE != 3)) { if ((R_PAUSE_MENU_MODE != 2) && (R_PAUSE_MENU_MODE != 3)) {
@ -4076,22 +4114,24 @@ void Interface_Update(PlayState* play) {
WREG(7) = interfaceCtx->unk_1F4; WREG(7) = interfaceCtx->unk_1F4;
// Update Magic
if ((play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0) && (msgCtx->msgMode == MSGMODE_NONE) && if ((play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0) && (msgCtx->msgMode == MSGMODE_NONE) &&
(play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->gameOverCtx.state == GAMEOVER_INACTIVE) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->gameOverCtx.state == GAMEOVER_INACTIVE) &&
(play->transitionMode == TRANS_MODE_OFF) && ((play->csCtx.state == CS_STATE_IDLE) || !Player_InCsMode(play))) { (play->transitionMode == TRANS_MODE_OFF) && ((play->csCtx.state == CS_STATE_IDLE) || !Player_InCsMode(play))) {
if ((gSaveContext.magicAcquired != 0) && (gSaveContext.magicLevel == 0)) {
gSaveContext.magicLevel = gSaveContext.doubleMagic + 1; if (gSaveContext.isMagicAcquired && (gSaveContext.magicLevel == 0)) {
gSaveContext.unk_13F0 = 8; gSaveContext.magicLevel = gSaveContext.isDoubleMagicAcquired + 1;
gSaveContext.magicState = MAGIC_STATE_STEP_CAPACITY;
osSyncPrintf(VT_FGCOL(YELLOW)); osSyncPrintf(VT_FGCOL(YELLOW));
osSyncPrintf("魔法スター─────ト!!!!!!!!!\n"); // "Magic Start!!!!!!!!!" osSyncPrintf("魔法スター─────ト!!!!!!!!!\n"); // "Magic Start!!!!!!!!!"
osSyncPrintf("MAGIC_MAX=%d\n", gSaveContext.magicLevel); osSyncPrintf("MAGIC_MAX=%d\n", gSaveContext.magicLevel);
osSyncPrintf("MAGIC_NOW=%d\n", gSaveContext.magic); osSyncPrintf("MAGIC_NOW=%d\n", gSaveContext.magic);
osSyncPrintf("Z_MAGIC_NOW_NOW=%d\n", gSaveContext.unk_13F6); osSyncPrintf("Z_MAGIC_NOW_NOW=%d\n", gSaveContext.magicFillTarget);
osSyncPrintf("Z_MAGIC_NOW_MAX=%d\n", gSaveContext.unk_13F4); osSyncPrintf("Z_MAGIC_NOW_MAX=%d\n", gSaveContext.magicCapacity);
osSyncPrintf(VT_RST); osSyncPrintf(VT_RST);
} }
Interface_UpdateMagicBar(play); Magic_Update(play);
} }
if (gSaveContext.timer1State == 0) { if (gSaveContext.timer1State == 0) {

View file

@ -271,7 +271,7 @@ void Play_Init(GameState* thisx) {
if (gSaveContext.gameMode != 0 || gSaveContext.cutsceneIndex >= 0xFFF0) { if (gSaveContext.gameMode != 0 || gSaveContext.cutsceneIndex >= 0xFFF0) {
gSaveContext.nayrusLoveTimer = 0; gSaveContext.nayrusLoveTimer = 0;
func_800876C8(this); Magic_Reset(this);
gSaveContext.sceneSetupIndex = (gSaveContext.cutsceneIndex & 0xF) + 4; gSaveContext.sceneSetupIndex = (gSaveContext.cutsceneIndex & 0xF) + 4;
} else if (!LINK_IS_ADULT && IS_DAY) { } else if (!LINK_IS_ADULT && IS_DAY) {
gSaveContext.sceneSetupIndex = 0; gSaveContext.sceneSetupIndex = 0;

View file

@ -483,7 +483,8 @@ s32 Player_InBlockingCsMode(PlayState* play, Player* this) {
return (this->stateFlags1 & (PLAYER_STATE1_7 | PLAYER_STATE1_29)) || (this->csMode != 0) || return (this->stateFlags1 & (PLAYER_STATE1_7 | PLAYER_STATE1_29)) || (this->csMode != 0) ||
(play->transitionTrigger == TRANS_TRIGGER_START) || (this->stateFlags1 & PLAYER_STATE1_0) || (play->transitionTrigger == TRANS_TRIGGER_START) || (this->stateFlags1 & PLAYER_STATE1_0) ||
(this->stateFlags3 & PLAYER_STATE3_7) || (this->stateFlags3 & PLAYER_STATE3_7) ||
((gSaveContext.unk_13F0 != 0) && (Player_ActionToMagicSpell(this, this->itemActionParam) >= 0)); ((gSaveContext.magicState != MAGIC_STATE_IDLE) &&
(Player_ActionToMagicSpell(this, this->itemActionParam) >= 0));
} }
s32 Player_InCsMode(PlayState* play) { s32 Player_InCsMode(PlayState* play) {

View file

@ -17,9 +17,9 @@ typedef struct {
/* 0x18 */ s16 rupees; /* 0x18 */ s16 rupees;
/* 0x1A */ u16 swordHealth; /* 0x1A */ u16 swordHealth;
/* 0x1C */ u16 naviTimer; /* 0x1C */ u16 naviTimer;
/* 0x1E */ u8 magicAcquired; /* 0x1E */ u8 isMagicAcquired;
/* 0x1F */ u8 unk_1F; /* 0x1F */ u8 unk_1F;
/* 0x20 */ u8 doubleMagic; /* 0x20 */ u8 isDoubleMagicAcquired;
/* 0x21 */ u8 doubleDefense; /* 0x21 */ u8 doubleDefense;
/* 0x22 */ u8 bgsFlag; /* 0x22 */ u8 bgsFlag;
/* 0x23 */ u8 ocarinaGameRoundNum; /* 0x23 */ u8 ocarinaGameRoundNum;
@ -104,13 +104,13 @@ static SavePlayerData sNewSavePlayerData = {
0x30, // healthCapacity 0x30, // healthCapacity
0x30, // defense 0x30, // defense
0, // magicLevel 0, // magicLevel
0x30, // magic MAGIC_NORMAL_METER, // magic
0, // rupees 0, // rupees
0, // swordHealth 0, // swordHealth
0, // naviTimer 0, // naviTimer
0, // magicAcquired false, // isMagicAcquired
0, // unk_1F 0, // unk_1F
0, // doubleMagic false, // isDoubleMagicAcquired
0, // doubleDefense 0, // doubleDefense
0, // bgsFlag 0, // bgsFlag
0, // ocarinaGameRoundNum 0, // ocarinaGameRoundNum
@ -189,13 +189,13 @@ static SavePlayerData sDebugSavePlayerData = {
0xE0, // healthCapacity 0xE0, // healthCapacity
0xE0, // health 0xE0, // health
0, // magicLevel 0, // magicLevel
0x30, // magic MAGIC_NORMAL_METER, // magic
150, // rupees 150, // rupees
8, // swordHealth 8, // swordHealth
0, // naviTimer 0, // naviTimer
1, // magicAcquired true, // isMagicAcquired
0, // unk_1F 0, // unk_1F
0, // doubleMagic false, // isDoubleMagicAcquired
0, // doubleDefense 0, // doubleDefense
0, // bgsFlag 0, // bgsFlag
0, // ocarinaGameRoundNum 0, // ocarinaGameRoundNum

View file

@ -54,7 +54,7 @@ void ArrowFire_Init(Actor* thisx, PlayState* play) {
} }
void ArrowFire_Destroy(Actor* thisx, PlayState* play) { void ArrowFire_Destroy(Actor* thisx, PlayState* play) {
func_800876C8(play); Magic_Reset(play);
LOG_STRING("消滅", "../z_arrow_fire.c", 421); // "Disappearance" LOG_STRING("消滅", "../z_arrow_fire.c", 421); // "Disappearance"
} }

View file

@ -55,7 +55,7 @@ void ArrowIce_Init(Actor* thisx, PlayState* play) {
} }
void ArrowIce_Destroy(Actor* thisx, PlayState* play) { void ArrowIce_Destroy(Actor* thisx, PlayState* play) {
func_800876C8(play); Magic_Reset(play);
LOG_STRING("消滅", "../z_arrow_ice.c", 415); // "Disappearance" LOG_STRING("消滅", "../z_arrow_ice.c", 415); // "Disappearance"
} }

View file

@ -55,7 +55,7 @@ void ArrowLight_Init(Actor* thisx, PlayState* play) {
} }
void ArrowLight_Destroy(Actor* thisx, PlayState* play) { void ArrowLight_Destroy(Actor* thisx, PlayState* play) {
func_800876C8(play); Magic_Reset(play);
LOG_STRING("消滅", "../z_arrow_light.c", 403); // "Disappearance" LOG_STRING("消滅", "../z_arrow_light.c", 403); // "Disappearance"
} }

View file

@ -181,12 +181,12 @@ void BgDyYoseizo_CheckMagicAcquired(BgDyYoseizo* this, PlayState* play) {
if (Flags_GetSwitch(play, 0x38)) { if (Flags_GetSwitch(play, 0x38)) {
play->msgCtx.ocarinaMode = OCARINA_MODE_04; play->msgCtx.ocarinaMode = OCARINA_MODE_04;
if (play->sceneNum == SCENE_DAIYOUSEI_IZUMI) { if (play->sceneNum == SCENE_DAIYOUSEI_IZUMI) {
if (!gSaveContext.magicAcquired && (this->fountainType != FAIRY_UPGRADE_MAGIC)) { if (!gSaveContext.isMagicAcquired && (this->fountainType != FAIRY_UPGRADE_MAGIC)) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
return; return;
} }
} else { } else {
if (!gSaveContext.magicAcquired) { if (!gSaveContext.isMagicAcquired) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
return; return;
} }
@ -225,7 +225,7 @@ void BgDyYoseizo_ChooseType(BgDyYoseizo* this, PlayState* play) {
} else { } else {
switch (this->fountainType) { switch (this->fountainType) {
case FAIRY_UPGRADE_MAGIC: case FAIRY_UPGRADE_MAGIC:
if (!gSaveContext.magicAcquired || BREG(2)) { if (!gSaveContext.isMagicAcquired || BREG(2)) {
// "Spin Attack speed UP" // "Spin Attack speed UP"
osSyncPrintf(VT_FGCOL(GREEN) " ☆☆☆☆☆ 回転切り速度UP ☆☆☆☆☆ \n" VT_RST); osSyncPrintf(VT_FGCOL(GREEN) " ☆☆☆☆☆ 回転切り速度UP ☆☆☆☆☆ \n" VT_RST);
this->givingSpell = true; this->givingSpell = true;
@ -233,7 +233,7 @@ void BgDyYoseizo_ChooseType(BgDyYoseizo* this, PlayState* play) {
} }
break; break;
case FAIRY_UPGRADE_DOUBLE_MAGIC: case FAIRY_UPGRADE_DOUBLE_MAGIC:
if (!gSaveContext.doubleMagic) { if (!gSaveContext.isDoubleMagicAcquired) {
// "Magic Meter doubled" // "Magic Meter doubled"
osSyncPrintf(VT_FGCOL(YELLOW) " ☆☆☆☆☆ 魔法ゲージメーター倍増 ☆☆☆☆☆ \n" VT_RST); osSyncPrintf(VT_FGCOL(YELLOW) " ☆☆☆☆☆ 魔法ゲージメーター倍増 ☆☆☆☆☆ \n" VT_RST);
this->givingSpell = true; this->givingSpell = true;
@ -466,7 +466,7 @@ void BgDyYoseizo_HealPlayer_NoReward(BgDyYoseizo* this, PlayState* play) {
this->refillTimer = 200; this->refillTimer = 200;
} }
if (((gSaveContext.healthCapacity == gSaveContext.health) && (gSaveContext.magic == gSaveContext.unk_13F4)) || if (((gSaveContext.healthCapacity == gSaveContext.health) && (gSaveContext.magic == gSaveContext.magicCapacity)) ||
(this->refillTimer == 1)) { (this->refillTimer == 1)) {
this->healingTimer--; this->healingTimer--;
if (this->healingTimer == 90) { if (this->healingTimer == 90) {
@ -709,16 +709,18 @@ void BgDyYoseizo_Give_Reward(BgDyYoseizo* this, PlayState* play) {
switch (actionIndex) { switch (actionIndex) {
case FAIRY_UPGRADE_MAGIC: case FAIRY_UPGRADE_MAGIC:
gSaveContext.magicAcquired = true; gSaveContext.isMagicAcquired = true;
gSaveContext.unk_13F6 = 0x30; gSaveContext.magicFillTarget = MAGIC_NORMAL_METER;
// magicLevel is already 0, setting isMagicAcquired to true triggers magicCapacity to grow
Interface_ChangeAlpha(9); Interface_ChangeAlpha(9);
break; break;
case FAIRY_UPGRADE_DOUBLE_MAGIC: case FAIRY_UPGRADE_DOUBLE_MAGIC:
if (!gSaveContext.magicAcquired) { if (!gSaveContext.isMagicAcquired) {
gSaveContext.magicAcquired = true; gSaveContext.isMagicAcquired = true;
} }
gSaveContext.doubleMagic = true; gSaveContext.isDoubleMagicAcquired = true;
gSaveContext.unk_13F6 = 0x60; gSaveContext.magicFillTarget = MAGIC_DOUBLE_METER;
// Setting magicLevel to 0 triggers magicCapacity to grow
gSaveContext.magicLevel = 0; gSaveContext.magicLevel = 0;
Interface_ChangeAlpha(9); Interface_ChangeAlpha(9);
break; break;
@ -750,8 +752,8 @@ void BgDyYoseizo_Give_Reward(BgDyYoseizo* this, PlayState* play) {
itemPos.y, itemPos.z, 0, 0, 0, sExItemTypes[actionIndex]); itemPos.y, itemPos.z, 0, 0, 0, sExItemTypes[actionIndex]);
if (this->item != NULL) { if (this->item != NULL) {
if (gSaveContext.magicAcquired == 0) { if (!gSaveContext.isMagicAcquired) {
gSaveContext.magicAcquired = 1; gSaveContext.isMagicAcquired = true;
} else { } else {
Magic_Fill(play); Magic_Fill(play);
} }

View file

@ -1189,7 +1189,7 @@ void BossGanon_SetupTowerCutscene(BossGanon* this, PlayState* play) {
this->csTimer = 0; this->csTimer = 0;
this->csState = 100; this->csState = 100;
this->unk_198 = 1; this->unk_198 = 1;
gSaveContext.magic = gSaveContext.unk_13F4; gSaveContext.magic = gSaveContext.magicCapacity;
gSaveContext.health = gSaveContext.healthCapacity; gSaveContext.health = gSaveContext.healthCapacity;
} else { } else {
this->actionFunc = BossGanon_SetupTowerCutscene; this->actionFunc = BossGanon_SetupTowerCutscene;

View file

@ -84,8 +84,9 @@ void EnMThunder_Init(Actor* thisx, PlayState* play2) {
this->unk_1CA = 0; this->unk_1CA = 0;
if (player->stateFlags2 & PLAYER_STATE2_17) { if (player->stateFlags2 & PLAYER_STATE2_17) {
if (!gSaveContext.magicAcquired || gSaveContext.unk_13F0 || if (!gSaveContext.isMagicAcquired || (gSaveContext.magicState != MAGIC_STATE_IDLE) ||
(((this->actor.params & 0xFF00) >> 8) && !(func_80087708(play, (this->actor.params & 0xFF00) >> 8, 0)))) { (((this->actor.params & 0xFF00) >> 8) &&
!(Magic_RequestChange(play, (this->actor.params & 0xFF00) >> 8, MAGIC_CONSUME_NOW)))) {
Audio_PlaySoundGeneral(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySoundGeneral(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4, Audio_PlaySoundGeneral(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4,
@ -114,7 +115,7 @@ void EnMThunder_Destroy(Actor* thisx, PlayState* play) {
EnMThunder* this = (EnMThunder*)thisx; EnMThunder* this = (EnMThunder*)thisx;
if (this->unk_1CA != 0) { if (this->unk_1CA != 0) {
func_800876C8(play); Magic_Reset(play);
} }
Collider_DestroyCylinder(play, &this->collider); Collider_DestroyCylinder(play, &this->collider);
@ -156,8 +157,9 @@ void func_80A9F408(EnMThunder* this, PlayState* play) {
if (this->unk_1CA == 0) { if (this->unk_1CA == 0) {
if (player->unk_858 >= 0.1f) { if (player->unk_858 >= 0.1f) {
if ((gSaveContext.unk_13F0) || (((this->actor.params & 0xFF00) >> 8) && if ((gSaveContext.magicState != MAGIC_STATE_IDLE) ||
!(func_80087708(play, (this->actor.params & 0xFF00) >> 8, 4)))) { (((this->actor.params & 0xFF00) >> 8) &&
!(Magic_RequestChange(play, (this->actor.params & 0xFF00) >> 8, MAGIC_CONSUME_WAIT_PREVIEW)))) {
func_80A9F350(this, play); func_80A9F350(this, play);
func_80A9EFE0(this, func_80A9F350); func_80A9EFE0(this, func_80A9F350);
this->unk_1C8 = 0; this->unk_1C8 = 0;
@ -191,7 +193,7 @@ void func_80A9F408(EnMThunder* this, PlayState* play) {
} else { } else {
player->stateFlags2 &= ~PLAYER_STATE2_17; player->stateFlags2 &= ~PLAYER_STATE2_17;
if ((this->actor.params & 0xFF00) >> 8) { if ((this->actor.params & 0xFF00) >> 8) {
gSaveContext.unk_13F0 = 1; gSaveContext.magicState = MAGIC_STATE_CONSUME_SETUP;
} }
if (player->unk_858 < 0.85f) { if (player->unk_858 < 0.85f) {
this->collider.info.toucher.dmgFlags = D_80AA044C[this->unk_1C7]; this->collider.info.toucher.dmgFlags = D_80AA044C[this->unk_1C7];

View file

@ -616,7 +616,7 @@ void func_80ACB274(EnOwl* this, PlayState* play) {
void EnOwl_WaitDeathMountainShortcut(EnOwl* this, PlayState* play) { void EnOwl_WaitDeathMountainShortcut(EnOwl* this, PlayState* play) {
EnOwl_LookAtLink(this, play); EnOwl_LookAtLink(this, play);
if (!gSaveContext.magicAcquired) { if (!gSaveContext.isMagicAcquired) {
if (func_80ACA558(this, play, 0x3062)) { if (func_80ACA558(this, play, 0x3062)) {
Audio_PlayFanfare(NA_BGM_OWL); Audio_PlayFanfare(NA_BGM_OWL);
this->actionFunc = func_80ACB274; this->actionFunc = func_80ACB274;

View file

@ -531,7 +531,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) {
// Causes Dark Link to shield in place when Link is using magic attacks other than the spin attack // Causes Dark Link to shield in place when Link is using magic attacks other than the spin attack
if ((gSaveContext.unk_13F0 == 3) && if ((gSaveContext.magicState == MAGIC_STATE_METER_FLASH_1) &&
(player->meleeWeaponState == 0 || !((player->meleeWeaponAnimation >= PLAYER_MWA_SPIN_ATTACK_1H) && (player->meleeWeaponState == 0 || !((player->meleeWeaponAnimation >= PLAYER_MWA_SPIN_ATTACK_1H) &&
(player->meleeWeaponAnimation <= PLAYER_MWA_BIG_SPIN_2H)))) { (player->meleeWeaponAnimation <= PLAYER_MWA_BIG_SPIN_2H)))) {
sStickTilt = 0.0f; sStickTilt = 0.0f;

View file

@ -1810,7 +1810,7 @@ void func_80B5772C(EnZl3* this, PlayState* play) {
} }
void func_80B57754(EnZl3* this, PlayState* play) { void func_80B57754(EnZl3* this, PlayState* play) {
if (gSaveContext.unk_13F0 == 0) { if (gSaveContext.magicState == MAGIC_STATE_IDLE) {
Actor_Spawn(&play->actorCtx, play, ACTOR_OCEFF_WIPE4, this->actor.world.pos.x, this->actor.world.pos.y, Actor_Spawn(&play->actorCtx, play, ACTOR_OCEFF_WIPE4, this->actor.world.pos.x, this->actor.world.pos.y,
this->actor.world.pos.z, 0, 0, 0, 1); this->actor.world.pos.z, 0, 0, 0, 1);
func_80B56DA4(this); func_80B56DA4(this);

View file

@ -64,7 +64,7 @@ void MagicDark_Init(Actor* thisx, PlayState* play) {
void MagicDark_Destroy(Actor* thisx, PlayState* play) { void MagicDark_Destroy(Actor* thisx, PlayState* play) {
if (gSaveContext.nayrusLoveTimer == 0) { if (gSaveContext.nayrusLoveTimer == 0) {
func_800876C8(play); Magic_Reset(play);
} }
} }

View file

@ -92,7 +92,7 @@ void MagicFire_Init(Actor* thisx, PlayState* play) {
} }
void MagicFire_Destroy(Actor* thisx, PlayState* play) { void MagicFire_Destroy(Actor* thisx, PlayState* play) {
func_800876C8(play); Magic_Reset(play);
} }
void MagicFire_UpdateBeforeCast(Actor* thisx, PlayState* play) { void MagicFire_UpdateBeforeCast(Actor* thisx, PlayState* play) {

View file

@ -69,7 +69,7 @@ void MagicWind_Init(Actor* thisx, PlayState* play) {
void MagicWind_Destroy(Actor* thisx, PlayState* play) { void MagicWind_Destroy(Actor* thisx, PlayState* play) {
MagicWind* this = (MagicWind*)thisx; MagicWind* this = (MagicWind*)thisx;
SkelCurve_Destroy(play, &this->skelCurve); SkelCurve_Destroy(play, &this->skelCurve);
func_800876C8(play); Magic_Reset(play);
// "wipe out" // "wipe out"
LOG_STRING("消滅", "../z_magic_wind.c", 505); LOG_STRING("消滅", "../z_magic_wind.c", 505);
} }

View file

@ -69,7 +69,7 @@ void OceffSpot_Destroy(Actor* thisx, PlayState* play) {
LightContext_RemoveLight(play, &play->lightCtx, this->lightNode1); LightContext_RemoveLight(play, &play->lightCtx, this->lightNode1);
LightContext_RemoveLight(play, &play->lightCtx, this->lightNode2); LightContext_RemoveLight(play, &play->lightCtx, this->lightNode2);
func_800876C8(play); Magic_Reset(play);
if ((gSaveContext.nayrusLoveTimer != 0) && (play->actorCtx.actorLists[ACTORCAT_PLAYER].length != 0)) { if ((gSaveContext.nayrusLoveTimer != 0) && (play->actorCtx.actorLists[ACTORCAT_PLAYER].length != 0)) {
player->stateFlags3 |= PLAYER_STATE3_6; player->stateFlags3 |= PLAYER_STATE3_6;
} }

View file

@ -59,7 +59,7 @@ void OceffStorm_Destroy(Actor* thisx, PlayState* play) {
OceffStorm* this = (OceffStorm*)thisx; OceffStorm* this = (OceffStorm*)thisx;
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
func_800876C8(play); Magic_Reset(play);
if (gSaveContext.nayrusLoveTimer != 0) { if (gSaveContext.nayrusLoveTimer != 0) {
player->stateFlags3 |= PLAYER_STATE3_6; player->stateFlags3 |= PLAYER_STATE3_6;
} }

View file

@ -39,7 +39,7 @@ void OceffWipe_Destroy(Actor* thisx, PlayState* play) {
OceffWipe* this = (OceffWipe*)thisx; OceffWipe* this = (OceffWipe*)thisx;
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
func_800876C8(play); Magic_Reset(play);
if (gSaveContext.nayrusLoveTimer != 0) { if (gSaveContext.nayrusLoveTimer != 0) {
player->stateFlags3 |= PLAYER_STATE3_6; player->stateFlags3 |= PLAYER_STATE3_6;
} }

View file

@ -39,7 +39,7 @@ void OceffWipe2_Destroy(Actor* thisx, PlayState* play) {
OceffWipe2* this = (OceffWipe2*)thisx; OceffWipe2* this = (OceffWipe2*)thisx;
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
func_800876C8(play); Magic_Reset(play);
if (gSaveContext.nayrusLoveTimer != 0) { if (gSaveContext.nayrusLoveTimer != 0) {
player->stateFlags3 |= PLAYER_STATE3_6; player->stateFlags3 |= PLAYER_STATE3_6;
} }

View file

@ -42,7 +42,7 @@ void OceffWipe3_Destroy(Actor* thisx, PlayState* play) {
OceffWipe3* this = (OceffWipe3*)thisx; OceffWipe3* this = (OceffWipe3*)thisx;
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
func_800876C8(play); Magic_Reset(play);
if (gSaveContext.nayrusLoveTimer != 0) { if (gSaveContext.nayrusLoveTimer != 0) {
player->stateFlags3 |= PLAYER_STATE3_6; player->stateFlags3 |= PLAYER_STATE3_6;
} }

View file

@ -38,7 +38,7 @@ void OceffWipe4_Init(Actor* thisx, PlayState* play) {
void OceffWipe4_Destroy(Actor* thisx, PlayState* play) { void OceffWipe4_Destroy(Actor* thisx, PlayState* play) {
OceffWipe4* this = (OceffWipe4*)thisx; OceffWipe4* this = (OceffWipe4*)thisx;
func_800876C8(play); Magic_Reset(play);
} }
void OceffWipe4_Update(Actor* thisx, PlayState* play) { void OceffWipe4_Update(Actor* thisx, PlayState* play) {

View file

@ -2174,7 +2174,7 @@ s32 func_8083442C(Player* this, PlayState* play) {
s32 magicArrowType; s32 magicArrowType;
if ((this->heldItemActionParam >= PLAYER_AP_BOW_FIRE) && (this->heldItemActionParam <= PLAYER_AP_BOW_0E) && if ((this->heldItemActionParam >= PLAYER_AP_BOW_FIRE) && (this->heldItemActionParam <= PLAYER_AP_BOW_0E) &&
(gSaveContext.unk_13F0 != 0)) { (gSaveContext.magicState != MAGIC_STATE_IDLE)) {
func_80078884(NA_SE_SY_ERROR); func_80078884(NA_SE_SY_ERROR);
} else { } else {
func_80833638(this, func_808351D4); func_80833638(this, func_808351D4);
@ -2190,7 +2190,7 @@ s32 func_8083442C(Player* this, PlayState* play) {
if (this->unk_860 >= 0) { if (this->unk_860 >= 0) {
if ((magicArrowType >= 0) && (magicArrowType <= 2) && if ((magicArrowType >= 0) && (magicArrowType <= 2) &&
!func_80087708(play, sMagicArrowCosts[magicArrowType], 0)) { !Magic_RequestChange(play, sMagicArrowCosts[magicArrowType], MAGIC_CONSUME_NOW)) {
arrowType = ARROW_NORMAL; arrowType = ARROW_NORMAL;
} }
@ -2881,7 +2881,7 @@ void func_80835F44(PlayState* play, Player* this, s32 item) {
(play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].length >= 3)))))) { (play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].length >= 3)))))) {
func_80078884(NA_SE_SY_ERROR); func_80078884(NA_SE_SY_ERROR);
} else if (actionParam == PLAYER_AP_LENS) { } else if (actionParam == PLAYER_AP_LENS) {
if (func_80087708(play, 0, 3)) { if (Magic_RequestChange(play, 0, MAGIC_CONSUME_LENS)) {
if (play->actorCtx.lensActive) { if (play->actorCtx.lensActive) {
Actor_DisableLens(play); Actor_DisableLens(play);
} else { } else {
@ -2900,7 +2900,7 @@ void func_80835F44(PlayState* play, Player* this, s32 item) {
} }
} else if ((temp = Player_ActionToMagicSpell(this, actionParam)) >= 0) { } else if ((temp = Player_ActionToMagicSpell(this, actionParam)) >= 0) {
if (((actionParam == PLAYER_AP_FARORES_WIND) && (gSaveContext.respawn[RESPAWN_MODE_TOP].data > 0)) || if (((actionParam == PLAYER_AP_FARORES_WIND) && (gSaveContext.respawn[RESPAWN_MODE_TOP].data > 0)) ||
((gSaveContext.unk_13F4 != 0) && (gSaveContext.unk_13F0 == 0) && ((gSaveContext.magicCapacity != 0) && (gSaveContext.magicState == MAGIC_STATE_IDLE) &&
(gSaveContext.magic >= sMagicSpellCosts[temp]))) { (gSaveContext.magic >= sMagicSpellCosts[temp]))) {
this->itemActionParam = actionParam; this->itemActionParam = actionParam;
this->unk_6AD = 4; this->unk_6AD = 4;
@ -4869,7 +4869,7 @@ void func_8083AF44(PlayState* play, Player* this, s32 magicSpell) {
func_80835DE4(play, this, func_808507F4, 0); func_80835DE4(play, this, func_808507F4, 0);
this->unk_84F = magicSpell - 3; this->unk_84F = magicSpell - 3;
func_80087708(play, sMagicSpellCosts[magicSpell], 4); Magic_RequestChange(play, sMagicSpellCosts[magicSpell], MAGIC_CONSUME_WAIT_PREVIEW);
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, &gPlayerAnim_002D28, 0.83f); LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, &gPlayerAnim_002D28, 0.83f);
@ -9381,7 +9381,7 @@ void Player_Init(Actor* thisx, PlayState* play2) {
} }
if (gSaveContext.nayrusLoveTimer != 0) { if (gSaveContext.nayrusLoveTimer != 0) {
gSaveContext.unk_13F0 = 3; gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1;
func_80846A00(play, this, 1); func_80846A00(play, this, 1);
this->stateFlags3 &= ~PLAYER_STATE3_6; this->stateFlags3 &= ~PLAYER_STATE3_6;
} }
@ -10169,8 +10169,9 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
func_80848C74(play, this); func_80848C74(play, this);
} }
if ((this->stateFlags3 & PLAYER_STATE3_6) && (gSaveContext.nayrusLoveTimer != 0) && (gSaveContext.unk_13F0 == 0)) { if ((this->stateFlags3 & PLAYER_STATE3_6) && (gSaveContext.nayrusLoveTimer != 0) &&
gSaveContext.unk_13F0 = 3; (gSaveContext.magicState == MAGIC_STATE_IDLE)) {
gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1;
func_80846A00(play, this, 1); func_80846A00(play, this, 1);
this->stateFlags3 &= ~PLAYER_STATE3_6; this->stateFlags3 &= ~PLAYER_STATE3_6;
} }
@ -10758,7 +10759,7 @@ void Player_Destroy(Actor* thisx, PlayState* play) {
Collider_DestroyQuad(play, &this->meleeWeaponQuads[1]); Collider_DestroyQuad(play, &this->meleeWeaponQuads[1]);
Collider_DestroyQuad(play, &this->shieldQuad); Collider_DestroyQuad(play, &this->shieldQuad);
func_800876C8(play); Magic_Reset(play);
gSaveContext.linkAge = play->linkAgeOnLoad; gSaveContext.linkAge = play->linkAgeOnLoad;
} }
@ -12366,7 +12367,7 @@ void func_8084EAC0(Player* this, PlayState* play) {
func_8083C0E8(this, play); func_8083C0E8(this, play);
func_8005B1A4(Play_GetCamera(play, CAM_ID_MAIN)); func_8005B1A4(Play_GetCamera(play, CAM_ID_MAIN));
} else if (this->unk_850 == 1) { } else if (this->unk_850 == 1) {
if ((gSaveContext.healthAccumulator == 0) && (gSaveContext.unk_13F0 != 9)) { if ((gSaveContext.healthAccumulator == 0) && (gSaveContext.magicState != MAGIC_STATE_FILL)) {
func_80832B78(play, this, &gPlayerAnim_002660); func_80832B78(play, this, &gPlayerAnim_002660);
this->unk_850 = 2; this->unk_850 = 2;
Player_UpdateBottleHeld(play, this, ITEM_BOTTLE, PLAYER_AP_BOTTLE); Player_UpdateBottleHeld(play, this, ITEM_BOTTLE, PLAYER_AP_BOTTLE);
@ -13107,7 +13108,7 @@ static struct_80832924 D_80854A8C[][2] = {
void func_808507F4(Player* this, PlayState* play) { void func_808507F4(Player* this, PlayState* play) {
if (LinkAnimation_Update(play, &this->skelAnime)) { if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->unk_84F < 0) { if (this->unk_84F < 0) {
if ((this->itemActionParam == PLAYER_AP_NAYRUS_LOVE) || (gSaveContext.unk_13F0 == 0)) { if ((this->itemActionParam == PLAYER_AP_NAYRUS_LOVE) || (gSaveContext.magicState == MAGIC_STATE_IDLE)) {
func_80839FFC(this, play); func_80839FFC(this, play);
func_8005B1A4(Play_GetCamera(play, CAM_ID_MAIN)); func_8005B1A4(Play_GetCamera(play, CAM_ID_MAIN));
} }
@ -13118,10 +13119,10 @@ void func_808507F4(Player* this, PlayState* play) {
if (func_80846A00(play, this, this->unk_84F) != NULL) { if (func_80846A00(play, this, this->unk_84F) != NULL) {
this->stateFlags1 |= PLAYER_STATE1_28 | PLAYER_STATE1_29; this->stateFlags1 |= PLAYER_STATE1_28 | PLAYER_STATE1_29;
if ((this->unk_84F != 0) || (gSaveContext.respawn[RESPAWN_MODE_TOP].data <= 0)) { if ((this->unk_84F != 0) || (gSaveContext.respawn[RESPAWN_MODE_TOP].data <= 0)) {
gSaveContext.unk_13F0 = 1; gSaveContext.magicState = MAGIC_STATE_CONSUME_SETUP;
} }
} else { } else {
func_800876C8(play); Magic_Reset(play);
} }
} else { } else {
LinkAnimation_PlayLoopSetSpeed(play, &this->skelAnime, D_80854A64[this->unk_84F], 0.83f); LinkAnimation_PlayLoopSetSpeed(play, &this->skelAnime, D_80854A64[this->unk_84F], 0.83f);

View file

@ -1473,8 +1473,8 @@ void FileChoose_LoadGame(GameState* thisx) {
gSaveContext.unk_13EE = 0x32; gSaveContext.unk_13EE = 0x32;
gSaveContext.nayrusLoveTimer = 0; gSaveContext.nayrusLoveTimer = 0;
gSaveContext.healthAccumulator = 0; gSaveContext.healthAccumulator = 0;
gSaveContext.unk_13F0 = 0; gSaveContext.magicState = MAGIC_STATE_IDLE;
gSaveContext.unk_13F2 = 0; gSaveContext.prevMagicState = MAGIC_STATE_IDLE;
gSaveContext.forcedSeqId = NA_BGM_GENERAL_SFX; gSaveContext.forcedSeqId = NA_BGM_GENERAL_SFX;
gSaveContext.skyboxTime = CLOCK_TIME(0, 0); gSaveContext.skyboxTime = CLOCK_TIME(0, 0);
gSaveContext.nextTransitionType = TRANS_NEXT_TYPE_DEFAULT; gSaveContext.nextTransitionType = TRANS_NEXT_TYPE_DEFAULT;
@ -1488,16 +1488,16 @@ void FileChoose_LoadGame(GameState* thisx) {
gSaveContext.buttonStatus[3] = gSaveContext.buttonStatus[4] = BTN_ENABLED; gSaveContext.buttonStatus[3] = gSaveContext.buttonStatus[4] = BTN_ENABLED;
gSaveContext.unk_13E7 = gSaveContext.unk_13E8 = gSaveContext.unk_13EA = gSaveContext.unk_13EC = gSaveContext.unk_13E7 = gSaveContext.unk_13E8 = gSaveContext.unk_13EA = gSaveContext.unk_13EC =
gSaveContext.unk_13F4 = 0; gSaveContext.magicCapacity = 0;
gSaveContext.unk_13F6 = gSaveContext.magic; // Set the fill target to be the saved magic amount
gSaveContext.magic = 0; gSaveContext.magicFillTarget = gSaveContext.magic;
gSaveContext.magicLevel = gSaveContext.magic; // Set `magicLevel` and `magic` to 0 so `magicCapacity` then `magic` grows from nothing to respectively the full
// capacity and `magicFillTarget`
if (1) {} gSaveContext.magicLevel = gSaveContext.magic = 0;
osSyncPrintf(VT_FGCOL(GREEN)); osSyncPrintf(VT_FGCOL(GREEN));
osSyncPrintf("Z_MAGIC_NOW_NOW=%d MAGIC_NOW=%d\n", ((void)0, gSaveContext.unk_13F6), gSaveContext.magic); osSyncPrintf("Z_MAGIC_NOW_NOW=%d MAGIC_NOW=%d\n", ((void)0, gSaveContext.magicFillTarget), gSaveContext.magic);
osSyncPrintf(VT_RST); osSyncPrintf(VT_RST);
gSaveContext.naviTimer = 0; gSaveContext.naviTimer = 0;

View file

@ -20,10 +20,12 @@ void Select_LoadGame(SelectContext* this, s32 entranceIndex) {
osSyncPrintf(VT_RST); osSyncPrintf(VT_RST);
if (gSaveContext.fileNum == 0xFF) { if (gSaveContext.fileNum == 0xFF) {
Sram_InitDebugSave(); Sram_InitDebugSave();
gSaveContext.unk_13F6 = gSaveContext.magic; // Set the fill target to be the saved magic amount
gSaveContext.magic = 0; gSaveContext.magicFillTarget = gSaveContext.magic;
gSaveContext.unk_13F4 = 0; // Set `magicLevel` and `magic` to 0 so `magicCapacity` then `magic` grows from nothing
gSaveContext.magicLevel = gSaveContext.magic; // to respectively the full capacity and `magicFillTarget`
gSaveContext.magicCapacity = 0;
gSaveContext.magicLevel = gSaveContext.magic = 0;
} }
gSaveContext.buttonStatus[0] = gSaveContext.buttonStatus[1] = gSaveContext.buttonStatus[2] = gSaveContext.buttonStatus[0] = gSaveContext.buttonStatus[1] = gSaveContext.buttonStatus[2] =
gSaveContext.buttonStatus[3] = gSaveContext.buttonStatus[4] = BTN_ENABLED; gSaveContext.buttonStatus[3] = gSaveContext.buttonStatus[4] = BTN_ENABLED;

View file

@ -3403,16 +3403,19 @@ void KaleidoScope_Update(PlayState* play) {
gSaveContext.health = 0x30; gSaveContext.health = 0x30;
Audio_QueueSeqCmd(0xF << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0xA); Audio_QueueSeqCmd(0xF << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0xA);
gSaveContext.healthAccumulator = 0; gSaveContext.healthAccumulator = 0;
gSaveContext.unk_13F0 = 0; gSaveContext.magicState = MAGIC_STATE_IDLE;
gSaveContext.unk_13F2 = 0; gSaveContext.prevMagicState = MAGIC_STATE_IDLE;
osSyncPrintf(VT_FGCOL(YELLOW)); osSyncPrintf(VT_FGCOL(YELLOW));
osSyncPrintf("MAGIC_NOW=%d ", gSaveContext.magic); osSyncPrintf("MAGIC_NOW=%d ", gSaveContext.magic);
osSyncPrintf("Z_MAGIC_NOW_NOW=%d → ", gSaveContext.unk_13F6); osSyncPrintf("Z_MAGIC_NOW_NOW=%d → ", gSaveContext.magicFillTarget);
gSaveContext.unk_13F4 = 0; gSaveContext.magicCapacity = 0;
gSaveContext.unk_13F6 = gSaveContext.magic; // Set the fill target to be the magic amount before game over
gSaveContext.magicFillTarget = gSaveContext.magic;
// Set `magicLevel` and `magic` to 0 so `magicCapacity` then `magic` grows from nothing
// to respectively the full capacity and `magicFillTarget`
gSaveContext.magicLevel = gSaveContext.magic = 0; gSaveContext.magicLevel = gSaveContext.magic = 0;
osSyncPrintf("MAGIC_NOW=%d ", gSaveContext.magic); osSyncPrintf("MAGIC_NOW=%d ", gSaveContext.magic);
osSyncPrintf("Z_MAGIC_NOW_NOW=%d\n", gSaveContext.unk_13F6); osSyncPrintf("Z_MAGIC_NOW_NOW=%d\n", gSaveContext.magicFillTarget);
osSyncPrintf(VT_RST); osSyncPrintf(VT_RST);
} else { } else {
play->state.running = false; play->state.running = false;