Skip to content

Commit 96f6ccb

Browse files
committed
Implement Quest Framework - Needs Quest Turn in Support later
1 parent 2d30a84 commit 96f6ccb

8 files changed

Lines changed: 222 additions & 0 deletions

File tree

soh/include/z64save.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ typedef struct ShipRogueLikeSaveContextData {
168168
u32 xp;
169169
u32 difficulty;
170170
uint64_t lastActivity;
171+
RogueLikeQuestObject quests[RL_QUEST_ID_MAX];
171172
} ShipRogueLikeSaveContextData;
172173

173174
typedef struct ShipBossRushSaveContextData {

soh/soh/Enhancements/RogueLike/ActorBehavior/ActorBehavior.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
extern "C" {
77
#include "variables.h"
8+
9+
// Quest Includes
10+
#include "overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.h"
11+
void func_80ABAC00(EnNiwLady* thisx, PlayState* play);
812
}
913

1014
// This is kind of a catch-all for things that are simple enough to not need their own file.
@@ -14,6 +18,13 @@ static void MiscVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
1418
*should = true;
1519
break;
1620
}
21+
case VB_GIVE_ITEM_FROM_ANJU_AS_ADULT: {
22+
EnNiwLady* enNiwLady = (EnNiwLady*)optionalArg;
23+
RogueLike::Quests::AddQuestById(RL_QUEST_HF_STALFOS);
24+
enNiwLady->actionFunc = func_80ABAC00;
25+
*should = false;
26+
break;
27+
}
1728
default:
1829
break;
1930
}

soh/soh/Enhancements/RogueLike/GUI/GUI.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ std::map<RoguelikeStats, std::pair<std::string, std::string>> rogueLikeStatMap =
1313
{ RL_DEFENSE, { "Defense", "ITEM_SHIELD_HYLIAN" } },
1414
};
1515

16+
std::vector<RogueLikeQuestObject> activeQuests;
17+
1618
void TableCellVerticalCenteredText(ImVec4 color, const char* text) {
1719
float textHeight = ImGui::GetTextLineHeight();
1820
float offsetX = (32.0f - textHeight + 10.0f) * 0.5f;
@@ -119,6 +121,26 @@ void RogueLike::GUI::HUDWindow::Draw() {
119121
}
120122

121123
ImGui::EndTable();
124+
125+
if (ImGui::BeginChild("QuestWindow", ImVec2(300.0f, 0))) {
126+
if (activeQuests.size() != 0) {
127+
ImVec4 completionColor = ImVec4(1, 1, 1, 1);
128+
for (auto& quests : activeQuests) {
129+
if (quests.questProgress == quests.questGoal) {
130+
completionColor = ImVec4(0, 1, 0, 1);
131+
}
132+
std::string questProgressStr = std::to_string(quests.questProgress).c_str();
133+
questProgressStr += " / ";
134+
questProgressStr += std::to_string(quests.questGoal).c_str();
135+
136+
ImGui::SeparatorText(quests.questName);
137+
ImGui::Text(quests.questDescription);
138+
TableCellHorizontalCenteredText(completionColor, questProgressStr.c_str());
139+
ImGui::Separator();
140+
}
141+
}
142+
ImGui::EndChild();
143+
}
122144
}
123145
ImGui::EndChild();
124146
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include "soh/Enhancements/RogueLike/RogueLike.h"
2+
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
3+
#include "soh/ShipInit.hpp"
4+
5+
extern "C" {
6+
#include "variables.h"
7+
#include "functions.h"
8+
}
9+
10+
static void OnLoadGame(int32_t fileNum) {
11+
ShipInit::Init("IS_ROGUELIKE");
12+
13+
if (IS_ROGUELIKE) {
14+
// TODO: These should all really be moved to OnFileCreate
15+
gSaveContext.ship.quest.data.rogueLike.stats[RL_ATTACK] = 0;
16+
gSaveContext.ship.quest.data.rogueLike.stats[RL_DEFENSE] = 0;
17+
18+
Flags_SetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME);
19+
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
20+
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH);
21+
}
22+
}
23+
24+
static RegisterShipInitFunc
25+
initFunc([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>(OnLoadGame); }, {});
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#include "soh/Enhancements/RogueLike/RogueLike.h"
2+
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
3+
#include "soh/ShipInit.hpp"
4+
#include "soh/ActorDB.h"
5+
#include "soh/Enhancements/custom-message/CustomMessageManager.h"
6+
7+
extern "C" {
8+
#include "variables.h"
9+
#include <macros.h>
10+
#include <functions.h>
11+
12+
extern PlayState* gPlayState;
13+
}
14+
15+
// clang-format off
16+
std::vector<RogueLikeQuestObject> rogueLikeQuestList = {
17+
{ RL_QUEST_HF_STALFOS, RL_QUEST_KILL, "Stal-Not-So-Child", "The Stalchild in Hyrule Field have\ngotten bigger, take them out!", 0, 5 },
18+
};
19+
// clang-format on
20+
21+
extern std::vector<RogueLikeQuestObject> activeQuests;
22+
23+
bool CheckActiveQuestById(u8 questId) {
24+
for (auto& quest : activeQuests) {
25+
if (quest.questId == questId) {
26+
return true;
27+
}
28+
}
29+
return false;
30+
}
31+
32+
bool CheckQuestCompleteById(u8 questId) {
33+
for (auto& quest : activeQuests) {
34+
if (quest.questId == questId) {
35+
return (quest.questProgress == quest.questGoal);
36+
}
37+
}
38+
return false;
39+
}
40+
41+
void RogueLike::Quests::AddQuestById(u8 questId) {
42+
if (CheckActiveQuestById(questId)) {
43+
return;
44+
}
45+
46+
activeQuests.push_back(rogueLikeQuestList[questId]);
47+
}
48+
49+
void RogueLike::Quests::UpdateQuestProgress(u8 questId) {
50+
if (CheckActiveQuestById(questId)) {
51+
return;
52+
}
53+
54+
activeQuests.at(questId).questProgress++;
55+
}
56+
57+
static void InitRogueLikeQuests() {
58+
activeQuests.clear();
59+
}
60+
61+
static void OnLoadGame() {
62+
activeQuests.clear();
63+
for (auto& load : gSaveContext.ship.quest.data.rogueLike.quests) {
64+
if (load.questDescription != NULL) {
65+
activeQuests.push_back(load);
66+
}
67+
}
68+
69+
// Test Quest Add
70+
// RogueLike::Quests::AddQuestById(RL_QUEST_HF_STALFOS);
71+
72+
COND_HOOK(OnSceneSpawnActors, IS_ROGUELIKE, []() {
73+
if (gPlayState->sceneNum == SCENE_HYRULE_FIELD) {
74+
if (CheckActiveQuestById(RL_QUEST_HF_STALFOS)) {
75+
if (!CheckQuestCompleteById(RL_QUEST_HF_STALFOS)) {
76+
float centerX = 2475.3f;
77+
float centerZ = 496.3f;
78+
float radius = 100.0f;
79+
80+
for (int i = activeQuests.at(RL_QUEST_HF_STALFOS).questProgress;
81+
i < activeQuests.at(RL_QUEST_HF_STALFOS).questGoal; i++) {
82+
float angle = i * (2 * M_PI / 5);
83+
float spawnX = centerX + radius * cosf(angle);
84+
float spawnZ = centerZ + radius * sinf(angle);
85+
86+
if (ActorDB::Instance->RetrieveEntry(ACTOR_EN_TEST).entry.valid) {
87+
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_TEST, spawnX, -4.7f, spawnZ, 0, 0,
88+
0, 1, 0);
89+
}
90+
}
91+
}
92+
}
93+
}
94+
});
95+
96+
COND_HOOK(OnActorKill, IS_ROGUELIKE, [](void* actor) {
97+
Actor* refActor = (Actor*)actor;
98+
99+
switch (refActor->id) {
100+
case ACTOR_EN_TEST:
101+
if (CheckActiveQuestById(RL_QUEST_HF_STALFOS)) {
102+
if (!CheckQuestCompleteById(RL_QUEST_HF_STALFOS)) {
103+
activeQuests.at(RL_QUEST_HF_STALFOS).questProgress++;
104+
}
105+
}
106+
break;
107+
default:
108+
break;
109+
}
110+
});
111+
112+
COND_HOOK(OnOpenText, IS_ROGUELIKE, [](u16* textId, bool* loadFromMessageTable) {
113+
if (std::to_string(*textId) == "20542") {
114+
auto entry = CustomMessage::LoadVanillaMessageTableEntry(*textId);
115+
// std::string newText = "Stalfos have been attacking our Cucco's, please help us!";
116+
// entry.msg = newText.c_str();
117+
}
118+
})
119+
}
120+
121+
static RegisterShipInitFunc initFunc(InitRogueLikeQuests, {});
122+
static RegisterShipInitFunc initFunc2(OnLoadGame, { "IS_ROGUELIKE" });
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef ROGUELIKE_QUESTS_H
2+
#define ROGUELIKE_QUESTS_H
3+
4+
extern "C" {
5+
#include <z64math.h>
6+
}
7+
8+
namespace RogueLike {
9+
10+
namespace Quests {
11+
12+
void AddQuestById(u8 questId);
13+
void UpdateQuestProgress(u8 questId);
14+
15+
} // namespace Quests
16+
17+
} // namespace RogueLike
18+
19+
#endif

soh/soh/Enhancements/RogueLike/RogueLike.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
#include "GUI/GUI.h"
55
#include "XP.h"
66
#include "Difficulty.h"
7+
#include "Quests.h"
78
#include "Types.h"
89

10+
extern std::vector<RogueLikeQuestObject> activeQuests;
11+
912
namespace RogueLike {} // namespace RogueLike
1013

1114
#endif // ROGUELIKE_H

soh/soh/Enhancements/RogueLike/Types.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,25 @@ typedef enum {
1111
RL_MAX,
1212
} RoguelikeStats;
1313

14+
typedef enum {
15+
RL_QUEST_KILL,
16+
RL_QUEST_MAX,
17+
} RogueLikeQuestTypes;
18+
19+
typedef enum {
20+
RL_QUEST_HF_STALFOS,
21+
RL_QUEST_ID_MAX,
22+
} RogueLikeQuest;
23+
24+
typedef struct {
25+
u8 questId;
26+
u8 questType;
27+
const char* questName;
28+
const char* questDescription;
29+
u16 questProgress;
30+
u16 questGoal;
31+
} RogueLikeQuestObject;
32+
1433
#ifdef __cplusplus
1534
}
1635
#endif

0 commit comments

Comments
 (0)