blob: 40823778bba1db68c15b64794b37481b301e772e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#include "MiscBehavior.h"
extern "C" {
#include <variables.h>
#include <functions.h>
}
SaveContext saveContextCopy;
// TODO: This should be moved somewhere else
bool IsRenewable(RandoItemId randoItemId) {
switch (randoItemId) {
case RI_BOTTLE_MILK:
case RI_MILK_REFILL:
case RI_BOTTLE_GOLD_DUST:
case RI_GOLD_DUST_REFILL:
case RI_BOTTLE_CHATEAU_ROMANI:
case RI_CHATEAU_ROMANI_REFILL:
case RI_RED_POTION_REFILL:
case RI_BLUE_POTION_REFILL:
case RI_GREEN_POTION_REFILL:
case RI_MAGIC_BEAN:
return true;
default:
return false;
}
}
void Rando::MiscBehavior::BeforeEndOfCycleSave() {
memcpy(&saveContextCopy, &gSaveContext, sizeof(SaveContext));
}
void Rando::MiscBehavior::AfterEndOfCycleSave() {
for (int i = 0; i < 8; i++) {
gSaveContext.save.saveInfo.inventory.dungeonItems[i] = saveContextCopy.save.saveInfo.inventory.dungeonItems[i];
gSaveContext.save.saveInfo.inventory.dungeonKeys[i] =
saveContextCopy.save.shipSaveInfo.rando.foundDungeonKeys[i];
gSaveContext.save.saveInfo.inventory.strayFairies[i] = saveContextCopy.save.saveInfo.inventory.strayFairies[i];
}
if (saveContextCopy.save.saveInfo.weekEventReg[((WEEKEVENTREG_08_80) >> 8)] & ((WEEKEVENTREG_08_80)&0xFF)) {
SET_WEEKEVENTREG(WEEKEVENTREG_08_80);
}
if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_GOLD_SKULLTULAS]) {
gSaveContext.save.saveInfo.skullTokenCount = saveContextCopy.save.saveInfo.skullTokenCount;
}
// Persist found frogs in frog shuffle. TODO: Make this optional
if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_FROGS]) {
if (saveContextCopy.save.saveInfo.weekEventReg[32] & 0x40) {
SET_WEEKEVENTREG(WEEKEVENTREG_32_40);
}
if (saveContextCopy.save.saveInfo.weekEventReg[32] & 0x80) {
SET_WEEKEVENTREG(WEEKEVENTREG_32_80);
}
if (saveContextCopy.save.saveInfo.weekEventReg[33] & 0x01) {
SET_WEEKEVENTREG(WEEKEVENTREG_33_01);
}
if (saveContextCopy.save.saveInfo.weekEventReg[33] & 0x02) {
SET_WEEKEVENTREG(WEEKEVENTREG_33_02);
}
}
// For now, we're just going to always persist these slots. We may do something smarter here later if this causes
// any issues.
gSaveContext.save.saveInfo.inventory.items[SLOT_TRADE_DEED] =
saveContextCopy.save.saveInfo.inventory.items[SLOT_TRADE_DEED];
gSaveContext.save.saveInfo.inventory.items[SLOT_TRADE_KEY_MAMA] =
saveContextCopy.save.saveInfo.inventory.items[SLOT_TRADE_KEY_MAMA];
gSaveContext.save.saveInfo.inventory.items[SLOT_TRADE_COUPLE] =
saveContextCopy.save.saveInfo.inventory.items[SLOT_TRADE_COUPLE];
// Unset any flags used for checks, whether or not they get the item or junk is determined on our end instead.
for (auto& [randoCheckId, randoStaticCheck] : Rando::StaticData::Checks) {
RANDO_SAVE_CHECKS[randoCheckId].cycleObtained = false;
if (randoCheckId == RC_CLOCK_TOWN_WEST_BANK_ADULTS_WALLET || randoCheckId == RC_CLOCK_TOWN_WEST_BANK_INTEREST ||
randoCheckId == RC_CLOCK_TOWN_WEST_BANK_PIECE_OF_HEART) {
continue;
}
switch (randoStaticCheck.flagType) {
case FLAG_WEEK_EVENT_REG:
// Clear the flag without triggering hook
WEEKEVENTREG((randoStaticCheck.flag) >> 8) =
GET_WEEKEVENTREG((randoStaticCheck.flag) >> 8) & (u8) ~((randoStaticCheck.flag) & 0xFF);
break;
case FLAG_CYCL_SCENE_SWITCH:
// Clear the flag without triggering hook
if (gPlayState->sceneId == randoStaticCheck.sceneId) {
gPlayState->actorCtx.sceneFlags.switches[(randoStaticCheck.flag & ~0x1F) >> 5] &=
~(1 << (randoStaticCheck.flag & 0x1F));
}
if ((randoStaticCheck.flag & ~0x1F) >> 5 == 0) {
gSaveContext.save.saveInfo.permanentSceneFlags[randoStaticCheck.sceneId].switch0 &=
~(1 << (randoStaticCheck.flag & 0x1F));
gSaveContext.cycleSceneFlags[randoStaticCheck.sceneId].switch0 &=
~(1 << (randoStaticCheck.flag & 0x1F));
} else if ((randoStaticCheck.flag & ~0x1F) >> 5 == 1) {
gSaveContext.save.saveInfo.permanentSceneFlags[randoStaticCheck.sceneId].switch1 &=
~(1 << (randoStaticCheck.flag & 0x1F));
gSaveContext.cycleSceneFlags[randoStaticCheck.sceneId].switch1 &=
~(1 << (randoStaticCheck.flag & 0x1F));
}
break;
case FLAG_CYCL_SCENE_COLLECTIBLE:
// Clear the flag without triggering hook
if (gPlayState->sceneId == randoStaticCheck.sceneId) {
gPlayState->actorCtx.sceneFlags.collectible[(randoStaticCheck.flag & ~0x1F) >> 5] &=
~(1 << (randoStaticCheck.flag & 0x1F));
}
gSaveContext.save.saveInfo.permanentSceneFlags[randoStaticCheck.sceneId].collectible &=
~(1 << (randoStaticCheck.flag & 0x1F));
gSaveContext.cycleSceneFlags[randoStaticCheck.sceneId].collectible &=
~(1 << (randoStaticCheck.flag & 0x1F));
break;
}
}
// Re-grant initial items, in the future we may only do this if it's a refill
if (IsRenewable(RANDO_SAVE_CHECKS[RC_STARTING_ITEM_DEKU_MASK].randoItemId)) {
RANDO_SAVE_CHECKS[RC_STARTING_ITEM_DEKU_MASK].eligible = true;
}
if (IsRenewable(RANDO_SAVE_CHECKS[RC_STARTING_ITEM_SONG_OF_HEALING].randoItemId)) {
RANDO_SAVE_CHECKS[RC_STARTING_ITEM_SONG_OF_HEALING].eligible = true;
}
// Override a cycle reset from trying to restore your sword if you don't have one
u8 curSword = (saveContextCopy.save.saveInfo.equips.equipment & gEquipMasks[EQUIP_TYPE_SWORD]) >>
gEquipShifts[EQUIP_TYPE_SWORD];
u8 stolen1 = ((saveContextCopy.save.saveInfo.stolenItems & 0xFF000000) >> 0x18);
u8 stolen2 = ((saveContextCopy.save.saveInfo.stolenItems & 0x00FF0000) >> 0x10);
// Check for sword not being stolen. Rando doesn't turn sword in to the smithy, so don't need to check that
if (curSword == EQUIP_VALUE_SWORD_NONE && !((stolen1 >= ITEM_SWORD_KOKIRI && stolen1 <= ITEM_SWORD_GILDED) ||
(stolen2 >= ITEM_SWORD_KOKIRI && stolen2 <= ITEM_SWORD_GILDED))) {
SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_NONE);
BUTTON_ITEM_EQUIP(0, EQUIP_SLOT_B) = ITEM_NONE;
}
}
|