Skip to content

Commit

Permalink
Chests with bottle content no longer show animation upon receiving re…
Browse files Browse the repository at this point in the history
…fill. (#30)

Hero Shield items will now give you a silver rupee if you already have the mirror shield.

Fix Bottle Logic, as well as chest repeat logic.

Progressive items will now properly give you fishing passes if retrieved once from trade items.

Better passthrough handling with bottle refills and blue rupee chest cases.
  • Loading branch information
PhlexPlexico authored Feb 8, 2024
1 parent c585614 commit 44223c5
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 94 deletions.
2 changes: 2 additions & 0 deletions code/include/rnd/item_upgrade.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ namespace rnd {
GetItemID ItemUpgrade_Sword(game::SaveData*, GetItemID);
GetItemID ItemUpgrade_ArrowsToRupee(game::SaveData*, GetItemID);
GetItemID ItemUpgrade_BombsToRupee(game::SaveData*, GetItemID);
GetItemID ItemUpgrade_RefillBottle(game::SaveData*, GetItemID);
GetItemID ItemUpgrade_CheckShield(game::SaveData*, GetItemID);
// GetItemID ItemUpgrade_LetterToBottle(game::SaveData*, GetItemID);
} // namespace rnd

Expand Down
149 changes: 66 additions & 83 deletions code/source/rnd/item_override.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ namespace rnd {
rItemOverrides[0].value.getItemId = 0x26;
rItemOverrides[0].value.looksLikeItemId = 0x26;
rItemOverrides[1].key.scene = 0x6F;
rItemOverrides[1].key.type = ItemOverride_Type::OVR_COLLECTABLE;
rItemOverrides[1].value.getItemId = 0x34;
rItemOverrides[1].value.looksLikeItemId = 0x34;
rItemOverrides[1].key.type = ItemOverride_Type::OVR_CHEST;
rItemOverrides[1].value.getItemId = 0x32;
rItemOverrides[1].value.looksLikeItemId = 0x32;
rItemOverrides[2].key.scene = 0x12;
rItemOverrides[2].key.type = ItemOverride_Type::OVR_COLLECTABLE;
rItemOverrides[2].value.getItemId = 0x37;
Expand Down Expand Up @@ -105,15 +105,15 @@ namespace rnd {
}

ItemOverride ItemOverride_Lookup(game::act::Actor* actor, u16 scene, s16 getItemId) {
ItemOverride_Key key = ItemOverride_GetSearchKey(actor, scene, getItemId);
if (key.all == 0) {
return (ItemOverride){0};
}
// #if defined ENABLE_DEBUG || defined DEBUG_PRINT
// rnd::util::Print(
// "%s: Our param values:\nActor Type %#04x\nGet Item ID: %#04x\nActor ID: %#06x\n",
// __func__, actor->actor_type, getItemId, actor->id);
// #endif
ItemOverride_Key key = ItemOverride_GetSearchKey(actor, scene, getItemId);
if (key.all == 0) {
return (ItemOverride){0};
}
return ItemOverride_LookupByKey(key);
}

Expand Down Expand Up @@ -141,7 +141,6 @@ namespace rnd {
u16 resolvedGetItemId = ItemTable_ResolveUpgrades(override.value.getItemId);

ItemRow* itemRow = ItemTable_GetItemRow(resolvedGetItemId);
// XXX: Maybe create function for progressive items so that the item drawn is correct?
u8 looksLikeItemId = ItemOverride_SetProgressiveItemDraw(override);

rActiveItemOverride = override;
Expand Down Expand Up @@ -492,6 +491,20 @@ namespace rnd {
gExtSaveData.givenItemChecks.enMtnDeedGivenItem = 1;
} else if (storedGetItemId == rnd::GetItemID::GI_OCEAN_TITLE_DEED) {
gExtSaveData.givenItemChecks.enOcnDeedGivenItem = 1;
} else if (storedGetItemId == GetItemID::GI_BOTTLE_MILK) {
gExtSaveData.givenItemChecks.bottleMilkGiven = 1;
} else if (storedGetItemId == GetItemID::GI_BOTTLE_GOLD_DUST ||
(s16)storedGetItemId == -(s16)GetItemID::GI_BOTTLE_GOLD_DUST) {
gExtSaveData.givenItemChecks.bottleGoldDustGiven = 1;
} else if (storedGetItemId == GetItemID::GI_BOTTLE_CHATEAU_ROMANI ||
(s16)storedGetItemId == -(s16)GetItemID::GI_BOTTLE_CHATEAU_ROMANI) {
gExtSaveData.givenItemChecks.bottleChateuGiven = 1;
} else if (storedGetItemId == GetItemID::GI_BOTTLE_SEAHORSE ||
(s16)storedGetItemId == -(s16)GetItemID::GI_BOTTLE_SEAHORSE) {
gExtSaveData.givenItemChecks.bottleSeahorseGiven = 1;
} else if (storedGetItemId == GetItemID::GI_BOTTLE_MYSTERY_MILK ||
(s16)storedGetItemId == -(s16)GetItemID::GI_BOTTLE_MYSTERY_MILK) {
gExtSaveData.givenItemChecks.bottleMysteryMilkGiven = 1;
}
}

Expand Down Expand Up @@ -550,31 +563,42 @@ namespace rnd {
return;
}

void ItemOverride_SetBottleRefill(game::act::Player* player, s16 refItemId, bool isChest = false) {
u16 ItemOverride_SetBottleRefill(game::act::Player* player, u16 refItemId) {
switch (refItemId) {
case 0x60:
player->get_item_id = isChest ? -(s16)GetItemID::GI_BOTTLE_MILK_REFILL : (s16)GetItemID::GI_BOTTLE_MILK_REFILL;
if (gExtSaveData.givenItemChecks.bottleMilkGiven == 1) {
storedGetItemId = GetItemID::GI_BOTTLE_MILK_REFILL;
return 0x92;
}
break;
case 0x6A:
player->get_item_id =
isChest ? -(s16)GetItemID::GI_BOTTLE_GOLD_DUST_REFILL : (s16)GetItemID::GI_BOTTLE_GOLD_DUST_REFILL;
if (gExtSaveData.givenItemChecks.bottleGoldDustGiven == 1) {
storedGetItemId = GetItemID::GI_BOTTLE_GOLD_DUST_REFILL;
return 0x93;
}
break;
case 0x6F:
player->get_item_id =
isChest ? -(s16)GetItemID::GI_BOTTLE_CHATEAU_ROMANI_REFILL : (s16)GetItemID::GI_BOTTLE_CHATEAU_ROMANI_REFILL;
if (gExtSaveData.givenItemChecks.bottleChateuGiven == 1) {
storedGetItemId = GetItemID::GI_BOTTLE_CHATEAU_ROMANI_REFILL;
return 0x91;
}
break;
case 0x6E:
player->get_item_id =
isChest ? -(s16)GetItemID::GI_BOTTLE_SEAHORSE_REFILL : (s16)GetItemID::GI_BOTTLE_SEAHORSE_REFILL;
if (gExtSaveData.givenItemChecks.bottleSeahorseGiven == 1) {
storedGetItemId = GetItemID::GI_BOTTLE_SEAHORSE_REFILL;
return 0x95;
}
break;
case 0x70:
player->get_item_id = isChest ? -(s16)GetItemID::GI_BOTTLE_MYSTERY_MILK : (s16)GetItemID::GI_BOTTLE_MYSTERY_MILK;
if (gExtSaveData.givenItemChecks.bottleMysteryMilkGiven == 0) {
storedGetItemId = GetItemID::GI_BOTTLE_MYSTERY_MILK_REFILL;
return 0x94;
}
break;
default:
player->get_item_id = isChest ? -(s16)GetItemID::GI_RUPEE_BLUE : (s16)GetItemID::GI_RUPEE_BLUE;
break;
return (u16)GetItemID::GI_RUPEE_BLUE;
}
return;
return (u16)refItemId;
}

u8 ItemOverride_SetProgressiveItemDraw(ItemOverride override) {
Expand All @@ -600,7 +624,8 @@ namespace rnd {
else
return 0x09;
}
return override.value.looksLikeItemId;
// No override, use the base item.
return 0x00;
}

extern "C" {
Expand Down Expand Up @@ -672,89 +697,47 @@ namespace rnd {
return;
} else if (override.key.type == ItemOverride_Type::OVR_CHEST &&
gExtSaveData.chestRewarded[override.key.scene][override.key.flag] == 1) {
// Override was already given, use base game's item code
// If we're a bottled item in our override, we've been received before. Give a refill.
u16 refItemId = override.value.getItemId;
#if defined ENABLE_DEBUG || defined DEBUG_PRINT
rnd::util::Print("%s: Our ref item id is %#04x\n", __func__, refItemId);
#endif
ItemOverride_Clear();
ItemOverride_SetBottleRefill(player, (s16)refItemId, true);
return;
} else if (override.value.getItemId > 0x45 && override.value.getItemId < 0x4B) {
// This check is mainly to ensure we do not have repeatable progressive items within these base items.
// This is to ensure fairness and allows us to place these items without second guessing in logic.
// Let's be a bit rude and give them fishing passes.
// Override was already given, give a blue rupee instead.
override.value.getItemId = 0x02;
override.value.looksLikeItemId = 0x02;
}

// This check is mainly to ensure we do not have repeatable progressive items within these base items.
// This is to ensure fairness and allows us to place these items without second guessing in logic.
// Let's be a bit rude and give them fishing passes.
if (override.value.getItemId > 0x45 || override.value.getItemId < 0x4A) {
if (incomingGetItemId == (s16)GetItemID::GI_MOONS_TEAR &&
gExtSaveData.givenItemChecks.enObjMoonStoneGivenItem == 1) {
player->get_item_id = (s16)GetItemID::GI_FISHING_HOLE_PASS;
ItemOverride_Clear();
return;
} else if (incomingGetItemId == (s16)GetItemID::GI_TOWN_TITLE_DEED &&
gExtSaveData.givenItemChecks.enTownDeedGivenItem == 1) {
player->get_item_id = (s16)GetItemID::GI_FISHING_HOLE_PASS;
ItemOverride_Clear();
return;
} else if (incomingGetItemId == (s16)GetItemID::GI_SWAMP_TITLE_DEED &&
gExtSaveData.givenItemChecks.enSwampDeedGivenItem == 1) {
player->get_item_id = (s16)GetItemID::GI_FISHING_HOLE_PASS;
ItemOverride_Clear();
return;
} else if (incomingGetItemId == (s16)GetItemID::GI_MOUNTAIN_TITLE_DEED &&
gExtSaveData.givenItemChecks.enMtnDeedGivenItem == 1) {
player->get_item_id = (s16)GetItemID::GI_FISHING_HOLE_PASS;
ItemOverride_Clear();
return;
} else if (incomingGetItemId == (s16)GetItemID::GI_OCEAN_TITLE_DEED &&
gExtSaveData.givenItemChecks.enOcnDeedGivenItem == 1) {
player->get_item_id = (s16)GetItemID::GI_FISHING_HOLE_PASS;
ItemOverride_Clear();
return;
}
} else if (override.key.type != ItemOverride_Type::OVR_CHEST &&
(override.value.getItemId == 0x60 ||
(override.value.getItemId > 0x69 && override.value.getItemId < 0x71))) {
switch (override.value.getItemId) {
case 0x60:
if (gExtSaveData.givenItemChecks.bottleMilkGiven == 0) {
gExtSaveData.givenItemChecks.bottleMilkGiven = 1;
} else {
ItemOverride_SetBottleRefill(player, (s16) override.value.getItemId);
return;
}
break;
case 0x6A:
if (gExtSaveData.givenItemChecks.bottleGoldDustGiven == 0) {
gExtSaveData.givenItemChecks.bottleGoldDustGiven = 1;
} else {
ItemOverride_SetBottleRefill(player, (s16) override.value.getItemId);
return;
}
break;
case 0x6F:
if (gExtSaveData.givenItemChecks.bottleGoldDustGiven == 0) {
gExtSaveData.givenItemChecks.bottleGoldDustGiven = 1;
} else {
ItemOverride_SetBottleRefill(player, (s16) override.value.getItemId);
return;
}
break;
case 0x6E:
if (gExtSaveData.givenItemChecks.bottleSeahorseGiven == 0) {
gExtSaveData.givenItemChecks.bottleSeahorseGiven = 1;
} else {
ItemOverride_SetBottleRefill(player, (s16) override.value.getItemId);
return;
}
break;
case 0x70:
if (gExtSaveData.givenItemChecks.bottleMysteryMilkGiven == 0) {
gExtSaveData.givenItemChecks.bottleMysteryMilkGiven = 1;
} else {
ItemOverride_SetBottleRefill(player, (s16) override.value.getItemId);
return;
}
break;
default:
player->get_item_id = -(s16)GetItemID::GI_RUPEE_BLUE;
break;
}
return;
}

// If we are a bottled item, store the GID to write the ext data. This will ensure through
// ItemUpgrade_BottleRefill that we get a refill on a bottle instead of a new bottle.
if (override.value.getItemId == 0x60 || (override.value.getItemId > 0x69 && override.value.getItemId < 0x71)) {
storedGetItemId = (GetItemID) override.value.getItemId;
}
ItemOverride_Activate(override);
s16 baseItemId = rActiveItemRow->baseItemId;
Expand Down
23 changes: 12 additions & 11 deletions code/source/rnd/item_table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ namespace rnd {
[0x32] =
ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::HeroShield, 0x0032, 0x000B3,
(s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s32)DrawGraphicItemID::DI_HERO_SHIELD,
(rnd::upgradeFunc)ItemUpgrade_None, ItemEffect_None, (s16)-1, (s16)-1), // Hero Sheild
(rnd::upgradeFunc)ItemUpgrade_CheckShield, ItemEffect_None, (s16)-1, (s16)-1), // Hero Sheild

[0x33] =
ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::MirrorShield, 0x0033, 0x000C3,
Expand Down Expand Up @@ -504,9 +504,10 @@ namespace rnd {
(s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s32)DrawGraphicItemID::DI_BOTTLE_DEKU_PRINCESS,
(rnd::upgradeFunc)ItemUpgrade_None, ItemEffect_None, (s16)-1, (s16)-1), // Bottle With Deku Princess

[0x60] = ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::Milk, 0x0060, 0x00B6,
(s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s32)DrawGraphicItemID::DI_MILK_FULL,
(rnd::upgradeFunc)ItemUpgrade_None, ItemEffect_None, (s16)-1, (s16)-1), // Bottle With Milk
[0x60] =
ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::Milk, 0x0060, 0x00B6, (s8)0xFF,
(s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s32)DrawGraphicItemID::DI_MILK_FULL,
(rnd::upgradeFunc)ItemUpgrade_RefillBottle, ItemEffect_None, (s16)-1, (s16)-1), // Bottle With Milk

[0x61] =
ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::Milk, 0x0061, 0x00B6, (s8)0xFF,
Expand Down Expand Up @@ -550,10 +551,10 @@ namespace rnd {
(s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s32)DrawGraphicItemID::DI_BOTTLE_ZORA_EGG,
(rnd::upgradeFunc)ItemUpgrade_None, ItemEffect_None, (s16)-1, (s16)-1), // Bottle With Zora Egg

[0x6A] =
ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::GoldDust, 0x006A, 0x01E9,
(s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s32)DrawGraphicItemID::DI_GOLD_DUST,
(rnd::upgradeFunc)ItemUpgrade_None, ItemEffect_None, (s16)-1, (s16)-1), // Bottle With Gold Dust
[0x6A] = ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::GoldDust, 0x006A, 0x01E9,
(s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s32)DrawGraphicItemID::DI_GOLD_DUST,
(rnd::upgradeFunc)ItemUpgrade_RefillBottle, ItemEffect_None, (s16)-1,
(s16)-1), // Bottle With Gold Dust

[0x6B] = ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::MagicalMushroom, 0x006B,
0x021D, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF,
Expand All @@ -572,20 +573,20 @@ namespace rnd {

[0x6E] = ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::SeaHorse, 0x006E, 0x01E9,
(s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s32)DrawGraphicItemID::DI_BOTTLE_SEAHORSE,
(rnd::upgradeFunc)ItemUpgrade_None, ItemEffect_None, (s16)-1,
(rnd::upgradeFunc)ItemUpgrade_RefillBottle, ItemEffect_None, (s16)-1,
(s16)-1), // Bottle With Sea Horse - Gold Dust Object

[0x6F] = ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::ChateauRomani, 0x006F,
0x0227, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF,
(s32)DrawGraphicItemID::DI_BOTTLE_CHATEAU_ROMANI, (rnd::upgradeFunc)ItemUpgrade_None,
(s32)DrawGraphicItemID::DI_BOTTLE_CHATEAU_ROMANI, (rnd::upgradeFunc)ItemUpgrade_RefillBottle,
ItemEffect_None, (s16)-1, (s16)-1), // Bottle With Chateau Romani

// XXX: Trade Item, may have to change values? Seems rather individual and leads to fishing
// pass.
[0x70] =
ITEM_ROW((u32)GetItemID::GI_NUTS_30, ChestType::WOODEN_BIG, (u8)game::ItemId::MysteryMilk, 0x00CE, 0x00B6,
(s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s8)0xFF, (s32)DrawGraphicItemID::DI_BOTTLE_MYSTERY_MILK,
(rnd::upgradeFunc)ItemUpgrade_None, ItemEffect_None, (s16)-1,
(rnd::upgradeFunc)ItemUpgrade_RefillBottle, ItemEffect_None, (s16)-1,
(s16)-1), // Bottle With Mystery Milk

[0x71] =
Expand Down
51 changes: 51 additions & 0 deletions code/source/rnd/item_upgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,57 @@ namespace rnd {
getItemId;
}

GetItemID ItemUpgrade_RefillBottle(game::SaveData* saveCtx, GetItemID getItemId) {
switch (getItemId) {
case GetItemID::GI_BOTTLE_MILK:
if (gExtSaveData.givenItemChecks.bottleMilkGiven == 1) {
return GetItemID::GI_BOTTLE_MILK_REFILL;
}
break;
case GetItemID::GI_BOTTLE_GOLD_DUST:
if (gExtSaveData.givenItemChecks.bottleGoldDustGiven == 1) {
#if defined ENABLE_DEBUG || defined DEBUG_PRINT
rnd::util::Print("%s: Gold dust given, overriding for refill.\n", __func__);
#endif
return GetItemID::GI_BOTTLE_GOLD_DUST_REFILL;
}
break;
case GetItemID::GI_BOTTLE_SEAHORSE:
if (gExtSaveData.givenItemChecks.bottleSeahorseGiven == 1) {
return GetItemID::GI_BOTTLE_SEAHORSE_REFILL;
}
break;
case GetItemID::GI_BOTTLE_CHATEAU_ROMANI:
if (gExtSaveData.givenItemChecks.bottleChateuGiven == 1) {
return GetItemID::GI_BOTTLE_CHATEAU_ROMANI_REFILL;
}
break;
case GetItemID::GI_BOTTLE_MYSTERY_MILK:
if (gExtSaveData.givenItemChecks.bottleMysteryMilkGiven == 1) {
return GetItemID::GI_BOTTLE_MYSTERY_MILK_REFILL;
}
break;
default:
return getItemId;
}
return getItemId;
}

GetItemID ItemUpgrade_CheckShield(game::SaveData* saveCtx, GetItemID getItemId) {
switch(saveCtx->equipment.sword_shield.shield) {
case game::ShieldType::NoShield:
return getItemId;
case game::ShieldType::HeroShield:
return getItemId;
case game::ShieldType::MirrorShield:
if (getItemId == GetItemID::GI_SHIELD_HERO)
return GetItemID::GI_RUPEE_SILVER; // Give siler rupee, close enough to same cost.
else return getItemId;
default:
return getItemId;
}
}

// TODO: Trade quest items.
/*
game::ItemId ItemUpgrade_LetterToBottle(game::SaveData *saveCtx, GetItemId GetItemId) {
Expand Down

0 comments on commit 44223c5

Please sign in to comment.