Skip to content

Commit d41a3ba

Browse files
committed
the modify cast update
1 parent 1c10525 commit d41a3ba

30 files changed

Lines changed: 469 additions & 182 deletions

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ else()
88
endif()
99
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
1010

11-
project(HorribleMenu VERSION 1.2.2)
11+
project(HorribleMenu VERSION 1.2.3)
1212

1313
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.cpp)
1414
add_library(${PROJECT_NAME} SHARED ${SOURCES})

changelog.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# v1.2.3
2+
- Rework game modification internals to allow safer option toggling mid-level
3+
- This should reduce crash issues with *Flicks* option
4+
- Fix jump boost not working for *Ending Gamble*, *Charged Leap*, and *Super Jump* options while the player's gravity is upside-down
5+
- Lowered cooldown range for *Blinking Icon* option
6+
- Several other fixes
7+
18
# v1.2.2
29
- Tweaked charge-up flow for *Charged Leap* option
310
- Decreased speed multiplier for *Charged Leap* option by `16.7%`

src/Utils.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@
3232

3333
#define HIGHEST_Z cocos2d::CCScene::get()->getHighestChildZ() + 1
3434

35+
#define HORRIBLE_MODIFY_EVENT_HANDLER(Base, Derived) \
36+
listenForHorribleOptionChanges( \
37+
THIS_ID, \
38+
[](HorribleOptionSave data) { \
39+
if (auto b = Base::get()) modify_cast<Derived*>(b)->setupHorribleInterface(data.enabled); \
40+
})
41+
42+
#define HORRIBLE_TOGGLE_MODIFY(Base, Derived) \
43+
$on_mod(Loaded) { \
44+
HORRIBLE_MODIFY_EVENT_HANDLER(Base, Derived); \
45+
}
46+
47+
#define HORRIBLE_SETUP_INTERFACE_FUNC void setupHorribleInterface(bool on = true)
48+
3549
// Additional utility methods for Horrible Menu
3650
namespace horrible {
3751
// Pointer to this Geode mod

src/hooks/Gambler.cpp

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,39 +24,31 @@ class $modify(GamblerPlayLayer, PlayLayer) {
2424
bool triggered = false;
2525
};
2626

27+
HORRIBLE_SETUP_INTERFACE_FUNC {
28+
if (!on) {
29+
unschedule(schedule_selector(GamblerPlayLayer::gamblerCheck));
30+
31+
return;
32+
};
33+
34+
schedule(schedule_selector(GamblerPlayLayer::gamblerCheck), 0.125f);
35+
};
36+
2737
bool init(GJGameLevel* level, bool useReplay, bool dontCreateObjects) {
2838
if (!PlayLayer::init(level, useReplay, dontCreateObjects)) return false;
2939

30-
// check every frame so we can detect each percentage change
31-
if (!m_fields->triggered) schedule(schedule_selector(GamblerPlayLayer::gamblerCheck), 0.125f);
40+
setupHorribleInterface();
3241

3342
return true;
3443
};
3544

36-
// ensure that triggered is reset on level restart/full reset
3745
void fullReset() {
3846
PlayLayer::fullReset();
39-
m_fields->triggered = false;
47+
schedule(schedule_selector(GamblerPlayLayer::gamblerCheck), 0.125f);
4048
log::trace("gambler full reset");
4149
};
4250

43-
void resetLevel() {
44-
PlayLayer::resetLevel();
45-
m_fields->triggered = false;
46-
log::trace("gambler level reset");
47-
};
48-
49-
void resetLevelFromStart() {
50-
PlayLayer::resetLevelFromStart();
51-
m_fields->triggered = false;
52-
log::trace("gambler level reset from start");
53-
};
54-
5551
void gamblerCheck(float) {
56-
auto f = m_fields.self();
57-
58-
if (f->triggered) return;
59-
6052
// detect the moment the player first reaches or crosses 95
6153
if (getCurrentPercentInt() >= 95) {
6254
if (rng::flip()) {
@@ -68,8 +60,8 @@ class $modify(GamblerPlayLayer, PlayLayer) {
6860
m_player1->reversePlayer(nullptr);
6961
m_player2->reversePlayer(nullptr);
7062

71-
m_player1->boostPlayer(rng::get(12.5f, 8.75f));
72-
m_player2->boostPlayer(rng::get(12.5f, 8.75f));
63+
m_player1->boostPlayer(rng::get(12.5f, 8.75f) * (m_player1->m_isUpsideDown ? -1.f : 1.f));
64+
m_player2->boostPlayer(rng::get(12.5f, 8.75f) * (m_player2->m_isUpsideDown ? -1.f : 1.f));
7365
} else {
7466
log::info("Gambler won the bet! instant win.");
7567

@@ -79,8 +71,9 @@ class $modify(GamblerPlayLayer, PlayLayer) {
7971
levelComplete();
8072
};
8173

82-
f->triggered = true;
8374
unschedule(schedule_selector(GamblerPlayLayer::gamblerCheck));
8475
};
8576
};
86-
};
77+
};
78+
79+
HORRIBLE_TOGGLE_MODIFY(PlayLayer, GamblerPlayLayer);

src/hooks/Sticky.cpp

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,32 @@ class $modify(StickyPlayerObject, PlayerObject) {
2323
struct Fields final {
2424
uint8_t chance = options::getChance(THIS_ID);
2525

26-
float m_defSpeed = 0.f;
26+
float defSpeed = 0.f;
2727

28-
CCLabelBMFont* m_clickLabel = nullptr;
28+
CCLabelBMFont* clickLabel = nullptr;
2929

30-
bool m_onGround = true;
30+
bool onGround = true;
3131
};
3232

33-
bool init(int player, int ship, GJBaseGameLayer* gameLayer, CCLayer* layer, bool playLayer) {
34-
if (!PlayerObject::init(player, ship, gameLayer, layer, playLayer)) return false;
35-
33+
HORRIBLE_SETUP_INTERFACE_FUNC {
3634
auto f = m_fields.self();
3735

38-
if (auto pl = PlayLayer::get()) {
39-
f->m_clickLabel = CCLabelBMFont::create("Press again to un-stick!", font::big, pl->getScaledContentWidth() - 12.5f);
40-
f->m_clickLabel->setID("sticky-alert"_spr);
41-
f->m_clickLabel->setScale(0.625f);
42-
f->m_clickLabel->setAlignment(kCCTextAlignmentCenter);
43-
f->m_clickLabel->setAnchorPoint({0.5, 0});
44-
f->m_clickLabel->setPosition({pl->getScaledContentWidth() / 2.f, 25.f});
45-
f->m_clickLabel->setVisible(false);
36+
if (!on) {
37+
cue::resetNode(f->clickLabel);
38+
39+
m_playerSpeed = f->defSpeed;
40+
41+
return;
42+
};
43+
44+
if (auto pl = PlayLayer::get(); pl && !f->clickLabel && !m_isSecondPlayer) {
45+
f->clickLabel = CCLabelBMFont::create("Press again to un-stick!", font::big, pl->getScaledContentWidth() - 12.5f);
46+
f->clickLabel->setID("sticky-alert"_spr);
47+
f->clickLabel->setScale(0.625f);
48+
f->clickLabel->setAlignment(kCCTextAlignmentCenter);
49+
f->clickLabel->setAnchorPoint({0.5, 0});
50+
f->clickLabel->setPosition({pl->getScaledContentWidth() / 2.f, 25.f});
51+
f->clickLabel->setVisible(m_playerSpeed <= 0.f);
4652

4753
auto seq = CCSequence::create(
4854
CCCallFuncN::create(this, callfuncN_selector(StickyPlayerObject::stickyCol1)),
@@ -51,11 +57,19 @@ class $modify(StickyPlayerObject, PlayerObject) {
5157
CCDelayTime::create(0.125f),
5258
nullptr);
5359

54-
pl->m_uiLayer->addChild(f->m_clickLabel, HIGHEST_Z);
55-
f->m_clickLabel->runAction(CCRepeatForever::create(seq));
60+
pl->m_uiLayer->addChild(f->clickLabel, HIGHEST_Z);
61+
f->clickLabel->runAction(CCRepeatForever::create(seq));
5662
};
63+
};
64+
65+
bool init(int player, int ship, GJBaseGameLayer* gameLayer, CCLayer* layer, bool playLayer) {
66+
if (!PlayerObject::init(player, ship, gameLayer, layer, playLayer)) return false;
67+
68+
if (playLayer) {
69+
m_fields->onGround = onGround();
5770

58-
f->m_onGround = onGround();
71+
setupHorribleInterface();
72+
};
5973

6074
return true;
6175
};
@@ -78,21 +92,21 @@ class $modify(StickyPlayerObject, PlayerObject) {
7892

7993
auto f = m_fields.self();
8094

81-
auto wasOnGround = f->m_onGround;
95+
auto wasOnGround = f->onGround;
8296
PlayerObject::hitGround(object, notFlipped);
8397
auto nowOnGround = onGround();
8498

8599
if (m_hasEverJumped) {
86100
if (nowOnGround && !wasOnGround) {
87101
if (rng::fast() < f->chance) {
88-
f->m_defSpeed = m_playerSpeed;
102+
f->defSpeed = m_playerSpeed;
89103
m_playerSpeed = 0.f;
90104

91-
if (f->m_clickLabel) f->m_clickLabel->setVisible(true);
105+
if (f->clickLabel) f->clickLabel->setVisible(true);
92106
};
93107
};
94108

95-
f->m_onGround = nowOnGround;
109+
f->onGround = nowOnGround;
96110
};
97111
};
98112

@@ -101,13 +115,21 @@ class $modify(StickyPlayerObject, PlayerObject) {
101115

102116
auto f = m_fields.self();
103117

104-
if (m_playerSpeed <= 0.f && f->m_onGround) {
105-
m_playerSpeed = f->m_defSpeed;
106-
if (f->m_clickLabel) f->m_clickLabel->setVisible(false);
118+
if (m_playerSpeed <= 0.f && f->onGround) {
119+
m_playerSpeed = f->defSpeed;
120+
if (f->clickLabel) f->clickLabel->setVisible(false);
107121
};
108122

109-
f->m_onGround = onGround();
123+
f->onGround = onGround();
110124

111125
return true;
112126
};
127+
};
128+
129+
$on_mod(Loaded) {
130+
listenForHorribleOptionChanges(
131+
THIS_ID,
132+
[](HorribleOptionSave data) {
133+
if (auto pl = PlayLayer::get()) modify_cast<StickyPlayerObject*>(pl->m_player1)->setupHorribleInterface(data.enabled);
134+
});
113135
};

src/hooks/chances/CrashGame.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class $modify(CrashGamePlayLayer, PlayLayer) {
3333
log::warn("ur game crash hehehehehehehe");
3434

3535
PlayLayer::destroyPlayer(p0, p1);
36-
game::exit(true); // saves data
36+
game::exit(true); // saves data mrrp
3737
};
3838

3939
PlayLayer::destroyPlayer(p0, p1);

src/hooks/chances/Pause.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,37 @@ static auto const o = Option::create(THIS_ID)
1717
->setCheating(true)
1818
->autoRegister();
1919

20-
class $modify(PausePlayerObject, PlayLayer) {
20+
class $modify(PausePlayLayer, PlayLayer) {
2121
HORRIBLE_DELEGATE_HOOKS(THIS_ID);
2222

2323
struct Fields final {
2424
uint8_t chance = options::getChance(THIS_ID);
2525
};
2626

27+
HORRIBLE_SETUP_INTERFACE_FUNC {
28+
if (!on) {
29+
unschedule(schedule_selector(PausePlayLayer::pause));
30+
31+
return;
32+
};
33+
34+
nextPause();
35+
};
36+
2737
void setupHasCompleted() {
2838
PlayLayer::setupHasCompleted();
29-
nextPause();
39+
setupHorribleInterface();
3040
};
3141

3242
void nextPause() {
3343
log::trace("scheduling pause");
34-
scheduleOnce(schedule_selector(PausePlayerObject::pause), rng::get(15.f, 3.f) * chanceToDelayPct(m_fields->chance));
44+
scheduleOnce(schedule_selector(PausePlayLayer::pause), rng::get(15.f, 3.f) * chanceToDelayPct(m_fields->chance));
3545
};
3646

3747
void pause(float) {
3848
nextPause();
3949
pauseGame(true);
4050
};
41-
};
51+
};
52+
53+
HORRIBLE_TOGGLE_MODIFY(PlayLayer, PausePlayLayer);

src/hooks/chances/RandomMirror.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,20 @@ class $modify(RandomMirrorPlayLayer, PlayLayer) {
2525
bool isFlipped = false;
2626
};
2727

28+
HORRIBLE_SETUP_INTERFACE_FUNC {
29+
if (!on) {
30+
unschedule(schedule_selector(RandomMirrorPlayLayer::nextFlipPortal));
31+
unschedule(schedule_selector(RandomMirrorPlayLayer::flipPortal));
32+
33+
return;
34+
};
35+
36+
scheduleOnce(schedule_selector(RandomMirrorPlayLayer::nextFlipPortal), 0.125f);
37+
};
38+
2839
void setupHasCompleted() {
2940
PlayLayer::setupHasCompleted();
30-
scheduleOnce(schedule_selector(RandomMirrorPlayLayer::nextFlipPortal), 0.125f);
41+
setupHorribleInterface();
3142
};
3243

3344
void toggleFlipped(bool p0, bool p1) {
@@ -45,9 +56,9 @@ class $modify(RandomMirrorPlayLayer, PlayLayer) {
4556
};
4657

4758
void flipPortal(float) {
48-
auto f = m_fields.self();
49-
50-
toggleFlipped(!f->isFlipped, false);
59+
toggleFlipped(!m_fields->isFlipped, false);
5160
scheduleOnce(schedule_selector(RandomMirrorPlayLayer::nextFlipPortal), 2.5f);
5261
};
53-
};
62+
};
63+
64+
HORRIBLE_TOGGLE_MODIFY(PlayLayer, RandomMirrorPlayLayer);

src/hooks/mechanics/DoubleJump.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class $modify(DoubleJumpPlayerObject, PlayerObject) {
2727
};
2828

2929
bool pushButton(PlayerButton p0) {
30+
if (!m_gameLayer) return PlayerObject::pushButton(p0);
31+
3032
auto f = m_fields.self();
3133

3234
if (p0 == PlayerButton::Jump) {

0 commit comments

Comments
 (0)