#include <libultraship/bridge.h>
#include "port/UI/cvar_prefixes.h"
#include "port/Enhancements/Events/Hooks/Events.h"
#include "port/Romhack/RomhackConfig.h"
#include "port/ShipInit.hpp"
#include "port/ShipUtils.h"
#include "enums.h"
#include "core2/statetimer.h"
#include "core2/ba/physics.h"
#include "bs_funcs.h"
#include "functions.h"
#define CVAR_INFINITE_HEALTH CVAR_ENHANCEMENT("Cheats.InfiniteHealth")
#define CVAR_INFINITE_AIR CVAR_ENHANCEMENT("Cheats.InfiniteAir")
#define CVAR_INFINITE_LIVES CVAR_ENHANCEMENT("Cheats.InfiniteLives")
#define CVAR_INFINITE_EGGS CVAR_ENHANCEMENT("Cheats.InfiniteEggs")
#define CVAR_INFINITE_RED_FEATHERS CVAR_ENHANCEMENT("Cheats.InfiniteRedFeathers")
#define CVAR_INFINITE_GOLD_FEATHERS CVAR_ENHANCEMENT("Cheats.InfiniteGoldFeathers")
#define CVAR_INFINITE_BOOTS_SNEAKERS CVAR_ENHANCEMENT("Cheats.InfiniteBootsSneakers")
#define CVAR_TALON_TROT_CYCLE CVAR_ENHANCEMENT("Cheats.TalonTrotCycle")
#define CVAR_LEVITATE CVAR_ENHANCEMENT("Cheats.Levitate")
#define CVAR_NO_MUMBO_UNTRANSFORM CVAR_ENHANCEMENT("Cheats.NoMumboUntransform")
#define CVAR_CYCLE_TRANSFORM CVAR_ENHANCEMENT("Cheats.CycleTransform")
#define CVAR_FAST_TRANSFORM CVAR_ENHANCEMENT("Cheats.FastTransform")
void RegisterInfiniteHealth_Init() {
volatileFlag_set(VOLATILE_FLAG_94_SANDCASTLE_INFINITE_HEALTH, 0);
COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_INFINITE_HEALTH, 0),
[](IEvent* event) { volatileFlag_set(VOLATILE_FLAG_94_SANDCASTLE_INFINITE_HEALTH, 1); });
}
void RegisterInfiniteAir_Init() {
volatileFlag_set(VOLATILE_FLAG_96_SANDCASTLE_INFINITE_AIR, 0);
COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_INFINITE_AIR, 0),
[](IEvent* event) { volatileFlag_set(VOLATILE_FLAG_96_SANDCASTLE_INFINITE_AIR, 1); });
}
void RegisterInfiniteLives_Init() {
COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_INFINITE_LIVES, 0), [](IEvent* event) {
if (gsworld_getMap() != MAP_91_FILE_SELECT && !IsDemoMode()) {
if (item_getCount(ITEM_16_LIFE) < 9) {
item_set(ITEM_16_LIFE, 9);
}
}
});
}
void RegisterInfiniteEggs_Init() {
COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_INFINITE_EGGS, 0), [](IEvent* event) {
if (gsworld_getMap() != MAP_91_FILE_SELECT && !IsDemoMode()) {
s32 currentCount = item_getCount(ITEM_D_EGGS);
s32 maxCount = port_getRomhackMaxEggs();
if (maxCount < 0)
maxCount = 100;
if (currentCount < maxCount) {
item_set(ITEM_D_EGGS, maxCount);
}
}
});
}
void RegisterInfiniteRedFeathers_Init() {
COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_INFINITE_RED_FEATHERS, 0), [](IEvent* event) {
if (gsworld_getMap() != MAP_91_FILE_SELECT && !IsDemoMode()) {
s32 currentCount = item_getCount(ITEM_F_RED_FEATHER);
s32 maxCount = port_getRomhackMaxRedFeathers();
if (maxCount < 0)
maxCount = 50;
if (currentCount < maxCount) {
item_set(ITEM_F_RED_FEATHER, maxCount);
}
}
});
}
void RegisterInfiniteGoldFeathers_Init() {
COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_INFINITE_GOLD_FEATHERS, 0),
[](IEvent* event) {
if (gsworld_getMap() != MAP_91_FILE_SELECT && !IsDemoMode()) {
s32 currentCount = item_getCount(ITEM_10_GOLD_FEATHER);
s32 maxCount = port_getRomhackMaxGoldFeathers();
if (maxCount < 0)
maxCount = 10;
if (currentCount < maxCount) {
item_set(ITEM_10_GOLD_FEATHER, maxCount);
}
}
});
}
void RegisterBootsAndSneakersTimer_Init() {
COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_INFINITE_BOOTS_SNEAKERS, 0),
[](IEvent* event) {
if (stateTimer_isActive(STATE_TIMER_2_LONGLEG)) {
stateTimer_set(STATE_TIMER_2_LONGLEG, 999.0f);
}
if (stateTimer_isActive(STATE_TIMER_3_TURBO_TALON)) {
stateTimer_set(STATE_TIMER_3_TURBO_TALON, 999.0f);
}
});
}
void RegisterTalonTrotCycle_Init() {
COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_TALON_TROT_CYCLE, 0), [](IEvent* event) {
if (bakey_pressed(BUTTON_D_RIGHT) || bakey_pressed(BUTTON_D_LEFT)) {
s32 currentState = bs_getState();
bool inTalonTrot = bsbtrot_inSet(currentState) || bslongleg_inSet(currentState);
if (inTalonTrot) {
bool inBoots = stateTimer_isActive(STATE_TIMER_2_LONGLEG);
bool inSneakers = stateTimer_isActive(STATE_TIMER_3_TURBO_TALON);
if (!inBoots && !inSneakers) {
if (bakey_pressed(BUTTON_D_RIGHT)) {
bs_setState(BS_26_LONGLEG_IDLE);
stateTimer_set(STATE_TIMER_2_LONGLEG, 999.0f);
} else {
stateTimer_set(STATE_TIMER_3_TURBO_TALON, 999.0f);
}
} else if (inBoots) {
if (bakey_pressed(BUTTON_D_RIGHT)) {
bs_setState(BS_15_BTROT_IDLE);
stateTimer_clear(STATE_TIMER_2_LONGLEG);
stateTimer_set(STATE_TIMER_3_TURBO_TALON, 999.0f);
} else {
bs_setState(BS_15_BTROT_IDLE);
stateTimer_clear(STATE_TIMER_2_LONGLEG);
}
} else {
if (bakey_pressed(BUTTON_D_RIGHT)) {
stateTimer_clear(STATE_TIMER_3_TURBO_TALON);
} else {
bs_setState(BS_26_LONGLEG_IDLE);
stateTimer_clear(STATE_TIMER_3_TURBO_TALON);
stateTimer_set(STATE_TIMER_2_LONGLEG, 999.0f);
}
}
}
}
});
}
void RegisterLevitate_Init() {
static const f32 LEVITATE_VELOCITY = 500.0f;
static bool levitateActive = false;
COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_LEVITATE, 0), [](IEvent* event) {
if (bakey_held(BUTTON_L) && !gcdialog_hasCurrentTextId()) {
if (bakey_pressed(BUTTON_L) && !player_isStable()) {
s32 fallDamage = 0;
if (bafalldamage_get_damage(&fallDamage) != 0) {
bafalldamage_start();
bs_setState(BS_1_IDLE);
}
}
baphysics_set_gravity(0.0f);
baphysics_set_vertical_velocity(LEVITATE_VELOCITY);
levitateActive = true;
} else if (levitateActive) {
baphysics_reset_gravity();
levitateActive = false;
}
});
}
static const s32 BAANIM_WISHYWASHY = 0x80;
static bool isWishyWashyUnlocked() {
return (baanim_getActiveBottlesBonusMask() & BAANIM_WISHYWASHY) != 0;
}
static bool jiggyCollectInFlight() {
return baflag_isTrue(BA_FLAG_7_TOUCHING_JIGGY) || bsjig_inJiggyJig((enum bs_e)bs_getState());
}
void RegisterCycleTransform_Init() {
COND_HOOK(GameFrameUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_CYCLE_TRANSFORM, 0), [](IEvent* event) {
if (jiggyCollectInFlight()) {
return;
}
s32 currentTransform = (s32)player_getTransformation();
if (bakey_pressed(BUTTON_D_UP)) {
currentTransform++;
if (currentTransform > TRANSFORM_7_WISHWASHY) {
currentTransform = TRANSFORM_1_BANJO;
}
if (currentTransform == TRANSFORM_7_WISHWASHY && !isWishyWashyUnlocked()) {
currentTransform = TRANSFORM_1_BANJO;
}
player_transform((enum transformation_e)currentTransform);
}
else if (bakey_pressed(BUTTON_D_DOWN)) {
currentTransform--;
if (currentTransform < TRANSFORM_1_BANJO) {
currentTransform = TRANSFORM_7_WISHWASHY;
}
if (currentTransform == TRANSFORM_7_WISHWASHY && !isWishyWashyUnlocked()) {
currentTransform = TRANSFORM_6_BEE;
}
player_transform((enum transformation_e)currentTransform);
}
});
}
void RegisterFastTransform_Init() {
COND_HOOK(SetAnimSpeedMult, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_FAST_TRANSFORM, 0), [](IEvent* event) {
if (baflag_isTrue(BA_FLAG_1B_TRANSFORMING)) {
SetAnimSpeedMult* ev = reinterpret_cast<SetAnimSpeedMult*>(event);
if (ev->id == 0) {
*ev->mult *= 8;
}
}
});
COND_HOOK(OnActorUpdate, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_FAST_TRANSFORM, 0), [](IEvent* event) {
OnActorUpdate* ev = reinterpret_cast<OnActorUpdate*>(event);
if (ev->actor->actor_info->actorId != ACTOR_7_MUMBO) {
return;
}
if (ev->actor->state == 4 || ev->actor->state == 5) {
anctrl_setDuration(ev->actor->anctrl, 7.5f / 8.0f);
}
});
}
void RegisterNoMumboUntransform_Init() {
COND_VB_SHOULD(VB_MUMBO_DETRANSFORM, EVENT_PRIORITY_NORMAL, CVarGetInteger(CVAR_NO_MUMBO_UNTRANSFORM, 0),
{ *should = false; });
}
static RegisterShipInitFunc initInfiniteHealthFunc(RegisterInfiniteHealth_Init, { CVAR_INFINITE_HEALTH });
static RegisterShipInitFunc initInfiniteAirFunc(RegisterInfiniteAir_Init, { CVAR_INFINITE_AIR });
static RegisterShipInitFunc initInfiniteLivesFunc(RegisterInfiniteLives_Init, { CVAR_INFINITE_LIVES });
static RegisterShipInitFunc initInfiniteEggsFunc(RegisterInfiniteEggs_Init, { CVAR_INFINITE_EGGS });
static RegisterShipInitFunc initInfiniteRedFeathersFunc(RegisterInfiniteRedFeathers_Init,
{ CVAR_INFINITE_RED_FEATHERS });
static RegisterShipInitFunc initInfiniteGoldFeathersFunc(RegisterInfiniteGoldFeathers_Init,
{ CVAR_INFINITE_GOLD_FEATHERS });
static RegisterShipInitFunc initBootsAndSneakersTimerFunc(RegisterBootsAndSneakersTimer_Init,
{ CVAR_INFINITE_BOOTS_SNEAKERS });
static RegisterShipInitFunc initBootCycleFunc(RegisterTalonTrotCycle_Init, { CVAR_TALON_TROT_CYCLE });
static RegisterShipInitFunc initLevitateFunc(RegisterLevitate_Init, { CVAR_LEVITATE });
static RegisterShipInitFunc initCycleTransformFunc(RegisterCycleTransform_Init, { CVAR_CYCLE_TRANSFORM });
static RegisterShipInitFunc initFastTransformFunc(RegisterFastTransform_Init, { CVAR_FAST_TRANSFORM });
static RegisterShipInitFunc initNoMumboUntransformFunc(RegisterNoMumboUntransform_Init, { CVAR_NO_MUMBO_UNTRANSFORM });