Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions mm/2s2h/BenGui/BenMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,14 @@ void BenMenu::AddEnhancements() {
AddWidget(path, "Time Moves when you Move", WIDGET_CVAR_CHECKBOX)
.CVar("gModes.TimeMovesWhenYouMove")
.Options(CheckboxOptions().Tooltip("Time only moves when Link is not standing still."));
AddWidget(path, "Super Hot", WIDGET_CVAR_CHECKBOX)
.CVar("gModes.SuperHot")
.PreFunc([](WidgetInfo& info) {
if (mBenMenu->disabledMap.at(DISABLE_FOR_TIME_MOVES_WHEN_YOU_MOVE).active) {
info.activeDisables.push_back(DISABLE_FOR_TIME_MOVES_WHEN_YOU_MOVE);
}
})
.Options(CheckboxOptions().Tooltip("Actor updates are also tied to Link moving"));
AddWidget(path, "Mirrored World", WIDGET_CVAR_CHECKBOX)
.CVar("gModes.MirroredWorld.Mode")
.Callback([](WidgetInfo& info) {
Expand Down Expand Up @@ -2052,6 +2060,9 @@ void BenMenu::InitElement() {
return CVarGetInteger("gEnhancements.Minigames.BoatArcheryInvincible", 0);
},
"Koume is Invincible" } },
{ DISABLE_FOR_TIME_MOVES_WHEN_YOU_MOVE,
{ [](disabledInfo& info) -> bool { return !CVarGetInteger("gModes.TimeMovesWhenYouMove", 0); },
"'Time Moves when you Move' is Disabled" } },
};
}

Expand Down
1 change: 1 addition & 0 deletions mm/2s2h/BenGui/MenuTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ typedef enum {
DISABLE_FOR_VERTICAL_RESOLUTION_OFF,
DISABLE_FOR_LINKS_VOICE_PITCH_MULTIPLIER_OFF,
DISABLE_FOR_KOUME_INVINCIBLE,
DISABLE_FOR_TIME_MOVES_WHEN_YOU_MOVE,
} DisableOption;

struct WidgetInfo;
Expand Down
87 changes: 45 additions & 42 deletions mm/2s2h/Enhancements/Modes/TimeMovesWhenYouMove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,64 @@

extern "C" {
#include "variables.h"
#include "overlays/actors/ovl_Arms_Hook/z_arms_hook.h"
void ArmsHook_Shoot(ArmsHook*, PlayState*);
}

#define CVAR_NAME "gModes.TimeMovesWhenYouMove"
#define CVAR CVarGetInteger(CVAR_NAME, 0)
#define TIME_MOVES_CVAR_NAME "gModes.TimeMovesWhenYouMove"
#define TIME_MOVES_CVAR CVarGetInteger(TIME_MOVES_CVAR_NAME, 0)

#define SUPER_HOT_CVAR_NAME "gModes.SuperHot"
#define SUPER_HOT_CVAR CVarGetInteger(SUPER_HOT_CVAR_NAME, 0)

// Arbitrary speed to determine the offset is unset
#define DEFAULT_TIME_OFFSET -12345
static s32 sStoredTimeOffset = DEFAULT_TIME_OFFSET;

void RegisterTimeMovesWhenYouMove() {
if (!CVAR && sStoredTimeOffset != DEFAULT_TIME_OFFSET) {
if (!TIME_MOVES_CVAR && sStoredTimeOffset != DEFAULT_TIME_OFFSET) {
gSaveContext.save.timeSpeedOffset = sStoredTimeOffset;
sStoredTimeOffset = DEFAULT_TIME_OFFSET;
}

// This is WIP code, sort of turns this enhancement into a "Super Hot" mode where
// actors update functions are also halted when not moving. The problem is this breaks
// many situations, like opening a chest or talking to actors. So it needs more time in the oven

// COND_HOOK(ShouldActorUpdate, CVAR, [](Actor* actor, bool* should) {
// static bool hookIsFiring = false;
// if (actor->id == ACTOR_ARMS_HOOK) {
// ArmsHook* hook = (ArmsHook*)actor;
// if (hook->actionFunc == ArmsHook_Shoot) {
// hookIsFiring = true;
// } else {
// hookIsFiring = false;
// }
// }
COND_HOOK(ShouldActorUpdate, TIME_MOVES_CVAR && SUPER_HOT_CVAR, [](Actor* actor, bool* should) {
static bool hookIsFiring = false;
if (actor->id == ACTOR_ARMS_HOOK) {
ArmsHook* hook = (ArmsHook*)actor;
if (hook->actionFunc == ArmsHook_Shoot) {
hookIsFiring = true;
} else {
hookIsFiring = false;
}
}

// if (actor->id != ACTOR_EN_ARROW &&
// (actor->id == ACTOR_PLAYER || actor->category == ACTORCAT_BG || actor->category == ACTORCAT_DOOR ||
// actor->category == ACTORCAT_SWITCH || actor->category == ACTORCAT_ITEMACTION)) {
// return;
// }
if (actor->id != ACTOR_EN_ARROW &&
(actor->id == ACTOR_PLAYER || actor->category == ACTORCAT_BG || actor->category == ACTORCAT_DOOR ||
actor->category == ACTORCAT_SWITCH || actor->category == ACTORCAT_ITEMACTION)) {
return;
}

// Player* player = GET_PLAYER(gPlayState);
Player* player = GET_PLAYER(gPlayState);

// static Actor* lastTalkActor = NULL;
// if (player->talkActor != NULL && player->talkActor != lastTalkActor) {
// lastTalkActor = player->talkActor;
// }
static Actor* lastTalkActor = NULL;
if (player->talkActor != NULL && player->talkActor != lastTalkActor) {
lastTalkActor = player->talkActor;
}

// if (player->speedXZ == 0 &&
// lastTalkActor != actor && !(player->stateFlags1 & PLAYER_STATE1_1) &&
// !(player->stateFlags1 & PLAYER_STATE1_2) && !(player->stateFlags1 & PLAYER_STATE1_20) &&
// !(player->stateFlags1 & PLAYER_STATE1_TALKING) && !(player->stateFlags1 & PLAYER_STATE1_80) &&
// !(player->stateFlags1 & PLAYER_STATE1_100) && !(player->stateFlags1 & PLAYER_STATE1_400) &&
// !(player->stateFlags1 & PLAYER_STATE1_1000) && !(player->stateFlags1 & PLAYER_STATE1_2000000) &&
// !(player->stateFlags1 & PLAYER_STATE1_10000000) && !(player->stateFlags1 & PLAYER_STATE1_20000000) &&
// !(player->stateFlags2 & PLAYER_STATE2_8) && !(player->stateFlags3 & PLAYER_STATE3_8) &&
// !(player->stateFlags3 & PLAYER_STATE3_2000000) && (!hookIsFiring)) {
// *should = false;
// }
// });
if (player->speedXZ == 0 && lastTalkActor != actor && !(player->stateFlags1 & PLAYER_STATE1_1) &&
!(player->stateFlags1 & PLAYER_STATE1_2) && !(player->stateFlags1 & PLAYER_STATE1_20) &&
!(player->stateFlags1 & PLAYER_STATE1_TALKING) && !(player->stateFlags1 & PLAYER_STATE1_DEAD) &&
!(player->stateFlags1 & PLAYER_STATE1_100) && !(player->stateFlags1 & PLAYER_STATE1_400) &&
!(player->stateFlags1 & PLAYER_STATE1_CHARGING_SPIN_ATTACK) &&
!(player->stateFlags1 & PLAYER_STATE1_ZORA_BOOMERANG_THROWN) &&
!(player->stateFlags1 & PLAYER_STATE1_10000000) && !(player->stateFlags1 & PLAYER_STATE1_20000000) &&
!(player->stateFlags2 & PLAYER_STATE2_8) && !(player->stateFlags3 & PLAYER_STATE3_8) &&
!(player->stateFlags3 & PLAYER_STATE3_2000000) && (!hookIsFiring)) {
*should = false;
}
});

COND_ID_HOOK(OnActorUpdate, ACTOR_PLAYER, CVAR, [](Actor* actor) {
COND_ID_HOOK(OnActorUpdate, ACTOR_PLAYER, TIME_MOVES_CVAR, [](Actor* actor) {
Player* player = GET_PLAYER(gPlayState);
bool timeShouldMove = (player->stateFlags2 & PLAYER_STATE2_USING_OCARINA) || player->speedXZ != 0.0f;

Expand All @@ -69,12 +70,14 @@ void RegisterTimeMovesWhenYouMove() {
sStoredTimeOffset = DEFAULT_TIME_OFFSET;

// This is for the section above, lets arrows continue flying after they were fired with time frozen
// player->unk_D57 = 4;
if (SUPER_HOT_CVAR) {
player->unk_D57 = 4;
}
} else if (!timeShouldMove && sStoredTimeOffset == DEFAULT_TIME_OFFSET) {
sStoredTimeOffset = gSaveContext.save.timeSpeedOffset;
gSaveContext.save.timeSpeedOffset = -R_TIME_SPEED;
}
});
}

static RegisterShipInitFunc initFunc(RegisterTimeMovesWhenYouMove, { CVAR_NAME });
static RegisterShipInitFunc initFunc(RegisterTimeMovesWhenYouMove, { TIME_MOVES_CVAR_NAME, SUPER_HOT_CVAR_NAME });
Loading