Skip to content

Commit def34c8

Browse files
committed
test delegate system
1 parent 35ebb3e commit def34c8

7 files changed

Lines changed: 220 additions & 194 deletions

File tree

include/Events.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// Container for Horrible Ideas API
88
namespace horrible {
99
// Event for option toggles
10-
struct OptionEvent final : geode::GlobalEvent<OptionEvent, bool(std::string, bool), std::string> {
10+
struct OptionEvent final : geode::GlobalEvent<OptionEvent, bool(std::string_view, bool), std::string_view> {
1111
using GlobalEvent::GlobalEvent;
1212
};
1313
};

include/Horrible.hpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,18 @@
1919

2020
#include <cocos2d.h>
2121

22+
#include <Geode/utils/function.hpp>
23+
#include <Geode/utils/ZStringView.hpp>
24+
2225
// Container for Horrible Ideas API functions
2326
namespace horrible {
2427
// Mod option manager for Horrible Ideas
2528
class AWCW_HORRIBLE_API_DLL OptionManager final : public cocos2d::CCObject {
2629
private:
2730
std::vector<Option> m_options; // Array of registered options
2831
std::vector<std::string> m_categories; // Array of auto-registered categories
32+
std::unordered_map<std::string_view, std::vector<std::function<void()>>> m_delegates; // Map of option ID to array of delegates to call when that option is toggled
2933

30-
protected:
3134
/**
3235
* Register a category if not already registered
3336
*
@@ -55,6 +58,14 @@ namespace horrible {
5558
*/
5659
void registerOption(Option option);
5760

61+
/**
62+
* Upsert a new hook delegate
63+
*
64+
* @param id The ID of the option to set the delegate for
65+
* @param callback The hook callback to register for this option's delegate
66+
*/
67+
void addDelegate(std::string_view id, std::function<void()>&& callback);
68+
5869
/**
5970
* Returns a reference to the array of all registered options
6071
*
@@ -79,7 +90,7 @@ namespace horrible {
7990
*
8091
* @returns Boolean of the old value
8192
*/
82-
bool setOption(geode::ZStringView id, bool enable) const;
93+
bool setOption(std::string_view id, bool enable) const;
8394

8495
/**
8596
* Returns a reference to the array of all registered categories

src/Utils.hpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22

3+
#include <ranges>
4+
35
#include <Horrible.hpp>
46

57
#include <classes/Jumpscares.hpp>
@@ -13,6 +15,8 @@
1315

1416
#include <cocos2d.h>
1517

18+
#include <Geode/utils/ZStringView.hpp>
19+
1620
#include <Geode/binding/FMODAudioEngine.hpp>
1721

1822
// Additional utility methods for Horrible Ideas
@@ -69,4 +73,30 @@ namespace horrible {
6973
using namespace ::horrible::ui;
7074
using namespace ::horrible::util;
7175
};
72-
};
76+
77+
template <typename Map>
78+
inline void delegateHooks(geode::ZStringView id, Map& hooks) {
79+
if (auto om = OptionManager::get()) {
80+
auto value = om->getOption(id);
81+
82+
std::vector<geode::Hook*> allHooks;
83+
for (auto& hook : hooks | std::views::values) {
84+
hook->setAutoEnable(value);
85+
allHooks.push_back(hook.get());
86+
};
87+
88+
om->addDelegate(
89+
id,
90+
[allHooks = std::move(allHooks), id, om] {
91+
auto value = om->getOption(id);
92+
for (auto hook : allHooks) (void)hook->toggle(value);
93+
}
94+
);
95+
};
96+
};
97+
};
98+
99+
#define DELEGATE_HOOKS(id) \
100+
static void onModify(auto& self) { \
101+
horrible::delegateHooks(id, self.m_hooks); \
102+
}

src/classes/ui/src/MathQuiz.cpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,6 @@ bool MathQuiz::init() {
4242
m_impl->m_numSecond = randng::get(10);
4343

4444
m_impl->m_operation = static_cast<MathOperation>(randng::get(3));
45-
switch (m_impl->m_operation) {
46-
default: [[fallthrough]];
47-
48-
case MathOperation::Addition:
49-
m_impl->m_correctAnswer = m_impl->m_numFirst + m_impl->m_numSecond;
50-
break;
51-
52-
case MathOperation::Subtraction:
53-
m_impl->m_correctAnswer = m_impl->m_numFirst - m_impl->m_numSecond;
54-
break;
55-
56-
case MathOperation::Multiplication:
57-
m_impl->m_correctAnswer = m_impl->m_numFirst * m_impl->m_numSecond;
58-
break;
59-
};
6045

6146
auto const winSize = CCDirector::get()->getWinSize();
6247

@@ -119,6 +104,22 @@ bool MathQuiz::init() {
119104
break;
120105
};
121106

107+
switch (m_impl->m_operation) {
108+
default: [[fallthrough]];
109+
110+
case MathOperation::Addition:
111+
m_impl->m_correctAnswer = m_impl->m_numFirst + m_impl->m_numSecond;
112+
break;
113+
114+
case MathOperation::Subtraction:
115+
m_impl->m_correctAnswer = m_impl->m_numFirst - m_impl->m_numSecond;
116+
break;
117+
118+
case MathOperation::Multiplication:
119+
m_impl->m_correctAnswer = m_impl->m_numFirst * m_impl->m_numSecond;
120+
break;
121+
};
122+
122123
problemText = fmt::format("{} {} {}", m_impl->m_numFirst, operation, m_impl->m_numSecond);
123124

124125
auto equalsLabel = CCLabelBMFont::create("= ?", "goldFont.fnt", getScaledContentWidth() - 1.25f);
@@ -153,8 +154,6 @@ bool MathQuiz::init() {
153154
m_impl->m_timeRemaining = m_impl->m_totalTime = 10.f;
154155
m_impl->m_timer->updateProgress(100.f);
155156

156-
// Generate 4 answer options with the correct answer randomized
157-
m_impl->m_answers.clear();
158157
m_impl->m_answers.push_back(m_impl->m_correctAnswer);
159158

160159
// Add 3 wrong answers
@@ -165,7 +164,7 @@ bool MathQuiz::init() {
165164
};
166165
} else {
167166
while (m_impl->m_answers.size() < 4) {
168-
int wrongAnswer = m_impl->m_correctAnswer + randng::get(10);
167+
int wrongAnswer = m_impl->m_correctAnswer + randng::get(10, -5);
169168
if (wrongAnswer != m_impl->m_correctAnswer && !hasAnswer(wrongAnswer)) m_impl->m_answers.push_back(wrongAnswer);
170169
};
171170
};

src/hooks/PlayLayer/Confetti.cpp

Lines changed: 45 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,79 +16,71 @@ inline static Option const o = {
1616
};
1717
REGISTER_HORRIBLE_OPTION(o);
1818

19+
static constexpr auto s_confettis = std::to_array<const char*>({
20+
"diffIcon_02_btn_001.png",
21+
"explosionIcon_20_001.png",
22+
"GJ_duplicateObjectBtn2_001.png",
23+
"diffIcon_10_btn_001.png",
24+
"modBadge_01_001.png",
25+
"miniSkull_001.png",
26+
"secretCoinUI_001.png",
27+
"secretCoinUI2_001.png",
28+
"GJ_rewardBtn_001.png",
29+
"GJ_achImage_001.png",
30+
"GJ_likesIcon_001.png",
31+
"btn_chatHistory_001.png",
32+
"GJ_starsIcon_001.png",
33+
"GJ_sMagicIcon_001.png",
34+
"GJ_pointsIcon_001.png",
35+
});
36+
1937
class $modify(ConfettiPlayLayer, PlayLayer) {
20-
struct Fields {
21-
bool enabled = options::get(o.id);
22-
23-
static constexpr auto confettis = std::to_array<const char*>({
24-
"diffIcon_02_btn_001.png",
25-
"explosionIcon_20_001.png",
26-
"GJ_duplicateObjectBtn2_001.png",
27-
"diffIcon_10_btn_001.png",
28-
"modBadge_01_001.png",
29-
"miniSkull_001.png",
30-
"secretCoinUI_001.png",
31-
"secretCoinUI2_001.png",
32-
"GJ_rewardBtn_001.png",
33-
"GJ_achImage_001.png",
34-
"GJ_likesIcon_001.png",
35-
"btn_chatHistory_001.png",
36-
"GJ_starsIcon_001.png",
37-
"GJ_sMagicIcon_001.png",
38-
"GJ_pointsIcon_001.png",
39-
});
40-
};
38+
DELEGATE_HOOKS(o.id);
4139

4240
void setupHasCompleted() {
4341
PlayLayer::setupHasCompleted();
4442

45-
auto f = m_fields.self();
46-
47-
if (f->enabled) scheduleOnce(schedule_selector(ConfettiPlayLayer::nextConfetti), randng::get(0.125f));
43+
scheduleOnce(schedule_selector(ConfettiPlayLayer::nextConfetti), randng::get(0.125f));
4844
};
4945

5046
void nextConfetti(float) {
5147
auto delay = randng::get(10.f, 1.f);
5248
log::debug("scheduling confetti in {}s", delay);
5349

54-
if (m_fields->enabled) scheduleOnce(schedule_selector(ConfettiPlayLayer::confetti), delay);
50+
scheduleOnce(schedule_selector(ConfettiPlayLayer::confetti), delay);
5551
};
5652

5753
void confetti(float) {
58-
if (m_fields->enabled) {
59-
log::info("unleashing confetti!");
54+
log::info("unleashing confetti!");
6055

61-
playSfx("jumpscareAudio.mp3");
62-
shakeCamera(1.25f, 2.5f, 0.00875F);
63-
for (int i = 0; i < randng::get(125, 75); i++) createConfetti();
64-
};
56+
playSfx("jumpscareAudio.mp3");
57+
shakeCamera(1.25f, 2.5f, 0.00875F);
58+
for (int i = 0; i < randng::get(125, 75); i++) createConfetti();
6559

6660
scheduleOnce(schedule_selector(ConfettiPlayLayer::nextConfetti), randng::get(0.125f));;
6761
};
6862

6963
void createConfetti() {
70-
if (m_fields->enabled) {
71-
auto conf = CCSprite::createWithSpriteFrameName(Fields::confettis[randng::get(Fields::confettis.size() - 1)]);
72-
conf->setPosition({ 0.f, 0.f });
73-
conf->setScale(0.875f * randng::pc());
74-
75-
auto useY = randng::get(1) > 0;
76-
auto const endPos = ccp(
77-
useY ? getScaledContentWidth() + conf->getScaledContentWidth() : getScaledContentWidth() * randng::pc(),
78-
useY ? getScaledContentHeight() * randng::pc() : getScaledContentHeight() + conf->getScaledContentHeight()
79-
);
80-
81-
auto move = CCEaseSineOut::create(CCMoveTo::create(0.875f + randng::pc() * 2.5f, endPos));
82-
auto rotate = CCEaseSineOut::create(CCRotateBy::create(0.875f + randng::pc() * 2.5f, 360.f * (randng::get(1) > 0 ? 1.f : -1.f)));
83-
84-
auto seq = CCSequence::createWithTwoActions(
85-
CCSpawn::createWithTwoActions(move, rotate),
86-
CCCallFuncN::create(this, callfuncN_selector(ConfettiPlayLayer::cleanConfetti))
87-
);
88-
89-
m_uiLayer->addChild(conf, 9);
90-
conf->runAction(seq);
91-
};
64+
auto conf = CCSprite::createWithSpriteFrameName(s_confettis[randng::get(s_confettis.size() - 1)]);
65+
conf->setPosition({ 0.f, 0.f });
66+
conf->setScale(0.875f * randng::pc());
67+
68+
auto useY = randng::get(1) > 0;
69+
auto const endPos = ccp(
70+
useY ? getScaledContentWidth() + conf->getScaledContentWidth() : getScaledContentWidth() * randng::pc(),
71+
useY ? getScaledContentHeight() * randng::pc() : getScaledContentHeight() + conf->getScaledContentHeight()
72+
);
73+
74+
auto move = CCEaseSineOut::create(CCMoveTo::create(0.875f + randng::pc() * 2.5f, endPos));
75+
auto rotate = CCEaseSineOut::create(CCRotateBy::create(0.875f + randng::pc() * 2.5f, 360.f * (randng::get(1) > 0 ? 1.f : -1.f)));
76+
77+
auto seq = CCSequence::createWithTwoActions(
78+
CCSpawn::createWithTwoActions(move, rotate),
79+
CCCallFuncN::create(this, callfuncN_selector(ConfettiPlayLayer::cleanConfetti))
80+
);
81+
82+
m_uiLayer->addChild(conf, 9);
83+
conf->runAction(seq);
9284
};
9385

9486
void cleanConfetti(CCNode * sender) {

0 commit comments

Comments
 (0)