mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-07-16 10:02:59 -07:00
* fix some warnings * fix error caught by mac build, fix 3 more warnings * merge fix * feedback * remove color refactor
449 lines
16 KiB
C++
449 lines
16 KiB
C++
#include "item.h"
|
|
#include "item_location.h"
|
|
|
|
#include "context.h"
|
|
#include "logic.h"
|
|
#include "3drando/item_pool.hpp"
|
|
#include "z64item.h"
|
|
#include "variables.h"
|
|
#include "macros.h"
|
|
#include "functions.h"
|
|
#include "../../OTRGlobals.h"
|
|
|
|
namespace Rando {
|
|
Item::Item() : randomizerGet(RG_NONE), type(ITEMTYPE_ITEM), getItemId(GI_NONE), advancement(false), hintKey(RHT_NONE),
|
|
progressive(false), price(0) {}
|
|
Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_,
|
|
const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const uint16_t itemId_,
|
|
const uint16_t objectId_, const uint16_t gid_, const uint16_t textId_, const uint16_t field_,
|
|
const int16_t chestAnimation_, const GetItemCategory category_, const uint16_t modIndex_,
|
|
const bool progressive_, const uint16_t price_)
|
|
: randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_),
|
|
advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), progressive(progressive_), price(price_) {
|
|
if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) {
|
|
giEntry = std::make_shared<GetItemEntry>(GetItemEntry{ itemId_, field_, static_cast<int16_t>((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, objectId_, modIndex_, TABLE_RANDOMIZER, static_cast<int16_t>(randomizerGet_), gid_, true, ITEM_FROM_NPC, category_, static_cast<uint16_t>(randomizerGet_), MOD_RANDOMIZER, NULL });
|
|
}
|
|
else {
|
|
giEntry = std::make_shared<GetItemEntry>(GetItemEntry{ itemId_, field_, static_cast<int16_t>((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, objectId_, modIndex_, TABLE_VANILLA, getItemId_, gid_, true, ITEM_FROM_NPC, category_, itemId_, modIndex_, NULL });
|
|
}
|
|
}
|
|
|
|
Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_,
|
|
const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const bool progressive_,
|
|
const uint16_t price_)
|
|
: randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_),
|
|
advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), progressive(progressive_), price(price_) {
|
|
}
|
|
|
|
Item::~Item() = default;
|
|
|
|
void Item::ApplyEffect() const {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
ctx->GetLogic()->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), true);
|
|
ctx->GetLogic()->SetInLogic(logicVal, true);
|
|
}
|
|
|
|
void Item::UndoEffect() const {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
ctx->GetLogic()->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), false);
|
|
ctx->GetLogic()->SetInLogic(logicVal, false);
|
|
}
|
|
|
|
const Text& Item::GetName() const {
|
|
return name;
|
|
}
|
|
|
|
bool Item::IsAdvancement() const {
|
|
return advancement;
|
|
}
|
|
|
|
int Item::GetItemID() const {
|
|
return getItemId;
|
|
}
|
|
|
|
ItemType Item::GetItemType() const {
|
|
return type;
|
|
}
|
|
|
|
LogicVal Item::GetLogicVal() const {
|
|
return logicVal;
|
|
}
|
|
|
|
RandomizerGet Item::GetRandomizerGet() const {
|
|
return randomizerGet;
|
|
}
|
|
|
|
uint16_t Item::GetPrice() const {
|
|
return price;
|
|
}
|
|
|
|
std::shared_ptr<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursion)
|
|
if (giEntry != nullptr) {
|
|
return giEntry;
|
|
}
|
|
std::shared_ptr<Rando::Context> ctx = Rando::Context::GetInstance();
|
|
auto logic = ctx->GetLogic();
|
|
RandomizerGet actual = RG_NONE;
|
|
const bool tycoonWallet = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INCLUDE_TYCOON_WALLET);
|
|
const u8 infiniteUpgrades = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INFINITE_UPGRADES);
|
|
switch (randomizerGet) {
|
|
case RG_PROGRESSIVE_STICK_UPGRADE:
|
|
switch (logic->CurrentUpgrade(UPG_STICKS)) {
|
|
case 0:
|
|
if (ctx->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG)) {
|
|
actual = RG_DEKU_STICK_BAG;
|
|
break;
|
|
}
|
|
[[fallthrough]];
|
|
case 1:
|
|
if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) {
|
|
actual = RG_STICK_UPGRADE_INF;
|
|
} else {
|
|
actual = RG_DEKU_STICK_CAPACITY_20;
|
|
}
|
|
break;
|
|
case 2:
|
|
actual = RG_DEKU_STICK_CAPACITY_30;
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) {
|
|
actual = RG_STICK_UPGRADE_INF;
|
|
} else {
|
|
actual = RG_DEKU_STICK_CAPACITY_30;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_NUT_UPGRADE:
|
|
switch (logic->CurrentUpgrade(UPG_NUTS)) {
|
|
case 0:
|
|
if (ctx->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG)) {
|
|
actual = RG_DEKU_NUT_BAG;
|
|
break;
|
|
}
|
|
[[fallthrough]];
|
|
case 1:
|
|
if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) {
|
|
actual = RG_NUT_UPGRADE_INF;
|
|
} else {
|
|
actual = RG_DEKU_NUT_CAPACITY_30;
|
|
}
|
|
break;
|
|
case 2:
|
|
actual = RG_DEKU_NUT_CAPACITY_40;
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) {
|
|
actual = RG_NUT_UPGRADE_INF;
|
|
} else {
|
|
actual = RG_DEKU_NUT_CAPACITY_40;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_BOMB_BAG:
|
|
switch (logic->CurrentUpgrade(UPG_BOMB_BAG)) {
|
|
case 0:
|
|
actual = RG_BOMB_BAG;
|
|
break;
|
|
case 1:
|
|
if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) {
|
|
actual = RG_BOMB_BAG_INF;
|
|
} else {
|
|
actual = RG_BIG_BOMB_BAG;
|
|
}
|
|
break;
|
|
case 2:
|
|
actual = RG_BIGGEST_BOMB_BAG;
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) {
|
|
actual = RG_BOMB_BAG_INF;
|
|
} else {
|
|
actual = RG_BIGGEST_BOMB_BAG;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_BOW:
|
|
switch (logic->CurrentUpgrade(UPG_QUIVER)) {
|
|
case 0:
|
|
actual = RG_FAIRY_BOW;
|
|
break;
|
|
case 1:
|
|
if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) {
|
|
actual = RG_QUIVER_INF;
|
|
} else {
|
|
actual = RG_BIG_QUIVER;
|
|
}
|
|
break;
|
|
case 2:
|
|
actual = RG_BIGGEST_QUIVER;
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) {
|
|
actual = RG_QUIVER_INF;
|
|
} else {
|
|
actual = RG_BIGGEST_QUIVER;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_SLINGSHOT:
|
|
switch (logic->CurrentUpgrade(UPG_BULLET_BAG)) {
|
|
case 0:
|
|
actual = RG_FAIRY_SLINGSHOT;
|
|
break;
|
|
case 1:
|
|
if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) {
|
|
actual = RG_BULLET_BAG_INF;
|
|
} else {
|
|
actual = RG_BIG_BULLET_BAG;
|
|
}
|
|
break;
|
|
case 2:
|
|
actual = RG_BIGGEST_BULLET_BAG;
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) {
|
|
actual = RG_BULLET_BAG_INF;
|
|
} else {
|
|
actual = RG_BIGGEST_BULLET_BAG;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_OCARINA:
|
|
switch (logic->CurrentInventory(ITEM_OCARINA_FAIRY)) {
|
|
case ITEM_NONE:
|
|
actual = RG_FAIRY_OCARINA;
|
|
break;
|
|
case ITEM_OCARINA_FAIRY:
|
|
case ITEM_OCARINA_TIME:
|
|
actual = RG_OCARINA_OF_TIME;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_HOOKSHOT:
|
|
switch (logic->CurrentInventory(ITEM_HOOKSHOT)) {
|
|
case ITEM_NONE:
|
|
actual = RG_HOOKSHOT;
|
|
break;
|
|
case ITEM_HOOKSHOT:
|
|
case ITEM_LONGSHOT:
|
|
actual = RG_LONGSHOT;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_STRENGTH:
|
|
switch (logic->CurrentUpgrade(UPG_STRENGTH)) {
|
|
case 0:
|
|
actual = RG_GORONS_BRACELET;
|
|
break;
|
|
case 1:
|
|
actual = RG_SILVER_GAUNTLETS;
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
actual = RG_GOLDEN_GAUNTLETS;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_WALLET:
|
|
if (!logic->CheckRandoInf(RAND_INF_HAS_WALLET)) {
|
|
actual = RG_CHILD_WALLET;
|
|
break;
|
|
}
|
|
switch (logic->CurrentUpgrade(UPG_WALLET)) {
|
|
case 0:
|
|
actual = RG_ADULT_WALLET;
|
|
break;
|
|
case 1:
|
|
actual = RG_GIANT_WALLET;
|
|
break;
|
|
case 2:
|
|
if(tycoonWallet){
|
|
actual = RG_TYCOON_WALLET;
|
|
break;
|
|
}
|
|
//fallthrough
|
|
case 3:
|
|
case 4:
|
|
if (infiniteUpgrades != RO_INF_UPGRADES_OFF) {
|
|
actual = RG_WALLET_INF;
|
|
} else {
|
|
actual = tycoonWallet ? RG_TYCOON_WALLET : RG_GIANT_WALLET;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_SCALE:
|
|
if (!logic->CheckRandoInf(RAND_INF_CAN_SWIM)) {
|
|
actual = RG_BRONZE_SCALE;
|
|
break;
|
|
}
|
|
switch (logic->CurrentUpgrade(UPG_SCALE)) {
|
|
case 0:
|
|
actual = RG_SILVER_SCALE;
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
actual = RG_GOLDEN_SCALE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_MAGIC_METER:
|
|
switch (logic->GetSaveContext()->magicLevel) {
|
|
case 0:
|
|
actual = RG_MAGIC_SINGLE;
|
|
break;
|
|
case 1:
|
|
actual = RG_MAGIC_DOUBLE;
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
if (infiniteUpgrades != RO_INF_UPGRADES_OFF) {
|
|
actual = RG_MAGIC_INF;
|
|
} else {
|
|
actual = RG_MAGIC_DOUBLE;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RG_PROGRESSIVE_GORONSWORD: // todo progressive?
|
|
actual = RG_BIGGORON_SWORD;
|
|
break;
|
|
case RG_PROGRESSIVE_BOMBCHUS:
|
|
if (logic->CurrentInventory(ITEM_BOMBCHU) == ITEM_NONE) {
|
|
actual = RG_BOMBCHU_BAG;
|
|
} else if (infiniteUpgrades != RO_INF_UPGRADES_OFF) {
|
|
actual = RG_BOMBCHU_INF;
|
|
} else {
|
|
actual = RG_BOMBCHU_10;
|
|
}
|
|
break;
|
|
default:
|
|
actual = RG_NONE;
|
|
break;
|
|
}
|
|
return StaticData::RetrieveItem(actual).GetGIEntry();
|
|
}
|
|
|
|
GetItemEntry Item::GetGIEntry_Copy() const {
|
|
return *GetGIEntry();
|
|
}
|
|
|
|
void Item::SetPrice(const uint16_t price_) {
|
|
price = price_;
|
|
}
|
|
|
|
void Item::SetAsPlaythrough() {
|
|
playthrough = true;
|
|
}
|
|
|
|
void Item::SetCustomDrawFunc(const CustomDrawFunc drawFunc) const {
|
|
giEntry->drawFunc = drawFunc;
|
|
}
|
|
|
|
bool Item::IsPlaythrough() const {
|
|
return playthrough;
|
|
}
|
|
|
|
bool Item::IsBottleItem() const {
|
|
return getItemId == 0x0F || // Empty Bottle
|
|
getItemId == 0X14 || // Bottle with Milk
|
|
(getItemId >= 0x8C && getItemId <= 0x94); // Rest of bottled contents
|
|
}
|
|
|
|
bool Item::IsMajorItem() const {
|
|
const auto ctx = Context::GetInstance();
|
|
if (type == ITEMTYPE_TOKEN) {
|
|
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) || ctx->LACSCondition() == RO_LACS_TOKENS;
|
|
}
|
|
|
|
if (type == ITEMTYPE_DROP || type == ITEMTYPE_EVENT || type == ITEMTYPE_SHOP || type == ITEMTYPE_MAP ||
|
|
type == ITEMTYPE_COMPASS) {
|
|
return false;
|
|
}
|
|
|
|
if (type == ITEMTYPE_DUNGEONREWARD && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
|
|
return false;
|
|
}
|
|
|
|
if ((randomizerGet == RG_BOMBCHU_5 || randomizerGet == RG_BOMBCHU_10 || randomizerGet == RG_BOMBCHU_20) &&
|
|
!ctx->GetOption(RSK_BOMBCHU_BAG)) {
|
|
return false;
|
|
}
|
|
|
|
if (randomizerGet == RG_HEART_CONTAINER || randomizerGet == RG_PIECE_OF_HEART ||
|
|
randomizerGet == RG_TREASURE_GAME_HEART) {
|
|
return false;
|
|
}
|
|
|
|
if (type == ITEMTYPE_SMALLKEY && (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON))) {
|
|
return false;
|
|
}
|
|
|
|
if (type == ITEMTYPE_FORTRESS_SMALLKEY && ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_VANILLA)) {
|
|
return false;
|
|
}
|
|
|
|
if (type == ITEMTYPE_BOSSKEY && getItemId != 0xAD &&
|
|
(ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA) || ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON))) {
|
|
return false;
|
|
}
|
|
// Ganons Castle Boss Key
|
|
if (getItemId == 0xAD && (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA) || ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON))) {
|
|
return false;
|
|
}
|
|
|
|
if (randomizerGet == RG_GREG_RUPEE) {
|
|
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG);
|
|
}
|
|
|
|
return IsAdvancement();
|
|
}
|
|
|
|
RandomizerHintTextKey Item::GetHintKey() const {
|
|
return hintKey;
|
|
}
|
|
|
|
const HintText& Item::GetHint() const {
|
|
return StaticData::hintTextTable[hintKey];
|
|
}
|
|
|
|
bool Item::operator==(const Item& right) const {
|
|
return type == right.GetItemType() && getItemId == right.GetItemID();
|
|
}
|
|
|
|
bool Item::operator!=(const Item& right) const {
|
|
return !operator==(right);
|
|
}
|
|
}
|