diff --git a/files.cmake b/files.cmake index 358ede7c81..8c01f6ceda 100644 --- a/files.cmake +++ b/files.cmake @@ -1381,6 +1381,10 @@ set(DUSK_FILES src/dusk/OSThread.cpp src/dusk/OSMutex.cpp # Randomizer files + src/dusk/randomizer/game/tools.cpp + src/dusk/randomizer/game/tools.h + src/dusk/randomizer/game/verify_item_functions.cpp + src/dusk/randomizer/game/verify_item_functions.h src/dusk/randomizer/logic/area.cpp src/dusk/randomizer/logic/area.hpp src/dusk/randomizer/logic/dungeon.cpp diff --git a/include/d/d_com_inf_game.h b/include/d/d_com_inf_game.h index 5ce43efd6d..34e7fa9180 100644 --- a/include/d/d_com_inf_game.h +++ b/include/d/d_com_inf_game.h @@ -1660,6 +1660,16 @@ inline void dComIfGs_setPachinkoNum(u8 i_num) { g_dComIfG_gameInfo.info.getPlayer().getItemRecord().setPachinkoNum(i_num); } +#if TARGET_PC +inline u8 dComIfGs_getAncientDocumentNum() { + return g_dComIfG_gameInfo.info.getPlayer().getItemRecord().getAncientDocumentNum(); +} + +inline void dComIfGs_setAncientDocumentNum(u8 i_num) { + g_dComIfG_gameInfo.info.getPlayer().getItemRecord().setAncientDocumentNum(i_num); +} +#endif + inline u8 dComIfGs_getPachinkoMax() { return 50; } diff --git a/include/d/d_save.h b/include/d/d_save.h index e43e7f1ad5..3356bd2e32 100644 --- a/include/d/d_save.h +++ b/include/d/d_save.h @@ -380,12 +380,21 @@ public: void setArrowNum(u8 i_num) { mArrowNum = i_num; } u8 getPachinkoNum() const { return mPachinkoNum; } void setPachinkoNum(u8 i_num) { mPachinkoNum = i_num; } +#if TARGET_PC + u8 getAncientDocumentNum() const { return mAncientDocumentNum; } + void setAncientDocumentNum(u8 i_num) { mAncientDocumentNum = i_num; } +#endif /* 0x0 */ u8 mArrowNum; /* 0x1 */ u8 mBombNum[3]; /* 0x4 */ u8 mBottleNum[4]; /* 0x8 */ u8 mPachinkoNum; +#if TARGET_PC + /* 0x9 */ u8 mAncientDocumentNum; // Custom Field for Randomizer + /* 0x9 */ u8 unk5[2]; +#else /* 0x9 */ u8 unk5[3]; +#endif }; // Size: 0xC class dSv_player_item_max_c { diff --git a/src/dusk/randomizer/game/tools.cpp b/src/dusk/randomizer/game/tools.cpp new file mode 100644 index 0000000000..e66ada7b5c --- /dev/null +++ b/src/dusk/randomizer/game/tools.cpp @@ -0,0 +1,87 @@ +#include "tools.h" +#include "d/d_com_inf_game.h" +#include "d/actor/d_a_alink.h" +#include "d/d_item.h" +#include "d/d_item_data.h" + +bool playerIsInRoomStage(s32 room, const char* stage) +{ + // Only check room if it is valid + // Room numbers are normally stored as int8_t, so the highest positive value is 127 + if ((room < 0) || (room > 127)) + { + return false; + } + + if (room != dStage_roomControl_c::mStayNo) + { + return false; + } + + // Only check stage if it is valid + if (!stage) + { + return false; + } + + return daAlink_c::checkStageName(stage); +} + +void checkTransformFromWolf() +{ + if (dComIfGs_getTransformStatus()) + { + daAlink_getAlinkActorClass()->procCoMetamorphoseInit(); + } +} + +u8 setNextWarashibeItem() +{ + static const u8 questItemsList[] = { + dItemNo_Randomizer_LETTER_e, + dItemNo_Randomizer_BILL_e, + dItemNo_Randomizer_WOOD_STATUE_e, + dItemNo_Randomizer_IRIAS_PENDANT_e, + dItemNo_Randomizer_HORSE_FLUTE_e + }; + + u32 listLength = sizeof(questItemsList) / sizeof(questItemsList[0]); + + u8 newItem = 0xFF; // null by default + + for (u32 i = 0; i < listLength; i++) + { + const u32 item = questItemsList[i]; + const u8 slotItem = dComIfGs_getItem(21, 0); + if (item == slotItem) + { + newItem = item; + u32 j = i; + do + { + j = (j + 1) % listLength; // Move to next index, wrapping around if needed. + if (checkItemGet(questItemsList[j], 1)) + { + newItem = questItemsList[j]; + break; + } + } while (j != i); + + // If the item to switch to is the same as the current item and we don't have the item anymore, null the slot + if ((newItem == item) && !checkItemGet(item, 1)) + { + newItem = 0xFF; + } + dComIfGs_setItem(21, newItem); + + break; + } + } + return newItem; +} + +void offWarashibeItem(u8 item) +{ + g_dComIfG_gameInfo.info.getSavedata().getPlayer().getGetItem().offFirstBit(item); + setNextWarashibeItem(); +} \ No newline at end of file diff --git a/src/dusk/randomizer/game/tools.h b/src/dusk/randomizer/game/tools.h new file mode 100644 index 0000000000..4b03fae130 --- /dev/null +++ b/src/dusk/randomizer/game/tools.h @@ -0,0 +1,8 @@ +#pragma once + +#include "dolphin/types.h" + +bool playerIsInRoomStage(s32 room, const char* stage); +void checkTransformFromWolf(); +u8 setNextWarashibeItem(); +void offWarashibeItem(u8 item); diff --git a/src/dusk/randomizer/game/verify_item_functions.cpp b/src/dusk/randomizer/game/verify_item_functions.cpp new file mode 100644 index 0000000000..39c187166c --- /dev/null +++ b/src/dusk/randomizer/game/verify_item_functions.cpp @@ -0,0 +1,331 @@ +#include "verify_item_functions.h" + +#include "d/d_com_inf_game.h" +#include "d/d_item.h" +#include "d/d_item_data.h" + +bool haveItem(u32 item) +{ + return checkItemGet((u8)item, 1); +} + +u32 getProgressiveSword() +{ + static constexpr u8 progressiveItemsList[] = {dItemNo_Randomizer_WOOD_STICK_e, dItemNo_Randomizer_SWORD_e, dItemNo_Randomizer_MASTER_SWORD_e}; + + u32 listLength = sizeof(progressiveItemsList) / sizeof(progressiveItemsList[0]); + for (int i = 0; i < listLength; i++) + { + const u32 item = progressiveItemsList[i]; + if (!haveItem(item)) + { + return item; + } + } + + // All previous obtained, so return last upgrade + return dItemNo_Randomizer_LIGHT_SWORD_e; +}; + +u32 getProgressiveBow() +{ + static const u8 progressiveItemsList[] = {dItemNo_Randomizer_BOW_e, dItemNo_Randomizer_ARROW_LV2_e}; + + u32 listLength = sizeof(progressiveItemsList) / sizeof(progressiveItemsList[0]); + for (int i = 0; i < listLength; i++) + { + const u32 item = progressiveItemsList[i]; + if (!haveItem(item)) + { + return item; + } + } + + // All previous obtained, so return last upgrade + return dItemNo_Randomizer_ARROW_LV3_e; +}; + +u32 getProgressiveSkill() +{ + static const u8 progressiveItemsList[] = { + dItemNo_Randomizer_ENDING_BLOW_e, + dItemNo_Randomizer_SHIELD_ATTACK_e, + dItemNo_Randomizer_BACK_SLICE_e, + dItemNo_Randomizer_HELM_SPLITTER_e, + dItemNo_Randomizer_MORTAL_DRAW_e, + dItemNo_Randomizer_JUMP_STRIKE_e + }; + + u32 listLength = sizeof(progressiveItemsList) / sizeof(progressiveItemsList[0]); + for (int i = 0; i < listLength; i++) + { + const u32 item = progressiveItemsList[i]; + if (!haveItem(item)) + { + return item; + } + } + + // All previous obtained, so return last upgrade + return dItemNo_Randomizer_GREAT_SPIN_e; +}; + +u32 getProgressiveSkybook() +{ + if (!haveItem(dItemNo_Randomizer_ANCIENT_DOCUMENT2_e)) + { + if (haveItem(dItemNo_Randomizer_ANCIENT_DOCUMENT_e)) + { + if (dComIfGs_getAncientDocumentNum() != 5) + { + return dItemNo_Randomizer_AIR_LETTER_e; + } + } + else + { + return dItemNo_Randomizer_ANCIENT_DOCUMENT_e; + } + } + + // All previous obtained, so return last upgrade + return dItemNo_Randomizer_ANCIENT_DOCUMENT2_e; +}; + +u32 getProgressiveKeyShard() +{ + static const u8 progressiveItemsList[] = {dItemNo_Randomizer_L2_KEY_PIECES1_e, dItemNo_Randomizer_L2_KEY_PIECES2_e}; + + u32 listLength = sizeof(progressiveItemsList) / sizeof(progressiveItemsList[0]); + for (int i = 0; i < listLength; i++) + { + const u32 item = progressiveItemsList[i]; + if (!haveItem(item)) + { + return item; + } + } + + // All previous obtained, so return last upgrade + return dItemNo_Randomizer_LV2_BOSS_KEY_e; +}; + +u32 getProgressiveMirrorShard() +{ + static const u8 progressiveItemsList[] = { + dItemNo_Randomizer_MIRROR_PIECE_1_e, + dItemNo_Randomizer_MIRROR_PIECE_2_e, + dItemNo_Randomizer_MIRROR_PIECE_3_e + }; + + u32 listLength = sizeof(progressiveItemsList) / sizeof(progressiveItemsList[0]); + for (int i = 0; i < listLength; i++) + { + const u32 item = progressiveItemsList[i]; + if (!haveItem(item)) + { + return item; + } + } + + // All previous obtained, so return last upgrade + return dItemNo_Randomizer_MIRROR_PIECE_4_e; +}; + +u32 getProgressiveFusedShadow() +{ + static const u8 progressiveItemsList[] = {dItemNo_Randomizer_FUSED_SHADOW_1_e, dItemNo_Randomizer_FUSED_SHADOW_2_e}; + + u32 listLength = sizeof(progressiveItemsList) / sizeof(progressiveItemsList[0]); + for (int i = 0; i < listLength; i++) + { + const u32 item = progressiveItemsList[i]; + if (!haveItem(item)) + { + return item; + } + } + + // All previous obtained, so return last upgrade + return dItemNo_Randomizer_FUSED_SHADOW_3_e; +}; + +u8 getWarashibeItemCount() +{ + static constexpr u8 itemsList[] = { + dItemNo_Randomizer_LETTER_e, + dItemNo_Randomizer_BILL_e, + dItemNo_Randomizer_WOOD_STATUE_e, + dItemNo_Randomizer_IRIAS_PENDANT_e, + dItemNo_Randomizer_HORSE_FLUTE_e + }; + u8 count = 0; + + u32 listLength = sizeof(itemsList) / sizeof(itemsList[0]); + for (int i = 0; i < listLength; i++) + { + const u32 item = itemsList[i]; + if (haveItem(item)) + { + count++; + } + } + return count; +}; + +u32 verifyProgressiveItem(u32 item) +{ + switch (item) + { + case dItemNo_Randomizer_WOOD_STICK_e: + case dItemNo_Randomizer_SWORD_e: + case dItemNo_Randomizer_MASTER_SWORD_e: + case dItemNo_Randomizer_LIGHT_SWORD_e: + { + item = getProgressiveSword(); + break; + } + case dItemNo_Randomizer_BOW_e: + case dItemNo_Randomizer_ARROW_LV2_e: + case dItemNo_Randomizer_ARROW_LV3_e: + { + item = getProgressiveBow(); + break; + } + case dItemNo_WALLET_LV2_e: + case dItemNo_WALLET_LV3_e: + { + if (haveItem(dItemNo_WALLET_LV2_e)) + { + item = dItemNo_WALLET_LV3_e; + } + else + { + item = dItemNo_WALLET_LV2_e; + } + break; + } + case dItemNo_Randomizer_ENDING_BLOW_e: + case dItemNo_Randomizer_SHIELD_ATTACK_e: + case dItemNo_Randomizer_BACK_SLICE_e: + case dItemNo_Randomizer_HELM_SPLITTER_e: + case dItemNo_Randomizer_MORTAL_DRAW_e: + case dItemNo_Randomizer_JUMP_STRIKE_e: + case dItemNo_Randomizer_GREAT_SPIN_e: + { + item = getProgressiveSkill(); + break; + } + case dItemNo_Randomizer_HOOKSHOT_e: + case dItemNo_Randomizer_W_HOOKSHOT_e: + { + // If we have either clawshot, we want to return the double no matter what. + // We check for both in this case because the game unsets the clawshot flag once the double has been obtained. + if (haveItem(dItemNo_Randomizer_HOOKSHOT_e) || haveItem(dItemNo_Randomizer_W_HOOKSHOT_e)) + { + item = dItemNo_Randomizer_W_HOOKSHOT_e; + } + else + { + item = dItemNo_Randomizer_HOOKSHOT_e; + } + break; + } + case dItemNo_Randomizer_ANCIENT_DOCUMENT_e: + case dItemNo_Randomizer_AIR_LETTER_e: + case dItemNo_Randomizer_ANCIENT_DOCUMENT2_e: + { + item = getProgressiveSkybook(); + break; + } + case dItemNo_Randomizer_L2_KEY_PIECES1_e: + case dItemNo_Randomizer_L2_KEY_PIECES2_e: + case dItemNo_Randomizer_LV2_BOSS_KEY_e: + { + item = getProgressiveKeyShard(); + break; + } + case dItemNo_Randomizer_COPY_ROD_e: + case dItemNo_Randomizer_COPY_ROD_2_e: + { + if (haveItem(dItemNo_Randomizer_COPY_ROD_e)) + { + item = dItemNo_Randomizer_COPY_ROD_2_e; + } + else + { + item = dItemNo_Randomizer_COPY_ROD_e; + } + break; + } + case dItemNo_Randomizer_FISHING_ROD_1_e: + case dItemNo_Randomizer_ZORAS_JEWEL_e: + { + if (haveItem(dItemNo_Randomizer_FISHING_ROD_1_e)) + { + item = dItemNo_Randomizer_ZORAS_JEWEL_e; + } + else + { + item = dItemNo_Randomizer_FISHING_ROD_1_e; + } + break; + } + case dItemNo_Randomizer_MIRROR_PIECE_1_e: + case dItemNo_Randomizer_MIRROR_PIECE_2_e: + case dItemNo_Randomizer_MIRROR_PIECE_3_e: + case dItemNo_Randomizer_MIRROR_PIECE_4_e: + { + item = getProgressiveMirrorShard(); + break; + } + case dItemNo_Randomizer_FUSED_SHADOW_1_e: + case dItemNo_Randomizer_FUSED_SHADOW_2_e: + case dItemNo_Randomizer_FUSED_SHADOW_3_e: + { + item = getProgressiveFusedShadow(); + break; + } + case dItemNo_Randomizer_ARROW_10_e: + case dItemNo_Randomizer_ARROW_20_e: + case dItemNo_Randomizer_ARROW_30_e: + { + if (!haveItem(dItemNo_Randomizer_BOW_e)) + { + item = dItemNo_Randomizer_BLUE_RUPEE_e; + } + break; + } + case dItemNo_Randomizer_BOMB_5_e: + case dItemNo_Randomizer_BOMB_10_e: + case dItemNo_Randomizer_BOMB_20_e: + case dItemNo_Randomizer_BOMB_30_e: + case dItemNo_Randomizer_WATER_BOMB_5_e: + case dItemNo_Randomizer_WATER_BOMB_10_e: + case dItemNo_Randomizer_WATER_BOMB_20_e: + case dItemNo_Randomizer_WATER_BOMB_30_e: + case dItemNo_Randomizer_BOMB_INSECT_5_e: + case dItemNo_Randomizer_BOMB_INSECT_10_e: + case dItemNo_Randomizer_BOMB_INSECT_20_e: + case dItemNo_Randomizer_BOMB_INSECT_30_e: + { + if (!haveItem(dItemNo_Randomizer_BOMB_IN_BAG_e)) + { + item = dItemNo_Randomizer_BLUE_RUPEE_e; + } + break; + } + case dItemNo_Randomizer_PACHINKO_SHOT_e: + { + if (!haveItem(dItemNo_Randomizer_PACHINKO_e)) + { + item = dItemNo_Randomizer_BLUE_RUPEE_e; + } + break; + } + default: + { + break; + } + } + return item; +} \ No newline at end of file diff --git a/src/dusk/randomizer/game/verify_item_functions.h b/src/dusk/randomizer/game/verify_item_functions.h new file mode 100644 index 0000000000..69be545a50 --- /dev/null +++ b/src/dusk/randomizer/game/verify_item_functions.h @@ -0,0 +1,15 @@ +#pragma once + +#include "dolphin/types.h" + +bool haveItem(u32 item); +u32 getProgressiveSword(); +u32 getProgressiveBow(); +u32 getProgressiveSkill(); +u32 getProgressiveSkybook(); +u32 getProgressiveKeyShard(); +u32 getProgressiveMirrorShard(); +u32 getProgressiveFusedShadow(); +u8 getWarashibeItemCount(); +u32 verifyProgressiveItem(); +