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
|
#include "MiscBehavior.h"
#include <libultraship/bridge/consolevariablebridge.h>
#include "2s2h/GameInteractor/GameInteractor.h"
#include "2s2h/CustomItem/CustomItem.h"
#include "2s2h/CustomMessage/CustomMessage.h"
#include "2s2h/BenGui/Notification.h"
#include "2s2h/Rando/StaticData/StaticData.h"
#include "2s2h/ShipUtils.h"
#include "Traps.h"
extern "C" {
#include "variables.h"
#include <functions.h>
extern TexturePtr gItemIcons[131];
extern s16 D_801CFF94[250];
}
static bool queued = false;
// This function handles queuing up item gives that the player has been marked as eligible for. If you are looking for
// the behavior of the actual giving itself, the heavy lifting is done by the GameInteractor queue. This function is
// currently called every frame, and loops through the entire list of checks, this works for now but as the check list
// grows we should keep an eye on performance.
//
// Though it seems counter-intuitive, we currently only allow one thing from randommizer to be queued at a time,
// primarily because of the way an item can be converted may change as you queue up multiple items. This is actually
// fine for both the giving/drawing, as we can call ConvertItem() inside the Give/Draw lambda, but the message we
// pass to the queue is static and would need to be updated if we allowed multiple items to be queued at once.
void Rando::MiscBehavior::CheckQueue() {
if (queued) {
return;
}
for (auto& [randoCheckId, randoStaticCheck] : Rando::StaticData::Checks) {
auto randoSaveCheck = RANDO_SAVE_CHECKS[randoCheckId];
if (randoSaveCheck.eligible) {
queued = true;
GameInteractor::Instance->events.emplace_back(GIEventGiveItem{
.showGetItemCutscene =
Rando::StaticData::ShouldShowGetItemCutscene(ConvertItem(randoSaveCheck.randoItemId, randoCheckId)),
.param = (int16_t)randoCheckId,
.giveItem =
[](Actor* actor, PlayState* play) {
auto& randoSaveCheck = RANDO_SAVE_CHECKS[CUSTOM_ITEM_PARAM];
RandoItemId randoItemId =
Rando::ConvertItem(randoSaveCheck.randoItemId, (RandoCheckId)CUSTOM_ITEM_PARAM);
std::string prefix = "You found";
std::string message = Rando::StaticData::GetItemName(randoItemId);
if (randoItemId == RI_JUNK) {
randoItemId = Rando::CurrentJunkItem();
}
if (randoItemId == RI_TRIFORCE_PIECE) {
if (gSaveContext.save.shipSaveInfo.rando.foundTriforcePieces + 1 >=
RANDO_SAVE_OPTIONS[RO_TRIFORCE_PIECES_REQUIRED]) {
prefix = "You";
message = "completed the Triforce";
}
randoItemId = RI_TRIFORCE_PIECE_PREVIOUS;
}
if (randoItemId == RI_TRAP) {
prefix = "";
message = GetTrapMessage();
// We need to remove the Color Codes if the player is skipping Item Get Cutscenes as the
// Notification Emit doesnt support it.
if (CVarGetInteger("gEnhancements.Cutscenes.SkipGetItemCutscenes", 0) >= 2) {
message = CustomMessage::RemoveColorCodes(message);
}
}
CustomMessage::Entry entry = {
.textboxType = 2,
.icon = Rando::StaticData::GetIconForZMessage(randoItemId),
.msg = (prefix == "" ? "" : prefix + " ") + message + (randoItemId == RI_TRAP ? "" : "!"),
};
if (CUSTOM_ITEM_FLAGS & CustomItem::GIVE_ITEM_CUTSCENE) {
CustomMessage::SetActiveCustomMessage(entry.msg, entry);
} else if (Rando::StaticData::ShouldShowGetItemCutscene(randoItemId)) {
CustomMessage::StartTextbox(entry.msg + "\x1C\x02\x10", entry);
} else {
Notification::Emit({
.itemIcon = Rando::StaticData::GetIconTexturePath(randoItemId),
.message = prefix,
.suffix = message,
});
}
Rando::GiveItem(randoItemId);
randoSaveCheck.cycleObtained = true;
randoSaveCheck.obtained = true;
randoSaveCheck.eligible = false;
queued = false;
CUSTOM_ITEM_PARAM = randoItemId;
},
.drawItem =
[](Actor* actor, PlayState* play) {
RandoItemId randoItemId;
// If the item has been given, the CUSTOM_ITEM_PARAM is set to the RI, prior to that it's the RC
if (CUSTOM_ITEM_FLAGS & CustomItem::CALLED_ACTION) {
if ((RandoItemId)CUSTOM_ITEM_PARAM == RI_TRAP) {
randoItemId = RI_MAX_TRAP;
} else {
randoItemId = (RandoItemId)CUSTOM_ITEM_PARAM;
}
} else {
auto& randoSaveCheck = RANDO_SAVE_CHECKS[CUSTOM_ITEM_PARAM];
randoItemId =
Rando::ConvertItem(randoSaveCheck.randoItemId, (RandoCheckId)CUSTOM_ITEM_PARAM);
}
Matrix_Scale(30.0f, 30.0f, 30.0f, MTXMODE_APPLY);
Rando::DrawItem(randoItemId);
} });
return;
}
}
}
void Rando::MiscBehavior::CheckQueueReset() {
queued = false;
GameInteractor::Instance->currentEvent = GIEventNone{};
GameInteractor::Instance->events.clear();
}
|