From 0267d6ad3fde74f64e9f3161be616f0a823442cd Mon Sep 17 00:00:00 2001 From: lunarsoap5 <40438826+lunarsoap5@users.noreply.github.com> Date: Thu, 1 Aug 2024 20:18:29 -0500 Subject: [PATCH] Randomizer v1.2 (#34) * push my ER stuff * Inital commit of reading custom text from seed data. * Patched Faron and Lanayru CS crashes. Changed skipper patch from automatic to seed-based. * Multiple Changes - Updated version to 1.2 - Updated skipper code to be more optimized - Added ER code just as a framework. * Added quick game over feature and modified item wheel menu to close on item wheel close * Multiple changes - Added fourth mirror shard item - Added function definitions for shop functions - Added function definitions for custom signs * Multiple Changes - Created a framework to give items to the player when they are not doing anything. - Applied a patch to the master sword actor that adds two checks to the game. - Added code that gives the player a check when they have defeated Stallord - Updated various code to reflect fleshed out libtp definitions * Remove skipper code since it is no longer needed here. * Added another patch for MS Pedestal checks to fix giving MS. - modified it so save warping in N Faron spawns you in central area. * Created support for starting time of day and adjusted message headers to support simplified format * Update ER to use state as an additonal condition. * Start updating angles for signs. * Clean up and update libtp references to match wii support * Various adjustments * Small optimization in handle_dComIfGp_setNextStage * Make sure randomizer seed is loaded in certain functions This is to prevent game crashes if a seed is not loaded. * Multiple changes to event item system - Changed the custom event item process to be a queue based system instead of a true/false. The old system assumed that the next event is always a get-item event, which is not always true. - removed the calls to verifyProgressiveItem before adding an item to the event queue because when giving an item, the event system calls createItemForPresentDemo, which also calls verifyProgressiveItem. * Update message flow for broken signs and adjust angle on GBoH sign. Adjusted spawn for FW sign as well * Update KV, KGY, DMT, Ordon, SG * Update WoCT and SoCT * Update LH and LS * Update HV and ZD * Update UZR and SP * Update GD, BC, AG, FT * Update LBT and SPR * Update ToT, CitS, LLC, CoO * Update Hyrule Field signs * Add back include * Update all of Lake Hylia to use the proper node. Removed unnecessary check for swimming from quick transform. * Add function to allow the red potion item to be bought. * Keep lantern meter color vanilla when color set to default * Minor changes - Set Ordon Ranch to use post Faron Twilight state when not doing goats or during night stealth - fixed bug with shop flags - Set red potion model to only change in kak malo mart - Updated 60 poe soul reward asm patch * Remove unneeded info for donation text * Update hint signs to use mStayNo to check for the current room. * Move positions; add ToT midpoint sign * Added patch for layer specific actors that rely on environmental checks to spawn. * Adjust position of PoT and HC signs * Add CT hint sign; fix Ordon sign issue * Modify custom room actors to use event manager room to validate the room that is being loaded instead of the room we are in. * Msg work gci * Add patch for giving souls to jovani pre-mdh * Remove unused code since we handle required dungeons on the generator side now. * Added a third . to the ellipses on the foolish item message * Add translations for first mirror shard text * Add check specifically for Malo mart before spawning the sold out sign. * Adjust wooden shield shop item flag * Fix setting 20 poe souls flag when killing poes The flag is now set when 20 poe souls have actually been collected, via the _00_handle_poeItem function. * Fix being able to lose Poe items This causes defeated Poes (excluding Arbiter Poes) to immediately despawn, and the item they would give is added to the queue to give to the player when they are free. Also adjusted _00_handle_poeItem to not increment the Poe count if it is already at 60 or greater. Also increased the amount of bytes used for queued items to 8. * Update wooden shield model for shops and fix Kak Malo Mart shop state * Revert "Fix setting 20 poe souls flag when killing poes" This reverts commit 6bd200e99a870b05c22ed0d23fbbce730607b61d. * Reset giveItemToPlayer upon starting/loading a file This is necessary because the player potentially could have died after initializing getting an item (which would set giveItemToPlayer to ITEM_IN_QUEUE), and then chosen to return to the title screen. * Update comment to include saving * Minor patch so that queued items show the correct model/text * Update allowed procs for item queue. Fixed wooden shield flag check * Update item wheel menu and fix quick transform affecting item usage * Accounted to Ordon Shield when buying Ordon Shield check * Add rel patch to fix MA/ZA MS check crash * Update shop models for City * Adjust killing poes to skip the backflip and trigger the item get immediately * Clear reserved bytes upon reaching title screen This is because the reserved bytes that the queue uses to store the items to give are not cleared upon starting a new file, which means that the player could soft reset during the process of being given item(s), and then start a new file to be given those items on that new file. Also moved resetting giveItemToPlayer to QUEUE_EMPTY to resetQueueOnFileSelectScreen as well, since it makes more sense for it to be reset there alongside the reserved bytes being cleared. * Fix issue with shield house/existing conversations messing with goats * Fix flag check for putting midna on back if Eldin twilight is last twilight --------- Co-authored-by: Zephiles Co-authored-by: Isaac --- GameCube/Makefile | 2 +- GameCube/assets/eu.lst | 27 +- GameCube/assets/jp.lst | 27 +- GameCube/assets/us.lst | 36 +- GameCube/externals/libtp_rel | 2 +- GameCube/include/asm.h | 22 +- GameCube/include/events.h | 9 +- GameCube/include/game_patch/game_patch.h | 9 +- GameCube/include/main.h | 131 ++- GameCube/include/rando/customItems.h | 1 + GameCube/include/rando/data.h | 86 +- GameCube/include/rando/randomizer.h | 2 + GameCube/include/rando/seed.h | 13 +- .../include/user_patch/05_newFileFunctions.h | 1 + GameCube/include/user_patch/user_patch.h | 2 +- GameCube/source/asm/adjustPoeItem.s | 19 +- GameCube/source/asm/check60PoeReward.s | 12 +- GameCube/source/asm/giveMasterSwordItems.s | 19 + GameCube/source/asm/handler.cpp | 35 +- GameCube/source/events.cpp | 812 +++++++++++++++--- GameCube/source/game_patch/00_poe.cpp | 12 +- GameCube/source/game_patch/01_getLayerNo.cpp | 179 ++-- .../source/game_patch/02_modifyItemData.cpp | 84 +- .../game_patch/04_verifyItemFunctions.cpp | 4 +- .../source/game_patch/05_itemMsgFunctions.cpp | 118 ++- .../game_patch/07_checkPlayerStageReturn.cpp | 7 +- GameCube/source/item_wheel_menu.cpp | 12 +- GameCube/source/main.cpp | 586 +++++++++++-- GameCube/source/rando/randomizer.cpp | 38 +- GameCube/source/rando/seed.cpp | 70 +- .../source/custom_messages/customMessages.cpp | 51 -- .../custom_messages/englishMessages.cpp | 85 +- .../source/custom_messages/frenchMessages.cpp | 90 +- .../source/custom_messages/germanMessages.cpp | 92 +- .../custom_messages/italianMessages.cpp | 158 ++-- .../custom_messages/japaneseMessages.cpp | 92 +- .../custom_messages/spanishMessages.cpp | 24 +- .../source/game_patch/02_modifyItemData.cpp | 217 ++--- .../source/game_patch/06_asmOverrides.cpp | 10 +- GameCube/subrel/boot/source/main.cpp | 24 +- .../seed/source/rando/linkHouseSign.cpp | 430 ---------- .../subrel/seed/source/rando/randomizer.cpp | 2 + GameCube/subrel/seed/source/rando/seed.cpp | 57 +- .../source/user_patch/05_newFileFunctions.cpp | 23 + .../seed/source/user_patch/user_patch.cpp | 9 +- 45 files changed, 2451 insertions(+), 1290 deletions(-) create mode 100644 GameCube/source/asm/giveMasterSwordItems.s delete mode 100644 GameCube/subrel/seed/source/rando/linkHouseSign.cpp diff --git a/GameCube/Makefile b/GameCube/Makefile index b1421fe2..747b54cc 100644 --- a/GameCube/Makefile +++ b/GameCube/Makefile @@ -14,7 +14,7 @@ export BUILDID:='"$(shell date +'%Y%m%d%H%M')"' # Version export _VERSION_MAJOR:=1 -export _VERSION_MINOR:=1 +export _VERSION_MINOR:=2 export _VERSION_PATCH:=0 export _VERSION:='"$(_VERSION_MAJOR).$(_VERSION_MINOR).$(_VERSION_PATCH)"' # Variant: i.e. Public, NoLogic, Race, etc. diff --git a/GameCube/assets/eu.lst b/GameCube/assets/eu.lst index c4f6c0f4..b26893c0 100644 --- a/GameCube/assets/eu.lst +++ b/GameCube/assets/eu.lst @@ -75,6 +75,9 @@ 800428A8:defaultSkipStb 80042B04:skipper +// d_event_manager.o +80047888:getEventIdx3 + // DynamicLink.o 80263460:DynamicModuleControl_ct 80263A5C:do_link @@ -97,6 +100,10 @@ 80019B50:CreateAppend 80019e40:fopAcM_create 8001bbbc:fopAcM_getTalkEventPartner +8001b68c:fopAcM_orderChangeEventId + +// f_op_msg_mng.o +8001ff2c:fopMsgM_messageSet // f_pc_node_req 803A5718:l_fpcNdRq_Queue @@ -124,13 +131,13 @@ 8039325C:getSeType 800c7a00:procCoMetamorphoseInit 80115E2C:checkEventRun -803DEDF4:linkStatus 800e2728:checkBootsMoveAnime 800d9148:procDamageInit 800d7e4c:checkDamageAction 801183ac:setGetItemFace 801362f8:procWolfDamageInit 8011ae34:procCoGetItem +8011a9a4:procCoGetItemInit 800d01b0:dComIfGp_setItemLifeCount 800be5f0:checkRestartRoom 8011fbf8:checkWarpStart @@ -142,6 +149,7 @@ 800c5120:procFrontRollCrashInit 8012dacc:procWolfDashReverseInit 8013cad4:procWolfAttackReverseInit +8012ddb4:procWolfAtnActorMoveInit // data 8039038C:climbVars @@ -152,7 +160,6 @@ //d_meter2_info.o 80432148:g_meter2_info -80432164:wZButtonPtr 8021e388:resetMiniGameItem //d_meter2_draw.o @@ -314,6 +321,7 @@ // Z2SeqMgr 802B5CB0:startBattleBgm 802ad30c:seStartLevel +802b4cac:checkBgmIDPlaying // Z2SoundMgr.o 802AACE8:startSound @@ -357,10 +365,15 @@ //d_a_shop_item_static.o 8037a178:shopItemData +//d_shop_system.o +8019a080:seq_decide_yes +8019a5ac:setSoldOutFlag + //d_menu_window.o 801fa854:collect_save_open_init //d_msg_flow.o +8024b7dc:query001 8024bf88:query022 8024bfbc:query023 8024c018:query025 @@ -373,6 +386,8 @@ 8024e11c:event041 8024d138:event017 8024c944:query049 +8024a97c:doFlow +8024b0f4:setNormalMsg //d_a_npc.o @@ -456,4 +471,10 @@ 8034E630:VISetNextFrameBuffer // f_op_actor_iter.o -800198A0:fopAcIt_Judge \ No newline at end of file +800198A0:fopAcIt_Judge + +// d_gameover.o +8019b664:dispWait_init + +// d_file_select.o +801845d8:dFile_select_c___create \ No newline at end of file diff --git a/GameCube/assets/jp.lst b/GameCube/assets/jp.lst index 6f9f906c..d1377b51 100644 --- a/GameCube/assets/jp.lst +++ b/GameCube/assets/jp.lst @@ -75,6 +75,9 @@ 80042778:defaultSkipStb 800429D4:skipper +// d_event_manager.o +80047758:getEventIdx3 + // DynamicLink.o 80264A90:DynamicModuleControl_ct 8026508C:do_link @@ -97,6 +100,10 @@ 80019AA8:CreateAppend 80019d98:fopAcM_create 8001bb14:fopAcM_getTalkEventPartner +8001b5e4:fopAcM_orderChangeEventId + +// f_op_msg_mng.o +8001fe84:fopMsgM_messageSet // f_pc_node_req 8039DB98:l_fpcNdRq_Queue @@ -125,12 +132,12 @@ 800e2554:checkBootsMoveAnime 801181d8:setGetItemFace 8038badc:getSeType -803D6F94:linkStatus 80141188:mDoAud_seStartLevel 80136138:procWolfDamageInit 800d8f74:procDamageInit 801412b0:dComIfGs_isItemFirstBit 8011ac60:procCoGetItem +8011a7d0:procCoGetItemInit 800cffdc:dComIfGp_setItemLifeCount 800be41c:checkRestartRoom 8011fa24:checkWarpStart @@ -142,6 +149,7 @@ 800c4f4c:procFrontRollCrashInit 8012d90c:procWolfDashReverseInit 8013c914:procWolfAttackReverseInit +8012dbf4:procWolfAtnActorMoveInit // data 80388C0C:climbVars @@ -303,6 +311,7 @@ // Z2SeqMgr.o 802B72F0:startBattleBgm +802b62ec:checkBgmIDPlaying // Z2SoundMgr.o 802AC328:startSound @@ -360,6 +369,7 @@ 802ab8d0:parseCharacter_1Byte // d_msg_flow.o +8024caa0:query001 8024d24c:query022 8024d280:query023 8024d2dc:query025 @@ -372,6 +382,8 @@ 8024f3e0:event041 8024f130:event035 8024dc08:query049 +8024bc40:doFlow +8024c3b8:setNormalMsg // d_a_npc.o 8014ca78:daNpcT_onEvtBit @@ -387,8 +399,11 @@ // d_a_shop_item_static.o 8037b790:shopItemData +// d_shop_system.o +80199de8:seq_decide_yes +8019a314:setSoldOutFlag + // d_meter2_info.o -8042A2E4:wZButtonPtr 8042a2c8:g_meter2_info 8021e81c:resetMiniGameItem @@ -451,4 +466,10 @@ 8034FC60:VISetNextFrameBuffer // f_op_actor_iter.o -800197F8:fopAcIt_Judge \ No newline at end of file +800197F8:fopAcIt_Judge + +// d_gameover.o +8019b3cc:dispWait_init + +// d_file_select.o +80184418:dFile_select_c___create \ No newline at end of file diff --git a/GameCube/assets/us.lst b/GameCube/assets/us.lst index 73c7220f..3ce4c0b2 100644 --- a/GameCube/assets/us.lst +++ b/GameCube/assets/us.lst @@ -75,6 +75,9 @@ 80042778:defaultSkipStb 800429D4:skipper +// d_event_manager.o +80047758:getEventIdx3 + // DynamicLink.o 80262660:DynamicModuleControl_ct 80262C5C:do_link @@ -97,6 +100,10 @@ 80019AA8:CreateAppend 80019D98:fopAcM_create 8001bb14:fopAcM_getTalkEventPartner +8001b5e4:fopAcM_orderChangeEventId + +// f_op_msg_mng.o +8001fe84:fopMsgM_messageSet // f_pc_node_req 803A3A38:l_fpcNdRq_Queue @@ -130,7 +137,6 @@ 800d29d4:checkDownAttackState 800c77f4:procCoMetamorphoseInit 80115c20:checkEventRun -803DCE54:linkStatus 800e251c:checkBootsMoveAnime 80119d98:procCoTalkInit 800d8f3c:procDamageInit @@ -139,6 +145,7 @@ 801181a0:setGetItemFace 800d96dc:procCoLargeDamageInit 8011ac28:procCoGetItem +8011a798:procCoGetItemInit 800cffa4:dComIfGp_setItemLifeCount 800be3e4:checkRestartRoom 8011f9ec:checkWarpStart @@ -150,6 +157,7 @@ 800c4f14:procFrontRollCrashInit 8012d8c0:procWolfDashReverseInit 8013c8c8:procWolfAttackReverseInit +8012dba8:procWolfAtnActorMoveInit // data 8038EB8C:climbVars @@ -317,6 +325,7 @@ // Z2SeqMgr.o 802B4EB0:startBattleBgm +802b3eac:checkBgmIDPlaying // Z2SoundMgr.o 802A9EE8:startSound @@ -338,7 +347,6 @@ //d_meter2_info.o 80430188:g_meter2_info -804301A4:wZButtonPtr 8021e0c4:resetMiniGameItem //d_meter2_draw.o @@ -358,11 +366,13 @@ // d_msg_object.o 802369D8:isSend +802383d0:getMessageID // processor.o 802A7C54:getResource_groupID //d_msg_flow.o +8024b138:query001 8024b250:query004 8024b8e4:query022 8024b918:query023 @@ -375,6 +385,9 @@ 8024da78:event041 8024bc80:query037 8024c2a0:query049 +8024a2d8:doFlow +8024a528:getEventId +8024aa50:setNormalMsg //d_menu_window.o 801fa590:collect_save_open_init @@ -383,6 +396,7 @@ 8014ca2c:daNpcT_onEvtBit 8014caac:daNpcT_chkEvtBit 80155634:daNpcF_chkEvtBit +8014a224:evtChange //resource.o 802a9490:parseCharacter_1Byte @@ -458,4 +472,20 @@ 8034D7C4:VISetNextFrameBuffer // f_op_actor_iter.o -800197F8:fopAcIt_Judge \ No newline at end of file +800197F8:fopAcIt_Judge + +// d_gameover.o +8019b40c:dispWait_init + +// d_shop_system.o +80199e28:seq_decide_yes +801975dc:offFlag +8019a4f4:setSoldOutItemHide +8019a344:setSeq +8019a354:setSoldOutFlag + +// f_pc_executor.o +8002139c:fpcEx_IsExist + +// d_file_select.o +801843cc:dFile_select_c___create \ No newline at end of file diff --git a/GameCube/externals/libtp_rel b/GameCube/externals/libtp_rel index 36aa1bbc..d1cddf13 160000 --- a/GameCube/externals/libtp_rel +++ b/GameCube/externals/libtp_rel @@ -1 +1 @@ -Subproject commit 36aa1bbc626bf4f11a08fc5f8d4cdee18494059d +Subproject commit d1cddf131adceea98b142f7ae3d084e633e87608 diff --git a/GameCube/include/asm.h b/GameCube/include/asm.h index e5e04c15..d3c3d48b 100644 --- a/GameCube/include/asm.h +++ b/GameCube/include/asm.h @@ -19,20 +19,20 @@ // Original: li 0xE0 // Normally loads the poesoul item id into r4 -#define e_hp_ExecDead_liOffset 0x247C +#define e_hp_ExecDead_beqOffset 0x2440 #define e_po_ExecDead_liOffset 0x3C9C // Original: -// stb r0, 0x10c( r4 ) = > numPoeSouls -// Normally increments poe count -#define e_hp_ExecDead_incOffset 0x2354 -#define e_po_ExecDead_incOffset 0x36A8 +// lis r3,dComIfG_gameInfo@h +// Normally increments poe count if not at 255 +#define e_hp_ExecDead_incOffset 0x233C +#define e_po_ExecDead_incOffset 0x3690 // d_a_obj_Lv5Key__Wait_offset: // 0xBC is offset to the text section relative to the start of the decompressed // REL. 0x4E4 is offset to Wait function relative to the start of the text // section (as seen on line 14 of d_a_obj_Lv5Key.map). -#define d_a_obj_Lv5Key__Wait_offset 0xBC + 0x4E4 +#define d_a_obj_Lv5Key__Wait_offset (0xBC + 0x4E4) namespace mod::assembly { @@ -46,9 +46,8 @@ namespace mod::assembly void handleDoLinkHook(libtp::tp::dynamic_link::DynamicModuleControl* dmc); // d_e_hp.rel - void asmAdjustPoeItemStart(void); - void asmAdjustPoeItemEnd(void); - int32_t handleAdjustPoeItem(void*); + void asmAdjustPoeItem(void); + void handleAdjustPoeItem(void*); // d_e_po.rel void asmAdjustAGPoeItemStart(void); @@ -97,6 +96,11 @@ namespace mod::assembly void asmReplaceGWolfWithItem(void); bool handleReplaceGWolfWithItem(const int16_t* l_delFlag, void* daNpcGWolf); + // d_a_obj_master_sword.o + void asmGiveMasterSwordItemsStart(); + void asmGiveMasterSwordItemsEnd(); + void handleGiveMasterSwordItems(); + // vi.o void asmCallCodehandler(); diff --git a/GameCube/include/events.h b/GameCube/include/events.h index 22eeee58..6a17f478 100644 --- a/GameCube/include/events.h +++ b/GameCube/include/events.h @@ -39,6 +39,9 @@ namespace mod::events extern libtp::tp::dzx::ACTR ForestGWolfActr; extern libtp::tp::dzx::ACTR ImpPoeActr; extern libtp::tp::dzx::ACTR CampBoarActr; + extern libtp::tp::dzx::ACTR KakShopSlot2Actr; + extern libtp::tp::dzx::ACTR SignActr; + extern libtp::tp::dzx::ACTR MstrSrdActr; extern uint8_t timeChange; @@ -142,14 +145,16 @@ namespace mod::events int32_t proc_query023(void* unk1, void* unk2, int32_t unk3); + int32_t proc_query025(void* unk1, void* unk2, int32_t unk3); + int32_t proc_query042(void* unk1, void* unk2, int32_t unk3); bool proc_isDungeonItem(libtp::tp::d_save::dSv_memBit_c* memBitPtr, const int32_t memBit); void proc_onDungeonItem(libtp::tp::d_save::dSv_memBit_c* memBitPtr, const int32_t memBit); - void loadCustomActors(); - void loadCustomRoomActors(); + void loadCustomActors(void* mStatus_roomControl); + void loadCustomRoomActors(rando::Randomizer* randomizer); void loadCustomRoomSCOBs(); void handleQuickTransform(); void handleTimeOfDayChange(); diff --git a/GameCube/include/game_patch/game_patch.h b/GameCube/include/game_patch/game_patch.h index ea88e218..545b63ae 100644 --- a/GameCube/include/game_patch/game_patch.h +++ b/GameCube/include/game_patch/game_patch.h @@ -118,6 +118,7 @@ namespace mod::game_patch void _02_firstFusedShadowItemFunc(); void _02_secondFusedShadowItemFunc(); void _02_thirdFusedShadowItemFunc(); + void _02_firstMirrorShardItemFunc(); void _02_secondMirrorShardItemFunc(); void _02_thirdMirrorShardItemFunc(); void _02_fourthMirrorShardItemFunc(); @@ -140,6 +141,7 @@ namespace mod::game_patch int32_t _02_firstFusedShadowItemGetCheck(); int32_t _02_secondFusedShadowItemGetCheck(); int32_t _02_thirdFusedShadowItemGetCheck(); + int32_t _02_firstMirrorShardItemGetCheck(); int32_t _02_secondMirrorShardItemGetCheck(); int32_t _02_thirdMirrorShardItemGetCheck(); int32_t _02_fourthMirrorShardItemGetCheck(); @@ -167,15 +169,12 @@ namespace mod::game_patch uint32_t _04_getProgressiveFusedShadow(); // 05 - Function definitions related to custom messages - void _05_setCustomItemMessage(libtp::tp::control::TControl* control, - const void* TProcessor, - uint16_t unk3, - uint16_t msgId, - rando::Randomizer* randomizer); + void _05_setCustomItemMessage(libtp::tp::control::TControl* control, const void* TProcessor, uint16_t unk3, uint16_t msgId); uint32_t _05_getCustomMsgColor(uint8_t colorId); const char* _05_getMsgById(uint32_t msgId); const char* _05_getMsgById(uint32_t msgId, uint16_t* msgSizeOut); + const char* _05_getSpecialMsgById(uint32_t msgId); const char** _05_replaceMessageString(const char** text); // 06 - Function definitions for assembly patches diff --git a/GameCube/include/main.h b/GameCube/include/main.h index 382fb3b3..8eba718b 100644 --- a/GameCube/include/main.h +++ b/GameCube/include/main.h @@ -21,12 +21,18 @@ #include "tp/d_stage.h" #include "tp/control.h" #include "Z2AudioLib/Z2SceneMgr.h" +#include "Z2AudioLib/Z2SeqMgr.h" #include "events.h" #include "tp/d_resource.h" #include "tp/JKRMemArchive.h" #include "tp/m_Do_dvd_thread.h" #include "tp/d_meter2_info.h" #include "tp/d_menu_fmap2D.h" +#include "tp/d_gameover.h" +#include "tp/d_shop_system.h" +#include "tp/f_op_actor.h" +#include "tp/d_msg_flow.h" +#include "tp/d_file_select.h" #ifdef TP_EU #include "tp/d_s_logo.h" @@ -52,6 +58,9 @@ #define SEED_ACTION_CHANGE_SEED 2 #define SEED_ACTION_FATAL 255 +// Number of bytes reserved for giving items to the player at arbitrary times via initGiveItemToPlayer +#define GIVE_PLAYER_ITEM_RESERVED_BYTES 8 + // Converting item ids to msg ids and vice versa #define ITEM_TO_ID(item) (item + 0x64) #define ID_TO_ITEM(msgId) (msgId - 0x64) @@ -63,6 +72,13 @@ namespace mod { + enum EventItemStatus : uint8_t + { + QUEUE_EMPTY = 0, + ITEM_IN_QUEUE = 1, + CLEAR_QUEUE = 2, + }; + // General public objects extern libtp::display::Console* console; extern rando::Randomizer* randomizer; @@ -70,13 +86,14 @@ namespace mod extern void* z2ScenePtr; extern uint32_t randState; - extern const char* m_DonationText; // Variables - extern uint8_t* m_MsgTableInfo; // Custom message string data + extern uint8_t* m_MsgTableInfo; // Custom message string data + extern uint8_t* m_HintMsgTableInfo; // Custom message string data extern libtp::tp::J2DPicture::J2DPicture* bgWindow; extern uint16_t lastButtonInput; - extern uint16_t m_TotalMsgEntries; // Number of currently loaded custom string + extern uint16_t m_TotalMsgEntries; // Number of currently loaded custom string + extern uint16_t m_TotalHintMsgEntries; // Number of currently loaded custom string extern bool roomReloadingState; extern bool consoleState; extern uint8_t gameState; @@ -88,6 +105,7 @@ namespace mod extern bool transformAnywhereEnabled; extern uint8_t damageMultiplier; extern bool bonksDoDamage; + extern EventItemStatus giveItemToPlayer; #ifdef TP_EU extern libtp::tp::d_s_logo::Languages currentLanguage; @@ -99,6 +117,7 @@ namespace mod bool checkButtonCombo(uint32_t combo, bool checkAnalog); float intToFloat(int32_t value); void handleInput(uint32_t inputs); + void initGiveItemToPlayer(libtp::tp::d_a_alink::daAlink* linkMapPtr); void handleFoolishItem(); void handleBonkDamage(); @@ -168,31 +187,29 @@ namespace mod int32_t unk3, void* unk4); - /* - void handle_dComIfGp_setNextStage( const char* stage, - int16_t point, - int8_t roomNo, - int8_t layer, - float lastSpeed, - uint32_t lastMode, - int32_t setPoint, - int8_t wipe, - int16_t lastAngle, - int32_t param_9, - int32_t wipSpeedT ); - - extern void ( *return_dComIfGp_setNextStage )( const char* stage, - int16_t point, - int8_t roomNo, - int8_t layer, - float lastSpeed, - uint32_t lastMode, - int32_t setPoint, - int8_t wipe, - int16_t lastAngle, - int32_t param_9, - int32_t wipSpeedT ); - */ + void handle_dComIfGp_setNextStage(const char* stage, + int16_t point, + int8_t roomNo, + int8_t layer, + float lastSpeed, + uint32_t lastMode, + int32_t setPoint, + int8_t wipe, + int16_t lastAngle, + int32_t param_9, + int32_t wipSpeedT); + + extern void (*return_dComIfGp_setNextStage)(const char* stage, + int16_t point, + int8_t roomNo, + int8_t layer, + float lastSpeed, + uint32_t lastMode, + int32_t setPoint, + int8_t wipe, + int16_t lastAngle, + int32_t param_9, + int32_t wipSpeedT); int32_t handle_tgscInfoInit(void* stageDt, void* i_data, int32_t entryNum, void* param_3); extern int32_t (*return_tgscInfoInit)(void* stageDt, void* i_data, int32_t entryNum, void* param_3); @@ -202,10 +219,12 @@ namespace mod // void handle_stageLoader( void* data, void* stageDt ); // extern void ( *return_stageLoader )( void* data, void* stageDt ); + int32_t handle_dStage_playerInit(void* stageDt, libtp::tp::d_stage::stage_dzr_header_entry* i_data, int32_t num, void* raw_data); + extern int32_t (*return_dStage_playerInit)(void* stageDt, libtp::tp::d_stage::stage_dzr_header_entry* i_data, int32_t num, @@ -214,6 +233,14 @@ namespace mod // State functions extern int32_t (*return_getLayerNo_common_common)(const char* stageName, int32_t roomId, int32_t layerOverride); + int32_t procCoGetItemInitCreateItem(const float pos[3], + int32_t item, + uint8_t unk3, + int32_t unk4, + int32_t unk5, + const float rot[3], + const float scale[3]); + // Item creation functions. These are ran when the game displays an item though various means. int32_t handle_createItemForBoss(const float pos[3], int32_t item, @@ -323,12 +350,18 @@ namespace mod uint32_t unk4); // Query/Event functions. Various uses + int32_t handle_query001(void* unk1, void* unk2, int32_t unk3); + extern int32_t (*return_query001)(void* unk1, void* unk2, int32_t unk3); + int32_t handle_query022(void* unk1, void* unk2, int32_t unk3); extern int32_t (*return_query022)(void* unk1, void* unk2, int32_t unk3); int32_t handle_query023(void* unk1, void* unk2, int32_t unk3); extern int32_t (*return_query023)(void* unk1, void* unk2, int32_t unk3); + int32_t handle_query025(void* unk1, void* unk2, int32_t unk3); + extern int32_t (*return_query025)(void* unk1, void* unk2, int32_t unk3); + uint8_t handle_checkEmptyBottle(libtp::tp::d_save::dSv_player_item_c* playerItem); extern uint8_t (*return_checkEmptyBottle)(libtp::tp::d_save::dSv_player_item_c* playerItem); @@ -347,6 +380,24 @@ namespace mod int32_t handle_event017(void* messageFlow, void* nodeEvent, void* actrPtr); extern int32_t (*return_event017)(void* messageFlow, void* nodeEvent, void* actrPtr); + int32_t handle_doFlow(libtp::tp::d_msg_flow::dMsgFlow* msgFlow, + libtp::tp::f_op_actor::fopAc_ac_c* actrPtr, + libtp::tp::f_op_actor::fopAc_ac_c** actrValue, + int32_t i_flow); + + extern int32_t (*return_doFlow)(libtp::tp::d_msg_flow::dMsgFlow* msgFlow, + libtp::tp::f_op_actor::fopAc_ac_c* actrPtr, + libtp::tp::f_op_actor::fopAc_ac_c** actrValue, + int32_t i_flow); + + int32_t handle_setNormalMsg(libtp::tp::d_msg_flow::dMsgFlow* msgFlow, + void* flowNode, + libtp::tp::f_op_actor::fopAc_ac_c* actrPtr); + + extern int32_t (*return_setNormalMsg)(libtp::tp::d_msg_flow::dMsgFlow* msgFlow, + void* flowNode, + libtp::tp::f_op_actor::fopAc_ac_c* actrPtr); + // Save flag functions bool handle_isDungeonItem(libtp::tp::d_save::dSv_memBit_c* memBitPtr, const int32_t memBit); extern bool (*return_isDungeonItem)(libtp::tp::d_save::dSv_memBit_c* memBitPtr, const int32_t memBit); @@ -407,6 +458,9 @@ namespace mod float handle_damageMagnification(libtp::tp::d_a_alink::daAlink* daALink, int32_t param_1, int32_t param_2); extern float (*return_damageMagnification)(libtp::tp::d_a_alink::daAlink* daALink, int32_t param_1, int32_t param_2); + int32_t handle_procCoGetItemInit(libtp::tp::d_a_alink::daAlink* linkActrPtr); + extern int32_t (*return_procCoGetItemInit)(libtp::tp::d_a_alink::daAlink* linkActrPtr); + // Audio functions void handle_loadSeWave(void* Z2SceneMgr, uint32_t waveID); extern void (*return_loadSeWave)(void* Z2SceneMgr, uint32_t waveID); @@ -430,12 +484,14 @@ namespace mod bool param_7); void handle_startSound(void* soungMgr, libtp::z2audiolib::z2scenemgr::JAISoundID soundId, void* soundHandle, void* pos); - extern void (*return_startSound)(void* soundMgr, libtp::z2audiolib::z2scenemgr::JAISoundID soundId, void* soundHandle, void* pos); + bool handle_checkBgmIDPlaying(libtp::z2audiolib::z2seqmgr::Z2SeqMgr* seqMgr, uint32_t sfx_id); + extern bool (*return_checkBgmIDPlaying)(libtp::z2audiolib::z2seqmgr::Z2SeqMgr* seqMgr, uint32_t sfx_id); + // Title Screen functions void* handle_dScnLogo_c_dt(void* dScnLogo_c, int16_t bFreeThis); extern void* (*return_dScnLogo_c_dt)(void* dScnLogo_c, int16_t bFreeThis); @@ -454,5 +510,22 @@ namespace mod // d_meter functions void handle_resetMiniGameItem(libtp::tp::d_meter2_info::G_Meter2_Info* gMeter2InfoPtr, bool minigameFlag); extern void (*return_resetMiniGameItem)(libtp::tp::d_meter2_info::G_Meter2_Info* gMeter2InfoPtr, bool minigameFlag); + + // Game Over functions + void handle_dispWait_init(libtp::tp::d_gameover::dGameOver* ptr); + extern void (*return_dispWait_init)(libtp::tp::d_gameover::dGameOver* ptr); + + // Shop Functions + int32_t handle_seq_decide_yes(libtp::tp::d_shop_system::dShopSystem* shopPtr, + libtp::tp::f_op_actor::fopAc_ac_c* actor, + void* msgFlow); + + extern int32_t (*return_seq_decide_yes)(libtp::tp::d_shop_system::dShopSystem* shopPtr, + libtp::tp::f_op_actor::fopAc_ac_c* actor, + void* msgFlow); + + // Title Screen functions + void resetQueueOnFileSelectScreen(libtp::tp::d_file_select::dFile_select_c* thisPtr); + extern void (*return_dFile_select_c___create)(libtp::tp::d_file_select::dFile_select_c* thisPtr); } // namespace mod #endif \ No newline at end of file diff --git a/GameCube/include/rando/customItems.h b/GameCube/include/rando/customItems.h index cd173dc8..31af7a00 100644 --- a/GameCube/include/rando/customItems.h +++ b/GameCube/include/rando/customItems.h @@ -21,6 +21,7 @@ namespace mod::rando::customItems Foolish_Item_3 = 0x15, // Custom Item added for the Randomizer. Foolish_Item_4 = 0x4D, // Custom Item added for the Randomizer. Foolish_Item_5 = 0x4E, // Custom Item added for the Randomizer. + Mirror_Piece_1 = 0x53, // Custom Item added for the Randomizer Foolish_Item_6 = 0x57, // Custom Item added for the Randomizer. Forest_Temple_Small_Key = 0x85, // Custom Item added for the Randomizer. Goron_Mines_Small_Key = 0x86, // Custom Item added for the Randomizer. diff --git a/GameCube/include/rando/data.h b/GameCube/include/rando/data.h index 313c01b5..64f6b655 100644 --- a/GameCube/include/rando/data.h +++ b/GameCube/include/rando/data.h @@ -56,17 +56,21 @@ namespace mod::rando /* 0x3C */ entryInfo bugRewardCheckInfo; /* 0x40 */ entryInfo skyCharacterCheckInfo; /* 0x44 */ entryInfo shopItemCheckInfo; - /* 0x48 */ entryInfo startingItemInfo; - /* 0x4C */ uint16_t bgmHeaderOffset; - /* 0x4E */ uint16_t clr0Offset; - /* 0x50 */ uint8_t transformAnywhere; - /* 0x51 */ uint8_t quickTransform; - /* 0x52 */ uint8_t castleRequirements; - /* 0x53 */ uint8_t palaceRequirements; - /* 0x54 */ uint8_t mapClearBits; - /* 0x55 */ uint8_t damageMagnification; - /* 0x56 */ uint8_t bonksDoDamage; - /* 0x57 */ uint8_t padding; + /* 0x48 */ entryInfo eventItemCheckInfo; + /* 0x4C */ entryInfo startingItemInfo; + /* 0x50 */ entryInfo EntranceTableInfo; + /* 0x54 */ uint16_t bgmHeaderOffset; + /* 0x56 */ uint16_t clr0Offset; + /* 0x58 */ uint16_t customTextHeaderSize; + /* 0x5A */ uint16_t customTextHeaderOffset; + /* 0x5C */ uint8_t transformAnywhere; + /* 0x5D */ uint8_t quickTransform; + /* 0x5E */ uint8_t castleRequirements; + /* 0x5F */ uint8_t palaceRequirements; + /* 0x60 */ uint8_t mapClearBits; + /* 0x61 */ uint8_t damageMagnification; + /* 0x62 */ uint8_t bonksDoDamage; + /* 0x63 */ uint8_t startingTimeOfDay; } __attribute__((__packed__)); // Minimum amount of data needed for keeping track of a seed @@ -211,21 +215,28 @@ namespace mod::rando uint8_t roomID; // The room that the Owl Statue is located in. } __attribute__((__packed__)); - struct CustomMessageEntryInfo + // These items are given either during cutscenes or at a specific time. + struct EventItem { - uint8_t language; - uint8_t padding[1]; + uint8_t itemID; // The item to be given. + uint8_t stageIDX; // The stage that the event is in. + uint8_t roomID; // The room that the event is in. + uint8_t flag; // The unique identifier used to disinguish between checks in the same room. + } __attribute__((__packed__)); + + struct CustomMessageHeaderInfo + { + uint16_t headerSize; uint16_t totalEntries; uint32_t msgTableSize; uint32_t msgIdTableOffset; } __attribute__((__packed__)); - struct CustomMessageHeaderInfo + struct CustomMessageData { - uint16_t headerSize; - uint8_t totalLanguages; - uint8_t padding[1]; - CustomMessageEntryInfo entry[]; // Size is totalLanguages + uint8_t stageIDX; + uint8_t roomIDX; + uint16_t msgID; } __attribute__((__packed__)); struct CLR0Header @@ -269,6 +280,31 @@ namespace mod::rando ZBtn }; + enum CastleEntryRequirements : uint8_t + { + HC_Open = 0, + HC_Fused_Shadows = 1, + HC_Mirror_Shards, + HC_All_Dungeons, + HC_Vanilla + }; + + enum PalaceEntryRequirements : uint8_t + { + PoT_Open = 0, + PoT_Fused_Shadows = 1, + PoT_Mirror_Shards, + PoT_Vanilla + }; + + enum StartingTimeOfDay : uint8_t + { + Morning = 0, + Noon = 1, + Evening = 2, + Night = 3 + }; + struct RawRGBTable { uint32_t lanternColor; @@ -307,6 +343,18 @@ namespace mod::rando uint8_t markerFlag; // Flag associated with the current golden wolf's marker on the map }; + struct ShuffledEntrance + { + uint8_t origStageIDX; + uint8_t origRoomIDX; + uint8_t origSpawn; + int8_t origState; + uint8_t newStageIDX; + uint8_t newRoomIDX; + uint8_t newSpawn; + int8_t newState; + } __attribute__((__packed__)); + extern int32_t lookupTable[DvdEntryNumIdSize]; } // namespace mod::rando diff --git a/GameCube/include/rando/randomizer.h b/GameCube/include/rando/randomizer.h index c625da6f..b5a7535a 100644 --- a/GameCube/include/rando/randomizer.h +++ b/GameCube/include/rando/randomizer.h @@ -34,12 +34,14 @@ namespace mod::rando int32_t getPoeItem(uint8_t flag); uint8_t getSkyCharacter(); uint8_t getBossItem(int32_t originalItem); + uint8_t getEventItem(uint8_t flag); void overrideARC(uint32_t fileAddr, FileDirectory fileDirectory, int32_t roomNo); void overrideObjectARC(libtp::tp::d_resource::dRes_info_c* resourcePtr, const char* fileName); void overrideEventARC(); uint8_t overrideBugReward(uint8_t bugID); void getHiddenSkillItem(void* daNpcGWolfPtr, int16_t flag, uint32_t markerFlag); void replaceWolfLockDomeColor(libtp::tp::d_a_alink::daAlink* linkActrPtr); + void addItemToEventQueue(uint32_t itemToAdd); // NOTE: This function returns dynamic memory BMDEntry* generateBmdEntries(mod::rando::DvdEntryNumId arcIndex, uint32_t numEntries); diff --git a/GameCube/include/rando/seed.h b/GameCube/include/rando/seed.h index f2c6801a..0769c3eb 100644 --- a/GameCube/include/rando/seed.h +++ b/GameCube/include/rando/seed.h @@ -37,8 +37,8 @@ namespace mod::rando BugReward* m_BugRewardChecks = nullptr; SkyCharacter* m_SkyBookChecks = nullptr; ObjectArchiveReplacement* m_ObjectArcReplacements = nullptr; - - const char* m_RequiredDungeons = nullptr; // Displayed when reading the sign in front of Link's house + ShuffledEntrance* m_ShuffledEntrances = nullptr; + EventItem* m_EventChecks = nullptr; BGMReplacement* m_BgmTable = nullptr; // Bgm replacement data BGMReplacement* m_FanfareTable = nullptr; // Fanfare replacement data @@ -54,7 +54,9 @@ namespace mod::rando uint16_t m_numHiddenSkillChecks = 0; uint16_t m_numBugRewardChecks = 0; uint16_t m_numSkyBookChecks = 0; + uint16_t m_numLoadedEventChecks = 0; uint16_t m_numLoadedObjectArcReplacements = 0; + uint16_t m_numShuffledEntrances = 0; uint16_t m_PatchesApplied = 0; uint16_t m_EventFlagsModified = 0; @@ -62,8 +64,8 @@ namespace mod::rando uint8_t m_StageIDX = 0xFF; // StageIDX from last Checkload - uint8_t m_BgmTableEntries; - uint8_t m_FanfareTableEntries; + uint8_t m_BgmTableEntries = 0; + uint8_t m_FanfareTableEntries = 0; // Member functions public: @@ -127,6 +129,7 @@ namespace mod::rando void applyOneTimePatches(bool set); void loadShopModels(); + void loadShuffledEntrances(); private: uint8_t* m_GCIData = nullptr; // GCI Data including header @@ -148,6 +151,8 @@ namespace mod::rando void LoadSkyCharacter(uint8_t stageIDX); void LoadHiddenSkill(); void LoadBugReward(); + void LoadEventChecks(uint8_t stageIDX); + void loadCustomText(uint8_t* data); }; } // namespace mod::rando #endif \ No newline at end of file diff --git a/GameCube/include/user_patch/05_newFileFunctions.h b/GameCube/include/user_patch/05_newFileFunctions.h index 3486a3ac..6c9fcd8a 100644 --- a/GameCube/include/user_patch/05_newFileFunctions.h +++ b/GameCube/include/user_patch/05_newFileFunctions.h @@ -25,6 +25,7 @@ namespace mod::user_patch void setInstantText(rando::Randomizer* randomizer, bool set); void setMapRegionBits(rando::Randomizer* randomizer, bool set); void increaseSpinnerVelocity(rando::Randomizer* randomizer, bool set); + void skipMajorCutscenes(rando::Randomizer* randomizer, bool set); } // namespace mod::user_patch #endif \ No newline at end of file diff --git a/GameCube/include/user_patch/user_patch.h b/GameCube/include/user_patch/user_patch.h index 07ddee93..2c277af7 100644 --- a/GameCube/include/user_patch/user_patch.h +++ b/GameCube/include/user_patch/user_patch.h @@ -23,7 +23,7 @@ namespace mod::user_patch // Available Game patches accessible by index extern GamePatch volatilePatches[6]; - extern GamePatch oneTimePatches[6]; + extern GamePatch oneTimePatches[7]; } // namespace mod::user_patch #endif \ No newline at end of file diff --git a/GameCube/source/asm/adjustPoeItem.s b/GameCube/source/asm/adjustPoeItem.s index 57cb5ac6..71471c22 100644 --- a/GameCube/source/asm/adjustPoeItem.s +++ b/GameCube/source/asm/adjustPoeItem.s @@ -1,16 +1,7 @@ -.global asmAdjustPoeItemStart -.global asmAdjustPoeItemEnd +.global asmAdjustPoeItem +.hidden asmAdjustPoeItem -.hidden asmAdjustPoeItemStart -.hidden asmAdjustPoeItemEnd - -asmAdjustPoeItemStart: +asmAdjustPoeItem: +# r4 normally would need to be backed up here, but a different patch is skipping the code that would use the value in r4, so we don't need to back it up mr %r3,%r31 # e_hp_class -bl handleAdjustPoeItem -mr %r4,%r3 #The item to give - -# Restore important register values -addi %r3,%r31,0x4D0 - -asmAdjustPoeItemEnd: -b 0 \ No newline at end of file +b handleAdjustPoeItem \ No newline at end of file diff --git a/GameCube/source/asm/check60PoeReward.s b/GameCube/source/asm/check60PoeReward.s index a6b3fd34..890e9afa 100644 --- a/GameCube/source/asm/check60PoeReward.s +++ b/GameCube/source/asm/check60PoeReward.s @@ -3,7 +3,7 @@ asmCheck60PoeReward: # Move r0 to r3 since it contains the value we need -mr %r3, %r0 +mr %r3,%r0 # Push stack stwu %sp,-0x10(%sp) @@ -16,10 +16,12 @@ stw %r3,0xC(%sp) bl handleCheck60PoeReward cmplwi %r3,1 -# Pop stack -lwz %r0,0x14(%sp) -mtlr %r0 +# Restore important register values lwz %r0,0xC(%sp) -addi %sp,%sp,0x10 +# Pop stack +lwz %r3,0x14(%sp) +mtlr %r3 +lwz %r3,0xC(%sp) +addi %sp,%sp,0x10 blr \ No newline at end of file diff --git a/GameCube/source/asm/giveMasterSwordItems.s b/GameCube/source/asm/giveMasterSwordItems.s new file mode 100644 index 00000000..b2dc1744 --- /dev/null +++ b/GameCube/source/asm/giveMasterSwordItems.s @@ -0,0 +1,19 @@ +.global asmGiveMasterSwordItemsStart +.global asmGiveMasterSwordItemsEnd + +.hidden asmGiveMasterSwordItemsStart +.hidden asmGiveMasterSwordItemsEnd + +asmGiveMasterSwordItemsStart: +bl handleGiveMasterSwordItems + +# Clear the current actor status for the Master Sword actor since we set the flag to delete it in the handle function. +# Specifically clear the lower 16 bits of fopAc_ac_c::mStatus +li %r3,0 +sth %r3,0x49E(%r26) # fopAc_ac_c::mStatus + +# Restore the original instruction +li %r3,47 + +asmGiveMasterSwordItemsEnd: +b 0 \ No newline at end of file diff --git a/GameCube/source/asm/handler.cpp b/GameCube/source/asm/handler.cpp index 7f42131b..3775412c 100644 --- a/GameCube/source/asm/handler.cpp +++ b/GameCube/source/asm/handler.cpp @@ -12,6 +12,7 @@ #include "data/items.h" #include "data/flags.h" #include "tp/d_a_npc.h" +#include "game_patch/game_patch.h" namespace mod::assembly { @@ -23,10 +24,16 @@ namespace mod::assembly } } - int32_t handleAdjustPoeItem(void* e_hp_class) + void handleAdjustPoeItem(void* e_hp_class) { - uint8_t flag = *reinterpret_cast(reinterpret_cast(e_hp_class) + 0x77B); - return events::onPoe(randomizer, flag); + // Get the item and put it into the queue + const uint8_t flag = *reinterpret_cast(reinterpret_cast(e_hp_class) + 0x77B); + const int32_t item = events::onPoe(randomizer, flag); + randomizer->addItemToEventQueue(static_cast(item)); + + // Force wolf Link into the PROC_WOLF_ATN_AC_MOVE proc to skip the backflip and trigger the queue to give the item + // immediately + libtp::tp::d_a_alink::procWolfAtnActorMoveInit(libtp::tp::d_com_inf_game::dComIfG_gameInfo.play.mPlayer); } int32_t handleAdjustAGPoeItem(void* e_po_class) @@ -76,7 +83,7 @@ namespace mod::assembly uint8_t handleShowReekfishPath(uint8_t scent) { if ((libtp::tp::d_a_alink::checkStageName(libtp::data::stage::allStages[libtp::data::stage::StageIDs::Snowpeak])) && - libtp::tp::d_a_alink::dComIfGs_isEventBit( + libtp::tp::d_com_inf_game::dComIfGs_isEventBit( libtp::data::flags::GOT_REEKFISH_SCENT)) // If we are currently at Snowpeak and the flag for having // smelled a Reekfish is set { @@ -96,7 +103,7 @@ namespace mod::assembly bool handleCheck60PoeReward(uint8_t poeCount) { // Check if we are getting the 60 Poe Check and that we have already gotten the 20 Poe Check. - return ((poeCount >= 60) && libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::GOT_BOTTLE_FROM_JOVANI)); + return ((poeCount >= 60) && libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::GOT_BOTTLE_FROM_JOVANI)); } bool handleReplaceGWolfWithItem(const int16_t* l_delFlag, void* daNpcGWolf) @@ -126,6 +133,24 @@ namespace mod::assembly return flagIsSet; } + void handleGiveMasterSwordItems() + { + using namespace libtp::data; + + // Give the player the Master Sword replacement + uint32_t itemToGive = randomizer->getEventItem(items::Master_Sword); + randomizer->addItemToEventQueue(itemToGive); + + // Give the player the Shadow Crystal replacement + itemToGive = randomizer->getEventItem(items::Shadow_Crystal); + randomizer->addItemToEventQueue(itemToGive); + + // Set the local event flag to make the sword de-spawn and set the save file event flag. + libtp::tp::d_save::dSv_info_c* savePtr = &libtp::tp::d_com_inf_game::dComIfG_gameInfo.save; + libtp::tp::d_save::onEventBit(&savePtr->mTmp, 0x820); + libtp::tp::d_save::onEventBit(&savePtr->save_file.mEvent, 0x2120); + } + #ifdef TP_JP void unpatchMapGlitch(libtp::tp::d_a_alink::daAlink* d_a_alink) { diff --git a/GameCube/source/events.cpp b/GameCube/source/events.cpp index 437a0674..5d953542 100644 --- a/GameCube/source/events.cpp +++ b/GameCube/source/events.cpp @@ -31,6 +31,8 @@ #include "rando/customItems.h" #include "tp/f_op_actor_iter.h" #include "tp/d_pane_class.h" +#include "game_patch/game_patch.h" +#include "tp/m_do_printf.h" namespace mod::events { @@ -41,26 +43,53 @@ namespace mod::events daObjLifeContainer_initActionOrderGetDemo_Def return_daObjLifeContainer_c__initActionOrderGetDemo = nullptr; daMidna_checkMetamorphoseEnableBase_Def daMidna_c__checkMetamorphoseEnableBase = nullptr; + // Custom Ganon Barrier to prevent the player from trying to enter Lanayru Twilight during Eldin Twilight libtp::tp::dzx::ACTR GanonBarrierActor = {"Obj_gb", 0x800F0601, 10778.207f, 3096.82666f, -62651.0078f, static_cast(-164), 0x4000, 0, 0xFFFF}; + // Auru actor that is added to the Post-Cannon repair state of Lake Hylia libtp::tp::dzx::ACTR AuruActr = {"Rafrel", 0x00001D01, -116486.945f, -13860.f, 58533.0078f, 0, static_cast(0xCCCD), 0, 0xFFFF}; + // item actor template libtp::tp::dzx::ACTR ItemActr = {"item", 0xF3FFFF04, -108290.086f, -18654.748f, 45935.2969f, 0, static_cast(0x1), 0x3F, 0xFFFF}; + // Epona actor template libtp::tp::dzx::ACTR EponaActr = {"Horse", 0x00000F0D, -1200.f, 367.f, 6100.f, 0, -180, 0, 0xFFFF}; + // Horse jump SCOB template libtp::tp::dzx::SCOB HorseJumpScob = {"Hjump", 0x044FFF02, 5600.f, -5680.f, 52055.f, 0, static_cast(0x4000), 0, 0xFFFF, 0x20, 0x2D, 0x2D, 0xFF}; - libtp::tp::dzx::ACTR ForestGWolfActr = {"GWolf", 0x05FF01FF, -35178.f, 430.21f, -21503.6f, 0, -0x4000, 0xFF, 0xFFFF}; + // Golden Wolf actor placed in Faron Woods. + libtp::tp::dzx::ACTR ForestGWolfActr = {"GWolf", 0x05FF01FF, -36714.9023f, 424.03894f, -23698.0273f, 0, 0, 0xFF, 0xFFFF}; + // Poe actor template libtp::tp::dzx::ACTR ImpPoeActr = {"E_hp", 0xFF031E00, 4531.19f, -30.f, 2631.961f, 0, 0, 0x0, 0xFFFF}; + // Boar actor template libtp::tp::dzx::ACTR CampBoarActr = {"E_wb", 0xFFFFFFFF, 1650.f, 0.f, 1250.f, 0, static_cast(0xA000), 0x0, 0xFFFF}; + // Custom shop sold out actors for shop checks. using actor template: 0x48 bytes in memory due to instructions + // Creating new actors uses less memory than modifying a template due to the amount of memory used by instructions. + // (0x28 vs 0x48 bytes) + libtp::tp::dzx::ACTR KakShopSlot2Actr = + {"TGSPITM", 0x02FFFFFF, -650.f, 450.f, -500.f, 0x147, static_cast(0x8000), 0x05FF, 0xFFFF}; + + // Sign Actors + libtp::tp::dzx::ACTR SignActor = {"Obj_kn2", + 0xFFFFFFFF, + -2088.f, + 0.8535f, + 7535.77f, + static_cast(0xFFFE), // Flow Node ID + static_cast(0xD556), + 0, + 0xFFFF}; + + libtp::tp::dzx::ACTR MstrSrdActr = {"mstrsrd", 0x000020110, 0.f, 1700.f, -5435.f, 0x147, 0x0, 0x0, 0xFFFF}; + uint8_t timeChange = 0; void onLoad(rando::Randomizer* randomizer) @@ -86,8 +115,8 @@ namespace mod::events d_stage::dStage_startStage* startStagePtr = &playPtr->mStartStage; const char* currentStage = startStagePtr->mStage; - int32_t currentRoom = startStagePtr->mRoomNo; - int32_t currentPoint = startStagePtr->mPoint; + const int32_t currentRoom = startStagePtr->mRoomNo; + const int32_t currentPoint = startStagePtr->mPoint; // Check if the seed is already applied to the save-file (flags etc.) // Try to do it otherwise @@ -96,12 +125,35 @@ namespace mod::events randomizer->initSave(); } - if ((strcmp(playPtr->mNextStage.stageValues.mStage, "F_SP103") == 0) && (currentRoom == 1) && + if ((strcmp(playPtr->mNextStage.mStage, "F_SP103") == 0) && (currentRoom == 1) && (currentPoint == 0x1)) // If we are spawning in Ordon for the first time. { - savePtr->save_file.player.player_status_b.skyAngle = 180.f; + float* skyAnglePtr = &savePtr->save_file.player.player_status_b.skyAngle; - if (d_a_alink::dComIfGs_isEventBit(flags::ORDON_DAY_2_OVER)) + switch (randomizer->m_Seed->m_Header->startingTimeOfDay) + { + case rando::StartingTimeOfDay::Morning: + { + *skyAnglePtr = 105.f; + break; + } + case rando::StartingTimeOfDay::Noon: + { + *skyAnglePtr = 180.f; + break; + } + case rando::StartingTimeOfDay::Night: + { + *skyAnglePtr = 0.f; + break; + } + default: // Evening + { + break; + } + } + + if (d_com_inf_game::dComIfGs_isEventBit(flags::ORDON_DAY_2_OVER)) { savePtr->save_file.player.horse_place.mPos.y = -1000.f; // Place Epona out of bounds in Faron if Talo has been // rescued since the game will spawn her in the air. @@ -119,6 +171,12 @@ namespace mod::events 0xF); // Main Room 1F explored } + // Clear the danBit that starts a conversation when entering the ranch so the player can do goats as needed. + if ((strcmp(currentStage, stage::allStages[stage::StageIDs::Ordon_Ranch]) == 0) && (currentPoint == 0x1)) + { + d_com_inf_game::dComIfG_gameInfo.save.mDan.mSwitch[0] = 0x0; + } + randomizer->overrideEventARC(); } @@ -169,12 +227,20 @@ namespace mod::events // Generic Poe case D_A_E_HP: { - libtp::patch::writeStandardBranches(relPtrRaw + e_hp_ExecDead_liOffset, - assembly::asmAdjustPoeItemStart, - assembly::asmAdjustPoeItemEnd); + // Force the poe to be despawned immediately without playing the get item animation + performStaticASMReplacement(relPtrRaw + e_hp_ExecDead_beqOffset, ASM_NOP); + + // Initialize giving the proper item rather than the poe soul + libtp::patch::writeBranchBL(relPtrRaw + e_hp_ExecDead_incOffset, assembly::asmAdjustPoeItem); // Disable Poe increment (handled through item_get_func; see game_patches) - performStaticASMReplacement(relPtrRaw + e_hp_ExecDead_incOffset, ASM_NOP); + performStaticASMReplacement(relPtrRaw + e_hp_ExecDead_incOffset + 0x4, ASM_BRANCH(0x18)); + + // Skip checking for setting the flag for having obtained 20 poe souls + + // This cannot be combined with the previous branch due to a value being stored in a class in the middle of the + // branches + performStaticASMReplacement(relPtrRaw + e_hp_ExecDead_incOffset + 0x24, ASM_BRANCH(0x28)); break; } @@ -186,8 +252,9 @@ namespace mod::events assembly::asmAdjustAGPoeItemStart, assembly::asmAdjustAGPoeItemEnd); - // Disable Poe increment (handled through item_get_func; see game_patches) - performStaticASMReplacement(relPtrRaw + e_po_ExecDead_incOffset, ASM_NOP); + // Disable Poe increment (handled through item_get_func; see game_patches) and skip checking for setting the + // flag for having obtained 20 poe souls + performStaticASMReplacement(relPtrRaw + e_po_ExecDead_incOffset, ASM_BRANCH(0x44)); break; } @@ -235,6 +302,9 @@ namespace mod::events case D_A_MG_ROD: { libtp::patch::writeBranchBL(relPtrRaw + 0xB2B0, libtp::tp::d_item::execItemGet); + + // Branch over rng check instructions from uki_main for 100% bottle guarantee + performStaticASMReplacement(relPtrRaw + 0xBFAC, ASM_BRANCH(0x18)); break; } @@ -285,6 +355,7 @@ namespace mod::events break; } case items::Ordon_Sword: + case customItems::Mirror_Piece_1: case items::Mirror_Piece_2: case items::Mirror_Piece_3: case items::Mirror_Piece_4: @@ -673,6 +744,31 @@ namespace mod::events performStaticASMReplacement(relPtrRaw + 0x20B8, ASM_BRANCH_EQUAL_MINUS(0x38)); break; } + + // d_obj_master_sword.rel + // Master Sword Freestanding Actor + case D_A_OBJ_MASTER_SWORD: + { + // If a seed is not loaded, then use vanilla behavior + if (!getCurrentSeed(randomizer)) + { + break; + } + + // Apply an ASM patch to d_a_Obj_Master_Sword::executeWait to give the player two items and delete the Master + // Sword actor instead of trying to play the purification cutscene. + libtp::patch::writeStandardBranches(relPtrRaw + 0x254, + assembly::asmGiveMasterSwordItemsStart, + assembly::asmGiveMasterSwordItemsEnd); + + // Branch over the code that gives Link the master sword if it has been pulled + performStaticASMReplacement(relPtrRaw + 0xCA0, ASM_BRANCH(0x80)); + + // Nop out the function call to d_meter2_info::setCloth that causes a crash if you are wearing anything other + // than magic armor + performStaticASMReplacement(relPtrRaw + 0x25C, ASM_NOP); + break; + } } } @@ -713,7 +809,6 @@ namespace mod::events void onDZX(rando::Randomizer* randomizer, libtp::tp::dzx::ChunkTypeInfo* chunkTypeInfo) { randomizer->overrideDZX(chunkTypeInfo); - loadCustomActors(); } int32_t onPoe(rando::Randomizer* randomizer, uint8_t flag) @@ -768,13 +863,14 @@ namespace mod::events void setSaveFileEventFlag(uint16_t flag) { - libtp::tp::d_save::onEventBit(&libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.event_flags, flag); + libtp::tp::d_save::onEventBit(&libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.mEvent, flag); } void onAdjustFieldItemParams(libtp::tp::f_op_actor::fopAc_ac_c* fopAC, void* daObjLife) { using namespace libtp::data::stage; using namespace libtp::data::items; + using namespace rando::customItems; if (!getCurrentSeed(randomizer)) { @@ -819,6 +915,7 @@ namespace mod::events case Master_Sword: case Master_Sword_Light: + case Mirror_Piece_1: case Mirror_Piece_2: case Mirror_Piece_3: case Mirror_Piece_4: @@ -842,10 +939,12 @@ namespace mod::events } using namespace libtp::data::items; + using namespace rando::customItems; const uint32_t itemID = *reinterpret_cast(reinterpret_cast(daDitem) + 0x92A); switch (itemID) { + case Mirror_Piece_1: case Mirror_Piece_2: case Mirror_Piece_3: case Mirror_Piece_4: @@ -869,20 +968,23 @@ namespace mod::events int32_t proc_query022(void* unk1, void* unk2, int32_t unk3) { + using namespace libtp::data; + using namespace libtp::tp; + // Check to see if currently in one of the Ordon interiors - if (libtp::tp::d_a_alink::checkStageName( - libtp::data::stage::allStages[libtp::data::stage::StageIDs::Ordon_Village_Interiors])) + if (d_a_alink::checkStageName(stage::allStages[stage::StageIDs::Ordon_Village_Interiors])) { - // Check to see if ckecking for the Iron Boots + // Check to see if checking for the Iron Boots const uint32_t item = *reinterpret_cast(reinterpret_cast(unk2) + 0x4); - if (item == libtp::data::items::Iron_Boots) + if (item == items::Iron_Boots) { // Return false so that the door in Bo's house can be opened without having the // Iron Boots return 0; } } + return mod::return_query022(unk1, unk2, unk3); } @@ -897,7 +999,7 @@ namespace mod::events libtp::data::stage::allStages[libtp::data::stage::StageIDs::Kakariko_Village_Interiors])) { // If player has not bought Barnes' Bomb Bag, we want to allow them to be able to get the check. - if ((!libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::BOUGHT_BARNES_BOMB_BAG))) + if ((!libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::BOUGHT_BARNES_BOMB_BAG))) { return 0; } @@ -913,6 +1015,22 @@ namespace mod::events return numBombs; } + int32_t proc_query025(void* unk1, void* unk2, int32_t unk3) + { + using namespace libtp::data::stage; + + const auto stagesPtr = &allStages[0]; + + // Check to see if currently in one of the Kakariko interiors + if (libtp::tools::playerIsInRoomStage(3, stagesPtr[StageIDs::Kakariko_Village_Interiors])) + { + // Return 0 so the player can buy the red potion item from the shop. + return 0; + } + + return mod::return_query025(unk1, unk2, unk3); + } + int32_t proc_query042(void* unk1, void* unk2, int32_t unk3) { if (checkValidTransformAnywhere()) @@ -990,107 +1108,529 @@ namespace mod::events void proc_onDungeonItem(libtp::tp::d_save::dSv_memBit_c* memBitPtr, const int32_t memBit) { + using namespace libtp; using namespace libtp::data::flags; - switch (memBit) + using namespace libtp::data::stage; + + // Make sure the randomizer is loaded/enabled and a seed is loaded + rando::Seed* seedPtr; + if (seedPtr = getCurrentSeed(randomizer), !seedPtr) { - case BOSS_DEFEATED: + return mod::return_onDungeonItem(memBitPtr, memBit); + } + + const auto stagesPtr = &allStages[0]; + tp::d_save::dSv_info_c* savePtr = &tp::d_com_inf_game::dComIfG_gameInfo.save; + + if (memBitPtr == &savePtr->memory.temp_flags) + { + switch (memBit) { - if (randomizer->m_Seed->m_Header->castleRequirements == 3) // All Dungeons + case BOSS_DEFEATED: { - // Check to see if the player has completed all of the other dungeons, if so, destroy the barrier. - uint8_t numDungeons = 0x0; - for (int32_t i = 0x10; i < 0x18; i++) + if (seedPtr->m_Header->castleRequirements == + rando::CastleEntryRequirements::HC_All_Dungeons) // All Dungeons { - if (libtp::tp::d_save::isDungeonItem( - &libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.area_flags[i].temp_flags, - 3)) + // Check to see if the player has completed all of the other dungeons, if so, destroy the barrier. + libtp::tp::d_save::dSv_memory_c* mSavePtr = savePtr->save_file.mSave; + uint32_t numDungeons = 0; + + for (int32_t i = 0x10; i < 0x18; i++) + { + if (libtp::tp::d_save::isDungeonItem(&mSavePtr[i].temp_flags, 3)) + { + numDungeons++; + } + } + + if (numDungeons == 7) // We check for 7 instead of 8 because when this code runs, the temp_flags for + // the current stage has not been updated with the boss flag value yet. { - numDungeons++; + events::setSaveFileEventFlag(libtp::data::flags::BARRIER_GONE); } } - if (numDungeons == 0x7) // We check for 7 instead of 8 because when this code runs, the temp_flags for - // the current stage has not been updated with the boss flag value yet. + if (tp::d_a_alink::checkStageName(stagesPtr[StageIDs::Stallord])) { - events::setSaveFileEventFlag(libtp::data::flags::BARRIER_GONE); + uint32_t agDungeonReward = randomizer->getEventItem(rando::customItems::Mirror_Piece_1); + randomizer->addItemToEventQueue(agDungeonReward); } + break; + } + default: + { + break; } - break; - } - default: - { - break; } } + mod::return_onDungeonItem(memBitPtr, memBit); } - void loadCustomActors() + void loadCustomActors(void* mStatus_roomControl) { using namespace libtp; + using namespace libtp::data::stage; - const auto stagesPtr = &data::stage::allStages[0]; - if (tp::d_a_alink::checkStageName(stagesPtr[data::stage::StageIDs::Faron_Woods])) + const auto stagesPtr = &allStages[0]; + tp::dzx::ACTR localSignActor; + memcpy(&localSignActor, &SignActor, sizeof(tp::dzx::ACTR)); + + if (tp::d_a_alink::checkStageName(stagesPtr[StageIDs::Faron_Woods])) { tools::spawnActor(0, EponaActr); } - else if ((tp::d_a_alink::checkStageName(stagesPtr[data::stage::StageIDs::Ordon_Village]) && - (libtp::tools::getCurrentRoomNo() == 0))) + else if (libtp::tools::playerIsInRoomStage(0, stagesPtr[libtp::data::stage::StageIDs::Ordon_Village])) { - libtp::tp::dzx::ACTR localEponaActor; - memcpy(&localEponaActor, &EponaActr, sizeof(libtp::tp::dzx::ACTR)); + tp::dzx::ACTR localEponaActor; + memcpy(&localEponaActor, &EponaActr, sizeof(tp::dzx::ACTR)); localEponaActor.parameters = 0x148; tools::spawnActor(0, localEponaActor); } + + // The actors in this case are actors who need to be spawned in even if the area is in a specific set state no matter + // what (i.e PoT, HC, etc. and cannot be spawned in with the mStageData actors due to checking for angles and the like, + // which causes a crash.) + if (randomizer && (reinterpret_cast(mStatus_roomControl) != + reinterpret_cast(&libtp::tp::d_com_inf_game::dComIfG_gameInfo.play.mStageData))) + { + switch (randomizer->m_Seed->m_StageIDX) + { + case StageIDs::Palace_of_Twilight: + { + localSignActor.pos.x = 1808.76245f; + localSignActor.pos.y = -208.901459f; + localSignActor.pos.z = 11813.2744f; + localSignActor.rot[1] = static_cast(0xA971); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Hyrule_Castle: + { + localSignActor.pos.x = 0.0f; + localSignActor.pos.y = 25.f; + localSignActor.pos.z = 11625.f; + localSignActor.rot[1] = static_cast(0x0000); + tools::spawnActor(11, localSignActor); + break; + } + } + } } - void loadCustomRoomActors() + void loadCustomRoomActors(rando::Randomizer* randomizer) { using namespace libtp; + using namespace libtp::data::stage; + + if (!getCurrentSeed(randomizer)) + { + return; + } - const auto stagesPtr = &data::stage::allStages[0]; - if (tp::d_a_alink::checkStageName(stagesPtr[data::stage::StageIDs::Lake_Hylia])) + tp::dzx::ACTR localSignActor; + memcpy(&localSignActor, &SignActor, sizeof(tp::dzx::ACTR)); + + const int32_t roomIDX = libtp::tp::d_com_inf_game::dComIfG_gameInfo.play.mEvtManager.mRoomNo; + switch (randomizer->m_Seed->m_StageIDX) { - if (libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::SKY_CANNON_REPAIRED)) + case StageIDs::Lake_Hylia: { - // Manually spawn Auru if the Lake is in the Repaired Cannon state as his actor is not in the DZX for that - // layer. - tools::spawnActor(0, AuruActr); + if (tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::SKY_CANNON_REPAIRED)) + { + // Manually spawn Auru if the Lake is in the Repaired Cannon state as his actor is not in the DZX for that + // layer. + tools::spawnActor(0, AuruActr); + } + + // Spawn a red rupee behind Fyer's house that allows the player to use his cannon to leave the lake which + // prevents a softlock. + tools::spawnActor(0, ItemActr); + + localSignActor.pos.x = -109203.461f; + localSignActor.pos.y = -7220.f; + localSignActor.pos.z = 33083.7344f; + localSignActor.rot[1] = static_cast(0x64B5); + tools::spawnActor(0, localSignActor); + + if (roomIDX == 1) // Lanayru Spring + { + localSignActor.pos.x = -309.997833f; + localSignActor.pos.y = -1614.82178f; + localSignActor.pos.z = 157.970795f; + localSignActor.rot[1] = static_cast(0x8000); + tools::spawnActor(1, localSignActor); + } + break; } - // Spawn a red rupee behind Fyer's house that allows the player to use his cannon to leave the lake which prevents a - // softlock. - tools::spawnActor(0, ItemActr); - } - else if (tp::d_a_alink::checkStageName(stagesPtr[data::stage::StageIDs::Hyrule_Field]) && - (!tp::d_save::isEventBit(&tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.event_flags, - data::flags::CLEARED_ELDIN_TWILIGHT))) - { - libtp::tp::dzx::ACTR localGanonBarrierActor; - memcpy(&localGanonBarrierActor, &GanonBarrierActor, sizeof(libtp::tp::dzx::ACTR)); + case StageIDs::Hyrule_Field: + { + if (roomIDX == 0) // Eldin Field + { + if (!tp::d_save::isEventBit(&tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.mEvent, + data::flags::CLEARED_ELDIN_TWILIGHT)) + { + libtp::tp::dzx::ACTR localGanonBarrierActor; + memcpy(&localGanonBarrierActor, &GanonBarrierActor, sizeof(libtp::tp::dzx::ACTR)); - tools::spawnActor(7, localGanonBarrierActor); + tools::spawnActor(7, localGanonBarrierActor); - localGanonBarrierActor.pos.z -= 270.f; - tools::spawnActor(7, localGanonBarrierActor); + localGanonBarrierActor.pos.z -= 270.f; + tools::spawnActor(7, localGanonBarrierActor); - localGanonBarrierActor.pos.z -= 270.f; - tools::spawnActor(7, localGanonBarrierActor); - } - else if (tp::d_a_alink::checkStageName(stagesPtr[data::stage::StageIDs::Faron_Woods]) && - (tp::d_save::isEventBit(&tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.event_flags, - data::flags::ORDON_DAY_2_OVER))) - { - tools::spawnActor(6, ForestGWolfActr); - } - else if (tp::d_a_alink::checkStageName(stagesPtr[data::stage::StageIDs::Castle_Town_Shops])) - { - tools::spawnActor(6, ImpPoeActr); - } - else if (tp::d_a_alink::checkStageName(stagesPtr[data::stage::StageIDs::Bulblin_Camp]) && - !libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::ESCAPED_BURNING_TENT_IN_BULBLIN_CAMP)) - { - tools::spawnActor(1, CampBoarActr); + localGanonBarrierActor.pos.z -= 270.f; + tools::spawnActor(7, localGanonBarrierActor); + } + localSignActor.pos.x = -12433.2744f; + localSignActor.pos.y = -1075.2218f; + localSignActor.pos.z = 20885.7129f; + localSignActor.rot[1] = static_cast(0x8000); + tools::spawnActor(0, localSignActor); + } + + if (roomIDX == 6) // Faron Field + { + localSignActor.pos.x = -46039.4922f; + localSignActor.pos.y = -9250.f; + localSignActor.pos.z = 81859.2891f; + localSignActor.rot[1] = static_cast(0x8000); + tools::spawnActor(6, localSignActor); + } + + if (roomIDX == 3) // Kakariko Gorge + { + localSignActor.pos.x = -11394.7832f; + localSignActor.pos.y = -3258.73096f; + localSignActor.pos.z = 39702.91995f; + localSignActor.rot[1] = static_cast(0xAC70); + tools::spawnActor(3, localSignActor); + } + + if (roomIDX == 7) // North Eldin Hint Sign + { + localSignActor.pos.x = 29691.0742f; + localSignActor.pos.y = 661.668; + localSignActor.pos.z = -53367.16f; + localSignActor.rot[1] = static_cast(0x742B); + tools::spawnActor(7, localSignActor); + } + + if (roomIDX == 10) // Lanayru Field + { + localSignActor.pos.x = -46711.957f; + localSignActor.pos.y = 268.4848f; + localSignActor.pos.z = -55505.5508f; + localSignActor.rot[1] = static_cast(0x85B9); + tools::spawnActor(10, localSignActor); + } + + if (roomIDX == 13) // Great Bridge of Hylia + { + localSignActor.pos.x = -94678.8672f; + localSignActor.pos.y = -3900.f; + localSignActor.pos.z = 18410.543f; + localSignActor.rot[1] = static_cast(0x0000); + tools::spawnActor(13, localSignActor); + } + + break; + } + + case StageIDs::Faron_Woods: + { + if (tp::d_save::isEventBit(&tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.mEvent, + data::flags::ORDON_DAY_2_OVER)) + { + tools::spawnActor(6, ForestGWolfActr); + } + + if (roomIDX == 4) + { + localSignActor.pos.x = -12423.8467f; + localSignActor.pos.y = 273.277985f; + localSignActor.pos.z = -11518.958f; + localSignActor.rot[1] = static_cast(0x9228); + tools::spawnActor(4, localSignActor); + } + break; + } + + case StageIDs::Castle_Town_Shops: + { + tools::spawnActor(5, ImpPoeActr); + break; + } + + case StageIDs::Bulblin_Camp: + { + if (!libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::ESCAPED_BURNING_TENT_IN_BULBLIN_CAMP)) + { + tools::spawnActor(1, CampBoarActr); + } + + localSignActor.pos.x = -568.556152f; + localSignActor.pos.y = 260.f; + localSignActor.pos.z = -3969.31f; + localSignActor.rot[1] = static_cast(0x0000); + tools::spawnActor(1, localSignActor); + break; + } + + case StageIDs::Kakariko_Village_Interiors: + { + if (roomIDX == 0x3) + { + tools::spawnActor(3, KakShopSlot2Actr); + } + break; + } + + case StageIDs::Kakariko_Village: + { + localSignActor.pos.x = -6277.372f; + localSignActor.pos.y = 2850.f; + localSignActor.pos.z = -2197.14331f; + localSignActor.rot[1] = static_cast(0x4000); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Ordon_Village: + { + // Need to check for room 1 or we get a floating sign near the + // roof of Sera's Shop. + if (roomIDX == 1) + { + localSignActor.pos.x = 687.89f; + localSignActor.pos.y = 800.f; + localSignActor.pos.z = -1424.16f; + localSignActor.rot[1] = static_cast(0xA019); + tools::spawnActor(1, localSignActor); + } + break; + } + + case StageIDs::Sacred_Grove: + { + localSignActor.pos.x = -1543.f; + localSignActor.pos.y = 1725.f; + localSignActor.pos.z = 7964.85498f; + localSignActor.rot[1] = static_cast(0x4000); + tools::spawnActor(1, localSignActor); + + if (roomIDX == 1) + { + tools::spawnActor(1, MstrSrdActr); + } + break; + } + + case StageIDs::Kakariko_Graveyard: + { + localSignActor.pos.x = 21765.9863f; + localSignActor.pos.y = 500.f; + localSignActor.pos.z = -62.247f; + localSignActor.rot[1] = static_cast(0xC000); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Death_Mountain: + { + localSignActor.pos.x = 920.583069f; + localSignActor.pos.y = 0.745985091f; + localSignActor.pos.z = 1227.39978f; + localSignActor.rot[1] = static_cast(0x35A5); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Hidden_Village: + { + localSignActor.pos.x = 5161.03f; + localSignActor.pos.y = 0.f; + localSignActor.pos.z = -5264.33f; + localSignActor.rot[1] = static_cast(0x0000); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Outside_Castle_Town: + { + if (roomIDX == 8) // Beside Castle Town + { + localSignActor.pos.x = -68194.2109f; + localSignActor.pos.y = -1050.f; + localSignActor.pos.z = 5603.60645f; + localSignActor.rot[1] = static_cast(0xC000); + tools::spawnActor(8, localSignActor); + } + else if (roomIDX == 16) // South of CT + { + localSignActor.pos.x = -51500.f; + localSignActor.pos.y = -5500.f; + localSignActor.pos.z = 27368.3086f; + localSignActor.rot[1] = static_cast(0x0000); + tools::spawnActor(16, localSignActor); + } + break; + } + + case StageIDs::Castle_Town: + { + localSignActor.pos.x = 0.f; + localSignActor.pos.y = -200.f; + localSignActor.pos.z = 835.f; + localSignActor.rot[1] = static_cast(0x0000); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Lake_Hylia_Long_Cave: + { + localSignActor.pos.x = -2897.38672f; + localSignActor.pos.y = -1636.68994f; + localSignActor.pos.z = -17674.8691f; + localSignActor.rot[1] = static_cast(0x3E21); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Zoras_Domain: + { + localSignActor.pos.x = -2964.84839f; + localSignActor.pos.y = -2500.f; + localSignActor.pos.z = 17146.2676f; + localSignActor.rot[1] = static_cast(0xAF09); + tools::spawnActor(1, localSignActor); + break; + } + + case StageIDs::Fishing_Pond: + { + localSignActor.pos.x = -2924.74585f; + localSignActor.pos.y = 35.f; + localSignActor.pos.z = 8386.28906f; + localSignActor.rot[1] = static_cast(0x8000); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Gerudo_Desert: + { + localSignActor.pos.x = 20356.23f; + localSignActor.pos.y = 556.7; + localSignActor.pos.z = 38694.8047f; + localSignActor.rot[1] = static_cast(0x0099); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Snowpeak: + { + localSignActor.pos.x = 15931.9238f; + localSignActor.pos.y = -14389.4912f; + localSignActor.pos.z = -17388.1992f; + localSignActor.rot[1] = static_cast(0x2C5A); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Cave_of_Ordeals: + { + localSignActor.pos.x = -1191.42f; + localSignActor.pos.y = 1100.f; + localSignActor.pos.z = -260.65f; + localSignActor.rot[1] = static_cast(0xE483); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Forest_Temple: + { + localSignActor.pos.x = -1972.11682f; + localSignActor.pos.y = 3150.f; + localSignActor.pos.z = 7610.9751f; + localSignActor.rot[1] = static_cast(0x6000); + tools::spawnActor(0, localSignActor); + break; + } + + case StageIDs::Goron_Mines: + { + localSignActor.pos.x = 11394.1855f; + localSignActor.pos.y = 2878.65; + localSignActor.pos.z = -17913.05f; + localSignActor.rot[1] = static_cast(0xD556); + tools::spawnActor(17, localSignActor); + break; + } + + case StageIDs::Lakebed_Temple: + { + localSignActor.pos.x = -4765.38037f; + localSignActor.pos.y = -1.21f; + localSignActor.pos.z = 272.192261f; + localSignActor.rot[1] = static_cast(0x46B9); + tools::spawnActor(3, localSignActor); + break; + } + + case StageIDs::Arbiters_Grounds: + { + localSignActor.pos.x = -349.4044f; + localSignActor.pos.y = 450.f; + localSignActor.pos.z = -2876.90771f; + localSignActor.rot[1] = static_cast(0x0000); + tools::spawnActor(2, localSignActor); + break; + } + + case StageIDs::Snowpeak_Ruins: + { + localSignActor.pos.x = -530.f; + localSignActor.pos.y = 0.f; + localSignActor.pos.z = -669.69f; + localSignActor.rot[1] = static_cast(0x0000); + tools::spawnActor(1, localSignActor); + break; + } + + case StageIDs::Temple_of_Time: + { + localSignActor.pos.x = -618.9335f; + localSignActor.pos.y = 725.f; + localSignActor.pos.z = 3112.2f; + localSignActor.rot[1] = static_cast(0x8000); + tools::spawnActor(0, localSignActor); + + // ToT midpoint sign + tp::dzx::ACTR localSignActor2; + memcpy(&localSignActor2, &SignActor, sizeof(tp::dzx::ACTR)); + localSignActor2.pos.x = -3885.2157f; + localSignActor2.pos.y = 4450.f; + localSignActor2.pos.z = -6353.38135f; + localSignActor2.rot[1] = static_cast(0x2000); + tools::spawnActor(4, localSignActor2); + break; + } + + case StageIDs::City_in_the_Sky: + { + localSignActor.pos.x = 3376.54f; + localSignActor.pos.y = 0.f; + localSignActor.pos.z = -12709.0352f; + localSignActor.rot[1] = static_cast(0xC846); + tools::spawnActor(2, localSignActor); + break; + } + + default: + { + break; + } } } @@ -1098,7 +1638,7 @@ namespace mod::events { using namespace libtp; if (tp::d_a_alink::checkStageName(data::stage::allStages[data::stage::StageIDs::Hyrule_Field]) && - libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::MIDNAS_DESPERATE_HOUR_COMPLETED)) + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::MIDNAS_DESPERATE_HOUR_COMPLETED)) { tools::spawnSCOB(3, HorseJumpScob); } @@ -1111,8 +1651,9 @@ namespace mod::events void handleQuickTransform() { - rando::Seed* seed; using namespace libtp::tp::d_com_inf_game; + + rando::Seed* seed; if (seed = getCurrentSeed(randomizer), !seed) { return; @@ -1137,45 +1678,63 @@ namespace mod::events } // Check to see if Link has the ability to transform. - if (!libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::TRANSFORMING_UNLOCKED)) + if (!libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::TRANSFORMING_UNLOCKED)) { return; } - // Ensure there is a proper pointer to the Z Button Alpha. - uint32_t zButtonAlphaPtr = reinterpret_cast(libtp::tp::d_meter2_info::wZButtonPtr); - if (!zButtonAlphaPtr) + // Make sure Link isn't riding anything (horse, boar, etc.) + if (libtp::tp::d_camera::checkRide(linkMapPtr)) { return; } - zButtonAlphaPtr = *reinterpret_cast(zButtonAlphaPtr + 0x10C); - if (!zButtonAlphaPtr) + // Make sure Link is not underwater or talking to someone. + switch (linkMapPtr->mProcID) { - return; + case libtp::tp::d_a_alink::PROC_TALK: + case libtp::tp::d_a_alink::PROC_SWIM_UP: + case libtp::tp::d_a_alink::PROC_SWIM_DIVE: + { + return; + } + // If Link is targeting or pulling a chain, we don't want to remove the ability to use items in combat accidently. + case libtp::tp::d_a_alink::PROC_ATN_ACTOR_MOVE: + case libtp::tp::d_a_alink::PROC_ATN_ACTOR_WAIT: + case libtp::tp::d_a_alink::PROC_WOLF_ATN_AC_MOVE: + { + break; + } + default: + { + // Disable the input that was just pressed, as sometimes it could cause items to be used or Wolf Link to dig. + libtp::tp::m_do_controller_pad::cpadInfo[libtp::tp::m_do_controller_pad::PAD_1].mPressedButtonFlags = 0; + break; + } } - // Ensure that the Z Button is not dimmed - const float zButtonAlpha = *reinterpret_cast(zButtonAlphaPtr + 0x720); - if (zButtonAlpha != 1.f) + // Ensure there is a proper pointer to the mMeterClass and mpMeterDraw structs in g_meter2_info. + const libtp::tp::d_meter2::dMeter2_c* meterClassPtr = libtp::tp::d_meter2_info::g_meter2_info.mMeterClass; + if (!meterClassPtr) { return; } - // Make sure Link is not underwater or talking to someone. - if (libtp::tp::d_a_alink::linkStatus->status != 0x1) + const libtp::tp::d_meter2_draw::dMeter2Draw_c* meterDrawPtr = meterClassPtr->mpMeterDraw; + if (!meterDrawPtr) { return; } - // The game will crash if trying to quick transform while holding the Ball and Chain - if (linkMapPtr->mEquipItem == libtp::data::items::Ball_and_Chain) + // Ensure that the Z Button is not dimmed + const float zButtonAlpha = meterDrawPtr->mZButtonAlpha; + if (zButtonAlpha != 1.f) { return; } - // Make sure Link isn't riding anything (horse, boar, etc.) - if (libtp::tp::d_camera::checkRide(linkMapPtr)) + // The game will crash if trying to quick transform while holding the Ball and Chain + if (linkMapPtr->mEquipItem == libtp::data::items::Ball_and_Chain) { return; } @@ -1230,15 +1789,15 @@ namespace mod::events } else { - libtp::tp::d_save::dSv_player_status_b_c* playerStatusPtr = &dComIfG_gameInfo.save.save_file.player.player_status_b; + float* skyAnglePtr = &dComIfG_gameInfo.save.save_file.player.player_status_b.skyAngle; if (!libtp::tp::d_kankyo::dKy_daynight_check()) // Day time { - playerStatusPtr->skyAngle = 285; + *skyAnglePtr = 285.f; } else { - playerStatusPtr->skyAngle = 105; + *skyAnglePtr = 105.f; } dComIfG_gameInfo.play.mNextStage.enabled |= 0x1; @@ -1292,23 +1851,23 @@ namespace mod::events // Check if Midna has actually been unlocked and is on the Z button // This is needed because the Z button will always be dimmed if she has not been unlocked - if (libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::MIDNA_ACCOMPANIES_WOLF)) + if (libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::MIDNA_ACCOMPANIES_WOLF)) { - // Ensure there is a proper pointer to the Z Button Alpha. - uint32_t zButtonAlphaPtr = reinterpret_cast(libtp::tp::d_meter2_info::wZButtonPtr); - if (!zButtonAlphaPtr) + // Ensure there is a proper pointer to the mMeterClass and mpMeterDraw structs in g_meter2_info. + const libtp::tp::d_meter2::dMeter2_c* meterClassPtr = libtp::tp::d_meter2_info::g_meter2_info.mMeterClass; + if (!meterClassPtr) { return false; } - zButtonAlphaPtr = *reinterpret_cast(zButtonAlphaPtr + 0x10C); - if (!zButtonAlphaPtr) + const libtp::tp::d_meter2_draw::dMeter2Draw_c* meterDrawPtr = meterClassPtr->mpMeterDraw; + if (!meterDrawPtr) { return false; } // Ensure that the Z Button is not dimmed - const float zButtonAlpha = *reinterpret_cast(zButtonAlphaPtr + 0x720); + const float zButtonAlpha = meterDrawPtr->mZButtonAlpha; if (zButtonAlpha != 1.f) { return false; @@ -1316,9 +1875,22 @@ namespace mod::events } // Make sure Link is not underwater or talking to someone. - if (libtp::tp::d_a_alink::linkStatus->status != 0x1) + switch (linkMapPtr->mProcID) { - return false; + case libtp::tp::d_a_alink::PROC_TALK: + case libtp::tp::d_a_alink::PROC_WOLF_SWIM_MOVE: + case libtp::tp::d_a_alink::PROC_SWIM_MOVE: + case libtp::tp::d_a_alink::PROC_SWIM_WAIT: + case libtp::tp::d_a_alink::PROC_WOLF_SWIM_WAIT: + case libtp::tp::d_a_alink::PROC_SWIM_UP: + case libtp::tp::d_a_alink::PROC_SWIM_DIVE: + { + return false; + } + default: + { + break; + } } return true; @@ -1442,7 +2014,7 @@ namespace mod::events } else // We are not in the correct node, so use the appropriate region node { - memoryFlags = saveDataPtr->save_file.area_flags[static_cast(nodeId)].temp_flags.memoryFlags; + memoryFlags = saveDataPtr->save_file.mSave[static_cast(nodeId)].temp_flags.memoryFlags; } return memoryFlags; @@ -1546,12 +2118,16 @@ namespace mod::events rando::RawRGBTable* rawRGBListPtr = randomizer->m_Seed->m_RawRGBTable; uint8_t* lanternColor = reinterpret_cast(&rawRGBListPtr->lanternColor); - color1->r = lanternColor[0]; - color1->g = lanternColor[1]; - color1->b = lanternColor[2]; - color2->r = lanternColor[0]; - color2->g = lanternColor[1]; - color2->b = lanternColor[2]; + + if (*reinterpret_cast(lanternColor) != 0x502814ff) // Don't set the value if it is already vanilla + { + color1->r = lanternColor[0]; + color1->g = lanternColor[1]; + color1->b = lanternColor[2]; + color2->r = lanternColor[0]; + color2->g = lanternColor[1]; + color2->b = lanternColor[2]; + } } libtp::tp::d_pane_class::setBlackWhite(panePtr, color1, color2); } diff --git a/GameCube/source/game_patch/00_poe.cpp b/GameCube/source/game_patch/00_poe.cpp index 3f592563..0312d79f 100644 --- a/GameCube/source/game_patch/00_poe.cpp +++ b/GameCube/source/game_patch/00_poe.cpp @@ -6,6 +6,16 @@ namespace mod::game_patch { KEEP_FUNC void _00_handle_poeItem() { - libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.player.player_collect.poe_count++; + uint8_t* poeCountPtr = &libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.player.player_collect.poe_count; + + // Do not increment the poe count if it is already at 60 + const uint32_t currentPoeCount = *poeCountPtr; + if (currentPoeCount >= 60) + { + return; + } + + // Increment the poe count + *poeCountPtr = static_cast(currentPoeCount + 1); } } // namespace mod::game_patch \ No newline at end of file diff --git a/GameCube/source/game_patch/01_getLayerNo.cpp b/GameCube/source/game_patch/01_getLayerNo.cpp index befab54c..840632bc 100644 --- a/GameCube/source/game_patch/01_getLayerNo.cpp +++ b/GameCube/source/game_patch/01_getLayerNo.cpp @@ -59,7 +59,7 @@ namespace mod::game_patch case stage::StageIDs::Snowpeak_Ruins: { condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(SNOWPEAK_RUINS_CLEARED); // Snowpeak Ruins Completed + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(SNOWPEAK_RUINS_CLEARED); // Snowpeak Ruins Completed if (condition) { @@ -70,7 +70,7 @@ namespace mod::game_patch case stage::StageIDs::Snowpeak: { condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(SNOWPEAK_RUINS_CLEARED); // Snowpeak Ruins Completed + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(SNOWPEAK_RUINS_CLEARED); // Snowpeak Ruins Completed if (condition && (roomId != 0)) { @@ -84,7 +84,7 @@ namespace mod::game_patch { if ((roomId == 5) || (roomId == 6)) // North Faron or Mist Area { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo Saved + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo Saved if (condition) { chosenLayer = stage::FaronStateIDs::Faron_MDH_Completed; @@ -96,11 +96,11 @@ namespace mod::game_patch } else { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo Saved + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo Saved if (condition) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(FOREST_TEMPLE_CLEARED); // Forest Temple Completed + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + FOREST_TEMPLE_CLEARED); // Forest Temple Completed if (condition) { @@ -117,12 +117,13 @@ namespace mod::game_patch case stage::StageIDs::Kakariko_Village: { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(WATCHED_CUTSCENE_AFTER_GORON_MINES); // Cutscene after GM - // Watched + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + WATCHED_CUTSCENE_AFTER_GORON_MINES); // Cutscene after GM Watched + if (condition == false) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(GORON_MINES_CLEARED); // Goron Mines Completed + condition = + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(GORON_MINES_CLEARED); // Goron Mines Completed if (condition == false) { @@ -146,22 +147,23 @@ namespace mod::game_patch } case stage::StageIDs::Kakariko_Graveyard: { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(GOT_ZORA_ARMOR_FROM_RUTELA); // Got Zora Armor from Rutela + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + GOT_ZORA_ARMOR_FROM_RUTELA); // Got Zora Armor from Rutela if (condition == false) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ZORA_ESCORT_CLEARED); // Zora Escort Cleared + condition = + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ZORA_ESCORT_CLEARED); // Zora Escort Cleared if (condition == false) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( - WATCHED_CUTSCENE_AFTER_GORON_MINES); // Cutscene after GM - // Watched + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + WATCHED_CUTSCENE_AFTER_GORON_MINES); // Cutscene after GM Watched + if (condition == false) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(GORON_MINES_CLEARED); // Goron Mines Completed + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + GORON_MINES_CLEARED); // Goron Mines Completed if (condition == false) { @@ -196,8 +198,9 @@ namespace mod::game_patch case stage::StageIDs::Kakariko_Graveyard_Interiors: { - if (((roomId == 1 && (condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(LAKEBED_TEMPLE_CLEARED), - condition != false)))) // Lakebed Completed + if (((roomId == 1 && + (condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(LAKEBED_TEMPLE_CLEARED), + condition != false)))) // Lakebed Completed { chosenLayer = stage::KakarikoInteriorStateIDs::Kakariko_Int_Lakebed_Completed; libtp::tp::d_com_inf_game::dComIfG_get_timelayer(&chosenLayer); @@ -217,6 +220,10 @@ namespace mod::game_patch chosenLayer = stage::KakarikoInteriorStateIDs::Kakariko_Int_Lakebed_Completed; libtp::tp::d_com_inf_game::dComIfG_get_timelayer(&chosenLayer); } + else if (roomId == 3) + { + chosenLayer = stage::KakarikoInteriorStateIDs::Kakariko_Int_KB1_Completed; + } else { chosenLayer = stage::KakarikoInteriorStateIDs::Kakariko_Int_KB1_Completed; @@ -227,7 +234,8 @@ namespace mod::game_patch case stage::StageIDs::Death_Mountain: { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(GORON_MINES_CLEARED); // Goron Mines Completed + condition = + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(GORON_MINES_CLEARED); // Goron Mines Completed if (condition) { @@ -246,12 +254,12 @@ namespace mod::game_patch { if (roomId == 1) // Lanayru Spring { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( LAKEBED_TEMPLE_CLEARED); // Lakebed Temple has been completed if (condition) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( MIDNAS_DESPERATE_HOUR_STARTED); // MDH has been started if (condition == false) @@ -266,11 +274,12 @@ namespace mod::game_patch } else { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(SKY_CANNON_REPAIRED); // Sky Cannon Repaired + condition = + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(SKY_CANNON_REPAIRED); // Sky Cannon Repaired if (condition == false) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( WARPED_SKY_CANNON_TO_LAKE_HYLIA); // Sky Cannon Warped to Lake Hylia if (condition == false) @@ -292,11 +301,11 @@ namespace mod::game_patch case stage::StageIDs::Castle_Town_Interiors: { - if (condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(LAKEBED_TEMPLE_CLEARED), + if (condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(LAKEBED_TEMPLE_CLEARED), condition) // Lakebed Temple Completed { chosenLayer = stage::CastleTownInteriorsStateIDs::Castle_Town_Int_Lakebed_Completed; - if (condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED), + if (condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED), condition) // MDH Completed { chosenLayer = stage::CastleTownInteriorsStateIDs::Castle_Town_Int_Twilight_Cleared; @@ -311,17 +320,18 @@ namespace mod::game_patch case stage::StageIDs::Castle_Town: { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED); // MDH Completed + condition = + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED); // MDH Completed if ((condition == false)) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(LAKEBED_TEMPLE_CLEARED); // Lakebed Temple Completed + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + LAKEBED_TEMPLE_CLEARED); // Lakebed Temple Completed if (condition == false) { if ((roomId == 3) && - (condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ZORA_ESCORT_CLEARED), + (condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ZORA_ESCORT_CLEARED), condition != false)) // Zora Escort Cleared { chosenLayer = stage::CastleTownStateIDs::Castle_Town_Finished_Zora_Escort; @@ -353,7 +363,7 @@ namespace mod::game_patch case stage::StageIDs::Zoras_Domain: { condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(SNOWPEAK_RUINS_CLEARED); // Snowpeak Ruins Completed + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(SNOWPEAK_RUINS_CLEARED); // Snowpeak Ruins Completed if (condition != false) { @@ -364,7 +374,7 @@ namespace mod::game_patch case stage::StageIDs::Upper_Zoras_River: { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(IZA_1_MINIGAME_UNLOCKED); // Iza 1 Unlocked + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(IZA_1_MINIGAME_UNLOCKED); // Iza 1 Unlocked if (condition != false) { chosenLayer = stage::UpperZorasRiverStateIDs::Upper_Zoras_River_Iza_1_Started; @@ -376,8 +386,8 @@ namespace mod::game_patch { chosenLayer = stage::GerudoDesertStateIDs::Desert_Entrance_Cutscene_Not_Watched; - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(VISITED_DESERT_FOR_THE_FIRST_TIME); // Have been to desert + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + VISITED_DESERT_FOR_THE_FIRST_TIME); // Have been to desert if (condition != false) { @@ -388,12 +398,13 @@ namespace mod::game_patch case stage::StageIDs::Zoras_River: { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(IZA_1_MINIGAME_DONE); // Iza 1 Minigame Completed + condition = + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(IZA_1_MINIGAME_DONE); // Iza 1 Minigame Completed if (condition == false) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(STARTED_IZA_1_MINIGAME); // Iza 1 Minigame Started + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + STARTED_IZA_1_MINIGAME); // Iza 1 Minigame Started if (condition != false) { @@ -411,15 +422,16 @@ namespace mod::game_patch { if (roomId == 0) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ORDON_DAY_1_FINISHED); // Ordon Day 1 done + condition = + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ORDON_DAY_1_FINISHED); // Ordon Day 1 done if (condition) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo Saved + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo Saved if (condition) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(FINISHED_SEWERS); // First trip to Sewers done + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + FINISHED_SEWERS); // First trip to Sewers done if (condition) { @@ -459,14 +471,15 @@ namespace mod::game_patch { if (roomId == 1) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ORDON_DAY_1_FINISHED); // Ordon Day 1 done + condition = + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ORDON_DAY_1_FINISHED); // Ordon Day 1 done if (condition) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo Saved + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo Saved if (condition) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( FINISHED_SEWERS); // First trip to Sewers done if (condition) @@ -505,7 +518,7 @@ namespace mod::game_patch /* not used in randomizer anymore. keeping for documentation sake if ( roomId == 1 ) // Sera's Shop { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( BOUGHT_SLINGSHOT_FROM_SERA ); // Bought slinghot from Sera if ( condition ) @@ -518,8 +531,8 @@ namespace mod::game_patch darkIsClear = libtp::tp::d_save::isDarkClearLV(playerStatusBPtr, 0); if (darkIsClear == false) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(FINISHED_SEWERS); // First Trip to Sewers done + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + FINISHED_SEWERS); // First Trip to Sewers done if (condition != false) { @@ -551,16 +564,16 @@ namespace mod::game_patch { if (roomId == 1) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( TALO_CHASES_MONKEY); // Sword training done on Ordon Day 2 if (condition) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo saved + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo saved if (condition) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(FINISHED_SEWERS); // First trip to Sewers done + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + FINISHED_SEWERS); // First trip to Sewers done if (condition) { @@ -594,19 +607,19 @@ namespace mod::game_patch case stage::StageIDs::Ordon_Ranch: { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ORDON_DAY_1_FINISHED); // Day 1 done + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ORDON_DAY_1_FINISHED); // Day 1 done if (condition) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo Saved + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo Saved if (condition) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( WATCHED_CUTSCENE_AFTER_GOATS_2); // Saw CS after Goats 2 done if (condition) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(FINISHED_SEWERS); // First trip to Sewers done + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + FINISHED_SEWERS); // First trip to Sewers done if (condition) { @@ -623,7 +636,7 @@ namespace mod::game_patch } else { - chosenLayer = stage::OrdonRanchStateIDs::Ordon_Ranch_Goats_2_Completed; + chosenLayer = stage::OrdonRanchStateIDs::Ordon_Ranch_Faron_Twilight_Cleared; } } else @@ -633,7 +646,7 @@ namespace mod::game_patch } else { - chosenLayer = stage::OrdonRanchStateIDs::Ordon_Ranch_Goats_1_Completed; + chosenLayer = stage::OrdonRanchStateIDs::Ordon_Ranch_Faron_Twilight_Cleared; } } else @@ -648,13 +661,13 @@ namespace mod::game_patch if (libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.player.player_status_b .dark_clear_level_flag >= 0x7) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_STARTED); // MDH State Activated + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + MIDNAS_DESPERATE_HOUR_STARTED); // MDH State Activated if (condition) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED); // MDH Completed + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + MIDNAS_DESPERATE_HOUR_COMPLETED); // MDH Completed if (condition) { @@ -681,12 +694,12 @@ namespace mod::game_patch { if (roomId == 8) { - condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED); // MDH Completed + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( + MIDNAS_DESPERATE_HOUR_COMPLETED); // MDH Completed if (condition == false) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( MIDNAS_DESPERATE_HOUR_STARTED); // MDH State Activated if (condition != false) @@ -703,21 +716,22 @@ namespace mod::game_patch { if (roomId == 0x10) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(GOT_WOOD_STATUE); // Wooden Statue Gotten + condition = + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(GOT_WOOD_STATUE); // Wooden Statue Gotten if (condition == false) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( TALKED_TO_LOUISE_ABOUT_THE_STOLEN_STATUE); // Talked to Louise after Medicine Scent if (condition == false) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( MIDNAS_DESPERATE_HOUR_COMPLETED); // MDH Completed if (condition == false) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( MIDNAS_DESPERATE_HOUR_STARTED); // MDH State Activated if (condition != false) @@ -750,12 +764,12 @@ namespace mod::game_patch { if (roomId == 0x11) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( MIDNAS_DESPERATE_HOUR_COMPLETED); // MDH Completed if (condition == false) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( MIDNAS_DESPERATE_HOUR_STARTED); // MDH State Activated if (condition != false) @@ -775,7 +789,8 @@ namespace mod::game_patch case stage::StageIDs::Hidden_Village: { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(GAVE_ILIA_HER_CHARM); // Ilia shown Ilia's Charm + condition = + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(GAVE_ILIA_HER_CHARM); // Ilia shown Ilia's Charm if (condition != false) { @@ -789,11 +804,11 @@ namespace mod::game_patch if (roomId == 5) { chosenLayer = stage::CastleTownShopsStateIDs::Castle_Town_Int_Jovani_MDH_Completed; - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_STARTED); + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_STARTED); if (condition) { chosenLayer = stage::CastleTownShopsStateIDs::Castle_Town_Int_Jovani_New_Game; - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED); + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED); if (condition) { chosenLayer = stage::CastleTownShopsStateIDs::Castle_Town_Int_Jovani_MDH_Completed; @@ -802,7 +817,7 @@ namespace mod::game_patch } else { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( MALO_MART_CASTLE_TOWN_BRANCH_IS_OPEN); // CT Shop is Malo Mart if (condition != false) @@ -821,7 +836,7 @@ namespace mod::game_patch case stage::StageIDs::Bulblin_Camp: { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( ESCAPED_BURNING_TENT_IN_BULBLIN_CAMP); // Escaped Burning Tent in Bulblin Camp uint8_t* memoryFlagsPtr = @@ -853,7 +868,7 @@ namespace mod::game_patch case stage::StageIDs::Faron_Woods_Cave: { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo saved + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(ORDON_DAY_2_OVER); // Talo saved if (condition != false) { chosenLayer = stage::FaronWoodsCaveStateIDs::Faron_Woods_Cave_Talo_Rescued; @@ -863,7 +878,7 @@ namespace mod::game_patch case stage::StageIDs::Hyrule_Castle_Sewers: { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(FINISHED_SEWERS); // Sewers Finished + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(FINISHED_SEWERS); // Sewers Finished if (condition) { chosenLayer = stage::SewersStateIDs::Sewers_Midna_On_Back; @@ -925,7 +940,7 @@ namespace mod::game_patch if (chosenLayer == stage::TwilightStateIDs::Default_Twilight_State) { condition = - libtp::tp::d_a_alink::dComIfGs_isEventBit(WARPED_METEOR_TO_ZORAS_DOMAIN); // Warped meteor to Zora's Domain + libtp::tp::d_com_inf_game::dComIfGs_isEventBit(WARPED_METEOR_TO_ZORAS_DOMAIN); // Warped meteor to Zora's Domain switch (stageID) { @@ -955,7 +970,7 @@ namespace mod::game_patch case stage::StageIDs::Hyrule_Castle_Sewers: { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit( + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit( WATCHED_CUTSCENE_AFTER_BEING_CAPTURED_IN_FARON_TWILIGHT); // Watched CS after being captured in // Faron Twilight if (condition == false) @@ -969,7 +984,7 @@ namespace mod::game_patch { if (roomId == 10) { - condition = libtp::tp::d_a_alink::dComIfGs_isEventBit(PALACE_OF_TWILIGHT_CLEARED); // Zant Defeated + condition = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(PALACE_OF_TWILIGHT_CLEARED); // Zant Defeated if (condition == false) { diff --git a/GameCube/source/game_patch/02_modifyItemData.cpp b/GameCube/source/game_patch/02_modifyItemData.cpp index 9b69127d..90ac5fc1 100644 --- a/GameCube/source/game_patch/02_modifyItemData.cpp +++ b/GameCube/source/game_patch/02_modifyItemData.cpp @@ -458,8 +458,8 @@ namespace mod::game_patch KEEP_FUNC void _02_ordonPumpkinItemFunc() { - events::setSaveFileEventFlag(libtp::data::flags::TOLD_YETA_ABOUT_PUMPKIN); // Told Yeta about Pumpkin - events::setSaveFileEventFlag(libtp::data::flags::PUMPKIN_PUT_IN_SOUP); // Yeto put Pumpkin in soup + events::setSaveFileEventFlag(libtp::data::flags::TOLD_YETA_ABOUT_PUMPKIN); // Told Yeta about Pumpkin + events::setSaveFileEventFlag(libtp::data::flags::PUMPKIN_PUT_IN_SOUP); // Yeto put Pumpkin in soup events::setSaveFileEventFlag(libtp::data::flags::TALKED_WITH_YETA_AFTER_GIVING_PUMPKIN); // SPR Lobby Door Unlocked @@ -474,14 +474,14 @@ namespace mod::game_patch } else { - savePtr->save_file.area_flags[0x14].temp_flags.memoryFlags[0x9] |= 0x4; + savePtr->save_file.mSave[0x14].temp_flags.memoryFlags[0x9] |= 0x4; } } KEEP_FUNC void _02_ordonGoatCheeseItemFunc() { - events::setSaveFileEventFlag(libtp::data::flags::TOLD_YETA_ABOUT_CHEESE); // Told Yeta about Cheese - events::setSaveFileEventFlag(libtp::data::flags::CHEESE_PUT_IN_SOUP); // Yeto put cheese in soup + events::setSaveFileEventFlag(libtp::data::flags::TOLD_YETA_ABOUT_CHEESE); // Told Yeta about Cheese + events::setSaveFileEventFlag(libtp::data::flags::CHEESE_PUT_IN_SOUP); // Yeto put cheese in soup events::setSaveFileEventFlag(libtp::data::flags::TALKED_WITH_YETA_AFTER_GIVING_CHEESE); // SPR Lobby West Door Unlocked @@ -496,7 +496,7 @@ namespace mod::game_patch } else { - savePtr->save_file.area_flags[0x14].temp_flags.memoryFlags[0x9] |= 0x8; + savePtr->save_file.mSave[0x14].temp_flags.memoryFlags[0x9] |= 0x8; } } @@ -567,7 +567,7 @@ namespace mod::game_patch else { libtp::tp::d_save::dSv_memBit_c* tempFlagsPtr = - &libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.area_flags[0x3].temp_flags; + &libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.mSave[0x3].temp_flags; libtp::tp::d_save::onSwitch_dSv_memBit(tempFlagsPtr, 0x69); libtp::tp::d_save::onSwitch_dSv_memBit(tempFlagsPtr, 0x65); @@ -594,23 +594,32 @@ namespace mod::game_patch libtp::tp::d_save::onCollectCrystal(&libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.player.player_collect, '\x02'); - rando::Randomizer* rando = randomizer; - if (randoIsEnabled(rando)) + // Make sure the randomizer is loaded/enabled and a seed is loaded + rando::Seed* seedPtr; + if (seedPtr = getCurrentSeed(randomizer), !seedPtr) { - rando::Header* headerPtr = rando->m_Seed->m_Header; + return; + } - // If the player has the castle requirement set to Fused Shadows. - if (headerPtr->castleRequirements == 1) - { - events::setSaveFileEventFlag(libtp::data::flags::BARRIER_GONE); - } + rando::Header* headerPtr = seedPtr->m_Header; - // If the player has the palace requirement set to Fused Shadows. - if (headerPtr->palaceRequirements == 1) - { - events::setSaveFileEventFlag(libtp::data::flags::FIXED_THE_MIRROR_OF_TWILIGHT); - } + // If the player has the castle requirement set to Fused Shadows. + if (headerPtr->castleRequirements == rando::CastleEntryRequirements::HC_Fused_Shadows) + { + events::setSaveFileEventFlag(libtp::data::flags::BARRIER_GONE); } + + // If the player has the palace requirement set to Fused Shadows. + if (headerPtr->palaceRequirements == rando::PalaceEntryRequirements::PoT_Fused_Shadows) + { + events::setSaveFileEventFlag(libtp::data::flags::FIXED_THE_MIRROR_OF_TWILIGHT); + } + } + + KEEP_FUNC void _02_firstMirrorShardItemFunc() + { + libtp::tp::d_save::onCollectMirror(&libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.player.player_collect, + '\0'); } KEEP_FUNC void _02_secondMirrorShardItemFunc() @@ -633,21 +642,24 @@ namespace mod::game_patch libtp::tp::d_save::onCollectMirror(&libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file.player.player_collect, '\x03'); - rando::Randomizer* rando = randomizer; - if (randoIsEnabled(rando)) + // Make sure the randomizer is loaded/enabled and a seed is loaded + rando::Seed* seedPtr; + if (seedPtr = getCurrentSeed(randomizer), !seedPtr) { - rando::Header* headerPtr = rando->m_Seed->m_Header; + return; + } - // If the player has the castle requirement set to Mirror Shards. - if (headerPtr->castleRequirements == 2) - { - events::setSaveFileEventFlag(libtp::data::flags::BARRIER_GONE); - } - // If the player has the palace requirement set to Mirror Shards. - if (headerPtr->palaceRequirements == 2) - { - events::setSaveFileEventFlag(libtp::data::flags::FIXED_THE_MIRROR_OF_TWILIGHT); - } + rando::Header* headerPtr = seedPtr->m_Header; + + // If the player has the castle requirement set to Mirror Shards. + if (headerPtr->castleRequirements == rando::CastleEntryRequirements::HC_Mirror_Shards) + { + events::setSaveFileEventFlag(libtp::data::flags::BARRIER_GONE); + } + // If the player has the palace requirement set to Mirror Shards. + if (headerPtr->palaceRequirements == rando::PalaceEntryRequirements::PoT_Mirror_Shards) + { + events::setSaveFileEventFlag(libtp::data::flags::FIXED_THE_MIRROR_OF_TWILIGHT); } } @@ -778,6 +790,12 @@ namespace mod::game_patch return static_cast(result); } + KEEP_FUNC int32_t _02_firstMirrorShardItemGetCheck() + { + bool result = libtp::tp::d_com_inf_game::dComIfGs_isItemFirstBit(rando::customItems::Mirror_Piece_1); + return static_cast(result); + } + KEEP_FUNC int32_t _02_secondMirrorShardItemGetCheck() { bool result = libtp::tp::d_com_inf_game::dComIfGs_isItemFirstBit(libtp::data::items::Mirror_Piece_2); diff --git a/GameCube/source/game_patch/04_verifyItemFunctions.cpp b/GameCube/source/game_patch/04_verifyItemFunctions.cpp index 835d438d..a1d3720e 100644 --- a/GameCube/source/game_patch/04_verifyItemFunctions.cpp +++ b/GameCube/source/game_patch/04_verifyItemFunctions.cpp @@ -117,8 +117,9 @@ namespace mod::game_patch uint32_t _04_getProgressiveMirrorShard() { using namespace libtp::data::items; + using namespace rando::customItems; - static const uint8_t progressiveMirrorShardsList[] {Mirror_Piece_2, Mirror_Piece_3, Mirror_Piece_4}; + static const uint8_t progressiveMirrorShardsList[] {Mirror_Piece_1, Mirror_Piece_2, Mirror_Piece_3, Mirror_Piece_4}; constexpr uint32_t listLength = sizeof(progressiveMirrorShardsList) / sizeof(progressiveMirrorShardsList[0]); for (uint32_t i = 0; i < listLength; i++) @@ -268,6 +269,7 @@ namespace mod::game_patch break; } + case Mirror_Piece_1: case Mirror_Piece_2: case Mirror_Piece_3: case Mirror_Piece_4: diff --git a/GameCube/source/game_patch/05_itemMsgFunctions.cpp b/GameCube/source/game_patch/05_itemMsgFunctions.cpp index c15eebe5..72241c41 100644 --- a/GameCube/source/game_patch/05_itemMsgFunctions.cpp +++ b/GameCube/source/game_patch/05_itemMsgFunctions.cpp @@ -1,7 +1,7 @@ #include "game_patch/game_patch.h" #include "data/items.h" #include "data/stages.h" -#include "gc_wii/bmgres.h" +#include "tp/bmgres.h" #include "main.h" #include "tp/control.h" #include "tp/d_a_alink.h" @@ -643,11 +643,7 @@ namespace mod::game_patch return _05_getMsgById(msgId); } - void _05_setCustomItemMessage(libtp::tp::control::TControl* control, - const void* TProcessor, - uint16_t unk3, - uint16_t msgId, - rando::Randomizer* randomizer) + void _05_setCustomItemMessage(libtp::tp::control::TControl* control, const void* TProcessor, uint16_t unk3, uint16_t msgId) { using namespace libtp::data::stage; using namespace libtp::data::items; @@ -663,29 +659,6 @@ namespace mod::game_patch } }; - auto checkForSpecificMsg = - [=](uint32_t desiredMsgId, int32_t room, const char* stage, const void* currentInf1, const char* desiredFile) - { - // Check if the message ids are the same - if (msgId != desiredMsgId) - { - return false; - } - - // Check if the stage and room are correct - if (!libtp::tools::playerIsInRoomStage(room, stage)) - { - return false; - } - - // Check if the desired file is being used - return currentInf1 == getInf1Ptr(desiredFile); - }; - - // Get message ids for specific checks - constexpr uint32_t linkHouseMsgId = 0x658; - constexpr uint32_t charloDonationMsgId = 0x355; - // Get a pointer to the current BMG file being used // The pointer is to INF1 const void* unk = libtp::tp::processor::getResource_groupID(TProcessor, unk3); @@ -695,8 +668,6 @@ namespace mod::game_patch } const void* currentInf1 = *reinterpret_cast(reinterpret_cast(unk) + 0xC); - rando::Seed* seed; - // Most text replacements are for zel_00.bmg, so check that first if (currentInf1 == getZel00BmgInf()) { @@ -718,25 +689,22 @@ namespace mod::game_patch } } - const char* newMessage = getCustomMessage(msgId); + const char* newMessage; + if (msgId == 0x1369) // The custom message ID used for hints on custom signs + { + newMessage = _05_getSpecialMsgById(msgId); + } + else + { + newMessage = getCustomMessage(msgId); + } + setMessageText(newMessage); return; } - else if (checkForSpecificMsg(charloDonationMsgId, 2, allStages[StageIDs::Castle_Town], currentInf1, "zel_04.bmg")) - { - setMessageText(m_DonationText); - return; - } - // Make sure the randomizer is loaded/enabled and a seed is loaded for seed-specific checks - else if (seed = getCurrentSeed(randomizer), seed) - { - if (checkForSpecificMsg(linkHouseMsgId, 1, allStages[StageIDs::Ordon_Village], currentInf1, "zel_01.bmg")) - { - setMessageText(seed->m_RequiredDungeons); - return; - } - } + // If the msg we are looking at is not in the zel_00.bmg, it may be a special case (hint, etc.) + setMessageText(_05_getSpecialMsgById(msgId)); } uint32_t _05_getCustomMsgColor(uint8_t colorId) @@ -850,4 +818,62 @@ namespace mod::game_patch // Didn't find msgId return nullptr; } + + const char* _05_getSpecialMsgById(uint32_t msgId) + { + using namespace rando; + + // Make sure the hints text is loaded + const uint32_t hintMsgTableInfoRaw = reinterpret_cast(m_HintMsgTableInfo); + if (!hintMsgTableInfoRaw) + { + return nullptr; + } + + // Get some variables now to avoid storing extra stuff on the stack, since a function call is necessary to get one of + // the variables + const libtp::tp::d_stage::dStage_startStage* startStagePtr = + &libtp::tp::d_com_inf_game::dComIfG_gameInfo.play.mStartStage; + + const char* currentStage = startStagePtr->mStage; + const int32_t currentRoom = libtp::tools::getCurrentRoomNo(); + const int32_t stageIDX = libtp::tools::getStageIndex(currentStage); + + // Get the total size of the message ids + const uint32_t hintTotalMessages = m_TotalHintMsgEntries; + uint32_t msgIdTableSize = hintTotalMessages * sizeof(CustomMessageData); + + // Round msgIdTableSize up to the size of the offset type to make sure the offsets are properly aligned + msgIdTableSize = (msgIdTableSize + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1); + + // Get a pointer to the message offsets + const uint32_t* hintMsgOffsets = reinterpret_cast(hintMsgTableInfoRaw + msgIdTableSize); + + // Get the total size of the message offsets + const uint32_t hintMsgOffsetTableSize = hintTotalMessages * sizeof(uint32_t); + + // Get a pointer to the messages + const char* hintMessages = reinterpret_cast(hintMsgTableInfoRaw + msgIdTableSize + hintMsgOffsetTableSize); + + // Get a pointer to the message data to search for + const CustomMessageData* msgData = reinterpret_cast(hintMsgTableInfoRaw); + + // Get the custom message + for (uint32_t i = 0; i < hintTotalMessages; i++) + { + const CustomMessageData* currentMsgData = &msgData[i]; + + if (currentMsgData->msgID == msgId) + { + if (((stageIDX == currentMsgData->stageIDX) && (currentRoom == currentMsgData->roomIDX)) || + (currentMsgData->stageIDX == 0xFF)) + { + return &hintMessages[hintMsgOffsets[i]]; + } + } + } + + // Didn't find msgId + return nullptr; + } } // namespace mod::game_patch \ No newline at end of file diff --git a/GameCube/source/game_patch/07_checkPlayerStageReturn.cpp b/GameCube/source/game_patch/07_checkPlayerStageReturn.cpp index 7d905d93..e2e55755 100644 --- a/GameCube/source/game_patch/07_checkPlayerStageReturn.cpp +++ b/GameCube/source/game_patch/07_checkPlayerStageReturn.cpp @@ -50,7 +50,10 @@ namespace mod::game_patch playerReturnPlacePtr->link_room_id = 0x6; } } - else if (libtp::tp::d_a_alink::checkStageName(stagesPtr[stage::StageIDs::Sacred_Grove])) + + // If for some reason we find ourselves outside Sacred Grove and cannot transform/warp, we want the player to be able to + // save warp to Faron. This is mostly usefull for Glitched Logic. + else if (libtp::tools::playerIsInRoomStage(6, stagesPtr[stage::StageIDs::Faron_Woods])) { if (!events::haveItem(items::Shadow_Crystal)) { @@ -62,7 +65,7 @@ namespace mod::game_patch playerReturnPlacePtr->link_room_id = 0x6; } } - else if (libtp::tp::d_a_alink::checkStageName(stagesPtr[stage::StageIDs::Fyrus])) + else if (libtp::tp::d_a_alink::checkStageName(stagesPtr[stage::StageIDs::Fyrus])) { strncpy(playerReturnPlacePtr->link_current_stage, stagesPtr[stage::StageIDs::Goron_Mines], diff --git a/GameCube/source/item_wheel_menu.cpp b/GameCube/source/item_wheel_menu.cpp index 43e2bd2c..a08bc230 100644 --- a/GameCube/source/item_wheel_menu.cpp +++ b/GameCube/source/item_wheel_menu.cpp @@ -86,6 +86,10 @@ namespace mod::item_wheel_menu // Hardcode false since the ring isn't being drawn anymore setHUDButtonsAlpha(false); + // If the item wheel is being closed, we also want to close the menu. This way, if the player forgets to close it or + // cannot remember how, closing the item wheel will also close the menu. + displayMenu = false; + // dMenuRing__delete is an empty function, so don't need to call the original function } @@ -243,7 +247,7 @@ namespace mod::item_wheel_menu } } - for (uint32_t b = 4; b < 7; b++) + for (uint32_t b = 4; b < 8; b++) { if ((collectedShards << b) & 0x80) { @@ -251,7 +255,7 @@ namespace mod::item_wheel_menu } } - snprintf(buf, sizeof(buf), "%" PRIu32 "/3\n%" PRIu32 "/3", shadowsCount, shardsCount); + snprintf(buf, sizeof(buf), "%" PRIu32 "/3\n%" PRIu32 "/4", shadowsCount, shardsCount); // Draw the counts for the fused shadows and mirror shards const int32_t shadowsAndShardsCountsPosXOffset = shadowsAndShardsMainPosXOffset + offsets->shadowsShardsOffset; @@ -270,7 +274,7 @@ namespace mod::item_wheel_menu events::drawText(strings->pumpkin, ringPosX + pumpkinPosXOffset, ringPosY + pumpkinPosYOffset, mainTextColor, textSize); // Get the offset for the pumpkin value - const bool hasPumpkin = libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::TOLD_YETA_ABOUT_PUMPKIN); + const bool hasPumpkin = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::TOLD_YETA_ABOUT_PUMPKIN); uint32_t pumpkinValueOffset; if (hasPumpkin) @@ -295,7 +299,7 @@ namespace mod::item_wheel_menu events::drawText(strings->cheese, ringPosX + cheesePosXOffset, ringPosY + cheesePosYOffset, mainTextColor, textSize); // Get the offset for the cheese value - const bool hasCheese = libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::TOLD_YETA_ABOUT_CHEESE); + const bool hasCheese = libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::TOLD_YETA_ABOUT_CHEESE); uint32_t cheeseValueOffset; if (hasCheese) diff --git a/GameCube/source/main.cpp b/GameCube/source/main.cpp index 8c8fb485..67321c0e 100644 --- a/GameCube/source/main.cpp +++ b/GameCube/source/main.cpp @@ -31,6 +31,7 @@ #include "tp/f_op_actor_mng.h" #include "tp/f_op_actor.h" #include "tp/f_op_scene_req.h" +#include "tp/f_op_msg_mng.h" #include "tp/f_pc_node_req.h" #include "tp/m_do_controller_pad.h" #include "tp/m_do_audio.h" @@ -50,6 +51,9 @@ #include "tp/d_kankyo.h" #include "rando/customItems.h" #include "cxx.h" +#include "tp/f_pc_executor.h" +#include "tp/d_msg_flow.h" +#include "tp/d_file_select.h" #ifdef TP_EU #include "tp/d_s_logo.h" @@ -65,16 +69,17 @@ namespace mod // Variables void* z2ScenePtr = nullptr; uint32_t randState = 0; - KEEP_VAR const char* m_DonationText = nullptr; // Analog L is currently not being used, so commented out // float prevFrameAnalogL = 0.f; float prevFrameAnalogR = 0.f; KEEP_VAR uint8_t* m_MsgTableInfo = nullptr; + KEEP_VAR uint8_t* m_HintMsgTableInfo = nullptr; libtp::tp::J2DPicture::J2DPicture* bgWindow = nullptr; uint16_t lastButtonInput = 0; KEEP_VAR uint16_t m_TotalMsgEntries = 0; + KEEP_VAR uint16_t m_TotalHintMsgEntries = 0; bool roomReloadingState = false; bool consoleState = true; uint8_t gameState = GAME_BOOT; @@ -86,6 +91,7 @@ namespace mod bool transformAnywhereEnabled = false; uint8_t damageMultiplier = 1; bool bonksDoDamage = false; + EventItemStatus giveItemToPlayer = QUEUE_EMPTY; #ifdef TP_EU KEEP_VAR libtp::tp::d_s_logo::Languages currentLanguage = libtp::tp::d_s_logo::Languages::uk; @@ -124,19 +130,17 @@ namespace mod int32_t num, void* raw_data) = nullptr; - /* - KEEP_VAR void ( *return_dComIfGp_setNextStage )( const char* stage, - int16_t point, - int8_t roomNo, - int8_t layer, - float lastSpeed, - uint32_t lastMode, - int32_t setPoint, - int8_t wipe, - int16_t lastAngle, - int32_t param_9, - int32_t wipSpeedT ) = nullptr; - */ + KEEP_VAR void (*return_dComIfGp_setNextStage)(const char* stage, + int16_t point, + int8_t roomNo, + int8_t layer, + float lastSpeed, + uint32_t lastMode, + int32_t setPoint, + int8_t wipe, + int16_t lastAngle, + int32_t param_9, + int32_t wipSpeedT) = nullptr; // GetLayerNo trampoline KEEP_VAR int32_t (*return_getLayerNo_common_common)(const char* stageName, int32_t roomId, int32_t layerOverride) = nullptr; @@ -192,6 +196,7 @@ namespace mod KEEP_VAR uint32_t (*return_getFontCCColorTable)(uint8_t colorId, uint8_t unk) = nullptr; KEEP_VAR uint32_t (*return_getFontGCColorTable)(uint8_t colorId, uint8_t unk) = nullptr; + KEEP_VAR void (*return_jmessage_tSequenceProcessor__do_begin)(void* seqProcessor, const void* unk2, const char* text) = nullptr; @@ -202,8 +207,10 @@ namespace mod uint32_t unk4) = nullptr; // Query/Event functions. + KEEP_VAR int32_t (*return_query001)(void* unk1, void* unk2, int32_t unk3) = nullptr; KEEP_VAR int32_t (*return_query022)(void* unk1, void* unk2, int32_t unk3) = nullptr; KEEP_VAR int32_t (*return_query023)(void* unk1, void* unk2, int32_t unk3) = nullptr; + KEEP_VAR int32_t (*return_query025)(void* unk1, void* unk2, int32_t unk3) = nullptr; KEEP_VAR uint8_t (*return_checkEmptyBottle)(libtp::tp::d_save::dSv_player_item_c* playerItem) = nullptr; KEEP_VAR int32_t (*return_query042)(void* unk1, void* unk2, int32_t unk3) = nullptr; KEEP_VAR int32_t (*return_query004)(void* unk1, void* unk2, int32_t unk3) = nullptr; @@ -213,6 +220,15 @@ namespace mod KEEP_VAR int32_t (*return_event017)(void* messageFlow, void* nodeEvent, void* actrPtr) = nullptr; KEEP_VAR int32_t (*return_event003)(void* messageFlow, void* nodeEvent, void* actrPtr) = nullptr; + KEEP_VAR int32_t (*return_doFlow)(libtp::tp::d_msg_flow::dMsgFlow* msgFlow, + libtp::tp::f_op_actor::fopAc_ac_c* actrPtr, + libtp::tp::f_op_actor::fopAc_ac_c** actrValue, + int32_t i_flow) = nullptr; + + KEEP_VAR int32_t (*return_setNormalMsg)(libtp::tp::d_msg_flow::dMsgFlow* msgFlow, + void* flowNode, + libtp::tp::f_op_actor::fopAc_ac_c* actrPtr) = nullptr; + // Save flag functions KEEP_VAR bool (*return_isDungeonItem)(libtp::tp::d_save::dSv_memBit_c* memBitPtr, const int32_t memBit) = nullptr; KEEP_VAR void (*return_onDungeonItem)(libtp::tp::d_save::dSv_memBit_c* memBitPtr, const int32_t memBit) = nullptr; @@ -236,13 +252,17 @@ namespace mod KEEP_VAR bool (*return_procWolfAttackReverseInit)(libtp::tp::d_a_alink::daAlink* daALink) = nullptr; KEEP_VAR bool (*return_procWolfDashReverseInit)(libtp::tp::d_a_alink::daAlink* daALink, bool param_1) = nullptr; KEEP_VAR libtp::tp::f_op_actor::fopAc_ac_c* (*return_searchBouDoor)(libtp::tp::f_op_actor::fopAc_ac_c* actrPtr) = nullptr; + KEEP_VAR float (*return_damageMagnification)(libtp::tp::d_a_alink::daAlink* daALink, int32_t param_1, int32_t param_2) = nullptr; + KEEP_VAR bool (*return_checkCastleTownUseItem)(uint16_t item_id) = nullptr; + KEEP_VAR int32_t (*return_procCoGetItemInit)(libtp::tp::d_a_alink::daAlink* linkActrPtr) = nullptr; // Audio functions KEEP_VAR void (*return_loadSeWave)(void* Z2SceneMgr, uint32_t waveID) = nullptr; + KEEP_VAR void (*return_sceneChange)(libtp::z2audiolib::z2scenemgr::Z2SceneMgr* sceneMgr, libtp::z2audiolib::z2scenemgr::JAISoundID BGMid, uint8_t SeWave1, @@ -251,11 +271,14 @@ namespace mod uint8_t BgmWave2, uint8_t DemoWave, bool param_7) = nullptr; + KEEP_VAR void (*return_startSound)(void* soungMgr, libtp::z2audiolib::z2scenemgr::JAISoundID soundId, void* soundHandle, void* pos) = nullptr; + KEEP_VAR bool (*return_checkBgmIDPlaying)(libtp::z2audiolib::z2seqmgr::Z2SeqMgr* seqMgr, uint32_t sfx_id) = nullptr; + // Title Screen functions KEEP_VAR void* (*return_dScnLogo_c_dt)(void* dScnLogo_c, int16_t bFreeThis) = nullptr; @@ -263,12 +286,24 @@ namespace mod KEEP_VAR libtp::tp::d_resource::dRes_info_c* (*return_getResInfo)(const char* arcName, libtp::tp::d_resource::dRes_info_c* objectInfo, int32_t size) = nullptr; + KEEP_VAR bool (*return_mountArchive__execute)(libtp::tp::m_Do_dvd_thread::mDoDvdThd_mountArchive_c* mountArchive) = nullptr; // d_meter functions KEEP_VAR void (*return_resetMiniGameItem)(libtp::tp::d_meter2_info::G_Meter2_Info* gMeter2InfoPtr, bool minigameFlag) = nullptr; + // Game Over functions + KEEP_VAR void (*return_dispWait_init)(libtp::tp::d_gameover::dGameOver* ptr) = nullptr; + + // Shop Functions + KEEP_VAR int32_t (*return_seq_decide_yes)(libtp::tp::d_shop_system::dShopSystem* shopPtr, + libtp::tp::f_op_actor::fopAc_ac_c* actor, + void* msgFlow) = nullptr; + + // Title Screen functions + KEEP_VAR void (*return_dFile_select_c___create)(libtp::tp::d_file_select::dFile_select_c* thisPtr) = nullptr; + void main() { // do_link needs to be hooked immediately, as otherwise we may not be able to modify f_pc_profile_lst.rel, which gets @@ -458,8 +493,7 @@ namespace mod } getConsole().setLine(CONSOLE_PROTECTED_LINES - 1); - getConsole() << "\r" - << "Press X/Y to select a seed\n" + getConsole() << "\r" << "Press X/Y to select a seed\n" << "Press R + Z to close the console\n" << "[" << static_cast(selectedSeed) + 1 << "/" << static_cast(numSeeds) << "] Seed: " << seedList->m_minSeedInfo[selectedSeed].fileName << "\n"; @@ -481,7 +515,6 @@ namespace mod drawHeapDebugInfo(); #undef DRAW_DEBUG_HEAP_INFO #endif - // New frame, so the ring will be redrawn item_wheel_menu::ringDrawnThisFrame = false; @@ -499,7 +532,7 @@ namespace mod if (prevState != GAME_ACTIVE && state == 11) { // check whether we're in title screen CS - if (0 != strcmp("S_MV000", gameInfo->play.mNextStage.stageValues.mStage)) + if (0 != strcmp("S_MV000", gameInfo->play.mNextStage.mStage)) { gameState = GAME_ACTIVE; } @@ -555,6 +588,9 @@ namespace mod // Special combo to (de)activate the console should be handled first if (checkBtn(currentButtons, PadInputs::Button_R | PadInputs::Button_Z)) { + // Disable the input that was just pressed, as sometimes it could cause talking to Midna when in-game + padInfo->mPressedButtonFlags = 0; + // Disallow during boot as we print info etc. // Will automatically disappear if there is no seeds to select from setScreen(!consoleState); @@ -583,6 +619,7 @@ namespace mod // Handle generic button checks if (checkButtonCombo(PadInputs::Button_R | PadInputs::Button_Y, true)) { + // Handle transforming events::handleQuickTransform(); } @@ -690,6 +727,7 @@ namespace mod // Custom events bool currentReloadingState; + if (linkMapPtr) { // checkRestartRoom is needed for voiding @@ -725,16 +763,22 @@ namespace mod } } - handleFoolishItem(); - roomReloadingState = currentReloadingState; + handleFoolishItem(); tools::xorshift32(&randState); if (events::timeChange != 0) { events::handleTimeSpeed(); } + + // Giving items at any point + if (linkMapPtr) + { + initGiveItemToPlayer(linkMapPtr); + } + // End of custom events // Call the original function @@ -746,6 +790,89 @@ namespace mod prevFrameAnalogR = padInfo->mTriggerRight; } + void initGiveItemToPlayer(libtp::tp::d_a_alink::daAlink* linkMapPtr) + { + using namespace libtp::tp; + + switch (linkMapPtr->mProcID) + { + case d_a_alink::PROC_WAIT: + case d_a_alink::PROC_TIRED_WAIT: + case d_a_alink::PROC_MOVE: + case d_a_alink::PROC_WOLF_WAIT: + case d_a_alink::PROC_WOLF_TIRED_WAIT: + case d_a_alink::PROC_WOLF_MOVE: + case d_a_alink::PROC_ATN_MOVE: + case d_a_alink::PROC_WOLF_ATN_AC_MOVE: + { + // Check if link is currently in a cutscene + if (d_a_alink::checkEventRun(linkMapPtr)) + { + break; + } + + // Ensure that link is not currently in a message-based event. + if (linkMapPtr->mMsgFlow.mEventId != 0) + { + break; + } + + d_com_inf_game::dComIfG_inf_c* gameInfo = &d_com_inf_game::dComIfG_gameInfo; + uint8_t* reserveBytesPtr = &gameInfo->save.save_file.reserve.unk[0]; + uint32_t itemToGive = 0xFF; + + for (uint32_t i = 0; i < GIVE_PLAYER_ITEM_RESERVED_BYTES; i++) + { + const uint32_t storedItem = reserveBytesPtr[i]; + + if (storedItem) + { + // If we have the call to clear the queue, then we want to clear the item and break out. + if (giveItemToPlayer == CLEAR_QUEUE) + { + reserveBytesPtr[i] = 0; + giveItemToPlayer = QUEUE_EMPTY; + break; + } + + // If the queue is empty and we have an item to give, update the queue state. + else if (giveItemToPlayer == QUEUE_EMPTY) + { + giveItemToPlayer = ITEM_IN_QUEUE; + } + itemToGive = game_patch::_04_verifyProgressiveItem(randomizer, storedItem); + break; + } + } + + // if there is no item to give, break out of the case. + if (itemToGive == 0xFF) + { + break; + } + + libtp::tp::d_com_inf_game::dComIfG_play* playPtr = &gameInfo->play; + playPtr->mEvent.mGtItm = static_cast(itemToGive); + + // Set the process value for getting an item to start the "get item" cutscene when next available. + linkMapPtr->mProcID = libtp::tp::d_a_alink::PROC_GET_ITEM; + + // Get the event index for the "Get Item" event. + const int16_t eventIdx = d_event_manager::getEventIdx3(&playPtr->mEvtManager, + reinterpret_cast(linkMapPtr), + "DEFAULT_GETITEM", + 0xFF); + + // Finally we want to modify the event stack to prioritize our custom event so that it happens next. + libtp::tp::f_op_actor_mng::fopAcM_orderChangeEventId(linkMapPtr, eventIdx, 1, 0xFFFF); + } + default: + { + break; + } + } + } + int32_t initCreatePlayerItem(uint32_t itemID, uint32_t flag, const float pos[3], @@ -757,6 +884,26 @@ namespace mod return libtp::tp::f_op_actor_mng::fopAcM_create(539, params, pos, roomNo, rot, scale, -1); } + KEEP_FUNC void resetQueueOnFileSelectScreen(libtp::tp::d_file_select::dFile_select_c* thisPtr) + { + using namespace libtp::tp::d_com_inf_game; + + // Call the original function immediately to avoid storing thisPtr on the stack + return_dFile_select_c___create(thisPtr); + + // giveItemToPlayer needs to be reset to QUEUE_EMPTY upon going to the file select screen, as the player could have + // potentially saved/died after initializing getting an item (which would set giveItemToPlayer to ITEM_IN_QUEUE), and + // then chosen to return to the title screen. + giveItemToPlayer = QUEUE_EMPTY; + + // The reserved bytes that the queue uses to store the items to give are not cleared upon starting a new file, which + // means that the player could soft reset during the process of being given item(s), and then start a new file to be + // given those items on that new file. To avoid this, the reserved bytes need to be cleared upon going to the file + // select screen. All of the reserved bytes excluding the ones used by the queue will also be cleared, in the event that + // they need to be used for other stuff in the future. + libtp::memory::clearMemory(&dComIfG_gameInfo.save.save_file.reserve, sizeof(dComIfG_gameInfo.save.save_file.reserve)); + } + KEEP_FUNC bool handle_do_unlink(libtp::tp::dynamic_link::DynamicModuleControl* dmc) { events::onRELUnlink(randomizer, dmc); @@ -770,6 +917,7 @@ namespace mod { // Load DZX based randomizer checks that are stored in the local DZX events::onDZX(randomizer, chunkTypeInfo); + events::loadCustomActors(mStatus_roomControl); return return_actorInit(mStatus_roomControl, chunkTypeInfo, unk3, unk4); } @@ -789,8 +937,10 @@ namespace mod void* unk4) { // Load DZX based checks that are stored in the current layer DZX - events::onDZX(randomizer, chunkTypeInfo); - events::loadCustomRoomActors(); + rando::Randomizer* randoPtr = randomizer; + events::onDZX(randoPtr, chunkTypeInfo); + events::loadCustomRoomActors(randoPtr); + return return_actorCommonLayerInit(mStatus_roomControl, chunkTypeInfo, unk3, unk4); } @@ -800,40 +950,70 @@ namespace mod return return_tgscInfoInit(stageDt, i_data, entryNum, param_3); } - /* - KEEP_FUNC void handle_dComIfGp_setNextStage( const char* stage, - int16_t point, - int8_t roomNo, - int8_t layer, - float lastSpeed, - uint32_t lastMode, - int32_t setPoint, - int8_t wipe, - int16_t lastAngle, - int32_t param_9, - int32_t wipSpeedT ) - { - if ( libtp::tp::d_a_alink::checkStageName( - libtp::data::stage::allStages[libtp::data::stage::StageIDs::Hidden_Skill] ) && - ( roomNo == 6 ) ) - { - // If we are in the hidden skill area and the wolf is trying to force load room 6, we know that we are trying to - // go back to faron so we want to use the default state instead of forcing 0. - layer = 0xff; - } - return return_dComIfGp_setNextStage( stage, - point, - roomNo, - layer, - lastSpeed, - lastMode, - setPoint, - wipe, - lastAngle, - param_9, - wipSpeedT ); + KEEP_FUNC void handle_dComIfGp_setNextStage(const char* stage, + int16_t point, + int8_t roomNo, + int8_t layer, + float lastSpeed, + uint32_t lastMode, + int32_t setPoint, + int8_t wipe, + int16_t lastAngle, + int32_t param_9, + int32_t wipSpeedT) + { + rando::Seed* seedPtr; + if (seedPtr = getCurrentSeed(randomizer), seedPtr) + { + const int32_t stageIDX = libtp::tools::getStageIndex(stage); + const uint32_t numShuffledEntrances = seedPtr->m_numShuffledEntrances; + const rando::ShuffledEntrance* shuffledEntrances = &seedPtr->m_ShuffledEntrances[0]; + + // getConsole() << stageIDX << "," << roomNo << "," << point << "," << layer << "\n"; + + if (stageIDX != + libtp::data::stage::StageIDs::Title_Screen) // We won't want to shuffle if we are loading a save since some + // stages use their default spawn for their entrances. + { + for (uint32_t i = 0; i < numShuffledEntrances; i++) + { + const rando::ShuffledEntrance* currentEntrance = &shuffledEntrances[i]; + + if ((stageIDX == currentEntrance->origStageIDX) && (roomNo == currentEntrance->origRoomIDX) && + (point == currentEntrance->origSpawn) && (layer == currentEntrance->origState)) + { + // getConsole() << "Shuffling Entrance\n"; + + return return_dComIfGp_setNextStage(libtp::data::stage::allStages[currentEntrance->newStageIDX], + currentEntrance->newSpawn, + currentEntrance->newRoomIDX, + currentEntrance->newState, + lastSpeed, + lastMode, + setPoint, + wipe, + lastAngle, + param_9, + wipSpeedT); + } + } + } + } + + // getConsole() << "No match found.\n"; + + return return_dComIfGp_setNextStage(stage, + point, + roomNo, + layer, + lastSpeed, + lastMode, + setPoint, + wipe, + lastAngle, + param_9, + wipSpeedT); } - */ KEEP_FUNC void handle_roomLoader(void* data, void* stageDt, int32_t roomNo) { @@ -898,7 +1078,7 @@ namespace mod { if (libtp::tp::d_a_alink::checkStageName( libtp::data::stage::allStages[libtp::data::stage::StageIDs::Lake_Hylia]) && - !libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::CLEARED_LANAYRU_TWILIGHT)) + !libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::CLEARED_LANAYRU_TWILIGHT)) { *entranceType = 0x50; } @@ -911,6 +1091,22 @@ namespace mod return return_dStage_playerInit(stageDt, i_data, num, raw_data); } + KEEP_FUNC int32_t procCoGetItemInitCreateItem(const float pos[3], + int32_t item, + uint8_t unk3, + int32_t unk4, + int32_t unk5, + const float rot[3], + const float scale[3]) + { + if (giveItemToPlayer == ITEM_IN_QUEUE) + { + giveItemToPlayer = CLEAR_QUEUE; + } + + return libtp::tp::f_op_actor_mng::createItemForPresentDemo(pos, item, unk3, unk4, unk5, rot, scale); + } + KEEP_FUNC int32_t handle_createItemForBoss(const float pos[3], int32_t item, int32_t roomNo, @@ -1063,7 +1259,7 @@ namespace mod { // Check if we are at Kakariko Malo mart and verify that we have not bought the shield. if (libtp::tools::playerIsInRoomStage(3, stagesPtr[StageIDs::Kakariko_Village_Interiors]) && - !tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::BOUGHT_HYLIAN_SHIELD_AT_MALO_MART)) + !tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::BOUGHT_HYLIAN_SHIELD_AT_MALO_MART)) { // Return false so we can buy the shield. return 0; @@ -1081,6 +1277,18 @@ namespace mod } break; } + case items::Ordon_Shield: + case items::Wooden_Shield: + { + // Check if we are at Kakariko Malo Mart and that the Wooden Shield has not been bought. + if (libtp::tools::playerIsInRoomStage(3, stagesPtr[StageIDs::Kakariko_Village_Interiors]) && + !libtp::tp::d_save::isSwitch_dSv_memBit(&d_com_inf_game::dComIfG_gameInfo.save.memory.temp_flags, 0x5)) + { + // Return false so we can buy the wooden shield. + return 0; + } + break; + } case items::Ordon_Pumpkin: case items::Ordon_Goat_Cheese: { @@ -1117,7 +1325,7 @@ namespace mod KEEP_FUNC void handle_item_func_ASHS_SCRIBBLING() { using namespace libtp::data::flags; - if (!libtp::tp::d_a_alink::dComIfGs_isEventBit(GOT_CORAL_EARRING_FROM_RALIS)) + if (!libtp::tp::d_com_inf_game::dComIfGs_isEventBit(GOT_CORAL_EARRING_FROM_RALIS)) { return_item_func_ASHS_SCRIBBLING(); } @@ -1134,7 +1342,7 @@ namespace mod // Make sure the function ran successfully if (ret) { - game_patch::_05_setCustomItemMessage(control, TProcessor, unk3, msgId, randomizer); + game_patch::_05_setCustomItemMessage(control, TProcessor, unk3, msgId); } return ret; } @@ -1163,6 +1371,32 @@ namespace mod } } + KEEP_FUNC int32_t handle_query001(void* unk1, void* unk2, int32_t unk3) + { + using namespace libtp::data::flags; + using namespace libtp::data; + + uint16_t flag = *reinterpret_cast(reinterpret_cast(unk2) + 0x4); + + switch (flag) + { + case 0xFA: // MDH Completed + { + // Check to see if currently in Jovani's house + if (libtp::tools::playerIsInRoomStage(5, stage::allStages[stage::StageIDs::Castle_Town_Shops])) + { + return 0; // Return 0 to be able to turn souls into Jovani pre MDH + } + break; + } + default: + { + break; + } + } + return return_query001(unk1, unk2, unk3); + } + KEEP_FUNC int32_t handle_query022(void* unk1, void* unk2, int32_t unk3) { return events::proc_query022(unk1, unk2, unk3); @@ -1173,6 +1407,11 @@ namespace mod return events::proc_query023(unk1, unk2, unk3); } + KEEP_FUNC int32_t handle_query025(void* unk1, void* unk2, int32_t unk3) + { + return events::proc_query025(unk1, unk2, unk3); + } + KEEP_FUNC uint8_t handle_checkEmptyBottle(libtp::tp::d_save::dSv_player_item_c* playerItem) { if (libtp::tp::d_a_alink::checkStageName(libtp::data::stage::allStages[libtp::data::stage::StageIDs::Cave_of_Ordeals])) @@ -1202,7 +1441,7 @@ namespace mod { const int32_t poeFlag = return_query049(unk1, unk2, unk3); - if ((poeFlag == 4) && !libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::GOT_BOTTLE_FROM_JOVANI)) + if ((poeFlag == 4) && !libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::GOT_BOTTLE_FROM_JOVANI)) { return 3; } @@ -1240,6 +1479,70 @@ namespace mod return return_event017(messageFlow, nodeEvent, actrPtr); } + KEEP_FUNC int32_t handle_doFlow(libtp::tp::d_msg_flow::dMsgFlow* msgFlow, + libtp::tp::f_op_actor::fopAc_ac_c* actrPtr, + libtp::tp::f_op_actor::fopAc_ac_c** actrValue, + int32_t i_flow) + { + using namespace libtp::data::stage; + if (msgFlow->mFlow == 0xFFFE) // Check if it equals our custom flow value + { + if (msgFlow->mMsg == 0xFFFFFFFF) + { + // Clear the invalid msg value since it will be set by the game once our text is loaded. + msgFlow->mMsg = 0; + + // When this byte is set, the current event is aborted. With unused nodes, it is set to 1 by default so we need + // to unset it. + msgFlow->field_0x26 = 0; + + if (libtp::tp::d_a_alink::checkStageName(allStages[StageIDs::Hyrule_Field]) || + libtp::tp::d_a_alink::checkStageName(allStages[StageIDs::Outside_Castle_Town]) || + libtp::tp::d_a_alink::checkStageName(allStages[StageIDs::Lake_Hylia])) + { + // Hyrule Field and outside Lake Hylia do not have a valid flow node for node 0 so we want it to use its + // native node (8) + msgFlow->field_0x10 = 0x8; + } + else if (libtp::tp::d_a_alink::checkStageName(allStages[StageIDs::Castle_Town])) + { + // For Castle Town, both 1 and 2 seem to work at the very + // least. If you use 4, you will also get shiny shoes. + msgFlow->field_0x10 = 0x2; + } + else if (libtp::tp::d_a_alink::checkStageName(allStages[StageIDs::Death_Mountain])) + { + // Death Mountain does not have a valid flow node for node 0 so we want it to use its + // native node (4) + msgFlow->field_0x10 = 0x4; + } + else + { + // Sets the flow to use the same flow grouping as the standard flow that getItem text uses. + msgFlow->field_0x10 = 0; + } + } + } + + return return_doFlow(msgFlow, actrPtr, actrValue, i_flow); + } + + KEEP_FUNC int32_t handle_setNormalMsg(libtp::tp::d_msg_flow::dMsgFlow* msgFlow, + void* flowNode, + libtp::tp::f_op_actor::fopAc_ac_c* actrPtr) + { + if (msgFlow->mFlow == 0xFFFE) // Check if it equals our custom flow value + { + // Set the msg id in the node to that of our specified message. + const uint32_t msg = libtp::tp::f_op_msg_mng::fopMsgM_messageSet(0x1360, 1000); + + msgFlow->mMsg = msg; + return 1; + } + + return return_setNormalMsg(msgFlow, flowNode, actrPtr); + } + KEEP_FUNC void handle_jmessage_tSequenceProcessor__do_begin(void* seqProcessor, const void* unk2, const char* text) { // Call the original function immediately as it sets necessary values needed later on. @@ -1316,11 +1619,11 @@ namespace mod KEEP_FUNC bool handle_isEventBit(libtp::tp::d_save::dSv_event_c* eventPtr, uint16_t flag) { using namespace libtp::tp::d_a_alink; + using namespace libtp::tp::d_com_inf_game; using namespace libtp::data::stage; using namespace libtp::data::flags; const auto stagesPtr = &allStages[0]; - rando::Randomizer* rando = randomizer; switch (flag) { @@ -1432,12 +1735,12 @@ namespace mod { if (checkStageName(stagesPtr[StageIDs::Mirror_Chamber])) { - if (!libtp::tp::d_a_alink::dComIfGs_isEventBit(libtp::data::flags::FIXED_THE_MIRROR_OF_TWILIGHT)) + if (!libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::FIXED_THE_MIRROR_OF_TWILIGHT)) { - using namespace libtp::data; - if (randoIsEnabled(rando)) + rando::Seed* seed; + if (seed = getCurrentSeed(randomizer), seed) { - if (rando->m_Seed->m_Header->palaceRequirements != 3) + if (seed->m_Header->palaceRequirements != 3) { return false; } @@ -1459,7 +1762,7 @@ namespace mod { if (libtp::tools::playerIsInRoomStage(1, stagesPtr[StageIDs::Ordon_Village_Interiors])) { - if (libtp::tp::d_a_alink::dComIfGs_isEventBit(SERAS_CAT_RETURNED_TO_SHOP)) + if (libtp::tp::d_com_inf_game::dComIfGs_isEventBit(SERAS_CAT_RETURNED_TO_SHOP)) { return false; // Return false so Sera will give the milk item to the player once they help the cat. } @@ -1487,29 +1790,58 @@ namespace mod using namespace libtp::data::flags; libtp::tp::d_save::dSv_save_c* saveFilePtr = &libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.save_file; - if (eventPtr == &saveFilePtr->event_flags) + if (eventPtr == &saveFilePtr->mEvent) { - libtp::tp::d_save::dSv_player_status_b_c* playerStatusPtr = &saveFilePtr->player.player_status_b; - const uint32_t darkClearLevelFlag = playerStatusPtr->dark_clear_level_flag; + libtp::tp::d_save::dSv_player_c* playerPtr = &saveFilePtr->player; + libtp::tp::d_save::dSv_player_status_a_c* playerStatusAPtr = &playerPtr->player_status_a; + libtp::tp::d_save::dSv_player_status_b_c* playerStatusBPtr = &playerPtr->player_status_b; + + const uint32_t darkClearLevelFlag = playerStatusBPtr->dark_clear_level_flag; switch (flag) { + // Case block for Wolf -> Human crash patches/bug fixes. Some cutscenes/events either crash or act weird if Link + // is Human but needs to be Wolf and the game no longer attempts to auto-transform Link once the Shadow Crystal + // has been obtained. + case ENTERED_ORDON_SPRING_DAY_3: + { + if (libtp::tp::d_com_inf_game::dComIfGs_isEventBit(TRANSFORMING_UNLOCKED)) + { + // Set player to Human as the game will not do so if Shadow Crystal has been obtained. + playerStatusAPtr->currentForm = 0; + } + break; + } + + // Case block for Human -> Wolf crash patches/bug fixes. Some cutscenes/events either crash or act weird if Link + // is Wolf but needs to be human and the game no longer attempts to auto-transform Link once the Shadow Crystal + // has been obtained. + case WATCHED_CUTSCENE_AFTER_BEING_CAPTURED_IN_FARON_TWILIGHT: + { + if (libtp::tp::d_com_inf_game::dComIfGs_isEventBit(TRANSFORMING_UNLOCKED)) + { + // Set player to Wolf as the game will not do so if Shadow Crystal has been obtained. + playerStatusAPtr->currentForm = 1; + } + break; + } + case MIDNAS_DESPERATE_HOUR_COMPLETED: // MDH Completed { - playerStatusPtr->dark_clear_level_flag |= 0x8; + playerStatusBPtr->dark_clear_level_flag |= 0x8; break; } case CLEARED_FARON_TWILIGHT: // Cleared Faron Twilight { - if (libtp::tp::d_a_alink::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED)) + if (libtp::tp::d_com_inf_game::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED)) { if (darkClearLevelFlag == 0x6) { - playerStatusPtr->transform_level_flag = 0x8; // Set the flag for the last transformed twilight. - // Also puts Midna on the player's back + playerStatusBPtr->transform_level_flag = 0x8; // Set the flag for the last transformed twilight. + // Also puts Midna on the player's back - playerStatusPtr->dark_clear_level_flag |= 0x8; + playerStatusBPtr->dark_clear_level_flag |= 0x8; } } break; @@ -1518,14 +1850,14 @@ namespace mod case CLEARED_ELDIN_TWILIGHT: // Cleared Eldin Twilight { events::setSaveFileEventFlag(MAP_WARPING_UNLOCKED); // in glitched Logic, you can skip the gorge bridge. - if (libtp::tp::d_a_alink::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED)) + if (libtp::tp::d_com_inf_game::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED)) { - if (darkClearLevelFlag == 0x5) + if (darkClearLevelFlag == 0x7) { - playerStatusPtr->transform_level_flag |= 0x8; // Set the flag for the last transformed twilight. - // Also puts Midna on the player's back + playerStatusBPtr->transform_level_flag |= 0x8; // Set the flag for the last transformed twilight. + // Also puts Midna on the player's back - playerStatusPtr->dark_clear_level_flag |= 0x8; + playerStatusBPtr->dark_clear_level_flag |= 0x8; } } @@ -1534,14 +1866,14 @@ namespace mod case CLEARED_LANAYRU_TWILIGHT: // Cleared Lanayru Twilight { - if (libtp::tp::d_a_alink::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED)) + if (libtp::tp::d_com_inf_game::dComIfGs_isEventBit(MIDNAS_DESPERATE_HOUR_COMPLETED)) { if (darkClearLevelFlag == 0x7) // All twilights completed { - playerStatusPtr->transform_level_flag |= 0x8; // Set the flag for the last transformed twilight. - // Also puts Midna on the player's back + playerStatusBPtr->transform_level_flag |= 0x8; // Set the flag for the last transformed twilight. + // Also puts Midna on the player's back - playerStatusPtr->dark_clear_level_flag |= 0x8; + playerStatusBPtr->dark_clear_level_flag |= 0x8; } } @@ -1550,9 +1882,10 @@ namespace mod case PALACE_OF_TWILIGHT_CLEARED: { - if (randoIsEnabled(randomizer)) + rando::Seed* seed; + if (seed = getCurrentSeed(randomizer), seed) { - if (randomizer->m_Seed->m_Header->castleRequirements == 4) // Vanilla + if (seed->m_Header->castleRequirements == rando::CastleEntryRequirements::HC_Vanilla) // Vanilla { events::setSaveFileEventFlag(libtp::data::flags::BARRIER_GONE); return return_onEventBit(eventPtr, flag); // set PoT story flag @@ -1567,6 +1900,7 @@ namespace mod } } } + return return_onEventBit(eventPtr, flag); } @@ -1578,7 +1912,7 @@ namespace mod { if (flag == 0x66) // Check for escort completed flag { - if (!libtp::tp::d_a_alink::dComIfGs_isEventBit( + if (!libtp::tp::d_com_inf_game::dComIfGs_isEventBit( libtp::data::flags::GOT_ZORA_ARMOR_FROM_RUTELA)) // return false if we haven't gotten the item // from Rutella. { @@ -1607,7 +1941,9 @@ namespace mod KEEP_FUNC void handle_onSwitch_dSv_memBit(libtp::tp::d_save::dSv_memBit_c* memoryBit, int32_t flag) { - if (memoryBit == &libtp::tp::d_com_inf_game::dComIfG_gameInfo.save.memory.temp_flags) + libtp::tp::d_save::dSv_info_c* savePtr = &libtp::tp::d_com_inf_game::dComIfG_gameInfo.save; + + if (memoryBit == &savePtr->memory.temp_flags) { const auto stagesPtr = &libtp::data::stage::allStages[0]; @@ -1615,19 +1951,39 @@ namespace mod { if (flag == 0x52) { - return; // Don't set the flag for all monkeys freed in the lobby of Forest Temple + // Don't set the flag for all monkeys freed in the lobby of Forest Temple + return; } } else if (libtp::tp::d_a_alink::checkStageName(stagesPtr[libtp::data::stage::StageIDs::Arbiters_Grounds])) { - if (flag == 0x26) + if (flag == 0x26) // Poe flame CS trigger { - libtp::tp::d_save::offSwitch_dSv_memBit(memoryBit, - 0x45); // Open the Poe gate + // Open the Poe gate + libtp::tp::d_save::offSwitch_dSv_memBit(memoryBit, 0x45); return; } } + else if (libtp::tp::d_a_alink::checkStageName(stagesPtr[libtp::data::stage::StageIDs::Lake_Hylia])) + { + if (flag == 0xD) // Lanayru Twilight End CS trigger. + { + if (libtp::tp::d_com_inf_game::dComIfGs_isEventBit(libtp::data::flags::TRANSFORMING_UNLOCKED)) + { + // Set player to Human as the game will not do so if Shadow Crystal has been obtained. + savePtr->save_file.player.player_status_a.currentForm = 0; + } + } + } + else if (libtp::tp::d_a_alink::checkStageName(stagesPtr[libtp::data::stage::StageIDs::Kakariko_Village])) + { + if (flag == 0x3E) // Hawkeye is for sell. + { + // Remove the coming soon sign so the hawkeye can be bought. + libtp::tp::d_save::offSwitch_dSv_memBit(memoryBit, 0xB); + } + } } return return_onSwitch_dSv_memBit(memoryBit, flag); @@ -1830,6 +2186,54 @@ namespace mod return return_loadSeWave(z2SceneMgr, waveID); } + KEEP_FUNC bool handle_checkBgmIDPlaying(libtp::z2audiolib::z2seqmgr::Z2SeqMgr* seqMgr, uint32_t sfx_id) + { + // Call original function immediately as it sets necessary values. + const bool ret = return_checkBgmIDPlaying(seqMgr, sfx_id); + + if (sfx_id == 0x01000013) // Game Over sfx + { + return false; + } + + return ret; + } + + KEEP_FUNC void handle_dispWait_init(libtp::tp::d_gameover::dGameOver* ptr) + { + // Set the timer + ptr->mTimer = 0; + return return_dispWait_init(ptr); + } + + KEEP_FUNC int32_t handle_seq_decide_yes(libtp::tp::d_shop_system::dShopSystem* shopPtr, + libtp::tp::f_op_actor::fopAc_ac_c* actor, + void* msgFlow) + { + using namespace libtp::data::stage; + + const auto stagesPtr = &allStages[0]; + if (libtp::tools::playerIsInRoomStage(3, stagesPtr[StageIDs::Kakariko_Village_Interiors])) + { + // We want the shop item to have its flag updated no matter what in kak malo mart + libtp::tp::d_shop_system::setSoldOutFlag(shopPtr); + } + + return return_seq_decide_yes(shopPtr, actor, msgFlow); + } + + KEEP_FUNC int32_t handle_procCoGetItemInit(libtp::tp::d_a_alink::daAlink* linkActrPtr) + { + // If we are giving a custom item, we want to set mParam0 to 0x100 so that instead of trying to search for an item actor + // that doesnt exist we want the game to create one using the item id in mGtItm. + if (giveItemToPlayer == ITEM_IN_QUEUE) + { + libtp::tp::d_com_inf_game::dComIfG_gameInfo.play.mPlayer->mDemo.mParam0 = 0x100; + } + + return return_procCoGetItemInit(linkActrPtr); + } + KEEP_FUNC void* handle_dScnLogo_c_dt(void* dScnLogo_c, int16_t bFreeThis) { // Call the original function immediately, as certain values need to be set first diff --git a/GameCube/source/rando/randomizer.cpp b/GameCube/source/rando/randomizer.cpp index c2a6dc4d..493dccfb 100644 --- a/GameCube/source/rando/randomizer.cpp +++ b/GameCube/source/rando/randomizer.cpp @@ -69,7 +69,7 @@ namespace mod::rando return; } - const char* stage = libtp::tp::d_com_inf_game::dComIfG_gameInfo.play.mNextStage.stageValues.mStage; + const char* stage = libtp::tp::d_com_inf_game::dComIfG_gameInfo.play.mNextStage.mStage; seed->LoadChecks(stage); // Make sure the foolish items spawn count is reset before randomizing foolish item models @@ -98,6 +98,8 @@ namespace mod::rando case libtp::data::stage::StageIDs::Ordon_Village_Interiors: case libtp::data::stage::StageIDs::Kakariko_Village_Interiors: case libtp::data::stage::StageIDs::Castle_Town_Shops: + case libtp::data::stage::StageIDs::Death_Mountain: + case libtp::data::stage::StageIDs::City_in_the_Sky: { if (modifyShopModels) { @@ -341,6 +343,25 @@ namespace mod::rando } } + uint8_t Randomizer::getEventItem(uint8_t flag) + { + const uint32_t numLoadedEventChecks = m_Seed->m_numLoadedEventChecks; + const EventItem* eventChecks = &m_Seed->m_EventChecks[0]; + + for (uint32_t i = 0; i < numLoadedEventChecks; i++) + { + const EventItem* currentEventCheck = &eventChecks[i]; + if (flag == currentEventCheck->flag) + { + // Return new item + return currentEventCheck->itemID; + } + } + + // Currently we just use the vanilla item ID as the flag since the scope of these checks are limited at the moment. + return flag; + } + void Randomizer::overrideARC(uint32_t fileAddr, FileDirectory fileDirectory, int32_t roomNo) { // Make sure the randomizer is loaded/enabled and a seed is loaded @@ -677,4 +698,19 @@ namespace mod::rando } } } + + void Randomizer::addItemToEventQueue(uint32_t itemToAdd) + { + using namespace libtp::tp; + + uint8_t* reserveBytesPtr = d_com_inf_game::dComIfG_gameInfo.save.save_file.reserve.unk; + for (uint32_t i = 0; i < GIVE_PLAYER_ITEM_RESERVED_BYTES; i++) + { + if (reserveBytesPtr[i] == 0) + { + reserveBytesPtr[i] = static_cast(itemToAdd); + break; + } + } + } } // namespace mod::rando \ No newline at end of file diff --git a/GameCube/source/rando/seed.cpp b/GameCube/source/rando/seed.cpp index 5ff86ac4..aa0c0413 100644 --- a/GameCube/source/rando/seed.cpp +++ b/GameCube/source/rando/seed.cpp @@ -74,7 +74,7 @@ namespace mod::rando const uint32_t offset = eventFlags[i].offset; const uint8_t flag = eventFlags[i].flag; - gameInfo->save.save_file.event_flags.event_flags[offset] |= flag; + gameInfo->save.save_file.mEvent.mEvent[offset] |= flag; eventFlagsModified++; } @@ -188,6 +188,7 @@ namespace mod::rando this->LoadBugReward(); this->LoadSkyCharacter(stageIDX); this->LoadHiddenSkill(); + this->LoadEventChecks(stageIDX); // Save current stageIDX for next time this->m_StageIDX = stageIDX; @@ -204,6 +205,7 @@ namespace mod::rando m_numBugRewardChecks = 0; m_numSkyBookChecks = 0; m_numHiddenSkillChecks = 0; + m_numLoadedEventChecks = 0; delete[] m_DZXChecks; delete[] m_RELChecks; @@ -212,6 +214,7 @@ namespace mod::rando delete[] m_BugRewardChecks; delete[] m_SkyBookChecks; delete[] m_HiddenSkillChecks; + delete[] m_EventChecks; } void Seed::LoadDZX(uint8_t stageIDX) @@ -469,6 +472,38 @@ namespace mod::rando } } + void Seed::LoadEventChecks(uint8_t stageIDX) + { + using namespace libtp; + + Header* headerPtr = m_Header; + const uint32_t num_eventchecks = headerPtr->eventItemCheckInfo.numEntries; + const uint32_t gci_offset = headerPtr->eventItemCheckInfo.dataOffset; + + // Set the pointer as offset into our buffer + EventItem* eventChecksPtr = new EventItem[num_eventchecks]; + m_EventChecks = eventChecksPtr; + EventItem* allEvent = reinterpret_cast(&m_GCIData[gci_offset]); + + // offset into m_EventChecks + uint32_t j = 0; + + for (uint32_t i = 0; i < num_eventchecks; i++) + { + EventItem* currentEventCheck = &allEvent[i]; + EventItem* globalEventCheck = &eventChecksPtr[j]; + + uint32_t numEventChecks = m_numLoadedEventChecks; + if ((currentEventCheck->stageIDX == stageIDX)) + { + memcpy(globalEventCheck, currentEventCheck, sizeof(EventItem)); + numEventChecks++; + j++; + } + m_numLoadedEventChecks = static_cast(numEventChecks); + } + } + void Seed::LoadARCChecks(uint8_t stageIDX, FileDirectory fileDirectory, int32_t roomNo) { using namespace libtp; @@ -636,6 +671,7 @@ namespace mod::rando uint8_t foolishModelIndexes[MAX_SPAWNED_FOOLISH_ITEMS]; uint32_t foolishModelCounter = 0; + const uint32_t stageIdx = this->m_StageIDX; for (uint32_t i = 0; i < num_shopItems; i++) { @@ -708,6 +744,38 @@ namespace mod::rando } } } + else if (shopItem == 0x2) // Red Potion + { + if (stageIdx != libtp::data::stage::Kakariko_Village_Interiors) + { + d_item_data::ItemResource* currentItemResourcePtr = &itemResourcePtr[libtp::data::items::Red_Potion_Shop]; + + currentShopItemDataPtr->arcName = currentItemResourcePtr->arcName; + currentShopItemDataPtr->modelResIdx = currentItemResourcePtr->modelResIdx; + currentShopItemDataPtr->wBtkResIdx = currentItemResourcePtr->btkResIdx; + currentShopItemDataPtr->wBckResIdx = currentItemResourcePtr->bckResIdx; + currentShopItemDataPtr->wBrkResIdx = currentItemResourcePtr->brkResIdx; + currentShopItemDataPtr->wBtpResIdx = currentItemResourcePtr->btpResIdx; + currentShopItemDataPtr->tevFrm = currentItemResourcePtr->tevFrm; + currentShopItemDataPtr->posY = 15.f; + } + } + else if (shopItem == 0x6) // Wooden Shield + { + if (stageIdx != libtp::data::stage::Kakariko_Village_Interiors) + { + d_item_data::ItemResource* currentItemResourcePtr = &itemResourcePtr[libtp::data::items::Wooden_Shield]; + + currentShopItemDataPtr->arcName = currentItemResourcePtr->arcName; + currentShopItemDataPtr->modelResIdx = currentItemResourcePtr->modelResIdx; + currentShopItemDataPtr->wBtkResIdx = currentItemResourcePtr->btkResIdx; + currentShopItemDataPtr->wBckResIdx = currentItemResourcePtr->bckResIdx; + currentShopItemDataPtr->wBrkResIdx = currentItemResourcePtr->brkResIdx; + currentShopItemDataPtr->wBtpResIdx = currentItemResourcePtr->btpResIdx; + currentShopItemDataPtr->tevFrm = currentItemResourcePtr->tevFrm; + currentShopItemDataPtr->posY = 15.f; + } + } else { currentShopItemDataPtr->posY = 15.f; diff --git a/GameCube/subrel/boot/source/custom_messages/customMessages.cpp b/GameCube/subrel/boot/source/custom_messages/customMessages.cpp index ec12d0be..d5d6ff74 100644 --- a/GameCube/subrel/boot/source/custom_messages/customMessages.cpp +++ b/GameCube/subrel/boot/source/custom_messages/customMessages.cpp @@ -317,55 +317,4 @@ namespace mod::customMessages // Assign textData dataDest->textData = textData; } - - void createCharloDonationMessage() - { - // Get the donation string to use - using namespace customMessages; - const MsgEntry* donationEntry; -#ifdef TP_US - donationEntry = &charloDonationEntryUs; -#elif defined TP_JP - donationEntry = &charloDonationEntryJp; -#elif defined TP_EU - switch (currentLanguage) - { - case Languages::uk: - default: // The language is invalid/unsupported, so the game defaults to English - { - donationEntry = &charloDonationEntryUs; - break; - } - case Languages::de: - { - donationEntry = &charloDonationEntryDe; - break; - } - case Languages::fr: - { - donationEntry = &charloDonationEntryFr; - break; - } - case Languages::sp: - { - donationEntry = &charloDonationEntrySp; - break; - } - case Languages::it: - { - donationEntry = &charloDonationEntryIt; - break; - } - } -#endif - // Allocate memory for the buffer and write the string - // Must use memcpy instead of strncpy since message commands have NULL characters - // Align to char, as strings don't have specific alignment requirements - uint32_t donationEntrySize = donationEntry->size; - char* buf = new (sizeof(char)) char[donationEntrySize]; - memcpy(buf, donationEntry->msg, donationEntrySize); - - // Assign the buffer - m_DonationText = buf; - } } // namespace mod::customMessages \ No newline at end of file diff --git a/GameCube/subrel/boot/source/custom_messages/englishMessages.cpp b/GameCube/subrel/boot/source/custom_messages/englishMessages.cpp index 9060b6d1..b46bab65 100644 --- a/GameCube/subrel/boot/source/custom_messages/englishMessages.cpp +++ b/GameCube/subrel/boot/source/custom_messages/englishMessages.cpp @@ -16,8 +16,8 @@ namespace mod::customMessages // Disable formatting for the textbox messages because it makes things look weird. // clang-format off - MSG_BEGIN_ARRAY( forestSmallKeyEn ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(forestSmallKeyEn) + MSG_SPEED(MSG_SPEED_FAST) "You got " MSG_COLOR(MSG_COLOR_RED) "%s" @@ -28,7 +28,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( shadowCrystalEn ) + MSG_BEGIN_ARRAY(shadowCrystalEn) MSG_SPEED(MSG_SPEED_SLOW) "You got the " MSG_COLOR(MSG_COLOR_RED) @@ -40,7 +40,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "power that allows\nyou to transform at will!" MSG_END(); - MSG_BEGIN_ARRAY( endingBlowEn ) + MSG_BEGIN_ARRAY(endingBlowEn) MSG_SPEED(MSG_SPEED_FAST) "You learned the " MSG_COLOR(MSG_COLOR_RED) @@ -48,7 +48,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( shieldAttackEn ) + MSG_BEGIN_ARRAY(shieldAttackEn) MSG_SPEED(MSG_SPEED_FAST) "You learned the " MSG_COLOR(MSG_COLOR_RED) @@ -56,7 +56,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( backSliceEn ) + MSG_BEGIN_ARRAY(backSliceEn) MSG_SPEED(MSG_SPEED_FAST) "You learned the " MSG_COLOR(MSG_COLOR_RED) @@ -64,7 +64,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( helmSplitterEn ) + MSG_BEGIN_ARRAY(helmSplitterEn) MSG_SPEED(MSG_SPEED_FAST) "You learned the " MSG_COLOR(MSG_COLOR_RED) @@ -72,7 +72,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( mortalDrawEn ) + MSG_BEGIN_ARRAY(mortalDrawEn) MSG_SPEED(MSG_SPEED_FAST) "You learned the " MSG_COLOR(MSG_COLOR_RED) @@ -80,7 +80,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( jumpStrikeEn ) + MSG_BEGIN_ARRAY(jumpStrikeEn) MSG_SPEED(MSG_SPEED_FAST) "You learned the " MSG_COLOR(MSG_COLOR_RED) @@ -88,7 +88,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( greatSpinEn ) + MSG_BEGIN_ARRAY(greatSpinEn) MSG_SPEED(MSG_SPEED_FAST) "You learned the " MSG_COLOR(MSG_COLOR_RED) @@ -96,7 +96,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( poweredRodEn ) + MSG_BEGIN_ARRAY(poweredRodEn) MSG_SPEED(MSG_SPEED_FAST) "Power has been restored to\nthe " MSG_COLOR(MSG_COLOR_RED) @@ -104,7 +104,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "! Now it can\nbe used to imbue statues\nwith life in the present!" MSG_END(); - MSG_BEGIN_ARRAY( skyBookCharacterEn ) + MSG_BEGIN_ARRAY(skyBookCharacterEn) MSG_SPEED(MSG_SPEED_FAST) "You got a " MSG_COLOR(MSG_COLOR_RED) @@ -116,7 +116,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) " so far." MSG_END(); - MSG_BEGIN_ARRAY( firstFusedShadowEn ) + MSG_BEGIN_ARRAY(firstFusedShadowEn) MSG_SPEED(MSG_SPEED_FAST) "You got a " MSG_COLOR(MSG_COLOR_RED) @@ -128,7 +128,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "\ngrowing on it.." MSG_END(); - MSG_BEGIN_ARRAY( secondFusedShadowEn ) + MSG_BEGIN_ARRAY(secondFusedShadowEn) MSG_SPEED(MSG_SPEED_FAST) "You got the second " MSG_COLOR(MSG_COLOR_RED) @@ -140,7 +140,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) " to\nthe touch.." MSG_END(); - MSG_BEGIN_ARRAY( thirdFusedShadowEn ) + MSG_BEGIN_ARRAY(thirdFusedShadowEn) MSG_SPEED(MSG_SPEED_FAST) "You got the final " MSG_COLOR(MSG_COLOR_RED) @@ -152,7 +152,19 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) " and\nsmells like fish.." MSG_END(); - MSG_BEGIN_ARRAY( secondMirrorShardEn ) + MSG_BEGIN_ARRAY(firstMirrorShardEn) + MSG_SPEED(MSG_SPEED_FAST) + "You got the first shard of\nthe " + MSG_COLOR(MSG_COLOR_RED) + "Mirror of Twilight" + MSG_COLOR(MSG_COLOR_WHITE) + "! It\nis covered in " + MSG_COLOR(MSG_COLOR_ORANGE) + "sand" + MSG_COLOR(MSG_COLOR_WHITE) + ".." + MSG_END(); + MSG_BEGIN_ARRAY(secondMirrorShardEn) MSG_SPEED(MSG_SPEED_FAST) "You got the second shard of\nthe " MSG_COLOR(MSG_COLOR_RED) @@ -164,7 +176,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) ".." MSG_END(); - MSG_BEGIN_ARRAY( thirdMirrorShardEn ) + MSG_BEGIN_ARRAY(thirdMirrorShardEn) MSG_SPEED(MSG_SPEED_FAST) "You got the third shard of\nthe " MSG_COLOR(MSG_COLOR_RED) @@ -176,7 +188,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) ".." MSG_END(); - MSG_BEGIN_ARRAY( fourthMirrorShardEn ) + MSG_BEGIN_ARRAY(fourthMirrorShardEn) MSG_SPEED(MSG_SPEED_FAST) "You got the final shard of\nthe " MSG_COLOR(MSG_COLOR_RED) @@ -188,15 +200,15 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) ".." MSG_END(); - MSG_BEGIN_ARRAY( foolishItemEn ) + MSG_BEGIN_ARRAY(foolishItemEn) MSG_SPEED(MSG_SPEED_FAST) "A " MSG_COLOR(MSG_COLOR_LIGHT_BLUE) "cold" MSG_COLOR(MSG_COLOR_WHITE) - " wind blows.." + " wind blows..." MSG_END(); - MSG_BEGIN_ARRAY( talkToMidnaEn ) + MSG_BEGIN_ARRAY(talkToMidnaEn) "What is it, " MSG_PLYR_NAME "?" @@ -207,7 +219,7 @@ namespace mod::customMessages MSG_OPTION_LIST(MSG_OPTION_3) "Change time of day" MSG_END(); - MSG_BEGIN_ARRAY( bigWalletEn ) + MSG_BEGIN_ARRAY(bigWalletEn) MSG_SPEED(MSG_SPEED_FAST) "You got the " MSG_COLOR(MSG_COLOR_RED) @@ -219,7 +231,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( giantWalletEn ) + MSG_BEGIN_ARRAY(giantWalletEn) MSG_SPEED(MSG_SPEED_FAST) "You got the " MSG_COLOR(MSG_COLOR_RED) @@ -231,20 +243,20 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( smallWalletPauseEn ) + MSG_BEGIN_ARRAY(smallWalletPauseEn) MSG_SPEED(MSG_SPEED_FAST) "A wallet from your childhood.\nIt holds up to 1,000 Rupees." MSG_END(); - MSG_BEGIN_ARRAY( bigWalletPauseEn ) + MSG_BEGIN_ARRAY(bigWalletPauseEn) MSG_SPEED(MSG_SPEED_FAST) "The wallet given to you by Agitha,\nprincess of the insect kingdom.\nIt can hold 5,000 Rupees." MSG_END(); - MSG_BEGIN_ARRAY( giantWalletPauseEn ) + MSG_BEGIN_ARRAY(giantWalletPauseEn) MSG_SPEED(MSG_SPEED_FAST) "The wallet given by Agitha to\nbenefactors of the insect kingdom.\nIt can hold up to 9,999 Rupees." MSG_END(); - MSG_BEGIN_ARRAY( poeSoulEn ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(poeSoulEn) + MSG_SPEED(MSG_SPEED_FAST) "You got a " MSG_COLOR(MSG_COLOR_RED) "Poe's soul" @@ -255,7 +267,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) " so far." MSG_END(); - MSG_BEGIN_ARRAY( skyBookDescriptionEn ) + MSG_BEGIN_ARRAY(skyBookDescriptionEn) MSG_SPEED(MSG_SPEED_FAST) "A book written in the ancient Sky language.\nCharacters are missing in areas.\n\nYou've collected " MSG_COLOR(MSG_COLOR_RED) @@ -263,16 +275,16 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) " character(s) so far." MSG_END(); - MSG_BEGIN_ARRAY( charloDonationEn ) + MSG_BEGIN_ARRAY(charloDonationEn) "For the sake of peace in Hyrule...\nWould you please make a donation?" - MSG_OPTION_LIST( MSG_OPTION_1 ) + MSG_OPTION_LIST(MSG_OPTION_1) "100 Rupees\n" - MSG_OPTION_LIST( MSG_OPTION_2 ) + MSG_OPTION_LIST(MSG_OPTION_2) "50 Rupees\n" - MSG_OPTION_LIST( MSG_OPTION_3 ) + MSG_OPTION_LIST(MSG_OPTION_3) "Sorry..." MSG_END(); - MSG_BEGIN_ARRAY( recognitionMsg ) + MSG_BEGIN_ARRAY(recognitionMsg) MSG_SPEED(MSG_SPEED_FAST) "The Randomizer Team would like\nto thank our amazing testers.\nWithout you, this project would\nnot be what it is today: Taka\nAnorakkis, Archer, Br00ty, Chris\nChrono, clabrus, Demon, EmperorP\nElinadrian, Empty, Fennec, Zushi\nFleakee, Foxhole Gaming, Luzagar\nHeartPiece, Hornlitz, IceStorm\nJanWegh, JD, jdflyer, Jeez, Oxy\nJustRyland, Lance H., link1183\nLinkman124, Luneyes, GameWyrm\nMattStrats, MultFij, NesmaN88\nXenoWars, Papy_Grant, Simikins\npokemongenius, Psi-Hate, Lars P\nRaziel_Stratton, Redriel, Revven\nSparky7198, Zach, SwiftIke, j_im\nZenith, Prince, The., TheBruce\nTreZc0_, Wameslo, WickedGligar\nDGod63 and Sushi." MSG_END(); @@ -367,6 +379,11 @@ namespace mod::customMessages sizeof(thirdFusedShadowEn), 0x013E, + // First Mirror Shard + firstMirrorShardEn, + sizeof(firstMirrorShardEn), + 0x0B7, + // Second Mirror Shard secondMirrorShardEn, sizeof(secondMirrorShardEn), diff --git a/GameCube/subrel/boot/source/custom_messages/frenchMessages.cpp b/GameCube/subrel/boot/source/custom_messages/frenchMessages.cpp index e2b58b43..93662466 100644 --- a/GameCube/subrel/boot/source/custom_messages/frenchMessages.cpp +++ b/GameCube/subrel/boot/source/custom_messages/frenchMessages.cpp @@ -16,8 +16,8 @@ namespace mod::customMessages // Disable formatting for the textbox messages because it makes things look weird. // clang-format off - MSG_BEGIN_ARRAY( forestSmallKeyFr ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(forestSmallKeyFr) + MSG_SPEED(MSG_SPEED_FAST) //Vous obtenez une "\x56\x6f\x75\x73\x20\x6f\x62\x74\x65\x6e\x65\x7a\x20" MSG_COLOR(MSG_COLOR_RED) @@ -29,7 +29,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( shadowCrystalFr ) + MSG_BEGIN_ARRAY(shadowCrystalFr) MSG_SPEED(MSG_SPEED_SLOW) //Vous obtenez le "\x56\x6f\x75\x73\x20\x6f\x62\x74\x65\x6e\x65\x7a\x20\x6c\x65\x20" @@ -40,7 +40,7 @@ namespace mod::customMessages //!La sombre manifestation des pouvoirs de Xanto qui permet de se transformer à volonté! "\x21\x0A\x4c\x61\x20\x73\x6f\x6d\x62\x72\x65\x20\x6d\x61\x6e\x69\x66\x65\x73\x74\x61\x74\x69\x6f\x6e\x20\x64\x65\x73\x0A\x70\x6f\x75\x76\x6f\x69\x72\x73\x20\x64\x65\x20\x58\x61\x6e\x74\x6f\x20\x71\x75\x69\x20\x70\x65\x72\x6d\x65\x74\x0A\x64\x65\x20\x73\x65\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x20\xe0\x20\x76\x6f\x6c\x6f\x6e\x74\xe9\x21" MSG_END(); - MSG_BEGIN_ARRAY( endingBlowFr ) + MSG_BEGIN_ARRAY(endingBlowFr) MSG_SPEED(MSG_SPEED_FAST) //Vous avez appris le "\x56\x6f\x75\x73\x20\x61\x76\x65\x7a\x20\x61\x70\x70\x72\x69\x73\x20\x6c\x65\x20" @@ -51,7 +51,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( shieldAttackFr ) + MSG_BEGIN_ARRAY(shieldAttackFr) MSG_SPEED(MSG_SPEED_FAST) //Vous avez appris la "\x56\x6f\x75\x73\x20\x61\x76\x65\x7a\x20\x61\x70\x70\x72\x69\x73\x20\x6c\x61\x20" @@ -62,7 +62,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( backSliceFr ) + MSG_BEGIN_ARRAY(backSliceFr) MSG_SPEED(MSG_SPEED_FAST) //Vous avez appris le "\x56\x6f\x75\x73\x20\x61\x76\x65\x7a\x20\x61\x70\x70\x72\x69\x73\x20\x6c\x65\x20" @@ -73,7 +73,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( helmSplitterFr ) + MSG_BEGIN_ARRAY(helmSplitterFr) MSG_SPEED(MSG_SPEED_FAST) //Vous avez appris le "\x56\x6f\x75\x73\x20\x61\x76\x65\x7a\x20\x61\x70\x70\x72\x69\x73\x20\x6c\x65\x20" @@ -84,7 +84,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( mortalDrawFr ) + MSG_BEGIN_ARRAY(mortalDrawFr) MSG_SPEED(MSG_SPEED_FAST) //Vous avez appris le "\x56\x6f\x75\x73\x20\x61\x76\x65\x7a\x20\x61\x70\x70\x72\x69\x73\x20\x6c\x65\x20" @@ -95,7 +95,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( jumpStrikeFr ) + MSG_BEGIN_ARRAY(jumpStrikeFr) MSG_SPEED(MSG_SPEED_FAST) //Vous avez appris le "\x56\x6f\x75\x73\x20\x61\x76\x65\x7a\x20\x61\x70\x70\x72\x69\x73\x20\x6c\x65\x20" @@ -106,7 +106,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( greatSpinFr ) + MSG_BEGIN_ARRAY(greatSpinFr) MSG_SPEED(MSG_SPEED_FAST) //Vous avez appris "\x56\x6f\x75\x73\x20\x61\x76\x65\x7a\x20\x61\x70\x70\x72\x69\x73\x20" @@ -117,7 +117,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( poweredRodFr ) + MSG_BEGIN_ARRAY(poweredRodFr) MSG_SPEED(MSG_SPEED_FAST) //Le "\x4c\x65\x20" @@ -128,7 +128,7 @@ namespace mod::customMessages //a recouvré ses pouvoirs magiques! Vous pouvez désormais insuffler la vie aux statues dans le présent! "\x61\x20\x72\x65\x63\x6F\x75\x76\x72\xE9\x20\x73\x65\x73\x0A\x70\x6F\x75\x76\x6F\x69\x72\x73\x20\x6D\x61\x67\x69\x71\x75\x65\x73\x21\x20\x56\x6F\x75\x73\x20\x70\x6F\x75\x76\x65\x7A\x0A\x64\xE9\x73\x6F\x72\x6D\x61\x69\x73\x20\x69\x6E\x73\x75\x66\x66\x6C\x65\x72\x20\x6C\x61\x20\x76\x69\x65\x20\x61\x75\x78\x0A\x73\x74\x61\x74\x75\x65\x73\x20\x64\x61\x6E\x73\x20\x6C\x65\x20\x70\x72\xE9\x73\x65\x6E\x74\x21" MSG_END(); - MSG_BEGIN_ARRAY( skyBookCharacterFr ) + MSG_BEGIN_ARRAY(skyBookCharacterFr) MSG_SPEED(MSG_SPEED_FAST) // Vous avez trouvé un "\x56\x6F\x75\x73\x20\x61\x76\x65\x7A\x20\x74\x72\x6F\x75\x76\xE9\x20\x75\x6E\x20" @@ -145,7 +145,7 @@ namespace mod::customMessages // pour l'instant. "\x20\x70\x6F\x75\x72\x20\x6C\x27\x69\x6E\x73\x74\x61\x6E\x74\x2E" MSG_END(); - MSG_BEGIN_ARRAY( firstFusedShadowFr ) + MSG_BEGIN_ARRAY(firstFusedShadowFr) MSG_SPEED(MSG_SPEED_FAST) //Vous obtenez un "\x56\x6f\x75\x73\x20\x6f\x62\x74\x65\x6e\x65\x7a\x20\x75\x6e\x20" @@ -162,7 +162,7 @@ namespace mod::customMessages //.. "\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( secondFusedShadowFr ) + MSG_BEGIN_ARRAY(secondFusedShadowFr) MSG_SPEED(MSG_SPEED_FAST) //Vous obtenez un second "\x56\x6f\x75\x73\x20\x6f\x62\x74\x65\x6e\x65\x7a\x20\x75\x6e\x20\x73\x65\x63\x6f\x6e\x64\x0A" @@ -179,7 +179,7 @@ namespace mod::customMessages //sur vos mains.. "\x73\x75\x72\x20\x76\x6f\x73\x20\x6d\x61\x69\x6e\x73\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( thirdFusedShadowFr ) + MSG_BEGIN_ARRAY(thirdFusedShadowFr) MSG_SPEED(MSG_SPEED_FAST) //Vous obtenez le dernier "\x56\x6f\x75\x73\x20\x6f\x62\x74\x65\x6e\x65\x7a\x20\x6c\x65\x20\x64\x65\x72\x6e\x69\x65\x72\x0A" @@ -196,7 +196,24 @@ namespace mod::customMessages //s'en dégage.. "\x73\x27\x65\x6e\x20\x64\xe9\x67\x61\x67\x65\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( secondMirrorShardFr ) + MSG_BEGIN_ARRAY(firstMirrorShardFr) + MSG_SPEED(MSG_SPEED_FAST) + // Vous obtenez le premier fragmentdu + "\x56\x6F\x75\x73\x20\x6F\x62\x74\x65\x6E\x65\x7A\x20\x6C\x65\x20\x70\x72\x65\x6D\x69\x65\x72\x20\x66\x72\x61\x67\x6D\x65\x6E\x74\x0A\x64\x75\x20" + MSG_COLOR(MSG_COLOR_RED) + // Miroir des Ombres + "\x4d\x69\x72\x6f\x69\x72\x20\x64\x65\x73\x20\x4f\x6d\x62\x72\x65\x73" + MSG_COLOR(MSG_COLOR_WHITE) + // ! Il est recouvert de + "\x21\x20\x49\x6C\x20\x65\x73\x74\x0A\x72\x65\x63\x6F\x75\x76\x65\x72\x74\x20\x64\x65\x20" + MSG_COLOR(MSG_COLOR_ORANGE) + // sable + "\x73\x61\x62\x6C\x65" + MSG_COLOR(MSG_COLOR_WHITE) + // ... + "\x2e\x2e\x2e" + MSG_END(); + MSG_BEGIN_ARRAY(secondMirrorShardFr) MSG_SPEED(MSG_SPEED_FAST) //Vous obtenez le second fragmentdu "\x56\x6f\x75\x73\x20\x6f\x62\x74\x65\x6e\x65\x7a\x20\x6c\x65\x20\x73\x65\x63\x6f\x6e\x64\x20\x66\x72\x61\x67\x6d\x65\x6e\x74\x0A\x64\x75\x20" @@ -213,7 +230,7 @@ namespace mod::customMessages //et brille demille feux.. "\x65\x74\x20\x62\x72\x69\x6c\x6c\x65\x20\x64\x65\x0A\x6d\x69\x6c\x6c\x65\x20\x66\x65\x75\x78\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( thirdMirrorShardFr ) + MSG_BEGIN_ARRAY(thirdMirrorShardFr) MSG_SPEED(MSG_SPEED_FAST) //Vous obtenez le troisièmefragment du "\x56\x6f\x75\x73\x20\x6f\x62\x74\x65\x6e\x65\x7a\x20\x6c\x65\x20\x74\x72\x6f\x69\x73\x69\xe8\x6d\x65\x0A\x66\x72\x61\x67\x6d\x65\x6e\x74\x20\x64\x75\x20" @@ -230,7 +247,7 @@ namespace mod::customMessages //.. "\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( fourthMirrorShardFr ) + MSG_BEGIN_ARRAY(fourthMirrorShardFr) MSG_SPEED(MSG_SPEED_FAST) //Vous obtenez le dernierfragment du "\x56\x6f\x75\x73\x20\x6f\x62\x74\x65\x6e\x65\x7a\x20\x6c\x65\x20\x64\x65\x72\x6e\x69\x65\x72\x0A\x66\x72\x61\x67\x6d\x65\x6e\x74\x20\x64\x75\x20" @@ -247,7 +264,7 @@ namespace mod::customMessages //.. "\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( foolishItemFr ) + MSG_BEGIN_ARRAY(foolishItemFr) MSG_SPEED(MSG_SPEED_FAST) //Le "\x4c\x65\x20" @@ -256,9 +273,9 @@ namespace mod::customMessages "\x62\x6c\x69\x7a\x7a\x61\x72\x64\x20" MSG_COLOR(MSG_COLOR_WHITE) //souffle.. - "\x73\x6f\x75\x66\x66\x6c\x65\x2e\x2e" + "\x73\x6f\x75\x66\x66\x6c\x65\x2e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( talkToMidnaFr ) + MSG_BEGIN_ARRAY(talkToMidnaFr) //Qu'est-ce qu'il y a, "\x51\x75\x27\x65\x73\x74\x2d\x63\x65\x20\x71\x75\x27\x69\x6c\x20\x79\x20\x61\x2c\x20" MSG_PLYR_NAME @@ -274,7 +291,7 @@ namespace mod::customMessages //Changer l'heure de la journée "\x43\x68\x61\x6e\x67\x65\x72\x20\x6c\x27\x68\x65\x75\x72\x65\x20\x64\x65\x20\x6c\x61\x20\x6a\x6f\x75\x72\x6e\xe9\x65" MSG_END(); - MSG_BEGIN_ARRAY( bigWalletFr ) + MSG_BEGIN_ARRAY(bigWalletFr) MSG_SPEED(MSG_SPEED_FAST) //Vous obtenez la "\x56\x6f\x75\x73\x20\x6f\x62\x74\x65\x6e\x65\x7a\x20\x6c\x61\x20" @@ -291,7 +308,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( giantWalletFr ) + MSG_BEGIN_ARRAY(giantWalletFr) MSG_SPEED(MSG_SPEED_FAST) //Vous obtenez la "\x56\x6f\x75\x73\x20\x6f\x62\x74\x65\x6e\x65\x7a\x20\x6c\x61\x20" @@ -308,23 +325,23 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( smallWalletPauseFr ) + MSG_BEGIN_ARRAY(smallWalletPauseFr) MSG_SPEED(MSG_SPEED_FAST) // Votre bourse préférée que vous avez depuis tout petit. Elle peut contenir 1000 rubis. "\x56\x6F\x74\x72\x65\x20\x62\x6F\x75\x72\x73\x65\x20\x70\x72\xE9\x66\xE9\x72\xE9\x65\x20\x71\x75\x65\x20\x76\x6F\x75\x73\x0A\x61\x76\x65\x7A\x20\x64\x65\x70\x75\x69\x73\x20\x74\x6F\x75\x74\x20\x70\x65\x74\x69\x74\x2E\x0A\x45\x6C\x6C\x65\x20\x70\x65\x75\x74\x20\x63\x6F\x6E\x74\x65\x6E\x69\x72\x20\x31\x30\x30\x30\x20\x72\x75\x62\x69\x73\x2E" MSG_END(); - MSG_BEGIN_ARRAY( bigWalletPauseFr ) + MSG_BEGIN_ARRAY(bigWalletPauseFr) MSG_SPEED(MSG_SPEED_FAST) // La bourse que vous avez reçue de Machaon, la princesse des insectes. Elle peut contenir 5000 rubis. "\x4C\x61\x20\x62\x6F\x75\x72\x73\x65\x20\x71\x75\x65\x20\x76\x6F\x75\x73\x20\x61\x76\x65\x7A\x20\x72\x65\xE7\x75\x65\x20\x64\x65\x0A\x4D\x61\x63\x68\x61\x6F\x6E\x2C\x20\x6C\x61\x20\x70\x72\x69\x6E\x63\x65\x73\x73\x65\x20\x64\x65\x73\x20\x69\x6E\x73\x65\x63\x74\x65\x73\x2E\x0A\x45\x6C\x6C\x65\x20\x70\x65\x75\x74\x20\x63\x6F\x6E\x74\x65\x6E\x69\x72\x20\x35\x30\x30\x30\x20\x72\x75\x62\x69\x73\x2E" MSG_END(); - MSG_BEGIN_ARRAY( giantWalletPauseFr ) + MSG_BEGIN_ARRAY(giantWalletPauseFr) MSG_SPEED(MSG_SPEED_FAST) // La bourse que Machaon vous a donnée en récompense. Elle peut contenir 9999 rubis. "\x4C\x61\x20\x62\x6F\x75\x72\x73\x65\x20\x71\x75\x65\x20\x4D\x61\x63\x68\x61\x6F\x6E\x20\x76\x6F\x75\x73\x20\x61\x20\x64\x6F\x6E\x6E\xE9\x65\x0A\x65\x6E\x20\x72\xE9\x63\x6F\x6D\x70\x65\x6E\x73\x65\x2E\x20\x45\x6C\x6C\x65\x20\x70\x65\x75\x74\x20\x63\x6F\x6E\x74\x65\x6E\x69\x72\x0A\x39\x39\x39\x39\x20\x72\x75\x62\x69\x73\x2E" MSG_END(); - MSG_BEGIN_ARRAY( poeSoulFr ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(poeSoulFr) + MSG_SPEED(MSG_SPEED_FAST) // Vous obtenez une "\x56\x6F\x75\x73\x20\x6F\x62\x74\x65\x6E\x65\x7A\x20\x75\x6E\x65\x20" MSG_COLOR(MSG_COLOR_RED) @@ -340,7 +357,7 @@ namespace mod::customMessages // pour l'instant. "\x20\x70\x6F\x75\x72\x20\x6C\x27\x69\x6E\x73\x74\x61\x6E\x74\x2e" MSG_END(); - MSG_BEGIN_ARRAY( skyBookDescriptionFr ) + MSG_BEGIN_ARRAY(skyBookDescriptionFr) MSG_SPEED(MSG_SPEED_FAST) // Des écrits très anciens en célestien.\nIl manque des mots ici et là.\n\nVous en avez collecté "\x44\x65\x73\x20\xE9\x63\x72\x69\x74\x73\x20\x74\x72\xE8\x73\x20\x61\x6E\x63\x69\x65\x6E\x73\x20\x65\x6E\x20\x63\xE9\x6C\x65\x73\x74\x69\x65\x6E\x2E\x0A\x49\x6C\x20\x6D\x61\x6E\x71\x75\x65\x20\x64\x65\x73\x20\x6D\x6F\x74\x73\x20\x69\x63\x69\x20\x65\x74\x20\x6C\xE0\x2E\x0A\x0A\x56\x6F\x75\x73\x20\x65\x6E\x20\x61\x76\x65\x7A\x20\x63\x6F\x6C\x6C\x65\x63\x74\xE9\x20" @@ -351,21 +368,21 @@ namespace mod::customMessages // pour l'instant. "\x20\x70\x6F\x75\x72\x20\x6C\x27\x69\x6E\x73\x74\x61\x6E\x74\x2E" MSG_END(); - MSG_BEGIN_ARRAY( charloDonationFr ) + MSG_BEGIN_ARRAY(charloDonationFr) // Pour que la paix règne en Hyrule... puis-je vous demander l'aumône...? "\x50\x6F\x75\x72\x20\x71\x75\x65\x20\x6C\x61\x20\x70\x61\x69\x78\x20\x72\xE8\x67\x6E\x65\x20\x65\x6E\x20\x48\x79\x72\x75\x6C\x65\x2E\x2E\x2E\x0A\x70\x75\x69\x73\x2D\x6A\x65\x20\x76\x6F\x75\x73\x20\x64\x65\x6D\x61\x6E\x64\x65\x72\x20\x6C\x27\x61\x75\x6D\xF4\x6E\x65\x2E\x2E\x2E\x3F" - MSG_OPTION_LIST( MSG_OPTION_1 ) + MSG_OPTION_LIST(MSG_OPTION_1) // Voici 100 rubis. "\x56\x6F\x69\x63\x69\x20\x31\x30\x30\x20\x72\x75\x62\x69\x73\x2E\x0A" - MSG_OPTION_LIST( MSG_OPTION_2 ) + MSG_OPTION_LIST(MSG_OPTION_2) // Voici 50 rubis "\x56\x6F\x69\x63\x69\x20\x35\x30\x20\x72\x75\x62\x69\x73\x2E\x0A" - MSG_OPTION_LIST( MSG_OPTION_3 ) + MSG_OPTION_LIST(MSG_OPTION_3) // Je refuse. "\x4A\x65\x20\x72\x65\x66\x75\x73\x65\x2E"; MSG_END(); - MSG_BEGIN_ARRAY( recognitionFr ) + MSG_BEGIN_ARRAY(recognitionFr) MSG_SPEED(MSG_SPEED_FAST) // L'équipe du Randomizer souhaiterait remercier nos incroyables testeurs. Ce projet ne serait pas ce qu'il est aujourd'hui sans vous "\x4C\x27\xE9\x71\x75\x69\x70\x65\x20\x64\x75\x20\x52\x61\x6E\x64\x6F\x6D\x69\x7A\x65\x72\n\x73\x6F\x75\x68\x61\x69\x74\x65\x72\x61\x69\x74\x20\x72\x65\x6D\x65\x72\x63\x69\x65\x72\x20\x6E\x6F\x73\n\x69\x6E\x63\x72\x6F\x79\x61\x62\x6C\x65\x73\x20\x74\x65\x73\x74\x65\x75\x72\x73\x2E\x20\x43\x65\n\x70\x72\x6F\x6A\x65\x74\x20\x6E\x65\x20\x73\x65\x72\x61\x69\x74\x20\x70\x61\x73\x20\x63\x65\x20\x71\x75\x27\x69\x6C\n\x65\x73\x74\x20\x61\x75\x6A\x6F\x75\x72\x64\x27\x68\x75\x69\x20\x73\x61\x6E\x73\x20\x76\x6F\x75\x73: Taka\nAnorakkis, Archer, Br00ty, Chris\nChrono, clabrus, Demon, EmperorP\nElinadrian, Empty, Fennec, Zushi\nFleakee, Foxhole Gaming, Luzagar\nHeartPiece, Hornlitz, IceStorm\nJanWegh, JD, jdflyer, Jeez, Oxy\nJustRyland, Lance H., link1183\nLinkman124, Luneyes, GameWyrm\nMattStrats, MultFij, NesmaN88\nXenoWars, Papy_Grant, Simikins\npokemongenius, Psi-Hate, Lars P\nRaziel_Stratton, Redriel, Revven\nSparky7198, Zach, SwiftIke, j_im\nZenith, Prince, The., TheBruce\nTreZc0_, Wameslo, WickedGligar\nDGod63 and Sushi." @@ -458,6 +475,11 @@ namespace mod::customMessages sizeof(thirdFusedShadowFr), 0x013E, + // First Mirror Shard + firstMirrorShardFr, + sizeof(firstMirrorShardFr), + 0x0B7, + // Second Mirror Shard secondMirrorShardFr, sizeof(secondMirrorShardFr), diff --git a/GameCube/subrel/boot/source/custom_messages/germanMessages.cpp b/GameCube/subrel/boot/source/custom_messages/germanMessages.cpp index 67e0d4c3..923adb0f 100644 --- a/GameCube/subrel/boot/source/custom_messages/germanMessages.cpp +++ b/GameCube/subrel/boot/source/custom_messages/germanMessages.cpp @@ -16,8 +16,8 @@ namespace mod::customMessages // Disable formatting for the textbox messages because it makes things look weird. // clang-format off - MSG_BEGIN_ARRAY( forestSmallKeyDe ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(forestSmallKeyDe) + MSG_SPEED(MSG_SPEED_FAST) //Du erhältst "\x44\x75\x20\x65\x72\x68\xe4\x6c\x74\x73\x74\x20" MSG_COLOR(MSG_COLOR_RED) @@ -29,7 +29,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( shadowCrystalDe ) + MSG_BEGIN_ARRAY(shadowCrystalDe) MSG_SPEED(MSG_SPEED_SLOW) //Du erhältst den "\x44\x75\x20\x65\x72\x68\xe4\x6c\x74\x73\x74\x20\x64\x65\x6e\x20" @@ -46,7 +46,7 @@ namespace mod::customMessages //erlaubt es dir, dichnach Belieben zu verwandeln! "\x65\x72\x6c\x61\x75\x62\x74\x20\x65\x73\x20\x64\x69\x72\x2c\x20\x64\x69\x63\x68\x0A\x6e\x61\x63\x68\x20\x42\x65\x6c\x69\x65\x62\x65\x6e\x20\x7a\x75\x20\x76\x65\x72\x77\x61\x6e\x64\x65\x6c\x6e\x21" MSG_END(); - MSG_BEGIN_ARRAY( endingBlowDe ) + MSG_BEGIN_ARRAY(endingBlowDe) MSG_SPEED(MSG_SPEED_FAST) //Du erlernst den "\x44\x75\x20\x65\x72\x6c\x65\x72\x6e\x73\x74\x20\x64\x65\x6e\x20" @@ -57,7 +57,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( shieldAttackDe ) + MSG_BEGIN_ARRAY(shieldAttackDe) MSG_SPEED(MSG_SPEED_FAST) //Du erlernst die "\x44\x75\x20\x65\x72\x6c\x65\x72\x6e\x73\x74\x20\x64\x69\x65\x20" @@ -68,7 +68,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( backSliceDe ) + MSG_BEGIN_ARRAY(backSliceDe) MSG_SPEED(MSG_SPEED_FAST) //Du erlernst den "\x44\x75\x20\x65\x72\x6c\x65\x72\x6e\x73\x74\x20\x64\x65\x6e\x20" @@ -79,7 +79,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( helmSplitterDe ) + MSG_BEGIN_ARRAY(helmSplitterDe) MSG_SPEED(MSG_SPEED_FAST) //Du erlernst den "\x44\x75\x20\x65\x72\x6c\x65\x72\x6e\x73\x74\x20\x64\x65\x6e\x20" @@ -90,7 +90,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( mortalDrawDe ) + MSG_BEGIN_ARRAY(mortalDrawDe) MSG_SPEED(MSG_SPEED_FAST) //Du erlernst das "\x44\x75\x20\x65\x72\x6c\x65\x72\x6e\x73\x74\x20\x64\x61\x73\x20" @@ -101,7 +101,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( jumpStrikeDe ) + MSG_BEGIN_ARRAY(jumpStrikeDe) MSG_SPEED(MSG_SPEED_FAST) //Du erlernst die "\x44\x75\x20\x65\x72\x6c\x65\x72\x6e\x73\x74\x20\x64\x69\x65\x0A" @@ -112,7 +112,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( greatSpinDe ) + MSG_BEGIN_ARRAY(greatSpinDe) MSG_SPEED(MSG_SPEED_FAST) //Du erlernst die "\x44\x75\x20\x65\x72\x6c\x65\x72\x6e\x73\x74\x20\x64\x69\x65\x0A" @@ -123,7 +123,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( poweredRodDe ) + MSG_BEGIN_ARRAY(poweredRodDe) MSG_SPEED(MSG_SPEED_FAST) //Der "\x44\x65\x72\x20" @@ -134,7 +134,7 @@ namespace mod::customMessages //hat wiedermagische Kraft! Verwende ihn,um den antiken Statuen wiederLeben einzuhauchen. "\x68\x61\x74\x20\x77\x69\x65\x64\x65\x72\x0A\x6d\x61\x67\x69\x73\x63\x68\x65\x20\x4b\x72\x61\x66\x74\x21\x20\x56\x65\x72\x77\x65\x6e\x64\x65\x20\x69\x68\x6e\x2c\x0A\x75\x6d\x20\x64\x65\x6e\x20\x61\x6e\x74\x69\x6b\x65\x6e\x20\x53\x74\x61\x74\x75\x65\x6e\x20\x77\x69\x65\x64\x65\x72\x0A\x4c\x65\x62\x65\x6e\x20\x65\x69\x6e\x7a\x75\x68\x61\x75\x63\x68\x65\x6e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( skyBookCharacterDe ) + MSG_BEGIN_ARRAY(skyBookCharacterDe) MSG_SPEED(MSG_SPEED_FAST) // Du entdeckst ein "\x44\x75\x20\x65\x6E\x74\x64\x65\x63\x6B\x73\x74\x0A\x65\x69\x6E\x20" @@ -151,7 +151,7 @@ namespace mod::customMessages // gesammelt. "\x20\x67\x65\x73\x61\x6d\x6d\x65\x6c\x74\x2e" MSG_END(); - MSG_BEGIN_ARRAY( firstFusedShadowDe ) + MSG_BEGIN_ARRAY(firstFusedShadowDe) MSG_SPEED(MSG_SPEED_FAST) //Du erhältst einen "\x44\x75\x20\x65\x72\x68\xe4\x6c\x74\x73\x74\x20\x65\x69\x6e\x65\x6e\x0A" @@ -168,7 +168,7 @@ namespace mod::customMessages //darauf wachsen.. "\x64\x61\x72\x61\x75\x66\x20\x77\x61\x63\x68\x73\x65\x6e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( secondFusedShadowDe ) + MSG_BEGIN_ARRAY(secondFusedShadowDe) MSG_SPEED(MSG_SPEED_FAST) //Du erhältst den zweiten "\x44\x75\x20\x65\x72\x68\xe4\x6c\x74\x73\x74\x20\x64\x65\x6e\x20\x7a\x77\x65\x69\x74\x65\x6e\x0A" @@ -185,7 +185,7 @@ namespace mod::customMessages //an.. "\x61\x6e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( thirdFusedShadowDe ) + MSG_BEGIN_ARRAY(thirdFusedShadowDe) MSG_SPEED(MSG_SPEED_FAST) //Du erhältst den letzten "\x44\x75\x20\x65\x72\x68\xe4\x6c\x74\x73\x74\x20\x64\x65\x6e\x20\x6c\x65\x74\x7a\x74\x65\x6e\x0A" @@ -202,9 +202,26 @@ namespace mod::customMessages //steigtdir in die Nase.. "\x73\x74\x65\x69\x67\x74\x0A\x64\x69\x72\x20\x69\x6e\x20\x64\x69\x65\x20\x4e\x61\x73\x65\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( secondMirrorShardDe ) + MSG_BEGIN_ARRAY(firstMirrorShardDe) + MSG_SPEED(MSG_SPEED_FAST) + // Du hast die erste + "\x44\x75\x20\x68\x61\x73\x74\x20\x64\x69\x65\x20\x65\x72\x73\x74\x65\x0A" + MSG_COLOR(MSG_COLOR_RED) + //Schattenspiegels + "\x53\x63\x68\x61\x74\x74\x65\x6e\x73\x70\x69\x65\x67\x65\x6c\x73" + MSG_COLOR(MSG_COLOR_WHITE) + // gefunden! Sie ist von + "\x67\x65\x66\x75\x6E\x64\x65\x6E\x21\x0A\x53\x69\x65\x20\x69\x73\x74\x20\x76\x6F\x6E\x20" + MSG_COLOR(MSG_COLOR_ORANGE) + // Sand + "\x53\x61\x6E\x64" + MSG_COLOR(MSG_COLOR_WHITE) + // bedeckt... + "\x20\x62\x65\x64\x65\x63\x6B\x74\x2E\x2E\x2E" + MSG_END(); + MSG_BEGIN_ARRAY(secondMirrorShardDe) MSG_SPEED(MSG_SPEED_FAST) - //Du erhältst die zweiteScherbe des + //Du erhältst die zweite Scherbe des "\x44\x75\x20\x65\x72\x68\xe4\x6c\x74\x73\x74\x20\x64\x69\x65\x20\x7a\x77\x65\x69\x74\x65\x0A\x53\x63\x68\x65\x72\x62\x65\x20\x64\x65\x73\x20" MSG_COLOR(MSG_COLOR_RED) //Schattenspiegels @@ -219,7 +236,7 @@ namespace mod::customMessages //glitzert im Licht um dich herum.. "\x67\x6c\x69\x74\x7a\x65\x72\x74\x20\x69\x6d\x20\x4c\x69\x63\x68\x74\x20\x75\x6d\x20\x64\x69\x63\x68\x20\x68\x65\x72\x75\x6d\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( thirdMirrorShardDe ) + MSG_BEGIN_ARRAY(thirdMirrorShardDe) MSG_SPEED(MSG_SPEED_FAST) //Du erhältst die dritteScherbe des "\x44\x75\x20\x65\x72\x68\xe4\x6c\x74\x73\x74\x20\x64\x69\x65\x20\x64\x72\x69\x74\x74\x65\x0A\x53\x63\x68\x65\x72\x62\x65\x20\x64\x65\x73\x20" @@ -236,7 +253,7 @@ namespace mod::customMessages //.. "\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( fourthMirrorShardDe ) + MSG_BEGIN_ARRAY(fourthMirrorShardDe) MSG_SPEED(MSG_SPEED_FAST) //Du erhältst die letzteScherbe des "\x44\x75\x20\x65\x72\x68\xe4\x6c\x74\x73\x74\x20\x64\x69\x65\x20\x6c\x65\x74\x7a\x74\x65\x0A\x53\x63\x68\x65\x72\x62\x65\x20\x64\x65\x73\x20" @@ -253,7 +270,7 @@ namespace mod::customMessages //an.. "\x61\x6e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( foolishItemDe ) + MSG_BEGIN_ARRAY(foolishItemDe) MSG_SPEED(MSG_SPEED_FAST) //Ein "\x45\x69\x6e\x20" @@ -262,9 +279,9 @@ namespace mod::customMessages "\x6b\x61\x6c\x74\x65\x72" MSG_COLOR(MSG_COLOR_WHITE) // wind weht.. - "\x20\x77\x69\x6e\x64\x20\x77\x65\x68\x74\x2e\x2e" + "\x20\x77\x69\x6e\x64\x20\x77\x65\x68\x74\x2e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( talkToMidnaDe ) + MSG_BEGIN_ARRAY(talkToMidnaDe) //Was ist los, "\x57\x61\x73\x20\x69\x73\x74\x20\x6c\x6f\x73\x2c\x20" MSG_PLYR_NAME @@ -280,7 +297,7 @@ namespace mod::customMessages //Tageszeit ändern "\x54\x61\x67\x65\x73\x7a\x65\x69\x74\x20\xe4\x6e\x64\x65\x72\x6e" MSG_END(); - MSG_BEGIN_ARRAY( bigWalletDe ) + MSG_BEGIN_ARRAY(bigWalletDe) MSG_COLOR(MSG_COLOR_RED) "\x47\x72\x6f\xdf\x65\x20\x47\x65\x6c\x64\x62\xf6\x72\x73\x65\x20" MSG_COLOR(MSG_COLOR_WHITE) @@ -290,7 +307,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "\x61\x75\x66\x62\x65\x77\x61\x68\x72\x65\x6e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( giantWalletDe ) + MSG_BEGIN_ARRAY(giantWalletDe) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) "\x4d\x61\x78\x69\x2d\x47\x65\x6c\x64\x62\xf6\x72\x73\x65\x20" @@ -301,23 +318,23 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "\x61\x75\x66\x62\x65\x77\x61\x68\x72\x65\x6e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( smallWalletPauseDe ) + MSG_BEGIN_ARRAY(smallWalletPauseDe) MSG_SPEED(MSG_SPEED_FAST) // Schon seit vielen Jahren in deinem Besitz. Sie fasst bis zu 1000 Rubine. "\x53\x63\x68\x6F\x6E\x20\x73\x65\x69\x74\x20\x76\x69\x65\x6C\x65\x6E\x20\x4A\x61\x68\x72\x65\x6E\x20\x69\x6E\x0A\x64\x65\x69\x6E\x65\x6D\x20\x42\x65\x73\x69\x74\x7A\x2E\x20\x53\x69\x65\x20\x66\x61\x73\x73\x74\x20\x62\x69\x73\x0A\x7A\x75\x20\x31\x30\x30\x30\x20\x52\x75\x62\x69\x6E\x65\x2E" MSG_END(); - MSG_BEGIN_ARRAY( bigWalletPauseDe ) + MSG_BEGIN_ARRAY(bigWalletPauseDe) MSG_SPEED(MSG_SPEED_FAST) // Geldbörse von Agnetha, der Königin des Insektenreichs. Bewahre in ihr bis zu 5000 Rubine auf! "\x47\x65\x6C\x64\x62\xF6\x72\x73\x65\x20\x76\x6F\x6E\x20\x41\x67\x6E\x65\x74\x68\x61\x2C\x20\x64\x65\x72\x20\x4B\xF6\x6E\x69\x67\x69\x6E\x0A\x64\x65\x73\x20\x49\x6E\x73\x65\x6B\x74\x65\x6E\x72\x65\x69\x63\x68\x73\x2E\x20\x42\x65\x77\x61\x68\x72\x65\x20\x69\x6E\x20\x69\x68\x72\x0A\x62\x69\x73\x20\x7A\x75\x20\x35\x30\x30\x30\x20\x52\x75\x62\x69\x6E\x65\x20\x61\x75\x66\x21" MSG_END(); - MSG_BEGIN_ARRAY( giantWalletPauseDe ) + MSG_BEGIN_ARRAY(giantWalletPauseDe) MSG_SPEED(MSG_SPEED_FAST) // Ein Geschenk von Agnetha: Höchste Auszeichnung, die das Insektenreich bietet. Fasst bis zu 9999 Rubine. "\x45\x69\x6E\x20\x47\x65\x73\x63\x68\x65\x6E\x6B\x20\x76\x6F\x6E\x20\x41\x67\x6E\x65\x74\x68\x61\x3A\x20\x48\xF6\x63\x68\x73\x74\x65\x0A\x41\x75\x73\x7A\x65\x69\x63\x68\x6E\x75\x6E\x67\x2C\x20\x64\x69\x65\x20\x64\x61\x73\x20\x49\x6E\x73\x65\x6B\x74\x65\x6E\x72\x65\x69\x63\x68\x0A\x62\x69\x65\x74\x65\x74\x2E\x20\x46\x61\x73\x73\x74\x20\x62\x69\x73\x20\x7A\x75\x20\x39\x39\x39\x39\x20\x52\x75\x62\x69\x6E\x65\x2E" MSG_END(); - MSG_BEGIN_ARRAY( poeSoulDe ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(poeSoulDe) + MSG_SPEED(MSG_SPEED_FAST) // Du erhältst eine "\x44\x75\x20\x65\x72\x68\xe4\x6c\x74\x73\x74\x20\x65\x69\x6e\x65\x20" MSG_COLOR(MSG_COLOR_RED) @@ -333,7 +350,7 @@ namespace mod::customMessages // gesammelt. "\x20\x67\x65\x73\x61\x6d\x6d\x65\x6c\x74\x2e" MSG_END(); - MSG_BEGIN_ARRAY( skyBookDescriptionDe ) + MSG_BEGIN_ARRAY(skyBookDescriptionDe) MSG_SPEED(MSG_SPEED_FAST) // Text, der in altem Kumulanisch ver-\nfasst ist. Leider fehlen einige Buchstaben.\nEr enthält wichtige Hinweise // für die Reise\nnach Kumula.\n\nDu hast bisher 0 @@ -345,20 +362,20 @@ namespace mod::customMessages // gesammelt. "\x20\x67\x65\x73\x61\x6d\x6d\x65\x6c\x74\x2e" MSG_END(); - MSG_BEGIN_ARRAY( charloDonationDe ) + MSG_BEGIN_ARRAY(charloDonationDe) // ...eine kleine Spende? Für den Frieden in Hyrule? "\x2E\x2E\x2E\x65\x69\x6E\x65\x20\x6B\x6C\x65\x69\x6E\x65\x20\x53\x70\x65\x6E\x64\x65\x3F\x0A\x46\xFC\x72\x20\x64\x65\x6E\x20\x46\x72\x69\x65\x64\x65\x6E\x20\x69\x6E\x20\x48\x79\x72\x75\x6C\x65\x3F" - MSG_OPTION_LIST( MSG_OPTION_1 ) + MSG_OPTION_LIST(MSG_OPTION_1) // 100 Rubine "\x31\x30\x30\x20\x52\x75\x62\x69\x6E\x65\x0A" - MSG_OPTION_LIST( MSG_OPTION_2 ) + MSG_OPTION_LIST(MSG_OPTION_2) // 50 Rubine "\x35\x30\x20\x52\x75\x62\x69\x6E\x65\x0A" - MSG_OPTION_LIST( MSG_OPTION_3 ) + MSG_OPTION_LIST(MSG_OPTION_3) // Nein danke! "\x4E\x65\x69\x6E\x20\x64\x61\x6E\x6B\x65\x21"; MSG_END(); - MSG_BEGIN_ARRAY( recognitionDe ) + MSG_BEGIN_ARRAY(recognitionDe) MSG_SPEED(MSG_SPEED_FAST) // Das gesamte Randomizer Team möchte sich bei unseren fantastischen Testern bedanken. Ohne euch wäre das Projekt nicht, was es heute ist. "\x44\x61\x73\x20\x67\x65\x73\x61\x6D\x74\x65\x20\x52\x61\x6E\x64\x6F\x6D\x69\x7A\x65\x72\x20\x54\x65\x61\x6D\n\x6D\xF6\x63\x68\x74\x65\x20\x73\x69\x63\x68\x20\x62\x65\x69\x20\x75\x6E\x73\x65\x72\x65\x6E\n\x66\x61\x6E\x74\x61\x73\x74\x69\x73\x63\x68\x65\x6E\x20\x54\x65\x73\x74\x65\x72\x6E\x20\x62\x65\x64\x61\x6E\x6B\x65\x6E\x2E\n\x4F\x68\x6E\x65\x20\x65\x75\x63\x68\x20\x77\xE4\x72\x65\x20\x64\x61\x73\x20\x50\x72\x6F\x6A\x65\x6B\x74\n\x6E\x69\x63\x68\x74\x2C\x20\x77\x61\x73\x20\x65\x73\x20\x68\x65\x75\x74\x65\x20\x69\x73\x74: Taka\nAnorakkis, Archer, Br00ty, Chris\nChrono, clabrus, Demon, EmperorP\nElinadrian, Empty, Fennec, Zushi\nFleakee, Foxhole Gaming, Luzagar\nHeartPiece, Hornlitz, IceStorm\nJanWegh, JD, jdflyer, Jeez, Oxy\nJustRyland, Lance H., link1183\nLinkman124, Luneyes, GameWyrm\nMattStrats, MultFij, NesmaN88\nXenoWars, Papy_Grant, Simikins\npokemongenius, Psi-Hate, Lars P\nRaziel_Stratton, Redriel, Revven\nSparky7198, Zach, SwiftIke, j_im\nZenith, Prince, The., TheBruce\nTreZc0_, Wameslo, WickedGligar\nDGod63 and Sushi." @@ -452,6 +469,11 @@ namespace mod::customMessages sizeof(thirdFusedShadowDe), 0x013E, + // First Mirror Shard + firstMirrorShardDe, + sizeof(firstMirrorShardDe), + 0x0B7, + // Second Mirror Shard secondMirrorShardDe, sizeof(secondMirrorShardDe), diff --git a/GameCube/subrel/boot/source/custom_messages/italianMessages.cpp b/GameCube/subrel/boot/source/custom_messages/italianMessages.cpp index 7362ff4f..e399f388 100644 --- a/GameCube/subrel/boot/source/custom_messages/italianMessages.cpp +++ b/GameCube/subrel/boot/source/custom_messages/italianMessages.cpp @@ -16,8 +16,8 @@ namespace mod::customMessages // Disable formatting for the textbox messages because it makes things look weird. // clang-format off - MSG_BEGIN_ARRAY( forestSmallKeyIt ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(forestSmallKeyIt) + MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20" MSG_COLOR(MSG_COLOR_RED) @@ -29,7 +29,7 @@ namespace mod::customMessages MSG_COLOR(MSG_COLOR_WHITE) "!" MSG_END(); - MSG_BEGIN_ARRAY( minesSmallKeyIt ) + MSG_BEGIN_ARRAY(minesSmallKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -46,7 +46,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( lakebedSmallKeyIt ) + MSG_BEGIN_ARRAY(lakebedSmallKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -63,7 +63,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( arbitersSmallKeyIt ) + MSG_BEGIN_ARRAY(arbitersSmallKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -80,7 +80,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( snowpeakSmallKeyIt ) + MSG_BEGIN_ARRAY(snowpeakSmallKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -97,7 +97,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( timeSmallKeyIt ) + MSG_BEGIN_ARRAY(timeSmallKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -114,7 +114,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( citySmallKeyIt ) + MSG_BEGIN_ARRAY(citySmallKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -131,7 +131,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( palaceSmallKeyIt ) + MSG_BEGIN_ARRAY(palaceSmallKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -148,7 +148,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( hyruleSmallKeyIt ) + MSG_BEGIN_ARRAY(hyruleSmallKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -165,7 +165,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( campSmallKeyIt ) + MSG_BEGIN_ARRAY(campSmallKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -182,7 +182,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( shadowCrystalIt ) + MSG_BEGIN_ARRAY(shadowCrystalIt) MSG_SPEED(MSG_SPEED_SLOW) //Ora hai il "\x4f\x72\x61\x20\x68\x61\x69\x20\x69\x6c\x20" @@ -199,7 +199,7 @@ namespace mod::customMessages //ti permette sitransformarti quando vuoi. "\x74\x69\x20\x70\x65\x72\x6d\x65\x74\x74\x65\x20\x73\x69\x0A\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x61\x72\x74\x69\x20\x71\x75\x61\x6e\x64\x6f\x20\x76\x75\x6f\x69\x2e\x20" MSG_END(); - MSG_BEGIN_ARRAY( forestDungeonMapIt ) + MSG_BEGIN_ARRAY(forestDungeonMapIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto la "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x6c\x61\x20" @@ -216,7 +216,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( minesDungeonMapIt ) + MSG_BEGIN_ARRAY(minesDungeonMapIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto la "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x6c\x61\x20" @@ -233,7 +233,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( lakebedDungeonMapIt ) + MSG_BEGIN_ARRAY(lakebedDungeonMapIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto la "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x6c\x61\x20" @@ -250,7 +250,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( arbitersDungeonMapIt ) + MSG_BEGIN_ARRAY(arbitersDungeonMapIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto la "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x6c\x61\x20" @@ -267,7 +267,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( snowpeakDungeonMapIt ) + MSG_BEGIN_ARRAY(snowpeakDungeonMapIt) MSG_SPEED(MSG_SPEED_FAST) //Ora hai la "\x4f\x72\x61\x20\x68\x61\x69\x20\x6c\x61\x20" @@ -284,7 +284,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( timeDungeonMapIt ) + MSG_BEGIN_ARRAY(timeDungeonMapIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto la "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x6c\x61\x20" @@ -301,7 +301,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( cityDungeonMapIt ) + MSG_BEGIN_ARRAY(cityDungeonMapIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto la "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x6c\x61\x20" @@ -318,7 +318,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( palaceDungeonMapIt ) + MSG_BEGIN_ARRAY(palaceDungeonMapIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto la "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x6c\x61\x20" @@ -335,7 +335,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( hyruleDungeonMapIt ) + MSG_BEGIN_ARRAY(hyruleDungeonMapIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto la "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x6c\x61\x20" @@ -352,7 +352,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( forestCompassIt ) + MSG_BEGIN_ARRAY(forestCompassIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -369,7 +369,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( minesCompassIt ) + MSG_BEGIN_ARRAY(minesCompassIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -386,7 +386,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( lakebedCompassIt ) + MSG_BEGIN_ARRAY(lakebedCompassIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -403,7 +403,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( arbitersCompassIt ) + MSG_BEGIN_ARRAY(arbitersCompassIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -420,7 +420,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( snowpeakCompassIt ) + MSG_BEGIN_ARRAY(snowpeakCompassIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -437,7 +437,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( timeCompassIt ) + MSG_BEGIN_ARRAY(timeCompassIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -454,7 +454,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( cityCompassIt ) + MSG_BEGIN_ARRAY(cityCompassIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -471,7 +471,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( palaceCompassIt ) + MSG_BEGIN_ARRAY(palaceCompassIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -488,7 +488,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( hyruleCompassIt ) + MSG_BEGIN_ARRAY(hyruleCompassIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -505,7 +505,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( forestBigKeyIt ) + MSG_BEGIN_ARRAY(forestBigKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -522,7 +522,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( lakebedBigKeyIt ) + MSG_BEGIN_ARRAY(lakebedBigKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -539,7 +539,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( arbitersBigKeyIt ) + MSG_BEGIN_ARRAY(arbitersBigKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -556,7 +556,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( timeBigKeyIt ) + MSG_BEGIN_ARRAY(timeBigKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -573,7 +573,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( cityBigKeyIt ) + MSG_BEGIN_ARRAY(cityBigKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -590,7 +590,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( palaceBigKeyIt ) + MSG_BEGIN_ARRAY(palaceBigKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -607,7 +607,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( hyruleBigKeyIt ) + MSG_BEGIN_ARRAY(hyruleBigKeyIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto una "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x61\x20" @@ -624,7 +624,7 @@ namespace mod::customMessages //. "\x2e" MSG_END(); - MSG_BEGIN_ARRAY( endingBlowIt ) + MSG_BEGIN_ARRAY(endingBlowIt) MSG_SPEED(MSG_SPEED_FAST) //Hai appreso il "\x48\x61\x69\x20\x61\x70\x70\x72\x65\x73\x6f\x20\x69\x6c\x20" @@ -635,7 +635,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( shieldAttackIt ) + MSG_BEGIN_ARRAY(shieldAttackIt) MSG_SPEED(MSG_SPEED_FAST) //Hai appreso l' "\x48\x61\x69\x20\x61\x70\x70\x72\x65\x73\x6f\x20\x6c\x27" @@ -646,7 +646,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( backSliceIt ) + MSG_BEGIN_ARRAY(backSliceIt) MSG_SPEED(MSG_SPEED_FAST) //Hai appreso il "\x48\x61\x69\x20\x61\x70\x70\x72\x65\x73\x6f\x20\x69\x6c\x20" @@ -657,7 +657,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( helmSplitterIt ) + MSG_BEGIN_ARRAY(helmSplitterIt) MSG_SPEED(MSG_SPEED_FAST) //Hai appreso lo "\x48\x61\x69\x20\x61\x70\x70\x72\x65\x73\x6f\x20\x6c\x6f\x20" @@ -668,7 +668,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( mortalDrawIt ) + MSG_BEGIN_ARRAY(mortalDrawIt) MSG_SPEED(MSG_SPEED_FAST) //Hai appreso il "\x48\x61\x69\x20\x61\x70\x70\x72\x65\x73\x6f\x20\x69\x6c\x20" @@ -679,7 +679,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( jumpStrikeIt ) + MSG_BEGIN_ARRAY(jumpStrikeIt) MSG_SPEED(MSG_SPEED_FAST) //Hai appreso il "\x48\x61\x69\x20\x61\x70\x70\x72\x65\x73\x6f\x20\x69\x6c\x20" @@ -690,7 +690,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( greatSpinIt ) + MSG_BEGIN_ARRAY(greatSpinIt) MSG_SPEED(MSG_SPEED_FAST) //Hai appreso il "\x48\x61\x69\x20\x61\x70\x70\x72\x65\x73\x6f\x20\x69\x6c\x20" @@ -701,7 +701,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( poweredRodIt ) + MSG_BEGIN_ARRAY(poweredRodIt) MSG_SPEED(MSG_SPEED_FAST) //Lo "\x4c\x6f\x20" @@ -712,7 +712,7 @@ namespace mod::customMessages //è dotatodi nuovo di poteri magici! Puòinfondere vita alle antichestatue, anche nel presente. "\xe8\x20\x64\x6f\x74\x61\x74\x6f\x0A\x64\x69\x20\x6e\x75\x6f\x76\x6f\x20\x64\x69\x20\x70\x6f\x74\x65\x72\x69\x20\x6d\x61\x67\x69\x63\x69\x21\x20\x50\x75\xf2\x0A\x69\x6e\x66\x6f\x6e\x64\x65\x72\x65\x20\x76\x69\x74\x61\x20\x61\x6c\x6c\x65\x20\x61\x6e\x74\x69\x63\x68\x65\x0A\x73\x74\x61\x74\x75\x65\x2c\x20\x61\x6e\x63\x68\x65\x20\x6e\x65\x6c\x20\x70\x72\x65\x73\x65\x6e\x74\x65\x2e" MSG_END(); - MSG_BEGIN_ARRAY( skyBookCharacterIt ) + MSG_BEGIN_ARRAY(skyBookCharacterIt) MSG_SPEED(MSG_SPEED_FAST) // Ecco delle "\x45\x63\x63\x6F\x20\x64\x65\x6C\x6C\x65\x20" @@ -729,7 +729,7 @@ namespace mod::customMessages // finora. "\x20\x66\x69\x6E\x6F\x72\x61\x2E" MSG_END(); - MSG_BEGIN_ARRAY( firstFusedShadowIt ) + MSG_BEGIN_ARRAY(firstFusedShadowIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto un frammento di "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x75\x6e\x20\x66\x72\x61\x6d\x6d\x65\x6e\x74\x6f\x20\x64\x69\x0A" @@ -746,7 +746,7 @@ namespace mod::customMessages //crescendo sopra lui.. "\x63\x72\x65\x73\x63\x65\x6e\x64\x6f\x20\x73\x6f\x70\x72\x61\x20\x6c\x75\x69\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( secondFusedShadowIt ) + MSG_BEGIN_ARRAY(secondFusedShadowIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto il secondoframmento di "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x69\x6c\x20\x73\x65\x63\x6f\x6e\x64\x6f\x0A\x66\x72\x61\x6d\x6d\x65\x6e\x74\x6f\x20\x64\x69\x20" @@ -763,7 +763,7 @@ namespace mod::customMessages //come fuoco.. "\x63\x6f\x6d\x65\x20\x66\x75\x6f\x63\x6f\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( thirdFusedShadowIt ) + MSG_BEGIN_ARRAY(thirdFusedShadowIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto il utilmoframmento di "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x69\x6c\x20\x75\x74\x69\x6c\x6d\x6f\x0A\x66\x72\x61\x6d\x6d\x65\x6e\x74\x6f\x20\x64\x69\x20" @@ -780,7 +780,24 @@ namespace mod::customMessages //!? "\x21\x3f" MSG_END(); - MSG_BEGIN_ARRAY( secondMirrorShardIt ) + MSG_BEGIN_ARRAY(firstMirrorShardIt) + MSG_SPEED(MSG_SPEED_FAST) + //Hai ottenuto il primo\nframmento del + "\x48\x61\x69\x20\x6F\x74\x74\x65\x6E\x75\x74\x6F\x20\x69\x6C\x20\x70\x72\x69\x6D\x6F\x0A\x66\x72\x61\x6D\x6D\x65\x6E\x74\x6F\x20\x64\x65\x6C\x20" + MSG_COLOR(MSG_COLOR_RED) + //Specchio oscuro + "\x53\x70\x65\x63\x63\x68\x69\x6f\x20\x6f\x73\x63\x75\x72\x6f" + MSG_COLOR(MSG_COLOR_WHITE) + //!È coperto di + "\x21\x0A\xC8\x20\x63\x6F\x70\x65\x72\x74\x6F\x20\x64\x69\x20" + MSG_COLOR(MSG_COLOR_ORANGE) + //sabbia + "\x73\x61\x62\x62\x69\x61" + MSG_COLOR(MSG_COLOR_WHITE) + //.. + "\x2e\x2e" + MSG_END(); + MSG_BEGIN_ARRAY(secondMirrorShardIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto il secondoframmento del "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x69\x6c\x20\x73\x65\x63\x6f\x6e\x64\x6f\x0A\x66\x72\x61\x6d\x6d\x65\x6e\x74\x6f\x20\x64\x65\x6c\x20" @@ -797,7 +814,7 @@ namespace mod::customMessages //.. "\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( thirdMirrorShardIt ) + MSG_BEGIN_ARRAY(thirdMirrorShardIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto il terzoframmento del "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x69\x6c\x20\x74\x65\x72\x7a\x6f\x0A\x66\x72\x61\x6d\x6d\x65\x6e\x74\x6f\x20\x64\x65\x6c\x20" @@ -814,7 +831,7 @@ namespace mod::customMessages //.. "\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( fourthMirrorShardIt ) + MSG_BEGIN_ARRAY(fourthMirrorShardIt) MSG_SPEED(MSG_SPEED_FAST) //Hai ottenuto il ultimo frammento del "\x48\x61\x69\x20\x6f\x74\x74\x65\x6e\x75\x74\x6f\x20\x69\x6c\x20\x75\x6c\x74\x69\x6d\x6f\x20\x66\x72\x61\x6d\x6d\x65\x6e\x74\x6f\x0A\x64\x65\x6c\x20" @@ -831,7 +848,7 @@ namespace mod::customMessages //.. "\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( foolishItemIt ) + MSG_BEGIN_ARRAY(foolishItemIt) MSG_SPEED(MSG_SPEED_FAST) //Un "\x55\x6e\x20" @@ -840,9 +857,9 @@ namespace mod::customMessages "\x76\x65\x6e\x74\x6f\x20\x66\x72\x65\x64\x64\x6f\x20" MSG_COLOR(MSG_COLOR_WHITE) //soffia.. - "\x73\x6f\x66\x66\x69\x61\x2e\x2e" + "\x73\x6f\x66\x66\x69\x61\x2e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( talkToMidnaIt ) + MSG_BEGIN_ARRAY(talkToMidnaIt) //Cosa vuoi, "\x43\x6f\x73\x61\x20\x76\x75\x6f\x69\x2c\x20" MSG_PLYR_NAME @@ -858,7 +875,7 @@ namespace mod::customMessages //Cambiare il tempo del giorno "\x43\x61\x6d\x62\x69\x61\x72\x65\x20\x69\x6c\x20\x74\x65\x6d\x70\x6f\x20\x64\x65\x6c\x20\x67\x69\x6f\x72\x6e\x6f" MSG_END(); - MSG_BEGIN_ARRAY( bigWalletIt ) + MSG_BEGIN_ARRAY(bigWalletIt) MSG_SPEED(MSG_SPEED_FAST) //Ora hai un "\x4f\x72\x61\x20\x68\x61\x69\x20\x75\x6e\x20" @@ -875,7 +892,7 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( giantWalletIt ) + MSG_BEGIN_ARRAY(giantWalletIt) MSG_SPEED(MSG_SPEED_FAST) //Ora hai un "\x4f\x72\x61\x20\x68\x61\x69\x20\x75\x6e\x20" @@ -892,23 +909,23 @@ namespace mod::customMessages //! "\x21" MSG_END(); - MSG_BEGIN_ARRAY( smallWalletPauseIt ) + MSG_BEGIN_ARRAY(smallWalletPauseIt) MSG_SPEED(MSG_SPEED_FAST) //Oggetto dell'infanzia. Può contenere fino a 1000 Rupie. "\x4F\x67\x67\x65\x74\x74\x6F\x20\x64\x65\x6C\x6C\x27\x69\x6E\x66\x61\x6E\x7A\x69\x61\x2E\x20\x50\x75\xF2\x0A\x63\x6F\x6E\x74\x65\x6E\x65\x72\x65\x20\x66\x69\x6E\x6F\x20\x61\x20\x31\x2E\x30\x30\x30\x20\x52\x75\x70\x69\x65\x2E" MSG_END(); - MSG_BEGIN_ARRAY( bigWalletPauseIt ) + MSG_BEGIN_ARRAY(bigWalletPauseIt) MSG_SPEED(MSG_SPEED_FAST) // Portarupie ricevuto in dono da Xenia, la principessa del regno degli insetti. Può contenere fino a 5000 Rupie. "\x50\x6F\x72\x74\x61\x72\x75\x70\x69\x65\x20\x72\x69\x63\x65\x76\x75\x74\x6F\x20\x69\x6E\x20\x64\x6F\x6E\x6F\x0A\x64\x61\x20\x58\x65\x6E\x69\x61\x2C\x20\x6C\x61\x20\x70\x72\x69\x6E\x63\x69\x70\x65\x73\x73\x61\x20\x64\x65\x6C\x0A\x72\x65\x67\x6E\x6F\x20\x64\x65\x67\x6C\x69\x20\x69\x6E\x73\x65\x74\x74\x69\x2E\x20\x50\x75\xF2\x0A\x63\x6F\x6E\x74\x65\x6E\x65\x72\x65\x20\x66\x69\x6E\x6F\x20\x61\x20\x35\x2E\x30\x30\x30\x20\x52\x75\x70\x69\x65\x2E" MSG_END(); - MSG_BEGIN_ARRAY( giantWalletPauseIt ) + MSG_BEGIN_ARRAY(giantWalletPauseIt) MSG_SPEED(MSG_SPEED_FAST) // Portarupie ricevuto in dono da Xenia, la principessa del regno degli insetti. Lo merita solo chi ha aiutato il regno. Può contenere fino a 9.999 Rupie. "\x50\x6F\x72\x74\x61\x72\x75\x70\x69\x65\x20\x72\x69\x63\x65\x76\x75\x74\x6F\x20\x69\x6E\x20\x64\x6F\x6E\x6F\x20\x64\x61\x20\x58\x65\x6E\x69\x61\x2C\x0A\x6C\x61\x20\x70\x72\x69\x6E\x63\x69\x70\x65\x73\x73\x61\x20\x64\x65\x6C\x20\x72\x65\x67\x6E\x6F\x20\x64\x65\x67\x6C\x69\x20\x69\x6E\x73\x65\x74\x74\x69\x2E\x0A\x4C\x6F\x20\x6D\x65\x72\x69\x74\x61\x20\x73\x6F\x6C\x6F\x20\x63\x68\x69\x20\x68\x61\x20\x61\x69\x75\x74\x61\x74\x6F\x20\x69\x6C\x20\x72\x65\x67\x6E\x6F\x2E\x0A\x50\x75\xF2\x20\x63\x6F\x6E\x74\x65\x6E\x65\x72\x65\x20\x66\x69\x6E\x6F\x20\x61\x20\x39\x2E\x39\x39\x39\x20\x52\x75\x70\x69\x65\x2E" MSG_END(); - MSG_BEGIN_ARRAY( poeSoulIt ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(poeSoulIt) + MSG_SPEED(MSG_SPEED_FAST) // Ora hai un' "\x4f\x72\x61\x20\x68\x61\x69\x20\x75\x6e\x27" MSG_COLOR(MSG_COLOR_RED) @@ -924,7 +941,7 @@ namespace mod::customMessages // finora. "\x20\x66\x69\x6e\x6f\x72\x61\x2e" MSG_END(); - MSG_BEGIN_ARRAY( skyBookDescriptionIt ) + MSG_BEGIN_ARRAY(skyBookDescriptionIt) MSG_SPEED(MSG_SPEED_FAST) // Documento stilato nell'antica scrittura\ndegli Eterei. Alcune Lettere sono\nilleggibili...\n\nHai raccolto "\x44\x6F\x63\x75\x6D\x65\x6E\x74\x6F\x20\x73\x74\x69\x6C\x61\x74\x6F\x20\x6E\x65\x6C\x6C\x27\x61\x6E\x74\x69\x63\x61\x20\x73\x63\x72\x69\x74\x74\x75\x72\x61\x0A\x64\x65\x67\x6C\x69\x20\x45\x74\x65\x72\x65\x69\x2E\x20\x41\x6C\x63\x75\x6E\x65\x20\x4C\x65\x74\x74\x65\x72\x65\x20\x73\x6F\x6E\x6F\x0A\x69\x6C\x6C\x65\x67\x67\x69\x62\x69\x6C\x69\x2E\x2E\x2E\x0A\x0A\x48\x61\x69\x20\x72\x61\x63\x63\x6F\x6C\x74\x6F\x20" @@ -935,21 +952,21 @@ namespace mod::customMessages // finora. "\x20\x66\x69\x6E\x6F\x72\x61\x2E" MSG_END(); - MSG_BEGIN_ARRAY( charloDonationIt ) + MSG_BEGIN_ARRAY(charloDonationIt) // Avresti qualche spicciolo da dare per la pace di Hyrule? "\x41\x76\x72\x65\x73\x74\x69\x20\x71\x75\x61\x6C\x63\x68\x65\x20\x73\x70\x69\x63\x63\x69\x6F\x6C\x6F\x20\x64\x61\x0A\x64\x61\x72\x65\x20\x70\x65\x72\x20\x6C\x61\x20\x70\x61\x63\x65\x20\x64\x69\x20\x48\x79\x72\x75\x6C\x65\x3F\x31" - MSG_OPTION_LIST( MSG_OPTION_1 ) + MSG_OPTION_LIST(MSG_OPTION_1) // 100 Rupie "\x31\x30\x30\x20\x52\x75\x70\x69\x65\x0A" - MSG_OPTION_LIST( MSG_OPTION_2 ) + MSG_OPTION_LIST(MSG_OPTION_2) // 50 Rupie "\x35\x30\x20\x52\x75\x70\x69\x65\x0A" - MSG_OPTION_LIST( MSG_OPTION_3 ) + MSG_OPTION_LIST(MSG_OPTION_3) // No "\x4E\x6F"; MSG_END(); - MSG_BEGIN_ARRAY( recognitionIt ) + MSG_BEGIN_ARRAY(recognitionIt) MSG_SPEED(MSG_SPEED_FAST) // La Squadra Randomizer vuole ringraziare ai nostri fantastici tester. Senza di voi, questo progetto non sarebbe quello lo che è oggi "\x4C\x61\x20\x53\x71\x75\x61\x64\x72\x61\x20\x52\x61\x6E\x64\x6F\x6D\x69\x7A\x65\x72\x20\x76\x75\x6F\x6C\x65\n\x72\x69\x6E\x67\x72\x61\x7A\x69\x61\x72\x65\x20\x61\x69\x20\x6E\x6F\x73\x74\x72\x69\n\x66\x61\x6E\x74\x61\x73\x74\x69\x63\x69\x20\x74\x65\x73\x74\x65\x72\x2E\x20\x53\x65\x6E\x7A\x61\x20\x64\x69\n\x76\x6F\x69\x2C\x20\x71\x75\x65\x73\x74\x6F\x20\x70\x72\x6F\x67\x65\x74\x74\x6F\x20\x6E\x6F\x6E\n\x73\x61\x72\x65\x62\x62\x65\x20\x71\x75\x65\x6C\x6C\x6F\x20\x6C\x6F\x20\x63\x68\x65\x20\xE8\x20\x6F\x67\x67\x69: Taka\nAnorakkis, Archer, Br00ty, Chris\nChrono, clabrus, Demon, EmperorP\nElinadrian, Empty, Fennec, Zushi\nFleakee, Foxhole Gaming, Luzagar\nHeartPiece, Hornlitz, IceStorm\nJanWegh, JD, jdflyer, Jeez, Oxy\nJustRyland, Lance H., link1183\nLinkman124, Luneyes, GameWyrm\nMattStrats, MultFij, NesmaN88\nXenoWars, Papy_Grant, Simikins\npokemongenius, Psi-Hate, Lars P\nRaziel_Stratton, Redriel, Revven\nSparky7198, Zach, SwiftIke, j_im\nZenith, Prince, The., TheBruce\nTreZc0_, Wameslo, WickedGligar\nDGod63 and Sushi." @@ -1043,6 +1060,11 @@ namespace mod::customMessages sizeof(thirdFusedShadowIt), 0x013E, + // First Mirror Shard + firstMirrorShardIt, + sizeof(firstMirrorShardIt), + 0x0B7, + // Second Mirror Shard secondMirrorShardIt, sizeof(secondMirrorShardIt), diff --git a/GameCube/subrel/boot/source/custom_messages/japaneseMessages.cpp b/GameCube/subrel/boot/source/custom_messages/japaneseMessages.cpp index fe3b9e96..df7b8286 100644 --- a/GameCube/subrel/boot/source/custom_messages/japaneseMessages.cpp +++ b/GameCube/subrel/boot/source/custom_messages/japaneseMessages.cpp @@ -16,8 +16,8 @@ namespace mod::customMessages // Disable formatting for the textbox messages because it makes things look weird. // clang-format off - MSG_BEGIN_ARRAY( forestSmallKeyJp ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(forestSmallKeyJp) + MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_GREEN) // Y "%s" @@ -31,8 +31,8 @@ namespace mod::customMessages // を手に入れ "\x82\xF0\x8E\xE8\x82\xC9\x93\xFC\x82\xEA" MSG_END(); - MSG_BEGIN_ARRAY( snowpeakSmallKeyJp ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(snowpeakSmallKeyJp) + MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_LIGHT_BLUE) // 雪山の廃墟 "\x90\xE1\x8E\x52\x82\xCC\x94\x70" MSG_SP_CHAR_KYO @@ -46,7 +46,7 @@ namespace mod::customMessages // を手に入れ "\x82\xF0\x8E\xE8\x82\xC9\x93\xFC\x82\xEA" MSG_END(); - MSG_BEGIN_ARRAY( shadowCrystalJp ) + MSG_BEGIN_ARRAY(shadowCrystalJp) MSG_SPEED(MSG_SPEED_SLOW) MSG_COLOR(MSG_COLOR_RED) // 影の結晶石 @@ -55,7 +55,7 @@ namespace mod::customMessages // を手に入れた! ザントの魔力の塊 使えばいつでも獣になれる! "\x82\xF0\x8E\xE8\x82\xC9\x93\xFC\x82\xEA\x82\xBD\x81\x49\x0A\x83\x55\x83\x93\x83\x67\x82\xCC\x96\x82\x97\xCD\x82\xCC\x89\xF2\x0A\x8E\x67\x82\xA6\x82\xCE\x82\xA2\x82\xC2\x82\xC5\x82\xE0\x8F\x62\x82\xC9\x82\xC8\x82\xEA\x82\xE9\x81\x49" MSG_END(); - MSG_BEGIN_ARRAY( endingBlowJp ) + MSG_BEGIN_ARRAY(endingBlowJp) MSG_SPEED(MSG_SPEED_FAST) // 奥義その一、 "\x89\x9C\x8B\x60\x82\xBB\x82\xCC\x88\xEA\x81\x41" @@ -66,7 +66,7 @@ namespace mod::customMessages // を習得した! "\x82\xF0\x8F\x4B\x93\xBE\x82\xB5\x82\xBD\x81\x49" MSG_END(); - MSG_BEGIN_ARRAY( shieldAttackJp ) + MSG_BEGIN_ARRAY(shieldAttackJp) MSG_SPEED(MSG_SPEED_FAST) // 奥義その二、 "\x89\x9C\x8B\x60\x82\xBB\x82\xCC\x93\xF1\x81\x41" @@ -77,7 +77,7 @@ namespace mod::customMessages // を習得した! "\x82\xF0\x8F\x4B\x93\xBE\x82\xB5\x82\xBD\x81\x49" MSG_END(); - MSG_BEGIN_ARRAY( backSliceJp ) + MSG_BEGIN_ARRAY(backSliceJp) MSG_SPEED(MSG_SPEED_FAST) // 奥義その三、 "\x89\x9C\x8B\x60\x82\xBB\x82\xCC\x8E\x4F\x81\x41" @@ -88,7 +88,7 @@ namespace mod::customMessages // を習得した! "\x82\xF0\x8F\x4B\x93\xBE\x82\xB5\x82\xBD\x81\x49" MSG_END(); - MSG_BEGIN_ARRAY( helmSplitterJp ) + MSG_BEGIN_ARRAY(helmSplitterJp) MSG_SPEED(MSG_SPEED_FAST) // 奥義その四、 "\x89\x9C\x8B\x60\x82\xBB\x82\xCC\x8E\x6C\x81\x41" @@ -99,7 +99,7 @@ namespace mod::customMessages // を習得した! "\x82\xF0\x8F\x4B\x93\xBE\x82\xB5\x82\xBD\x81\x49" MSG_END(); - MSG_BEGIN_ARRAY( mortalDrawJp ) + MSG_BEGIN_ARRAY(mortalDrawJp) MSG_SPEED(MSG_SPEED_FAST) // 奥義その五、 "\x89\x9C\x8B\x60\x82\xBB\x82\xCC\x8C\xDC\x81\x41" @@ -110,7 +110,7 @@ namespace mod::customMessages // を習得した! "\x82\xF0\x8F\x4B\x93\xBE\x82\xB5\x82\xBD\x81\x49" MSG_END(); - MSG_BEGIN_ARRAY( jumpStrikeJp ) + MSG_BEGIN_ARRAY(jumpStrikeJp) MSG_SPEED(MSG_SPEED_FAST) // 奥義その六、 "\x89\x9C\x8B\x60\x82\xBB\x82\xCC\x98\x5A\x81\x41" @@ -121,7 +121,7 @@ namespace mod::customMessages // を習得した! "\x82\xF0\x8F\x4B\x93\xBE\x82\xB5\x82\xBD\x81\x49" MSG_END(); - MSG_BEGIN_ARRAY( greatSpinJp ) + MSG_BEGIN_ARRAY(greatSpinJp) MSG_SPEED(MSG_SPEED_FAST) // 奥義その七、 "\x89\x9C\x8B\x60\x82\xBB\x82\xCC\x8E\xB5\x81\x41" @@ -132,7 +132,7 @@ namespace mod::customMessages // を習得した! "\x82\xF0\x8F\x4B\x93\xBE\x82\xB5\x82\xBD\x81\x49" MSG_END(); - MSG_BEGIN_ARRAY( poweredRodJp ) + MSG_BEGIN_ARRAY(poweredRodJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // コピーロッド @@ -141,7 +141,7 @@ namespace mod::customMessages // に魔力が戻った!太古の石像に命を吹き込む 不思議なロッド "\x82\xC9\x96\x82\x97\xCD\x82\xAA\x96\xDF\x82\xC1\x82\xBD\x81\x49\x0A\x91\xBE\x8C\xC3\x82\xCC\x90\xCE\x91\x9C\x82\xC9\x96\xBD\x82\xF0\x90\x81\x82\xAB\x8D\x9E\x82\xDE\x0A\x95\x73\x8E\x76\x8B\x63\x82\xC8\x83\x8D\x83\x62\x83\x68" MSG_END(); - MSG_BEGIN_ARRAY( skyBookCharacterJp ) + MSG_BEGIN_ARRAY(skyBookCharacterJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // 天空文字 @@ -156,7 +156,7 @@ namespace mod::customMessages // 個集まりました。 "\x8C\xC2\x8F\x57\x82\xDC\x82\xE8\x82\xDC\x82\xB5\x82\xBD\x81\x42" MSG_END(); - MSG_BEGIN_ARRAY( firstFusedShadowJp ) + MSG_BEGIN_ARRAY(firstFusedShadowJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // 一つ目の影の結晶石 @@ -171,7 +171,7 @@ namespace mod::customMessages // ケが生えている... "\x82\xAA\x90\xB6\x82\xA6\x82\xC4\x82\xA2\x82\xE9\x2e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( secondFusedShadowJp ) + MSG_BEGIN_ARRAY(secondFusedShadowJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // 二つ目の影の結晶石 @@ -186,7 +186,7 @@ namespace mod::customMessages // 感じがする... "\x8A\xB4\x82\xB6\x82\xAA\x82\xB7\x82\xE9\x2e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( thirdFusedShadowJp ) + MSG_BEGIN_ARRAY(thirdFusedShadowJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // 三つ目の影の結晶石 @@ -201,7 +201,24 @@ namespace mod::customMessages // の臭いがする... "\x82\xCC\x8F\x4C\x82\xA2\x82\xAA\x82\xB7\x82\xE9\x2e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( secondMirrorShardJp ) + MSG_BEGIN_ARRAY(firstMirrorShardJp) + MSG_SPEED(MSG_SPEED_FAST) + // 一つ目の + "\x88\xEA\x82\xC2\x96\xDA\x82\xCC" + MSG_COLOR(MSG_COLOR_RED) + // 陰りの鏡のかけら + "\x89\x41\x82\xE8\x82\xCC\x8B\xBE\x82\xCC\x82\xA9\x82\xAF\x82\xE7" + MSG_COLOR(MSG_COLOR_WHITE) + // を手に入れた! + "\x82\xF0\x8E\xE8\x82\xC9\x93\xFC\x82\xEA\x82\xBD\x81\x49\x0A" + MSG_COLOR(MSG_COLOR_ORANGE) + // 砂 + "\x8D\xBB" + MSG_COLOR(MSG_COLOR_WHITE) + // で覆われている・・・ + "\x82\xC5\x95\xA2\x82\xED\x82\xEA\x82\xC4\x82\xA2\x82\xE9\x81\x45\x81\x45\x81\x45" + MSG_END(); + MSG_BEGIN_ARRAY(secondMirrorShardJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // 二つ目の陰りの鏡 @@ -216,7 +233,7 @@ namespace mod::customMessages // 感じがする... "\x8A\xB4\x82\xB6\x82\xAA\x82\xB7\x82\xE9\x2e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( thirdMirrorShardJp ) + MSG_BEGIN_ARRAY(thirdMirrorShardJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // 三つ目の陰りの鏡 @@ -231,7 +248,7 @@ namespace mod::customMessages // が付着している... "\x82\xAA\x95\x74\x92\x85\x82\xB5\x82\xC4\x82\xA2\x82\xE9\x2e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( fourthMirrorShardJp ) + MSG_BEGIN_ARRAY(fourthMirrorShardJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // 四つ目の陰りの鏡 @@ -246,7 +263,7 @@ namespace mod::customMessages // より軽く感じる... "\x82\xE6\x82\xE8\x8C\x79\x82\xAD\x8A\xB4\x82\xB6\x82\xE9\x2e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( foolishItemJp ) + MSG_BEGIN_ARRAY(foolishItemJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_LIGHT_BLUE) // 冷たい @@ -255,7 +272,7 @@ namespace mod::customMessages // 感じがする... "\x8A\xB4\x82\xB6\x82\xAA\x82\xB7\x82\xE9\x2e\x2e\x2e" MSG_END(); - MSG_BEGIN_ARRAY( talkToMidnaJp ) + MSG_BEGIN_ARRAY(talkToMidnaJp) // どうした、 "\x82\xC7\x82\xA4\x82\xB5\x82\xBD\x81\x41" MSG_PLYR_NAME @@ -271,7 +288,7 @@ namespace mod::customMessages // 時間を変更する "\x8E\x9E\x8A\xD4\x82\xF0\x95\xCF\x8D\x58\x82\xB7\x82\xE9" MSG_END(); - MSG_BEGIN_ARRAY( bigWalletJp ) + MSG_BEGIN_ARRAY(bigWalletJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // 大きなサイフ @@ -286,7 +303,7 @@ namespace mod::customMessages // まで入れられる! "\x82\xDC\x82\xC5\x93\xFC\x82\xEA\x82\xE7\x82\xEA\x82\xE9\x81\x49" MSG_END(); - MSG_BEGIN_ARRAY( giantWalletJp ) + MSG_BEGIN_ARRAY(giantWalletJp) MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // 最大のサイフ @@ -301,23 +318,23 @@ namespace mod::customMessages // まで入れられる! "\x82\xDC\x82\xC5\x93\xFC\x82\xEA\x82\xE7\x82\xEA\x82\xE9\x81\x49" MSG_END(); - MSG_BEGIN_ARRAY( smallWalletPauseJp ) + MSG_BEGIN_ARRAY(smallWalletPauseJp) MSG_SPEED(MSG_SPEED_FAST) // ようしょう幼少じだい時代からのあい愛ようひん用品 1000ルピーまでい入れられる "\x1A\x10\xFF\x00\x02\x02\x82\xE6\x82\xA4\x82\xB5\x82\xE5\x82\xA4\x97\x63\x8F\xAD\x1A\x0C\xFF\x00\x02\x02\x82\xB6\x82\xBE\x82\xA2\x8E\x9E\x91\xE3\x82\xA9\x82\xE7\x82\xCC\x1A\x0A\xFF\x00\x02\x01\x82\xA0\x82\xA2\x88\xA4\x1A\x0E\xFF\x00\x02\x02\x82\xE6\x82\xA4\x82\xD0\x82\xF1\x97\x70\x95\x69\x0A\x82\x50\x82\x4F\x82\x4F\x82\x4F\x83\x8B\x83\x73\x81\x5B\x82\xDC\x82\xC5\x1A\x08\xFF\x00\x02\x01\x82\xA2\x93\xFC\x82\xEA\x82\xE7\x82\xEA\x82\xE9" MSG_END(); - MSG_BEGIN_ARRAY( bigWalletPauseJp ) + MSG_BEGIN_ARRAY(bigWalletPauseJp) MSG_SPEED(MSG_SPEED_FAST) // むし虫さんおうこく王国のおうじょ王女、アゲハからもらったサイフ 5000ルピーまでい入れられる "\x1A\x0A\xFF\x00\x02\x01\x82\xDE\x82\xB5\x92\x8E\x82\xB3\x82\xF1\x1A\x0E\xFF\x00\x02\x02\x82\xA8\x82\xA4\x82\xB1\x82\xAD\x89\xA4\x8D\x91\x82\xCC\x1A\x0E\xFF\x00\x02\x02\x82\xA8\x82\xA4\x82\xB6\x82\xE5\x89\xA4\x8F\x97\x81\x41\x83\x41\x83\x51\x83\x6E\x82\xA9\x82\xE7\x82\xE0\x82\xE7\x82\xC1\x82\xBD\x83\x54\x83\x43\x83\x74\x0A\x82\x54\x82\x4F\x82\x4F\x82\x4F\x83\x8B\x83\x73\x81\x5B\x82\xDC\x82\xC5\x1A\x08\xFF\x00\x02\x01\x82\xA2\x93\xFC\x82\xEA\x82\xE7\x82\xEA\x82\xE9" MSG_END(); - MSG_BEGIN_ARRAY( giantWalletPauseJp ) + MSG_BEGIN_ARRAY(giantWalletPauseJp) MSG_SPEED(MSG_SPEED_FAST) // むし虫さんおうこく王国のおうじょ王女、アゲハからもらったサイフおうこく王国にこうけん貢献したもの者だけにあた与えられる 9999ルピーまでい入れられる "\x1A\x0A\xFF\x00\x02\x01\x82\xDE\x82\xB5\x92\x8E\x82\xB3\x82\xF1\x1A\x0E\xFF\x00\x02\x02\x82\xA8\x82\xA4\x82\xB1\x82\xAD\x89\xA4\x8D\x91\x82\xCC\x1A\x0E\xFF\x00\x02\x02\x82\xA8\x82\xA4\x82\xB6\x82\xE5\x89\xA4\x8F\x97\x81\x41\x83\x41\x83\x51\x83\x6E\x82\xA9\x82\xE7\x82\xE0\x82\xE7\x82\xC1\x82\xBD\x83\x54\x83\x43\x83\x74\x0A\x1A\x0E\xFF\x00\x02\x02\x82\xA8\x82\xA4\x82\xB1\x82\xAD\x89\xA4\x8D\x91\x82\xC9\x1A\x0E\xFF\x00\x02\x02\x82\xB1\x82\xA4\x82\xAF\x82\xF1\x8D\x76\x8C\xA3\x82\xB5\x82\xBD\x1A\x0A\xFF\x00\x02\x01\x82\xE0\x82\xCC\x8E\xD2\x82\xBE\x82\xAF\x82\xC9\x1A\x0A\xFF\x00\x02\x01\x82\xA0\x82\xBD\x97\x5E\x82\xA6\x82\xE7\x82\xEA\x82\xE9\x0A\x82\x58\x82\x58\x82\x58\x82\x58\x83\x8B\x83\x73\x81\x5B\x82\xDC\x82\xC5\x1A\x08\xFF\x00\x02\x01\x82\xA2\x93\xFC\x82\xEA\x82\xE7\x82\xEA\x82\xE9" MSG_END(); - MSG_BEGIN_ARRAY( poeSoulJp ) - MSG_SPEED( MSG_SPEED_FAST ) + MSG_BEGIN_ARRAY(poeSoulJp) + MSG_SPEED(MSG_SPEED_FAST) MSG_COLOR(MSG_COLOR_RED) // ゴーストの魂 "\x83\x53\x81\x5B\x83\x58\x83\x67\x82\xCC\x8D\xB0" @@ -331,7 +348,7 @@ namespace mod::customMessages // 個集まりました。 "\x8C\xC2\x8F\x57\x82\xDC\x82\xE8\x82\xDC\x82\xB5\x82\xBD\x81\x42" MSG_END(); - MSG_BEGIN_ARRAY( skyBookDescriptionJp ) + MSG_BEGIN_ARRAY(skyBookDescriptionJp) MSG_SPEED(MSG_SPEED_FAST) // 古の天空語で 記された書物\nところどころ 言葉がか欠けている\n\n "\x8C\xC3\x82\xCC\x93\x56\x8B\xF3\x8C\xEA\x82\xC5\x20\x8B\x4C\x82\xB3\x82\xEA\x82\xBD\x8F\x91\x95\xA8\x0A\x82\xC6\x82\xB1\x82\xEB\x82\xC7\x82\xB1\x82\xEB\x20\x8C\xBE\x97\x74\x82\xAA\x82\xA9\x8C\x87\x82\xAF\x82\xC4\x82\xA2\x82\xE9\x0A\x0A" @@ -342,20 +359,20 @@ namespace mod::customMessages // 個集まりました。 "\x8C\xC2\x8F\x57\x82\xDC\x82\xE8\x82\xDC\x82\xB5\x82\xBD\x81\x42" MSG_END(); - MSG_BEGIN_ARRAY( charloDonationJp ) + MSG_BEGIN_ARRAY(charloDonationJp) // ハイラルのへいわ平和のため・・・ほどこ施しをいただけませんかな・・・? "\x83\x6E\x83\x43\x83\x89\x83\x8B\x82\xCC\x1A\x0C\xFF\x00\x02\x02\x82\xD6\x82\xA2\x82\xED\x95\xBD\x98\x61\x82\xCC\x82\xBD\x82\xDF\x81\x45\x81\x45\x81\x45\x0A\x1A\x0C\xFF\x00\x02\x01\x82\xD9\x82\xC7\x82\xB1\x8E\x7B\x82\xB5\x82\xF0\x82\xA2\x82\xBD\x82\xBE\x82\xAF\x82\xDC\x82\xB9\x82\xF1\x82\xA9\x82\xC8\x81\x45\x81\x45\x81\x45\x81\x48" - MSG_OPTION_LIST( MSG_OPTION_1 ) + MSG_OPTION_LIST(MSG_OPTION_1) // 100ルピー "\x82\x50\x82\x4f\x82\x4F\x83\x8B\x83\x73\x81\x5B\x0A" - MSG_OPTION_LIST( MSG_OPTION_2 ) + MSG_OPTION_LIST(MSG_OPTION_2) // 50ルピー "\x82\x54\x82\x4F\x83\x8B\x83\x73\x81\x5B\x0A" - MSG_OPTION_LIST( MSG_OPTION_3 ) + MSG_OPTION_LIST(MSG_OPTION_3) // 断る "\x1A\x0C\xFF\x00\x02\x01\x82\xB1\x82\xC6\x82\xED\x92\x66\x82\xE9"; MSG_END(); - MSG_BEGIN_ARRAY( recognitionJp ) + MSG_BEGIN_ARRAY(recognitionJp) MSG_SPEED(MSG_SPEED_FAST) // ベータテスターの皆様に感謝します。本当にありがとうございました "\x83\x78\x81\x5B\x83\x5E\x83\x65\x83\x58\x83\x5E\x81\x5B\x82\xCC\x8A\x46\x97\x6C\x82\xC9\x8A\xB4\x8E\xD3\x82\xB5\x82\xDC\n\x82\xB7\x81\x42\x96\x7B\x93\x96\x82\xC9\x82\xA0\x82\xE8\x82\xAA\x82\xC6\x82\xA4\x82\xB2\x82\xB4\x82\xA2\x82\xDC\x82\xB5\n\x82\xBD: Taka\nAnorakkis, Archer, Br00ty, Chris\nChrono, clabrus, Demon, EmperorP\nElinadrian, Empty, Fennec, Zushi\nFleakee, Foxhole Gaming, Luzagar\nHeartPiece, Hornlitz, IceStorm\nJanWegh, JD, jdflyer, Jeez, Oxy\nJustRyland, Lance H., link1183\nLinkman124, Luneyes, GameWyrm\nMattStrats, MultFij, NesmaN88\nXenoWars, Papy_Grant, Simikins\npokemongenius, Psi-Hate, Lars P\nRaziel_Stratton, Redriel, Revven\nSparky7198, Zach, SwiftIke, j_im\nZenith, Prince, The., TheBruce\nTreZc0_, Wameslo, WickedGligar\nDGod63 and Sushi." @@ -452,6 +469,11 @@ namespace mod::customMessages sizeof(thirdFusedShadowJp), 0x013E, + // First Mirror Shard + firstMirrorShardJp, + sizeof(firstMirrorShardJp), + 0x0B7, + // Second Mirror Shard secondMirrorShardJp, sizeof(secondMirrorShardJp), diff --git a/GameCube/subrel/boot/source/custom_messages/spanishMessages.cpp b/GameCube/subrel/boot/source/custom_messages/spanishMessages.cpp index 0ebf0f1e..3b3d5d9c 100644 --- a/GameCube/subrel/boot/source/custom_messages/spanishMessages.cpp +++ b/GameCube/subrel/boot/source/custom_messages/spanishMessages.cpp @@ -208,6 +208,23 @@ namespace mod::customMessages // y huele\na pescado.. "\x79\x20\x68\x75\x65\x6C\x65\x0A\x61\x20\x70\x65\x73\x63\x61\x64\x6F\x2E\x2E" MSG_END(); + MSG_BEGIN_ARRAY( firstMirrorShardSp ) + MSG_SPEED(MSG_SPEED_FAST) + // ¡Has obtenido el primer\nfragmento del + "\xA1\x48\x61\x73\x20\x6F\x62\x74\x65\x6E\x69\x64\x6F\x20\x65\x6C\x20\x70\x72\x69\x6D\x65\x72\x0A\x66\x72\x61\x67\x6D\x65\x6E\x74\x6F\x20\x64\x65\x6C\x20" + MSG_COLOR(MSG_COLOR_RED) + // Espejo del\nCrepúsculo + "\x45\x73\x70\x65\x6A\x6F\x20\x64\x65\x6C\x0A\x43\x72\x65\x70\xFA\x73\x63\x75\x6C\x6F" + MSG_COLOR(MSG_COLOR_WHITE) + // ! Está cubierto de\n + "\x21\x20\x45\x73\x74\xE1\x20\x63\x75\x62\x69\x65\x72\x74\x6F\x20\x64\x65\x0A" + MSG_COLOR(MSG_COLOR_LIGHT_BLUE) + // arena + "\x61\x72\x65\x6E\x61" + MSG_COLOR(MSG_COLOR_WHITE) + // .. + "\x2E\x2E" + MSG_END(); MSG_BEGIN_ARRAY( secondMirrorShardSp ) MSG_SPEED(MSG_SPEED_FAST) // ¡Has obtenido el segundo\nfragmento del @@ -268,7 +285,7 @@ namespace mod::customMessages "\x66\x72\xED\x6F" MSG_COLOR(MSG_COLOR_WHITE) // .. - "\x2E\x2E" + "\x2E\x2E\x2E" MSG_END(); MSG_BEGIN_ARRAY( talkToMidnaSp ) // ¿Qué quieres, @@ -469,6 +486,11 @@ namespace mod::customMessages sizeof(thirdFusedShadowSp), 0x013E, + // First Mirror Shard + firstMirrorShardSp, + sizeof(firstMirrorShardSp), + 0x0B7, + // Second Mirror Shard secondMirrorShardSp, sizeof(secondMirrorShardSp), diff --git a/GameCube/subrel/boot/source/game_patch/02_modifyItemData.cpp b/GameCube/subrel/boot/source/game_patch/02_modifyItemData.cpp index 1b97a1ea..d5390cbb 100644 --- a/GameCube/subrel/boot/source/game_patch/02_modifyItemData.cpp +++ b/GameCube/subrel/boot/source/game_patch/02_modifyItemData.cpp @@ -165,6 +165,7 @@ namespace mod::game_patch libtp::data::items::Key_Shard_3, libtp::data::items::Big_Key_Goron_Mines, libtp::data::items::Coro_Key, + rando::customItems::Mirror_Piece_1, libtp::data::items::Mirror_Piece_2, libtp::data::items::Mirror_Piece_3, libtp::data::items::Mirror_Piece_4, @@ -176,13 +177,14 @@ namespace mod::game_patch { using namespace libtp::data; using namespace libtp::tp; + d_item_data::ItemInfo* itemInfoPtr = &d_item_data::item_info[0]; d_item_data::FieldItemRes* fieldItemResPtr = &d_item_data::field_item_res[0]; d_item_data::ItemResource* itemResourcePtr = &d_item_data::item_resource[0]; uint8_t* getSeTypePtr = &libtp::tp::d_a_alink::getSeType[0]; - d_item_data::ItemInfo* yellowRupeeInfoPtr = &d_item_data::item_info[items::Yellow_Rupee]; + const d_item_data::ItemInfo* yellowRupeeInfoPtr = &d_item_data::item_info[items::Yellow_Rupee]; - int16_t bombBagIcon = itemResourcePtr[items::Bomb_Bag_Regular_Bombs].ringTexResIdx; + const int16_t bombBagIcon = itemResourcePtr[items::Bomb_Bag_Regular_Bombs].ringTexResIdx; memcpy(&itemResourcePtr[items::Bomb_Bag_Regular_Bombs], &itemResourcePtr[items::Goron_Bomb_Bag], @@ -192,9 +194,11 @@ namespace mod::game_patch // First we copy over the Ordon Sword data to the Master/Light Sword as a base and then modify the model appropriately memcpy(&itemResourcePtr[items::Master_Sword], &itemResourcePtr[items::Ordon_Sword], sizeof(d_item_data::ItemResource)); + memcpy(&itemResourcePtr[items::Master_Sword_Light], &itemResourcePtr[items::Ordon_Sword], sizeof(d_item_data::ItemResource)); + itemResourcePtr[items::Master_Sword].arcName = _02_masterSwordArc; itemResourcePtr[items::Master_Sword_Light].arcName = _02_masterSwordArc; itemResourcePtr[items::Master_Sword].modelResIdx = 0x5; @@ -206,10 +210,11 @@ namespace mod::game_patch &itemResourcePtr[items::Purple_Rupee], sizeof(d_item_data::ItemResource)); - uint32_t loopCount = sizeof(itemsWithNoFieldModel) / sizeof(itemsWithNoFieldModel[0]); + constexpr uint32_t loopCount = sizeof(itemsWithNoFieldModel) / sizeof(itemsWithNoFieldModel[0]); for (uint32_t i = 0; i < loopCount; i++) { - uint32_t item = itemsWithNoFieldModel[i]; + const uint32_t item = itemsWithNoFieldModel[i]; + // Set the shadow size to 0xFF for items that don't cast a proper shadow. switch (item) { @@ -227,6 +232,7 @@ namespace mod::game_patch itemInfoPtr[item].mCollisionH = yellowRupeeInfoPtr->mCollisionH; itemInfoPtr[item].mCollisionR = yellowRupeeInfoPtr->mCollisionR; + // Set the item's field model to use the getItem model. fieldItemResPtr[item].arcName = itemResourcePtr[item].arcName; fieldItemResPtr[item].modelResIdx = itemResourcePtr[item].modelResIdx; @@ -250,90 +256,91 @@ namespace mod::game_patch using namespace libtp::data; using namespace libtp::tp; using namespace rando; - d_item_data::ItemInfo* itemInfoPtr = &d_item_data::item_info[0]; + + const d_item_data::ItemInfo* itemInfoPtr = &d_item_data::item_info[0]; d_item_data::ItemResource* itemResourcePtr = &d_item_data::item_resource[0]; - d_item_data::ItemResource* smallKeyItemResourcePtr = &itemResourcePtr[items::Small_Key]; - d_item_data::ItemResource* bigKeyItemResourcePtr = &itemResourcePtr[items::Big_Key]; - d_item_data::ItemResource* dungeonMapItemResourcePtr = &itemResourcePtr[items::Dungeon_Map]; - d_item_data::ItemResource* compassItemResourcePtr = &itemResourcePtr[items::Compass]; - d_item_data::ItemResource* skybookItemResourcePtr = &itemResourcePtr[items::Ancient_Sky_Book_Empty]; + const d_item_data::ItemResource* smallKeyItemResourcePtr = &itemResourcePtr[items::Small_Key]; + const d_item_data::ItemResource* bigKeyItemResourcePtr = &itemResourcePtr[items::Big_Key]; + const d_item_data::ItemResource* dungeonMapItemResourcePtr = &itemResourcePtr[items::Dungeon_Map]; + const d_item_data::ItemResource* compassItemResourcePtr = &itemResourcePtr[items::Compass]; + const d_item_data::ItemResource* skybookItemResourcePtr = &itemResourcePtr[items::Ancient_Sky_Book_Empty]; uint8_t* getSeTypePtr = &libtp::tp::d_a_alink::getSeType[0]; - uint8_t listLength = 0; - uint8_t smallKeySeType = getSeTypePtr[items::Small_Key]; - uint8_t bigKeySeType = getSeTypePtr[items::Big_Key]; - uint8_t dungeonMapSeType = getSeTypePtr[items::Dungeon_Map]; - uint8_t compassSeType = getSeTypePtr[items::Compass]; - uint8_t skyBookSeType = getSeTypePtr[items::Ancient_Sky_Book_Empty]; - - uint8_t customSmallKeyItemIDs[] = {customItems::Forest_Temple_Small_Key, - customItems::Goron_Mines_Small_Key, - customItems::Lakebed_Temple_Small_Key, - customItems::Arbiters_Grounds_Small_Key, - customItems::Snowpeak_Ruins_Small_Key, - customItems::Temple_of_Time_Small_Key, - customItems::City_in_The_Sky_Small_Key, - customItems::Palace_of_Twilight_Small_Key, - customItems::Hyrule_Castle_Small_Key, - customItems::Bulblin_Camp_Key}; - - uint8_t customBigKeyItemIDs[] = {customItems::Forest_Temple_Big_Key, - customItems::Lakebed_Temple_Big_Key, - customItems::Arbiters_Grounds_Big_Key, - customItems::Temple_of_Time_Big_Key, - customItems::City_in_The_Sky_Big_Key, - customItems::Palace_of_Twilight_Big_Key, - customItems::Hyrule_Castle_Big_Key}; - - uint8_t customDungeonMapItemIDs[] = {customItems::Forest_Temple_Dungeon_Map, - customItems::Goron_Mines_Dungeon_Map, - customItems::Lakebed_Temple_Dungeon_Map, - customItems::Arbiters_Grounds_Dungeon_Map, - customItems::Snowpeak_Ruins_Dungeon_Map, - customItems::Temple_of_Time_Dungeon_Map, - customItems::City_in_The_Sky_Dungeon_Map, - customItems::Palace_of_Twilight_Dungeon_Map, - customItems::Hyrule_Castle_Dungeon_Map}; - - uint8_t customCompassItemIDs[] = {customItems::Forest_Temple_Compass, - customItems::Goron_Mines_Compass, - customItems::Lakebed_Temple_Compass, - customItems::Arbiters_Grounds_Compass, - customItems::Snowpeak_Ruins_Compass, - customItems::Temple_of_Time_Compass, - customItems::City_in_The_Sky_Compass, - customItems::Palace_of_Twilight_Compass, - customItems::Hyrule_Castle_Compass}; - - uint8_t customHiddenSkillItemIDs[] = {customItems::Ending_Blow, - customItems::Shield_Attack, - customItems::Back_Slice, - customItems::Helm_Splitter, - customItems::Mortal_Draw, - customItems::Jump_Strike, - customItems::Great_Spin}; - - uint8_t customSkyCharacterItemIDs[] = {customItems::Ancient_Sky_Book_First_Character, - customItems::Ancient_Sky_Book_Second_Character, - customItems::Ancient_Sky_Book_Third_Character, - customItems::Ancient_Sky_Book_Fourth_Character, - customItems::Ancient_Sky_Book_Fifth_Character}; - - uint8_t customShardsIDs[] = { - items::Mirror_Piece_2, - items::Mirror_Piece_3, - items::Mirror_Piece_4, - }; - - uint8_t customShadowsIDs[] = { - customItems::Fused_Shadow_1, - customItems::Fused_Shadow_2, - customItems::Fused_Shadow_3, - }; + uint32_t listLength = 0; + const uint8_t smallKeySeType = getSeTypePtr[items::Small_Key]; + const uint8_t bigKeySeType = getSeTypePtr[items::Big_Key]; + const uint8_t dungeonMapSeType = getSeTypePtr[items::Dungeon_Map]; + const uint8_t compassSeType = getSeTypePtr[items::Compass]; + const uint8_t skyBookSeType = getSeTypePtr[items::Ancient_Sky_Book_Empty]; + + static const uint8_t customSmallKeyItemIDs[] = {customItems::Forest_Temple_Small_Key, + customItems::Goron_Mines_Small_Key, + customItems::Lakebed_Temple_Small_Key, + customItems::Arbiters_Grounds_Small_Key, + customItems::Snowpeak_Ruins_Small_Key, + customItems::Temple_of_Time_Small_Key, + customItems::City_in_The_Sky_Small_Key, + customItems::Palace_of_Twilight_Small_Key, + customItems::Hyrule_Castle_Small_Key, + customItems::Bulblin_Camp_Key}; + + static const uint8_t customBigKeyItemIDs[] = {customItems::Forest_Temple_Big_Key, + customItems::Lakebed_Temple_Big_Key, + customItems::Arbiters_Grounds_Big_Key, + customItems::Temple_of_Time_Big_Key, + customItems::City_in_The_Sky_Big_Key, + customItems::Palace_of_Twilight_Big_Key, + customItems::Hyrule_Castle_Big_Key}; + + static const uint8_t customDungeonMapItemIDs[] = {customItems::Forest_Temple_Dungeon_Map, + customItems::Goron_Mines_Dungeon_Map, + customItems::Lakebed_Temple_Dungeon_Map, + customItems::Arbiters_Grounds_Dungeon_Map, + customItems::Snowpeak_Ruins_Dungeon_Map, + customItems::Temple_of_Time_Dungeon_Map, + customItems::City_in_The_Sky_Dungeon_Map, + customItems::Palace_of_Twilight_Dungeon_Map, + customItems::Hyrule_Castle_Dungeon_Map}; + + static const uint8_t customCompassItemIDs[] = {customItems::Forest_Temple_Compass, + customItems::Goron_Mines_Compass, + customItems::Lakebed_Temple_Compass, + customItems::Arbiters_Grounds_Compass, + customItems::Snowpeak_Ruins_Compass, + customItems::Temple_of_Time_Compass, + customItems::City_in_The_Sky_Compass, + customItems::Palace_of_Twilight_Compass, + customItems::Hyrule_Castle_Compass}; + + static const uint8_t customHiddenSkillItemIDs[] = {customItems::Ending_Blow, + customItems::Shield_Attack, + customItems::Back_Slice, + customItems::Helm_Splitter, + customItems::Mortal_Draw, + customItems::Jump_Strike, + customItems::Great_Spin}; + + static const uint8_t customSkyCharacterItemIDs[] = {customItems::Ancient_Sky_Book_First_Character, + customItems::Ancient_Sky_Book_Second_Character, + customItems::Ancient_Sky_Book_Third_Character, + customItems::Ancient_Sky_Book_Fourth_Character, + customItems::Ancient_Sky_Book_Fifth_Character}; + + static const uint8_t customShardsIDs[] = {customItems::Mirror_Piece_1, + items::Mirror_Piece_2, + items::Mirror_Piece_3, + items::Mirror_Piece_4}; + + static const uint8_t customShadowsIDs[] = {customItems::Fused_Shadow_1, + customItems::Fused_Shadow_2, + customItems::Fused_Shadow_3}; // Set the item info for the custom small keys to that of the current Small Key listLength = (sizeof(customSmallKeyItemIDs) / sizeof(customSmallKeyItemIDs[0])); - uint32_t smallKeyItemInfo = *reinterpret_cast(reinterpret_cast(&itemInfoPtr[items::Small_Key])); + + const uint32_t smallKeyItemInfo = + *reinterpret_cast(reinterpret_cast(&itemInfoPtr[items::Small_Key])); + for (uint32_t i = 0; i < listLength; i++) { *reinterpret_cast(reinterpret_cast(&itemInfoPtr[customSmallKeyItemIDs[i]])) = smallKeyItemInfo; @@ -343,7 +350,8 @@ namespace mod::game_patch // Set the item info for the custom big keys to that of the current Big Key listLength = (sizeof(customBigKeyItemIDs) / sizeof(customBigKeyItemIDs[0])); - uint32_t bigKeyItemInfo = *reinterpret_cast(reinterpret_cast(&itemInfoPtr[items::Big_Key])); + const uint32_t bigKeyItemInfo = *reinterpret_cast(reinterpret_cast(&itemInfoPtr[items::Big_Key])); + for (uint32_t i = 0; i < listLength; i++) { *reinterpret_cast(reinterpret_cast(&itemInfoPtr[customBigKeyItemIDs[i]])) = bigKeyItemInfo; @@ -353,19 +361,23 @@ namespace mod::game_patch // Set the item info for the custom dungeon map to that of the current Dungeon Map listLength = (sizeof(customDungeonMapItemIDs) / sizeof(customDungeonMapItemIDs[0])); - uint32_t dungeonMapItemInfo = + + const uint32_t dungeonMapItemInfo = *reinterpret_cast(reinterpret_cast(&itemInfoPtr[items::Dungeon_Map])); + for (uint32_t i = 0; i < listLength; i++) { *reinterpret_cast(reinterpret_cast(&itemInfoPtr[customDungeonMapItemIDs[i]])) = dungeonMapItemInfo; + getSeTypePtr[customDungeonMapItemIDs[i]] = dungeonMapSeType; memcpy(&itemResourcePtr[customDungeonMapItemIDs[i]], dungeonMapItemResourcePtr, sizeof(d_item_data::ItemResource)); } // Set the item info for the custom compass to that of the current compass listLength = (sizeof(customCompassItemIDs) / sizeof(customCompassItemIDs[0])); - uint32_t compassItemInfo = *reinterpret_cast(reinterpret_cast(&itemInfoPtr[items::Compass])); + const uint32_t compassItemInfo = *reinterpret_cast(reinterpret_cast(&itemInfoPtr[items::Compass])); + for (uint32_t i = 0; i < listLength; i++) { *reinterpret_cast(reinterpret_cast(&itemInfoPtr[customCompassItemIDs[i]])) = compassItemInfo; @@ -375,12 +387,15 @@ namespace mod::game_patch // Set the item info for the custom skybook characters to that of the current Sky Book listLength = (sizeof(customSkyCharacterItemIDs) / sizeof(customSkyCharacterItemIDs[0])); - uint32_t skybookItemInfo = + + const uint32_t skybookItemInfo = *reinterpret_cast(reinterpret_cast(&itemInfoPtr[items::Ancient_Sky_Book_Empty])); + for (uint32_t i = 0; i < listLength; i++) { *reinterpret_cast(reinterpret_cast(&itemInfoPtr[customSkyCharacterItemIDs[i]])) = skybookItemInfo; + getSeTypePtr[customSkyCharacterItemIDs[i]] = skyBookSeType; memcpy(&itemResourcePtr[customSkyCharacterItemIDs[i]], skybookItemResourcePtr, sizeof(d_item_data::ItemResource)); } @@ -389,29 +404,35 @@ namespace mod::game_patch listLength = sizeof(customHiddenSkillItemIDs) / sizeof(customHiddenSkillItemIDs[0]); for (uint32_t i = 0; i < listLength; i++) { - itemResourcePtr[customHiddenSkillItemIDs[i]].arcName = _02_hiddenSkillArc; - itemResourcePtr[customHiddenSkillItemIDs[i]].ringTexResIdx = 0x003D; - itemResourcePtr[customHiddenSkillItemIDs[i]].modelResIdx = 0x0003; - itemResourcePtr[customHiddenSkillItemIDs[i]].brkResIdx = 0xFFFF; - itemResourcePtr[customHiddenSkillItemIDs[i]].tevFrm = 0x00; + d_item_data::ItemResource* currentHiddenSkillPtr = &itemResourcePtr[customHiddenSkillItemIDs[i]]; + + currentHiddenSkillPtr->arcName = _02_hiddenSkillArc; + currentHiddenSkillPtr->ringTexResIdx = 0x003D; + currentHiddenSkillPtr->modelResIdx = 0x0003; + currentHiddenSkillPtr->brkResIdx = 0xFFFF; + currentHiddenSkillPtr->tevFrm = 0x00; getSeTypePtr[customHiddenSkillItemIDs[i]] = 0x2; } listLength = sizeof(customShardsIDs) / sizeof(customShardsIDs[0]); for (uint32_t i = 0; i < listLength; i++) { - itemResourcePtr[customShardsIDs[i]].arcName = _02_mirrorShardArc; - itemResourcePtr[customShardsIDs[i]].modelResIdx = 0x0009; - itemResourcePtr[customShardsIDs[i]].brkResIdx = 0xFFFF; - itemResourcePtr[customShardsIDs[i]].tevFrm = 0x00; + d_item_data::ItemResource* currentShardPtr = &itemResourcePtr[customShardsIDs[i]]; + + currentShardPtr->arcName = _02_mirrorShardArc; + currentShardPtr->modelResIdx = 0x0009; + currentShardPtr->brkResIdx = 0xFFFF; + currentShardPtr->tevFrm = 0x00; getSeTypePtr[customShardsIDs[i]] = getSeTypePtr[items::Clawshot]; } listLength = sizeof(customShadowsIDs) / sizeof(customShadowsIDs[0]); for (uint32_t i = 0; i < listLength; i++) { - itemResourcePtr[customShadowsIDs[i]].brkResIdx = 0xFFFF; - itemResourcePtr[customShadowsIDs[i]].tevFrm = 0x00; + d_item_data::ItemResource* currentShadowPtr = &itemResourcePtr[customShadowsIDs[i]]; + + currentShadowPtr->brkResIdx = 0xFFFF; + currentShadowPtr->tevFrm = 0x00; getSeTypePtr[customShadowsIDs[i]] = getSeTypePtr[items::Clawshot]; } @@ -486,6 +507,7 @@ namespace mod::game_patch itemFuncPtr[customItems::Fused_Shadow_1] = _02_firstFusedShadowItemFunc; itemFuncPtr[customItems::Fused_Shadow_2] = _02_secondFusedShadowItemFunc; itemFuncPtr[customItems::Fused_Shadow_3] = _02_thirdFusedShadowItemFunc; + itemFuncPtr[customItems::Mirror_Piece_1] = _02_firstMirrorShardItemFunc; itemFuncPtr[items::Mirror_Piece_2] = _02_secondMirrorShardItemFunc; itemFuncPtr[items::Mirror_Piece_3] = _02_thirdMirrorShardItemFunc; itemFuncPtr[items::Mirror_Piece_4] = _02_fourthMirrorShardItemFunc; @@ -528,6 +550,7 @@ namespace mod::game_patch itemGetCheckFuncPtr[customItems::Fused_Shadow_1] = _02_firstFusedShadowItemGetCheck; itemGetCheckFuncPtr[customItems::Fused_Shadow_2] = _02_secondFusedShadowItemGetCheck; itemGetCheckFuncPtr[customItems::Fused_Shadow_3] = _02_thirdFusedShadowItemGetCheck; + itemGetCheckFuncPtr[customItems::Mirror_Piece_1] = _02_firstMirrorShardItemGetCheck; itemGetCheckFuncPtr[items::Mirror_Piece_2] = _02_secondMirrorShardItemGetCheck; itemGetCheckFuncPtr[items::Mirror_Piece_3] = _02_thirdMirrorShardItemGetCheck; itemGetCheckFuncPtr[items::Mirror_Piece_4] = _02_fourthMirrorShardItemGetCheck; diff --git a/GameCube/subrel/boot/source/game_patch/06_asmOverrides.cpp b/GameCube/subrel/boot/source/game_patch/06_asmOverrides.cpp index 2d75f818..e80b52df 100644 --- a/GameCube/subrel/boot/source/game_patch/06_asmOverrides.cpp +++ b/GameCube/subrel/boot/source/game_patch/06_asmOverrides.cpp @@ -1,5 +1,6 @@ #include +#include "main.h" #include "game_patch/game_patch.h" #include "asm_templates.h" #include "tp/d_item.h" @@ -44,12 +45,6 @@ namespace mod::game_patch // Nop out the instruction that causes a miscalculation in message resources. *patchMessageCalculation = ASM_NOP; - // Modify the skipper function to check whether or not a cutscene is skippable instead of whether the player skips the - // CS. This effectively auto-skips all skippable cutscenes. - uint32_t skipperFunctionAddress = reinterpret_cast(libtp::tp::d_event::skipper); - *reinterpret_cast(skipperFunctionAddress + 0x54) = - ASM_COMPARE_LOGICAL_WORD_IMMEDIATE(30, 0); // Previous rlwinm r0,r0,0,19,19 - // Modify the Wooden Sword function to not set a region flag by default by nopping out the function call to isSwitch uint32_t woodenSwordFunctionAddress = reinterpret_cast(libtp::tp::d_item::item_func_WOOD_STICK); *reinterpret_cast(woodenSwordFunctionAddress + 0x40) = ASM_NOP; // Previous 0x4bf9cafd @@ -102,6 +97,9 @@ namespace mod::game_patch // Modify drawKanteraScreen to change the lantern meter color to match lantern light color from seed. uint32_t drawKanteraAddress = reinterpret_cast(libtp::tp::d_meter2_draw::drawKanteraScreen); libtp::patch::writeBranchBL(drawKanteraAddress + 0xE4, events::modifyLanternMeterColor); + + uint32_t procCoGetItemInitAddress = reinterpret_cast(libtp::tp::d_a_alink::procCoGetItemInit); + libtp::patch::writeBranchBL(procCoGetItemInitAddress + 0x17C, procCoGetItemInitCreateItem); #ifdef TP_JP uint32_t checkWarpStartAddress = reinterpret_cast(libtp::tp::d_a_alink::checkWarpStart); diff --git a/GameCube/subrel/boot/source/main.cpp b/GameCube/subrel/boot/source/main.cpp index 5ed153b2..3beb0aed 100644 --- a/GameCube/subrel/boot/source/main.cpp +++ b/GameCube/subrel/boot/source/main.cpp @@ -33,6 +33,7 @@ #include "gc_wii/OSInterrupt.h" #include "gc_wii/vi.h" #include "asm.h" +#include "tp/d_file_select.h" #include #include @@ -73,7 +74,6 @@ namespace mod // Load custom messages customMessages::createMsgTable(); customMessages::setDungeonItemAreaColorIndex(); - customMessages::createCharloDonationMessage(); // Load item wheel menu strings customMessages::createItemWheelMenuData(); @@ -120,10 +120,8 @@ namespace mod // return_stageLoader = patch::hookFunction( libtp::tp::d_stage::stageLoader, mod::handle_stageLoader ); return_dStage_playerInit = patch::hookFunction(libtp::tp::d_stage::dStage_playerInit, mod::handle_dStage_playerInit); - /* return_dComIfGp_setNextStage = - patch::hookFunction( libtp::tp::d_com_inf_game::dComIfGp_setNextStage, mod::handle_dComIfGp_setNextStage ); - */ + patch::hookFunction(libtp::tp::d_com_inf_game::dComIfGp_setNextStage, mod::handle_dComIfGp_setNextStage); // Custom States return_getLayerNo_common_common = patch::hookFunction(getLayerNo_common_common, game_patch::_01_getLayerNo); @@ -178,14 +176,18 @@ namespace mod mod::handle_jmessage_tSequenceProcessor__do_tag); // Query/EventFunctions + return_query001 = patch::hookFunction(libtp::tp::d_msg_flow::query001, mod::handle_query001); return_query022 = patch::hookFunction(libtp::tp::d_msg_flow::query022, mod::handle_query022); return_query023 = patch::hookFunction(libtp::tp::d_msg_flow::query023, mod::handle_query023); + return_query025 = patch::hookFunction(libtp::tp::d_msg_flow::query025, mod::handle_query025); return_checkEmptyBottle = patch::hookFunction(libtp::tp::d_save::checkEmptyBottle, mod::handle_checkEmptyBottle); return_query037 = patch::hookFunction(libtp::tp::d_msg_flow::query037, mod::handle_query037); return_query049 = patch::hookFunction(libtp::tp::d_msg_flow::query049, mod::handle_query049); return_query042 = patch::hookFunction(libtp::tp::d_msg_flow::query042, mod::handle_query042); // return_event000 = patch::hookFunction( libtp::tp::d_msg_flow::event000, mod::handle_event000 ); return_event017 = patch::hookFunction(libtp::tp::d_msg_flow::event017, mod::handle_event017); + return_doFlow = patch::hookFunction(libtp::tp::d_msg_flow::doFlow, mod::handle_doFlow); + return_setNormalMsg = patch::hookFunction(libtp::tp::d_msg_flow::setNormalMsg, mod::handle_setNormalMsg); // Save flag functions return_isDungeonItem = patch::hookFunction(tp::d_save::isDungeonItem, mod::handle_isDungeonItem); @@ -234,10 +236,14 @@ namespace mod return_damageMagnification = patch::hookFunction(libtp::tp::d_a_alink::damageMagnification, mod::handle_damageMagnification); + return_procCoGetItemInit = patch::hookFunction(libtp::tp::d_a_alink::procCoGetItemInit, mod::handle_procCoGetItemInit); + // Audio functions return_loadSeWave = patch::hookFunction(libtp::z2audiolib::z2scenemgr::loadSeWave, mod::handle_loadSeWave); return_sceneChange = patch::hookFunction(libtp::z2audiolib::z2scenemgr::sceneChange, mod::handle_sceneChange); return_startSound = patch::hookFunction(libtp::z2audiolib::z2soundmgr::startSound, mod::handle_startSound); + return_checkBgmIDPlaying = + patch::hookFunction(libtp::z2audiolib::z2seqmgr::checkBgmIDPlaying, mod::handle_checkBgmIDPlaying); // Title Screen functions return_dScnLogo_c_dt = patch::hookFunction(libtp::tp::d_s_logo::dScnLogo_c_dt, mod::handle_dScnLogo_c_dt); @@ -255,6 +261,16 @@ namespace mod // d_meter functions return_resetMiniGameItem = patch::hookFunction(libtp::tp::d_meter2_info::resetMiniGameItem, mod::handle_resetMiniGameItem); + + // Game Over functions + return_dispWait_init = patch::hookFunction(libtp::tp::d_gameover::dispWait_init, mod::handle_dispWait_init); + + // Shop Functions + return_seq_decide_yes = patch::hookFunction(libtp::tp::d_shop_system::seq_decide_yes, mod::handle_seq_decide_yes); + + // Title Screen functions + return_dFile_select_c___create = + patch::hookFunction(libtp::tp::d_file_select::dFile_select_c___create, mod::resetQueueOnFileSelectScreen); } void initRandState() diff --git a/GameCube/subrel/seed/source/rando/linkHouseSign.cpp b/GameCube/subrel/seed/source/rando/linkHouseSign.cpp deleted file mode 100644 index ef6079ba..00000000 --- a/GameCube/subrel/seed/source/rando/linkHouseSign.cpp +++ /dev/null @@ -1,430 +0,0 @@ -#include "rando/linkHouseSign.h" -#include "rando/seed.h" -#include "tp/resource.h" -#include "main.h" -#include "cxx.h" - -#ifdef TP_EU -#include "tp/d_s_logo.h" -#endif - -#include -#include - -namespace mod::link_house_sign -{ - // Set up an array to hold each area's color id - const uint8_t areaColorIds[TOTAL_POSSIBLE_DUNGEONS] = {MSG_COLOR_GREEN_HEX, - MSG_COLOR_RED_HEX, - CUSTOM_MSG_COLOR_BLUE_HEX, - MSG_COLOR_ORANGE_HEX, - MSG_COLOR_LIGHT_BLUE_HEX, - CUSTOM_MSG_COLOR_DARK_GREEN_HEX, - MSG_COLOR_YELLOW_HEX, - MSG_COLOR_PURPLE_HEX}; - -#ifndef TP_JP - // English - const char* dungeonsUs[TOTAL_POSSIBLE_DUNGEONS] = { - "Forest Temple", - "Goron Mines", - "Lakebed Temple", - "Arbiter's Grounds", - "Snowpeak Ruins", - "Temple of Time", - "City in the Sky", - "Palace of Twilight", - }; - - const char* noDungeonsRequiredUs = "No dungeons required"; -#else - // Japanese - // Snowpeak Ruins - // 雪山の廃 - const char* snowpeakRuinsJp = "\x90\xE1\x8E\x52\x82\xCC\x94\x70"; - - const char* dungeonsJp[TOTAL_POSSIBLE_DUNGEONS] = { - // Forest Temple - // 森の神殿 - "\x90\x58\x82\xCC\x90\x5F\x93\x61", - - // Goron Mines - // ゴロン鉱山 - "\x83\x53\x83\x8D\x83\x93\x8D\x7A\x8E\x52", - - // Lakebed Temple - // 湖底の神殿 - "\x8C\xCE\x92\xEA\x82\xCC\x90\x5F\x93\x61", - - // Arbiter's Grounds - // 砂漠の処刑場 - "\x8D\xBB\x94\x99\x82\xCC\x8F\x88\x8C\x59\x8F\xEA", - - // Snowpeak Ruins - // 雪山の廃 - snowpeakRuinsJp, - - // Temple of Time - // 時の神殿 - "\x8E\x9E\x82\xCC\x90\x5F\x93\x61", - - // City in the Sky - // 天空都市 - "\x93\x56\x8B\xF3\x93\x73\x8E\x73", - - // Palace of Twilight - // 影の宮殿 - "\x89\x65\x82\xCC\x8B\x7B\x93\x61", - }; - - // ダンジョンは必要ない - const char* noDungeonsRequiredJp = "\x83\x5F\x83\x93\x83\x57\x83\x87\x83\x93\x82\xCD\x95\x4B\x97\x76\x82\xC8\x82\xA2"; -#endif - -#ifdef TP_EU - // German - const char* dungeonsDe[TOTAL_POSSIBLE_DUNGEONS] = { - // Forest Temple - // Waldschrein - "\x57\x61\x6c\x64\x73\x63\x68\x72\x65\x69\x6e", - - // Goron Mines - // Minen der Goronen - "\x4d\x69\x6e\x65\x6e\x20\x64\x65\x72\x20\x47\x6f\x72\x6f\x6e\x65\x6e", - - // Lakebed Temple - // Seeschrein - "\x53\x65\x65\x73\x63\x68\x72\x65\x69\x6e", - - // Arbiter's Grounds - // Wüstenburg - "\x57\xfc\x73\x74\x65\x6e\x62\x75\x72\x67", - - // Snowpeak Ruins - // Bergruine - "\x42\x65\x72\x67\x72\x75\x69\x6e\x65", - - // Temple of Time - // Zeitschrein - "\x5a\x65\x69\x74\x73\x63\x68\x72\x65\x69\x6e", - - // City in the Sky - // Kumula - "\x4b\x75\x6d\x75\x6c\x61", - - // Palace of Twilight - // Schattenpalast - "\x53\x63\x68\x61\x74\x74\x65\x6e\x70\x61\x6c\x61\x73\x74", - }; - - // Kein Dungeon erforderlich - const char* noDungeonsRequiredDe = - "\x4B\x65\x69\x6E\x20\x44\x75\x6E\x67\x65\x6F\x6E\x20\x65\x72\x66\x6F\x72\x64\x65\x72\x6C\x69\x63\x68"; - - // French - const char* dungeonsFr[TOTAL_POSSIBLE_DUNGEONS] = { - // Forest Temple - // Temple Sylvestre - "\x54\x65\x6d\x70\x6c\x65\x20\x53\x79\x6c\x76\x65\x73\x74\x72\x65", - - // Goron Mines - // Mine Goron - "\x4d\x69\x6e\x65\x20\x47\x6f\x72\x6f\x6e", - - // Lakebed Temple - // Temple Abyssal - "\x54\x65\x6d\x70\x6c\x65\x20\x41\x62\x79\x73\x73\x61\x6c", - - // Arbiter's Grounds - // Tour du Jugement - "\x54\x6f\x75\x72\x20\x64\x75\x20\x4a\x75\x67\x65\x6d\x65\x6e\x74", - - // Snowpeak Ruins - // Ruines des Pics Blancs - "\x52\x75\x69\x6e\x65\x73\x20\x64\x65\x73\x20\x50\x69\x63\x73\x20\x42\x6c\x61\x6e\x63\x73", - - // Temple of Time - // Temple du Temps - "\x54\x65\x6d\x70\x6c\x65\x20\x64\x75\x20\x54\x65\x6d\x70\x73", - - // City in the Sky - // Célestia - "\x43\xe9\x6c\x65\x73\x74\x69\x61", - - // Palace of Twilight - // Palais du Crépuscule - "\x50\x61\x6c\x61\x69\x73\x20\x64\x75\x20\x43\x72\xe9\x70\x75\x73\x63\x75\x6c\x65", - }; - - // Aucuns donjons requis - const char* noDungeonsRequiredFr = "\x41\x75\x63\x75\x6E\x73\x20\x64\x6F\x6E\x6A\x6F\x6E\x73\x20\x72\x65\x71\x75\x69\x73"; - - // Spanish - const char* dungeonsSp[TOTAL_POSSIBLE_DUNGEONS] = { - // Forest Temple - // Templo del Bosque - "\x54\x65\x6D\x70\x6C\x6F\x20\x64\x65\x6C\x20\x42\x6F\x73\x71\x75\x65", - - // Goron Mines - // Minas de los Goron - "\x4D\x69\x6E\x61\x73\x20\x64\x65\x20\x6C\x6F\x73\x20\x47\x6F\x72\x6F\x6E", - - // Lakebed Temple - // Santuario del Lago - "\x53\x61\x6E\x74\x75\x61\x72\x69\x6F\x20\x64\x65\x6C\x20\x4C\x61\x67\x6F", - - // Arbiter's Grounds - // Patíbulo del Desierto - "\x50\x61\x74\xED\x62\x75\x6C\x6F\x20\x64\x65\x6C\x20\x44\x65\x73\x69\x65\x72\x74\x6F", - - // Snowpeak Ruins - // Ruinas del Pico Nevado - "\x52\x75\x69\x6E\x61\x73\x20\x64\x65\x6C\x20\x50\x69\x63\x6F\x20\x4E\x65\x76\x61\x64\x6F", - - // Temple of Time - // Templo del Tiempo - "\x54\x65\x6D\x70\x6C\x6F\x20\x64\x65\x6C\x20\x54\x69\x65\x6D\x70\x6F", - - // City in the Sky - // Celestia - "\x43\x65\x6C\x65\x73\x74\x69\x61", - - // Palace of Twilight - // Palacio del Crepúsculo - "\x50\x61\x6C\x61\x63\x69\x6F\x20\x64\x65\x6C\x20\x43\x72\x65\x70\xFA\x73\x63\x75\x6C\x6F", - }; - - // Sin mazmorras requeridas - const char* noDungeonsRequiredSp = - "\x53\x69\x6E\x20\x6D\x61\x7A\x6D\x6F\x72\x72\x61\x73\x20\x72\x65\x71\x75\x65\x72\x69\x64\x61\x73"; - - // Italian - const char* dungeonsIt[TOTAL_POSSIBLE_DUNGEONS] = { - // Forest Temple - // Santuario della foresta - "\x53\x61\x6E\x74\x75\x61\x72\x69\x6F\x20\x64\x65\x6C\x6C\x61\x20\x66\x6F\x72\x65\x73\x74\x61", - - // Goron Mines - // Miniera dei Goron - "\x4D\x69\x6E\x69\x65\x72\x61\x20\x64\x65\x69\x20\x47\x6F\x72\x6F\x6E", - - // Lakebed Temple - // Santuario nel lago - "\x53\x61\x6E\x74\x75\x61\x72\x69\x6F\x20\x6E\x65\x6C\x20\x6C\x61\x67\x6F", - - // Arbiter's Grounds - // Patibolo del deserto - "\x50\x61\x74\x69\x62\x6F\x6C\x6F\x20\x64\x65\x6C\x20\x64\x65\x73\x65\x72\x74\x6F", - - // Snowpeak Ruins - // Rovine sul ghiacciaio - "\x52\x6F\x76\x69\x6E\x65\x20\x73\x75\x6C\x20\x67\x68\x69\x61\x63\x63\x69\x61\x69\x6F", - - // Temple of Time - // Santuario del tempo - "\x53\x61\x6E\x74\x75\x61\x72\x69\x6F\x20\x64\x65\x6C\x20\x74\x65\x6D\x70\x6F", - - // City in the Sky - // Città eterea - "\x43\x69\x74\x74\xE0\x20\x65\x74\x65\x72\x65\x61", - - // Palace of Twilight - // Palazzo del crepuscolo - "\x50\x61\x6C\x61\x7A\x7A\x6F\x20\x64\x65\x6C\x20\x63\x72\x65\x70\x75\x73\x63\x6F\x6C\x6F", - }; - - // Nessun santuario richiesto - const char* noDungeonsRequiredIt = - "\x4E\x65\x73\x73\x75\x6E\x20\x73\x61\x6E\x74\x75\x61\x72\x69\x6F\x20\x72\x69\x63\x68\x69\x65\x73\x74\x6F"; -#endif - - void createRequiredDungeonsString(rando::Seed* seed, uint32_t requiredDungeonFlags) - { - // Make sure a seed is actually loaded - if (!seed) - { - return; - } - - // Get the dungeon strings array to use - const char** dungeons; - const char* noDungeonsRequired; -#ifdef TP_US - dungeons = dungeonsUs; - noDungeonsRequired = noDungeonsRequiredUs; -#elif defined TP_JP - dungeons = dungeonsJp; - noDungeonsRequired = noDungeonsRequiredJp; -#elif defined TP_EU - using namespace libtp::tp::d_s_logo; - - switch (currentLanguage) - { - case Languages::uk: - default: // The language is invalid/unsupported, so the game defaults to English - { - dungeons = dungeonsUs; - noDungeonsRequired = noDungeonsRequiredUs; - break; - } - case Languages::de: - { - dungeons = dungeonsDe; - noDungeonsRequired = noDungeonsRequiredDe; - break; - } - case Languages::fr: - { - dungeons = dungeonsFr; - noDungeonsRequired = noDungeonsRequiredFr; - break; - } - case Languages::sp: - { - dungeons = dungeonsSp; - noDungeonsRequired = noDungeonsRequiredSp; - break; - } - case Languages::it: - { - dungeons = dungeonsIt; - noDungeonsRequired = noDungeonsRequiredIt; - break; - } - } -#endif - // Get the strings to write and the total length used for the strings - const char* requiredDungeons[TOTAL_POSSIBLE_DUNGEONS]; - char requiredDungeonsColor[TOTAL_POSSIBLE_DUNGEONS]; - - uint32_t requiredDungeonsLength = 0; - uint32_t totalStringsLength = 0; - - const uint8_t* areaColors = areaColorIds; -#ifdef TP_JP - constexpr uint32_t snowpeakRuinsSpecialCharLength = sizeof(MSG_SP_CHAR_KYO) - 1; - const char* snowpeakRuinsText = snowpeakRuinsJp; - - auto isCurrentTextSnowpeakRuins = [=](const char* currentArea) - { return strncmp(currentArea, snowpeakRuinsText, snowpeakRuinsSpecialCharLength) == 0; }; -#endif - // It's possible that there will be no required dungeons - constexpr uint32_t maxBitsValue = (1 << TOTAL_POSSIBLE_DUNGEONS) - 1; - if ((requiredDungeonFlags & maxBitsValue) != 0) - { - // At least one dungeon is required - for (uint32_t i = 0; i < TOTAL_POSSIBLE_DUNGEONS; i++) - { - if (requiredDungeonFlags & (1 << i)) - { - const char* currentDungeon = dungeons[i]; - - requiredDungeons[requiredDungeonsLength] = currentDungeon; - requiredDungeonsColor[requiredDungeonsLength] = static_cast(areaColors[i]); - requiredDungeonsLength++; - - totalStringsLength += strlen(currentDungeon); -#ifdef TP_JP - // If the current text is for Snowpeak Ruins, then add the length of the special character for it - if (isCurrentTextSnowpeakRuins(currentDungeon)) - { - totalStringsLength += snowpeakRuinsSpecialCharLength; - } -#endif - } - } - } - else - { - // No dungeons are required - requiredDungeons[0] = noDungeonsRequired; - requiredDungeonsColor[0] = MSG_COLOR_WHITE_HEX; - requiredDungeonsLength = 1; - - totalStringsLength += strlen(noDungeonsRequired); - } - - // Get the font size command string and it's length - // Subtract one to remove the NULL terminator since the command is not NULL terminated - const char* fontSizeString = MSG_FONT_SIZE("\x45"); - constexpr uint32_t fontSizeStringLength = sizeof(MSG_FONT_SIZE("\x45")) - 1; - - // Account for the string having the size command - totalStringsLength += fontSizeStringLength; - - // Get the size of the color command excluding the NULL terminator - // Subtract one to remove the NULL terminator since the command is not NULL terminated - constexpr uint32_t colorCommandLength = sizeof(MSG_COLOR(MSG_COLOR_WHITE)) - 1; - - // Account for each string having a color command - totalStringsLength += requiredDungeonsLength * colorCommandLength; - - // Account for the newlines between each string - totalStringsLength += requiredDungeonsLength - 1; - - // Allocate memory for the strings - // Add one to account for the NULL terminator - // Align to char, as strings don't have specific alignment requirements - char* buf = new (sizeof(char)) char[totalStringsLength + 1]; - - // Set up a variable to keep track of how many characters were written to the buffer - uint32_t writtenSize = 0; - - // Set the font size for the string - // Subtract one to remove the NULL terminator since the command is not NULL terminated - memcpy(buf, fontSizeString, fontSizeStringLength); - - // Increment writtenSize to go to the next string - writtenSize += fontSizeStringLength; - - // Get the color command string - // Must use memcpy instead of strncpy since message commands have NULL characters - char colorCommand[colorCommandLength]; - memcpy(colorCommand, MSG_COLOR(MSG_COLOR_WHITE), colorCommandLength); - - // Write each string to the buffer - for (uint32_t i = 0; i < requiredDungeonsLength; i++) - { - // Replace the current color with the color for the current area - colorCommand[colorCommandLength - 1] = requiredDungeonsColor[i]; - - // Write the color command for the current string - // Must use memcpy instead of strncpy since message commands have NULL characters - memcpy(&buf[writtenSize], colorCommand, colorCommandLength); - - // Increment writtenSize to go to the next string - writtenSize += colorCommandLength; - - // Get the length of the current string - const char* currentString = requiredDungeons[i]; - uint32_t currentStringLength = strlen(currentString); - - // Copy the current string to the buffer - // Must use memcpy instead of strncpy since message commands have NULL characters - memcpy(&buf[writtenSize], currentString, currentStringLength); -#ifdef TP_JP - // If the current text is for Snowpeak Ruins, then add the special character to the end of it - if (isCurrentTextSnowpeakRuins(currentString)) - { - // Must use memcpy instead of strncpy since message commands have NULL characters - memcpy(&buf[writtenSize + currentStringLength], MSG_SP_CHAR_KYO, snowpeakRuinsSpecialCharLength); - - // Increment currentStringLength to account for the new length - currentStringLength += snowpeakRuinsSpecialCharLength; - } -#endif - // Increment writtenSize to go to the next string - writtenSize += currentStringLength; - - // Apply a newline to go to the next line - buf[writtenSize++] = '\n'; - } - - // Make sure the string is properly NULL terminated - // Subtract one to overwrite the extra newline - buf[writtenSize - 1] = '\0'; - - // Assign the buffer - seed->m_RequiredDungeons = buf; - } -} // namespace mod::link_house_sign \ No newline at end of file diff --git a/GameCube/subrel/seed/source/rando/randomizer.cpp b/GameCube/subrel/seed/source/rando/randomizer.cpp index 7c839d80..728b4b5e 100644 --- a/GameCube/subrel/seed/source/rando/randomizer.cpp +++ b/GameCube/subrel/seed/source/rando/randomizer.cpp @@ -50,6 +50,8 @@ namespace mod::rando // Update transformAnywhereEnabled now that a seed is loaded transformAnywhereEnabled = static_cast(m_Seed->m_Header->transformAnywhere); + m_Seed->loadShuffledEntrances(); + // Update the damage multiplier to the value stored in the seed damageMultiplier = m_Seed->m_Header->damageMagnification; diff --git a/GameCube/subrel/seed/source/rando/seed.cpp b/GameCube/subrel/seed/source/rando/seed.cpp index 2eb178db..012f5cc9 100644 --- a/GameCube/subrel/seed/source/rando/seed.cpp +++ b/GameCube/subrel/seed/source/rando/seed.cpp @@ -17,7 +17,6 @@ #endif #include "rando/seed.h" -#include "rando/linkHouseSign.h" #include "cxx.h" #include "game_patch/game_patch.h" #include "main.h" @@ -79,16 +78,16 @@ namespace mod::rando m_GCIData = new (0x20) uint8_t[dataSize]; memcpy(m_GCIData, &data[headerPtr->headerSize], dataSize); - // Create the required dungeons text that is displayed when reading the sign in front of Link's house - link_house_sign::createRequiredDungeonsString(this, headerPtr->requiredDungeons); - // Generate the BGM/Fanfare table data loadBgmData(data); m_CLR0 = reinterpret_cast(m_GCIData + headerPtr->clr0Offset); m_RawRGBTable = reinterpret_cast(m_GCIData + headerPtr->clr0Offset + m_CLR0->rawRGBOffset); m_BmdEntries = reinterpret_cast(m_GCIData + headerPtr->clr0Offset + m_CLR0->bmdEntriesOffset); - // Set the static pointers for the Seed Header and Data + // Load the custom text data + this->loadCustomText(data); + + // Set the static pointers for the Seed Header and Data. These are used by TPO void** ptrTable = reinterpret_cast(0x800042BC); ptrTable[0] = m_Header; ptrTable[1] = m_GCIData; @@ -101,7 +100,7 @@ namespace mod::rando // Make sure to delete tempcheck buffers this->clearChecks(); - // Clear the static pointers for the Seed Header and Data + // Clear the static pointers for the Seed Header and Data. These are used by TPO void** ptrTable = reinterpret_cast(0x800042BC); ptrTable[0] = nullptr; ptrTable[1] = nullptr; @@ -115,9 +114,6 @@ namespace mod::rando delete[] m_GCIData; } - // Clear the memory used by the required dungeons text that is displayed when reading the sign in front of Link's house - delete[] m_RequiredDungeons; - // Clear the bgm table buffers delete[] m_BgmTable; delete[] m_FanfareTable; @@ -195,4 +191,47 @@ namespace mod::rando m_FanfareTable = reinterpret_cast(buf); } } + + void Seed::loadShuffledEntrances() + { + const entryInfo* shuffledEntranceInfo = &m_Header->EntranceTableInfo; + const uint32_t num_shuffledEntrances = shuffledEntranceInfo->numEntries; + const uint32_t gci_offset = shuffledEntranceInfo->dataOffset; + + // Set the pointer as offset into our buffer + m_ShuffledEntrances = reinterpret_cast(&m_GCIData[gci_offset]); + m_numShuffledEntrances = num_shuffledEntrances; + } + + void Seed::loadCustomText(uint8_t* data) + { + const uint32_t headerOffset = m_Header->headerSize + m_Header->customTextHeaderOffset; + + // Get the custom message header + const CustomMessageHeaderInfo* customMessageHeader = reinterpret_cast(&data[headerOffset]); + + // Allocate memory for the ids, message offsets, and messages + m_TotalHintMsgEntries = customMessageHeader->totalEntries; + uint32_t msgIdTableSize = m_TotalHintMsgEntries * sizeof(CustomMessageData); + const uint32_t msgOffsetTableSize = m_TotalHintMsgEntries * sizeof(uint32_t); + + // Round msgIdTableSize up to the size of the offsets to make sure the offsets are properly aligned + msgIdTableSize = (msgIdTableSize + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1); + const uint32_t msgTableInfoSize = msgIdTableSize + msgOffsetTableSize + customMessageHeader->msgTableSize; + + // Align to uint16_t, as thagt's the largest variable type in CustomMessageData + m_HintMsgTableInfo = new (sizeof(uint16_t)) uint8_t[msgTableInfoSize]; + // When calculating the offset the the message table information, we are assuming that the message header is + // followed by the entry information for all of the languages in the seed data. + const uint32_t offset = headerOffset + customMessageHeader->msgIdTableOffset; + + // Copy the data to the pointers + memcpy(m_HintMsgTableInfo, &data[offset], msgTableInfoSize); + + for (uint32_t i = msgIdTableSize + msgOffsetTableSize; i < msgTableInfoSize; i++) + { + m_HintMsgTableInfo[i] = ~m_HintMsgTableInfo[i]; + } + } + } // namespace mod::rando \ No newline at end of file diff --git a/GameCube/subrel/seed/source/user_patch/05_newFileFunctions.cpp b/GameCube/subrel/seed/source/user_patch/05_newFileFunctions.cpp index 2e5be0f6..9f33938f 100644 --- a/GameCube/subrel/seed/source/user_patch/05_newFileFunctions.cpp +++ b/GameCube/subrel/seed/source/user_patch/05_newFileFunctions.cpp @@ -2,6 +2,8 @@ #include "rando/data.h" #include "rando/randomizer.h" #include "user_patch/user_patch.h" +#include "asm_templates.h" +#include "memory.h" namespace mod::user_patch { @@ -22,4 +24,25 @@ namespace mod::user_patch (void)randomizer; increaseSpinnerSpeed = set; } + + void skipMajorCutscenes(rando::Randomizer* randomizer, bool set) + { + (void)randomizer; + + uint32_t* skipperFunctionAddress = + reinterpret_cast(reinterpret_cast(libtp::tp::d_event::skipper) + 0x54); + + if (set) + { + // Modifies the 'skipper' function to automatically attempt to skip all major cutscenes + *skipperFunctionAddress = ASM_COMPARE_LOGICAL_WORD_IMMEDIATE(30, 0); + } + else + { + // Vanilla instruction + *skipperFunctionAddress = 0x540004e7; // rlwinm r0,r0,0,19,19 + } + + libtp::memory::clear_DC_IC_Cache(skipperFunctionAddress, sizeof(uint32_t)); + } } // namespace mod::user_patch \ No newline at end of file diff --git a/GameCube/subrel/seed/source/user_patch/user_patch.cpp b/GameCube/subrel/seed/source/user_patch/user_patch.cpp index fa4c90a0..74d68499 100644 --- a/GameCube/subrel/seed/source/user_patch/user_patch.cpp +++ b/GameCube/subrel/seed/source/user_patch/user_patch.cpp @@ -14,6 +14,11 @@ namespace mod::user_patch { - GamePatch oneTimePatches[6] = - {patchWallet, removeIBLimit, loadShopModels, disableBattleMusic, setInstantText, increaseSpinnerVelocity}; + GamePatch oneTimePatches[7] = {patchWallet, + removeIBLimit, + loadShopModels, + disableBattleMusic, + setInstantText, + increaseSpinnerVelocity, + skipMajorCutscenes}; } \ No newline at end of file