-
Notifications
You must be signed in to change notification settings - Fork 615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document Magic #1199
Document Magic #1199
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job! 🪄 🎩 🐰
include/z64save.h
Outdated
/* 02 */ MAGIC_BAR_CONSUME_NOW_ALT, // Identical behaviour to MAGIC_BAR_CONSUME_NOW. Unused | ||
/* 03 */ MAGIC_BAR_CONSUME_LENS, // Lens consumption | ||
/* 04 */ MAGIC_BAR_CONSUME_WAIT_PREVIEW, // Sets consume target but waits to consume. Draws yellow magic to target consumption | ||
/* 05 */ MAGIC_BAR_ADD // Sets a target to add magic | ||
} MagicBarChange; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would call the enum ChangeType instead of just "Change". may need to update variables to reflect that.
also normally we would have a common prefix for these values that all fit under the same umbrella, but its a bit weird with add
being different from all the other consume types i guess
in general I think we can probably afford to make all the magic related enums just start with MAGIC_
and omit the bar? that goes for the enum above too.
Then we can do MAGIC_CHANGE_CONSUME_NOW
and MAGIC_CHANGE_ADD
etc, with MAGIC
telling you its for the magic system, and CHANGE
telling you its for the change type, followed by the actual type name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For your first point:
I also had CHANGE_
in the enum earlier, but then decided to take it out because the names were getting quite long and it seems like some of the names had reduncency in them i.e.
typedef enum MagicBarChange {
/* 00 */ MAGIC_BAR_CHANGE_CONSUME_NOW,
/* 01 */ MAGIC_BAR_CHANGE_CONSUME_WAIT_NO_PREVIEW,
/* 02 */ MAGIC_BAR_CHANGE_CONSUME_NOW_ALT,
/* 03 */ MAGIC_BAR_CHANGE_CONSUME_LENS,
/* 04 */ MAGIC_BAR_CHANGE_CONSUME_WAIT_PREVIEW,
/* 05 */ MAGIC_BAR_CHANGE_ADD
} MagicBarChange;
The terms CHANGE_CONSUME
and CHANGE_ADD
feel redundant, and there's only one that's different than the others ADD
(I'm fine with MagicBarChangeType
though)
For your second point, I messed around a bit with magic
vs. magicBar
for many of these names and enums. The reason I leaned more towards MagicBar
when I could is because magic
felt a bit too general, like magic spell or magic amount, it's hard to articulate. I felt MagicBar
was really clear in what it was referring to, does that make sense?
Thoughts on consistently using the Also, maybe |
I've made the suggestions from the discord discussion, using the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor things besides Magic_Reset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job on this! 🧙 🎈
I'm still not convinced by Magic_Reset
but I don't have a strong suggestion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job, this is actually comprehensible now. Couple of things.
/* 0x003A */ u8 isMagicAcquired; | ||
/* 0x003B */ char unk_3B[0x01]; | ||
/* 0x003C */ u8 doubleMagic; | ||
/* 0x003C */ u8 isDoubleMagicAcquired; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't realise this was used extensively in the repo, but now I'm wondering if we want to name variables like this interrogatively... does the is
actually do anything here, that the plain past participle doesn't?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in this specific instance, doubleMagicAcquired
alone can be inferred to be a boolean-like value (it still uses the 0/1 in calculating magicCapacity
so it's not a true bool), but as you mentioned, is
is just a common and fast way to identify that something is boolean without thinking about it, at least that was my understanding of the convention
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also as a side note, not related to this comment but something I wanted to note:
doubleDefense
-> isDoubleDefenseAcquired
(or without the is
) would be consistent with isDoubleMagicAcquired
but I refrained from changing it for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we were going by the game it should be "half damage" (or possibly "enhanced defence") anyway:
"I'm going to enhance your \n"
COLOR(LIGHTBLUE) "defensive power" COLOR(DEFAULT) "."
[...]
"Your " COLOR(LIGHTBLUE) "defensive power" COLOR(DEFAULT) " is enhanced!"
[...]
"Your defensive power has been \n"
"enhanced! Damage inflicted by \n"
"enemies will be " COLOR(RED) "reduced by half" COLOR(DEFAULT) "."
(I suppose we could say the same thing for magic, actually, it never explicitly says it doubles, although that's obvious from the bar size)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imo this is a case where the common colloquial name makes more sense. no one says half damage or enhanced defense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a look into this, since I was curious. I looked at 4 guidebooks (3 English, 1 the official one, 1 Japanese) and the first page of Google results for walkthroughs, including 4 GameFAQs guides. A large majority say one or more of
- half damage
- enhanced defense
- doubled health
and only 2 (of about 20) say double/doubled defense. I was pretty surprised by this myself, since the tiny speedrunning corner of the world does seem to call always call it "double defense", probably because of the alliteration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to add a different perspective, I come from the randomizer community and never heard of any of those terms, it's only ever been "double defense" for me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other related names in decomp: FAIRY_UPGRADE_HALF_DAMAGE
(hi elliptic), gGreatFairyDoubleDefenceCs
(hi louis)
I would be okay with normalizing all of that to "half damage", with a comment on the save context struct member like // double defense
"double defense" probably is so popular because it rolls so well off the tongue
src/code/z_parameter.c
Outdated
|
||
switch (gSaveContext.magicState) { | ||
case MAGIC_STATE_GROW_METER: | ||
// Step magicCapacityDrawn to what is magicCapacity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As here: it's basically the same as MAGIC_STATE_FILL, but for the bar itself, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a sense. The way this block is designed is that it just moves the bar drawn to where the true capacity is. In theory, it could be moved wider or smaller (i.e. it doesn't specifically have to grow), it's just that in practice it only grows based on how this case is used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it could be UPDATE_WIDTH
, even.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WIDTH
could apply to a lot of things so I think it'd be important to specify meter in there, but yeah I'd be fine with that. Could maybe even be SYNC_METER_WIDTH
in the sense that it "sync"s the magicCapacityDrawn
to the true magicCapacity
just as an idea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, something along those lines makes sense to me.
@@ -1191,7 +1191,7 @@ void BossGanon_SetupTowerCutscene(BossGanon* this, GlobalContext* globalCtx) { | |||
this->csTimer = 0; | |||
this->csState = 100; | |||
this->unk_198 = 1; | |||
gSaveContext.magic = gSaveContext.unk_13F4; | |||
gSaveContext.magic = gSaveContext.magicCapacityDrawn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
magicCapacityDrawn
seems misleading since it's used for things other than drawing (like here and in a few other places), and it seems to be closer to the "effective" capacity at a specific point in time (eg. in Magic_RequestChange
).
So as you mentioned originally I think it would be better to name this one magicCapacity
and the other one something like magicCapacityTarget
or magicCapacityMax
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be okay with either, but I have a slight preference to the way I have it now but it’s hard to articulate why.
But I interpret it as the point of magicCapacity
being to store the “true” value in a sense while magicCapacityDrawn
gives flexibility on how the capacity is drawn from 0 -> magicCapacity
or the previous magicCapacity
-> new magicCapacity
. Most checks when comparing against magic capacity seems to be against magicCapacity
instead of magicCapacityDrawn
, but either work due to them being mostly the same. But I still has a sense that magicCapacity
is the true value and calling that magicCapacityTarget
or magicCapacityMax
seems a bit funny to me.
Sure magicCapacityDrawn
is used more to draw, but it also contains info on the magicCapacity which is what it’s used for, and is still in the name, so I don't find it misleading imo.
With the current names, you also get a meaningful distinction between the two variables instead of something like magicCapacityMax
and magicCapacity
which seems too similar.
There also doesn’t seemed to be a logic as to whether devs used magicCapacity
vs magicCapacityDrawn
(outside z_parameter) since they basically contain the same info 99.5% of the time and the devs names were awful so I’d understand if they mixed them up a little.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To note, I followed through on my suggestion of changing MAGIC_STATE_GROW_METER
to MAGIC_STATE_SYNC_METER_WIDTH
, but if these variables were to change, maybe it's be worth changing it to something like MAGIC_STATE_SYNC_CAPACITIES
or something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree they are both used as the capacity in different instances, but to me it's misleading to have magicCapacityDrawn
if it gets used in actual game logic. Personally I would interpret that name as something that is used for drawing on the hud, which means I could change its value without affecting the rest of the game, but that would be a big mistake in this case.
Regarding the names I suggested, it's true that magicCapacity
and magicCapacityMax
/magicCapacityTarget
are pretty similar, but I would argue there is no real way around that since they are used for similar purposes like you mentioned, and we can't fix that on our end unfortunately.
Also, looking at the code again, magicCapacityDrawn
is actually used more than magicCapacity
, even when only accounting for game logic purposes. Besides debug prints, magicCapacity
is only read in one place for case MAGIC_STATE_FILL
in Magic_Update
, while magicCapacityDrawn
is used everywhere else, including when adding magic through Magic_RequestChange
. So imo it makes more sense to treat it as the "true" capacity in almost all cases (hence magicCapacity
). And maybe we could have the other one as magicFillCapacity
since that's only thing it's really used for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I see what you mean.
There's also the process of obtaining magic and double magic:
For obtaining normal magic,
gSaveContext.magicCapacity = MAGIC_NORMAL_METER;
Then in Interface_Update
:
if (gSaveContext.isMagicAcquired && (gSaveContext.magicLevel == 0)) {
gSaveContext.magicLevel = gSaveContext.isDoubleMagicAcquired + 1;
gSaveContext.magicState = MAGIC_STATE_SYNC_METER_WIDTH;
Which is true because the magicLevel
was 0 before, and this magicState
is the one that steps magicCapacityDrawn
-> magicCapacity
(it happens when the hud is hidden so you don't actually visually see the magic bar grown).
And when obtaining double magic:
gSaveContext.magicCapacity = MAGIC_DOUBLE_METER;
gSaveContext.magicLevel = 0;
They explicitly set magicLevel to 0 so that the same code in Interface_Update
runs i.e. (gSaveContext.magicLevel == 0)
passes, and the state becomes MAGIC_STATE_SYNC_METER_WIDTH
. to step magicCapacityDrawn
-> magicCapacity
In both cases, magicCapacity
is acting like a target, and magicCapacityDrawn
does feel like the true magic capacity.
So I kinda like:
magicCapacity
-> magicCapacityTarget
magicCapacityDrawn
-> magicCapacity
as originally had. Then maybe:
MAGIC_STATE_SYNC_METER_WIDTH
-> MAGIC_STATE_SYNC_CAPACITY
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe something like:
MAGIC_STATE_SYNC_METER_WIDTH
->
MAGIC_STATE_STEP_CAPACITY
OR
MAGIC_STATE_UPDATE_CAPACITY
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yay figured it out for real this time
comments, mostly on comments
* 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 documents the different magic variables and functions in the game, primarily from z_parameter.
A few notes:
magicCapacity
that's "drawn", which exists as a separate variable specifically for when you enter the first scene from a new load, and the magic bar grows from 0 width to the width of the current bar. I went withmagicCapacity
for the fixed value andmagicCapacityDrawn
as the drawn value. Other than that first scene load, they're always the same and are used interchangeably throughout the repo in terms of checking for magic capacity. Maybe another name could bemagicCapacityTarget
for the fixed values andmagicCapacity
for the drawn valuesMagicBarChange
could be improved, but I went with a more verbose name to start just to help reviewers understand how magic is working