Skip to content
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

New QoL setting : textbox to equip new swords/shields/tunic when finding them #2335

Open
wants to merge 2 commits into
base: Dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,056 changes: 544 additions & 512 deletions ASM/build/asm_symbols.txt

Large diffs are not rendered by default.

Binary file modified ASM/build/bundle.o
Binary file not shown.
976 changes: 500 additions & 476 deletions ASM/build/c_symbols.txt

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions ASM/c/item_effects.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "trade_quests.h"
#include "bg_gate_shutter.h"
#include "save.h"
#include "message.h"

#define rupee_cap ((uint16_t*)0x800F8CEC)
volatile uint8_t MAX_RUPEES = 0;
Expand Down Expand Up @@ -50,6 +51,7 @@ void give_tycoon_wallet(z64_file_t* save, int16_t arg1, int16_t arg2) {

void give_biggoron_sword(z64_file_t* save, int16_t arg1, int16_t arg2) {
save->bgs_flag = 1; // Set flag to make the sword durable
equip_biggoron_sword_message(save, arg1, arg2);
}

void give_bottle(z64_file_t* save, int16_t bottle_item_id, int16_t arg2) {
Expand Down
13 changes: 7 additions & 6 deletions ASM/c/item_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "dungeon_info.h"
#include "item_effects.h"
#include "item_upgrades.h"
#include "message.h"
#include "save.h"
#include "util.h"
#include "z64.h"
Expand Down Expand Up @@ -68,13 +69,13 @@ item_row_t item_table[GI_RANDO_MAX] = {
[GI_EYE_DROPS] = ITEM_ROW(0x53, GILDED_CHEST, 0x36, -1, 0x000E, 0x013F, 0x52, no_upgrade, trade_quest_upgrade, 0x36, -1, NULL), // Eye Drops
[GI_CLAIM_CHECK] = ITEM_ROW(0x53, GILDED_CHEST, 0x37, -1, 0x000A, 0x0142, 0x55, no_upgrade, trade_quest_upgrade, 0x37, -1, NULL), // Claim Check

[GI_SWORD_KOKIRI] = ITEM_ROW(0x53, GILDED_CHEST, 0x3B, -1, 0x00A4, 0x018D, 0x74, no_upgrade, no_effect, -1, -1, NULL), // Kokiri Sword
[GI_SWORD_KOKIRI] = ITEM_ROW(0x53, GILDED_CHEST, 0x3B, -1, 0x00A4, 0x018D, 0x74, no_upgrade, equip_kokiri_sword_message, -1, -1, NULL), // Kokiri Sword
[GI_SWORD_KNIFE] = ITEM_ROW(0x53, GILDED_CHEST, 0x3D, -1, 0x004B, 0x00F8, 0x43, no_upgrade, no_effect, -1, -1, NULL), // Giant's Knife
[GI_SHIELD_DEKU] = ITEM_ROW(0x53, BROWN_CHEST, 0x3E, -1, 0x90AD, 0x00CB, 0x1D, no_upgrade, no_effect, -1, -1, NULL), // Deku Shield
[GI_SHIELD_HYLIAN] = ITEM_ROW(0x53, BROWN_CHEST, 0x3F, -1, 0x90AE, 0x00DC, 0x2C, no_upgrade, no_effect, -1, -1, NULL), // Hylian Shield
[GI_SHIELD_MIRROR] = ITEM_ROW(0x53, GILDED_CHEST, 0x40, -1, 0x004E, 0x00EE, 0x3A, no_upgrade, no_effect, -1, -1, NULL), // Mirror Shield
[GI_TUNIC_GORON] = ITEM_ROW(0x53, GILDED_CHEST, 0x42, -1, 0x90AF, 0x00F2, 0x3C, no_upgrade, no_effect, -1, -1, NULL), // Goron Tunic
[GI_TUNIC_ZORA] = ITEM_ROW(0x53, GILDED_CHEST, 0x43, -1, 0x90B0, 0x00F2, 0x3D, no_upgrade, no_effect, -1, -1, NULL), // Zora Tunic
[GI_SHIELD_DEKU] = ITEM_ROW(0x53, BROWN_CHEST, 0x3E, -1, 0x90AD, 0x00CB, 0x1D, no_upgrade, equip_deku_shield_message, -1, -1, NULL), // Deku Shield
[GI_SHIELD_HYLIAN] = ITEM_ROW(0x53, BROWN_CHEST, 0x3F, -1, 0x90AE, 0x00DC, 0x2C, no_upgrade, equip_hylian_shield_message, -1, -1, NULL), // Hylian Shield
[GI_SHIELD_MIRROR] = ITEM_ROW(0x53, GILDED_CHEST, 0x40, -1, 0x004E, 0x00EE, 0x3A, no_upgrade, equip_mirror_shield_message, -1, -1, NULL), // Mirror Shield
[GI_TUNIC_GORON] = ITEM_ROW(0x53, GILDED_CHEST, 0x42, -1, 0x90AF, 0x00F2, 0x3C, no_upgrade, equip_goron_tunic_message, -1, -1, NULL), // Goron Tunic
[GI_TUNIC_ZORA] = ITEM_ROW(0x53, GILDED_CHEST, 0x43, -1, 0x90B0, 0x00F2, 0x3D, no_upgrade, equip_zora_tunic_message, -1, -1, NULL), // Zora Tunic
[GI_BOOTS_IRON] = ITEM_ROW(0x53, GILDED_CHEST, 0x45, -1, 0x0053, 0x0118, 0x47, no_upgrade, no_effect, -1, -1, NULL), // Iron Boots
[GI_BOOTS_HOVER] = ITEM_ROW(0x53, GILDED_CHEST, 0x46, -1, 0x0054, 0x0157, 0x5F, no_upgrade, no_effect, -1, -1, NULL), // Hover Boots
[GI_QUIVER_40] = ITEM_ROW(0x53, GILDED_CHEST, 0x4B, -1, 0x0056, 0x00BE, 0x16, no_upgrade, no_effect, -1, -1, NULL), // Big Quiver
Expand Down
232 changes: 231 additions & 1 deletion ASM/c/message.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "message.h"
#include "z64.h"
#include "stdbool.h"
#include "save.h"

Expand Down Expand Up @@ -151,6 +150,144 @@ void treasure_chest_game_message() {
}
}

extern uint8_t EQUIPMENT_TEXTBOX;
uint8_t kokiri_sword_message = 0;
uint8_t biggoron_sword_message = 0;
uint8_t deku_shield_message = 0;
uint8_t hylian_shield_message = 0;
uint8_t mirror_shield_message = 0;
uint8_t goron_tunic_message = 0;
uint8_t zora_tunic_message = 0;
void manage_kokiri_sword_message() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd put a space above this line

if (kokiri_sword_message == 1 &&
z64_MessageGetState(((uint8_t *)(&z64_game)) + 0x20D8) == 0) {
z64_DisplayTextbox(&z64_game, 0x045E, 0);
kokiri_sword_message = 2;
}
if (kokiri_sword_message == 2) {
MessageContext *msgCtx = &(z64_game.msgContext);
z64_link.common.frozen = 10;
if (Message_ShouldAdvance(&z64_game)) {
if (msgCtx->choiceIndex == 0) {
z64_file.button_items[0] = Z64_ITEM_KOKIRI_SWORD;
Interface_LoadItemIcon1(&z64_game, 0);
Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_KOKIRI);
}
kokiri_sword_message = 0;
}
}
}

void manage_biggoron_sword_message() {
if (biggoron_sword_message == 1 &&
z64_MessageGetState(((uint8_t *)(&z64_game)) + 0x20D8) == 0) {
z64_DisplayTextbox(&z64_game, 0x045E, 0);
biggoron_sword_message = 2;
}
if (biggoron_sword_message == 2) {
MessageContext *msgCtx = &(z64_game.msgContext);
z64_link.common.frozen = 10;
if (Message_ShouldAdvance(&z64_game)) {
if (msgCtx->choiceIndex == 0) {
z64_file.button_items[0] = Z64_ITEM_BIGGORON_SWORD;
Interface_LoadItemIcon1(&z64_game, 0);
Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_BIGGORON);
}
biggoron_sword_message = 0;
}
}
}

void manage_deku_shield_message() {
if (deku_shield_message == 1 &&
z64_MessageGetState(((uint8_t *)(&z64_game)) + 0x20D8) == 0) {
z64_DisplayTextbox(&z64_game, 0x045E, 0);
deku_shield_message = 2;
}
if (deku_shield_message == 2) {
MessageContext *msgCtx = &(z64_game.msgContext);
z64_link.common.frozen = 10;
if (Message_ShouldAdvance(&z64_game)) {
if (msgCtx->choiceIndex == 0) {
Inventory_ChangeEquipment(EQUIP_TYPE_SHIELD, EQUIP_VALUE_SHIELD_DEKU);
}
deku_shield_message = 0;
}
}
}

void manage_hylian_shield_message() {
if (hylian_shield_message == 1 &&
z64_MessageGetState(((uint8_t *)(&z64_game)) + 0x20D8) == 0) {
z64_DisplayTextbox(&z64_game, 0x045E, 0);
hylian_shield_message = 2;
}
if (hylian_shield_message == 2) {
MessageContext *msgCtx = &(z64_game.msgContext);
z64_link.common.frozen = 10;
if (Message_ShouldAdvance(&z64_game)) {
if (msgCtx->choiceIndex == 0) {
Inventory_ChangeEquipment(EQUIP_TYPE_SHIELD, EQUIP_VALUE_SHIELD_HYLIAN);
}
hylian_shield_message = 0;
}
}
}

void manage_mirror_shield_message() {
if (mirror_shield_message == 1 &&
z64_MessageGetState(((uint8_t *)(&z64_game)) + 0x20D8) == 0) {
z64_DisplayTextbox(&z64_game, 0x045E, 0);
mirror_shield_message = 2;
}
if (mirror_shield_message == 2) {
MessageContext *msgCtx = &(z64_game.msgContext);
z64_link.common.frozen = 10;
if (Message_ShouldAdvance(&z64_game)) {
if (msgCtx->choiceIndex == 0) {
Inventory_ChangeEquipment(EQUIP_TYPE_SHIELD, EQUIP_VALUE_SHIELD_MIRROR);
}
mirror_shield_message = 0;
}
}
}

void manage_goron_tunic_message() {
if (goron_tunic_message == 1 &&
z64_MessageGetState(((uint8_t *)(&z64_game)) + 0x20D8) == 0) {
z64_DisplayTextbox(&z64_game, 0x045E, 0);
goron_tunic_message = 2;
}
if (goron_tunic_message == 2) {
MessageContext *msgCtx = &(z64_game.msgContext);
z64_link.common.frozen = 10;
if (Message_ShouldAdvance(&z64_game)) {
if (msgCtx->choiceIndex == 0) {
Inventory_ChangeEquipment(EQUIP_TYPE_TUNIC, EQUIP_VALUE_TUNIC_GORON);
}
goron_tunic_message = 0;
}
}
}

void manage_zora_tunic_message() {
if (zora_tunic_message == 1 &&
z64_MessageGetState(((uint8_t *)(&z64_game)) + 0x20D8) == 0) {
z64_DisplayTextbox(&z64_game, 0x045E, 0);
zora_tunic_message = 2;
}
if (zora_tunic_message == 2) {
MessageContext *msgCtx = &(z64_game.msgContext);
z64_link.common.frozen = 10;
if (Message_ShouldAdvance(&z64_game)) {
if (msgCtx->choiceIndex == 0) {
Inventory_ChangeEquipment(EQUIP_TYPE_TUNIC, EQUIP_VALUE_TUNIC_ZORA);
}
zora_tunic_message = 0;
}
}
}

// Function to display custom textboxes ingame.
void display_misc_messages() {
if (z64_MessageGetState(((uint8_t *)(&z64_game)) + 0x20D8) == 0) {
Expand All @@ -166,4 +303,97 @@ void display_misc_messages() {
treasure_chest_game_show_message = 0;
}
}
if (EQUIPMENT_TEXTBOX & 1 << 0) {
manage_deku_shield_message();
manage_hylian_shield_message();
manage_mirror_shield_message();
}
if (EQUIPMENT_TEXTBOX & 1 << 1) {
manage_kokiri_sword_message();
manage_biggoron_sword_message();
}
if (EQUIPMENT_TEXTBOX & 1 << 2) {
manage_goron_tunic_message();
manage_zora_tunic_message();
}
}

void equip_kokiri_sword_message(z64_file_t* save, int16_t arg1, int16_t arg2) {
if (LINK_IS_ADULT) {
return;
}
// If kokiri sword is already equipped.
if (z64_file.equip_sword == 1) {
return;
}
kokiri_sword_message = 1;
}

void equip_biggoron_sword_message(z64_file_t* save, int16_t arg1, int16_t arg2) {
if (!LINK_IS_ADULT) {
return;
}
// If biggoron sword is already equipped.
if (z64_file.equip_sword == 3) {
return;
}
biggoron_sword_message = 1;
}

void equip_deku_shield_message(z64_file_t* save, int16_t arg1, int16_t arg2) {
if (LINK_IS_ADULT) {
return;
}
// If a deku shield is already equipped.
if (z64_file.equip_shield == 1) {
return;
}
deku_shield_message = 1;
}

void equip_hylian_shield_message(z64_file_t* save, int16_t arg1, int16_t arg2) {
// Only ask for child if he has no shield equipped at all.
if (!LINK_IS_ADULT) {
if (z64_file.equip_shield == 1) {
return;
}
}
// If a hylian shield or mirror shield is already equipped.
if (z64_file.equip_shield > 1) {
return;
}
hylian_shield_message = 1;
}

void equip_mirror_shield_message(z64_file_t* save, int16_t arg1, int16_t arg2) {
if (!LINK_IS_ADULT) {
return;
}
// If mirror shield is already equipped.
if (z64_file.equip_shield == 3) {
return;
}
mirror_shield_message = 1;
}

void equip_goron_tunic_message(z64_file_t* save, int16_t arg1, int16_t arg2) {
if (!LINK_IS_ADULT) {
return;
}
// If a goron tunic is already equipped.
if (z64_file.equip_tunic == 2) {
return;
}
goron_tunic_message = 1;
}

void equip_zora_tunic_message(z64_file_t* save, int16_t arg1, int16_t arg2) {
if (!LINK_IS_ADULT) {
return;
}
// If a zora tunic is already equipped.
if (z64_file.equip_shield == 3) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is checking for shield instead of tunic

return;
}
zora_tunic_message = 1;
}
12 changes: 12 additions & 0 deletions ASM/c/message.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#ifndef MESSAGE_H
#define MESSAGE_H

#include "z64.h"

void Inventory_ChangeEquipment(int16_t equipment, uint16_t value);
uint8_t Message_ShouldAdvance(z64_game_t* play);

void equip_kokiri_sword_message(z64_file_t* save, int16_t arg1, int16_t arg2);
void equip_biggoron_sword_message(z64_file_t* save, int16_t arg1, int16_t arg2);
void equip_deku_shield_message(z64_file_t* save, int16_t arg1, int16_t arg2);
void equip_hylian_shield_message(z64_file_t* save, int16_t arg1, int16_t arg2);
void equip_mirror_shield_message(z64_file_t* save, int16_t arg1, int16_t arg2);
void equip_goron_tunic_message(z64_file_t* save, int16_t arg1, int16_t arg2);
void equip_zora_tunic_message(z64_file_t* save, int16_t arg1, int16_t arg2);
void display_misc_messages();

#endif
39 changes: 39 additions & 0 deletions ASM/c/z64.h
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,45 @@ typedef struct {
int16_t copyDestFileIndex; /* 0x1CA50 */
} z64_FileChooseContext_t;

typedef enum EquipmentType {
/* 0 */ EQUIP_TYPE_SWORD,
/* 1 */ EQUIP_TYPE_SHIELD,
/* 2 */ EQUIP_TYPE_TUNIC,
/* 3 */ EQUIP_TYPE_BOOTS,
/* 4 */ EQUIP_TYPE_MAX
} EquipmentType;

typedef enum EquipValueSword {
/* 0 */ EQUIP_VALUE_SWORD_NONE,
/* 1 */ EQUIP_VALUE_SWORD_KOKIRI,
/* 2 */ EQUIP_VALUE_SWORD_MASTER,
/* 3 */ EQUIP_VALUE_SWORD_BIGGORON,
/* 4 */ EQUIP_VALUE_SWORD_MAX
} EquipValueSword;

typedef enum EquipValueShield {
/* 0 */ EQUIP_VALUE_SHIELD_NONE,
/* 1 */ EQUIP_VALUE_SHIELD_DEKU,
/* 2 */ EQUIP_VALUE_SHIELD_HYLIAN,
/* 3 */ EQUIP_VALUE_SHIELD_MIRROR,
/* 4 */ EQUIP_VALUE_SHIELD_MAX
} EquipValueShield;

typedef enum EquipValueTunic {
/* 0 */ EQUIP_VALUE_TUNIC_NONE,
/* 1 */ EQUIP_VALUE_TUNIC_KOKIRI,
/* 2 */ EQUIP_VALUE_TUNIC_GORON,
/* 3 */ EQUIP_VALUE_TUNIC_ZORA,
/* 4 */ EQUIP_VALUE_TUNIC_MAX
} EquipValueTunic;

typedef enum EquipValueBoots {
/* 0 */ EQUIP_VALUE_BOOTS_NONE,
/* 1 */ EQUIP_VALUE_BOOTS_KOKIRI,
/* 2 */ EQUIP_VALUE_BOOTS_IRON,
/* 3 */ EQUIP_VALUE_BOOTS_HOVER,
/* 4 */ EQUIP_VALUE_BOOTS_MAX
} EquipValueBoots;
typedef struct {
int32_t entrance_index; /* 0x0000 */
int32_t link_age; /* 0x0004 */
Expand Down
2 changes: 2 additions & 0 deletions ASM/ootSymbols.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
/* Addresses should be listed in order */
z64_EquippedItemOutlineTex = 0x2000E00;
z64_Gfx_SetupDL_42Opa = 0x8007E868;
Inventory_ChangeEquipment = 0x80081130;
Audio_StopCurrentMusic = 0x800C7684;
sprintf = 0x800CE7b4;
Fault_AddHungupAndCrashImpl = 0x800AF564;
Message_ShouldAdvance = 0x800D6110;
z64_ItemIcons = 0x800F8D2C;
z64_SfxDefaultPos = 0x80104394;
z64_SfxDefaultFreqAndVolScale = 0x801043A0;
Expand Down
2 changes: 2 additions & 0 deletions ASM/src/config.asm
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ SHUFFLE_SILVER_RUPEES:
.byte 0x00
CFG_DUNGEON_INFO_SILVER_RUPEES:
.byte 0x00
EQUIPMENT_TEXTBOX:
.byte 0x00
CUSTOM_KEY_MODELS:
.byte 0x00
SHUFFLE_OCARINA_BUTTONS:
Expand Down
2 changes: 2 additions & 0 deletions Messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@
(0x045B, ("\x12\x68\x7AMweep", 0x23)),
(0x045C, ("Come back when you have\x01your own bow and you'll get the\x01\x05\x41real prize\x05\x40!\x0E\x78", 0x00)),
(0x045D, ("\x12\x68\x5F\x05\x44This game seems shady. Maybe\x01the \x05\x41eye of truth\x05\x44 will show the\x01way forward?\x0E\x78", 0x00)),
(0x045E, ("Equip it now?\x01\x01\x1B\x05\x42Yes\x01No\x05\x40", 0x00)),
(0x6013, ("Hey, newcomer!\x04Want me to throw you in jail?\x01\x01\x1B\x05\x42No\x01Yes\x05\x40", 0x00)),
]

Expand Down Expand Up @@ -1320,6 +1321,7 @@ def is_exempt(m: Message) -> bool:
)
shuffle_exempt = [
0x045C, # Adult shooting gallery helping message when the player wins without having a bow
0x045E, # Equipment prompt
0x208D, # "One more lap!" for Cow in House race.
0xFFFC, # Character data from JP table used on title and file select screens
]
Expand Down
Loading