HarbourMasters / Shipwright

3.27k stars 490 forks source link

Feature request: automatically equip weapons/equipment if none are currently equipped #482

Closed jbodner09 closed 1 year ago

jbodner09 commented 2 years ago

Mostly just leaving this here for myself so I don't forget the idea when I eventually have time to work on something. I was watching ZFG's commentary of the 100%, 2 pauses LOTAD, and it occurred to me how much of that constraint was due to the game not auto-equipping when there are available slots. And I know it was frustrating to them too since they expressed so much happiness over the times the game does auto-equip things. So, given how annoying it is even for me to have to immediately pause in a new game to equip the most basic equipment, I thought of a few things that would help.

First, for equipment, obtaining a new sword, shield, or tunic would automatically equip it, even if there is one already equipped. Or if that "even if" clause is contentious, then at minimum if there is currently none equipped, with maybe an option to also do the "even if" part. Boots, obviously, would be left out of this change.

Second, for new items, if there's an empty C button slot, automatically equip it to one of them. And since I'm already courting controversy, perhaps an option to automatically equip any new item as well, with which button it gets put on being easily customizable, just so there's parity with the equipment.

Finally, to make these changes actually useful beyond a few key points in the game, making it so equipment and items can be easily unequipable. For sword and shield, I say let Link go defenseless if he wants! Pressing the button on the equipment/item when it's already equipped would unequip it.

wawa1474 commented 2 years ago

randomizer puts boots and ocarina on the d-pad, which would also cut down on repetitive pausing, especially in water temple for water boots. and with ocarina on d-pad that frees up a spot on c buttons. iron boots on d-left, hover boots on d-right, ocarina on d-down Annotation 2022-06-15 181803

maybe have configurable d-up item, or be able to configure all d-pad items? maybe have the d-pad be able to act as a second set of c buttons? would mean they cant be used in pause menu to move around but would be a good trade off in my opinion.

another nice thing would maybe be if MM bunny hood option is used, put that on d-up (once you have it obv., and make it stay on through loading zones too)

the auto-equipping a sword and shield if one is not equipped would be nice, though auto-equipping the blue tunic could be troublesome as it increases damage taken from fire and ice (IIRC).

the equipping a new item to an empty c button is nice, though equipping it when no c buttons are empty not so much. maybe if some kind of "prompt" came up where you could press a c button to equip the item, or press b to not equip it would work?

vaguerant commented 2 years ago

This seemed like a fun idea, so I had a quick look at it. I only implemented it for Swords/Shields/Tunics, not for C-buttons as you suggest here, but here's how I did it:

diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c
index 14d6772..7be667a 100644
--- a/soh/src/code/z_parameter.c
+++ b/soh/src/code/z_parameter.c
@@ -1366,6 +1366,7 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
     s16 i;
     s16 slot;
     s16 temp;
+    Player* player = GET_PLAYER(globalCtx);

     slot = SLOT(item);
     if (item >= ITEM_STICKS_5) {
@@ -1427,6 +1428,11 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
         return ITEM_NONE;
     } else if ((item >= ITEM_SWORD_KOKIRI) && (item <= ITEM_SWORD_BGS)) {
         gSaveContext.inventory.equipment |= gBitFlags[item - ITEM_SWORD_KOKIRI] << gEquipShifts[EQUIP_SWORD];
+        if (CVar_GetS32("gAutoEquips", 0)) {
+            gSaveContext.equips.buttonItems[0] = item;
+            Inventory_ChangeEquipment(EQUIP_SWORD, item - ITEM_SWORD_KOKIRI + 1);
+            Interface_LoadItemIcon1(globalCtx, 0);
+        }

         if (item == ITEM_SWORD_BGS) {
             gSaveContext.swordHealth = 8;
@@ -1448,9 +1454,17 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
         return ITEM_NONE;
     } else if ((item >= ITEM_SHIELD_DEKU) && (item <= ITEM_SHIELD_MIRROR)) {
         gSaveContext.inventory.equipment |= (gBitFlags[item - ITEM_SHIELD_DEKU] << gEquipShifts[EQUIP_SHIELD]);
+        if (CVar_GetS32("gAutoEquips", 0)) {
+            Inventory_ChangeEquipment(EQUIP_SHIELD, item - ITEM_SHIELD_DEKU + 1);
+            Player_SetEquipmentData(globalCtx, player);
+        }
         return ITEM_NONE;
     } else if ((item >= ITEM_TUNIC_KOKIRI) && (item <= ITEM_TUNIC_ZORA)) {
         gSaveContext.inventory.equipment |= (gBitFlags[item - ITEM_TUNIC_KOKIRI] << gEquipShifts[EQUIP_TUNIC]);
+        if (CVar_GetS32("gAutoEquips", 0)) {
+            Inventory_ChangeEquipment(EQUIP_TUNIC, item - ITEM_TUNIC_KOKIRI + 1);
+            Player_SetEquipmentData(globalCtx, player);
+        }
         return ITEM_NONE;
     } else if ((item >= ITEM_BOOTS_KOKIRI) && (item <= ITEM_BOOTS_HOVER)) {
         gSaveContext.inventory.equipment |= (gBitFlags[item - ITEM_BOOTS_KOKIRI] << gEquipShifts[EQUIP_BOOTS]);

The only particularly complicated thing here going on is the math around those enums, e.g. item - ITEM_SWORD_KOKIRI + 1. item is the item value of whatever you just picked up, but the equipment values expect numbers from 1-3, not the actual item number. So for example:

ITEM_SWORD_KOKIRI = 59
ITEM_SWORD_MASTER = 60
ITEM_SWORD_BGS = 61

If you've just picked up the Kokiri Sword, item is 59, so that's just 59 - 59 + 1 == 1, or slot 1, the Kokiri Sword. If you've just picked up the Biggoron's Sword, item is 61, so that's now 61 - 59 + 1 == 3, or slot 3, the Biggoron's Sword.

EDIT: I have no plans to go any further with this, it's all yours if you'd like to expand on it, or not as you prefer.

jbodner09 commented 2 years ago

@wawa1474 The D-pad work I believe is being worked on by others, and that's a good point about the blue tunic. Obviously this wouldn't stop people from changing it after the fact though. That's also a really good idea for the prompt, since that would make a good "default" option for people who don't want it to always go to a particular button but do want it equipped immediately.

jbodner09 commented 2 years ago

Also see the discussion between my comment here and what I'm replying to for other potential additions: https://discord.com/channels/808039310850130000/955997420288888902/987001838920400927

wawa1474 commented 2 years ago

yeah, the blue tunic is... useless? i mean, really it could probably be auto equipped/unequipped any time iron boots are put on (assuming you have the tunic obv.).

the only time you wear the iron boots and not be in water is if you're walking against fan currents (shadow temple, ganons tower, any others?), although, i suppose there is that one corridor in shadow temple where you have fans and the fire throwing eyes, so maybe auto equipping blue tunic with iron boots might not be so good.

then again maybe when equipping iron boots check if the player is in water and if so equip blue tunic? that would keep it simple, and mean you wouldn't end up getting burnt to a crisp. although if you're checking if the player is in water, maybe just auto equip the blue tunic regardless if they're wearing the iron boots? that would definitely simplify things, and mean you won't accidentally get burnt...

as for the prompt, when first getting an item you get a prompt saying:

You got a ... ! On the Select Item Subscreen, you can set it to <, \/, or >.

*text telling you what the item does*

that prompt is shown the first time buying or picking up an item, and then not? shown again for said item. it might fine to "get rid of" that prompt, and/or use it for the prompt to put the item on a button, something like:

You got a ... ! Press <, \/, or > to equip it, or B to put it in your inventory.

though with the prompt also saying what the item is used for, like:

You got a Deku Nut ! On the Select Item Subscreen, you can set it to <, \/, or >.

Set it to C and try throwing it It will flash and stun the enemy !

it might be good to "swap" those paragraphs, like:

You got a Deku Nut ! Throwing It will flash and stun the enemy !

Press <, \/, or > to equip it, or B to put it in your inventory.

but i don't know which is better, or if it really possible to do that, just an idea i had.

vaguerant commented 2 years ago

For what it's worth, you can drown underwater without having the boots on. If you e.g. dive under an alcove so that Link can't get back up to the surface, you can drown anywhere. It's time-based rather than boot-based. The discussion we had in the Discord was centered around equipping the Zora Tunic automatically when you're in water. It could either be set up to equip immediately on contact with water, or tied to the function which handles the drowning timer, before the timer is ever started or displayed.

Then, presumably, you would drop back to the Goron Tunic as soon as you got out of the water if it was available. I don't think there's really that many (any?) situations where you're in the water and the Goron Tunic is a better option. There's no underwater fire enemies, etc.

EDIT: I think behavior like this would definitely need to be under a separate CVar, or perhaps the CVar would have a range from "don't do anything different to the base game," "equip every new item you find," and "always equip optimum loadout" which would do things like the tunic behavior discussed above, equipping the Mirror Shield automatically in the Spirit Temple, etc.

wawa1474 commented 2 years ago

yeah, it's definitely a case of having an option to auto equip the zora tunic in water and goron tunic outside of water (if you have the appropriate tunic obv.) i don't know how the drowning timer works, but isn't there a delay before it pops on screen? would that delay the equipping of the zora tunic or does the function activate sooner than it actually displays? i suppose that wouldn't really matter but it might be nice for the tunic to equip instantly on entering the water rather than several seconds later.

it might be a nice idea to also have the option for the goron tunic to auto equip/de-equip when in a hot room, for those who want link to be in the kokiri tunic most of the time. kind of a... link wears whatevers appropriate for the occasion type thing. though just wearing the goron tunic all the time is fine too.

for auto equipping the mirror shield, while it could just be in the spirit temple, its maybe more accurate to be any time link stands in one of the light rays (IDK what they're called), or in the spirit temple/spirit temple boss room? because the mirror shield breaks, rather than reflecting any spit projectiles from things like deku scrubs and octoroks, and it might be nice to still be able to reflect the projectiles back at said enemies, rather than just breaking them.

jbodner09 commented 2 years ago

I think what all of this discussion is hinting at is that there really are two levels of auto-equipping. Level 1, which is what I was initially thinking of, is just equipping something when you first obtain it. Level 2, which would be a lot more work, would be equipping something automatically any time you need it. Level 1 is all I was planning on doing myself, but even within that, I think there's room to treat the Zora tunic special given its drawbacks.

One option would be to treat it as something Link just has instead of something he uses. We already know the game checks if Link is wearing it before starting a drowning timer, so all that would need to be done is add an additional check to that for if a flag like gAutoZora is enabled and if the tunic is in Link's inventory, and if it is, then just follow the same codepath as if he's wearing it. That's a single line change (or however many places they check before starting the drowning timer).

Alternatively, automatically equipping Link whenever he's in water is basically what I would call the Level 2 approach. Of course, there are also different ways Level 2 could be triggered, as mentioned. It could be depending on if he's in a particular map/room, if he's currently interacting with a specific actor (which I assume the light rays used by Mirror Shield are), if he's got another item equipped, etc. Having not looked at the code, I imagine there are discrete functions for when Link is in water in some form, so it actually wouldn't be too hard to add auto equips and unequips for Zora tunic at least. In any case, that behavior would indeed be something that would just be covered under a general "Level 2" cvar.

wawa1474 commented 2 years ago

yeah, i guess having an option for it to work like the zora scales would work. like, once you get the tunic, it just kinda... works? then it wouldn't even matter if the game auto equipped the tunic.

in fact, if anything have it be the same for the goron tunic, once you get the tunic you instantly get fire resistance.

then what tunic you wear could just be aesthetics, like, which look do you like the best kinda thing. and at that point the only thing you'd have to switch would really be the boots and shields, which aren't really changed that often...

and if, as said earlier, people are working to have randomizer-like boots and ocarina on d-pad, then the only thing that you'd have to change would be shield, and once you get mirror shield, you never really change it back...

so in conclusion, if the goron and zora tunic worked like the scales and other things where it just checks if you have them, then the only things that you'd have to change would be boots and shields, of which shields aren't changed often, and boots could be either on c-buttons as they currently can be (assignable boots enhancement), or better yet have them on the d-pad.

jbodner09 commented 2 years ago

More discussion here: https://discord.com/channels/808039310850130000/955997420288888902/987857646335971378. After #501, future work still includes other sliders for shields, etc., and all C-button functionality for auto-equipping items and being able to unequip items.