Apply clang-format to files (#5273)

This commit is contained in:
Archez 2025-04-01 22:33:38 -04:00 committed by GitHub
parent e8389e0b2e
commit 8f126344a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
885 changed files with 40384 additions and 36263 deletions

View file

@ -1,5 +1,5 @@
#include <unistd.h>
long pathconf(const char *path, int name) {
long pathconf(const char* path, int name) {
return -1;
}

View file

@ -2,15 +2,15 @@
// Microsoft Visual C++ generated include file.
// Used by Resource.rc
//
#define IDI_ICON1 111
#define IDI_ICON1 111
// Next default values for new objects
//
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 113
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#define _APS_NEXT_RESOURCE_VALUE 113
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View file

@ -4,7 +4,6 @@
ActorDB* ActorDB::Instance;
#define DEFINE_ACTOR(name, _1, _2) extern "C" ActorInit name##_InitVars;
#define DEFINE_ACTOR_INTERNAL(name, _1, _2) extern "C" ActorInit name##_InitVars;
#define DEFINE_ACTOR_UNSET(_0)
@ -464,7 +463,8 @@ static constexpr std::pair<u16, const char*> actorDescriptionData[] = {
{ ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" },
{ ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" },
};
static std::unordered_map<u16, const char*> actorDescriptions = std::unordered_map<u16, const char*>(std::begin(actorDescriptionData), std::end(actorDescriptionData));
static std::unordered_map<u16, const char*> actorDescriptions =
std::unordered_map<u16, const char*>(std::begin(actorDescriptionData), std::end(actorDescriptionData));
ActorDB::ActorDB() {
db.reserve(ACTOR_NUMBER_MAX); // reserve size for all initial entries so we don't do it for each
@ -475,7 +475,8 @@ ActorDB::ActorDB() {
// Adds an actor at the given index. The name must be unique.
ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& desc, size_t index) {
assert(!nameTable.contains(name)); // TODO this should maybe throw instead. We'll need to think about error handling for mods that try to declare the same actor.
assert(!nameTable.contains(name)); // TODO this should maybe throw instead. We'll need to think about error handling
// for mods that try to declare the same actor.
if (db.size() < (index + 1)) {
db.resize(index + 1);
@ -513,7 +514,8 @@ ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& de
return entry;
}
// Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the return Entry or RetrieveId to get it.
// Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the return Entry or
// RetrieveId to get it.
ActorDB::Entry& ActorDB::AddEntry(const ActorDBInit& init) {
Entry& entry = AddEntry(init.name, init.desc, nextFreeId);
@ -598,7 +600,8 @@ static ActorDBInit EnPartnerInit = {
"En_Partner",
"Ivan",
ACTORCAT_ITEMACTION,
(ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED | ACTOR_FLAG_HOOKSHOT_PULLS_PLAYER | ACTOR_FLAG_CAN_PRESS_SWITCHES),
(ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED | ACTOR_FLAG_HOOKSHOT_PULLS_PLAYER |
ACTOR_FLAG_CAN_PRESS_SWITCHES),
OBJECT_GAMEPLAY_KEEP,
sizeof(EnPartner),
(ActorFunc)EnPartner_Init,

View file

@ -39,7 +39,7 @@ struct ActorDBInit {
};
class ActorDB {
public:
public:
static ActorDB* Instance;
ActorDB();
@ -65,7 +65,8 @@ public:
static void AddBuiltInCustomActors();
int GetEntryCount();
private:
private:
Entry& AddEntry(const std::string& name, const std::string& desc, size_t index);
Entry& AddEntry(const std::string& name, const std::string& desc, const ActorInit& init);

View file

@ -1,11 +1,10 @@
#include <libultraship/bridge.h>
#ifdef __cplusplus
extern "C" {
#endif
void CrashHandler_PrintSohData(char* buffer, size_t* pos);
void CrashHandler_PrintSohData(char* buffer, size_t* pos);
#ifdef __cplusplus
}

View file

@ -22,7 +22,7 @@ static std::array<const char*, ACTORCAT_MAX> sCatToStrArray{
#define DEFINE_SCENE(_1, _2, enumName, _4, _5, _6) #enumName
static std::array<const char*, SCENE_ID_MAX> sSceneIdToStrArray{
#include "tables/scene_table.h"
#include "tables/scene_table.h"
};
#undef DEFINE_SCENE
@ -46,7 +46,7 @@ static void CrashHandler_WriteActorData(char* buffer, size_t* pos) {
ActorListEntry* entry = &gPlayState->actorCtx.actorLists[i];
Actor* cur;
if(entry->length == 0) {
if (entry->length == 0) {
continue;
}
WRITE_VAR_LINE(buffer, pos, "Actor Cat: ", sCatToStrArray[i]);
@ -76,7 +76,7 @@ extern "C" void CrashHandler_PrintSohData(char* buffer, size_t* pos) {
if (gPlayState != nullptr) {
append_line(buffer, pos, "Actors:");
CrashHandler_WriteActorData(buffer, pos);
WRITE_VAR_LINE(buffer, pos, "Scene: ", sSceneIdToStrArray[gPlayState->sceneNum]);
snprintf(intCharBuffer, sizeof(intCharBuffer), "%i", gPlayState->roomCtx.curRoom.num);

View file

@ -16,10 +16,9 @@ static u16 sItemButtons[] = { BTN_B, BTN_CLEFT, BTN_CDOWN, BTN_CRIGHT, BTN_DUP,
void UseTunicBoots(Player* player, PlayState* play, Input* input) {
// Boots and tunics equip despite state
if (
player->stateFlags1 & (PLAYER_STATE1_INPUT_DISABLED | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE | PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD) ||
player->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING
) {
if (player->stateFlags1 & (PLAYER_STATE1_INPUT_DISABLED | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE |
PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD) ||
player->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING) {
return;
}
@ -40,7 +39,8 @@ void UseTunicBoots(Player* player, PlayState* play, Input* input) {
Inventory_ChangeEquipment(EQUIP_TYPE_BOOTS, bootsValue);
}
Player_SetEquipmentData(play, player);
func_808328EC(player, CUR_EQUIP_VALUE(EQUIP_TYPE_BOOTS) == EQUIP_VALUE_BOOTS_IRON ? NA_SE_PL_WALK_HEAVYBOOTS : NA_SE_PL_CHANGE_ARMS);
func_808328EC(player, CUR_EQUIP_VALUE(EQUIP_TYPE_BOOTS) == EQUIP_VALUE_BOOTS_IRON ? NA_SE_PL_WALK_HEAVYBOOTS
: NA_SE_PL_CHANGE_ARMS);
} else {
u16 tunicValue = item - ITEM_TUNIC_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == tunicValue) {
@ -87,7 +87,7 @@ void RegisterAssignableTunicsBoots() {
}
});
// don't throw items when the pressed button is a tunic or boots
// don't throw items when the pressed button is a tunic or boots
COND_VB_SHOULD(VB_THROW_OR_PUT_DOWN_HELD_ITEM, CVAR_TUNICBOOTS_VALUE != CVAR_TUNICBOOTS_DEFAULT, {
// if the vanilla condition doesn't want us to throw/put down the item, early return
if (!*should) {
@ -103,7 +103,7 @@ void RegisterAssignableTunicsBoots() {
break;
}
}
if (item >= ITEM_TUNIC_KOKIRI && item <= ITEM_BOOTS_HOVER) {
*should = false;
}

View file

@ -13,13 +13,13 @@ extern PlayState* gPlayState;
#define CVAR_DEKU_STICK_VALUE CVarGetInteger(CVAR_DEKU_STICK_NAME, CVAR_DEKU_STICK_DEFAULT)
void RegisterDekuStickCheats() {
COND_VB_SHOULD(VB_DEKU_STICK_BREAK, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
COND_VB_SHOULD(VB_DEKU_STICK_BURN_OUT, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
COND_VB_SHOULD(VB_DEKU_STICK_BREAK, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
COND_VB_SHOULD(VB_DEKU_STICK_BURN_OUT, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
COND_VB_SHOULD(VB_DEKU_STICK_BURN_DOWN, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
COND_VB_SHOULD(VB_DEKU_STICK_BE_ON_FIRE, CVAR_DEKU_STICK_VALUE == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, {
Player* player = GET_PLAYER(gPlayState);
player->unk_860 = 200; // Keeps the stick's flame lit
player->unk_85C = 1.0f; // Ensures the stick is the proper length
player->unk_860 = 200; // Keeps the stick's flame lit
player->unk_85C = 1.0f; // Ensures the stick is the proper length
*should = true;
});
}

View file

@ -30,7 +30,8 @@ void RegisterFreezeTime() {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnGameFrameUpdate>(hookId);
hookId = 0;
if (CVAR_FREEZE_TIME_VALUE) {
hookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(OnGameFrameUpdateFreezeTime);
hookId =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(OnGameFrameUpdateFreezeTime);
} else {
CVarClear(CVAR_PREV_TIME_NAME);
}

View file

@ -15,10 +15,7 @@ extern s32 Flags_GetRandomizerInf(RandomizerInf flag);
#define CVAR_INFINITE_MONEY_VALUE CVarGetInteger(CVAR_INFINITE_MONEY_NAME, CVAR_INFINITE_MONEY_DEFAULT)
void OnGameFrameUpdateInfiniteMoney() {
if (
!GameInteractor::IsSaveLoaded(true) ||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))
) {
if (!GameInteractor::IsSaveLoaded(true) || (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))) {
return;
}

View file

@ -7,7 +7,8 @@ extern "C" SaveContext gSaveContext;
#define CVAR_INFINITE_NAYRUS_LOVE_NAME CVAR_CHEAT("InfiniteNayru")
#define CVAR_INFINITE_NAYRUS_LOVE_DEFAULT 0
#define CVAR_INFINITE_NAYRUS_LOVE_VALUE CVarGetInteger(CVAR_INFINITE_NAYRUS_LOVE_NAME, CVAR_INFINITE_NAYRUS_LOVE_DEFAULT)
#define CVAR_INFINITE_NAYRUS_LOVE_VALUE \
CVarGetInteger(CVAR_INFINITE_NAYRUS_LOVE_NAME, CVAR_INFINITE_NAYRUS_LOVE_DEFAULT)
void OnGameFrameUpdateInfiniteNayrusLove() {
if (!GameInteractor::IsSaveLoaded(true)) {

View file

@ -36,23 +36,19 @@ static int statusTimer = -1;
static int eventTimer = -1;
const char* altTrapTypeCvars[] = {
CVAR_ENHANCEMENT("ExtraTraps.Ice"),
CVAR_ENHANCEMENT("ExtraTraps.Burn"),
CVAR_ENHANCEMENT("ExtraTraps.Shock"),
CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
CVAR_ENHANCEMENT("ExtraTraps.Speed"),
CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
CVAR_ENHANCEMENT("ExtraTraps.Void"),
CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
CVAR_ENHANCEMENT("ExtraTraps.Kill"),
CVAR_ENHANCEMENT("ExtraTraps.Teleport"),
CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"),
CVAR_ENHANCEMENT("ExtraTraps.Shock"), CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
CVAR_ENHANCEMENT("ExtraTraps.Speed"), CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
CVAR_ENHANCEMENT("ExtraTraps.Void"), CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
CVAR_ENHANCEMENT("ExtraTraps.Kill"), CVAR_ENHANCEMENT("ExtraTraps.Teleport"),
};
std::vector<AltTrapType> getEnabledAddTraps () {
std::vector<AltTrapType> getEnabledAddTraps() {
std::vector<AltTrapType> enabledAddTraps;
for (int i = 0; i < ADD_TRAP_MAX; i++) {
if (CVarGetInteger(altTrapTypeCvars[i], 0)) {
if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE && (i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) {
if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE &&
(i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) {
continue; // don't add void or teleport if you're holding the fishing pole, as this causes issues
}
enabledAddTraps.push_back(static_cast<AltTrapType>(i));
@ -65,7 +61,8 @@ std::vector<AltTrapType> getEnabledAddTraps () {
};
static void RollRandomTrap(uint32_t seed) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
uint32_t finalSeed =
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed);
roll = RandomElement(getEnabledAddTraps());
@ -83,7 +80,8 @@ static void RollRandomTrap(uint32_t seed) {
eventTimer = 3;
break;
case ADD_SPEED_TRAP:
Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
GameInteractor::State::RunSpeedModifier = -2;
statusTimer = 200;
Notification::Emit({ .message = "Speed Decreased!" });
@ -92,7 +90,8 @@ static void RollRandomTrap(uint32_t seed) {
eventTimer = 3;
break;
case ADD_VOID_TRAP:
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
eventTimer = 3;
break;
case ADD_AMMO_TRAP:
@ -133,7 +132,8 @@ static void OnPlayerUpdate() {
AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5;
AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5;
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break;
case ADD_TELEPORT_TRAP: {
int entrance;
@ -199,5 +199,3 @@ void RegisterExtraTraps() {
}
static RegisterShipInitFunc initFunc(RegisterExtraTraps, { CVAR_EXTRA_TRAPS_NAME });

View file

@ -6,7 +6,7 @@
#include <string>
#include <vector>
std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
{
// English
"Start Randomizer",
@ -39,28 +39,27 @@ std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
// French
"Génération en cours...",
},
{
// English
"No randomizer seed loaded.\nPlease generate one first"
#if defined(__WIIU__) || defined(__SWITCH__)
".",
#else
",\nor drop a spoiler log on the game window.",
#endif
// German
"No randomizer seed loaded.\nPlease generate one first"
#if defined(__WIIU__) || defined(__SWITCH__)
".",
#else
",\nor drop a spoiler log on the game window.",
#endif
// French
"Aucune Seed de Randomizer actuellement disponible.\nGénérez-en une dans les \"Randomizer Settings\""
#if (defined(__WIIU__) || defined(__SWITCH__))
"."
#else
"\nou glissez un spoilerlog sur la fenêtre du jeu."
#endif
{ // English
"No randomizer seed loaded.\nPlease generate one first"
#if defined(__WIIU__) || defined(__SWITCH__)
".",
#else
",\nor drop a spoiler log on the game window.",
#endif
// German
"No randomizer seed loaded.\nPlease generate one first"
#if defined(__WIIU__) || defined(__SWITCH__)
".",
#else
",\nor drop a spoiler log on the game window.",
#endif
// French
"Aucune Seed de Randomizer actuellement disponible.\nGénérez-en une dans les \"Randomizer Settings\""
#if (defined(__WIIU__) || defined(__SWITCH__))
"."
#else
"\nou glissez un spoilerlog sur la fenêtre du jeu."
#endif
},
};

View file

@ -3,10 +3,14 @@
#include "soh/cvar_prefixes.h"
#include "soh/Enhancements/enhancementTypes.h"
#define PRESET_ENTRY_S32(cvar, value) { cvar, PRESET_ENTRY_TYPE_S32, value }
#define PRESET_ENTRY_FLOAT(cvar, value) { cvar, PRESET_ENTRY_TYPE_FLOAT, value }
#define PRESET_ENTRY_STRING(cvar, value) { cvar, PRESET_ENTRY_TYPE_STRING, value }
#define PRESET_ENTRY_CPP_STRING(cvar, value) { cvar, PRESET_ENTRY_TYPE_CPP_STRING, value }
#define PRESET_ENTRY_S32(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_S32, value }
#define PRESET_ENTRY_FLOAT(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_FLOAT, value }
#define PRESET_ENTRY_STRING(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_STRING, value }
#define PRESET_ENTRY_CPP_STRING(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_CPP_STRING, value }
// TODO: Ideally everything in this file will come from one/many JSON files
@ -20,16 +24,14 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
// Skips & Speed-ups
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
// Graphics
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1),
@ -41,26 +43,20 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
// Fixes
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
// Difficulty
// NONE
@ -78,42 +74,33 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
const std::vector<PresetEntry> enhancedPresetEntries = {
// Quality of Life
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseWarp"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseWarp"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableCritWiggle"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableCritWiggle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 1),
// Skips & Speed-ups
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SlowTextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CrawlSpeed"), 2),
PRESET_ENTRY_FLOAT(CVAR_ENHANCEMENT("MweepSpeed"), 5.0f),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CrawlSpeed"), 2),
PRESET_ENTRY_FLOAT(CVAR_ENHANCEMENT("MweepSpeed"), 5.0f), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
// Graphics
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseMenuAnimatedLink"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ToTMedallionsColors"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterAmmoRendering"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1),
@ -125,49 +112,36 @@ const std::vector<PresetEntry> enhancedPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PersistentMasks"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PersistentMasks"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableFirstPersonChus"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterBombchuShopping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterFarore"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterFarore"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1),
// Fixes
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickBongoKill"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickBongoKill"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 1),
// Difficulty
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnableBombchuDrops"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnableBombchuDrops"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1),
// Minigames
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 1),
@ -502,15 +476,12 @@ const std::vector<PresetEntry> randomizerAdvancedPresetEntries = {
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SheikLAHint"), 0),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SariaHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FrogsHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MerchantText"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),

View file

@ -10,14 +10,14 @@
std::string FormatLocations(std::vector<RandomizerCheck> locs) {
std::string locString = "";
for (auto loc: locs) {
for (auto loc : locs) {
locString += std::to_string(loc) + ",";
}
return locString;
}
void applyPreset(std::vector<PresetEntry> entries) {
for(auto& [cvar, type, value] : entries) {
for (auto& [cvar, type, value] : entries) {
switch (type) {
case PRESET_ENTRY_TYPE_S32:
CVarSetInteger(cvar, std::get<int32_t>(value));
@ -41,20 +41,21 @@ void DrawPresetSelector(PresetType presetTypeId) {
const std::string presetTypeCvar = CVAR_GENERAL("SelectedPresets.") + std::to_string(presetTypeId);
const PresetTypeDefinition presetTypeDef = presetTypes.at(presetTypeId);
uint16_t selectedPresetId = CVarGetInteger(presetTypeCvar.c_str(), 0);
if(selectedPresetId >= presetTypeDef.presets.size()){
if (selectedPresetId >= presetTypeDef.presets.size()) {
selectedPresetId = 0;
}
const PresetDefinition selectedPresetDef = presetTypeDef.presets.at(selectedPresetId);
std::string comboboxTooltip = "";
for ( auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter ) {
if (iter->first != 0) comboboxTooltip += "\n\n";
for (auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter) {
if (iter->first != 0)
comboboxTooltip += "\n\n";
comboboxTooltip += std::string(iter->second.label) + " - " + std::string(iter->second.description);
}
ImGui::Text("Presets");
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##PresetsComboBox", selectedPresetDef.label)) {
for ( auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter ) {
for (auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter) {
if (ImGui::Selectable(iter->second.label, iter->first == selectedPresetId)) {
CVarSetInteger(presetTypeCvar.c_str(), iter->first);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
@ -68,7 +69,7 @@ void DrawPresetSelector(PresetType presetTypeId) {
UIWidgets::PushStyleButton(THEME_COLOR);
if (ImGui::Button(("Apply Preset##" + presetTypeCvar).c_str())) {
for(const char* block : presetTypeDef.blocksToClear) {
for (const char* block : presetTypeDef.blocksToClear) {
CVarClearBlock(block);
}
if (selectedPresetId != 0) {

View file

@ -33,10 +33,13 @@ void OnEnMThunderInitReplaceUpdateWithCustom(void* thunder) {
#define CVAR_REMOVESPINATTACKDARKNESS_NAME CVAR_ENHANCEMENT("RemoveSpinAttackDarkness")
#define CVAR_REMOVESPINATTACKDARKNESS_DEFAULT 0
#define CVAR_REMOVESPINATTACKDARKNESS_VALUE CVarGetInteger(CVAR_REMOVESPINATTACKDARKNESS_NAME, CVAR_REMOVESPINATTACKDARKNESS_DEFAULT)
#define CVAR_REMOVESPINATTACKDARKNESS_VALUE \
CVarGetInteger(CVAR_REMOVESPINATTACKDARKNESS_NAME, CVAR_REMOVESPINATTACKDARKNESS_DEFAULT)
void RegisterCustomEnMThunderUpdate() {
COND_ID_HOOK(OnActorInit, ACTOR_EN_M_THUNDER, CVAR_REMOVESPINATTACKDARKNESS_VALUE != CVAR_REMOVESPINATTACKDARKNESS_DEFAULT, OnEnMThunderInitReplaceUpdateWithCustom);
COND_ID_HOOK(OnActorInit, ACTOR_EN_M_THUNDER,
CVAR_REMOVESPINATTACKDARKNESS_VALUE != CVAR_REMOVESPINATTACKDARKNESS_DEFAULT,
OnEnMThunderInitReplaceUpdateWithCustom);
}
static RegisterShipInitFunc initFunc(RegisterCustomEnMThunderUpdate, { CVAR_REMOVESPINATTACKDARKNESS_NAME });

View file

@ -98,11 +98,13 @@ void HandleBAInventoryQuestItems() {
void HandleRBAInventoryQuestItems(uint8_t itemToPutInBottle) {
auto itemOnCRight = gSaveContext.equips.buttonItems[3];
if (itemOnCRight == ITEM_ODD_MUSHROOM) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 24) | (gSaveContext.inventory.questItems & 0x00FFFFFF);
gSaveContext.inventory.questItems =
(itemToPutInBottle << 24) | (gSaveContext.inventory.questItems & 0x00FFFFFF);
} else if (itemOnCRight == ITEM_ODD_POTION) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 16) | (gSaveContext.inventory.questItems & 0xFF00FFFF);
gSaveContext.inventory.questItems =
(itemToPutInBottle << 16) | (gSaveContext.inventory.questItems & 0xFF00FFFF);
} else if (itemOnCRight == ITEM_SAW) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 8) | (gSaveContext.inventory.questItems & 0xFFFF00FF);
} else if (itemOnCRight == ITEM_SWORD_BROKEN) {
@ -119,7 +121,7 @@ void HandleBAInventoryDungeonItems() {
void HandleRBAInventoryDungeonItems(uint8_t itemToPutInBottle) {
auto itemOnCRight = gSaveContext.equips.buttonItems[3];
gSaveContext.inventory.dungeonItems[itemOnCRight - ITEM_PRESCRIPTION] = itemToPutInBottle;
}
@ -132,7 +134,7 @@ void HandleBAInventoryDungeonKeys() {
void HandleRBAInventoryDungeonKeys(uint8_t itemToPutInBottle) {
auto itemOnCRight = gSaveContext.equips.buttonItems[3];
gSaveContext.inventory.dungeonKeys[itemOnCRight - ITEM_BULLET_BAG_40] = itemToPutInBottle;
}
@ -172,90 +174,90 @@ void HandleBASceneFlags() {
u32 offset = gSaveContext.equips.buttonItems[3] - ITEM_SONG_LULLABY;
u32 scene = offset / sizeof(SavedSceneFlags);
switch (offset % sizeof(SavedSceneFlags)) {
case 0:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 24) & 0xFF;
break;
case 1:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 16) & 0xFF;
break;
case 2:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 8) & 0xFF;
break;
case 3:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].chest & 0xFF;
break;
case 4:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 24) & 0xFF;
break;
case 5:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 16) & 0xFF;
break;
case 6:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 8) & 0xFF;
break;
case 7:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].swch & 0xFF;
break;
case 8:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 24) & 0xFF;
break;
case 9:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 16) & 0xFF;
break;
case 10:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 8) & 0xFF;
break;
case 11:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].clear & 0xFF;
break;
case 12:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 24) & 0xFF;
break;
case 13:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 16) & 0xFF;
break;
case 14:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 8) & 0xFF;
break;
case 15:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].collect & 0xFF;
break;
case 16:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 24) & 0xFF;
break;
case 17:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 16) & 0xFF;
break;
case 18:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 8) & 0xFF;
break;
case 19:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].unk & 0xFF;
break;
case 20:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 24) & 0xFF;
break;
case 21:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 16) & 0xFF;
break;
case 22:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 8) & 0xFF;
break;
case 23:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].rooms & 0xFF;
break;
case 24:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 24) & 0xFF;
break;
case 25:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 16) & 0xFF;
break;
case 26:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 8) & 0xFF;
break;
case 27:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].floors & 0xFF;
break;
case 0:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 24) & 0xFF;
break;
case 1:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 16) & 0xFF;
break;
case 2:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 8) & 0xFF;
break;
case 3:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].chest & 0xFF;
break;
case 4:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 24) & 0xFF;
break;
case 5:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 16) & 0xFF;
break;
case 6:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 8) & 0xFF;
break;
case 7:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].swch & 0xFF;
break;
case 8:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 24) & 0xFF;
break;
case 9:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 16) & 0xFF;
break;
case 10:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 8) & 0xFF;
break;
case 11:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].clear & 0xFF;
break;
case 12:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 24) & 0xFF;
break;
case 13:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 16) & 0xFF;
break;
case 14:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 8) & 0xFF;
break;
case 15:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].collect & 0xFF;
break;
case 16:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 24) & 0xFF;
break;
case 17:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 16) & 0xFF;
break;
case 18:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 8) & 0xFF;
break;
case 19:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].unk & 0xFF;
break;
case 20:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 24) & 0xFF;
break;
case 21:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 16) & 0xFF;
break;
case 22:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 8) & 0xFF;
break;
case 23:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].rooms & 0xFF;
break;
case 24:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 24) & 0xFF;
break;
case 25:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 16) & 0xFF;
break;
case 26:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 8) & 0xFF;
break;
case 27:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].floors & 0xFF;
break;
}
}
@ -264,90 +266,117 @@ void HandleRBASceneFlags(uint8_t itemToPutInBottle) {
u32 offset = gSaveContext.equips.buttonItems[3] - ITEM_SONG_LULLABY;
u32 scene = offset / sizeof(SavedSceneFlags);
switch (offset % sizeof(SavedSceneFlags)) {
case 0:
gSaveContext.sceneFlags[scene].chest = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].chest & 0x00FFFFFF);
break;
case 1:
gSaveContext.sceneFlags[scene].chest = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].chest & 0xFF00FFFF);
break;
case 2:
gSaveContext.sceneFlags[scene].chest = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].chest & 0xFFFF00FF);
break;
case 3:
gSaveContext.sceneFlags[scene].chest = itemToPutInBottle | (gSaveContext.sceneFlags[scene].chest & 0xFFFFFF00);
break;
case 4:
gSaveContext.sceneFlags[scene].swch = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].swch & 0x00FFFFFF);
break;
case 5:
gSaveContext.sceneFlags[scene].swch = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].swch & 0xFF00FFFF);
break;
case 6:
gSaveContext.sceneFlags[scene].swch = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].swch & 0xFFFF00FF);
break;
case 7:
gSaveContext.sceneFlags[scene].swch = itemToPutInBottle | (gSaveContext.sceneFlags[scene].swch & 0xFFFFFF00);
break;
case 8:
gSaveContext.sceneFlags[scene].clear = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].clear & 0x00FFFFFF);
break;
case 9:
gSaveContext.sceneFlags[scene].clear = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].clear & 0xFF00FFFF);
break;
case 10:
gSaveContext.sceneFlags[scene].clear = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].clear & 0xFFFF00FF);
break;
case 11:
gSaveContext.sceneFlags[scene].clear = itemToPutInBottle | (gSaveContext.sceneFlags[scene].clear & 0xFFFFFF00);
break;
case 12:
gSaveContext.sceneFlags[scene].collect = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].collect & 0x00FFFFFF);
break;
case 13:
gSaveContext.sceneFlags[scene].collect = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].collect & 0xFF00FFFF);
break;
case 14:
gSaveContext.sceneFlags[scene].collect = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].collect & 0xFFFF00FF);
break;
case 15:
gSaveContext.sceneFlags[scene].collect = itemToPutInBottle | (gSaveContext.sceneFlags[scene].collect & 0xFFFFFF00);
break;
case 16:
gSaveContext.sceneFlags[scene].unk = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].unk & 0x00FFFFFF);
break;
case 17:
gSaveContext.sceneFlags[scene].unk = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].unk & 0xFF00FFFF);
break;
case 18:
gSaveContext.sceneFlags[scene].unk = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].unk & 0xFFFF00FF);
break;
case 19:
gSaveContext.sceneFlags[scene].unk = itemToPutInBottle | (gSaveContext.sceneFlags[scene].unk & 0xFFFFFF00);
break;
case 20:
gSaveContext.sceneFlags[scene].rooms = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].rooms & 0x00FFFFFF);
break;
case 21:
gSaveContext.sceneFlags[scene].rooms = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].rooms & 0xFF00FFFF);
break;
case 22:
gSaveContext.sceneFlags[scene].rooms = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].rooms & 0xFFFF00FF);
break;
case 23:
gSaveContext.sceneFlags[scene].rooms = itemToPutInBottle | (gSaveContext.sceneFlags[scene].rooms & 0xFFFFFF00);
break;
case 24:
gSaveContext.sceneFlags[scene].floors = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].floors & 0x00FFFFFF);
break;
case 25:
gSaveContext.sceneFlags[scene].floors = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].floors & 0xFF00FFFF);
break;
case 26:
gSaveContext.sceneFlags[scene].floors = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].floors & 0xFFFF00FF);
break;
case 27:
gSaveContext.sceneFlags[scene].floors = itemToPutInBottle | (gSaveContext.sceneFlags[scene].floors & 0xFFFFFF00);
break;
case 0:
gSaveContext.sceneFlags[scene].chest =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].chest & 0x00FFFFFF);
break;
case 1:
gSaveContext.sceneFlags[scene].chest =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].chest & 0xFF00FFFF);
break;
case 2:
gSaveContext.sceneFlags[scene].chest =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].chest & 0xFFFF00FF);
break;
case 3:
gSaveContext.sceneFlags[scene].chest =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].chest & 0xFFFFFF00);
break;
case 4:
gSaveContext.sceneFlags[scene].swch =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].swch & 0x00FFFFFF);
break;
case 5:
gSaveContext.sceneFlags[scene].swch =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].swch & 0xFF00FFFF);
break;
case 6:
gSaveContext.sceneFlags[scene].swch =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].swch & 0xFFFF00FF);
break;
case 7:
gSaveContext.sceneFlags[scene].swch =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].swch & 0xFFFFFF00);
break;
case 8:
gSaveContext.sceneFlags[scene].clear =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].clear & 0x00FFFFFF);
break;
case 9:
gSaveContext.sceneFlags[scene].clear =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].clear & 0xFF00FFFF);
break;
case 10:
gSaveContext.sceneFlags[scene].clear =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].clear & 0xFFFF00FF);
break;
case 11:
gSaveContext.sceneFlags[scene].clear =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].clear & 0xFFFFFF00);
break;
case 12:
gSaveContext.sceneFlags[scene].collect =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].collect & 0x00FFFFFF);
break;
case 13:
gSaveContext.sceneFlags[scene].collect =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].collect & 0xFF00FFFF);
break;
case 14:
gSaveContext.sceneFlags[scene].collect =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].collect & 0xFFFF00FF);
break;
case 15:
gSaveContext.sceneFlags[scene].collect =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].collect & 0xFFFFFF00);
break;
case 16:
gSaveContext.sceneFlags[scene].unk =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].unk & 0x00FFFFFF);
break;
case 17:
gSaveContext.sceneFlags[scene].unk =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].unk & 0xFF00FFFF);
break;
case 18:
gSaveContext.sceneFlags[scene].unk =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].unk & 0xFFFF00FF);
break;
case 19:
gSaveContext.sceneFlags[scene].unk = itemToPutInBottle | (gSaveContext.sceneFlags[scene].unk & 0xFFFFFF00);
break;
case 20:
gSaveContext.sceneFlags[scene].rooms =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].rooms & 0x00FFFFFF);
break;
case 21:
gSaveContext.sceneFlags[scene].rooms =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].rooms & 0xFF00FFFF);
break;
case 22:
gSaveContext.sceneFlags[scene].rooms =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].rooms & 0xFFFF00FF);
break;
case 23:
gSaveContext.sceneFlags[scene].rooms =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].rooms & 0xFFFFFF00);
break;
case 24:
gSaveContext.sceneFlags[scene].floors =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].floors & 0x00FFFFFF);
break;
case 25:
gSaveContext.sceneFlags[scene].floors =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].floors & 0xFF00FFFF);
break;
case 26:
gSaveContext.sceneFlags[scene].floors =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].floors & 0xFFFF00FF);
break;
case 27:
gSaveContext.sceneFlags[scene].floors =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].floors & 0xFFFFFF00);
break;
}
}

View file

@ -31,8 +31,9 @@ void RegisterPauseBufferInputs() {
COND_VB_SHOULD(VB_KALEIDO_UNPAUSE_CLOSE, CVAR_BUFFER_VALUE || CVAR_INCLUDE_VALUE, {
Input* input = &gPlayState->state.input[0];
// STEP #3: If the user opts to include held inputs in the buffer window, store the currnently held inputs, minus
// the held inputs when the pause menu was opened. This only applies to the first frame of the buffer window
// STEP #3: If the user opts to include held inputs in the buffer window, store the currnently held inputs,
// minus the held inputs when the pause menu was opened. This only applies to the first frame of the buffer
// window
if (CVAR_INCLUDE_VALUE && inputBufferTimer == 0) {
pauseInputs |= input->cur.button & ~prePauseInputs;
prePauseInputs = 0;
@ -56,16 +57,15 @@ void RegisterPauseBufferInputs() {
Input* input = &gPlayState->state.input[0];
PauseContext* pauseCtx = &gPlayState->pauseCtx;
// STEP #1: If the user opts to include held inputs in the buffer window, store the held inputs at the beginning
// STEP #1: If the user opts to include held inputs in the buffer window, store the held inputs at the beginning
// of the pause process, minus the START input
if (pauseCtx->state == PAUSE_STATE_OPENING_1 && CVAR_INCLUDE_VALUE) {
prePauseInputs = input->cur.button & ~BTN_START;
}
// STEP #2: The unpause process has begun, so let's reset the input buffer timer
if (pauseCtx->state == PAUSE_STATE_UNPAUSE_SETUP || (
pauseCtx->state == PAUSE_STATE_SAVEPROMPT && (pauseCtx->unk_1EC == 2 || pauseCtx->unk_1EC == 5)
)) {
if (pauseCtx->state == PAUSE_STATE_UNPAUSE_SETUP ||
(pauseCtx->state == PAUSE_STATE_SAVEPROMPT && (pauseCtx->unk_1EC == 2 || pauseCtx->unk_1EC == 5))) {
inputBufferTimer = 0;
}

View file

@ -147,18 +147,18 @@ void TimeDisplayUpdateDisplayOptions() {
}
}
//if (pushBack) {
// activeTimers.push_back(timeDisplayList[timeID]);
//} else {
// uint32_t index = 0;
// for (auto& check : activeTimers) {
// if (check.timeID == timeID) {
// activeTimers.erase(activeTimers.begin() + index);
// return;
// }
// index++;
// }
//}
// if (pushBack) {
// activeTimers.push_back(timeDisplayList[timeID]);
// } else {
// uint32_t index = 0;
// for (auto& check : activeTimers) {
// if (check.timeID == timeID) {
// activeTimers.erase(activeTimers.begin() + index);
// return;
// }
// index++;
// }
// }
}
void TimeDisplayWindow::Draw() {
@ -174,9 +174,9 @@ void TimeDisplayWindow::Draw() {
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
ImGui::Begin("TimerDisplay", nullptr,
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar);
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar);
ImGui::SetWindowFontScale(fontScale);
if (activeTimers.size() == 0) {
ImGui::Text("No Enabled Timers...");
@ -247,13 +247,17 @@ static void TimeDisplayInitTimers() {
}
void TimeDisplayWindow::InitElement() {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("GAMEPLAY_TIMER", gClockIconTex, ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("DAY_TIME_TIMER", gSunIconTex, ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NIGHT_TIME_TIMER", gMoonIconTex, ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("GAMEPLAY_TIMER", gClockIconTex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("DAY_TIME_TIMER", gSunIconTex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NIGHT_TIME_TIMER", gMoonIconTex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NAVI_TIMER", gNaviIconTex, ImVec4(1, 1, 1, 1));
for (auto& load : digitList) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(load.first.c_str(), load.second, ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(load.first.c_str(), load.second,
ImVec4(1, 1, 1, 1));
}
TimeDisplayInitSettings();

View file

@ -5,9 +5,9 @@ class TimeDisplayWindow : public Ship::GuiWindow {
using GuiWindow::GuiWindow;
void InitElement() override;
void DrawElement() override {};
void DrawElement() override{};
void Draw() override;
void UpdateElement() override {};
void UpdateElement() override{};
};
void TimeDisplayUpdateDisplayOptions();

View file

@ -4,12 +4,12 @@
#include "spdlog/spdlog.h"
extern "C" {
#include "z64save.h"
#include "macros.h"
#include "variables.h"
#include "functions.h"
extern PlayState* gPlayState;
extern SaveContext gSaveContext;
#include "z64save.h"
#include "macros.h"
#include "variables.h"
#include "functions.h"
extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
/**
@ -20,29 +20,30 @@ void FasterHeavyBlockLift_Register() {
REGISTER_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, {
Actor* actor = va_arg(args, Actor*);
if (
actor->id == ACTOR_BG_HEAVY_BLOCK &&
(CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO))
) {
if (actor->id == ACTOR_BG_HEAVY_BLOCK &&
(CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO))) {
*should = false;
}
});
REGISTER_VB_SHOULD(VB_FREEZE_LINK_FOR_BLOCK_THROW, {
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
*should = false;
}
});
REGISTER_VB_SHOULD(VB_PLAY_THROW_ANIMATION, {
Player *player = GET_PLAYER(gPlayState);
Player* player = GET_PLAYER(gPlayState);
Actor* interactRangeActor = player->interactRangeActor;
s32 interactActorId = interactRangeActor->id;
LinkAnimationHeader* anim = va_arg(args, LinkAnimationHeader*);
// Same actor is used for small and large silver rocks, use actor params to identify large ones
bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1;
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) && (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) {
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) &&
(isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) {
*should = false;
LinkAnimation_PlayOnceSetSpeed(gPlayState, &player->skelAnime, anim, 5.0f);
}

View file

@ -4,17 +4,18 @@
#include "spdlog/spdlog.h"
extern "C" {
#include "z64save.h"
#include "macros.h"
#include "variables.h"
#include "functions.h"
extern PlayState* gPlayState;
extern SaveContext gSaveContext;
#include "z64save.h"
#include "macros.h"
#include "variables.h"
#include "functions.h"
extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
void FasterRupeeAccumulator_Register() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnInterfaceUpdate>([]() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 0)) return;
if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 0))
return;
if (gSaveContext.rupeeAccumulator == 0) {
return;
@ -28,10 +29,10 @@ void FasterRupeeAccumulator_Register() {
}
if (gSaveContext.rupeeAccumulator >= 10 && gSaveContext.rupees + 10 < CUR_CAPACITY(UPG_WALLET)) {
gSaveContext.rupeeAccumulator-= 10;
gSaveContext.rupeeAccumulator -= 10;
gSaveContext.rupees += 10;
}
// Losing rupees
// Losing rupees
} else if (gSaveContext.rupeeAccumulator < 0) {
// No rupees to lose
if (gSaveContext.rupees == 0) {

View file

@ -24,7 +24,7 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
if (IS_BOSS_RUSH) {
return;
}
bool overrideBlueWarpDestinations =
IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF);
@ -37,16 +37,19 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) {
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP;
isBlueWarpCutscene = true;
// Dodongo's Cavern Blue warp
} else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT && gSaveContext.cutsceneIndex == 0xFFF1) {
// Dodongo's Cavern Blue warp
} else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT &&
gSaveContext.cutsceneIndex == 0xFFF1) {
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP;
isBlueWarpCutscene = true;
// Jabu Jabu's Blue warp
} else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP && gSaveContext.cutsceneIndex == 0xFFF0) {
// Jabu Jabu's Blue warp
} else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP &&
gSaveContext.cutsceneIndex == 0xFFF0) {
gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP;
isBlueWarpCutscene = true;
// Forest Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) {
// Forest Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) {
// Normally set in the blue warp cutscene
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT);
@ -57,27 +60,31 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
}
isBlueWarpCutscene = true;
// Fire Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE && gSaveContext.cutsceneIndex == 0xFFF3) {
// Fire Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE &&
gSaveContext.cutsceneIndex == 0xFFF3) {
// Normally set in the blue warp cutscene
Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED);
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true;
// Water Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) {
// Water Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) {
// Normally set in the blue warp cutscene
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800;
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER);
gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true;
// Spirit Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) {
// Spirit Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) {
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true;
// Shadow Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) {
// Shadow Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) {
gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true;
}
@ -92,7 +99,8 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
gSaveContext.cutsceneIndex = 0;
}
// This is outside the above condition because we want to handle both first and following visits to the blue warp
// This is outside the above condition because we want to handle both first and following visits to the blue
// warp
if (sEnteredBlueWarp && overrideBlueWarpDestinations) {
Entrance_OverrideBlueWarp();
}
@ -111,7 +119,7 @@ void SkipBlueWarp_ShouldPlayBlueWarpCS(GIVanillaBehavior _, bool* should, va_lis
/**
* While we could rely on the Item_Give that's normally called, it's not very clear to the player that they
* received the item when skipping the blue warp cutscene, so we'll prevent that and queue it up to be given
* received the item when skipping the blue warp cutscene, so we'll prevent that and queue it up to be given
* to the player instead.
*/
void SkipBlueWarp_ShouldGiveItem(GIVanillaBehavior _, bool* should, va_list originalArgs) {
@ -142,31 +150,35 @@ void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) {
void SkipBlueWarp_OnActorUpdate(void* actorPtr) {
EnKo* enKo = static_cast<EnKo*>(actorPtr);
if (
(enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 &&
enKo->actionFunc == func_80A995CC &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)
) {
if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && enKo->actionFunc == func_80A995CC &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
enKo->actionFunc = EnKo_MoveWhenReady;
}
}
/**
* This will ensure that the Deku Tree Sprout considers the Forest Temple finished when you skip the blue warp cutscene.
* Typically this checks for if you have the medallion, and when skipping the cutscene at this point you don't have it yet.
* Typically this checks for if you have the medallion, and when skipping the cutscene at this point you don't have it
* yet.
*/
void SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished(GIVanillaBehavior _, bool* should, va_list originalArgs) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP && gSaveContext.cutsceneIndex == 0xFFF1) {
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP &&
gSaveContext.cutsceneIndex == 0xFFF1) {
*should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
}
}
}
void SkipBlueWarp_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO, SkipBlueWarp_OnActorUpdate);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_GIVE_ITEM_FROM_BLUE_WARP, SkipBlueWarp_ShouldGiveItem);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO,
SkipBlueWarp_OnActorUpdate);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_GIVE_ITEM_FROM_BLUE_WARP,
SkipBlueWarp_ShouldGiveItem);
}

View file

@ -3,18 +3,19 @@
#include "soh/OTRGlobals.h"
extern "C" {
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
}
/**
* This will skip the Deku Tree intro, and simply open the mouth as you approach it.
*/
*/
void SkipDekuTreeIntro_Register() {
REGISTER_VB_SHOULD(VB_PLAY_DEKU_TREE_INTRO_CS, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
BgTreemouth* treeMouth = va_arg(args, BgTreemouth*);
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
BgTreemouth_SetupAction(treeMouth, func_808BC6F8);
*should = false;
}

View file

@ -3,19 +3,21 @@
#include "soh/OTRGlobals.h"
extern "C" {
#include "z64save.h"
#include "functions.h"
extern PlayState* gPlayState;
extern SaveContext gSaveContext;
#include "z64save.h"
#include "functions.h"
extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
void SkipLostWoodsBridge_Register() {
/**
* This skips the cutscene where you speak to Saria on the bridge in Lost Woods, where she gives you the Fairy Ocarina.
* This skips the cutscene where you speak to Saria on the bridge in Lost Woods, where she gives you the Fairy
* Ocarina.
*/
REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_BRIDGE_EAST_EXIT) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_BRIDGE_EAST_EXIT) &&
!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE);
if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true)) {
Item_Give(gPlayState, ITEM_OCARINA_FAIRY);
@ -26,8 +28,9 @@ void SkipLostWoodsBridge_Register() {
});
/**
* While we could rely on the Item_Give that's normally called (and that we have above), it's not very clear to the player
* that they received the item when skipping the cutscene, so we'll prevent it, and queue it up to be given instead.
* While we could rely on the Item_Give that's normally called (and that we have above), it's not very clear to the
* player that they received the item when skipping the cutscene, so we'll prevent it, and queue it up to be given
* instead.
*/
REGISTER_VB_SHOULD(VB_GIVE_ITEM_FAIRY_OCARINA, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {

View file

@ -3,7 +3,7 @@
#include "soh/OTRGlobals.h"
extern "C" {
#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
}
/**
@ -21,7 +21,8 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
Audio_PlayFanfare(NA_BGM_APPEAR);
enZl4->csState = 8; // ZL4_CS_PLAN
} else {
Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f, EnZl4_GiveItemTextId, func_80B5B9B0);
Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f,
EnZl4_GiveItemTextId, func_80B5B9B0);
func_80B5BB78(enZl4, play);
if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) {
@ -34,12 +35,14 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
void SkipToGivingZeldasLetter_OnActorInit(void* actorPtr) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
EnZl4* enZl4 = static_cast<EnZl4*>(actorPtr);
if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return;
if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0)
return;
enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter;
}
}
void SkipToGivingZeldasLetter_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_ZL4, SkipToGivingZeldasLetter_OnActorInit);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_ZL4,
SkipToGivingZeldasLetter_OnActorInit);
}

View file

@ -3,9 +3,9 @@
#include "soh/OTRGlobals.h"
extern "C" {
#include "z64save.h"
#include "functions.h"
extern SaveContext gSaveContext;
#include "z64save.h"
#include "functions.h"
extern SaveContext gSaveContext;
}
void SkipZeldaFleeingCastle_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
@ -46,13 +46,11 @@ void SkipZeldaFleeingCastle_OnActorUpdate(void* actorPtr) {
void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) {
Actor* actor = static_cast<Actor*>(actorPtr);
if (
actor->params == 3 &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)
) {
if (actor->params == 3 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
framesSinceSpawn = 0;
itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr<GameInteractor::OnActorUpdate>((uintptr_t)actorPtr, SkipZeldaFleeingCastle_OnActorUpdate);
sceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([] (int16_t sceneNum) {
itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr<GameInteractor::OnActorUpdate>(
(uintptr_t)actorPtr, SkipZeldaFleeingCastle_OnActorUpdate);
sceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
GameInteractor::Instance->UnregisterGameHookForPtr<GameInteractor::OnActorUpdate>(itemOcarinaUpdateHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(sceneInitHook);
itemOcarinaUpdateHook = 0;
@ -62,6 +60,8 @@ void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) {
}
void SkipZeldaFleeingCastle_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_ITEM_OCARINA, SkipZeldaFleeingCastle_OnActorInit);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_TRANSITION_CS, SkipZeldaFleeingCastle_ShouldPlayTransitionCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_ITEM_OCARINA,
SkipZeldaFleeingCastle_OnActorInit);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_TRANSITION_CS, SkipZeldaFleeingCastle_ShouldPlayTransitionCS);
}

View file

@ -10,18 +10,19 @@ extern "C" {
* Adjusts the behavior of the elevator to start near the bottom if you are entering the room from the bottom
*/
void MoveJabuJabuElevator_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_BG_BDAN_OBJECTS, [](void* actorRef) {
Player* player = GET_PLAYER(gPlayState);
BgBdanObjects* bgBdanObjects = static_cast<BgBdanObjects*>(actorRef);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(
ACTOR_BG_BDAN_OBJECTS, [](void* actorRef) {
Player* player = GET_PLAYER(gPlayState);
BgBdanObjects* bgBdanObjects = static_cast<BgBdanObjects*>(actorRef);
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
return;
}
if (bgBdanObjects->dyna.actor.params == 1) {
if (player->actor.world.pos.y < -500.0f) {
bgBdanObjects->timer = 220;
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
return;
}
}
});
if (bgBdanObjects->dyna.actor.params == 1) {
if (player->actor.world.pos.y < -500.0f) {
bgBdanObjects->timer = 220;
}
}
});
}

View file

@ -3,12 +3,12 @@
#include "soh/OTRGlobals.h"
extern "C" {
#include "z64save.h"
#include "macros.h"
#include "variables.h"
#include "functions.h"
extern PlayState* gPlayState;
extern SaveContext gSaveContext;
#include "z64save.h"
#include "macros.h"
#include "variables.h"
#include "functions.h"
extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
/**
@ -17,13 +17,10 @@ extern "C" {
*/
void MoveMidoInKokiriForest_Register() {
REGISTER_VB_SHOULD(VB_MOVE_MIDO_IN_KOKIRI_FOREST, {
if (
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) &&
gSaveContext.cutsceneIndex == 0
) {
(CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && gSaveContext.cutsceneIndex == 0) {
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
*should = true;
}

View file

@ -29,7 +29,7 @@ void SkipChildRutoInteractions_Register() {
if (*should) {
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildTurnAroundAnim, 1.0f, 0,
Animation_GetLastFrame((void*)&gRutoChildTurnAroundAnim), ANIMMODE_ONCE, -8.0f);
Animation_GetLastFrame((void*)&gRutoChildTurnAroundAnim), ANIMMODE_ONCE, -8.0f);
enRu1->action = 10;
}
@ -48,7 +48,8 @@ void SkipChildRutoInteractions_Register() {
}
});
// Prevents Ruto from running to the Sapphire when she wants to be tossed to it, instead she just stands up and waits for link to get closer
// Prevents Ruto from running to the Sapphire when she wants to be tossed to it, instead she just stands up and
// waits for link to get closer
REGISTER_VB_SHOULD(VB_RUTO_RUN_TO_SAPPHIRE, {
EnRu1* enRu1 = va_arg(args, EnRu1*);
DynaPolyActor* dynaPolyActor = va_arg(args, DynaPolyActor*);
@ -63,12 +64,13 @@ void SkipChildRutoInteractions_Register() {
Flags_SetSwitch(gPlayState, 0x02);
Flags_SetSwitch(gPlayState, 0x1F);
enRu1->action = 42;
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildWait2Anim, 1.0f, 0,
Animation_GetLastFrame((void*)&gRutoChildWait2Anim), ANIMMODE_LOOP, -8.0f);
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildWait2Anim, 1.0f, 0,
Animation_GetLastFrame((void*)&gRutoChildWait2Anim), ANIMMODE_LOOP, -8.0f);
// If we aren't skipping one point cutscenes and BgBdan objects has set the camera setting
// to CAM_SET_NORMAL1 (2), don't reset the camera setting to 1. This prevents the One Point
// Cutscene of Ruto getting lifted up from getting queued up twice.
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) || enRu1->unk_28C->cameraSetting != 2) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) ||
enRu1->unk_28C->cameraSetting != 2) {
enRu1->unk_28C->cameraSetting = 1;
}
Actor* sapphire = func_80AEB124(gPlayState);
@ -80,7 +82,8 @@ void SkipChildRutoInteractions_Register() {
}
});
// This overrides the behavior that causes Ruto to get upset at you before sitting back down again when INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME is set
// This overrides the behavior that causes Ruto to get upset at you before sitting back down again when
// INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME is set
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_RU1, [](void* actorRef) {
EnRu1* enRu1 = static_cast<EnRu1*>(actorRef);
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
@ -92,7 +95,7 @@ void SkipChildRutoInteractions_Register() {
enRu1->drawConfig = 1;
enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY;
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f,
Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f);
Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f);
}
});
}

View file

@ -2,17 +2,17 @@
void TimeSavers_Register() {
// SkipCutscene
// Story
SkipBlueWarp_Register();
SkipDekuTreeIntro_Register();
SkipLostWoodsBridge_Register();
SkipToGivingZeldasLetter_Register();
SkipZeldaFleeingCastle_Register();
SkipIntro_Register();
// Story
SkipBlueWarp_Register();
SkipDekuTreeIntro_Register();
SkipLostWoodsBridge_Register();
SkipToGivingZeldasLetter_Register();
SkipZeldaFleeingCastle_Register();
SkipIntro_Register();
// SkipMiscInteractions
MoveJabuJabuElevator_Register();
MoveMidoInKokiriForest_Register();
SkipChildRutoInteractions_Register();
MoveJabuJabuElevator_Register();
MoveMidoInKokiriForest_Register();
SkipChildRutoInteractions_Register();
FasterHeavyBlockLift_Register();
FasterRupeeAccumulator_Register();
}

View file

@ -4,17 +4,17 @@
void TimeSavers_Register();
// SkipCutscene
// Story
void SkipBlueWarp_Register();
void SkipDekuTreeIntro_Register();
void SkipLostWoodsBridge_Register();
void SkipToGivingZeldasLetter_Register();
void SkipZeldaFleeingCastle_Register();
void SkipIntro_Register();
// Story
void SkipBlueWarp_Register();
void SkipDekuTreeIntro_Register();
void SkipLostWoodsBridge_Register();
void SkipToGivingZeldasLetter_Register();
void SkipZeldaFleeingCastle_Register();
void SkipIntro_Register();
// SkipMiscInteractions
void MoveJabuJabuElevator_Register();
void MoveMidoInKokiriForest_Register();
void SkipChildRutoInteractions_Register();
void MoveJabuJabuElevator_Register();
void MoveMidoInKokiriForest_Register();
void SkipChildRutoInteractions_Register();
void FasterHeavyBlockLift_Register();
void FasterRupeeAccumulator_Register();

View file

@ -11,7 +11,11 @@
#include <filesystem>
#define SEQUENCE_MAP_ENTRY(sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement) \
{ sequenceId, { sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement } }
{ \
sequenceId, { \
sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement \
} \
}
AudioCollection::AudioCollection() {
// clang-format off
@ -355,10 +359,13 @@ void AudioCollection::AddToCollection(char* otrPath, uint16_t seqNum) {
if (typeString == "fanfare") {
type = SEQ_FANFARE;
}
SequenceInfo info = {seqNum,
sequenceName,
StringHelper::Replace(StringHelper::Replace(StringHelper::Replace(sequenceName, " ", "_"), "~", "-"),".", ""),
type, false, true};
SequenceInfo info = { seqNum,
sequenceName,
StringHelper::Replace(
StringHelper::Replace(StringHelper::Replace(sequenceName, " ", "_"), "~", "-"), ".", ""),
type,
false,
true };
sequenceMap.emplace(seqNum, info);
}
@ -367,7 +374,8 @@ uint16_t AudioCollection::GetReplacementSequence(uint16_t seqId) {
// for Hyrule Field instead. Otherwise, leave it alone, so that without any sfx editor modifications we will
// play the normal track as usual.
if (seqId == NA_BGM_FIELD_MORNING) {
if (CVarGetInteger(CVAR_AUDIO("ReplacedSequences.NA_BGM_FIELD_LOGIC.value"), NA_BGM_FIELD_LOGIC) != NA_BGM_FIELD_LOGIC) {
if (CVarGetInteger(CVAR_AUDIO("ReplacedSequences.NA_BGM_FIELD_LOGIC.value"), NA_BGM_FIELD_LOGIC) !=
NA_BGM_FIELD_LOGIC) {
seqId = NA_BGM_FIELD_LOGIC;
}
}
@ -402,10 +410,12 @@ void AudioCollection::AddToShufflePool(SequenceInfo* seqInfo) {
}
void AudioCollection::InitializeShufflePool() {
if (shufflePoolInitialized) return;
if (shufflePoolInitialized)
return;
for (auto& [seqId, seqInfo] : sequenceMap) {
if (!seqInfo.canBeUsedAsReplacement) continue;
if (!seqInfo.canBeUsedAsReplacement)
continue;
const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo.sfxKey;
if (CVarGetInteger(cvarKey.c_str(), 0)) {
excludedSequences.insert(&seqInfo);
@ -417,7 +427,7 @@ void AudioCollection::InitializeShufflePool() {
shufflePoolInitialized = true;
};
extern "C" void AudioCollection_AddToCollection(char *otrPath, uint16_t seqNum) {
extern "C" void AudioCollection_AddToCollection(char* otrPath, uint16_t seqNum) {
AudioCollection::Instance->AddToCollection(otrPath, seqNum);
}

View file

@ -6,16 +6,16 @@
#include <cstdint>
enum SeqType {
SEQ_NOSHUFFLE = 0,
SEQ_BGM_WORLD = 1 << 0,
SEQ_BGM_EVENT = 1 << 1,
SEQ_NOSHUFFLE = 0,
SEQ_BGM_WORLD = 1 << 0,
SEQ_BGM_EVENT = 1 << 1,
SEQ_BGM_BATTLE = 1 << 2,
SEQ_OCARINA = 1 << 3,
SEQ_FANFARE = 1 << 4,
SEQ_BGM_ERROR = 1 << 5,
SEQ_SFX = 1 << 6,
SEQ_OCARINA = 1 << 3,
SEQ_FANFARE = 1 << 4,
SEQ_BGM_ERROR = 1 << 5,
SEQ_SFX = 1 << 6,
SEQ_INSTRUMENT = 1 << 7,
SEQ_VOICE = 1 << 8,
SEQ_VOICE = 1 << 8,
SEQ_BGM_CUSTOM = SEQ_BGM_WORLD | SEQ_BGM_EVENT | SEQ_BGM_BATTLE,
};
@ -31,45 +31,45 @@ struct SequenceInfo {
};
class AudioCollection {
private:
// All Loaded Audio
std::map<uint16_t, SequenceInfo> sequenceMap;
// Sequences/SFX to include in/exclude from shuffle pool
struct compareSequenceLabel {
bool operator() (SequenceInfo* a, SequenceInfo* b) const {
return a->label < b->label;
};
};
std::set<SequenceInfo*, compareSequenceLabel> includedSequences;
std::set<SequenceInfo*, compareSequenceLabel> excludedSequences;
bool shufflePoolInitialized = false;
private:
// All Loaded Audio
std::map<uint16_t, SequenceInfo> sequenceMap;
public:
static AudioCollection* Instance;
AudioCollection();
std::map<uint16_t, SequenceInfo> GetAllSequences() const {
return sequenceMap;
}
std::set<SequenceInfo*, compareSequenceLabel> GetIncludedSequences() const {
return includedSequences;
// Sequences/SFX to include in/exclude from shuffle pool
struct compareSequenceLabel {
bool operator()(SequenceInfo* a, SequenceInfo* b) const {
return a->label < b->label;
};
std::set<SequenceInfo*, compareSequenceLabel> GetExcludedSequences() const {
return excludedSequences;
};
void AddToShufflePool(SequenceInfo*);
void RemoveFromShufflePool(SequenceInfo*);
void AddToCollection(char* otrPath, uint16_t seqNum);
uint16_t GetReplacementSequence(uint16_t seqId);
void InitializeShufflePool();
const char* GetSequenceName(uint16_t seqId);
bool HasSequenceNum(uint16_t seqId);
size_t SequenceMapSize();
std::string GetCvarKey(std::string sfxKey);
std::string GetCvarLockKey(std::string sfxKey);
};
std::set<SequenceInfo*, compareSequenceLabel> includedSequences;
std::set<SequenceInfo*, compareSequenceLabel> excludedSequences;
bool shufflePoolInitialized = false;
public:
static AudioCollection* Instance;
AudioCollection();
std::map<uint16_t, SequenceInfo> GetAllSequences() const {
return sequenceMap;
}
std::set<SequenceInfo*, compareSequenceLabel> GetIncludedSequences() const {
return includedSequences;
};
std::set<SequenceInfo*, compareSequenceLabel> GetExcludedSequences() const {
return excludedSequences;
};
void AddToShufflePool(SequenceInfo*);
void RemoveFromShufflePool(SequenceInfo*);
void AddToCollection(char* otrPath, uint16_t seqNum);
uint16_t GetReplacementSequence(uint16_t seqId);
void InitializeShufflePool();
const char* GetSequenceName(uint16_t seqId);
bool HasSequenceNum(uint16_t seqId);
size_t SequenceMapSize();
std::string GetCvarKey(std::string sfxKey);
std::string GetCvarLockKey(std::string sfxKey);
};
#else
void AudioCollection_AddToCollection(char *otrPath, uint16_t seqNum);
void AudioCollection_AddToCollection(char* otrPath, uint16_t seqNum);
const char* AudioCollection_GetSequenceName(uint16_t seqId);
bool AudioCollection_HasSequenceNum(uint16_t seqId);
size_t AudioCollection_SequenceMapSize();

View file

@ -17,8 +17,8 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
extern "C" {
#include "z64save.h"
extern SaveContext gSaveContext;
#include "z64save.h"
extern SaveContext gSaveContext;
}
Vec3f pos = { 0.0f, 0.0f, 0.0f };
@ -58,7 +58,7 @@ size_t AuthenticCountBySequenceType(SeqType type) {
case SEQ_VOICE:
return SEQ_COUNT_VOICE;
default:
return 0;
return 0;
}
}
@ -101,7 +101,8 @@ void RandomizeGroup(SeqType type) {
}
// if we didn't find any, return early without shuffling to prevent an infinite loop
if (!values.size()) return;
if (!values.size())
return;
}
Shuffle(values);
for (const auto& [seqId, seqData] : AudioCollection::Instance->GetAllSequences()) {
@ -110,7 +111,9 @@ void RandomizeGroup(SeqType type) {
// don't randomize locked entries
if ((seqData.category & type) && CVarGetInteger(cvarLockKey.c_str(), 0) == 0) {
// Only save authentic sequence CVars
if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) && seqData.sequenceId >= MAX_AUTHENTIC_SEQID) || seqData.canBeReplaced == false) {
if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) &&
seqData.sequenceId >= MAX_AUTHENTIC_SEQID) ||
seqData.canBeReplaced == false) {
continue;
}
const int randomValue = values.back();
@ -172,20 +175,20 @@ void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequence
if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) == sequenceId) {
if (UIWidgets::Button(stopButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Stop Preview")
.Color(THEME_COLOR))) {
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Stop Preview")
.Color(THEME_COLOR))) {
func_800F5C2C();
CVarSetInteger(CVAR_AUDIO("Playing"), 0);
}
} else {
if (UIWidgets::Button(previewButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Play Preview")
.Color(THEME_COLOR))) {
if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) != 0) {
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Play Preview")
.Color(THEME_COLOR))) {
if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) != 0) {
func_800F5C2C();
CVarSetInteger(CVAR_AUDIO("Playing"), 0);
} else {
@ -215,7 +218,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
ImGui::SeparatorText(tabName.c_str());
if (UIWidgets::Button(resetAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
ResetGroup(map, type);
@ -227,7 +230,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
}
ImGui::SameLine();
if (UIWidgets::Button(randomizeAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
RandomizeGroup(type);
@ -239,7 +242,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
}
ImGui::SameLine();
if (UIWidgets::Button(lockAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
LockGroup(map, type);
@ -251,7 +254,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
}
ImGui::SameLine();
if (UIWidgets::Button(unlockAllButton.c_str(),
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM);
UnlockGroup(map, type);
@ -273,7 +276,9 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
continue;
}
// Do not display custom sequences in the list
if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) && defaultValue >= MAX_AUTHENTIC_SEQID) || seqData.canBeReplaced == false) {
if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) &&
defaultValue >= MAX_AUTHENTIC_SEQID) ||
seqData.canBeReplaced == false) {
continue;
}
@ -296,8 +301,10 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo(hiddenKey.c_str(), map.at(initialValue).label.c_str())) {
for (const auto& [value, seqData] : map) {
// If excluded as a replacement sequence, don't show in other dropdowns except the effect's own dropdown.
if (~(seqData.category) & type || (!seqData.canBeUsedAsReplacement && initialSfxKey != seqData.sfxKey)) {
// If excluded as a replacement sequence, don't show in other dropdowns except the effect's own
// dropdown.
if (~(seqData.category) & type ||
(!seqData.canBeUsedAsReplacement && initialSfxKey != seqData.sfxKey)) {
continue;
}
@ -317,15 +324,17 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
UIWidgets::PopStyleCombobox();
ImGui::TableNextColumn();
ImGui::PushItemWidth(-FLT_MIN);
DrawPreviewButton((type == SEQ_SFX || type == SEQ_VOICE || type == SEQ_INSTRUMENT) ? defaultValue : currentValue, seqData.sfxKey, type);
auto locked = CVarGetInteger(cvarLockKey.c_str(), 0) == 1;
DrawPreviewButton((type == SEQ_SFX || type == SEQ_VOICE || type == SEQ_INSTRUMENT) ? defaultValue
: currentValue,
seqData.sfxKey, type);
auto locked = CVarGetInteger(cvarLockKey.c_str(), 0) == 1;
ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN);
if (UIWidgets::Button(resetButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Reset to default")
.Color(THEME_COLOR))) {
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Reset to default")
.Color(THEME_COLOR))) {
CVarClear(cvarKey.c_str());
CVarClear(cvarLockKey.c_str());
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
@ -334,10 +343,10 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN);
if (UIWidgets::Button(randomizeButton.c_str(), UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Randomize this sound")
.Color(THEME_COLOR))) {
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip("Randomize this sound")
.Color(THEME_COLOR))) {
std::vector<SequenceInfo*> validSequences = {};
for (const auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) {
if (seqInfo->category & type) {
@ -354,16 +363,16 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
UpdateCurrentBGM(defaultValue, type);
}
}
}
ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN);
if (UIWidgets::Button(locked ? lockedButton.c_str() : unlockedButton.c_str(),
UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip(locked ? "Sound locked" : "Sound unlocked")
.Color(THEME_COLOR))) {
UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.0f, 6.0f))
.Tooltip(locked ? "Sound locked" : "Sound unlocked")
.Color(THEME_COLOR))) {
if (locked) {
CVarClear(cvarLockKey.c_str());
} else {
@ -442,7 +451,6 @@ void DrawTypeChip(SeqType type, std::string sequenceName) {
ImGui::EndDisabled();
}
void AudioEditorRegisterOnSceneInitHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
if (gSaveContext.gameMode != GAMEMODE_END_CREDITS && CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0)) {
@ -460,40 +468,39 @@ void AudioEditor::DrawElement() {
UIWidgets::Separator();
if (UIWidgets::Button("Randomize All Groups",
UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Randomizes all unlocked music and sound effects across tab groups"))) {
UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Randomizes all unlocked music and sound effects across tab groups"))) {
AudioEditor_RandomizeAll();
}
ImGui::SameLine();
if (UIWidgets::Button("Reset All Groups",
UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Resets all unlocked music and sound effects across tab groups"))) {
UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Resets all unlocked music and sound effects across tab groups"))) {
AudioEditor_ResetAll();
}
ImGui::SameLine();
if (UIWidgets::Button("Lock All Groups", UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Locks all music and sound effects across tab groups"))) {
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Locks all music and sound effects across tab groups"))) {
AudioEditor_LockAll();
}
ImGui::SameLine();
if (UIWidgets::Button("Unlock All Groups",
UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Unlocks all music and sound effects across tab groups"))) {
if (UIWidgets::Button("Unlock All Groups", UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR)
.Tooltip("Unlocks all music and sound effects across tab groups"))) {
AudioEditor_UnlockAll();
}
UIWidgets::Separator();
UIWidgets::PushStyleTabs(THEME_COLOR);
if (ImGui::BeginTabBar("SfxContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
static ImVec2 cellPadding(8.0f, 8.0f);
if (ImGui::BeginTabItem("Audio Options")) {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding);
@ -609,16 +616,10 @@ void AudioEditor::DrawElement() {
excludeTabOpen = true;
}
static std::map<SeqType, bool> showType {
{SEQ_BGM_WORLD, true},
{SEQ_BGM_EVENT, true},
{SEQ_BGM_BATTLE, true},
{SEQ_OCARINA, true},
{SEQ_FANFARE, true},
{SEQ_SFX, true },
{SEQ_VOICE, true },
{SEQ_INSTRUMENT, true},
{SEQ_BGM_CUSTOM, true},
static std::map<SeqType, bool> showType{
{ SEQ_BGM_WORLD, true }, { SEQ_BGM_EVENT, true }, { SEQ_BGM_BATTLE, true },
{ SEQ_OCARINA, true }, { SEQ_FANFARE, true }, { SEQ_SFX, true },
{ SEQ_VOICE, true }, { SEQ_INSTRUMENT, true }, { SEQ_BGM_CUSTOM, true },
};
// make temporary sets because removing from the set we're iterating through crashes ImGui
@ -631,7 +632,7 @@ void AudioEditor::DrawElement() {
UIWidgets::PopStyleInput();
ImGui::SameLine();
if (UIWidgets::Button("Exclude All",
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
for (auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
seqsToExclude.insert(seqInfo);
@ -640,7 +641,7 @@ void AudioEditor::DrawElement() {
}
ImGui::SameLine();
if (UIWidgets::Button("Include All",
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
for (auto seqInfo : AudioCollection::Instance->GetExcludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
seqsToInclude.insert(seqInfo);
@ -648,7 +649,8 @@ void AudioEditor::DrawElement() {
}
}
ImGui::BeginTable("sequenceTypes", 9, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders);
ImGui::BeginTable("sequenceTypes", 9,
ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders);
ImGui::TableNextColumn();
ImGui::PushStyleColor(ImGuiCol_Header, GetSequenceTypeColor(SEQ_BGM_WORLD));
@ -710,10 +712,10 @@ void AudioEditor::DrawElement() {
for (auto seqInfo : AudioCollection::Instance->GetIncludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
if (UIWidgets::Button(std::string(ICON_FA_TIMES "##" + seqInfo->sfxKey).c_str(),
UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(9.0f, 6.0f))
.Color(THEME_COLOR))) {
UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(9.0f, 6.0f))
.Color(THEME_COLOR))) {
seqsToExclude.insert(seqInfo);
}
ImGui::SameLine();
@ -738,10 +740,10 @@ void AudioEditor::DrawElement() {
for (auto seqInfo : AudioCollection::Instance->GetExcludedSequences()) {
if (sequenceSearch.PassFilter(seqInfo->label.c_str()) && showType[seqInfo->category]) {
if (UIWidgets::Button(std::string(ICON_FA_PLUS "##" + seqInfo->sfxKey).c_str(),
UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(9.0f, 6.0f))
.Color(THEME_COLOR))) {
UIWidgets::ButtonOptions()
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(9.0f, 6.0f))
.Color(THEME_COLOR))) {
seqsToInclude.insert(seqInfo);
}
ImGui::SameLine();
@ -772,7 +774,9 @@ void AudioEditor::DrawElement() {
UIWidgets::PopStyleTabs();
}
std::vector<SeqType> allTypes = { SEQ_BGM_WORLD, SEQ_BGM_EVENT, SEQ_BGM_BATTLE, SEQ_OCARINA, SEQ_FANFARE, SEQ_INSTRUMENT, SEQ_SFX, SEQ_VOICE, };
std::vector<SeqType> allTypes = {
SEQ_BGM_WORLD, SEQ_BGM_EVENT, SEQ_BGM_BATTLE, SEQ_OCARINA, SEQ_FANFARE, SEQ_INSTRUMENT, SEQ_SFX, SEQ_VOICE,
};
void AudioEditor_RandomizeAll() {
for (auto type : allTypes) {

View file

@ -8,13 +8,13 @@
#include "AudioCollection.h"
class AudioEditor : public Ship::GuiWindow {
public:
using GuiWindow::GuiWindow;
public:
using GuiWindow::GuiWindow;
void DrawElement() override;
void InitElement() override;
void UpdateElement() override {};
~AudioEditor() {};
void DrawElement() override;
void InitElement() override;
void UpdateElement() override{};
~AudioEditor(){};
};
void AudioEditor_RandomizeAll();
@ -29,7 +29,6 @@ extern "C" {
u16 AudioEditor_GetReplacementSeq(u16 seqId);
#ifdef __cplusplus
}
#endif

View file

@ -12,8 +12,7 @@
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
void BootCommands_Init()
{
void BootCommands_Init() {
// Clears vars to prevent randomizer menu from being disabled
CVarClear(CVAR_GENERAL("RandoGenerating")); // Clear when a crash happened during rando seed generation
CVarClear(CVAR_GENERAL("NewSeedGenerated"));

View file

@ -8,18 +8,18 @@
#include <vector>
extern "C" {
#include "functions.h"
#include "macros.h"
#include "variables.h"
#include "src/overlays/actors/ovl_Boss_Goma/z_boss_goma.h"
#include "src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h"
#include "src/overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
extern PlayState* gPlayState;
#include "functions.h"
#include "macros.h"
#include "variables.h"
#include "src/overlays/actors/ovl_Boss_Goma/z_boss_goma.h"
#include "src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h"
#include "src/overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
extern PlayState* gPlayState;
Gfx* KaleidoScope_QuadTextureIA8(Gfx* gfx, void* texture, s16 width, s16 height, u16 point);
#include "textures/icon_item_nes_static/icon_item_nes_static.h"
#include "textures/icon_item_ger_static/icon_item_ger_static.h"
#include "textures/icon_item_fra_static/icon_item_fra_static.h"
Gfx* KaleidoScope_QuadTextureIA8(Gfx* gfx, void* texture, s16 width, s16 height, u16 point);
#include "textures/icon_item_nes_static/icon_item_nes_static.h"
#include "textures/icon_item_ger_static/icon_item_ger_static.h"
#include "textures/icon_item_fra_static/icon_item_fra_static.h"
}
typedef struct BossRushSetting {
@ -27,103 +27,79 @@ typedef struct BossRushSetting {
std::vector<std::array<std::string, LANGUAGE_MAX>> choices;
} BossRushSetting;
BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = {
{
{ "BOSSES:", "BOSSE:", "BOSS:" },
{
{ "All", "Alle", "Tous" },
{ "Child", "Kind", "Enfant" },
{ "Adult", "Erwachsener", "Adulte" },
{ "Ganondorf & Ganon", "Ganondorf & Ganon", "Ganondorf & Ganon" },
}
},
{
{ "HEARTS:", "HERZEN:", "COEURS:" },
{
{ "10", "10", "10" },
{ "15", "15", "15" },
{ "20", "20", "20" },
{ "3", "3", "3" },
{ "5", "5", "5" },
{ "7", "7", "7" },
}
},
{
{ "AMMO:", "MUNITION:", "MUNITIONS:" },
{
{ "Limited", "Limitiert", "Limitées" },
{ "Full", "Voll", "Pleines" },
{ "Maxed", "Maximum", "Maximum" },
}
},
{
{ "HEAL:", "REGENERATION:", "SOIN:" },
{
{ "Before Ganondorf", "Vor Ganondorf", "Avant Ganondorf" },
{ "Every Boss", "Bei jedem Boss", "Tous les Boss" },
{ "Never", "Niemals", "Jamais" },
}
},
{
{ "HYPER BOSSES:", "HYPER-BOSSE:", "HYPER BOSS:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "MAGIC:", "MAGIE:", "MAGIE:" },
{
{ "Single", "Einzel", "Simple" },
{ "Double", "Doppel", "Double" },
}
},
{
{ "BIG. SWORD:", "BIG.-SCHWERT:", "EPÉE DE BIG.:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "BOTTLE:", "FLASCHEN:", "BOUTEILLE:" },
{
{ "No", "Nein", "Non" },
{ "Empty", "Leer", "Vide" },
{ "Fairy", "Fee", "Fée" },
{ "Red Potion", "Rotes Elixier", "Potion Rouge" },
{ "Green Potion", "Grünes Elixier", "Potion Verte" },
{ "Blue Potion", "Blaues Elixier", "Potion Bleue" },
}
},
{
{ "LONGSHOT:", "ENTERHAKEN:", "SUPER GRAPPIN:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "HOVER BOOTS:", "GLEITSTIEFEL:", "BOTTES DES AIRS:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "BUNNY HOOD:", "HASENOHREN:", "MASQUE DU LAPIN:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "TIMER:", "TIMER:", "TIMER:" },
{
{ "Yes", "Ja", "Oui" },
{ "No", "Nein", "Non" },
}
}
BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = {
{ { "BOSSES:", "BOSSE:", "BOSS:" },
{
{ "All", "Alle", "Tous" },
{ "Child", "Kind", "Enfant" },
{ "Adult", "Erwachsener", "Adulte" },
{ "Ganondorf & Ganon", "Ganondorf & Ganon", "Ganondorf & Ganon" },
} },
{ { "HEARTS:", "HERZEN:", "COEURS:" },
{
{ "10", "10", "10" },
{ "15", "15", "15" },
{ "20", "20", "20" },
{ "3", "3", "3" },
{ "5", "5", "5" },
{ "7", "7", "7" },
} },
{ { "AMMO:", "MUNITION:", "MUNITIONS:" },
{
{ "Limited", "Limitiert", "Limitées" },
{ "Full", "Voll", "Pleines" },
{ "Maxed", "Maximum", "Maximum" },
} },
{ { "HEAL:", "REGENERATION:", "SOIN:" },
{
{ "Before Ganondorf", "Vor Ganondorf", "Avant Ganondorf" },
{ "Every Boss", "Bei jedem Boss", "Tous les Boss" },
{ "Never", "Niemals", "Jamais" },
} },
{ { "HYPER BOSSES:", "HYPER-BOSSE:", "HYPER BOSS:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
} },
{ { "MAGIC:", "MAGIE:", "MAGIE:" },
{
{ "Single", "Einzel", "Simple" },
{ "Double", "Doppel", "Double" },
} },
{ { "BIG. SWORD:", "BIG.-SCHWERT:", "EPÉE DE BIG.:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
} },
{ { "BOTTLE:", "FLASCHEN:", "BOUTEILLE:" },
{
{ "No", "Nein", "Non" },
{ "Empty", "Leer", "Vide" },
{ "Fairy", "Fee", "Fée" },
{ "Red Potion", "Rotes Elixier", "Potion Rouge" },
{ "Green Potion", "Grünes Elixier", "Potion Verte" },
{ "Blue Potion", "Blaues Elixier", "Potion Bleue" },
} },
{ { "LONGSHOT:", "ENTERHAKEN:", "SUPER GRAPPIN:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
} },
{ { "HOVER BOOTS:", "GLEITSTIEFEL:", "BOTTES DES AIRS:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
} },
{ { "BUNNY HOOD:", "HASENOHREN:", "MASQUE DU LAPIN:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
} },
{ { "TIMER:", "TIMER:", "TIMER:" },
{
{ "Yes", "Ja", "Oui" },
{ "No", "Nein", "Non" },
} }
};
const char* BossRush_GetSettingName(u8 optionIndex, u8 language) {
@ -196,7 +172,7 @@ void BossRush_SetEquipment(u8 linkAge) {
Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_KOKIRI);
Inventory_ChangeEquipment(EQUIP_TYPE_SHIELD, EQUIP_VALUE_SHIELD_DEKU);
// Set Adult equipment.
// Set Adult equipment.
} else {
brButtonItems = { ITEM_SWORD_MASTER, ITEM_BOW, ITEM_HAMMER, ITEM_BOMB,
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE };
@ -229,34 +205,36 @@ void BossRush_HandleBlueWarp(PlayState* play, f32 warpPosX, f32 warpPosZ) {
} else {
play->nextEntranceIndex = ENTR_FOREST_TEMPLE_BOSS_ENTRANCE;
}
// King Dodongo & Volvagia
// King Dodongo & Volvagia
} else if (warpPosX == 100 && warpPosZ == -170) {
if (gSaveContext.linkAge == LINK_AGE_CHILD) {
play->nextEntranceIndex = ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE;
} else {
play->nextEntranceIndex = ENTR_FIRE_TEMPLE_BOSS_ENTRANCE;
}
// Barinade & Morb
// Barinade & Morb
} else if (warpPosX == 199 && warpPosZ == 0) {
if (gSaveContext.linkAge == LINK_AGE_CHILD) {
play->nextEntranceIndex = ENTR_JABU_JABU_BOSS_ENTRANCE;
} else {
play->nextEntranceIndex = ENTR_WATER_TEMPLE_BOSS_ENTRANCE;
}
// Twinrova
// Twinrova
} else if (warpPosX == 100 && warpPosZ == 170) {
play->nextEntranceIndex = ENTR_SPIRIT_TEMPLE_BOSS_2;
// Bongo Bongo
// Bongo Bongo
} else if (warpPosX == -100 && warpPosZ == 170) {
play->nextEntranceIndex = ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE;
// Ganondork
// Ganondork
} else if (warpPosX == -199 && warpPosZ == 0) {
play->nextEntranceIndex = ENTR_GANONDORF_BOSS_0;
} else {
SPDLOG_ERROR("[BossRush]: Unknown blue warp in chamber of sages at position ({}, {}). Warping back to chamber of sages.", warpPosX, warpPosZ);
SPDLOG_ERROR("[BossRush]: Unknown blue warp in chamber of sages at position ({}, {}). Warping back to "
"chamber of sages.",
warpPosX, warpPosZ);
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
}
// If coming from a boss room, teleport back to Chamber of Sages and set flag.
// If coming from a boss room, teleport back to Chamber of Sages and set flag.
} else {
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
@ -267,7 +245,7 @@ void BossRush_HandleBlueWarp(PlayState* play, f32 warpPosX, f32 warpPosZ) {
// Change to Adult Link.
if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ALL) {
BossRush_SetEquipment(LINK_AGE_ADULT);
// Warp to credits.
// Warp to credits.
} else if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) {
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0xFFF2;
@ -328,7 +306,8 @@ void BossRush_HandleCompleteBoss(PlayState* play) {
Health_ChangeBy(play, 320);
}
if ((CheckDungeonCount() == 3 && gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) ||
if ((CheckDungeonCount() == 3 &&
gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) ||
play->sceneNum == SCENE_GANON_BOSS) {
gSaveContext.ship.stats.playTimer += 2;
gSaveContext.ship.stats.gameComplete = 1;
@ -399,17 +378,17 @@ void BossRush_InitSave() {
gSaveContext.eventChkInf[7] |= 0x80; // bongo bongo
// Sets all rando flags to false
// Boss Rush currently uses 2 randomizer flags (RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE & RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)
// Boss Rush currently uses 2 randomizer flags (RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE &
// RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)
for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.ship.randomizerInf); i++) {
gSaveContext.ship.randomizerInf[i] = 0;
}
// Set items
std::array<u8, 24> brItems = {
ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE,
ITEM_SLINGSHOT, ITEM_NONE, ITEM_NONE, ITEM_HOOKSHOT, ITEM_NONE, ITEM_NONE,
ITEM_BOOMERANG, ITEM_LENS, ITEM_NONE, ITEM_HAMMER, ITEM_ARROW_LIGHT, ITEM_NONE,
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE,
ITEM_NONE, ITEM_HOOKSHOT, ITEM_NONE, ITEM_NONE, ITEM_BOOMERANG, ITEM_LENS, ITEM_NONE, ITEM_HAMMER,
ITEM_ARROW_LIGHT, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
};
if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_LONGSHOT] == BR_CHOICE_LONGSHOT_YES) {
@ -541,11 +520,13 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
break;
}
}
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, childPos.x, bossGoma->actor.world.pos.y, childPos.z, 0, 0, 0, WARP_DUNGEON_ADULT, false);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, childPos.x,
bossGoma->actor.world.pos.y, childPos.z, 0, 0, 0, WARP_DUNGEON_ADULT, false);
break;
}
case SCENE_DODONGOS_CAVERN_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, WARP_DUNGEON_ADULT, false);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0,
0, WARP_DUNGEON_ADULT, false);
break;
}
case SCENE_JABU_JABU_BOSS: {
@ -563,28 +544,34 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
}
}
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, sWarpPos[sp7C].x, sWarpPos[sp7C].y, sWarpPos[sp7C].z, 0, 0, 0, WARP_DUNGEON_ADULT, false);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, sWarpPos[sp7C].x, sWarpPos[sp7C].y,
sWarpPos[sp7C].z, 0, 0, 0, WARP_DUNGEON_ADULT, false);
break;
}
case SCENE_FOREST_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 14.0f, -33.0f, -3315.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 14.0f, -33.0f, -3315.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break;
}
case SCENE_FIRE_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break;
}
case SCENE_WATER_TEMPLE_BOSS: {
BossMo* bossMo = va_arg(args, BossMo*);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, bossMo->actor.world.pos.x, -280.0f, bossMo->actor.world.pos.z, 0, 0, 0, WARP_DUNGEON_ADULT, true);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, bossMo->actor.world.pos.x, -280.0f,
bossMo->actor.world.pos.z, 0, 0, 0, WARP_DUNGEON_ADULT, true);
break;
}
case SCENE_SPIRIT_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break;
}
case SCENE_SHADOW_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -50.0f, 0.0f, 400.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -50.0f, 0.0f, 400.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break;
}
default: {
@ -699,12 +686,18 @@ void BossRush_RegisterHooks() {
onBossDefeatHook = 0;
onActorUpdate = 0;
if (!IS_BOSS_RUSH) return;
if (!IS_BOSS_RUSH)
return;
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(BossRush_OnVanillaBehaviorHandler);
onSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(BossRush_OnSceneInitHandler);
onActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(BossRush_OnActorInitHandler);
onBossDefeatHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnBossDefeat>(BossRush_OnBossDefeatHandler);
onActorUpdate = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_DOOR_WARP1, BossRush_OnBlueWarpUpdate);
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(
BossRush_OnVanillaBehaviorHandler);
onSceneInitHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(BossRush_OnSceneInitHandler);
onActorInitHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(BossRush_OnActorInitHandler);
onBossDefeatHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnBossDefeat>(BossRush_OnBossDefeatHandler);
onActorUpdate = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(
ACTOR_DOOR_WARP1, BossRush_OnBlueWarpUpdate);
});
}

View file

@ -5,12 +5,12 @@
#ifdef __cplusplus
extern "C" {
#endif
void BossRush_HandleBlueWarpHeal(PlayState* play);
void BossRush_InitSave();
const char* BossRush_GetSettingName(u8 optionIndex, u8 language);
const char* BossRush_GetSettingChoiceName(u8 optionIndex, u8 choiceIndex, u8 language);
u8 BossRush_GetSettingOptionsAmount(u8 optionIndex);
void BossRush_RegisterHooks();
void BossRush_HandleBlueWarpHeal(PlayState* play);
void BossRush_InitSave();
const char* BossRush_GetSettingName(u8 optionIndex, u8 language);
const char* BossRush_GetSettingChoiceName(u8 optionIndex, u8 choiceIndex, u8 language);
u8 BossRush_GetSettingOptionsAmount(u8 optionIndex);
void BossRush_RegisterHooks();
#ifdef __cplusplus
};
#endif

View file

@ -20,15 +20,22 @@ static Color_RGBA8 textColorDefault = { 255, 255, 255, 255 };
static Color_RGBA8 range1ColorDefault = { 255, 178, 0, 255 };
static Color_RGBA8 range2ColorDefault = { 0, 255, 0, 255 };
static std::unordered_map<int32_t, const char*> buttonOutlineOptions =
{{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Always Shown" }, { BUTTON_OUTLINE_NOT_PRESSED, "Shown Only While Not Pressed" },
{ BUTTON_OUTLINE_PRESSED, "Shown Only While Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "Always Hidden" }};
static std::unordered_map<int32_t, const char*> buttonOutlineOptionsVerbose =
{{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Outline Always Shown" }, { BUTTON_OUTLINE_NOT_PRESSED, "Outline Shown Only While Not Pressed" },
{ BUTTON_OUTLINE_PRESSED, "Outline Shown Only While Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "Outline Always Hidden" }};
static std::unordered_map<int32_t, const char*> buttonOutlineOptions = {
{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Always Shown" },
{ BUTTON_OUTLINE_NOT_PRESSED, "Shown Only While Not Pressed" },
{ BUTTON_OUTLINE_PRESSED, "Shown Only While Pressed" },
{ BUTTON_OUTLINE_ALWAYS_HIDDEN, "Always Hidden" }
};
static std::unordered_map<int32_t, const char*> buttonOutlineOptionsVerbose = {
{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Outline Always Shown" },
{ BUTTON_OUTLINE_NOT_PRESSED, "Outline Shown Only While Not Pressed" },
{ BUTTON_OUTLINE_PRESSED, "Outline Shown Only While Pressed" },
{ BUTTON_OUTLINE_ALWAYS_HIDDEN, "Outline Always Hidden" }
};
static std::unordered_map<int32_t, const char*> stickModeOptions =
{{ STICK_MODE_ALWAYS_SHOWN, "Always" }, { STICK_MODE_HIDDEN_IN_DEADZONE, "While In Use" }, { STICK_MODE_ALWAYS_HIDDEN, "Never" }};
static std::unordered_map<int32_t, const char*> stickModeOptions = { { STICK_MODE_ALWAYS_SHOWN, "Always" },
{ STICK_MODE_HIDDEN_IN_DEADZONE, "While In Use" },
{ STICK_MODE_ALWAYS_HIDDEN, "Never" } };
InputViewer::~InputViewer() {
SPDLOG_TRACE("destruct input viewer");
@ -68,66 +75,78 @@ void InputViewer::DrawElement() {
if (!sButtonTexturesLoaded) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Input-Viewer-Background", "textures/buttons/InputViewerBackground.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn",
"textures/buttons/StartBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick",
"textures/buttons/AnalogStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left",
"textures/buttons/DPadLeft.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right",
"textures/buttons/DPadRight.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down",
"textures/buttons/DPadDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1", "textures/buttons/Mod1.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2", "textures/buttons/Mod2.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick",
"textures/buttons/RightStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline",
"textures/buttons/ABtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn Outline",
"textures/buttons/BBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn Outline",
"textures/buttons/LBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn Outline",
"textures/buttons/RBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn Outline",
"textures/buttons/ZBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn Outline",
"textures/buttons/StartBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left Outline",
"textures/buttons/CLeftOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right Outline",
"textures/buttons/CRightOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up Outline",
"textures/buttons/CUpOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down Outline",
"textures/buttons/CDownOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick Outline",
"textures/buttons/AnalogStickOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left Outline",
"textures/buttons/DPadLeftOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right Outline",
"textures/buttons/DPadRightOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up Outline",
"textures/buttons/DPadUpOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline",
"textures/buttons/DPadDownOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1 Outline",
"textures/buttons/Mod1Outline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2 Outline",
"textures/buttons/Mod2Outline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline",
"textures/buttons/RightStickOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn",
"textures/buttons/ABtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn",
"textures/buttons/BBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn",
"textures/buttons/LBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn",
"textures/buttons/RBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn",
"textures/buttons/ZBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Start-Btn", "textures/buttons/StartBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left",
"textures/buttons/CLeft.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right",
"textures/buttons/CRight.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up",
"textures/buttons/CUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down",
"textures/buttons/CDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Analog-Stick", "textures/buttons/AnalogStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Left", "textures/buttons/DPadLeft.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Right", "textures/buttons/DPadRight.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up",
"textures/buttons/DPadUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Down", "textures/buttons/DPadDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1",
"textures/buttons/Mod1.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2",
"textures/buttons/Mod2.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Right-Stick", "textures/buttons/RightStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"A-Btn Outline", "textures/buttons/ABtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"B-Btn Outline", "textures/buttons/BBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"L-Btn Outline", "textures/buttons/LBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"R-Btn Outline", "textures/buttons/RBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Z-Btn Outline", "textures/buttons/ZBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Start-Btn Outline", "textures/buttons/StartBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"C-Left Outline", "textures/buttons/CLeftOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"C-Right Outline", "textures/buttons/CRightOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"C-Up Outline", "textures/buttons/CUpOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"C-Down Outline", "textures/buttons/CDownOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Analog-Stick Outline", "textures/buttons/AnalogStickOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Left Outline", "textures/buttons/DPadLeftOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Right Outline", "textures/buttons/DPadRightOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Up Outline", "textures/buttons/DPadUpOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Down Outline", "textures/buttons/DPadDownOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Modifier-1 Outline", "textures/buttons/Mod1Outline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Modifier-2 Outline", "textures/buttons/Mod2Outline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Right-Stick Outline", "textures/buttons/RightStickOutline.png");
sButtonTexturesLoaded = true;
}
@ -140,7 +159,8 @@ void InputViewer::DrawElement() {
const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f);
#endif
const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0);
const int buttonOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED);
const int buttonOutlineMode =
CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED);
const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1);
ImVec2 bgSize = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background");
@ -148,12 +168,12 @@ void InputViewer::DrawElement() {
ImGui::SetNextWindowSize(
ImVec2(scaledBGSize.x + 20, scaledBGSize.y +
(showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale *
CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) +
20));
(showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale *
CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) +
20));
ImGui::SetNextWindowContentSize(
ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale *
CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f)));
CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f)));
ImGui::SetNextWindowPos(
ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30),
ImGuiCond_FirstUseEver);
@ -161,11 +181,12 @@ void InputViewer::DrawElement() {
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
OSContPad* pads = std::dynamic_pointer_cast<LUS::ControlDeck>(Ship::Context::GetInstance()->GetControlDeck())->GetPads();
OSContPad* pads =
std::dynamic_pointer_cast<LUS::ControlDeck>(Ship::Context::GetInstance()->GetControlDeck())->GetPads();
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoFocusOnAppearing;
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoFocusOnAppearing;
if (!CVarGetInteger(CVAR_INPUT_VIEWER("EnableDragging"), 1)) {
windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove;
@ -188,17 +209,17 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("BBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("BBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
if (CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("ABtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("ABtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
// C buttons
@ -206,33 +227,33 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CUpOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CUpOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
if (CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CLeftOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CLeftOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
if (CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CRightOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CRightOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
if (CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CDownOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("CDownOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
// L/R/Z
@ -240,25 +261,25 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("LBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("LBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
if (CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("RBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("RBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
if (CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
// Start
@ -266,9 +287,9 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"),
BUTTON_OUTLINE_NOT_PRESSED));
}
// Dpad
@ -276,27 +297,27 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
// Modifier 1
@ -304,18 +325,18 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Modifier-1", "Modifier-1 Outline", pads[0].button & BTN_CUSTOM_MODIFIER1, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("Mod1OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("Mod1OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
// Modifier 2
if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Modifier-2", "Modifier-2 Outline", pads[0].button & BTN_CUSTOM_MODIFIER2, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("Mod2OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("Mod2OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
}
const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y;
@ -340,9 +361,9 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(
ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale,
aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale));
aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale));
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
}
// Right Stick
@ -364,15 +385,16 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(
ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale,
aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale));
aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale));
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
}
// Analog stick angle text
if (showAnalogAngles) {
ImGui::SetCursorPos(ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale,
scaledBGSize.y + aPos.y + 10));
ImGui::SetCursorPos(
ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale,
scaledBGSize.y + aPos.y + 10));
// Scale font with input viewer scale
float oldFontScale = ImGui::GetFont()->Scale;
ImGui::GetFont()->Scale *= scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f);
@ -392,18 +414,17 @@ void InputViewer::DrawElement() {
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) &&
(rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) {
ImGui::PushStyleColor(
ImGuiCol_Text,
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"), range1ColorDefault)));
}
else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) &&
(rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) {
ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"),
range1ColorDefault)));
} else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) &&
(rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) {
ImGui::PushStyleColor(
ImGuiCol_Text,
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"), range2ColorDefault)));
}
else {
ImGui::PushStyleColor(ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"),
textColorDefault)));
ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"),
range2ColorDefault)));
} else {
ImGui::PushStyleColor(ImGuiCol_Text,
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"),
textColorDefault)));
}
// Render text
@ -430,15 +451,23 @@ InputViewerSettingsWindow::~InputViewerSettingsWindow() {
void InputViewerSettingsWindow::DrawElement() {
// gInputViewer.Scale
CVarSliderFloat("Input Viewer Scale: %.2f", CVAR_INPUT_VIEWER("Scale"),
FloatSliderOptions().Color(THEME_COLOR).DefaultValue(1.0f).Min(0.1f).Max(5.0f).ShowButtons(true).Tooltip("Sets the on screen size of the input viewer"));
FloatSliderOptions()
.Color(THEME_COLOR)
.DefaultValue(1.0f)
.Min(0.1f)
.Max(5.0f)
.ShowButtons(true)
.Tooltip("Sets the on screen size of the input viewer"));
// gInputViewer.EnableDragging
CVarCheckbox("Enable Dragging", CVAR_INPUT_VIEWER("EnableDragging"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Enable Dragging", CVAR_INPUT_VIEWER("EnableDragging"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator(true, true);
// gInputViewer.ShowBackground
CVarCheckbox("Show Background Layer", CVAR_INPUT_VIEWER("ShowBackground"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show Background Layer", CVAR_INPUT_VIEWER("ShowBackground"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator(true, true);
@ -446,121 +475,138 @@ void InputViewerSettingsWindow::DrawElement() {
if (ImGui::CollapsingHeader("Buttons")) {
// gInputViewer.ButtonOutlineMode
CVarCombobox("Button Outlines/Backgrounds", CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions,
ComboboxOptions({{ .disabled = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1), .disabledTooltip = "Disabled because Global Button Outline is off" }})
.Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)
.Tooltip("Sets the desired visibility behavior for the button outline/background layers. Useful for "
"custom input viewers."));
CVarCombobox(
"Button Outlines/Backgrounds", CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions,
ComboboxOptions({ { .disabled = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1),
.disabledTooltip = "Disabled because Global Button Outline is off" } })
.Color(THEME_COLOR)
.DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)
.Tooltip("Sets the desired visibility behavior for the button outline/background layers. Useful for "
"custom input viewers."));
// gInputViewer.UseGlobalButtonOutlineMode
CVarCheckbox("Use for all buttons", CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Use for all buttons", CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator();
bool useIndividualOutlines = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1);
// gInputViewer.ABtn
CVarCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) {
ImGui::Indent();
CVarCombobox("##ABtnOutline", CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
CVarCombobox("##ABtnOutline", CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.BBtn
CVarCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) {
ImGui::Indent();
CVarCombobox("##BBtnOutline", CVAR_INPUT_VIEWER("BBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.CUp
CVarCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) {
ImGui::Indent();
CVarCombobox("##CUpOutline", CVAR_INPUT_VIEWER("CUpOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.CRight
CVarCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) {
ImGui::Indent();
CVarCombobox("##CRightOutline", CVAR_INPUT_VIEWER("CRightOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.CDown
CVarCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) {
ImGui::Indent();
CVarCombobox("##CDownOutline", CVAR_INPUT_VIEWER("CDownOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.CLeft
CVarCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) {
ImGui::Indent();
CVarCombobox("##CLeftOutline", CVAR_INPUT_VIEWER("CLeftOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.LBtn
CVarCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) {
ImGui::Indent();
CVarCombobox("##LBtnOutline", CVAR_INPUT_VIEWER("LBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.RBtn
CVarCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) {
ImGui::Indent();
CVarCombobox("##RBtnOutline", CVAR_INPUT_VIEWER("RBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.ZBtn
CVarCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) {
ImGui::Indent();
CVarCombobox("##ZBtnOutline", CVAR_INPUT_VIEWER("ZBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.StartBtn
CVarCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) {
ImGui::Indent();
CVarCombobox("##StartBtnOutline", CVAR_INPUT_VIEWER("StartBtnOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.Dpad
CVarCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) {
ImGui::Indent();
CVarCombobox("##DpadOutline", CVAR_INPUT_VIEWER("DpadOutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.Mod1
CVarCheckbox("Show Modifier Button 1 Layers", CVAR_INPUT_VIEWER("Mod1"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show Modifier Button 1 Layers", CVAR_INPUT_VIEWER("Mod1"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) {
ImGui::Indent();
CVarCombobox("##Mmod1Outline", CVAR_INPUT_VIEWER("Mod1OutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
// gInputViewer.Mod2
CVarCheckbox("Show Modifier Button 2 Layers", CVAR_INPUT_VIEWER("Mod2"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
CVarCheckbox("Show Modifier Button 2 Layers", CVAR_INPUT_VIEWER("Mod2"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) {
ImGui::Indent();
CVarCombobox("##Mod2Outline", CVAR_INPUT_VIEWER("Mod2OutlineMode"), buttonOutlineOptionsVerbose,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED));
ImGui::Unindent();
}
@ -569,72 +615,124 @@ void InputViewerSettingsWindow::DrawElement() {
if (ImGui::CollapsingHeader("Analog Stick")) {
// gInputViewer.AnalogStick.VisibilityMode
CVarCombobox("Analog Stick Visibility", CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip("Determines the conditions under which the moving layer of the analog stick texture is visible."));
CVarCombobox(
"Analog Stick Visibility", CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions,
ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the moving layer of the analog stick texture is visible."));
// gInputViewer.AnalogStick.OutlineMode
CVarCombobox("Analog Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), stickModeOptions,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip("Determines the conditions under which the analog stick outline/background texture is visible."));
CVarCombobox(
"Analog Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"),
stickModeOptions,
ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the analog stick outline/background texture is visible."));
// gInputViewer.AnalogStick.Movement
CVarSliderInt("Analog Stick Movement: %dpx", CVAR_INPUT_VIEWER("AnalogStick.Movement"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(200).DefaultValue(12).ShowButtons(true)
.Tooltip("Sets the distance to move the analog stick in the input viewer. Useful for custom input viewers."));
CVarSliderInt("Analog Stick Movement: %dpx", CVAR_INPUT_VIEWER("AnalogStick.Movement"),
IntSliderOptions()
.Color(THEME_COLOR)
.Min(0)
.Max(200)
.DefaultValue(12)
.ShowButtons(true)
.Tooltip("Sets the distance to move the analog stick in the input viewer. Useful for custom "
"input viewers."));
UIWidgets::PaddedSeparator(true, true);
}
if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) {
// gInputViewer.RightStick.VisibilityMode
CVarCombobox("Right Stick Visibility", CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip("Determines the conditions under which the moving layer of the right stick texture is visible."));
CVarCombobox(
"Right Stick Visibility", CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions,
ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the moving layer of the right stick texture is visible."));
// gInputViewer.RightStick.OutlineMode
CVarCombobox("Right Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip("Determines the conditions under which the right stick outline/background texture is visible."));
CVarCombobox(
"Right Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions,
ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the right stick outline/background texture is visible."));
// gInputViewer.RightStick.Movement
CVarSliderInt("Right Stick Movement: %dpx", CVAR_INPUT_VIEWER("RightStick.Movement"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(200).DefaultValue(7).ShowButtons(true)
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for custom input viewers."));
CVarSliderInt(
"Right Stick Movement: %dpx", CVAR_INPUT_VIEWER("RightStick.Movement"),
IntSliderOptions()
.Color(THEME_COLOR)
.Min(0)
.Max(200)
.DefaultValue(7)
.ShowButtons(true)
.Tooltip(
"Sets the distance to move the right stick in the input viewer. Useful for custom input viewers."));
UIWidgets::PaddedSeparator(true, true);
}
if (ImGui::CollapsingHeader("Analog Angle Values")) {
// gAnalogAngles
CVarCheckbox("Show Analog Stick Angle Values", CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Displays analog stick angle values in the input viewer"));
CVarCheckbox(
"Show Analog Stick Angle Values", CVAR_INPUT_VIEWER("AnalogAngles.Enabled"),
CheckboxOptions().Color(THEME_COLOR).Tooltip("Displays analog stick angle values in the input viewer"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0)) {
// gInputViewer.AnalogAngles.TextColor
CVarColorPicker("Text Color", CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), textColorDefault,
true, ColorPickerRandomButton | ColorPickerResetButton);
CVarColorPicker("Text Color", CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), textColorDefault, true,
ColorPickerRandomButton | ColorPickerResetButton);
// gAnalogAngleScale
CVarSliderFloat("Angle Text Scale: %.2f%%", CVAR_INPUT_VIEWER("AnalogAngles.Scale"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.1f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Angle Text Scale: %.2f%%", CVAR_INPUT_VIEWER("AnalogAngles.Scale"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.1f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
// gInputViewer.AnalogAngles.Offset
CVarSliderInt("Angle Text Offset: %dpx", CVAR_INPUT_VIEWER("AnalogAngles.Offset"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(400).DefaultValue(0).ShowButtons(true)
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for custom input viewers."));
CVarSliderInt("Angle Text Offset: %dpx", CVAR_INPUT_VIEWER("AnalogAngles.Offset"),
IntSliderOptions()
.Color(THEME_COLOR)
.Min(0)
.Max(400)
.DefaultValue(0)
.ShowButtons(true)
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for "
"custom input viewers."));
UIWidgets::PaddedSeparator(true, true);
// gInputViewer.AnalogAngles.Range1.Enabled
CVarCheckbox("Highlight ESS Position", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Highlights the angle value text when the analog stick is in ESS position (on flat ground)"));
CVarCheckbox(
"Highlight ESS Position", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip(
"Highlights the angle value text when the analog stick is in ESS position (on flat ground)"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0)) {
// gInputViewer.AnalogAngles.Range1.Color
CVarColorPicker("ESS Color", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), range1ColorDefault,
true, ColorPickerRandomButton | ColorPickerResetButton);
CVarColorPicker("ESS Color", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), range1ColorDefault, true,
ColorPickerRandomButton | ColorPickerResetButton);
}
UIWidgets::PaddedSeparator(true, true);
// gInputViewer.AnalogAngles.Range2.Enabled
CVarCheckbox("Highlight Walking Speed Angles", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Highlights the angle value text when the analog stick is at an angle that would "
"produce a walking speed (on flat ground)\n\n"
"Useful for 1.0 Empty Jumpslash Quick Put Away"));
CVarCheckbox("Highlight Walking Speed Angles", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Highlights the angle value text when the analog stick is at an angle that would "
"produce a walking speed (on flat ground)\n\n"
"Useful for 1.0 Empty Jumpslash Quick Put Away"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0)) {
// gInputViewer.AnalogAngles.Range2.Color
CVarColorPicker("Walking Speed Color", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"), range2ColorDefault,
true, ColorPickerRandomButton | ColorPickerResetButton);
CVarColorPicker("Walking Speed Color", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"),
range2ColorDefault, true, ColorPickerRandomButton | ColorPickerResetButton);
}
}
}

View file

@ -18,28 +18,28 @@ typedef enum {
} StickMode;
class InputViewer : public Ship::GuiWindow {
public:
public:
using GuiWindow::GuiWindow;
void Draw() override;
void InitElement() override {};
void InitElement() override{};
void DrawElement() override;
void UpdateElement() override {};
void UpdateElement() override{};
InputViewer();
~InputViewer();
private:
void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode);
private:
void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode);
};
class InputViewerSettingsWindow : public Ship::GuiWindow {
public:
public:
using GuiWindow::GuiWindow;
void InitElement() override {};
void InitElement() override{};
void DrawElement() override;
void UpdateElement() override {};
void UpdateElement() override{};
InputViewerSettingsWindow();
~InputViewerSettingsWindow();

View file

@ -42,10 +42,12 @@ void Mouse_HandleThirdPerson(f32* newCamX, f32* newCamY) {
void Mouse_HandleFirstPerson(Player* player) {
f32 xAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.X"), 1.0f);
f32 yAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.Y"), 1.0f);
s8 invertXAxisMulti = ((CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0)
&& !CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0))
|| (!CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0)
&& CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0))) ? -1 : 1;
s8 invertXAxisMulti = ((CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) &&
!CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) ||
(!CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) &&
CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)))
? -1
: 1;
s8 invertYAxisMulti = CVarGetInteger(CVAR_SETTING("Controls.InvertAimingYAxis"), 1) ? 1 : -1;
if (MOUSE_ENABLED) {
player->actor.focus.rot.y -= mouseCoordRel.x * 6.0f * xAxisMulti * invertXAxisMulti;
@ -57,7 +59,7 @@ void Mouse_RecenterCursor() {
u32 width = GetWindow()->GetWidth();
u32 height = GetWindow()->GetHeight();
if (MOUSE_ENABLED) {
GetWindow()->SetMousePos({(s32) (width/2), (s32) (height/2)});
GetWindow()->SetMousePos({ (s32)(width / 2), (s32)(height / 2) });
}
}
@ -67,7 +69,8 @@ void Mouse_HandleShield(f32* sp50, f32* sp54) {
s32 height = GetWindow()->GetHeight();
f32 xBound = 7200 / ((f32)width / 2);
f32 yBound = 6000 / ((f32)height / 2);
*sp50 += (mouseCoord.x - (width / 2)) * xBound * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 1 : -1);
*sp50 +=
(mouseCoord.x - (width / 2)) * xBound * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 1 : -1);
*sp54 += (mouseCoord.y - (height / 2)) * yBound;
*sp50 = CLAMP(*sp50, -7200, 7200);
*sp54 = CLAMP(*sp54, -6000, 6000);
@ -142,7 +145,7 @@ void Mouse_RegisterUpdateQuickspinCount() {
}
void Mouse_RegisterHandleQuickspin() {
REGISTER_VB_SHOULD(VB_SHOULD_QUICKSPIN, { Mouse_HandleQuickspin(should, va_arg(args, s8*), va_arg(args, s8*)); } );
REGISTER_VB_SHOULD(VB_SHOULD_QUICKSPIN, { Mouse_HandleQuickspin(should, va_arg(args, s8*), va_arg(args, s8*)); });
}
static RegisterShipInitFunc initFunc_shieldRecenter(Mouse_RegisterRecenterCursorOnShield, { CVAR_ENABLE_MOUSE_NAME });
@ -150,4 +153,4 @@ static RegisterShipInitFunc initFunc_firstPerson(Mouse_RegisterHandleFirstPerson
static RegisterShipInitFunc initFunc_quickspinCount(Mouse_RegisterUpdateQuickspinCount, { CVAR_ENABLE_MOUSE_NAME });
static RegisterShipInitFunc initFunc_quickspin(Mouse_RegisterHandleQuickspin, { CVAR_ENABLE_MOUSE_NAME });
static RegisterShipInitFunc initFunc_shieldMove(Mouse_RegisterHandleShield, { CVAR_ENABLE_MOUSE_NAME });
} //extern "C"
} // extern "C"

View file

@ -18,8 +18,8 @@ void Mouse_HandleShield(f32* sp50, f32* sp54);
bool Mouse_HandleQuickspin(bool* should, s8* iter2, s8* sp3C);
void Mouse_UpdateQuickspinCount();
#ifdef __cplusplus
}; //extern "C"
}; // extern "C"
#endif
//MOUSE_H
// MOUSE_H
#endif

View file

@ -26,29 +26,25 @@ void SohInputEditorWindow::InitElement() {
mButtonsBitmasks = { BTN_A, BTN_B, BTN_START, BTN_L, BTN_R, BTN_Z, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT };
mDpadBitmasks = { BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT };
mModifierButtonsBitmasks = { BTN_CUSTOM_MODIFIER1, BTN_CUSTOM_MODIFIER2 };
mCustomOcarinaButtonsBitmasks = {
BTN_CUSTOM_OCARINA_NOTE_D4,
BTN_CUSTOM_OCARINA_NOTE_F4,
BTN_CUSTOM_OCARINA_NOTE_A4,
BTN_CUSTOM_OCARINA_NOTE_B4,
BTN_CUSTOM_OCARINA_NOTE_D5
};
mCustomOcarinaButtonsBitmasks = { BTN_CUSTOM_OCARINA_NOTE_D4, BTN_CUSTOM_OCARINA_NOTE_F4,
BTN_CUSTOM_OCARINA_NOTE_A4, BTN_CUSTOM_OCARINA_NOTE_B4,
BTN_CUSTOM_OCARINA_NOTE_D5 };
addButtonName(BTN_A, "A");
addButtonName(BTN_B, "B");
addButtonName(BTN_CUP, "C Up");
addButtonName(BTN_CDOWN, "C Down");
addButtonName(BTN_CLEFT, "C Left");
addButtonName(BTN_CRIGHT, "C Right");
addButtonName(BTN_L, "L");
addButtonName(BTN_Z, "Z");
addButtonName(BTN_R, "R");
addButtonName(BTN_START, "Start");
addButtonName(BTN_DUP, "D-pad up");
addButtonName(BTN_DDOWN, "D-pad down");
addButtonName(BTN_DLEFT, "D-pad left");
addButtonName(BTN_DRIGHT, "D-pad right");
addButtonName(0, "None");
addButtonName(BTN_A, "A");
addButtonName(BTN_B, "B");
addButtonName(BTN_CUP, "C Up");
addButtonName(BTN_CDOWN, "C Down");
addButtonName(BTN_CLEFT, "C Left");
addButtonName(BTN_CRIGHT, "C Right");
addButtonName(BTN_L, "L");
addButtonName(BTN_Z, "Z");
addButtonName(BTN_R, "R");
addButtonName(BTN_START, "Start");
addButtonName(BTN_DUP, "D-pad up");
addButtonName(BTN_DDOWN, "D-pad down");
addButtonName(BTN_DLEFT, "D-pad left");
addButtonName(BTN_DRIGHT, "D-pad right");
addButtonName(0, "None");
}
#define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929
@ -191,7 +187,7 @@ void SohInputEditorWindow::DrawAnalogPreview(const char* label, ImVec2 stick, fl
#define BUTTON_COLOR_GAMEPAD_PURPLE_HOVERED ImVec4(0.431f, 0.369f, 0.706f, 1.0f)
void SohInputEditorWindow::GetButtonColorsForDeviceType(Ship::PhysicalDeviceType lusIndex, ImVec4& buttonColor,
ImVec4& buttonHoveredColor) {
ImVec4& buttonHoveredColor) {
switch (lusIndex) {
case Ship::PhysicalDeviceType::Keyboard:
buttonColor = BUTTON_COLOR_KEYBOARD_BEIGE;
@ -669,8 +665,8 @@ void SohInputEditorWindow::DrawStickSection(uint8_t port, uint8_t stick, int32_t
}
ImGui::SameLine(0.0f, 0.0f);
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
if (ImGui::SliderInt(StringHelper::Sprintf("##Sensitivity%d", id).c_str(), &sensitivityPercentage, 0, 200, "%d%%",
ImGuiSliderFlags_AlwaysClamp)) {
if (ImGui::SliderInt(StringHelper::Sprintf("##Sensitivity%d", id).c_str(), &sensitivityPercentage, 0, 200,
"%d%%", ImGuiSliderFlags_AlwaysClamp)) {
controllerStick->SetSensitivity(sensitivityPercentage);
}
ImGui::SameLine(0.0f, 0.0f);
@ -1070,12 +1066,16 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
"Original Tunic Colors", "Cosmetics Tunic Colors", "Health Colors",
"Original Navi Targeting Colors", "Cosmetics Navi Targeting Colors", "Custom"
};
CVarCombobox("Source", CVAR_SETTING("LEDColorSource"), ledSources, UIWidgets::ComboboxOptions().Color(THEME_COLOR).DefaultIndex(LED_SOURCE_TUNIC_ORIGINAL)
.Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when "
"health < 40%. Green otherwise.\n\n"
"Tunics: colors will mirror currently equipped tunic, whether original or the current "
"values in Cosmetics Editor.\n\n"
"Custom: single, solid color"));
CVarCombobox(
"Source", CVAR_SETTING("LEDColorSource"), ledSources,
UIWidgets::ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(LED_SOURCE_TUNIC_ORIGINAL)
.Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when "
"health < 40%. Green otherwise.\n\n"
"Tunics: colors will mirror currently equipped tunic, whether original or the current "
"values in Cosmetics Editor.\n\n"
"Custom: single, solid color"));
if (CVarGetInteger(CVAR_SETTING("LEDColorSource"), 1) == LED_SOURCE_CUSTOM) {
UIWidgets::Spacer(3);
auto port1Color = CVarGetColor24(CVAR_SETTING("LEDPort1Color"), { 255, 255, 255 });
@ -1094,12 +1094,21 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
ImGui::Text("Custom Color");
}
CVarSliderFloat("Brightness: %.1f %%", CVAR_SETTING("LEDBrightness"),
FloatSliderOptions().IsPercentage().Min(0.0f).Max(1.0f).DefaultValue(1.0f).ShowButtons(true)
.Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off."));
CVarCheckbox("Critical Health Override", CVAR_SETTING("LEDCriticalOverride"),
CheckboxOptions({{ .disabled = CVarGetInteger(CVAR_SETTING("LEDColorSource"), LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH,
.disabledTooltip = "Override redundant for health source."}}).DefaultValue(true)
.Tooltip("Shows red color when health is critical, otherwise displays according to color source."));
FloatSliderOptions()
.IsPercentage()
.Min(0.0f)
.Max(1.0f)
.DefaultValue(1.0f)
.ShowButtons(true)
.Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off."));
CVarCheckbox(
"Critical Health Override", CVAR_SETTING("LEDCriticalOverride"),
CheckboxOptions({ { .disabled = CVarGetInteger(CVAR_SETTING("LEDColorSource"),
LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH,
.disabledTooltip = "Override redundant for health source." } })
.DefaultValue(true)
.Tooltip(
"Shows red color when health is critical, otherwise displays according to color source."));
}
ImGui::TreePop();
}
@ -1234,38 +1243,35 @@ void SohInputEditorWindow::DrawGyroSection(uint8_t port) {
}
}
const ImGuiTableFlags PANEL_TABLE_FLAGS =
ImGuiTableFlags_BordersH |
ImGuiTableFlags_BordersV;
const ImGuiTableFlags PANEL_TABLE_FLAGS = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV;
const ImGuiTableColumnFlags PANEL_TABLE_COLUMN_FLAGS =
ImGuiTableColumnFlags_IndentEnable |
ImGuiTableColumnFlags_NoSort;
ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
namespace TableHelper {
void InitHeader(bool has_header = true) {
if (has_header) {
ImGui::TableHeadersRow();
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding(); //This is to adjust Vertical pos of item in a cell to be normlized.
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
void NextCol() {
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
void NextLine() {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
void InitHeader(bool has_header = true) {
if (has_header) {
ImGui::TableHeadersRow();
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding(); // This is to adjust Vertical pos of item in a cell to be normlized.
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
void NextCol() {
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
void NextLine() {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
} // namespace TableHelper
void SohInputEditorWindow::addButtonName(N64ButtonMask mask, const char* name) {
buttons.push_back(std::make_pair(mask, name));
buttonNames[mask] = std::prev(buttons.end());
@ -1292,7 +1298,7 @@ void SohInputEditorWindow::DrawMapping(CustomButtonMap& mapping, float labelWidt
ImGui::SetCursorPosY(cursorPos.y);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
if (ImGui::BeginCombo(StringHelper::Sprintf("##%s", mapping.cVarName).c_str(), preview)) {
if (ImGui::BeginCombo(StringHelper::Sprintf("##%s", mapping.cVarName).c_str(), preview)) {
for (auto i = buttons.begin(); i != buttons.end(); i++) {
if ((i->first & excludedButtons) != 0) {
continue;
@ -1309,7 +1315,7 @@ void SohInputEditorWindow::DrawMapping(CustomButtonMap& mapping, float labelWidt
void SohInputEditorWindow::DrawOcarinaControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x, cursor.y + 5));
CheckboxOptions checkOpt = CheckboxOptions().Color(THEME_COLOR);
CVarCheckbox("Dpad Ocarina Playback", CVAR_SETTING("CustomOcarina.Dpad"), checkOpt);
CVarCheckbox("Right Stick Ocarina Playback", CVAR_SETTING("CustomOcarina.RightStick"), checkOpt);
@ -1344,29 +1350,47 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() {
void SohInputEditorWindow::DrawCameraControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
CVarCheckbox("Enable Mouse Controls", CVAR_SETTING("EnableMouse"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Allows for using the mouse to control the camera (must enable Free Look), "
"aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)"));
CVarCheckbox(
"Enable Mouse Controls", CVAR_SETTING("EnableMouse"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Allows for using the mouse to control the camera (must enable Free Look), "
"aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)"));
Ship::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail());
CVarCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming"));
CVarCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming"));
if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) {
CVarCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Changes the left stick to move the player while in first person mode"));
CVarCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Changes the left stick to move the player while in first person mode"));
}
CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"));
CVarCheckbox("Invert Aiming Y Axis", CVAR_SETTING("Controls.InvertAimingYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"));
CVarCheckbox("Invert Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingXAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)
.Tooltip("Inverts the Shield Aiming X Axis"));
CVarCheckbox("Invert Shield Aiming Y Axis", CVAR_SETTING("Controls.InvertShieldAimingYAxis"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Inverts the Shield Aiming Y Axis"));
CVarCheckbox("Invert Z-Weapon Aiming Y Axis", CVAR_SETTING("Controls.InvertZAimingYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming"));
CVarCheckbox("Disable Auto-Centering in First-Person View", CVAR_SETTING("DisableFirstPersonAutoCenterView"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"));
if (CVarCheckbox("Enable Custom Aiming/First-Person sensitivity", CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), CheckboxOptions().Color(THEME_COLOR))) {
CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"));
CVarCheckbox("Invert Aiming Y Axis", CVAR_SETTING("Controls.InvertAimingYAxis"),
CheckboxOptions()
.Color(THEME_COLOR)
.DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"));
CVarCheckbox("Invert Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingXAxis"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true).Tooltip("Inverts the Shield Aiming X Axis"));
CVarCheckbox("Invert Shield Aiming Y Axis", CVAR_SETTING("Controls.InvertShieldAimingYAxis"),
CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Shield Aiming Y Axis"));
CVarCheckbox("Invert Z-Weapon Aiming Y Axis", CVAR_SETTING("Controls.InvertZAimingYAxis"),
CheckboxOptions()
.Color(THEME_COLOR)
.DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming"));
CVarCheckbox("Disable Auto-Centering in First-Person View", CVAR_SETTING("DisableFirstPersonAutoCenterView"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"));
if (CVarCheckbox("Enable Custom Aiming/First-Person sensitivity",
CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), CheckboxOptions().Color(THEME_COLOR))) {
if (!CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) {
CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.X"));
CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.Y"));
@ -1374,10 +1398,24 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
}
}
if (CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) {
CVarSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FirstPersonCameraSensitivity.X"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FirstPersonCameraSensitivity.Y"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%",
CVAR_SETTING("FirstPersonCameraSensitivity.X"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%",
CVAR_SETTING("FirstPersonCameraSensitivity.Y"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
}
Ship::GuiWindow::EndGroupPanel(0);
@ -1385,19 +1423,37 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
Ship::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail());
CVarCheckbox("Free Look", CVAR_SETTING("FreeLook.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the "
"controller config menu, and map the camera stick to the right stick."));
CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Inverts the Camera X Axis in:\n-Free look"));
CVarCheckbox("Invert Camera Y Axis", CVAR_SETTING("FreeLook.InvertYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-Free look"));
CVarSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.X"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.Y"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderInt("Camera Distance: %d", CVAR_SETTING("FreeLook.MaxCameraDistance"), IntSliderOptions().Color(THEME_COLOR).Min(100).Max(900).DefaultValue(185).ShowButtons(true));
CVarSliderInt("Camera Transition Speed: %d", CVAR_SETTING("FreeLook.TransitionSpeed"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(900).DefaultValue(25).ShowButtons(true));
CVarCheckbox(
"Free Look", CVAR_SETTING("FreeLook.Enabled"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the "
"controller config menu, and map the camera stick to the right stick."));
CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"),
CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Camera X Axis in:\n-Free look"));
CVarCheckbox(
"Invert Camera Y Axis", CVAR_SETTING("FreeLook.InvertYAxis"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true).Tooltip("Inverts the Camera Y Axis in:\n-Free look"));
CVarSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.X"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.Y"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderInt("Camera Distance: %d", CVAR_SETTING("FreeLook.MaxCameraDistance"),
IntSliderOptions().Color(THEME_COLOR).Min(100).Max(900).DefaultValue(185).ShowButtons(true));
CVarSliderInt("Camera Transition Speed: %d", CVAR_SETTING("FreeLook.TransitionSpeed"),
IntSliderOptions().Color(THEME_COLOR).Min(0).Max(900).DefaultValue(25).ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0);
}
@ -1405,17 +1461,26 @@ void SohInputEditorWindow::DrawDpadControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail());
CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold C-Up to equip instead of navigate"));
CVarCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad"));
CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold "
"C-Up to equip instead of navigate"));
CVarCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry "
"screens with the D-pad"));
if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) {
ImGui::BeginDisabled();
}
CVarCheckbox("D-pad hold change", CVAR_SETTING("DpadHoldChange"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)
.Tooltip("The cursor will only move a single space no matter how long a D-pad direction is held"));
CVarCheckbox("D-pad hold change", CVAR_SETTING("DpadHoldChange"),
CheckboxOptions()
.Color(THEME_COLOR)
.DefaultValue(true)
.Tooltip("The cursor will only move a single space no matter how long a D-pad direction is held"));
if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) {
ImGui::EndDisabled();
@ -1457,7 +1522,7 @@ void SohInputEditorWindow::DrawDeviceToggles(uint8_t portIndex) {
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
auto notIgnored = !connectedDeviceManager->PortIsIgnoringInstanceId(portIndex, instanceId);
ImGui::PopItemFlag();
if(ImGui::Checkbox(StringHelper::Sprintf("###instanceId_%d", instanceId).c_str(), &notIgnored)) {
if (ImGui::Checkbox(StringHelper::Sprintf("###instanceId_%d", instanceId).c_str(), &notIgnored)) {
if (notIgnored) {
connectedDeviceManager->UnignoreInstanceIdForPort(portIndex, instanceId);
} else {
@ -1536,24 +1601,52 @@ void SohInputEditorWindow::DrawLinkTab() {
DrawButtonLine("M2", portIndex, BTN_CUSTOM_MODIFIER2);
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
CVarCheckbox("Enable speed modifiers", CVAR_SETTING("WalkModifier.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Hold the assigned button to change the maximum walking or swimming speed"));
CVarCheckbox("Enable speed modifiers", CVAR_SETTING("WalkModifier.Enabled"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Hold the assigned button to change the maximum walking or swimming speed"));
if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0)) {
UIWidgets::Spacer(5);
Ship::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail());
CVarCheckbox("Toggle modifier instead of holding", CVAR_SETTING("WalkModifier.SpeedToggle"), CheckboxOptions().Color(THEME_COLOR));
CVarCheckbox("Toggle modifier instead of holding", CVAR_SETTING("WalkModifier.SpeedToggle"),
CheckboxOptions().Color(THEME_COLOR));
Ship::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail());
CVarCheckbox("Don't affect jump distance/velocity", CVAR_SETTING("WalkModifier.DoesntChangeJump"), CheckboxOptions().Color(THEME_COLOR));
CVarSliderFloat("Walk Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.Mapping1"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Walk Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.Mapping2"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarCheckbox("Don't affect jump distance/velocity", CVAR_SETTING("WalkModifier.DoesntChangeJump"),
CheckboxOptions().Color(THEME_COLOR));
CVarSliderFloat("Walk Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.Mapping1"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Walk Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.Mapping2"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0);
Ship::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail());
CVarSliderFloat("Swim Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping1"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Swim Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping2"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true));
CVarSliderFloat("Swim Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping1"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Swim Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping2"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0);
Ship::GuiWindow::EndGroupPanel(0);
}
@ -1755,7 +1848,8 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) {
}
PopStyleButton();
if (ImGui::BeginPopupModal("Set Defaults for Gamepad (SDL)", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("This will clear all existing mappings for\nGamepad (SDL) on port %d.\n\nContinue?", portIndex + 1);
ImGui::Text("This will clear all existing mappings for\nGamepad (SDL) on port %d.\n\nContinue?",
portIndex + 1);
PushStyleButton(THEME_COLOR);
if (ImGui::Button("Cancel")) {
shouldClose = true;

View file

@ -41,7 +41,8 @@ class SohInputEditorWindow : public Ship::GuiWindow {
void DrawButtonLineEditMappingButton(uint8_t port, N64ButtonMask bitmask, std::string id);
void DrawButtonLineAddMappingButton(uint8_t port, N64ButtonMask bitmask);
void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction, std::string id);
void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction,
std::string id);
void DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction);
void DrawStickSection(uint8_t port, uint8_t stick, int32_t id, ImVec4 color);
@ -84,7 +85,7 @@ class SohInputEditorWindow : public Ship::GuiWindow {
void UpdateStickDirectionToMappingIds(uint8_t port);
void GetButtonColorsForDeviceType(Ship::PhysicalDeviceType lusIndex, ImVec4& buttonColor,
ImVec4& buttonHoveredColor);
ImVec4& buttonHoveredColor);
void DrawLinkTab();
void DrawIvanTab();
void DrawDebugPortTab(uint8_t portIndex, std::string customName = "");

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,9 @@
#pragma once
#include <libultraship/libultraship.h>
// Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to reset/randomize
// every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in `DrawCosmeticsEditor`
// Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to
// reset/randomize every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in
// `DrawCosmeticsEditor`
typedef enum {
COSMETICS_GROUP_LINK,
COSMETICS_GROUP_MIRRORSHIELD,
@ -32,7 +33,7 @@ typedef enum {
extern "C" {
#endif //__cplusplus
Color_RGBA8 CosmeticsEditor_GetDefaultValue(const char* id);
Color_RGBA8 CosmeticsEditor_GetDefaultValue(const char* id);
#ifdef __cplusplus
}
@ -50,7 +51,8 @@ typedef struct {
static float TablesCellsWidth = 300.0f;
static ImGuiTableColumnFlags FlagsTable = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV;
static ImGuiTableColumnFlags FlagsCell = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
static ImGuiTableColumnFlags FlagsCell =
ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
void CosmeticsEditor_RandomizeAll();
void CosmeticsEditor_RandomizeGroup(CosmeticGroup group);
@ -65,6 +67,6 @@ class CosmeticsEditorWindow : public Ship::GuiWindow {
void InitElement() override;
void DrawElement() override;
void ApplyDungeonKeyColors();
void UpdateElement() override {};
void UpdateElement() override{};
};
#endif //__cplusplus

View file

@ -68,9 +68,10 @@ extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToD
gDPSetCycleType(POLY_OPA_DISP++, G_CYC_2CYCLE);
gDPSetRenderMode(POLY_OPA_DISP++, G_RM_XLU_SURF2, G_RM_OPA_CI | CVG_DST_WRAP);
gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, PRIMITIVE, ENV_ALPHA, TEXEL0, 0, 0, 0, TEXEL0, PRIMITIVE, ENVIRONMENT,
COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0);
COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0);
if (CVarGetInteger(CVAR_COSMETIC("Title.NintendoLogo.Changed"), 0)) {
Color_RGB8 nintendoLogoColor = CVarGetColor24(CVAR_COSMETIC("Title.NintendoLogo.Value"), Color_RGB8{0, 0, 255});
Color_RGB8 nintendoLogoColor =
CVarGetColor24(CVAR_COSMETIC("Title.NintendoLogo.Value"), Color_RGB8{ 0, 0, 255 });
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
gDPSetEnvColor(POLY_OPA_DISP++, nintendoLogoColor.r, nintendoLogoColor.g, nintendoLogoColor.b, 128);
} else {
@ -79,16 +80,16 @@ extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToD
}
gDPLoadMultiBlock(POLY_OPA_DISP++, nintendo_rogo_static_Tex_001800, 0x100, 1, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 5, 5, 2, 11);
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 5, 5, 2, 11);
for (idx = 0, y = 94; idx < 16; idx++, y += 2)
{
gDPLoadMultiTile(POLY_OPA_DISP++, (logoToDraw == LOGO_TO_DRAW_N64) ? nintendo_rogo_static_Tex_000000 : nintendo_rogo_static_Tex_LUS_000000, 0, G_TX_RENDERTILE, G_IM_FMT_I, G_IM_SIZ_8b, 192, 32,
0, idx * 2, 192 - 1, (idx + 1) * 2 - 1, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gDPSetTileSize(POLY_OPA_DISP++, 0, 0, 0, (192 - 1) << G_TEXTURE_IMAGE_FRAC,
(2 - 1) << G_TEXTURE_IMAGE_FRAC);
for (idx = 0, y = 94; idx < 16; idx++, y += 2) {
gDPLoadMultiTile(
POLY_OPA_DISP++,
(logoToDraw == LOGO_TO_DRAW_N64) ? nintendo_rogo_static_Tex_000000 : nintendo_rogo_static_Tex_LUS_000000, 0,
G_TX_RENDERTILE, G_IM_FMT_I, G_IM_SIZ_8b, 192, 32, 0, idx * 2, 192 - 1, (idx + 1) * 2 - 1, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gDPSetTileSize(POLY_OPA_DISP++, 0, 0, 0, (192 - 1) << G_TEXTURE_IMAGE_FRAC, (2 - 1) << G_TEXTURE_IMAGE_FRAC);
gDPSetTileSize(POLY_OPA_DISP++, 1, titleContext->uls, (titleContext->ult & 0x7F) - idx * 4, 0, 0);
gSPTextureRectangle(POLY_OPA_DISP++, 388, y << 2, 1156, (y + 2) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
@ -99,13 +100,13 @@ extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToD
f32 scale = 0.4f;
gSPSegment(POLY_OPA_DISP++, 0x08,
(uintptr_t)Gfx_TwoTexScroll(titleContext->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1,
0, (1 * -2) % 128, 32, 32));
(uintptr_t)Gfx_TwoTexScroll(titleContext->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1, 0,
(1 * -2) % 128, 32, 32));
Matrix_Translate(0.0f, -10.0f, 0.0f, MTXMODE_APPLY);
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(titleContext->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPSetEnvColor(POLY_OPA_DISP++, 0, 50, 100, 255);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gEffIceFragment3DL);
}
@ -150,7 +151,7 @@ extern "C" void CustomLogoTitle_Main(TitleContext* titleContext) {
gSaveContext.natureAmbienceId = 0xFF;
gSaveContext.gameMode = GAMEMODE_TITLE_SCREEN;
titleContext->state.running = false;
logosSeen++;
if (CVAR_BOOTSEQUENCE_VALUE == BOOTSEQUENCE_DEFAULT && logosSeen == 1) {
@ -171,7 +172,7 @@ extern "C" void CustomLogoTitle_Main(TitleContext* titleContext) {
// // // //
// Always
//
//
void OnZTitleInitReplaceTitleMainWithCustom(void* gameState) {
TitleContext* titleContext = (TitleContext*)gameState;
@ -198,7 +199,7 @@ static RegisterShipInitFunc initFuncAlways(RegisterCustomLogoTitle);
// // // // // //
// Bootsequence
//
//
void OnZTitleUpdateSkipToFileSelect(void* gameState) {
TitleContext* titleContext = (TitleContext*)gameState;
@ -219,7 +220,7 @@ static RegisterShipInitFunc initFuncBootsequence(RegisterCustomLogoTitleBootsequ
// // // // // //
// Let it Snow
//
//
#define CVAR_LETITSNOW_NAME CVAR_GENERAL("LetItSnow")
#define CVAR_LETITSNOW_DEFAULT 0

View file

@ -19,10 +19,10 @@ void UpdateNoMSPatch() {
bool shouldPatch = (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_MASTER &&
gSaveContext.equips.buttonItems[0] != ITEM_SWORD_BGS &&
gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KNIFE &&
(gSaveContext.equips.buttonItems[0] != ITEM_FISHING_POLE ||
(!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) &&
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) &&
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE))));
(gSaveContext.equips.buttonItems[0] != ITEM_FISHING_POLE ||
(!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) &&
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) &&
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE))));
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_MASTER_SWORD) && shouldPatch) {
// Patching if conditions are met
@ -38,9 +38,12 @@ void UpdateNoMSPatch() {
std::string patchName = "adultNoMS." + std::to_string(3) + "." + std::to_string(i);
ResourceMgr_PatchGfxByName(gLinkAdultMirrorShieldSwordAndSheathFarDL, patchName.c_str(), i, gsDPNoOp());
}
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathNearDL, "adultNoMSHylianShield1", 75, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathFarDL, "adultNoMSHylianShield2", 71, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathNearDL, "adultNoMasterSword1", 2, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathNearDL, "adultNoMSHylianShield1", 75,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathFarDL, "adultNoMSHylianShield2", 71,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathNearDL, "adultNoMasterSword1", 2,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathFarDL, "adultNoMasterSword2", 2, gsSPEndDisplayList());
} else {
// Unpatching if conditions are not met
@ -80,26 +83,27 @@ void RegisterNoMasterSword() {
*should = false;
}
});
// skip post pedestal animation when we don't have a master sword
COND_VB_SHOULD(VB_EXECUTE_PLAYER_STARTMODE_FUNC, IS_RANDO && MASTER_SWORD_SHUFFLED, {
int32_t startMode = va_arg(args, int32_t);
Player* player = GET_PLAYER(gPlayState);
if (startMode == PLAYER_START_MODE_TIME_TRAVEL && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) {
if (startMode == PLAYER_START_MODE_TIME_TRAVEL &&
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) {
// don't run the vanilla startMode func
*should = false;
// position link correctly
Math_Vec3f_Copy(&player->actor.world.pos, &D_808546F4);
player->yaw = player->actor.shape.rot.y = -0x8000;
// execute the idle startMode func
Player_StartMode_Idle(gPlayState, player);
}
});
COND_HOOK(OnPlayerUpdate, IS_RANDO, []{
COND_HOOK(OnPlayerUpdate, IS_RANDO, [] {
static uint16_t lastItemOnB = gSaveContext.equips.buttonItems[0];
if (lastItemOnB != gSaveContext.equips.buttonItems[0]) {
UpdateNoMSPatch();

View file

@ -19,10 +19,8 @@ typedef struct {
} DListPatchInfo;
static DListPatchInfo freezardBodyDListPatchInfos[] = {
{ gFreezardIntactDL, 5 },
{ gFreezardTopRightHornChippedDL, 5 },
{ gFreezardHeadChippedDL, 5 },
{ gFreezardIceTriangleDL, 5 },
{ gFreezardIntactDL, 5 }, { gFreezardTopRightHornChippedDL, 5 },
{ gFreezardHeadChippedDL, 5 }, { gFreezardIceTriangleDL, 5 },
{ gFreezardIceRockDL, 5 },
};
@ -339,7 +337,8 @@ void PatchMirroredSoldOutGI() {
void PatchMirroredSunSongEtching() {
// Only using these strings for graphics patching lookup, we don't need aligned assets here
static const char gRoyalGraveBackRoomDL[] = "__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2DL_005040";
static const char gRoyalGraveBackRoomSongVtx[] = "__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2Vtx_004F80";
static const char gRoyalGraveBackRoomSongVtx[] =
"__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2Vtx_004F80";
static Vtx* mirroredSunSongVtx;
@ -365,7 +364,8 @@ void PatchMirroredSunSongEtching() {
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_1", 13, mirroredSunSongTex[1]);
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_2", 17, mirroredSunSongTex[5]);
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_1", 24, gsSPVertex(mirroredSunSongVtx, 4, 0));
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_1", 24,
gsSPVertex(mirroredSunSongVtx, 4, 0));
// noop as the original vertex command is 128 bit wide
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_2", 25, gsSPNoOp());
} else {

View file

@ -9,11 +9,11 @@ typedef enum {
ENEMYHEALTH_ANCHOR_BOTTOM,
} EnemyHealthBarAnchorType;
typedef enum {
ORIGINAL_LOCATION,
ANCHOR_LEFT,
ANCHOR_RIGHT,
ANCHOR_NONE,
HIDDEN,
typedef enum {
ORIGINAL_LOCATION,
ANCHOR_LEFT,
ANCHOR_RIGHT,
ANCHOR_NONE,
HIDDEN,
ANCHOR_TO_LIFE_METER,
} PosType;

View file

@ -16,35 +16,24 @@ static const std::unordered_map<std::string, char> textBoxSpecialCharacters = {
{ "è", 0x95 }, { "é", 0x96 }, { "ê", 0x97 }, { "ë", 0x98 }, { "ï", 0x99 }, { "ô", 0x9A }, { "ö", 0x9B },
{ "ù", 0x9C }, { "û", 0x9D }, { "ü", 0x9E }
};
static const std::unordered_map<std::string, std::string> percentColors = { { "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN },
{ "b", QM_BLUE }, { "c", QM_LBLUE }, { "p", QM_PINK },
{ "y", QM_YELLOW }, { "B", QM_BLACK }, };
static const std::unordered_map<std::string, std::string> percentColors = {
{ "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN }, { "b", QM_BLUE },
{ "c", QM_LBLUE }, { "p", QM_PINK }, { "y", QM_YELLOW }, { "B", QM_BLACK },
};
static const std::unordered_map<std::string, std::string> colorToPercent = { { QM_WHITE, "%w" }, { QM_RED, "%r"}, { QM_GREEN, "%g" },
{ QM_BLUE, "%b" }, { QM_LBLUE, "%c"}, { QM_PINK, "%p" },
{ QM_YELLOW, "%y" }, { QM_BLACK, "%B" }, };
static const std::unordered_map<std::string, std::string> colorToPercent = {
{ QM_WHITE, "%w" }, { QM_RED, "%r" }, { QM_GREEN, "%g" }, { QM_BLUE, "%b" },
{ QM_LBLUE, "%c" }, { QM_PINK, "%p" }, { QM_YELLOW, "%y" }, { QM_BLACK, "%B" },
};
static const std::unordered_map<std::string, ItemID> altarIcons = {
{ "0", ITEM_KOKIRI_EMERALD },
{ "1", ITEM_GORON_RUBY },
{ "2", ITEM_ZORA_SAPPHIRE },
{ "8", ITEM_MEDALLION_LIGHT },
{ "3", ITEM_MEDALLION_FOREST },
{ "4", ITEM_MEDALLION_FIRE },
{ "5", ITEM_MEDALLION_WATER },
{ "6", ITEM_MEDALLION_SPIRIT },
{ "7", ITEM_MEDALLION_SHADOW },
{ "l", ITEM_ARROW_LIGHT },
{ "b", ITEM_KEY_BOSS },
{ "o", ITEM_SWORD_MASTER },
{ "c", ITEM_OCARINA_FAIRY },
{ "i", ITEM_OCARINA_TIME },
{ "L", ITEM_BOW_ARROW_LIGHT },
{ "k", ITEM_TUNIC_KOKIRI },
{ "m", ITEM_DUNGEON_MAP },
{ "C", ITEM_COMPASS },
{ "s", ITEM_SKULL_TOKEN },
{ "g", ITEM_MASK_GORON },
{ "0", ITEM_KOKIRI_EMERALD }, { "1", ITEM_GORON_RUBY }, { "2", ITEM_ZORA_SAPPHIRE },
{ "8", ITEM_MEDALLION_LIGHT }, { "3", ITEM_MEDALLION_FOREST }, { "4", ITEM_MEDALLION_FIRE },
{ "5", ITEM_MEDALLION_WATER }, { "6", ITEM_MEDALLION_SPIRIT }, { "7", ITEM_MEDALLION_SHADOW },
{ "l", ITEM_ARROW_LIGHT }, { "b", ITEM_KEY_BOSS }, { "o", ITEM_SWORD_MASTER },
{ "c", ITEM_OCARINA_FAIRY }, { "i", ITEM_OCARINA_TIME }, { "L", ITEM_BOW_ARROW_LIGHT },
{ "k", ITEM_TUNIC_KOKIRI }, { "m", ITEM_DUNGEON_MAP }, { "C", ITEM_COMPASS },
{ "s", ITEM_SKULL_TOKEN }, { "g", ITEM_MASK_GORON },
};
static std::map<std::string, int> pixelWidthTable = {
@ -77,14 +66,15 @@ static std::map<std::string, int> pixelWidthTable = {
CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, TextBoxType type_,
TextBoxPosition position_)
: type(type_), position(position_){
: type(type_), position(position_) {
messages[LANGUAGE_ENG] = std::move(english_);
messages[LANGUAGE_GER] = std::move(german_);
messages[LANGUAGE_FRA] = std::move(french_);
}
CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, std::vector<std::string> colors_,
std::vector<bool> capital_, TextBoxType type_, TextBoxPosition position_) {
CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_,
std::vector<std::string> colors_, std::vector<bool> capital_, TextBoxType type_,
TextBoxPosition position_) {
messages[LANGUAGE_ENG] = std::move(english_);
messages[LANGUAGE_GER] = std::move(german_);
messages[LANGUAGE_FRA] = std::move(french_);
@ -99,7 +89,8 @@ CustomMessage::CustomMessage(std::string english_, TextBoxType type_, TextBoxPos
messages[LANGUAGE_ENG] = std::move(english_);
}
CustomMessage::CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_, TextBoxType type_, TextBoxPosition position_){
CustomMessage::CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_,
TextBoxType type_, TextBoxPosition position_) {
messages[LANGUAGE_ENG] = std::move(english_);
colors = colors_;
capital = capital_;
@ -107,7 +98,7 @@ CustomMessage::CustomMessage(std::string english_, std::vector<std::string> colo
position = position_;
}
CustomMessage::CustomMessage(Text text, TextBoxType type_,TextBoxPosition position_)
CustomMessage::CustomMessage(Text text, TextBoxType type_, TextBoxPosition position_)
: type(type_), position(position_) {
messages[LANGUAGE_ENG] = text.GetEnglish();
messages[LANGUAGE_GER] = text.GetGerman();
@ -141,7 +132,7 @@ CustomMessage CustomMessage::LoadVanillaMessageTableEntry(uint16_t textId) {
TextBoxPosition position = static_cast<TextBoxPosition>(msgEntry->typePos & 0xF);
TextBoxType type = static_cast<TextBoxType>(msgEntry->typePos >> 4);
// uint8_t icon = msgEntry->segment[1];
std::string message = std::string(msgEntry->segment , msgEntry->msgSize);
std::string message = std::string(msgEntry->segment, msgEntry->msgSize);
msg = CustomMessage(message, type, position);
// msg.Format(static_cast<ItemID>(icon));
return msg;
@ -151,7 +142,6 @@ CustomMessage CustomMessage::LoadVanillaMessageTableEntry(uint16_t textId) {
return CustomMessage();
}
const std::string CustomMessage::GetEnglish(MessageFormat format) const {
return GetForLanguage(LANGUAGE_ENG, format);
}
@ -174,22 +164,22 @@ const std::string CustomMessage::GetForLanguage(uint8_t language, MessageFormat
return output;
}
const std::vector<std::string> CustomMessage::GetAllMessages(MessageFormat format) const{
const std::vector<std::string> CustomMessage::GetAllMessages(MessageFormat format) const {
std::vector<std::string> output = messages;
for (auto str : output){
for (auto str : output) {
ProcessMessageFormat(str, format);
}
return output;
}
void CustomMessage::ProcessMessageFormat(std::string& str, MessageFormat format) const {
if (format == MF_FORMATTED){
if (format == MF_FORMATTED) {
FormatString(str);
} else if (format == MF_CLEAN){
} else if (format == MF_CLEAN) {
CleanString(str);
} else if (format == MF_AUTO_FORMAT){
} else if (format == MF_AUTO_FORMAT) {
AutoFormatString(str);
}else if (format == MF_ENCODE){
} else if (format == MF_ENCODE) {
EncodeColors(str);
}
}
@ -198,14 +188,14 @@ const std::vector<bool>& CustomMessage::GetCapital() const {
return capital;
}
void CustomMessage::SetCapital(std::vector<bool> capital_){
void CustomMessage::SetCapital(std::vector<bool> capital_) {
capital = capital_;
}
const std::vector<std::string>& CustomMessage::GetColors() const {
return colors;
}
void CustomMessage::SetColors(std::vector<std::string> colors_){
void CustomMessage::SetColors(std::vector<std::string> colors_) {
colors = colors_;
}
@ -213,7 +203,7 @@ const TextBoxType& CustomMessage::GetTextBoxType() const {
return type;
}
void CustomMessage::SetTextBoxType(TextBoxType boxType){
void CustomMessage::SetTextBoxType(TextBoxType boxType) {
type = boxType;
}
@ -224,19 +214,19 @@ const TextBoxPosition& CustomMessage::GetTextBoxPosition() const {
CustomMessage CustomMessage::operator+(const CustomMessage& right) const {
std::vector<std::string> newColors = colors;
std::vector<std::string> rColors = right.GetColors();
for (auto color: rColors){
for (auto color : rColors) {
newColors.push_back(color);
}
std::vector<bool> newCapital = capital;
newCapital.insert(newCapital.end(), right.GetCapital().begin(), right.GetCapital().end());
return CustomMessage(messages[LANGUAGE_ENG] + right.GetEnglish(MF_RAW),
messages[LANGUAGE_GER] + right.GetGerman(MF_RAW),
messages[LANGUAGE_FRA] + right.GetFrench(MF_RAW),
newColors, newCapital, type, position);
messages[LANGUAGE_FRA] + right.GetFrench(MF_RAW), newColors, newCapital, type, position);
}
CustomMessage CustomMessage::operator+(const std::string& right) const {
return CustomMessage(messages[LANGUAGE_ENG] + right, messages[LANGUAGE_GER] + right, messages[LANGUAGE_FRA] + right);
return CustomMessage(messages[LANGUAGE_ENG] + right, messages[LANGUAGE_GER] + right,
messages[LANGUAGE_FRA] + right);
}
void CustomMessage::operator+=(const CustomMessage& right) {
@ -258,8 +248,8 @@ bool CustomMessage::operator==(const CustomMessage& operand) const {
}
bool CustomMessage::operator==(const std::string& operand) const {
for (auto str: messages){
if (str == operand){
for (auto str : messages) {
if (str == operand) {
return true;
}
}
@ -291,7 +281,7 @@ void CustomMessage::Replace(std::string&& oldStr, CustomMessage newMessage) {
}
void CustomMessage::Format(ItemID iid) {
for (std::string &str : messages) {
for (std::string& str : messages) {
str.insert(0, ITEM_OBTAINED(iid));
size_t start_pos = 0;
std::replace(str.begin(), str.end(), '&', NEWLINE()[0]);
@ -341,7 +331,7 @@ void CustomMessage::FormatString(std::string& str) const {
str += MESSAGE_END();
}
void DeleteControlCode(std::string& str, std::string code){
void DeleteControlCode(std::string& str, std::string code) {
size_t start_pos = 0;
while ((start_pos = str.find(code, start_pos)) != std::string::npos) {
str.replace(start_pos, code.length(), "");
@ -362,56 +352,57 @@ void CustomMessage::CleanString(std::string& str) const {
}
static size_t NextLineLength(const std::string* textStr, const size_t lastNewline, bool hasIcon = false) {
const size_t maxLinePixelWidth = hasIcon ? 200 : 216;
const size_t maxLinePixelWidth = hasIcon ? 200 : 216;
size_t totalPixelWidth = 0;
size_t currentPos = lastNewline;
size_t totalPixelWidth = 0;
size_t currentPos = lastNewline;
// Looping through the string from the lastNewline until the total
// width of counted characters exceeds the maximum pixels in a line.
size_t nextPosJump = 0;
while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) {
// Skip over control codes
if (textStr->at(currentPos) == '%') {
nextPosJump = 2;
} else if (textStr->at(currentPos) == '$') {
nextPosJump = 2;
} else if (textStr->at(currentPos) == '@') {
nextPosJump = 1;
// Assume worst case for player name 12 * 8 (widest character * longest name length)
totalPixelWidth += 96;
} else if (textStr->at(currentPos) == '\x05') {
// Skip colour control characters.
nextPosJump = 2;
} else if (textStr->at(currentPos) == '\x1E') {
//For the high score char, we have to take the next Char, then use that to get a worst case scenario.
if (textStr->at(currentPos+1) == '\x01'){
totalPixelWidth += 28;
}
nextPosJump = 2;
} else {
// Some characters only one byte while others are two bytes
// So check both possibilities when checking for a character
if (pixelWidthTable.count(textStr->substr(currentPos, 1))) {
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)];
nextPosJump = 1;
} else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) {
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)];
nextPosJump = 2;
} else {
SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + textStr->substr(currentPos, 2));
SPDLOG_DEBUG("Full string: " + *textStr);
nextPosJump = 1;
}
// Looping through the string from the lastNewline until the total
// width of counted characters exceeds the maximum pixels in a line.
size_t nextPosJump = 0;
while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) {
// Skip over control codes
if (textStr->at(currentPos) == '%') {
nextPosJump = 2;
} else if (textStr->at(currentPos) == '$') {
nextPosJump = 2;
} else if (textStr->at(currentPos) == '@') {
nextPosJump = 1;
// Assume worst case for player name 12 * 8 (widest character * longest name length)
totalPixelWidth += 96;
} else if (textStr->at(currentPos) == '\x05') {
// Skip colour control characters.
nextPosJump = 2;
} else if (textStr->at(currentPos) == '\x1E') {
// For the high score char, we have to take the next Char, then use that to get a worst case scenario.
if (textStr->at(currentPos + 1) == '\x01') {
totalPixelWidth += 28;
}
nextPosJump = 2;
} else {
// Some characters only one byte while others are two bytes
// So check both possibilities when checking for a character
if (pixelWidthTable.count(textStr->substr(currentPos, 1))) {
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)];
nextPosJump = 1;
} else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) {
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)];
nextPosJump = 2;
} else {
SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" +
textStr->substr(currentPos, 2));
SPDLOG_DEBUG("Full string: " + *textStr);
nextPosJump = 1;
}
}
currentPos += nextPosJump;
}
// return the total number of characters we looped through
if (totalPixelWidth > maxLinePixelWidth && textStr->at(currentPos - nextPosJump) != ' ') {
return currentPos - lastNewline - nextPosJump;
} else {
return currentPos - lastNewline;
}
currentPos += nextPosJump;
}
// return the total number of characters we looped through
if (totalPixelWidth > maxLinePixelWidth && textStr->at(currentPos - nextPosJump) != ' ') {
return currentPos - lastNewline - nextPosJump;
} else {
return currentPos - lastNewline;
}
}
size_t CustomMessage::FindNEWLINE(std::string& str, size_t lastNewline) const {
@ -488,19 +479,19 @@ void CustomMessage::AutoFormatString(std::string& str) const {
const size_t lastSpace = str.rfind(' ', lastNewline + lineLength);
size_t waitForInput = str.find(WAIT_FOR_INPUT()[0], lastNewline);
size_t newLine = FindNEWLINE(str, lastNewline);
if (carrot < waitForInput){
if (carrot < waitForInput) {
waitForInput = carrot;
}
if (ampersand < newLine){
if (ampersand < newLine) {
newLine = ampersand;
}
if (lineCount != 3 && yesNo < lastNewline + lineLength && yesNo < waitForInput && yesNo < newLine){
if (lineCount >= 4){
if (lineCount != 3 && yesNo < lastNewline + lineLength && yesNo < waitForInput && yesNo < newLine) {
if (lineCount >= 4) {
str.replace(yesNo, 1, "^&&\x1B");
lineCount = 3;
lastNewline = yesNo + 3;
} else {
while(lineCount < 3){
while (lineCount < 3) {
str.replace(yesNo, 1, "&\x1B");
yesNo++;
lineCount++;
@ -508,7 +499,7 @@ void CustomMessage::AutoFormatString(std::string& str) const {
lastNewline = yesNo;
}
} else {
if (lineCount < 4){
if (lineCount < 4) {
// replace '&' first if it's within the newline range
if (newLine < lastNewline + lineLength) {
lastNewline = newLine + 1;
@ -526,12 +517,12 @@ void CustomMessage::AutoFormatString(std::string& str) const {
lastNewline = lastSpace + 1;
}
lineCount += 1;
} else {
} else {
const size_t lastColor = str.rfind("\x05"s, lastNewline + lineLength);
std::string colorText = "";
//check if we are on a non default colour, as ^ resets it, and readd if needed
if (lastColor != std::string::npos && str[lastColor+1] != 0){
colorText = "\x05"s + str[lastColor+1];
// check if we are on a non default colour, as ^ resets it, and readd if needed
if (lastColor != std::string::npos && str[lastColor + 1] != 0) {
colorText = "\x05"s + str[lastColor + 1];
}
// replace '&' first if it's within the newline range
if (ampersand < lastNewline + lineLength) {
@ -564,7 +555,7 @@ void CustomMessage::AutoFormatString(std::string& str) const {
str += MESSAGE_END();
}
void CustomMessage::InsertNumber(uint8_t num){
void CustomMessage::InsertNumber(uint8_t num) {
for (std::string& str : messages) {
size_t firstBar = str.find('|');
if (firstBar != std::string::npos) {
@ -581,12 +572,11 @@ void CustomMessage::InsertNumber(uint8_t num){
}
}
}
//remove the remaining bar
// remove the remaining bar
this->Replace("|", "");
Replace("[[d]]", std::to_string(num));
}
void CustomMessage::Capitalize() {
for (std::string str : messages) {
(str)[0] = std::toupper((str)[0]);
@ -625,7 +615,7 @@ const char* Interface_ReplaceSpecialCharacters(char text[]) {
}
void CustomMessage::EncodeColors(std::string& str) const {
for (std::string color: colors) {
for (std::string color : colors) {
if (const size_t firstHashtag = str.find('#'); firstHashtag != std::string::npos) {
str.replace(firstHashtag, 1, colorToPercent.at(color));
if (const size_t secondHashtag = str.find('#', firstHashtag + 1); secondHashtag != std::string::npos) {
@ -664,13 +654,13 @@ void CustomMessage::ReplaceAltarIcons(std::string& str) const {
}
}
void CustomMessage::InsertNames(std::vector<CustomMessage> toInsert){
for(uint8_t a = 0; a < toInsert.size(); a++){
void CustomMessage::InsertNames(std::vector<CustomMessage> toInsert) {
for (uint8_t a = 0; a < toInsert.size(); a++) {
CustomMessage temp = toInsert[a];
if ((capital.size() > a) && (capital[a] = true)){
if ((capital.size() > a) && (capital[a] = true)) {
temp.Capitalize();
}
Replace("[[" + std::to_string(a+1) + "]]", temp);
}
Replace("[[" + std::to_string(a + 1) + "]]", temp);
}
}
@ -735,16 +725,16 @@ CustomMessage CustomMessageManager::RetrieveMessage(std::string tableID, uint16_
}
CustomMessage message = foundMessage->second;
if (format == MF_FORMATTED){
if (format == MF_FORMATTED) {
message.Format();
} else if (format == MF_AUTO_FORMAT){
} else if (format == MF_AUTO_FORMAT) {
message.AutoFormat();
} else if (format == MF_CLEAN){
} else if (format == MF_CLEAN) {
message.Clean();
} else if (format == MF_ENCODE){
} else if (format == MF_ENCODE) {
message.Encode();
}
return message;
}
@ -758,7 +748,7 @@ bool CustomMessageManager::ClearMessageTable(std::string tableID) {
return true;
}
bool CustomMessageManager::AddCustomMessageTable(std::string tableID) {
bool CustomMessageManager::AddCustomMessageTable(std::string tableID) {
CustomMessageTable newMessageTable;
return messageTables.emplace(tableID, newMessageTable).second;
}

View file

@ -20,7 +20,7 @@
#define QM_YELLOW "\x46"
#define QM_BLACK "\x47"
#define HS_HORSE_ARCHERY "\x00"s //HS_HBA is an enum already
#define HS_HORSE_ARCHERY "\x00"s // HS_HBA is an enum already
typedef enum {
MF_FORMATTED,
@ -41,21 +41,24 @@ class CustomMessage {
CustomMessage() = default;
CustomMessage(std::string english_, std::string german_, std::string french_,
TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, std::string german_, std::string french_, std::vector<std::string> colors_, std::vector<bool> capital_ = {},
TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_ = {}, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, std::string german_, std::string french_, std::vector<std::string> colors_,
std::vector<bool> capital_ = {}, TextBoxType type_ = TEXTBOX_TYPE_BLACK,
TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK,
TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_ = {},
TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
static CustomMessage LoadVanillaMessageTableEntry(uint16_t textId);
static std::string MESSAGE_END() ;
static std::string ITEM_OBTAINED(uint8_t x) ;
static std::string NEWLINE() ;
static std::string COLOR(std::string x) ;
static std::string POINTS(std::string x) ;//HIGH_SCORE is also a macro
static std::string WAIT_FOR_INPUT() ;
static std::string PLAYER_NAME() ;
static std::string MESSAGE_END();
static std::string ITEM_OBTAINED(uint8_t x);
static std::string NEWLINE();
static std::string COLOR(std::string x);
static std::string POINTS(std::string x); // HIGH_SCORE is also a macro
static std::string WAIT_FOR_INPUT();
static std::string PLAYER_NAME();
const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const;
const std::string GetFrench(MessageFormat format = MF_FORMATTED) const;
@ -157,13 +160,13 @@ class CustomMessage {
void Format();
/**
* @brief formats the message specifically to fit in OoT's
* @brief formats the message specifically to fit in OoT's
* textboxes, and use it's formatting.
*/
void AutoFormat();
/**
* @brief Removes all OoT formatting from the message,
* @brief Removes all OoT formatting from the message,
* making it a good form for writing into spoiler logs.
*/
void Clean();
@ -179,15 +182,15 @@ class CustomMessage {
* . i.e. special characters, colors, newlines, wait for input, etc.
*/
void FormatString(std::string& str) const;
/**
* @brief finds NEWLINEs in a string, while filtering
* /x01's that are used as opperands
*/
size_t FindNEWLINE(std::string& str, size_t lastNewline) const;
/**
* @brief formats the string specifically to fit in OoT's
* @brief formats the string specifically to fit in OoT's
* textboxes, and use it's formatting.
* RANDOTODO whoever knows exactly what this does check my adaption
*/
@ -200,7 +203,7 @@ class CustomMessage {
void CleanString(std::string& str) const;
private:
std::vector<std::string> messages = {"","",""};
std::vector<std::string> messages = { "", "", "" };
TextBoxType type = TEXTBOX_TYPE_BLACK;
TextBoxPosition position = TEXTBOX_POS_BOTTOM;
std::vector<std::string> colors = {};

View file

@ -11,7 +11,7 @@ typedef enum {
TEXT_SKULLTULA_PEOPLE_STARTING_TO_WEAKEN = 0x0024,
TEXT_SKULLTULA_PEOPLE_WE_LOOK_LIKE_THIS = 0x0025,
TEXT_SKULLTULA_PEOPLE_GS_TUTORIAL = 0x0026,
TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH = 0x0027,
TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH = 0x0027,
TEXT_SKULLTULA_PEOPLE_CURSE_HAS_BEEN_BROKEN = 0x0028,
TEXT_SKULLTULA_PEOPLE_SAVING_MY_KIDS = 0x0029,
TEXT_ITEM_KEY_SMALL = 0x0060,
@ -96,7 +96,7 @@ typedef enum {
TEXT_MALON_HOW_IS_EPONA_DOING = 0x2001,
TEXT_MALON_EPONA_LOOKS_GREAT = 0x2002,
TEXT_MALON_OBSTICLE_COURSE = 0x2003,
TEXT_MALON_EVERYONE_TURNING_EVIL = 0x204C,
TEXT_MALON_EVERYONE_TURNING_EVIL = 0x204C,
TEXT_MALON_I_SING_THIS_SONG = 0x2050,
TEXT_MALON_EVERYONE_LIKED_SONG = 0x2051,
TEXT_MALON_EPONA_LIKED_SONG = 0x2052,
@ -211,6 +211,6 @@ typedef struct {
{ giid, iid, message, message, message }
#define GIMESSAGE_NO_GERMAN(giid, iid, english, french) \
{ giid, iid, english, english, french }
{ giid, iid, english, english, french }
#endif

File diff suppressed because it is too large Load diff

View file

@ -29,7 +29,8 @@ void MessageViewer::DrawElement() {
ImGui::Text("Table ID");
ImGui::SameLine();
PushStyleInput(THEME_COLOR);
ImGui::InputText("##TableID", mTableIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum);
ImGui::InputText("##TableID", mTableIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter,
UIWidgets::TextFilters::FilterAlphaNum);
UIWidgets::InsertHelpHoverText("Leave blank for vanilla table");
ImGui::Text("Text ID");
ImGui::SameLine();
@ -41,7 +42,8 @@ void MessageViewer::DrawElement() {
case HEXADECIMAL:
default:
ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsHexadecimal);
UIWidgets::InsertHelpHoverText("Hexadecimal Text ID of the message to load. Hexadecimal digits only (0-9/A-F).");
UIWidgets::InsertHelpHoverText(
"Hexadecimal Text ID of the message to load. Hexadecimal digits only (0-9/A-F).");
break;
}
PopStyleInput();
@ -169,8 +171,7 @@ void FindMessage(PlayState* play, const uint16_t textId, const uint8_t language)
font->msgLength = nextSeg - foundSeg;
}
static const char* msgStaticTbl[] =
{
static const char* msgStaticTbl[] = {
gDefaultMessageBackgroundTex,
gSignMessageBackgroundTex,
gNoteStaffMessageBackgroundTex,
@ -201,13 +202,14 @@ void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t lan
FindMessage(play, textId, language);
msgCtx->msgLength = static_cast<int32_t>(font->msgLength);
const uintptr_t src = font->msgOffset;
memcpy(font->msgBuf, reinterpret_cast<void const *>(src), font->msgLength);
memcpy(font->msgBuf, reinterpret_cast<void const*>(src), font->msgLength);
} else {
constexpr int maxBufferSize = sizeof(font->msgBuf);
const CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(tableId, textId);
font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition();
switch (language) {
font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetForLanguage(language), maxBufferSize);
font->msgLength =
SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetForLanguage(language), maxBufferSize);
}
msgCtx->msgLength = static_cast<int32_t>(font->msgLength);
}
@ -258,8 +260,6 @@ void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t lan
void MessageDebug_DisplayCustomMessage(const char* customMessage) {
CustomMessageManager::Instance->ClearMessageTable(MessageViewer::TABLE_ID);
CustomMessageManager::Instance->CreateMessage(MessageViewer::TABLE_ID, 0,
CustomMessage(customMessage, customMessage, customMessage));
CustomMessage(customMessage, customMessage, customMessage));
MessageDebug_StartTextBox(MessageViewer::TABLE_ID, 0, 0);
}

View file

@ -25,9 +25,8 @@ void MessageDebug_DisplayCustomMessage(const char* customMessage);
#ifdef __cplusplus
}
class MessageViewer : public Ship::GuiWindow {
public:
public:
static inline const char* TABLE_ID = "MessageViewer";
using GuiWindow::GuiWindow;
@ -37,12 +36,12 @@ public:
virtual ~MessageViewer() = default;
private:
private:
void DisplayExistingMessage() const;
void DisplayCustomMessage() const;
static constexpr uint16_t MAX_STRING_SIZE = 1024;
static constexpr std::array<const char*, LANGUAGE_MAX> mLanguages = {"English", "German", "French"};
static constexpr std::array<const char*, LANGUAGE_MAX> mLanguages = { "English", "German", "French" };
static constexpr int HEXADECIMAL = 0;
static constexpr int DECIMAL = 1;
char* mTableIdBuf;
@ -57,6 +56,5 @@ private:
bool mDisplayCustomMessageClicked = false;
};
#endif //__cplusplus
#endif //CUSTOMMESSAGEDEBUGGER_H
#endif // CUSTOMMESSAGEDEBUGGER_H

View file

@ -6,12 +6,12 @@
class SohStatsWindow : public Ship::GuiWindow {
public:
using GuiWindow::GuiWindow;
~SohStatsWindow() {};
~SohStatsWindow(){};
protected:
void InitElement() override {};
void InitElement() override{};
void DrawElement() override;
void UpdateElement() override {};
void UpdateElement() override{};
};
#endif // SOH_STATS_H

View file

@ -45,19 +45,13 @@ typedef enum {
INTERACT,
} RetrievalMethod;
std::array<const char*, 12> acMapping = {
"Switch",
"Background (Prop type 1)",
"Player",
"Bomb",
"NPC",
"Enemy",
"Prop type 2",
"Item/Action",
"Misc.",
"Boss",
"Door",
"Chest",
std::array<const char*, 12> acMapping = {
"Switch", "Background (Prop type 1)",
"Player", "Bomb",
"NPC", "Enemy",
"Prop type 2", "Item/Action",
"Misc.", "Boss",
"Door", "Chest",
};
using namespace UIWidgets;
@ -76,7 +70,8 @@ const std::string GetActorDescription(u16 id) {
template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) {
// First group encapsulates the inner portion and border
ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0),
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY);
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeX |
ImGuiChildFlags_AutoResizeY);
// Second group encapsulates just the inner portion
ImGui::BeginGroup();
@ -103,7 +98,7 @@ void PopulateActorDropdown(int i, std::vector<Actor*>& data) {
}
}
//actors that don't use params at all
// actors that don't use params at all
static std::vector<u16> noParamsActors = {
ACTOR_ARMS_HOOK,
ACTOR_ARROW_FIRE,
@ -250,7 +245,7 @@ void CreateActorSpecificData() {
if (!isFlower) {
ImGui::InputScalar("Shots Per Round", ImGuiDataType_S16, &shotsPerRound);
}
return isFlower ? DEKUNUTS_FLOWER : (shotsPerRound << 8);
};
@ -259,12 +254,12 @@ void CreateActorSpecificData() {
if (params == 0) {
params = -2;
}
//the + 2 is because the params are -2 & -1 instead of 0 & 1
// the + 2 is because the params are -2 & -1 instead of 0 & 1
int selectedItem = params + 2;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem - 2;
}
return params;
};
@ -274,7 +269,7 @@ void CreateActorSpecificData() {
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
@ -284,7 +279,7 @@ void CreateActorSpecificData() {
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
@ -294,7 +289,7 @@ void CreateActorSpecificData() {
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
@ -304,7 +299,7 @@ void CreateActorSpecificData() {
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
@ -314,7 +309,7 @@ void CreateActorSpecificData() {
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
@ -324,7 +319,7 @@ void CreateActorSpecificData() {
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
@ -333,12 +328,12 @@ void CreateActorSpecificData() {
if (params == 0) {
params = 0x40;
}
//the - 0x40 is because the params are 0x40 & 0x41 instead of 0 & 1
// the - 0x40 is because the params are 0x40 & 0x41 instead of 0 & 1
int selectedItem = params - 0x40;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem + 0x40;
}
return params;
};
@ -348,21 +343,21 @@ void CreateActorSpecificData() {
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
actorSpecificData[ACTOR_EN_REEBA] = [](s16 params) -> s16 {
bool isBig = params != 0;
ImGui::Checkbox("Big", &isBig);
return isBig;
};
actorSpecificData[ACTOR_EN_TK] = [](s16 params) -> s16 {
bool canTurn = params >= 0;
ImGui::Checkbox("Can Turn", &canTurn);
return canTurn ? 0 : -1;
};
@ -374,35 +369,13 @@ void CreateActorSpecificData() {
if (collectibleFlag > 0x3F) {
collectibleFlag = 0x3F;
}
static const char* items[] = {
"Green Rupee",
"Blue Rupee",
"Red Rupee",
"Recovery Heart",
"Bombs (A)",
"Arrow",
"Heart Piece",
"Heart Container",
"Arrows (5)",
"Arrows (10)",
"Arrows (30)",
"Bombs (B)",
"Deku Nuts (5)",
"Deku Stick",
"Magic (Large)",
"Magic (Small)",
"Deku Seeds (5)",
"Small Key",
"Flexible",
"Gold Rupee",
"Purple Rupee",
"Deku Shield",
"Hylian Shield",
"Zora Tunic",
"Goron Tunic",
"Bombs (Special)",
"Bombchus",
"Green Rupee", "Blue Rupee", "Red Rupee", "Recovery Heart", "Bombs (A)", "Arrow",
"Heart Piece", "Heart Container", "Arrows (5)", "Arrows (10)", "Arrows (30)", "Bombs (B)",
"Deku Nuts (5)", "Deku Stick", "Magic (Large)", "Magic (Small)", "Deku Seeds (5)", "Small Key",
"Flexible", "Gold Rupee", "Purple Rupee", "Deku Shield", "Hylian Shield", "Zora Tunic",
"Goron Tunic", "Bombs (Special)", "Bombchus",
};
int selectedItem = params & 0xFF;
@ -413,33 +386,11 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_OBJ_COMB] = [](s16 params) -> s16 {
static const char* items[] = {
"Green Rupee",
"Blue Rupee",
"Red Rupee",
"Recovery Heart",
"Bombs (A)",
"Arrow",
"Heart Piece",
"Heart Container",
"Arrows (5)",
"Arrows (10)",
"Arrows (30)",
"Bombs (B)",
"Deku Nuts (5)",
"Deku Stick",
"Magic (Large)",
"Magic (Small)",
"Deku Seeds (5)",
"Small Key",
"Flexible",
"Gold Rupee",
"Purple Rupee",
"Deku Shield",
"Hylian Shield",
"Zora Tunic",
"Goron Tunic",
"Bombs (Special)",
"Bombchus",
"Green Rupee", "Blue Rupee", "Red Rupee", "Recovery Heart", "Bombs (A)", "Arrow",
"Heart Piece", "Heart Container", "Arrows (5)", "Arrows (10)", "Arrows (30)", "Bombs (B)",
"Deku Nuts (5)", "Deku Stick", "Magic (Large)", "Magic (Small)", "Deku Seeds (5)", "Small Key",
"Flexible", "Gold Rupee", "Purple Rupee", "Deku Shield", "Hylian Shield", "Zora Tunic",
"Goron Tunic", "Bombs (Special)", "Bombchus",
};
int selectedItem = params & 0xFF;
@ -452,18 +403,18 @@ void CreateActorSpecificData() {
collectibleFlag = 0x3F;
}
}
return (collectibleFlag << 8) + selectedItem;
};
actorSpecificData[ACTOR_EN_GM] = [](s16 params) -> s16 {
u8 switchFlag = (params & 0x3F00) >> 8;
ImGui::InputScalar("Switch Flag", ImGuiDataType_U8, &switchFlag);
if (switchFlag > 0x3F) {
switchFlag = 0x3F;
}
return switchFlag << 8;
};
@ -525,7 +476,7 @@ void CreateActorSpecificData() {
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
@ -543,7 +494,7 @@ void CreateActorSpecificData() {
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem > 3 ? selectedItem + 1 : selectedItem;
}
return params;
};
@ -574,113 +525,102 @@ void CreateActorSpecificData() {
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
actorSpecificData[ACTOR_EN_ELF] = [](s16 params) -> s16 {
static const char* items[] = {
"Navi",
"Revive Bottle",
"Heal Timed",
"Kokiri",
"Spawner",
"Revive Death",
"Heal",
"Heal Big",
"Navi", "Revive Bottle", "Heal Timed", "Kokiri", "Spawner", "Revive Death", "Heal", "Heal Big",
};
int selectedItem = params;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
actorSpecificData[ACTOR_EN_CLEAR_TAG] = [](s16 params) -> s16 {
static const char* items[] = {
"Cutscene", //0
"Normal", //1
"Laser", //100
"Cutscene", // 0
"Normal", // 1
"Laser", // 100
};
int selectedItem = params == 100 ? 2 : params;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem == 2 ? 100 : selectedItem;
}
return params;
};
actorSpecificData[ACTOR_EN_BOMBF] = [](s16 params) -> s16 {
static const char* items[] = { "Flower", "Body", "Explosion" };
//the + 1 is because the params are -1, 0 & 1 instead of 0, 1 & 2
// the + 1 is because the params are -1, 0 & 1 instead of 0, 1 & 2
int selectedItem = params + 1;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem - 1;
}
return params;
};
actorSpecificData[ACTOR_EN_BOM] = [](s16 params) -> s16 {
static const char* items[] = { "Body", "Explosion" };
int selectedItem = params;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
actorSpecificData[ACTOR_DOOR_WARP1] = [](s16 params) -> s16 {
static const char* items[] = {
"Blue Crystal", // -2
"Dungeon Adult",
"Dungeon Child",
"Clear Flag", // Activate on temp clear flag
"Sages", // Used by sages warping into chamber of sages during their cutscene
"Blue Crystal", // -2
"Dungeon Adult", "Dungeon Child",
"Clear Flag", // Activate on temp clear flag
"Sages", // Used by sages warping into chamber of sages during their cutscene
"Purple Crystal",
"Yellow", // The colored variants don't warp, they are cutscene setpieces
"Yellow", // The colored variants don't warp, they are cutscene setpieces
"Blue Ruto",
"Destination", // Spawning in after having taken a warp
"UNK 7",
"Orange",
"Green",
"Red",
"Destination", // Spawning in after having taken a warp
"UNK 7", "Orange", "Green", "Red",
};
int selectedItem = params + 2;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem - 2;
}
return params;
};
actorSpecificData[ACTOR_EN_DY_EXTRA] = [](s16 params) -> s16 {
static const char* items[] = { "Orange", "Green" };
int selectedItem = params;
if (ImGui::Combo("Color", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
actorSpecificData[ACTOR_EN_SKB] = [](s16 params) -> s16 {
u8 size = params;
ImGui::InputScalar("Size", ImGuiDataType_U8, &size);
return size;
};
actorSpecificData[ACTOR_EN_WF] = [](s16 params) -> s16 {
static const char* items[] = { "Normal", "White" };
int selectedItem = params;
ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items));
u8 switchFlag = (params & 0x3F00) >> 8;
ImGui::InputScalar("Switch Flag", ImGuiDataType_U8, &switchFlag);
return (switchFlag << 8) + selectedItem;
@ -703,7 +643,7 @@ void CreateActorSpecificData() {
if (itemId > 0x7F) {
itemId = 0x7F;
}
static const char* items[] = {
"Big (Default)",
"Room Clear Big",
@ -751,7 +691,7 @@ void CreateActorSpecificData() {
if (transitionIndex > 0x3F) {
transitionIndex = 0x3F;
}
static const char* items[] = {
"Room Load", // loads rooms
"Locked", // small key locked door
@ -792,9 +732,9 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_EN_PO_DESERT] = [](s16 params) -> s16 {
u8 switchFlag = params >> 8;
ImGui::InputScalar("Path", ImGuiDataType_U8, &switchFlag);
return switchFlag << 8;
};
@ -807,30 +747,26 @@ void CreateActorSpecificData() {
if (ImGui::Checkbox("Fishing Sign", &fishingSign)) {
piece = false;
}
u8 textId = params;
if (!piece && !fishingSign) {
if (ImGui::InputScalar("Text ID", ImGuiDataType_U8, &textId)) {
textId |= 0x300;
}
}
return piece ? (s16)0xFFDD : (fishingSign ? 0x300 : textId);
};
actorSpecificData[ACTOR_EN_KUSA] = [](s16 params) -> s16 {
static const char* items[] = {
"0",
"1",
"2"
};
static const char* items[] = { "0", "1", "2" };
int type = params & 3;
ImGui::Combo("Type", &type, items, IM_ARRAYSIZE(items));
bool bugs = ((params >> 4) & 1) != 0;
ImGui::Checkbox("Bugs", &bugs);
u8 drop = (params >> 8) & 0xF;
if (type == 2) {
ImGui::InputScalar("Random Drop Params", ImGuiDataType_U8, &drop);
@ -845,17 +781,12 @@ void CreateActorSpecificData() {
};
actorSpecificData[ActorDB::Instance->RetrieveId("En_Partner")] = [](s16 params) -> s16 {
static const char* items[] = {
"Port 1",
"Port 2",
"Port 3",
"Port 4"
};
static const char* items[] = { "Port 1", "Port 2", "Port 3", "Port 4" };
int selectedItem = params;
if (ImGui::Combo("Controller Port", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
}
return params;
};
}
@ -921,7 +852,7 @@ void ActorViewerWindow::DrawElement() {
static Actor* display;
static Actor empty{};
static Actor* fetch = NULL;
static ActorInfo newActor = {0,0, {0, 0, 0}, {0, 0, 0}};
static ActorInfo newActor = { 0, 0, { 0, 0, 0 }, { 0, 0, 0 } };
static bool needs_reset = false;
static ImU16 one = 1;
static int actor;
@ -948,7 +879,7 @@ void ActorViewerWindow::DrawElement() {
actors.clear();
}
lastSceneId = gPlayState->sceneNum;
PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("Actor Type", acMapping[category])) {
for (int i = 0; i < acMapping.size(); i++) {
@ -986,37 +917,43 @@ void ActorViewerWindow::DrawElement() {
PushStyleHeader(THEME_COLOR);
if (ImGui::TreeNode("Selected Actor")) {
DrawGroupWithBorder([&]() {
ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str());
ImGui::Text("Description: %s", GetActorDescription(display->id).c_str());
ImGui::Text("Category: %s", acMapping[display->category]);
ImGui::Text("ID: %d", display->id);
ImGui::Text("Parameters: %d", display->params);
}, "Selected Actor");
DrawGroupWithBorder(
[&]() {
ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str());
ImGui::Text("Description: %s", GetActorDescription(display->id).c_str());
ImGui::Text("Category: %s", acMapping[display->category]);
ImGui::Text("ID: %d", display->id);
ImGui::Text("Parameters: %d", display->params);
},
"Selected Actor");
ImGui::SameLine();
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR);
ImGui::Text("Actor Position");
ImGui::InputScalar("X##CurPos", ImGuiDataType_Float, &display->world.pos.x);
ImGui::InputScalar("Y##CurPos", ImGuiDataType_Float, &display->world.pos.y);
ImGui::InputScalar("Z##CurPos", ImGuiDataType_Float, &display->world.pos.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "Actor Position");
DrawGroupWithBorder(
[&]() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR);
ImGui::Text("Actor Position");
ImGui::InputScalar("X##CurPos", ImGuiDataType_Float, &display->world.pos.x);
ImGui::InputScalar("Y##CurPos", ImGuiDataType_Float, &display->world.pos.y);
ImGui::InputScalar("Z##CurPos", ImGuiDataType_Float, &display->world.pos.z);
ImGui::PopItemWidth();
PopStyleInput();
},
"Actor Position");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
PushStyleInput(THEME_COLOR);
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::Text("Actor Rotation");
ImGui::InputScalar("X##CurRot", ImGuiDataType_S16, &display->world.rot.x);
ImGui::InputScalar("Y##CurRot", ImGuiDataType_S16, &display->world.rot.y);
ImGui::InputScalar("Z##CurRot", ImGuiDataType_S16, &display->world.rot.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "Actor Rotation");
DrawGroupWithBorder(
[&]() {
PushStyleInput(THEME_COLOR);
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::Text("Actor Rotation");
ImGui::InputScalar("X##CurRot", ImGuiDataType_S16, &display->world.rot.x);
ImGui::InputScalar("Y##CurRot", ImGuiDataType_S16, &display->world.rot.y);
ImGui::InputScalar("Z##CurRot", ImGuiDataType_S16, &display->world.rot.z);
ImGui::PopItemWidth();
PopStyleInput();
},
"Actor Rotation");
if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) {
PushStyleInput(THEME_COLOR);
@ -1025,17 +962,21 @@ void ActorViewerWindow::DrawElement() {
UIWidgets::InsertHelpHoverText("Some actors might not use this!");
}
DrawGroupWithBorder([&]() {
ImGui::Text("flags");
UIWidgets::DrawFlagArray32("flags", display->flags);
}, "flags");
DrawGroupWithBorder(
[&]() {
ImGui::Text("flags");
UIWidgets::DrawFlagArray32("flags", display->flags);
},
"flags");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
ImGui::Text("bgCheckFlags");
UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags);
}, "bgCheckFlags");
DrawGroupWithBorder(
[&]() {
ImGui::Text("bgCheckFlags");
UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags);
},
"bgCheckFlags");
if (Button("Refresh", ButtonOptions().Color(THEME_COLOR))) {
PopulateActorDropdown(category, list);
@ -1059,7 +1000,10 @@ void ActorViewerWindow::DrawElement() {
Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos);
}
if (Button("Fetch from Target", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor with target arrow above it. You might need C-Up for enemies"))) {
if (Button("Fetch from Target",
ButtonOptions()
.Color(THEME_COLOR)
.Tooltip("Grabs actor with target arrow above it. You might need C-Up for enemies"))) {
Player* player = GET_PLAYER(gPlayState);
fetch = player->talkActor;
if (fetch != NULL) {
@ -1069,7 +1013,8 @@ void ActorViewerWindow::DrawElement() {
rm = TARGET;
}
}
if (Button("Fetch from Held", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor that Link is holding"))) {
if (Button("Fetch from Held",
ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor that Link is holding"))) {
Player* player = GET_PLAYER(gPlayState);
fetch = player->heldActor;
if (fetch != NULL) {
@ -1079,7 +1024,8 @@ void ActorViewerWindow::DrawElement() {
rm = HELD;
}
}
if (Button("Fetch from Interaction", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor from \"interaction range\""))) {
if (Button("Fetch from Interaction",
ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor from \"interaction range\""))) {
Player* player = GET_PLAYER(gPlayState);
fetch = player->interactRangeActor;
if (fetch != NULL) {
@ -1094,7 +1040,7 @@ void ActorViewerWindow::DrawElement() {
}
if (ImGui::TreeNode("New...")) {
//ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
// ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
if (InputString("Search Actor", &searchString, InputOptions().Color(THEME_COLOR))) {
actors = GetActorsWithDescriptionContainingString(searchString);
@ -1102,14 +1048,14 @@ void ActorViewerWindow::DrawElement() {
}
if (!SohUtils::IsStringEmpty(searchString) && !actors.empty()) {
std::string preview = currentSelectedInDropdown == -1 ? "Please Select" : ActorDB::Instance->RetrieveEntry(actors[currentSelectedInDropdown]).desc;
std::string preview = currentSelectedInDropdown == -1
? "Please Select"
: ActorDB::Instance->RetrieveEntry(actors[currentSelectedInDropdown]).desc;
PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("Results", preview.c_str())) {
for (u8 i = 0; i < actors.size(); i++) {
if (ImGui::Selectable(
ActorDB::Instance->RetrieveEntry(actors[i]).desc.c_str(),
i == currentSelectedInDropdown
)) {
if (ImGui::Selectable(ActorDB::Instance->RetrieveEntry(actors[i]).desc.c_str(),
i == currentSelectedInDropdown)) {
currentSelectedInDropdown = i;
newActor.id = actors[i];
}
@ -1124,7 +1070,8 @@ void ActorViewerWindow::DrawElement() {
newActor.params = 0;
}
CVarCheckbox("Advanced mode", CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), CheckboxOptions().Tooltip("Changes the actor specific param menus with a direct input"));
CVarCheckbox("Advanced mode", CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"),
CheckboxOptions().Tooltip("Changes the actor specific param menus with a direct input"));
if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), 0)) {
PushStyleInput(THEME_COLOR);
@ -1137,36 +1084,42 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one);
PopStyleInput();
} else {
DrawGroupWithBorder([&]() {
ImGui::Text("Actor Specific Data");
newActor.params = actorSpecificData[newActor.id](newActor.params);
}, "Actor Specific Data");
DrawGroupWithBorder(
[&]() {
ImGui::Text("Actor Specific Data");
newActor.params = actorSpecificData[newActor.id](newActor.params);
},
"Actor Specific Data");
}
}
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() {
PushStyleInput(THEME_COLOR);
ImGui::Text("New Actor Position");
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::InputScalar("X##NewPos", ImGuiDataType_Float, &newActor.pos.x);
ImGui::InputScalar("Y##NewPos", ImGuiDataType_Float, &newActor.pos.y);
ImGui::InputScalar("Z##NewPos", ImGuiDataType_Float, &newActor.pos.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "New Actor Position");
DrawGroupWithBorder(
[&]() {
PushStyleInput(THEME_COLOR);
ImGui::Text("New Actor Position");
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::InputScalar("X##NewPos", ImGuiDataType_Float, &newActor.pos.x);
ImGui::InputScalar("Y##NewPos", ImGuiDataType_Float, &newActor.pos.y);
ImGui::InputScalar("Z##NewPos", ImGuiDataType_Float, &newActor.pos.z);
ImGui::PopItemWidth();
PopStyleInput();
},
"New Actor Position");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
PushStyleInput(THEME_COLOR);
ImGui::Text("New Actor Rotation");
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::InputScalar("X##NewRot", ImGuiDataType_S16, &newActor.rot.x);
ImGui::InputScalar("Y##NewRot", ImGuiDataType_S16, &newActor.rot.y);
ImGui::InputScalar("Z##NewRot", ImGuiDataType_S16, &newActor.rot.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "New Actor Rotation");
DrawGroupWithBorder(
[&]() {
PushStyleInput(THEME_COLOR);
ImGui::Text("New Actor Rotation");
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::InputScalar("X##NewRot", ImGuiDataType_S16, &newActor.rot.x);
ImGui::InputScalar("Y##NewRot", ImGuiDataType_S16, &newActor.rot.y);
ImGui::InputScalar("Z##NewRot", ImGuiDataType_S16, &newActor.rot.z);
ImGui::PopItemWidth();
PopStyleInput();
},
"New Actor Rotation");
if (Button("Fetch from Link", ButtonOptions().Color(THEME_COLOR))) {
Player* player = GET_PLAYER(gPlayState);
@ -1214,8 +1167,9 @@ void ActorViewerWindow::DrawElement() {
{ 3, "Both" },
};
if (CVarCombobox("Actor Name Tags", CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), nameTagOptions,
ComboboxOptions().Color(THEME_COLOR).Tooltip("Adds \"name tags\" above actors for identification"))) {
if (CVarCombobox(
"Actor Name Tags", CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), nameTagOptions,
ComboboxOptions().Color(THEME_COLOR).Tooltip("Adds \"name tags\" above actors for identification"))) {
NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG);
ActorViewer_AddTagForAllActors();
}

View file

@ -8,5 +8,5 @@ class ActorViewerWindow : public Ship::GuiWindow {
void DrawElement() override;
void InitElement() override;
void UpdateElement() override {};
void UpdateElement() override{};
};

View file

@ -20,7 +20,7 @@ extern "C" {
extern PlayState* gPlayState;
}
typedef enum ColRenderSetting { ColRenderDisabled, ColRenderSolid, ColRenderTransparent } ColRenderSetting ;
typedef enum ColRenderSetting { ColRenderDisabled, ColRenderSolid, ColRenderTransparent } ColRenderSetting;
static std::unordered_map<int32_t, const char*> ColRenderSettingNames = {
{ ColRenderDisabled, "Disabled" },
@ -68,9 +68,11 @@ void ColViewerWindow::DrawElement() {
CVarCombobox("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), ColRenderSettingNames, comboOpt);
CVarCheckbox("Apply as decal", CVAR_DEVELOPER_TOOLS("ColViewer.Decal"),
checkOpt.DefaultValue(true).Tooltip("Applies the collision as a decal display. This can be useful if there is z-fighting occuring "
"with the scene geometry, but can cause other artifacts."));
CVarCheckbox("Shaded", CVAR_DEVELOPER_TOOLS("ColViewer.Shaded"), checkOpt.DefaultValue(false).Tooltip("Applies the scene's shading to the collision display."));
checkOpt.DefaultValue(true).Tooltip(
"Applies the collision as a decal display. This can be useful if there is z-fighting occuring "
"with the scene geometry, but can cause other artifacts."));
CVarCheckbox("Shaded", CVAR_DEVELOPER_TOOLS("ColViewer.Shaded"),
checkOpt.DefaultValue(false).Tooltip("Applies the scene's shading to the collision display."));
// This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered()
const std::string colorHelpText = "View and change the colors used for collision display.";
@ -78,38 +80,58 @@ void ColViewerWindow::DrawElement() {
if (ImGui::TreeNode("Colors")) {
UIWidgets::Tooltip(colorHelpText.c_str());
if (CVarColorPicker("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
scene_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }));
if (CVarColorPicker("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
scene_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }));
}
if (CVarColorPicker("Hookshot", CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
hookshot_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }));
if (CVarColorPicker("Hookshot", CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
hookshot_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }));
}
if (CVarColorPicker("Entrance", CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
entrance_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }));
if (CVarColorPicker("Entrance", CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
entrance_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }));
}
if (CVarColorPicker("Special Surface (Grass/Sand/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
specialSurface_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }));
if (CVarColorPicker("Special Surface (Grass/Sand/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"),
{ 192, 255, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton,
THEME_COLOR)) {
specialSurface_col = VecFromRGBA8(
CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }));
}
if (CVarColorPicker("Interactable (Vines/Crawlspace/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
interactable_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 }));
if (CVarColorPicker("Interactable (Vines/Crawlspace/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"),
{ 192, 0, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton,
THEME_COLOR)) {
interactable_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 }));
}
if (CVarColorPicker("Slope", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
slope_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }));
if (CVarColorPicker("Slope", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
slope_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }));
}
if (CVarColorPicker("Void", CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
if (CVarColorPicker("Void", CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
void_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }));
}
if (CVarColorPicker("OC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
if (CVarColorPicker("OC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
oc_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }));
}
if (CVarColorPicker("AC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
if (CVarColorPicker("AC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
ac_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }));
}
if (CVarColorPicker("AT", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
if (CVarColorPicker("AT", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
at_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }));
}
if (CVarColorPicker("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
waterbox_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }));
if (CVarColorPicker("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
waterbox_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }));
}
ImGui::TreePop();
@ -210,9 +232,9 @@ void CreateSphereFace(std::vector<std::tuple<size_t, size_t, size_t>>& faces, in
// Create 3 new verticies at the midpoints
Vec3f vs[3] = {
Vec3f{(v0.n.ob[0] + v1.n.ob[0]) / 2.0f, (v0.n.ob[1] + v1.n.ob[1]) / 2.0f, (v0.n.ob[2] + v1.n.ob[2]) / 2.0f},
Vec3f{(v1.n.ob[0] + v2.n.ob[0]) / 2.0f, (v1.n.ob[1] + v2.n.ob[1]) / 2.0f, (v1.n.ob[2] + v2.n.ob[2]) / 2.0f},
Vec3f{(v2.n.ob[0] + v0.n.ob[0]) / 2.0f, (v2.n.ob[1] + v0.n.ob[1]) / 2.0f, (v2.n.ob[2] + v0.n.ob[2]) / 2.0f}
Vec3f{ (v0.n.ob[0] + v1.n.ob[0]) / 2.0f, (v0.n.ob[1] + v1.n.ob[1]) / 2.0f, (v0.n.ob[2] + v1.n.ob[2]) / 2.0f },
Vec3f{ (v1.n.ob[0] + v2.n.ob[0]) / 2.0f, (v1.n.ob[1] + v2.n.ob[1]) / 2.0f, (v1.n.ob[2] + v2.n.ob[2]) / 2.0f },
Vec3f{ (v2.n.ob[0] + v0.n.ob[0]) / 2.0f, (v2.n.ob[1] + v0.n.ob[1]) / 2.0f, (v2.n.ob[2] + v0.n.ob[2]) / 2.0f }
};
// Normalize vertex positions so they are on the sphere
@ -237,20 +259,20 @@ void CreateSphereData() {
float d = (1.0f + sqrtf(5.0f)) / 2.0f;
// Create the 12 starting verticies, 4 on each rectangle
base.emplace_back(Vec3f({-1, d, 0}));
base.emplace_back(Vec3f({1, d, 0}));
base.emplace_back(Vec3f({-1, -d, 0}));
base.emplace_back(Vec3f({1, -d, 0}));
base.emplace_back(Vec3f({ -1, d, 0 }));
base.emplace_back(Vec3f({ 1, d, 0 }));
base.emplace_back(Vec3f({ -1, -d, 0 }));
base.emplace_back(Vec3f({ 1, -d, 0 }));
base.emplace_back(Vec3f({0, -1, d}));
base.emplace_back(Vec3f({0, 1, d}));
base.emplace_back(Vec3f({0, -1, -d}));
base.emplace_back(Vec3f({0, 1, -d}));
base.emplace_back(Vec3f({ 0, -1, d }));
base.emplace_back(Vec3f({ 0, 1, d }));
base.emplace_back(Vec3f({ 0, -1, -d }));
base.emplace_back(Vec3f({ 0, 1, -d }));
base.emplace_back(Vec3f({d, 0, -1}));
base.emplace_back(Vec3f({d, 0, 1}));
base.emplace_back(Vec3f({-d, 0, -1}));
base.emplace_back(Vec3f({-d, 0, 1}));
base.emplace_back(Vec3f({ d, 0, -1 }));
base.emplace_back(Vec3f({ d, 0, 1 }));
base.emplace_back(Vec3f({ -d, 0, -1 }));
base.emplace_back(Vec3f({ -d, 0, 1 }));
// Normalize verticies so they are on the unit sphere
for (Vec3f& v : base) {
@ -349,7 +371,7 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
// Draws a dynapoly structure (scenes or Bg Actors)
void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
Color_RGBA8 color = {255, 255, 255, 255};
Color_RGBA8 color = { 255, 255, 255, 255 };
uint32_t lastColorR = color.r;
uint32_t lastColorG = color.g;
@ -367,7 +389,7 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
if (SurfaceType_IsHookshotSurface(&gPlayState->colCtx, poly, bgId)) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot.Value"), { 128, 128, 255, 255 });
} else if (func_80041D94(&gPlayState->colCtx, poly, bgId) > 0x01) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable.Value"), {192, 0, 192, 255});
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable.Value"), { 192, 0, 192, 255 });
} else if (func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x0C) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid.Value"), { 255, 0, 0, 255 });
} else if (SurfaceType_GetSceneExitIndex(&gPlayState->colCtx, poly, bgId) ||
@ -427,7 +449,8 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
// Draws the scene
void DrawSceneCollision() {
ColRenderSetting showSceneColSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_DISABLED);
ColRenderSetting showSceneColSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_DISABLED);
if (showSceneColSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return;
@ -442,7 +465,8 @@ void DrawSceneCollision() {
// Draws all Bg Actors
void DrawBgActorCollision() {
ColRenderSetting showBgActorSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_DISABLED);
ColRenderSetting showBgActorSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_DISABLED);
if (showBgActorSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return;
}
@ -567,7 +591,8 @@ void DrawColCheckList(std::vector<Gfx>& dl, Collider** objects, int32_t count) {
// Draws all Col Check objects
void DrawColCheckCollision() {
ColRenderSetting showColCheckSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), COLVIEW_DISABLED);
ColRenderSetting showColCheckSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), COLVIEW_DISABLED);
if (showColCheckSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return;
}
@ -619,7 +644,8 @@ extern "C" f32 zdWaterBoxMinY;
// Draws all waterboxes
void DrawWaterboxList() {
ColRenderSetting showWaterboxSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), COLVIEW_DISABLED);
ColRenderSetting showWaterboxSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), COLVIEW_DISABLED);
if (showWaterboxSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return;
}

View file

@ -2,11 +2,7 @@
#include <libultraship/libultraship.h>
typedef enum {
COLVIEW_DISABLED,
COLVIEW_SOLID,
COLVIEW_TRANSPARENT
} ColViewerRenderSetting;
typedef enum { COLVIEW_DISABLED, COLVIEW_SOLID, COLVIEW_TRANSPARENT } ColViewerRenderSetting;
#ifdef __cplusplus
class ColViewerWindow : public Ship::GuiWindow {
@ -15,7 +11,7 @@ class ColViewerWindow : public Ship::GuiWindow {
void InitElement() override;
void DrawElement() override;
void UpdateElement() override {};
void UpdateElement() override{};
};
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -66,7 +66,8 @@ std::map<int, std::string> cmdMap = {
};
void PerformDisplayListSearch() {
auto result = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*" + std::string(searchString) + "*DL*");
auto result = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(
"*" + std::string(searchString) + "*DL*");
displayListSearchResults.clear();
@ -79,15 +80,12 @@ void PerformDisplayListSearch() {
}
// Sort the final list
std::sort(displayListSearchResults.begin(), displayListSearchResults.end(), [](const std::string& a, const std::string& b) {
return std::lexicographical_compare(
a.begin(), a.end(),
b.begin(), b.end(),
[](char c1, char c2) {
return std::tolower(c1) < std::tolower(c2);
}
);
});
std::sort(displayListSearchResults.begin(), displayListSearchResults.end(),
[](const std::string& a, const std::string& b) {
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), [](char c1, char c2) {
return std::tolower(c1) < std::tolower(c2);
});
});
}
void DLViewerWindow::DrawElement() {
@ -128,7 +126,8 @@ void DLViewerWindow::DrawElement() {
}
try {
auto res = std::static_pointer_cast<Fast::DisplayList>(Ship::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList));
auto res = std::static_pointer_cast<Fast::DisplayList>(
Ship::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList));
if (res->GetInitData()->Type != static_cast<uint32_t>(Fast::ResourceType::DisplayList)) {
ImGui::Text("Resource type is not a Display List. Please choose another.");
@ -141,7 +140,8 @@ void DLViewerWindow::DrawElement() {
std::string id = "##CMD" + std::to_string(i);
Gfx* gfx = (Gfx*)&res->Instructions[i];
int cmd = gfx->words.w0 >> 24;
if (cmdMap.find(cmd) == cmdMap.end()) continue;
if (cmdMap.find(cmd) == cmdMap.end())
continue;
std::string cmdLabel = cmdMap.at(cmd);
@ -199,14 +199,13 @@ void DLViewerWindow::DrawElement() {
}
ImGui::PopItemWidth();
}
if (cmd == G_RDPPIPESYNC) {
}
if (cmd == G_RDPPIPESYNC) {}
if (cmd == G_SETGRAYSCALE) {
bool* state = (bool*)&gfx->words.w1;
ImGui::SameLine();
UIWidgets::PushStyleCheckbox(THEME_COLOR);
if (ImGui::Checkbox(("state" + id).c_str(), state)) {
//
//
}
UIWidgets::PopStyleCheckbox();
}
@ -304,8 +303,7 @@ void DLViewerWindow::DrawElement() {
ImGui::SameLine();
ImGui::Text("Vertex Name: %s", fileName);
}
if (cmd == G_DL) {
}
if (cmd == G_DL) {}
if (cmd == G_DL_OTR_HASH) {
gfx++;
uint64_t hash = ((uint64_t)gfx->words.w0 << 32) + (uint64_t)gfx->words.w1;
@ -320,8 +318,8 @@ void DLViewerWindow::DrawElement() {
}
// Skip second half of instructions that are over 128-bit wide
if (cmd == G_SETTIMG_OTR_HASH || cmd == G_DL_OTR_HASH || cmd == G_VTX_OTR_HASH ||
cmd == G_BRANCH_Z_OTR || cmd == G_MARKER || cmd == G_MTX_OTR) {
if (cmd == G_SETTIMG_OTR_HASH || cmd == G_DL_OTR_HASH || cmd == G_VTX_OTR_HASH || cmd == G_BRANCH_Z_OTR ||
cmd == G_MARKER || cmd == G_MTX_OTR) {
i++;
ImGui::Text("%lu - Reserved - Second half of %s", i, cmdLabel.c_str());
}

View file

@ -8,5 +8,5 @@ class DLViewerWindow : public Ship::GuiWindow {
void InitElement() override;
void DrawElement() override;
void UpdateElement() override {};
void UpdateElement() override{};
};

View file

@ -6,5 +6,5 @@ class HookDebuggerWindow : public Ship::GuiWindow {
void InitElement() override;
void DrawElement() override;
void UpdateElement() override {};
void UpdateElement() override{};
};

View file

@ -1,14 +1,14 @@
#include "performanceTimer.h"
void StartPerformanceTimer(TimerID timer){
void StartPerformanceTimer(TimerID timer) {
timeStarted[timer] = std::chrono::high_resolution_clock::now();
}
void StopPerformanceTimer(TimerID timer){
void StopPerformanceTimer(TimerID timer) {
totalTimes[timer] += (std::chrono::high_resolution_clock::now() - timeStarted[timer]);
}
std::chrono::duration<double, std::milli> GetPerformanceTimer(TimerID timer){
std::chrono::duration<double, std::milli> GetPerformanceTimer(TimerID timer) {
return totalTimes[timer];
}
@ -16,6 +16,6 @@ void ResetPerformanceTimer(TimerID timer) {
totalTimes[timer] = {};
}
void ResetPerformanceTimers(){
void ResetPerformanceTimers() {
totalTimes = {};
}

View file

@ -5,28 +5,28 @@
#include <chrono>
typedef enum {
PT_WHOLE_SEED,
PT_LOGIC_RESET,
PT_REGION_RESET,
PT_SPOILER_LOG,
PT_ENTRANCE_SHUFFLE,
PT_SHOPSANITY,
PT_OWN_DUNGEON,
PT_LIMITED_CHECKS,
PT_ADVANCEMENT_ITEMS,
PT_REMAINING_ITEMS,
PT_PLAYTHROUGH_GENERATION,
PT_PARE_DOWN_PLAYTHROUGH,
PT_WOTH,
PT_FOOLISH,
PT_OVERRIDES,
PT_HINTS,
PT_EVENT_ACCESS,
PT_TOD_ACCESS,
PT_ENTRANCE_LOGIC,
PT_LOCATION_LOGIC,
PT_RECALCULATE_AVAILABLE_CHECKS,
PT_MAX
PT_WHOLE_SEED,
PT_LOGIC_RESET,
PT_REGION_RESET,
PT_SPOILER_LOG,
PT_ENTRANCE_SHUFFLE,
PT_SHOPSANITY,
PT_OWN_DUNGEON,
PT_LIMITED_CHECKS,
PT_ADVANCEMENT_ITEMS,
PT_REMAINING_ITEMS,
PT_PLAYTHROUGH_GENERATION,
PT_PARE_DOWN_PLAYTHROUGH,
PT_WOTH,
PT_FOOLISH,
PT_OVERRIDES,
PT_HINTS,
PT_EVENT_ACCESS,
PT_TOD_ACCESS,
PT_ENTRANCE_LOGIC,
PT_LOCATION_LOGIC,
PT_RECALCULATE_AVAILABLE_CHECKS,
PT_MAX
} TimerID;
void StartPerformanceTimer(TimerID timer);
@ -36,4 +36,3 @@ void ResetPerformanceTimer(TimerID timer);
void ResetPerformanceTimers();
static std::array<std::chrono::duration<double, std::milli>, PT_MAX> totalTimes = {};
static std::array<std::chrono::high_resolution_clock::time_point, PT_MAX> timeStarted = {};

View file

@ -77,27 +77,35 @@ std::vector<ValueTableElement> valueTable = {
extern "C" void ValueViewer_Draw(GfxPrint* printer) {
for (int i = 0; i < valueTable.size(); i++) {
ValueTableElement& element = valueTable[i];
if (!element.isActive || !element.isPrinted || (gPlayState == NULL && element.requiresPlayState)) continue;
GfxPrint_SetColor(printer, element.color.x * 255, element.color.y * 255, element.color.z * 255, element.color.w * 255);
if (!element.isActive || !element.isPrinted || (gPlayState == NULL && element.requiresPlayState))
continue;
GfxPrint_SetColor(printer, element.color.x * 255, element.color.y * 255, element.color.z * 255,
element.color.w * 255);
GfxPrint_SetPos(printer, element.x, element.y);
switch (element.type) {
case TYPE_S8:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s8*)element.valueFn());
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(),
*(s8*)element.valueFn());
break;
case TYPE_U8:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u8*)element.valueFn());
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(),
*(u8*)element.valueFn());
break;
case TYPE_S16:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s16*)element.valueFn());
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(),
*(s16*)element.valueFn());
break;
case TYPE_U16:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u16*)element.valueFn());
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(),
*(u16*)element.valueFn());
break;
case TYPE_S32:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s32*)element.valueFn());
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(),
*(s32*)element.valueFn());
break;
case TYPE_U32:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u32*)element.valueFn());
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(),
*(u32*)element.valueFn());
break;
case TYPE_CHAR:
GfxPrint_Printf(printer, "%s%c", element.prefix.c_str(), *(char*)element.valueFn());
@ -106,7 +114,8 @@ extern "C" void ValueViewer_Draw(GfxPrint* printer) {
GfxPrint_Printf(printer, "%s%s", element.prefix.c_str(), (char*)element.valueFn());
break;
case TYPE_FLOAT:
GfxPrint_Printf(printer, (element.typeFormat ? "%s%4.1f" : "%s%f"), element.prefix.c_str(), *(float*)element.valueFn());
GfxPrint_Printf(printer, (element.typeFormat ? "%s%4.1f" : "%s%f"), element.prefix.c_str(),
*(float*)element.valueFn());
break;
}
}
@ -149,17 +158,16 @@ void ValueViewerWindow::DrawElement() {
ImGui::BeginGroup();
static int selectedElement = -1;
std::string selectedElementText = (selectedElement == -1) ? "Select a value" : (
std::string(valueTable[selectedElement].name) + " (" + std::string(valueTable[selectedElement].path) + ")"
);
std::string selectedElementText = (selectedElement == -1) ? "Select a value"
: (std::string(valueTable[selectedElement].name) + " (" +
std::string(valueTable[selectedElement].path) + ")");
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##valueViewerElement", selectedElementText.c_str())) {
for (int i = 0; i < valueTable.size(); i++) {
if (valueTable[i].isActive) continue;
if (valueTable[i].isActive)
continue;
bool isSelected = (selectedElement == i);
std::string elementText = (
std::string(valueTable[i].name) + " (" + std::string(valueTable[i].path) + ")"
);
std::string elementText = (std::string(valueTable[i].name) + " (" + std::string(valueTable[i].path) + ")");
if (ImGui::Selectable(elementText.c_str(), isSelected)) {
selectedElement = i;
}
@ -181,7 +189,8 @@ void ValueViewerWindow::DrawElement() {
for (int i = 0; i < valueTable.size(); i++) {
ValueTableElement& element = valueTable[i];
if (!element.isActive || (gPlayState == NULL && element.requiresPlayState)) continue;
if (!element.isActive || (gPlayState == NULL && element.requiresPlayState))
continue;
UIWidgets::PushStyleButton(THEME_COLOR);
UIWidgets::PushStyleCheckbox(THEME_COLOR);
ImGui::AlignTextToFramePadding();
@ -249,7 +258,8 @@ void ValueViewerWindow::DrawElement() {
}
UIWidgets::PopStyleInput();
ImGui::SameLine();
ImGui::ColorEdit3(("##color" + std::string(element.name)).c_str(), (float*)&element.color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
ImGui::ColorEdit3(("##color" + std::string(element.name)).c_str(), (float*)&element.color,
ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
ImGui::SameLine();
UIWidgets::PushStyleCheckbox(THEME_COLOR);
if (ImGui::Button(("Position##" + std::string(element.name)).c_str())) {

View file

@ -39,7 +39,7 @@ class ValueViewerWindow : public Ship::GuiWindow {
void InitElement() override;
void DrawElement() override;
void UpdateElement() override {};
void UpdateElement() override{};
};
#endif

View file

@ -42,18 +42,54 @@ const char* enemyCVarList[] = {
};
const char* enemyNameList[] = {
"Armos", "Arwing", "Baby Dodongo", "Bari",
"Beamos", "Big Skulltula", "Stalchild (Big)", "Biri",
"Iron Knuckle (Black)", "Blue Tektite", "Bubble", "Club Moblin",
"Dark Link", "Dinolfos", "Dodongo", "Fire Keese",
"Floor Tile", "Floormaster", "Flying Peahat", "Flying Pot",
"Freezard", "Gibdo", "Gohma Larva", "Guay",
"Ice Keese", "Invisible Skulltula", "Keese", "Large Deku Baba",
"Like-Like", "Lizalfos", "Mad Scrub", "Wolfos (Normal)",
"Peahat Larva", "Redead", "Red Tektite", "Shabom",
"Shell Blade", "Skulltula", "Small Deku Baba", "Stalchild (Small)",
"Spike", "Stalfos", "Stinger", "Tailpasaran",
"Torch Slug", "Wallmaster", "Iron Knuckle (White)", "Wolfos (White)",
"Armos",
"Arwing",
"Baby Dodongo",
"Bari",
"Beamos",
"Big Skulltula",
"Stalchild (Big)",
"Biri",
"Iron Knuckle (Black)",
"Blue Tektite",
"Bubble",
"Club Moblin",
"Dark Link",
"Dinolfos",
"Dodongo",
"Fire Keese",
"Floor Tile",
"Floormaster",
"Flying Peahat",
"Flying Pot",
"Freezard",
"Gibdo",
"Gohma Larva",
"Guay",
"Ice Keese",
"Invisible Skulltula",
"Keese",
"Large Deku Baba",
"Like-Like",
"Lizalfos",
"Mad Scrub",
"Wolfos (Normal)",
"Peahat Larva",
"Redead",
"Red Tektite",
"Shabom",
"Shell Blade",
"Skulltula",
"Small Deku Baba",
"Stalchild (Small)",
"Spike",
"Stalfos",
"Stinger",
"Tailpasaran",
"Torch Slug",
"Wallmaster",
"Iron Knuckle (White)",
"Wolfos (White)",
"Withered Deku Baba",
};
@ -111,43 +147,45 @@ static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] =
// Doesn't work {ACTOR_EN_POH, 0}, // Poe (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_POH, 2}, // Poe (composer Sharp) (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_POH, 3}, // Poe (composer Flat) (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping up)
// Doesn't work {ACTOR_EN_REEBA, 0}, // Leever (reliant on surface and also normally used in tandem with a leever spawner, kills itself too quickly otherwise)
// Kinda doesn't work { ACTOR_EN_FD, 0 }, // Flare Dancer (jumps out of bounds a lot, and possible cause of crashes because of spawning a ton of flame actors)
// Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping
// up) Doesn't work {ACTOR_EN_REEBA, 0}, // Leever (reliant on surface and also normally used in tandem with a
// leever spawner, kills itself too quickly otherwise) Kinda doesn't work { ACTOR_EN_FD, 0 }, // Flare Dancer (jumps
// out of bounds a lot, and possible cause of crashes because of spawning a ton of flame actors)
};
static int enemiesToRandomize[] = {
ACTOR_EN_FIREFLY, // Keese (including fire/ice)
ACTOR_EN_TEST, // Stalfos
ACTOR_EN_TITE, // Tektite
ACTOR_EN_POH, // Poe (normal, blue rupee, composers)
ACTOR_EN_OKUTA, // Octorok
ACTOR_EN_WALLMAS, // Wallmaster
ACTOR_EN_DODONGO, // Dodongo
ACTOR_EN_FIREFLY, // Keese (including fire/ice)
ACTOR_EN_TEST, // Stalfos
ACTOR_EN_TITE, // Tektite
ACTOR_EN_POH, // Poe (normal, blue rupee, composers)
ACTOR_EN_OKUTA, // Octorok
ACTOR_EN_WALLMAS, // Wallmaster
ACTOR_EN_DODONGO, // Dodongo
// ACTOR_EN_REEBA, // Leever (reliant on spawner (z_e_encount1.c)
ACTOR_EN_PEEHAT, // Flying Peahat, big one spawning larva, larva
ACTOR_EN_ZF, // Lizalfos, Dinolfos
ACTOR_EN_GOMA, // Gohma Larva (normal, eggs, gohma eggs)
ACTOR_EN_BUBBLE, // Shabom (bubble)
ACTOR_EN_DODOJR, // Baby Dodongo
ACTOR_EN_TORCH2, // Dark Link
ACTOR_EN_BILI, // Biri (small jellyfish)
ACTOR_EN_TP, // Electric Tailpasaran
ACTOR_EN_ST, // Skulltula (normal, big, invisible)
ACTOR_EN_BW, // Torch Slug
ACTOR_EN_EIYER, // Stinger (land)
ACTOR_EN_MB, // Moblins (Club, spear)
ACTOR_EN_DEKUBABA, // Deku Baba (small, large)
ACTOR_EN_AM, // Armos (enemy variant)
ACTOR_EN_DEKUNUTS, // Mad Scrub (single attack, triple attack)
ACTOR_EN_VALI, // Bari (big jellyfish) (spawns very high up)
ACTOR_EN_BB, // Bubble (flying skull enemy) (all colors)
ACTOR_EN_YUKABYUN, // Flying Floor Tile
ACTOR_EN_VM, // Beamos
ACTOR_EN_FLOORMAS, // Floormaster
ACTOR_EN_RD, // Redead, Gibdo
ACTOR_EN_SW, // Skullwalltula
// ACTOR_EN_FD, // Flare Dancer (can be randomized, but not randomized to, so keeping it in vanilla locations means it at least shows up in the game)
ACTOR_EN_PEEHAT, // Flying Peahat, big one spawning larva, larva
ACTOR_EN_ZF, // Lizalfos, Dinolfos
ACTOR_EN_GOMA, // Gohma Larva (normal, eggs, gohma eggs)
ACTOR_EN_BUBBLE, // Shabom (bubble)
ACTOR_EN_DODOJR, // Baby Dodongo
ACTOR_EN_TORCH2, // Dark Link
ACTOR_EN_BILI, // Biri (small jellyfish)
ACTOR_EN_TP, // Electric Tailpasaran
ACTOR_EN_ST, // Skulltula (normal, big, invisible)
ACTOR_EN_BW, // Torch Slug
ACTOR_EN_EIYER, // Stinger (land)
ACTOR_EN_MB, // Moblins (Club, spear)
ACTOR_EN_DEKUBABA, // Deku Baba (small, large)
ACTOR_EN_AM, // Armos (enemy variant)
ACTOR_EN_DEKUNUTS, // Mad Scrub (single attack, triple attack)
ACTOR_EN_VALI, // Bari (big jellyfish) (spawns very high up)
ACTOR_EN_BB, // Bubble (flying skull enemy) (all colors)
ACTOR_EN_YUKABYUN, // Flying Floor Tile
ACTOR_EN_VM, // Beamos
ACTOR_EN_FLOORMAS, // Floormaster
ACTOR_EN_RD, // Redead, Gibdo
ACTOR_EN_SW, // Skullwalltula
// ACTOR_EN_FD, // Flare Dancer (can be randomized, but not randomized to, so keeping it in vanilla locations
// means it at least shows up in the game)
ACTOR_EN_SB, // Shell Blade
ACTOR_EN_KAREBABA, // Withered Deku Baba
ACTOR_EN_RR, // Like-Like
@ -162,8 +200,8 @@ static int enemiesToRandomize[] = {
ACTOR_EN_CROW, // Guay
};
extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX,
int16_t *rotY, int16_t *rotZ, int16_t *params) {
extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX,
int16_t* rotY, int16_t* rotZ, int16_t* params) {
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(play->sceneNum);
@ -171,7 +209,8 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
// This should probably be handled on OTR generation in the future when object dependency is fully removed.
// Remove bats and Skulltulas from graveyard.
// Remove Octorok in Lost Woods.
if (((*actorId == ACTOR_EN_FIREFLY || (*actorId == ACTOR_EN_SW && *params == 0)) && play->sceneNum == SCENE_GRAVEYARD) ||
if (((*actorId == ACTOR_EN_FIREFLY || (*actorId == ACTOR_EN_SW && *params == 0)) &&
play->sceneNum == SCENE_GRAVEYARD) ||
(*actorId == ACTOR_EN_OKUTA && play->sceneNum == SCENE_LOST_WOODS)) {
return 0;
}
@ -229,7 +268,8 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
}
// Get randomized enemy ID and parameter.
uint32_t seed = play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params;
uint32_t seed =
play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params;
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed);
int8_t timesRandomized = 1;
@ -305,7 +345,8 @@ EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
GetSelectedEnemies();
}
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
uint32_t finalSeed =
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed);
uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE);
return selectedEnemyList[randomNumber];
@ -357,17 +398,19 @@ bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId,
// Don't randomize the Wolfos in SFM because it's needed to open the gate.
case ACTOR_EN_WF:
return (params != 7936);
// Don't randomize the Stalfos in Forest Temple because other enemies fall through the hole and don't trigger the platform.
// Don't randomize the Stalfos spawning on the boat in Shadow Temple, as randomizing them places the new enemies
// down in the river.
// Don't randomize the Stalfos in Forest Temple because other enemies fall through the hole and don't
// trigger the platform. Don't randomize the Stalfos spawning on the boat in Shadow Temple, as
// randomizing them places the new enemies down in the river.
case ACTOR_EN_TEST:
return (params != 1 && !(sceneNum == SCENE_SHADOW_TEMPLE && roomNum == 21));
// Only randomize the enemy variant of Armos Statue.
// Leave one Armos unrandomized in the Spirit Temple room where an armos is needed to push down a button.
// Leave one Armos unrandomized in the Spirit Temple room where an armos is needed to push down a
// button.
case ACTOR_EN_AM:
return ((params == -1 || params == 255) && !(sceneNum == SCENE_SPIRIT_TEMPLE && posX == 2141));
// Don't randomize Shell Blades and Spikes in the underwater portion in Water Temple as it's impossible to kill
// most other enemies underwater with just hookshot and they're required to be killed for a grate to open.
// Don't randomize Shell Blades and Spikes in the underwater portion in Water Temple as it's impossible
// to kill most other enemies underwater with just hookshot and they're required to be killed for a
// grate to open.
case ACTOR_EN_SB:
case ACTOR_EN_NY:
return (!(!isMQ && sceneNum == SCENE_WATER_TEMPLE && roomNum == 2));
@ -403,7 +446,8 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
// Deku Tree
case SCENE_DEKU_TREE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 9)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 4 || roomNum == 6 || roomNum == 9 || roomNum == 10)));
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 4 || roomNum == 6 || roomNum == 9 || roomNum == 10)));
// Dodongo's Cavern
case SCENE_DODONGOS_CAVERN:
return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) &&
@ -415,8 +459,10 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 11 || roomNum == 14)));
// Forest Temple
case SCENE_FOREST_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21)));
return (!(!isMQ && enemiesToExcludeClearRooms &&
(roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) &&
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21)));
// Fire Temple
case SCENE_FIRE_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) &&
@ -427,23 +473,31 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18)));
// Spirit Temple
case SCENE_SPIRIT_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 10 || roomNum == 17 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 2 || roomNum == 4 || roomNum == 10 || roomNum == 15 || roomNum == 19 || roomNum == 20)));
return (!(!isMQ && enemiesToExcludeClearRooms &&
(roomNum == 1 || roomNum == 10 || roomNum == 17 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 1 || roomNum == 2 || roomNum == 4 || roomNum == 10 || roomNum == 15 ||
roomNum == 19 || roomNum == 20)));
// Shadow Temple
case SCENE_SHADOW_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms &&
(roomNum == 1 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 16 || roomNum == 17 || roomNum == 19 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 6 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 20)));
return (
!(!isMQ && enemiesToExcludeClearRooms &&
(roomNum == 1 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 16 || roomNum == 17 ||
roomNum == 19 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 1 || roomNum == 6 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 20)));
// Ganon's Castle Trials
case SCENE_INSIDE_GANONS_CASTLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 5 || roomNum == 9)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 0 || roomNum == 2 || roomNum == 5 || roomNum == 9)));
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 0 || roomNum == 2 || roomNum == 5 || roomNum == 9)));
// Ice Caverns
case SCENE_ICE_CAVERN:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 7)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 7)));
// Bottom of the Well
// Exclude Dark Link from room with holes in the floor because it can pull you in a like-like making the player fall down.
// Exclude Dark Link from room with holes in the floor because it can pull you in a like-like making the player
// fall down.
case SCENE_BOTTOM_OF_THE_WELL:
return (!(!isMQ && enemy.id == ACTOR_EN_TORCH2 && roomNum == 3));
// Don't allow Dark Link in areas with lava void out zones as it voids out the player as well.
@ -452,18 +506,21 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
return (!(enemy.id == ACTOR_EN_TORCH2 && roomNum == 6) &&
!(!isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 7)) &&
!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 5 || roomNum == 10)) &&
!(isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 3 || roomNum == 5 || roomNum == 7)) &&
!(isMQ && enemiesToExcludeTimedRooms &&
(roomNum == 1 || roomNum == 3 || roomNum == 5 || roomNum == 7)) &&
!(isMQ && enemiesToExcludeClearRooms && roomNum == 10));
// Don't allow certain enemies in Ganon's Tower because they would spawn up on the ceiling,
// becoming impossible to kill.
// Ganon's Tower.
case SCENE_GANONS_TOWER:
return (!(enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)));
return (!(enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI ||
(enemy.id == ACTOR_EN_ZF && enemy.params == -1)));
// Ganon's Tower Escape.
case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR:
return (!((enemiesToExcludeTimedRooms || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)) && roomNum == 1));
// Don't allow big Stalchildren, big Peahats and the large Bari (jellyfish) during the Gohma fight because they can clip into Gohma
// and it crashes the game. Likely because Gohma on the ceiling can't handle collision with other enemies.
// Don't allow big Stalchildren, big Peahats and the large Bari (jellyfish) during the Gohma fight because they
// can clip into Gohma and it crashes the game. Likely because Gohma on the ceiling can't handle collision with
// other enemies.
case SCENE_DEKU_TREE_BOSS:
return (!enemiesToExcludeTimedRooms && !(enemy.id == ACTOR_EN_SKB && enemy.params == 20) &&
!(enemy.id == ACTOR_EN_PEEHAT && enemy.params == -1));

View file

@ -18,5 +18,6 @@ extern const char* enemyNameList[];
extern void GetSelectedEnemies();
#ifndef __cplusplus
uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX, int16_t *rotY, int16_t *rotZ, int16_t *params);
uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX,
int16_t* rotY, int16_t* rotZ, int16_t* params);
#endif

File diff suppressed because it is too large Load diff

View file

@ -6,271 +6,269 @@
#include <stdint.h>
#ifdef __cplusplus
enum GameInteractionEffectQueryResult {
Possible = 0x00,
TemporarilyNotPossible = 0x01,
NotPossible = 0xFF
};
enum GameInteractionEffectQueryResult { Possible = 0x00, TemporarilyNotPossible = 0x01, NotPossible = 0xFF };
class GameInteractionEffectBase {
public:
public:
virtual GameInteractionEffectQueryResult CanBeApplied() = 0;
GameInteractionEffectQueryResult Apply();
protected:
protected:
virtual void _Apply() = 0;
};
class RemovableGameInteractionEffect: public GameInteractionEffectBase {
public:
class RemovableGameInteractionEffect : public GameInteractionEffectBase {
public:
virtual GameInteractionEffectQueryResult CanBeRemoved();
GameInteractionEffectQueryResult Remove();
protected:
virtual void _Remove() {};
protected:
virtual void _Remove(){};
};
class ParameterizedGameInteractionEffect {
public:
public:
int32_t parameters[3];
};
namespace GameInteractionEffect {
class SetSceneFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SetSceneFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class UnsetSceneFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class UnsetSceneFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SetFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SetFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class UnsetFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class UnsetFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class ModifyHeartContainers: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class ModifyHeartContainers : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class FillMagic: public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class FillMagic : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class EmptyMagic: public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class EmptyMagic : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class ModifyRupees: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class ModifyRupees : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class NoUI: public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class NoUI : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ModifyGravity: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ModifyGravity : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ModifyHealth: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class ModifyHealth : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SetPlayerHealth: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SetPlayerHealth : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class FreezePlayer: public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class FreezePlayer : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class BurnPlayer: public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class BurnPlayer : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class ElectrocutePlayer: public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class ElectrocutePlayer : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class KnockbackPlayer: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class KnockbackPlayer : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class ModifyLinkSize: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ModifyLinkSize : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class InvisibleLink : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class InvisibleLink : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class PacifistMode : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class PacifistMode : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class DisableZTargeting: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class DisableZTargeting : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class WeatherRainstorm: public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class WeatherRainstorm : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ReverseControls: public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ReverseControls : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ForceEquipBoots: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ForceEquipBoots : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ModifyRunSpeedModifier: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ModifyRunSpeedModifier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class OneHitKO : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class OneHitKO : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ModifyDefenseModifier: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class ModifyDefenseModifier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class GiveOrTakeShield: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class GiveOrTakeShield : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class TeleportPlayer: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class TeleportPlayer : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class ClearAssignedButtons: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class ClearAssignedButtons : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SetTimeOfDay: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SetTimeOfDay : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SetCollisionViewer: public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class SetCollisionViewer : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class SetCosmeticsColor: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SetCosmeticsColor : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class RandomizeCosmetics: public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class RandomizeCosmetics : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class PressButton: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class PressButton : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class PressRandomButton: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class PressRandomButton : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class AddOrTakeAmmo: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class AddOrTakeAmmo : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class RandomBombFuseTimer: public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class RandomBombFuseTimer : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class DisableLedgeGrabs: public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class DisableLedgeGrabs : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class RandomWind: public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class RandomWind : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class RandomBonks: public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class RandomBonks : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class PlayerInvincibility: public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class PlayerInvincibility : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class SlipperyFloor: public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class SpawnEnemyWithOffset: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SpawnActor: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
}
class SlipperyFloor : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
void _Remove() override;
};
class SpawnEnemyWithOffset : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class SpawnActor : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
} // namespace GameInteractionEffect
#endif /* __cplusplus */
#endif /* GameInteractionEffect_h */

View file

@ -1,4 +1,4 @@
/*
/*
GameInteractor is meant to be used for interacting with the game (yup...).
It exposes functions that directly modify, add or remove game related elements.
@ -54,7 +54,10 @@ bool GameInteractor::IsSaveLoaded(bool allowDbgSave) {
bool GameInteractor::IsGameplayPaused() {
Player* player = GET_PLAYER(gPlayState);
return (Player_InBlockingCsMode(gPlayState, player) || gPlayState->pauseCtx.state != 0 || gPlayState->msgCtx.msgMode != 0) ? true : false;
return (Player_InBlockingCsMode(gPlayState, player) || gPlayState->pauseCtx.state != 0 ||
gPlayState->msgCtx.msgMode != 0)
? true
: false;
}
bool GameInteractor::CanSpawnActor() {

View file

@ -34,9 +34,9 @@ DEFINE_HOOK(OnPlayerBonk, ());
DEFINE_HOOK(OnPlayerHealthChange, (int16_t amount));
DEFINE_HOOK(OnPlayerBottleUpdate, (int16_t contents));
DEFINE_HOOK(OnPlayerHoldUpShield, ());
DEFINE_HOOK(OnPlayerFirstPersonControl, (Player* player));
DEFINE_HOOK(OnPlayerFirstPersonControl, (Player * player));
DEFINE_HOOK(OnPlayerProcessStick, ());
DEFINE_HOOK(OnPlayerShieldControl, (float_t* sp50, float_t* sp54));
DEFINE_HOOK(OnPlayerShieldControl, (float_t * sp50, float_t* sp54));
DEFINE_HOOK(OnPlayDestroy, ());
DEFINE_HOOK(OnPlayDrawEnd, ());
DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list originalArgs));

View file

@ -126,7 +126,7 @@ void GameInteractor_ExecuteOnBossDefeat(void* actor) {
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnBossDefeat>(actor);
}
void GameInteractor_ExecuteOnTimestamp (u8 item) {
void GameInteractor_ExecuteOnTimestamp(u8 item) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnTimestamp>(item);
}
@ -266,7 +266,8 @@ void GameInteractor_ExecuteOnUpdateFileQuestSelection(uint8_t questIndex) {
}
void GameInteractor_ExecuteOnUpdateFileBossRushOptionSelection(uint8_t optionIndex, uint8_t optionValue) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnUpdateFileBossRushOptionSelection>(optionIndex, optionValue);
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnUpdateFileBossRushOptionSelection>(optionIndex,
optionValue);
}
void GameInteractor_ExecuteOnUpdateFileNameSelection(int16_t charCode) {
@ -285,7 +286,7 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)) {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnAssetAltChange>(fn);
}
//MARK: Pause Menu
// MARK: Pause Menu
void GameInteractor_ExecuteOnKaleidoUpdate() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnKaleidoUpdate>();

View file

@ -31,7 +31,7 @@ void GameInteractor_ExecuteOnActorUpdate(void* actor);
void GameInteractor_ExecuteOnActorKill(void* actor);
void GameInteractor_ExecuteOnEnemyDefeat(void* actor);
void GameInteractor_ExecuteOnBossDefeat(void* actor);
void GameInteractor_ExecuteOnTimestamp (u8 item);
void GameInteractor_ExecuteOnTimestamp(u8 item);
void GameInteractor_ExecuteOnPlayerBonk();
void GameInteractor_ExecuteOnPlayerHealthChange(int16_t amount);
void GameInteractor_ExecuteOnPlayerBottleUpdate(int16_t contents);
@ -76,7 +76,7 @@ void GameInteractor_ExecuteOnSetGameLanguage();
// MARK: - System
void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void));
//Mark: - Pause Menu
// Mark: - Pause Menu
void GameInteractor_ExecuteOnKaleidoUpdate();
#ifdef __cplusplus

View file

@ -143,11 +143,13 @@ void GameInteractor::RawAction::SetSceneFlag(int16_t sceneNum, int16_t flagType,
}
break;
case FlagType::FLAG_SCENE_CLEAR:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.clear |= (1 << flag);
if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.clear |= (1 << flag);
gSaveContext.sceneFlags[sceneNum].clear |= (1 << flag);
break;
case FlagType::FLAG_SCENE_TREASURE:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.chest |= (1 << flag);
if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.chest |= (1 << flag);
gSaveContext.sceneFlags[sceneNum].chest |= (1 << flag);
break;
case FlagType::FLAG_SCENE_COLLECTIBLE:
@ -182,11 +184,13 @@ void GameInteractor::RawAction::UnsetSceneFlag(int16_t sceneNum, int16_t flagTyp
}
break;
case FlagType::FLAG_SCENE_CLEAR:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.clear &= ~(1 << flag);
if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.clear &= ~(1 << flag);
gSaveContext.sceneFlags[sceneNum].clear &= ~(1 << flag);
break;
case FlagType::FLAG_SCENE_TREASURE:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.chest &= ~(1 << flag);
if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.chest &= ~(1 << flag);
gSaveContext.sceneFlags[sceneNum].chest &= ~(1 << flag);
break;
case FlagType::FLAG_SCENE_COLLECTIBLE:
@ -337,7 +341,7 @@ void GameInteractor::RawAction::UpdateActor(void* refActor) {
// Update actor again outside of their normal update cycle.
Actor* actor = static_cast<Actor*>(refActor);
// Sometimes the actor is destroyed in the previous Update, so check if the update function still exists.
if (actor->update != NULL) {
// Fix for enemies sometimes taking a "fake" hit, where their invincibility timer is
@ -355,7 +359,8 @@ void GameInteractor::RawAction::UpdateActor(void* refActor) {
}
void GameInteractor::RawAction::TeleportPlayer(int32_t nextEntrance) {
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
gPlayState->nextEntranceIndex = nextEntrance;
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;
@ -386,7 +391,7 @@ void GameInteractor::RawAction::SetTimeOfDay(uint32_t time) {
void GameInteractor::RawAction::SetCollisionViewer(bool active) {
CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), active);
CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Decal"), active);
if (active) {
CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_TRANSPARENT);
CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_TRANSPARENT);
@ -406,8 +411,8 @@ void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint
newColor.g = 255;
newColor.b = 255;
newColor.a = 255;
switch (colorValue) {
switch (colorValue) {
case GI_COLOR_RED:
newColor.r = 200;
newColor.g = 30;
@ -457,7 +462,7 @@ void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint
break;
}
switch (cosmeticCategory) {
switch (cosmeticCategory) {
case GI_COSMETICS_TUNICS:
CVarSetColor(CVAR_COSMETIC("Link.KokiriTunic.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Link.KokiriTunic.Changed"), 1);
@ -495,19 +500,13 @@ void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint
}
void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) {
const char* cvarsToLock[12] = {
CVAR_COSMETIC("Link.KokiriTunic.Locked"),
CVAR_COSMETIC("Link.GoronTunic.Locked"),
CVAR_COSMETIC("Link.ZoraTunic.Locked"),
CVAR_COSMETIC("Navi.EnemyPrimary.Locked"),
CVAR_COSMETIC("Navi.EnemySecondary.Locked"),
CVAR_COSMETIC("Navi.IdlePrimary.Locked"),
CVAR_COSMETIC("Navi.IdleSecondary.Locked"),
CVAR_COSMETIC("Navi.NPCPrimary.Locked"),
CVAR_COSMETIC("Navi.NPCSecondary.Locked"),
CVAR_COSMETIC("Navi.PropsPrimary.Locked"),
CVAR_COSMETIC("Navi.PropsSecondary.Locked"),
CVAR_COSMETIC("Link.Hair.Locked")
const char* cvarsToLock[12] = {
CVAR_COSMETIC("Link.KokiriTunic.Locked"), CVAR_COSMETIC("Link.GoronTunic.Locked"),
CVAR_COSMETIC("Link.ZoraTunic.Locked"), CVAR_COSMETIC("Navi.EnemyPrimary.Locked"),
CVAR_COSMETIC("Navi.EnemySecondary.Locked"), CVAR_COSMETIC("Navi.IdlePrimary.Locked"),
CVAR_COSMETIC("Navi.IdleSecondary.Locked"), CVAR_COSMETIC("Navi.NPCPrimary.Locked"),
CVAR_COSMETIC("Navi.NPCSecondary.Locked"), CVAR_COSMETIC("Navi.PropsPrimary.Locked"),
CVAR_COSMETIC("Navi.PropsSecondary.Locked"), CVAR_COSMETIC("Link.Hair.Locked")
};
if (excludeBiddingWarColors) {
@ -533,7 +532,7 @@ void GameInteractor::RawAction::EmulateRandomButtonPress(uint32_t chancePercenta
uint32_t emulatedButton;
uint32_t randomNumber = rand();
uint32_t possibleButtons[14] = { BTN_CRIGHT, BTN_CLEFT, BTN_CDOWN, BTN_CUP, BTN_R, BTN_L, BTN_DRIGHT,
BTN_DLEFT, BTN_DDOWN, BTN_DUP, BTN_START, BTN_Z, BTN_B, BTN_A };
BTN_DLEFT, BTN_DDOWN, BTN_DUP, BTN_START, BTN_Z, BTN_B, BTN_A };
emulatedButton = possibleButtons[randomNumber % 14];
@ -575,12 +574,14 @@ void GameInteractor::RawAction::SetPlayerInvincibility(bool active) {
/// Clears the cutscene pointer to a value safe for wrong warps.
void GameInteractor::RawAction::ClearCutscenePointer() {
if (!gPlayState) return;
static uint32_t null_cs[] = {0, 0};
if (!gPlayState)
return;
static uint32_t null_cs[] = { 0, 0 };
gPlayState->csCtx.segment = &null_cs;
}
GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams) {
GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId,
int32_t enemyParams) {
if (!GameInteractor::CanSpawnActor()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@ -608,8 +609,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
// Don't allow Arwings in certain areas because they cause issues.
// Locations: King dodongo room, Morpha room, Twinrova room, Ganondorf room, Fishing pond, Ganon's room
// TODO: Swap this to disabling the option in CC options menu instead.
if (sceneNum == SCENE_DODONGOS_CAVERN_BOSS || sceneNum == SCENE_WATER_TEMPLE_BOSS || sceneNum == SCENE_SPIRIT_TEMPLE_BOSS ||
sceneNum == SCENE_GANONDORF_BOSS || sceneNum == SCENE_FISHING_POND || sceneNum == SCENE_GANON_BOSS) {
if (sceneNum == SCENE_DODONGOS_CAVERN_BOSS || sceneNum == SCENE_WATER_TEMPLE_BOSS ||
sceneNum == SCENE_SPIRIT_TEMPLE_BOSS || sceneNum == SCENE_GANONDORF_BOSS ||
sceneNum == SCENE_FISHING_POND || sceneNum == SCENE_GANON_BOSS) {
return GameInteractionEffectQueryResult::NotPossible;
}
}
@ -649,13 +651,15 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
pos.x += 10;
pos.y += 10;
pos.z += 10;
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) == NULL) {
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) ==
NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
}
}
return GameInteractionEffectQueryResult::Possible;
} else {
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) != NULL) {
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) !=
NULL) {
return GameInteractionEffectQueryResult::Possible;
}
}
@ -673,8 +677,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
if (actorId == ACTOR_EN_NIW) {
// Spawn Cucco and make it angry
EnNiw* cucco = (EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x,
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, actorParams, 0);
EnNiw* cucco =
(EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x,
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, actorParams, 0);
if (cucco == NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
}
@ -683,8 +688,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
return GameInteractionEffectQueryResult::Possible;
} else if (actorId == ACTOR_EN_BOM) {
// Spawn a bomb, make it explode instantly when params is set to 1 to emulate spawning an explosion
EnBom* bomb = (EnBom*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_BOM, player->actor.world.pos.x,
player->actor.world.pos.y + 30, player->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true);
EnBom* bomb =
(EnBom*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_BOM, player->actor.world.pos.x,
player->actor.world.pos.y + 30, player->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true);
if (bomb == NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@ -704,5 +710,4 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
}
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
}

View file

@ -136,7 +136,8 @@ typedef enum {
// #### `result`
// ```c
// !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)
// !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) &&
// Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)
// ```
// #### `args`
// - None
@ -163,7 +164,8 @@ typedef enum {
// #### `result`
// ```c
// CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)
// CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) &&
// !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)
// ```
// #### `args`
// - None
@ -275,7 +277,7 @@ typedef enum {
// #### `args`
// - `*EnDoor`
VB_CONSUME_SMALL_KEY,
// #### `result`
// ```c
// itemDropped >= 0 && itemDropped < 0x1A
@ -302,7 +304,8 @@ typedef enum {
// #### `result`
// ```c
// gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD
// gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum !=
// SCENE_GRAVEYARD
// ```
// #### `args`
// - `*EnTk`
@ -371,7 +374,8 @@ typedef enum {
// #### `result`
// ```c
// play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)
// play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT ||
// !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)
// ```
// #### `args`
// - `*EnCow`
@ -1322,7 +1326,8 @@ typedef enum {
// Close enough & various cutscene checks
// ```c
// (func_80AEC5FC(this, play)) && (!Play_InCsMode(play)) &&
// (!(player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER))) &&
// (!(player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE |
// PLAYER_STATE1_CLIMBING_LADDER))) &&
// (player->actor.bgCheckFlags & 1)
// ```
// #### `args`
@ -1676,7 +1681,8 @@ typedef enum {
// #### `result`
// ```c
// (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT
// (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) &&
// !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT
// ```
// #### `args`
// - None

View file

@ -17,4 +17,5 @@
extern PlayState* gPlayState;
void GameConsole_Init() {}
void GameConsole_Init() {
}

View file

@ -8,22 +8,19 @@
#define MAX_CVARS 2048
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
typedef enum
{
typedef enum {
CONSOLECOMMAND_RESULT_SUCCESS,
CONSOLECOMMAND_RESULT_INVALIDARGS,
CONSOLECOMMAND_RESULT_INVALIDCOMMAND,
CONSOLECOMMAND_RESULT_FAILURE
} ConsoleCommandResult;
typedef ConsoleCommandResult(*ConsoleCommandFunc)(char** argv, s32 argc); // Returns the number of arguments it read
typedef ConsoleCommandResult (*ConsoleCommandFunc)(char** argv, s32 argc); // Returns the number of arguments it read
typedef struct ConsoleCommand
{
typedef struct ConsoleCommand {
char* name;
ConsoleCommandFunc func;
char* description;

View file

@ -124,7 +124,7 @@ const char* const sceneMappings[] = {
"Goron City",
"Lon Lon Ranch",
"Outside Ganon's Castle",
//Debug Rooms
// Debug Rooms
"Test Map",
"Test Room",
"Depth Test",
@ -230,15 +230,15 @@ const char* const countMappings[] = {
"Start:",
};
#define COLOR_WHITE ImVec4(1.00f, 1.00f, 1.00f, 1.00f)
#define COLOR_RED ImVec4(1.00f, 0.00f, 0.00f, 1.00f)
#define COLOR_GREEN ImVec4(0.10f, 1.00f, 0.10f, 1.00f)
#define COLOR_BLUE ImVec4(0.00f, 0.33f, 1.00f, 1.00f)
#define COLOR_PURPLE ImVec4(0.54f, 0.19f, 0.89f, 1.00f)
#define COLOR_YELLOW ImVec4(1.00f, 1.00f, 0.00f, 1.00f)
#define COLOR_ORANGE ImVec4(1.00f, 0.67f, 0.11f, 1.00f)
#define COLOR_WHITE ImVec4(1.00f, 1.00f, 1.00f, 1.00f)
#define COLOR_RED ImVec4(1.00f, 0.00f, 0.00f, 1.00f)
#define COLOR_GREEN ImVec4(0.10f, 1.00f, 0.10f, 1.00f)
#define COLOR_BLUE ImVec4(0.00f, 0.33f, 1.00f, 1.00f)
#define COLOR_PURPLE ImVec4(0.54f, 0.19f, 0.89f, 1.00f)
#define COLOR_YELLOW ImVec4(1.00f, 1.00f, 0.00f, 1.00f)
#define COLOR_ORANGE ImVec4(1.00f, 0.67f, 0.11f, 1.00f)
#define COLOR_LIGHT_BLUE ImVec4(0.00f, 0.88f, 1.00f, 1.00f)
#define COLOR_GREY ImVec4(0.78f, 0.78f, 0.78f, 1.00f)
#define COLOR_GREY ImVec4(0.78f, 0.78f, 0.78f, 1.00f)
char itemTimestampDisplayName[TIMESTAMP_MAX][21] = { "" };
ImVec4 itemTimestampDisplayColor[TIMESTAMP_MAX];
@ -248,14 +248,14 @@ typedef struct {
u32 time;
ImVec4 color;
bool isRoom;
}TimestampInfo;
} TimestampInfo;
// Timestamps are an array of structs, each with a name, time, and color
// Names and colors are set up at the bottom of this file.
// Times are stored in gSaveContext.ship.stats.itemTimestamp.
TimestampInfo itemTimestampDisplay[TIMESTAMP_MAX];
TimestampInfo sceneTimestampDisplay[8191];
//std::vector<TimestampInfo> sceneTimestampDisplay;
// std::vector<TimestampInfo> sceneTimestampDisplay;
std::string formatTimestampGameplayStat(uint32_t value) {
uint32_t sec = value / 10;
@ -302,37 +302,38 @@ void LoadStatsVersion1() {
SaveManager::Instance->LoadData("fileCreatedAt", gSaveContext.ship.stats.fileCreatedAt);
SaveManager::Instance->LoadData("playTimer", gSaveContext.ship.stats.playTimer);
SaveManager::Instance->LoadData("pauseTimer", gSaveContext.ship.stats.pauseTimer);
SaveManager::Instance->LoadArray("itemTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.itemTimestamp), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.itemTimestamp[i]);
});
SaveManager::Instance->LoadArray("sceneTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.sceneTimestamps), [&](size_t i) {
SaveManager::Instance->LoadStruct("", [&]() {
int scene, room, sceneTime, roomTime, isRoom;
SaveManager::Instance->LoadData("scene", scene);
SaveManager::Instance->LoadData("room", room);
SaveManager::Instance->LoadData("sceneTime", sceneTime);
SaveManager::Instance->LoadData("roomTime", roomTime);
SaveManager::Instance->LoadData("isRoom", isRoom);
if (scene == 0 && room == 0 && sceneTime == 0 && roomTime == 0 && isRoom == 0) {
return;
}
gSaveContext.ship.stats.sceneTimestamps[i].scene = scene;
gSaveContext.ship.stats.sceneTimestamps[i].room = room;
gSaveContext.ship.stats.sceneTimestamps[i].sceneTime = sceneTime;
gSaveContext.ship.stats.sceneTimestamps[i].roomTime = roomTime;
gSaveContext.ship.stats.sceneTimestamps[i].isRoom = isRoom;
SaveManager::Instance->LoadArray(
"itemTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.itemTimestamp),
[](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.itemTimestamp[i]); });
SaveManager::Instance->LoadArray(
"sceneTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.sceneTimestamps), [&](size_t i) {
SaveManager::Instance->LoadStruct("", [&]() {
int scene, room, sceneTime, roomTime, isRoom;
SaveManager::Instance->LoadData("scene", scene);
SaveManager::Instance->LoadData("room", room);
SaveManager::Instance->LoadData("sceneTime", sceneTime);
SaveManager::Instance->LoadData("roomTime", roomTime);
SaveManager::Instance->LoadData("isRoom", isRoom);
if (scene == 0 && room == 0 && sceneTime == 0 && roomTime == 0 && isRoom == 0) {
return;
}
gSaveContext.ship.stats.sceneTimestamps[i].scene = scene;
gSaveContext.ship.stats.sceneTimestamps[i].room = room;
gSaveContext.ship.stats.sceneTimestamps[i].sceneTime = sceneTime;
gSaveContext.ship.stats.sceneTimestamps[i].roomTime = roomTime;
gSaveContext.ship.stats.sceneTimestamps[i].isRoom = isRoom;
});
});
});
SaveManager::Instance->LoadData("tsIdx", gSaveContext.ship.stats.tsIdx);
SaveManager::Instance->LoadArray("counts", ARRAY_COUNT(gSaveContext.ship.stats.count), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.count[i]);
});
SaveManager::Instance->LoadArray("scenesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.scenesDiscovered[i]);
});
SaveManager::Instance->LoadArray("entrancesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]);
});
SaveManager::Instance->LoadArray(
"scenesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered),
[](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.scenesDiscovered[i]); });
SaveManager::Instance->LoadArray(
"entrancesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered),
[](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]); });
}
void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) {
@ -350,30 +351,32 @@ void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) {
SaveManager::Instance->SaveData("fileCreatedAt", saveContext->ship.stats.fileCreatedAt);
SaveManager::Instance->SaveData("playTimer", saveContext->ship.stats.playTimer);
SaveManager::Instance->SaveData("pauseTimer", saveContext->ship.stats.pauseTimer);
SaveManager::Instance->SaveArray("itemTimestamps", ARRAY_COUNT(saveContext->ship.stats.itemTimestamp), [&](size_t i) {
SaveManager::Instance->SaveData("", saveContext->ship.stats.itemTimestamp[i]);
});
SaveManager::Instance->SaveArray("sceneTimestamps", ARRAY_COUNT(saveContext->ship.stats.sceneTimestamps), [&](size_t i) {
if (saveContext->ship.stats.sceneTimestamps[i].scene != 254 && saveContext->ship.stats.sceneTimestamps[i].room != 254) {
SaveManager::Instance->SaveStruct("", [&]() {
SaveManager::Instance->SaveData("scene", saveContext->ship.stats.sceneTimestamps[i].scene);
SaveManager::Instance->SaveData("room", saveContext->ship.stats.sceneTimestamps[i].room);
SaveManager::Instance->SaveData("sceneTime", saveContext->ship.stats.sceneTimestamps[i].sceneTime);
SaveManager::Instance->SaveData("roomTime", saveContext->ship.stats.sceneTimestamps[i].roomTime);
SaveManager::Instance->SaveData("isRoom", saveContext->ship.stats.sceneTimestamps[i].isRoom);
});
}
});
SaveManager::Instance->SaveArray(
"itemTimestamps", ARRAY_COUNT(saveContext->ship.stats.itemTimestamp),
[&](size_t i) { SaveManager::Instance->SaveData("", saveContext->ship.stats.itemTimestamp[i]); });
SaveManager::Instance->SaveArray(
"sceneTimestamps", ARRAY_COUNT(saveContext->ship.stats.sceneTimestamps), [&](size_t i) {
if (saveContext->ship.stats.sceneTimestamps[i].scene != 254 &&
saveContext->ship.stats.sceneTimestamps[i].room != 254) {
SaveManager::Instance->SaveStruct("", [&]() {
SaveManager::Instance->SaveData("scene", saveContext->ship.stats.sceneTimestamps[i].scene);
SaveManager::Instance->SaveData("room", saveContext->ship.stats.sceneTimestamps[i].room);
SaveManager::Instance->SaveData("sceneTime", saveContext->ship.stats.sceneTimestamps[i].sceneTime);
SaveManager::Instance->SaveData("roomTime", saveContext->ship.stats.sceneTimestamps[i].roomTime);
SaveManager::Instance->SaveData("isRoom", saveContext->ship.stats.sceneTimestamps[i].isRoom);
});
}
});
SaveManager::Instance->SaveData("tsIdx", saveContext->ship.stats.tsIdx);
SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(saveContext->ship.stats.count), [&](size_t i) {
SaveManager::Instance->SaveData("", saveContext->ship.stats.count[i]);
});
SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(saveContext->ship.stats.scenesDiscovered), [&](size_t i) {
SaveManager::Instance->SaveData("", saveContext->ship.stats.scenesDiscovered[i]);
});
SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(saveContext->ship.stats.entrancesDiscovered), [&](size_t i) {
SaveManager::Instance->SaveData("", saveContext->ship.stats.entrancesDiscovered[i]);
});
SaveManager::Instance->SaveArray(
"scenesDiscovered", ARRAY_COUNT(saveContext->ship.stats.scenesDiscovered),
[&](size_t i) { SaveManager::Instance->SaveData("", saveContext->ship.stats.scenesDiscovered[i]); });
SaveManager::Instance->SaveArray(
"entrancesDiscovered", ARRAY_COUNT(saveContext->ship.stats.entrancesDiscovered),
[&](size_t i) { SaveManager::Instance->SaveData("", saveContext->ship.stats.entrancesDiscovered[i]); });
}
void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color = COLOR_WHITE,
@ -394,7 +397,7 @@ bool compareTimestampInfoByTime(const TimestampInfo& a, const TimestampInfo& b)
return CVarGetInteger(CVAR_GAMEPLAY_STATS("ReverseTimestamps"), 0) ? a.time > b.time : a.time < b.time;
}
const char* ResolveSceneID(int sceneID, int roomID){
const char* ResolveSceneID(int sceneID, int roomID) {
if (sceneID == SCENE_GROTTOS) {
switch (roomID) {
case 0:
@ -427,7 +430,7 @@ const char* ResolveSceneID(int sceneID, int roomID){
return "Big Skulltula Grotto";
};
} else if (sceneID == SCENE_WINDMILL_AND_DAMPES_GRAVE) {
//Only the last room of Dampe's Grave (rm 6) is considered the windmill.
// Only the last room of Dampe's Grave (rm 6) is considered the windmill.
return roomID == 6 ? "Windmill" : "Dampe's Grave";
} else if (sceneID < SCENE_ID_MAX) {
return sceneMappings[sceneID];
@ -440,7 +443,7 @@ void DrawGameplayStatsHeader() {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 4.0f, 4.0f });
ImGui::BeginTable("gameplayStatsHeader", 1, ImGuiTableFlags_BordersOuter);
ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch);
//if tag is empty (not a release build)
// if tag is empty (not a release build)
if (gGitCommitTag[0] == 0) {
GameplayStatsRow("Git Branch:", (char*)gGitBranch);
GameplayStatsRow("Git Commit Hash:", (char*)gGitCommitHash);
@ -448,21 +451,30 @@ void DrawGameplayStatsHeader() {
GameplayStatsRow("Build Version:", (char*)gBuildVersion);
}
if (gSaveContext.ship.stats.rtaTiming) {
GameplayStatsRow("Total Time (RTA):", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
GameplayStatsRow("Total Time (RTA):", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME),
gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
} else {
GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME),
gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
}
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowAdditionalTimers"), 0)) { // !Only display total game time
GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.playTimer / 2), COLOR_GREY);
GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.pauseTimer / 3), COLOR_GREY);
GameplayStatsRow("Time in scene:", formatTimestampGameplayStat(gSaveContext.ship.stats.sceneTimer / 2), COLOR_LIGHT_BLUE);
GameplayStatsRow("Time in room:", formatTimestampGameplayStat(gSaveContext.ship.stats.roomTimer / 2), COLOR_LIGHT_BLUE);
GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.playTimer / 2),
COLOR_GREY);
GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.pauseTimer / 3),
COLOR_GREY);
GameplayStatsRow("Time in scene:", formatTimestampGameplayStat(gSaveContext.ship.stats.sceneTimer / 2),
COLOR_LIGHT_BLUE);
GameplayStatsRow("Time in room:", formatTimestampGameplayStat(gSaveContext.ship.stats.roomTimer / 2),
COLOR_LIGHT_BLUE);
}
if (gPlayState != NULL && CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowDebugInfo"), 0)) { // && display debug info
GameplayStatsRow("play->sceneNum:", formatHexGameplayStat(gPlayState->sceneNum), COLOR_YELLOW);
GameplayStatsRow("gSaveContext.entranceIndex:", formatHexGameplayStat(gSaveContext.entranceIndex), COLOR_YELLOW);
GameplayStatsRow("gSaveContext.cutsceneIndex:", formatHexOnlyGameplayStat(gSaveContext.cutsceneIndex), COLOR_YELLOW);
GameplayStatsRow("play->roomCtx.curRoom.num:", formatIntGameplayStat(gPlayState->roomCtx.curRoom.num), COLOR_YELLOW);
GameplayStatsRow("gSaveContext.entranceIndex:", formatHexGameplayStat(gSaveContext.entranceIndex),
COLOR_YELLOW);
GameplayStatsRow("gSaveContext.cutsceneIndex:", formatHexOnlyGameplayStat(gSaveContext.cutsceneIndex),
COLOR_YELLOW);
GameplayStatsRow("play->roomCtx.curRoom.num:", formatIntGameplayStat(gPlayState->roomCtx.curRoom.num),
COLOR_YELLOW);
}
ImGui::EndTable();
ImGui::PopStyleVar(1);
@ -484,12 +496,12 @@ void DrawGameplayStatsTimestampsTab() {
for (int i = 0; i < TIMESTAMP_MAX; i++) {
// To be shown, the entry must have a non-zero time and a string for its display name
if (itemTimestampDisplay[i].time > 0 && strnlen(itemTimestampDisplay[i].name, 21) > 1) {
GameplayStatsRow(itemTimestampDisplay[i].name, formatTimestampGameplayStat(itemTimestampDisplay[i].time), itemTimestampDisplay[i].color);
GameplayStatsRow(itemTimestampDisplay[i].name, formatTimestampGameplayStat(itemTimestampDisplay[i].time),
itemTimestampDisplay[i].color);
}
}
ImGui::EndTable();
ImGui::PopStyleVar(1);
}
void DrawGameplayStatsCountsTab() {
@ -520,7 +532,8 @@ void DrawGameplayStatsCountsTab() {
ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch);
GameplayStatsRow("Enemies Defeated:", formatIntGameplayStat(enemiesDefeated));
if (enemiesDefeated > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn();
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Enemy Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_ENEMIES_DEFEATED_ANUBIS; i <= COUNT_ENEMIES_DEFEATED_WOLFOS; i++) {
if (i == COUNT_ENEMIES_DEFEATED_FLOORMASTER) {
@ -537,7 +550,8 @@ void DrawGameplayStatsCountsTab() {
GameplayStatsRow("Chests Opened:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_CHESTS_OPENED]));
GameplayStatsRow("Ammo Used:", formatIntGameplayStat(ammoUsed));
if (ammoUsed > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn();
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Ammo Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_AMMO_USED_STICK; i <= COUNT_AMMO_USED_BEAN; i++) {
GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i]));
@ -548,8 +562,10 @@ void DrawGameplayStatsCountsTab() {
GameplayStatsRow("Sword Swings:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_SWORD_SWINGS]));
GameplayStatsRow("Steps Taken:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_STEPS]));
// If using MM Bunny Hood enhancement, show how long it's been equipped (not counting pause time)
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] > 0) {
GameplayStatsRow("Bunny Hood Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] / 2));
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA ||
gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] > 0) {
GameplayStatsRow("Bunny Hood Time:",
formatTimestampGameplayStat(gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] / 2));
}
GameplayStatsRow("Rolls:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_ROLLS]));
GameplayStatsRow("Bonks:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BONKS]));
@ -561,7 +577,8 @@ void DrawGameplayStatsCountsTab() {
GameplayStatsRow("Bushes Cut:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BUSHES_CUT]));
GameplayStatsRow("Buttons Pressed:", formatIntGameplayStat(buttonPresses));
if (buttonPresses > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn();
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Buttons...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_BUTTON_PRESSES_A; i <= COUNT_BUTTON_PRESSES_START; i++) {
GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i]));
@ -574,16 +591,19 @@ void DrawGameplayStatsCountsTab() {
void DrawGameplayStatsBreakdownTab() {
for (int i = 0; i < gSaveContext.ship.stats.tsIdx; i++) {
std::string sceneName = ResolveSceneID(gSaveContext.ship.stats.sceneTimestamps[i].scene, gSaveContext.ship.stats.sceneTimestamps[i].room);
std::string sceneName = ResolveSceneID(gSaveContext.ship.stats.sceneTimestamps[i].scene,
gSaveContext.ship.stats.sceneTimestamps[i].room);
std::string name;
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneTimestamps[i].scene != SCENE_GROTTOS) {
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) &&
gSaveContext.ship.stats.sceneTimestamps[i].scene != SCENE_GROTTOS) {
name = fmt::format("{:s} Room {:d}", sceneName, gSaveContext.ship.stats.sceneTimestamps[i].room);
} else {
name = sceneName;
}
strcpy(sceneTimestampDisplay[i].name, name.c_str());
sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ?
gSaveContext.ship.stats.sceneTimestamps[i].roomTime : gSaveContext.ship.stats.sceneTimestamps[i].sceneTime;
sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0)
? gSaveContext.ship.stats.sceneTimestamps[i].roomTime
: gSaveContext.ship.stats.sceneTimestamps[i].sceneTime;
sceneTimestampDisplay[i].color = COLOR_GREY;
sceneTimestampDisplay[i].isRoom = gSaveContext.ship.stats.sceneTimestamps[i].isRoom;
}
@ -600,7 +620,9 @@ void DrawGameplayStatsBreakdownTab() {
}
std::string toPass;
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneNum != SCENE_GROTTOS) {
toPass = fmt::format("{:s} Room {:d}", ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum), gSaveContext.ship.stats.roomNum);
toPass = fmt::format("{:s} Room {:d}",
ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum),
gSaveContext.ship.stats.roomNum);
} else {
toPass = ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum);
}
@ -611,27 +633,27 @@ void DrawGameplayStatsBreakdownTab() {
void DrawGameplayStatsOptionsTab() {
UIWidgets::CVarCheckbox("Show in-game total timer", CVAR_GAMEPLAY_STATS("ShowIngameTimer"),
UIWidgets::CheckboxOptions()
.Tooltip("Keep track of the timer as an in-game HUD element. The position of the "
"timer can be changed in the Cosmetics Editor.")
.Color(THEME_COLOR));
UIWidgets::CheckboxOptions()
.Tooltip("Keep track of the timer as an in-game HUD element. The position of the "
"timer can be changed in the Cosmetics Editor.")
.Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show latest timestamps on top", CVAR_GAMEPLAY_STATS("ReverseTimestamps"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Room Breakdown", CVAR_GAMEPLAY_STATS("RoomBreakdown"),
UIWidgets::CheckboxOptions()
.Tooltip("Allows a more in-depth perspective of time spent in a certain map.")
.Color(THEME_COLOR));
UIWidgets::CheckboxOptions()
.Tooltip("Allows a more in-depth perspective of time spent in a certain map.")
.Color(THEME_COLOR));
UIWidgets::CVarCheckbox("RTA Timing on new files", CVAR_GAMEPLAY_STATS("RTATiming"),
UIWidgets::CheckboxOptions()
.Tooltip("Timestamps are relative to starting timestamp rather than in game time, "
"usually necessary for races/speedruns.\n\n"
"Starting timestamp is on first non-C-up input after intro cutscene.\n\n"
"NOTE: THIS NEEDS TO BE SET BEFORE CREATING A FILE TO TAKE EFFECT")
.Color(THEME_COLOR));
UIWidgets::CheckboxOptions()
.Tooltip("Timestamps are relative to starting timestamp rather than in game time, "
"usually necessary for races/speedruns.\n\n"
"Starting timestamp is on first non-C-up input after intro cutscene.\n\n"
"NOTE: THIS NEEDS TO BE SET BEFORE CREATING A FILE TO TAKE EFFECT")
.Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show additional detail timers", CVAR_GAMEPLAY_STATS("ShowAdditionalTimers"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show Debug Info", CVAR_GAMEPLAY_STATS("ShowDebugInfo"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CheckboxOptions().Color(THEME_COLOR));
}
void GameplayStatsWindow::DrawElement() {
@ -693,7 +715,8 @@ void InitStats(bool isDebug) {
for (int scenesIdx = 0; scenesIdx < ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered); scenesIdx++) {
gSaveContext.ship.stats.scenesDiscovered[scenesIdx] = 0;
}
for (int entrancesIdx = 0; entrancesIdx < ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered); entrancesIdx++) {
for (int entrancesIdx = 0; entrancesIdx < ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered);
entrancesIdx++) {
gSaveContext.ship.stats.entrancesDiscovered[entrancesIdx] = 0;
}

View file

@ -6,30 +6,32 @@
#ifdef __cplusplus
extern "C" {
#endif
uint64_t GetUnixTimestamp(void);
char* GameplayStats_GetCurrentTime();
uint64_t GetUnixTimestamp(void);
char* GameplayStats_GetCurrentTime();
#ifdef __cplusplus
};
#endif
// When using RTA timing
// get the diff since the save was created,
// unless the game is complete in which we use the defeated ganon timestamp
// get the diff since the save was created,
// unless the game is complete in which we use the defeated ganon timestamp
// When not using RTA timing
// Total gameplay time is tracked in tenths of seconds
// I.E. game time counts frames at 20fps/2, pause time counts frames at 30fps/3
// Frame counts in z_play.c and z_kaleido_scope_call.c
#define GAMEPLAYSTAT_TOTAL_TIME (gSaveContext.ship.stats.rtaTiming ?\
(!gSaveContext.ship.stats.gameComplete ?\
(!gSaveContext.ship.stats.fileCreatedAt ? 0 : ((GetUnixTimestamp() - gSaveContext.ship.stats.fileCreatedAt) / 100)) :\
(gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \
// Total gameplay time is tracked in tenths of seconds
// I.E. game time counts frames at 20fps/2, pause time counts frames at 30fps/3
// Frame counts in z_play.c and z_kaleido_scope_call.c
#define GAMEPLAYSTAT_TOTAL_TIME \
(gSaveContext.ship.stats.rtaTiming \
? (!gSaveContext.ship.stats.gameComplete \
? (!gSaveContext.ship.stats.fileCreatedAt \
? 0 \
: ((GetUnixTimestamp() - gSaveContext.ship.stats.fileCreatedAt) / 100)) \
: (gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \
? gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \
: gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED])) \
:\
(gSaveContext.ship.stats.playTimer / 2 + gSaveContext.ship.stats.pauseTimer / 3))
#define CURRENT_MODE_TIMER (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ?\
gSaveContext.ship.stats.roomTimer :\
gSaveContext.ship.stats.sceneTimer)
: (gSaveContext.ship.stats.playTimer / 2 + gSaveContext.ship.stats.pauseTimer / 3))
#define CURRENT_MODE_TIMER \
(CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ? gSaveContext.ship.stats.roomTimer \
: gSaveContext.ship.stats.sceneTimer)
void InitStatTracker();
@ -37,22 +39,22 @@ typedef enum {
// 0x00 to 0x9B (0 to 155) used for getting items,
// piggybacked off enum "ItemID" in z64item.h
/* 0xA0 */ TIMESTAMP_DEFEAT_GOHMA = 0xA0, // z_boss_goma.c
/* 0xA1 */ TIMESTAMP_DEFEAT_KING_DODONGO, // z_boss_dodongo.c
/* 0xA2 */ TIMESTAMP_DEFEAT_BARINADE, // z_boss_va.c
/* 0xA3 */ TIMESTAMP_DEFEAT_PHANTOM_GANON, // z_boss_ganondrof.c
/* 0xA4 */ TIMESTAMP_DEFEAT_VOLVAGIA, // z_boss_fd2.c
/* 0xA5 */ TIMESTAMP_DEFEAT_MORPHA, // z_boss_mo.c
/* 0xA6 */ TIMESTAMP_DEFEAT_BONGO_BONGO, // z_boss_sst.c
/* 0xA7 */ TIMESTAMP_DEFEAT_TWINROVA, // z_boss_tw.c
/* 0xA8 */ TIMESTAMP_DEFEAT_GANONDORF, // z_boss_ganon.c
/* 0xA9 */ TIMESTAMP_DEFEAT_GANON, // z_boss_ganon2.c
/* 0xA9 */ TIMESTAMP_BOSSRUSH_FINISH, // z_boss_ganon2.c
/* 0xAA */ TIMESTAMP_FOUND_GREG, // z_parameter.c
/* 0xAA */ TIMESTAMP_TRIFORCE_COMPLETED, // z_parameter.c
/* 0xA0 */ TIMESTAMP_DEFEAT_GOHMA = 0xA0, // z_boss_goma.c
/* 0xA1 */ TIMESTAMP_DEFEAT_KING_DODONGO, // z_boss_dodongo.c
/* 0xA2 */ TIMESTAMP_DEFEAT_BARINADE, // z_boss_va.c
/* 0xA3 */ TIMESTAMP_DEFEAT_PHANTOM_GANON, // z_boss_ganondrof.c
/* 0xA4 */ TIMESTAMP_DEFEAT_VOLVAGIA, // z_boss_fd2.c
/* 0xA5 */ TIMESTAMP_DEFEAT_MORPHA, // z_boss_mo.c
/* 0xA6 */ TIMESTAMP_DEFEAT_BONGO_BONGO, // z_boss_sst.c
/* 0xA7 */ TIMESTAMP_DEFEAT_TWINROVA, // z_boss_tw.c
/* 0xA8 */ TIMESTAMP_DEFEAT_GANONDORF, // z_boss_ganon.c
/* 0xA9 */ TIMESTAMP_DEFEAT_GANON, // z_boss_ganon2.c
/* 0xA9 */ TIMESTAMP_BOSSRUSH_FINISH, // z_boss_ganon2.c
/* 0xAA */ TIMESTAMP_FOUND_GREG, // z_parameter.c
/* 0xAA */ TIMESTAMP_TRIFORCE_COMPLETED, // z_parameter.c
/* 0xAB */ TIMESTAMP_MAX
}GameplayStatTimestamp;
} GameplayStatTimestamp;
typedef enum {
// Enemies defeated

View file

@ -6,5 +6,5 @@ class GameplayStatsWindow : public Ship::GuiWindow {
void InitElement() override;
void DrawElement() override;
void UpdateElement() override {};
void UpdateElement() override{};
};

View file

@ -8,16 +8,16 @@ typedef std::unordered_map<uint16_t, GetItemEntry> ItemTable;
class ItemTableManager {
public:
static ItemTableManager* Instance;
ItemTableManager();
~ItemTableManager();
bool AddItemTable(uint16_t tableID);
bool AddItemEntry(uint16_t tableID, uint16_t getItemID, GetItemEntry getItemEntry);
GetItemEntry RetrieveItemEntry(uint16_t tableID, uint16_t getItemID);
bool ClearItemTable(uint16_t tableID);
static ItemTableManager* Instance;
ItemTableManager();
~ItemTableManager();
bool AddItemTable(uint16_t tableID);
bool AddItemEntry(uint16_t tableID, uint16_t getItemID, GetItemEntry getItemEntry);
GetItemEntry RetrieveItemEntry(uint16_t tableID, uint16_t getItemID);
bool ClearItemTable(uint16_t tableID);
private:
std::unordered_map<uint16_t, ItemTable> itemTables;
std::unordered_map<uint16_t, ItemTable> itemTables;
ItemTable* RetrieveItemTable(uint16_t tableID);
ItemTable* RetrieveItemTable(uint16_t tableID);
};

View file

@ -29,11 +29,18 @@ typedef enum GetItemCategory {
/* 0x05 */ ITEM_CATEGORY_MAJOR,
} GetItemCategory;
#define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, getItemId) \
{ itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, modIndex, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL }
#define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, getItemId) \
{ \
itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, \
modIndex, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL \
}
#define GET_ITEM_CUSTOM_TABLE(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, tableId, getItemId) \
{ itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, tableId, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL }
#define GET_ITEM_CUSTOM_TABLE(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, tableId, \
getItemId) \
{ \
itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, \
tableId, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL \
}
#define GET_ITEM_NONE \
{ ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, ITEM_NONE, 0, NULL }
@ -50,13 +57,16 @@ typedef struct GetItemEntry {
/* 0x03 */ uint16_t textId;
/* 0x04 */ uint16_t objectId;
/* 0x06 */ uint16_t modIndex; // Primarily used for determining whether to use Item_Give or Randomizer_Item_Give
/* 0x07 */ uint16_t tableId; // GetItemEntry table this entry is in (usually the same as modIndex, but not always)
/* 0x07 */ uint16_t tableId; // GetItemEntry table this entry is in (usually the same as modIndex, but not always)
/* 0x08 */ int16_t getItemId;
/* 0x0A */ uint16_t gid; // Stores the GID value unmodified for future reference.
/* 0x0C */ uint16_t collectable; // determines whether the item can be collected on the overworld. Will be true in most cases.
/* 0x0C */ uint16_t
collectable; // determines whether the item can be collected on the overworld. Will be true in most cases.
/* 0x0E */ GetItemFrom getItemFrom;
/* 0x0F */ GetItemCategory getItemCategory; // Primarily made and used for chest size/texture matches contents
/* 0x10 */ uint16_t drawItemId; // Will be a copy of itemId unless the item is an ice trap. Needed for particles to function on ice traps.
/* 0x11 */ uint16_t drawModIndex; // Will be a copy of modIndex unless the item is an ice trap. Needed for particles to function on ice traps.
/* 0x10 */ uint16_t drawItemId; // Will be a copy of itemId unless the item is an ice trap. Needed for particles to
// function on ice traps.
/* 0x11 */ uint16_t drawModIndex; // Will be a copy of modIndex unless the item is an ice trap. Needed for particles
// to function on ice traps.
CustomDrawFunc drawFunc;
} GetItemEntry; // size = 0x11

View file

@ -27,429 +27,423 @@ void KaleidoScope_MoveCursorToSpecialPos(PlayState* play, u16 specialPos);
namespace Rando {
void KaleidoEntryIcon::LoadIconTex(std::vector<Gfx>* mEntryDl) {
if (mIconFormat == G_IM_FMT_IA) {
if (mIconSize == G_IM_SIZ_8b) {
Gfx iconTexture[] = { gsDPLoadTextureBlock(mIconResourceName, G_IM_FMT_IA, G_IM_SIZ_8b, mIconWidth, mIconHeight, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture));
}
} else if (mIconFormat == G_IM_FMT_RGBA) {
if (mIconSize == G_IM_SIZ_32b) {
Gfx iconTexture[] = { gsDPLoadTextureBlock(mIconResourceName, G_IM_FMT_RGBA, G_IM_SIZ_32b, mIconWidth, mIconHeight, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture));
}
void KaleidoEntryIcon::LoadIconTex(std::vector<Gfx>* mEntryDl) {
if (mIconFormat == G_IM_FMT_IA) {
if (mIconSize == G_IM_SIZ_8b) {
Gfx iconTexture[] = { gsDPLoadTextureBlock(
mIconResourceName, G_IM_FMT_IA, G_IM_SIZ_8b, mIconWidth, mIconHeight, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture));
}
} else if (mIconFormat == G_IM_FMT_RGBA) {
if (mIconSize == G_IM_SIZ_32b) {
Gfx iconTexture[] = { gsDPLoadTextureBlock(
mIconResourceName, G_IM_FMT_RGBA, G_IM_SIZ_32b, mIconWidth, mIconHeight, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture));
}
}
}
KaleidoEntry::KaleidoEntry(int16_t x, int16_t y, std::string text) : mX(x), mY(y), mText(std::move(text)) {
mHeight = 0;
mWidth = 0;
vtx = nullptr;
KaleidoEntry::KaleidoEntry(int16_t x, int16_t y, std::string text) : mX(x), mY(y), mText(std::move(text)) {
mHeight = 0;
mWidth = 0;
vtx = nullptr;
}
void KaleidoEntry::SetYOffset(int yOffset) {
mY = yOffset;
}
void KaleidoEntryIcon::Draw(PlayState* play, std::vector<Gfx>* mEntryDl) {
if (vtx == nullptr) {
return;
}
size_t numChar = mText.length();
if (numChar == 0) {
return;
}
void KaleidoEntry::SetYOffset(int yOffset) {
mY = yOffset;
Color_RGBA8 textColor = { 255, 255, 255, 255 };
if (mAchieved) {
textColor = { 0x98, 0xFF, 0x44, 255 };
}
void KaleidoEntryIcon::Draw(PlayState* play, std::vector<Gfx>* mEntryDl) {
if (vtx == nullptr) {
return;
}
size_t numChar = mText.length();
if (numChar == 0) {
return;
}
Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY);
Color_RGBA8 textColor = { 255, 255, 255, 255 };
if (mAchieved) {
textColor = { 0x98, 0xFF, 0x44, 255 };
}
mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW));
Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY);
mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW));
// icon
if (!mAchieved) {
mEntryDl->push_back(gsDPSetGrayscaleColor(109, 109, 109, 255));
mEntryDl->push_back(gsSPGrayscale(true));
}
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mIconColor.r, mIconColor.g, mIconColor.b, mIconColor.a));
mEntryDl->push_back(gsSPVertex(vtx, 4, 0));
LoadIconTex(mEntryDl);
mEntryDl->push_back(gsSP1Quadrangle(0, 2, 3, 1, 0));
mEntryDl->push_back(gsSPGrayscale(false));
// text
mEntryDl->push_back(gsDPSetPrimColor(0, 0, textColor.r, textColor.g, textColor.b, textColor.a));
for (size_t i = 0, vtxGroup = 0; i < numChar; i++) {
// A maximum of 64 Vtx can be loaded at once by gSPVertex, or basically 16 characters
// handle loading groups of 16 chars at a time until there are no more left to load.
// By this point 4 vertices have already been loaded for the preceding icon.
if (i % 16 == 0) {
size_t numVtxToLoad = std::min<size_t>(numChar - i, 16) * 4;
mEntryDl->push_back(gsSPVertex(&vtx[4 + (vtxGroup * 16 * 4)], numVtxToLoad, 0));
vtxGroup++;
}
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(
texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
}
mEntryDl->push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
// icon
if (!mAchieved) {
mEntryDl->push_back(gsDPSetGrayscaleColor(109, 109, 109, 255));
mEntryDl->push_back(gsSPGrayscale(true));
}
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mIconColor.r, mIconColor.g, mIconColor.b, mIconColor.a));
mEntryDl->push_back(gsSPVertex(vtx, 4, 0));
LoadIconTex(mEntryDl);
mEntryDl->push_back(gsSP1Quadrangle(0, 2, 3, 1, 0));
mEntryDl->push_back(gsSPGrayscale(false));
Kaleido::Kaleido() {
const auto ctx = Rando::Context::GetInstance();
int yOffset = 2;
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(gRupeeCounterIconTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16,
Color_RGBA8{ 0xC8, 0xFF, 0x64, 255 }, FlagType::FLAG_RANDOMIZER_INF,
static_cast<int>(RAND_INF_GREG_FOUND), 0, yOffset, "Greg"));
// text
mEntryDl->push_back(gsDPSetPrimColor(0, 0, textColor.r, textColor.g, textColor.b, textColor.a));
for (size_t i = 0, vtxGroup = 0; i < numChar; i++) {
// A maximum of 64 Vtx can be loaded at once by gSPVertex, or basically 16 characters
// handle loading groups of 16 chars at a time until there are no more left to load.
// By this point 4 vertices have already been loaded for the preceding icon.
if (i % 16 == 0) {
size_t numVtxToLoad = std::min<size_t>(numChar - i, 16) * 4;
mEntryDl->push_back(gsSPVertex(&vtx[4 + (vtxGroup * 16 * 4)], numVtxToLoad, 0));
vtxGroup++;
}
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
}
mEntryDl->push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
}
Kaleido::Kaleido() {
const auto ctx = Rando::Context::GetInstance();
int yOffset = 2;
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
gRupeeCounterIconTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, Color_RGBA8{ 0xC8, 0xFF, 0x64, 255 },
FlagType::FLAG_RANDOMIZER_INF, static_cast<int>(RAND_INF_GREG_FOUND), 0, yOffset, "Greg"));
yOffset += 18;
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
mEntries.push_back(std::make_shared<KaleidoEntryIconCountRequired>(
gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 }, 0, yOffset,
reinterpret_cast<int*>(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected),
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1,
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1));
yOffset += 18;
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
mEntries.push_back(
std::make_shared<KaleidoEntryIconCountRequired>(
gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255,255,255,255 }, 0,
yOffset, reinterpret_cast<int*>(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected),
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1,
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1));
yOffset += 18;
}
if (ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS)) {
mEntries.push_back(std::make_shared<KaleidoEntryOcarinaButtons>(0, yOffset));
yOffset += 18;
}
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).IsNot(RO_BOSS_SOULS_OFF)) {
static const char* bossSoulNames[] = {
"Gohma's Soul",
"King Dodongo's Soul",
"Barinade's Soul",
"Phantom Ganon's Soul",
"Volvagia's Soul",
"Morpha's Soul",
"Bongo Bongo's Soul",
"Twinrova's Soul",
};
for (int i = RAND_INF_GOHMA_SOUL; i < RAND_INF_GANON_SOUL; i++) {
mEntries.push_back(
std::make_shared<KaleidoEntryIconFlag>(
gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
FlagType::FLAG_RANDOMIZER_INF, i, 0, yOffset, bossSoulNames[i - RAND_INF_GOHMA_SOUL]
)
);
yOffset += 18;
}
}
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON)) {
mEntries.push_back(
std::make_shared<KaleidoEntryIconFlag>(
gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
FlagType::FLAG_RANDOMIZER_INF, RAND_INF_GANON_SOUL, 0, yOffset, "Ganon's Soul"
)
);
}
if (ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS)) {
mEntries.push_back(std::make_shared<KaleidoEntryOcarinaButtons>(0, yOffset));
yOffset += 18;
}
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).IsNot(RO_BOSS_SOULS_OFF)) {
static const char* bossSoulNames[] = {
"Gohma's Soul", "King Dodongo's Soul", "Barinade's Soul", "Phantom Ganon's Soul",
"Volvagia's Soul", "Morpha's Soul", "Bongo Bongo's Soul", "Twinrova's Soul",
};
for (int i = RAND_INF_GOHMA_SOUL; i < RAND_INF_GANON_SOUL; i++) {
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
FlagType::FLAG_RANDOMIZER_INF, i, 0, yOffset, bossSoulNames[i - RAND_INF_GOHMA_SOUL]));
yOffset += 18;
}
}
extern "C" {
void FrameInterpolation_RecordCloseChild(void);
void FrameInterpolation_RecordOpenChild(const void* a, int b);
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON)) {
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
FlagType::FLAG_RANDOMIZER_INF, RAND_INF_GANON_SOUL, 0, yOffset, "Ganon's Soul"));
yOffset += 18;
}
}
void Kaleido::Draw(PlayState* play) {
if (play == nullptr || mEntries.empty()) {
return;
}
PauseContext* pauseCtx = &play->pauseCtx;
Input* input = &play->state.input[0];
mEntryDl.clear();
OPEN_DISPS(play->state.gfxCtx);
mEntryDl.push_back(gsDPPipeSync());
Gfx_SetupDL_42Opa(play->state.gfxCtx);
mEntryDl.push_back(gsDPSetCombineMode(G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM));
extern "C" {
void FrameInterpolation_RecordCloseChild(void);
void FrameInterpolation_RecordOpenChild(const void* a, int b);
}
// Move the matrix origin to the top-left corner of the kaleido page
Matrix_Translate(-108.f, 58.f, 0.0f, MTXMODE_APPLY);
// Invert the matrix to render vertices with positive going down
Matrix_Scale(1.0f, -1.0f, 1.0f, MTXMODE_APPLY);
// The scrolling logic is in here because the built in kaleido input throttling happens
// in its Draw functions, which get called after their update functions. I hate it but fixing
// it would be a much larger Kaleido change.
bool shouldScroll = false;
bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0);
if (((pauseCtx->unk_1E4 == 0) || (pauseCtx->unk_1E4 == 5) || (pauseCtx->unk_1E4 == 8)) &&
(pauseCtx->pageIndex == PAUSE_QUEST)) {
if (!((pauseCtx->state != 6) || ((pauseCtx->stickRelX == 0) && (pauseCtx->stickRelY == 0)))) {
if (pauseCtx->cursorSpecialPos == 0) {
if ((pauseCtx->stickRelY > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) {
if (mTopIndex > 0) {
mTopIndex--;
shouldScroll = true;
}
} else if ((pauseCtx->stickRelY < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) {
if (mTopIndex + mNumVisible < mEntries.size()) {
mTopIndex++;
shouldScroll = true;
}
void Kaleido::Draw(PlayState* play) {
if (play == nullptr || mEntries.empty()) {
return;
}
PauseContext* pauseCtx = &play->pauseCtx;
Input* input = &play->state.input[0];
mEntryDl.clear();
OPEN_DISPS(play->state.gfxCtx);
mEntryDl.push_back(gsDPPipeSync());
Gfx_SetupDL_42Opa(play->state.gfxCtx);
mEntryDl.push_back(gsDPSetCombineMode(G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM));
// Move the matrix origin to the top-left corner of the kaleido page
Matrix_Translate(-108.f, 58.f, 0.0f, MTXMODE_APPLY);
// Invert the matrix to render vertices with positive going down
Matrix_Scale(1.0f, -1.0f, 1.0f, MTXMODE_APPLY);
// The scrolling logic is in here because the built in kaleido input throttling happens
// in its Draw functions, which get called after their update functions. I hate it but fixing
// it would be a much larger Kaleido change.
bool shouldScroll = false;
bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0);
if (((pauseCtx->unk_1E4 == 0) || (pauseCtx->unk_1E4 == 5) || (pauseCtx->unk_1E4 == 8)) &&
(pauseCtx->pageIndex == PAUSE_QUEST)) {
if (!((pauseCtx->state != 6) || ((pauseCtx->stickRelX == 0) && (pauseCtx->stickRelY == 0)))) {
if (pauseCtx->cursorSpecialPos == 0) {
if ((pauseCtx->stickRelY > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) {
if (mTopIndex > 0) {
mTopIndex--;
shouldScroll = true;
}
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_LEFT);
pauseCtx->unk_1E4 = 0;
} else if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_RIGHT);
pauseCtx->unk_1E4 = 0;
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) {
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else if ((pauseCtx->stickRelY < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) {
if (mTopIndex + mNumVisible < mEntries.size()) {
mTopIndex++;
shouldScroll = true;
}
}
} else if (pauseCtx->cursorSpecialPos != 0 && pauseCtx->state == 7) {
pauseCtx->cursorSpecialPos = 0;
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_LEFT);
pauseCtx->unk_1E4 = 0;
} else if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_RIGHT);
pauseCtx->unk_1E4 = 0;
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) {
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
}
int yOffset = 2;
for (int i = mTopIndex; i < (mTopIndex + mNumVisible) && i < mEntries.size(); i++) {
auto& entry = mEntries[i];
if (shouldScroll) {
entry->SetYOffset(yOffset);
yOffset += 18;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
Matrix_Push();
entry->Draw(play, &mEntryDl);
Matrix_Pop();
}
mEntryDl.push_back(gsSPEndDisplayList());
gSPDisplayList(POLY_OPA_DISP++, mEntryDl.data());
CLOSE_DISPS(play->state.gfxCtx);
}
void Kaleido::Update(PlayState *play) {
for(int i = mTopIndex; i < (mTopIndex + mNumVisible) && i < mEntries.size(); i++) {
const auto& entry = mEntries[i];
entry->Update(play);
} else if (pauseCtx->cursorSpecialPos != 0 && pauseCtx->state == 7) {
pauseCtx->cursorSpecialPos = 0;
}
}
extern "C" void RandoKaleido_DrawMiscCollectibles(PlayState* play) {
OTRGlobals::Instance->gRandoContext->GetKaleido()->Draw(play);
}
extern "C" void RandoKaleido_UpdateMiscCollectibles(int16_t inDungeonScene) {
PauseContext* pauseCtx = &gPlayState->pauseCtx;
if (pauseCtx->randoQuestMode && pauseCtx->pageIndex == PAUSE_QUEST) {
OTRGlobals::Instance->gRandoContext->GetKaleido()->Update(gPlayState);
int yOffset = 2;
for (int i = mTopIndex; i < (mTopIndex + mNumVisible) && i < mEntries.size(); i++) {
auto& entry = mEntries[i];
if (shouldScroll) {
entry->SetYOffset(yOffset);
yOffset += 18;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
Matrix_Push();
entry->Draw(play, &mEntryDl);
Matrix_Pop();
}
KaleidoEntryIconFlag::KaleidoEntryIconFlag(const char *iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, FlagType flagType, int flag,
int16_t x, int16_t y, std::string name) :
mFlagType(flagType), mFlag(flag),
KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y, std::move(name)) {
BuildVertices();
}
mEntryDl.push_back(gsSPEndDisplayList());
gSPDisplayList(POLY_OPA_DISP++, mEntryDl.data());
CLOSE_DISPS(play->state.gfxCtx);
}
void KaleidoEntryIconFlag::Update(PlayState* play) {
mAchieved = GameInteractor::RawAction::CheckFlag(mFlagType, static_cast<int16_t>(mFlag));
void Kaleido::Update(PlayState* play) {
for (int i = mTopIndex; i < (mTopIndex + mNumVisible) && i < mEntries.size(); i++) {
const auto& entry = mEntries[i];
entry->Update(play);
}
}
KaleidoEntryIconCountRequired::KaleidoEntryIconCountRequired(const char *iconResourceName, int iconFormat,
int iconSize, int iconWidth, int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch,
int required, int total) : mWatch(watch), mRequired(required), mTotal(total),
KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y) {
extern "C" void RandoKaleido_DrawMiscCollectibles(PlayState* play) {
OTRGlobals::Instance->gRandoContext->GetKaleido()->Draw(play);
}
extern "C" void RandoKaleido_UpdateMiscCollectibles(int16_t inDungeonScene) {
PauseContext* pauseCtx = &gPlayState->pauseCtx;
if (pauseCtx->randoQuestMode && pauseCtx->pageIndex == PAUSE_QUEST) {
OTRGlobals::Instance->gRandoContext->GetKaleido()->Update(gPlayState);
}
}
KaleidoEntryIconFlag::KaleidoEntryIconFlag(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, FlagType flagType, int flag,
int16_t x, int16_t y, std::string name)
: mFlagType(flagType), mFlag(flag), KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight,
iconColor, x, y, std::move(name)) {
BuildVertices();
}
void KaleidoEntryIconFlag::Update(PlayState* play) {
mAchieved = GameInteractor::RawAction::CheckFlag(mFlagType, static_cast<int16_t>(mFlag));
}
KaleidoEntryIconCountRequired::KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize,
int iconWidth, int iconHeight, Color_RGBA8 iconColor,
int16_t x, int16_t y, int* watch, int required, int total)
: mWatch(watch), mRequired(required), mTotal(total),
KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y) {
mCount = *mWatch;
BuildText();
BuildVertices();
}
void KaleidoEntryIconCountRequired::BuildText() {
std::ostringstream totals;
totals << mCount;
if (mRequired != 0 && mCount < mRequired) {
totals << '/' << mRequired;
}
if (mTotal >= mRequired && mCount >= mRequired) {
totals << '/' << mTotal;
}
mText = totals.str();
}
void KaleidoEntryIcon::BuildVertices() {
int offsetY = 0;
int offsetX = 0;
// 4 vertices per character, plus one for the preceding icon.
Vtx* vertices = (Vtx*)calloc(sizeof(Vtx[4]), mText.length() + 1);
// Vertex for the preceding icon.
Ship_CreateQuadVertexGroup(vertices, offsetX, offsetY, mIconWidth, mIconHeight, 0);
offsetX += 18;
for (size_t i = 0; i < mText.length(); i++) {
int charWidth = static_cast<int>(Ship_GetCharFontWidth(mText[i]));
Ship_CreateQuadVertexGroup(&(vertices)[(i + 1) * 4], offsetX, offsetY, charWidth, 16, 0);
offsetX += charWidth;
}
offsetY += FONT_CHAR_TEX_HEIGHT;
mWidth = static_cast<int16_t>(offsetX);
mHeight = static_cast<int16_t>(offsetY);
vertices[1].v.ob[0] = 16;
vertices[2].v.ob[1] = 16;
vertices[3].v.ob[0] = 16;
vertices[3].v.ob[1] = 16;
vtx = vertices;
}
KaleidoEntryIcon::KaleidoEntryIcon(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text)
: mIconResourceName(iconResourceName), mIconFormat(iconFormat), mIconSize(iconSize), mIconWidth(iconWidth),
mIconHeight(iconHeight), mIconColor(iconColor), KaleidoEntry(x, y, std::move(text)) {
}
void KaleidoEntryIcon::RebuildVertices() {
free(vtx);
vtx = nullptr;
BuildVertices();
}
void KaleidoEntryIconCountRequired::Update(PlayState* play) {
if (mCount != *mWatch) {
mCount = *mWatch;
BuildText();
BuildVertices();
RebuildVertices();
mAchieved = mCount >= mRequired;
}
}
void KaleidoEntryIconCountRequired::BuildText() {
std::ostringstream totals;
totals << mCount;
if (mRequired != 0 && mCount < mRequired) {
totals << '/' << mRequired;
}
if (mTotal >= mRequired && mCount >= mRequired) {
totals << '/' << mTotal;
}
mText = totals.str();
KaleidoEntryOcarinaButtons::KaleidoEntryOcarinaButtons(int16_t x, int16_t y)
: KaleidoEntryIcon(gItemIconOcarinaOfTimeTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32,
Color_RGBA8{ 255, 255, 255, 255 }, x, y, "\x9F\xA5\xA6\xA7\xA8") {
CalculateColors();
BuildVertices();
}
void KaleidoEntryOcarinaButtons::CalculateColors() {
Color_RGB8 aButtonColor = { 80, 150, 255 };
if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) {
aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor);
} else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) {
aButtonColor = { 80, 255, 150 };
}
void KaleidoEntryIcon::BuildVertices() {
int offsetY = 0;
int offsetX = 0;
// 4 vertices per character, plus one for the preceding icon.
Vtx* vertices = (Vtx*)calloc(sizeof(Vtx[4]), mText.length() + 1);
// Vertex for the preceding icon.
Ship_CreateQuadVertexGroup(vertices, offsetX, offsetY, mIconWidth, mIconHeight, 0);
offsetX += 18;
for (size_t i = 0; i < mText.length(); i++) {
int charWidth = static_cast<int>(Ship_GetCharFontWidth(mText[i]));
Ship_CreateQuadVertexGroup(&(vertices)[(i + 1) * 4], offsetX, offsetY, charWidth, 16, 0);
offsetX += charWidth;
}
offsetY += FONT_CHAR_TEX_HEIGHT;
mWidth = static_cast<int16_t>(offsetX);
mHeight = static_cast<int16_t>(offsetY);
vertices[1].v.ob[0] = 16;
vertices[2].v.ob[1] = 16;
vertices[3].v.ob[0] = 16;
vertices[3].v.ob[1] = 16;
vtx = vertices;
mButtonColors[0] = { aButtonColor.r, aButtonColor.g, aButtonColor.b, 255 };
Color_RGB8 cButtonsColor = { 255, 255, 50 };
Color_RGB8 cUpButtonColor = cButtonsColor;
Color_RGB8 cDownButtonColor = cButtonsColor;
Color_RGB8 cLeftButtonColor = cButtonsColor;
Color_RGB8 cRightButtonColor = cButtonsColor;
if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) {
cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
}
KaleidoEntryIcon::KaleidoEntryIcon(const char *iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text)
: mIconResourceName(iconResourceName), mIconFormat(iconFormat), mIconSize(iconSize),
mIconWidth(iconWidth), mIconHeight(iconHeight), mIconColor(iconColor),
KaleidoEntry(x, y, std::move(text)) {}
void KaleidoEntryIcon::RebuildVertices() {
free(vtx);
vtx = nullptr;
BuildVertices();
if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) {
cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), cUpButtonColor);
}
void KaleidoEntryIconCountRequired::Update(PlayState *play) {
if (mCount != *mWatch) {
mCount = *mWatch;
BuildText();
RebuildVertices();
mAchieved = mCount >= mRequired;
}
if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) {
cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), cDownButtonColor);
}
KaleidoEntryOcarinaButtons::KaleidoEntryOcarinaButtons(int16_t x, int16_t y) :
KaleidoEntryIcon(gItemIconOcarinaOfTimeTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32,
Color_RGBA8{ 255, 255, 255, 255 }, x, y, "\x9F\xA5\xA6\xA7\xA8") {
CalculateColors();
BuildVertices();
if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) {
cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), cLeftButtonColor);
}
void KaleidoEntryOcarinaButtons::CalculateColors() {
Color_RGB8 aButtonColor = { 80, 150, 255 };
if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) {
aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor);
} else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) {
aButtonColor = { 80, 255, 150};
}
mButtonColors[0] = { aButtonColor.r, aButtonColor.g, aButtonColor.b, 255 };
Color_RGB8 cButtonsColor = { 255, 255, 50 };
Color_RGB8 cUpButtonColor = cButtonsColor;
Color_RGB8 cDownButtonColor = cButtonsColor;
Color_RGB8 cLeftButtonColor = cButtonsColor;
Color_RGB8 cRightButtonColor = cButtonsColor;
if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) {
cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor);
}
if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) {
cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), cUpButtonColor);
}
if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) {
cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), cDownButtonColor);
}
if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) {
cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), cLeftButtonColor);
}
if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) {
cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), cRightButtonColor);
}
mButtonColors[1] = { cUpButtonColor.r, cUpButtonColor.g, cUpButtonColor.b, 255 };
mButtonColors[2] = { cDownButtonColor.r, cDownButtonColor.g, cDownButtonColor.b, 255 };
mButtonColors[3] = { cLeftButtonColor.r, cLeftButtonColor.g, cLeftButtonColor.b, 255 };
mButtonColors[4] = { cRightButtonColor.r, cRightButtonColor.g, cRightButtonColor.b, 255 };
if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) {
cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), cRightButtonColor);
}
mButtonColors[1] = { cUpButtonColor.r, cUpButtonColor.g, cUpButtonColor.b, 255 };
mButtonColors[2] = { cDownButtonColor.r, cDownButtonColor.g, cDownButtonColor.b, 255 };
mButtonColors[3] = { cLeftButtonColor.r, cLeftButtonColor.g, cLeftButtonColor.b, 255 };
mButtonColors[4] = { cRightButtonColor.r, cRightButtonColor.g, cRightButtonColor.b, 255 };
}
void KaleidoEntryOcarinaButtons::Update(PlayState *play) {
mButtonCollected[0] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_A) > 0;
mButtonCollected[1] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_UP) > 0;
mButtonCollected[2] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_DOWN) > 0;
mButtonCollected[3] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_LEFT) > 0;
mButtonCollected[4] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_RIGHT) > 0;
CalculateColors();
mAchieved = false;
for (int i = 0; i < mButtonCollected.size(); i++) {
if (!mButtonCollected[i]) {
mButtonColors[i] = Color_RGBA8{ 109, 109, 109, 255 };
} else {
mAchieved = true;
}
void KaleidoEntryOcarinaButtons::Update(PlayState* play) {
mButtonCollected[0] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_A) > 0;
mButtonCollected[1] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_UP) > 0;
mButtonCollected[2] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_DOWN) > 0;
mButtonCollected[3] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_LEFT) > 0;
mButtonCollected[4] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_RIGHT) > 0;
CalculateColors();
mAchieved = false;
for (int i = 0; i < mButtonCollected.size(); i++) {
if (!mButtonCollected[i]) {
mButtonColors[i] = Color_RGBA8{ 109, 109, 109, 255 };
} else {
mAchieved = true;
}
}
}
void KaleidoEntryOcarinaButtons::Draw(PlayState *play, std::vector<Gfx>* mEntryDl) {
if (vtx == nullptr) {
return;
}
size_t numChar = mText.length();
if (numChar == 0) {
return;
}
Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY);
// Matrix_Scale(0.75f, 0.75f, 0.75f, MTXMODE_APPLY);
mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW));
// icon
if (!mAchieved) {
mEntryDl->push_back(gsDPSetGrayscaleColor(109, 109, 109, 255));
mEntryDl->push_back(gsSPGrayscale(true));
}
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mIconColor.r, mIconColor.g, mIconColor.b, mIconColor.a));
mEntryDl->push_back(gsSPVertex(vtx, 4, 0));
LoadIconTex(mEntryDl);
mEntryDl->push_back(gsSP1Quadrangle(0, 2, 3, 1, 0));
mEntryDl->push_back(gsSPGrayscale(false));
// text
for (size_t i = 0, vtxGroup = 0; i < numChar; i++) {
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mButtonColors[i].r, mButtonColors[i].g, mButtonColors[i].b, mButtonColors[i].a));
// A maximum of 64 Vtx can be loaded at once by gSPVertex, or basically 16 characters
// handle loading groups of 16 chars at a time until there are no more left to load.
// By this point 4 vertices have already been loaded for the preceding icon.
if (i % 16 == 0) {
size_t numVtxToLoad = std::min<size_t>(numChar - i, 16) * 4;
mEntryDl->push_back(gsSPVertex(&vtx[4 + (vtxGroup * 16 * 4)], numVtxToLoad, 0));
vtxGroup++;
}
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(
texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
}
mEntryDl->push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
void KaleidoEntryOcarinaButtons::Draw(PlayState* play, std::vector<Gfx>* mEntryDl) {
if (vtx == nullptr) {
return;
}
} // Rando
size_t numChar = mText.length();
if (numChar == 0) {
return;
}
Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY);
// Matrix_Scale(0.75f, 0.75f, 0.75f, MTXMODE_APPLY);
mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW));
// icon
if (!mAchieved) {
mEntryDl->push_back(gsDPSetGrayscaleColor(109, 109, 109, 255));
mEntryDl->push_back(gsSPGrayscale(true));
}
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mIconColor.r, mIconColor.g, mIconColor.b, mIconColor.a));
mEntryDl->push_back(gsSPVertex(vtx, 4, 0));
LoadIconTex(mEntryDl);
mEntryDl->push_back(gsSP1Quadrangle(0, 2, 3, 1, 0));
mEntryDl->push_back(gsSPGrayscale(false));
// text
for (size_t i = 0, vtxGroup = 0; i < numChar; i++) {
mEntryDl->push_back(
gsDPSetPrimColor(0, 0, mButtonColors[i].r, mButtonColors[i].g, mButtonColors[i].b, mButtonColors[i].a));
// A maximum of 64 Vtx can be loaded at once by gSPVertex, or basically 16 characters
// handle loading groups of 16 chars at a time until there are no more left to load.
// By this point 4 vertices have already been loaded for the preceding icon.
if (i % 16 == 0) {
size_t numVtxToLoad = std::min<size_t>(numChar - i, 16) * 4;
mEntryDl->push_back(gsSPVertex(&vtx[4 + (vtxGroup * 16 * 4)], numVtxToLoad, 0));
vtxGroup++;
}
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
}
mEntryDl->push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
}
} // namespace Rando
void RandoKaleido_RegisterHooks() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoscopeUpdate>(RandoKaleido_UpdateMiscCollectibles);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoscopeUpdate>(
RandoKaleido_UpdateMiscCollectibles);
}

View file

@ -2,7 +2,6 @@
#define KALEIDO_H
#include <z64.h>
#ifdef __cplusplus
#include <vector>
#include <string>
@ -18,7 +17,7 @@ namespace Rando {
* subclasses to declare their Draw and Update functions.
*/
class KaleidoEntry {
public:
public:
/**
* @brief Constructor for Base KaleidoEntry class. Sets the position and
* initial value of the line of text.
@ -31,7 +30,8 @@ public:
virtual void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) = 0;
virtual void Update(PlayState* play) = 0;
void SetYOffset(int yOffset);
protected:
protected:
int16_t mX;
int16_t mY;
int16_t mHeight;
@ -39,7 +39,6 @@ protected:
Vtx* vtx;
std::string mText;
bool mAchieved = false;
};
/**
@ -47,7 +46,7 @@ protected:
* that wish to render an Icon at the start of their line.
*/
class KaleidoEntryIcon : public KaleidoEntry {
public:
public:
/**
* @param iconResourceName resource name of the icon to draw
* @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA)
@ -63,7 +62,8 @@ public:
Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text = "");
void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override;
void RebuildVertices();
protected:
protected:
const char* mIconResourceName;
int mIconFormat;
int mIconSize;
@ -80,7 +80,7 @@ protected:
* that is either colored in or Grayscale according to a flag
*/
class KaleidoEntryIconFlag : public KaleidoEntryIcon {
public :
public:
/**
* @param iconResourceName resource name of the icon to draw
* @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA)
@ -98,7 +98,8 @@ public :
Color_RGBA8 iconColor, FlagType flagType, int flag, int16_t x, int16_t y,
std::string name = "");
void Update(PlayState* play) override;
private:
private:
FlagType mFlagType;
int mFlag;
};
@ -109,7 +110,7 @@ private:
* render the count and not show progress towards a required amount or a total.
*/
class KaleidoEntryIconCountRequired : public KaleidoEntryIcon {
public:
public:
/**
* @param iconResourceName resource name of the icon to draw
* @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA)
@ -126,10 +127,12 @@ public:
* @param required The amount of this collectible required to beat the seed. Set to 0 to not render.
* @param total The amount of this collectible available in the seed. Set to 0 to not render.
*/
KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth, int iconHeight,
Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch, int required = 0, int total = 0);
KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch,
int required = 0, int total = 0);
void Update(PlayState* play) override;
private:
private:
int* mWatch;
int mRequired;
int mTotal;
@ -139,11 +142,12 @@ private:
};
class KaleidoEntryOcarinaButtons : public KaleidoEntryIcon {
public:
public:
KaleidoEntryOcarinaButtons(int16_t x, int16_t y);
void Update(PlayState* play) override;
void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override;
private:
private:
void CalculateColors();
std::array<Color_RGBA8, 5> mButtonColors = {};
@ -151,17 +155,18 @@ private:
};
class Kaleido {
public:
public:
Kaleido();
void Draw(PlayState* play);
void Update(PlayState* play);
private:
private:
std::vector<std::shared_ptr<KaleidoEntry>> mEntries;
std::vector<Gfx> mEntryDl;
int mTopIndex = 0;
int mNumVisible = 7;
};
} // Rando
} // namespace Rando
extern "C" {
#endif
@ -172,5 +177,4 @@ void RandoKaleido_UpdateMiscCollectibles(int16_t inDungeonScene);
#endif
void RandoKaleido_RegisterHooks();
#endif //KALEIDO_H
#endif // KALEIDO_H

View file

@ -66,7 +66,8 @@ static const ALIGN_ASSET(2) char tokinoma_room_0DL_007FD0[] = dtokinoma_room_0DL
/// Switches Link's age and respawns him at the last entrance he entered.
void SwitchAge() {
if (gPlayState == NULL) return;
if (gPlayState == NULL)
return;
Player* player = GET_PLAYER(gPlayState);
@ -114,14 +115,16 @@ void RegisterOcarinaTimeTravel() {
}
Actor* player = &GET_PLAYER(gPlayState)->actor;
Actor* nearbyTimeBlockEmpty = Actor_FindNearby(gPlayState, player, ACTOR_OBJ_WARP2BLOCK, ACTORCAT_ITEMACTION, 300.0f);
Actor* nearbyTimeBlockEmpty =
Actor_FindNearby(gPlayState, player, ACTOR_OBJ_WARP2BLOCK, ACTORCAT_ITEMACTION, 300.0f);
Actor* nearbyTimeBlock = Actor_FindNearby(gPlayState, player, ACTOR_OBJ_TIMEBLOCK, ACTORCAT_ITEMACTION, 300.0f);
Actor* nearbyOcarinaSpot = Actor_FindNearby(gPlayState, player, ACTOR_EN_OKARINA_TAG, ACTORCAT_PROP, 120.0f);
Actor* nearbyDoorOfTime = Actor_FindNearby(gPlayState, player, ACTOR_DOOR_TOKI, ACTORCAT_BG, 500.0f);
Actor* nearbyFrogs = Actor_FindNearby(gPlayState, player, ACTOR_EN_FR, ACTORCAT_NPC, 300.0f);
Actor* nearbyGossipStone = Actor_FindNearby(gPlayState, player, ACTOR_EN_GS, ACTORCAT_NPC, 300.0f);
bool justPlayedSoT = gPlayState->msgCtx.lastPlayedSong == OCARINA_SONG_TIME;
bool notNearAnySource = !nearbyTimeBlockEmpty && !nearbyTimeBlock && !nearbyOcarinaSpot && !nearbyDoorOfTime && !nearbyFrogs && !nearbyGossipStone;
bool notNearAnySource = !nearbyTimeBlockEmpty && !nearbyTimeBlock && !nearbyOcarinaSpot && !nearbyDoorOfTime &&
!nearbyFrogs && !nearbyGossipStone;
bool hasOcarinaOfTime = (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME);
bool doesntNeedOcarinaOfTime = CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2;
bool hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER);
@ -137,11 +140,11 @@ void RegisterRupeeDash() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("RupeeDash"), 0)) {
return;
}
// Initialize Timer
static uint16_t rupeeDashTimer = 0;
uint16_t rdmTime = CVarGetInteger(CVAR_ENHANCEMENT("RupeeDashInterval"), 5) * 20;
// Did time change by DashInterval?
if (rupeeDashTimer >= rdmTime) {
rupeeDashTimer = 0;
@ -165,10 +168,10 @@ void RegisterShadowTag() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("ShadowTag"), 0)) {
return;
}
if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && // Forest Temple Scene
gPlayState->roomCtx.curRoom.num == 16 || // Green Poe Room
gPlayState->roomCtx.curRoom.num == 13 || // Blue Poe Room
gPlayState->roomCtx.curRoom.num == 12) { // Red Poe Room
if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && // Forest Temple Scene
gPlayState->roomCtx.curRoom.num == 16 || // Green Poe Room
gPlayState->roomCtx.curRoom.num == 13 || // Blue Poe Room
gPlayState->roomCtx.curRoom.num == 12) { // Red Poe Room
return;
} else {
if (shouldSpawn && (delayTimer <= 0)) {
@ -191,13 +194,14 @@ void RegisterShadowTag() {
static bool hasAffectedHealth = false;
void UpdatePermanentHeartLossState() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded())
return;
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) {
uint8_t heartContainers = gSaveContext.ship.stats.heartContainers; // each worth 16 health
uint8_t heartPieces = gSaveContext.ship.stats.heartPieces; // each worth 4 health, but only in groups of 4
uint8_t startingHealth = 16 * (IS_RANDO ? (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_HEARTS) + 1) : 3);
uint8_t startingHealth =
16 * (IS_RANDO ? (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_HEARTS) + 1) : 3);
uint8_t newCapacity = startingHealth + (heartContainers * 16) + ((heartPieces - (heartPieces % 4)) * 4);
gSaveContext.healthCapacity = MAX(newCapacity, gSaveContext.healthCapacity);
@ -213,7 +217,8 @@ void RegisterPermanentHeartLoss() {
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) || !GameInteractor::IsSaveLoaded()) return;
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) || !GameInteractor::IsSaveLoaded())
return;
if (gSaveContext.healthCapacity > 16 && gSaveContext.healthCapacity - gSaveContext.health >= 16) {
gSaveContext.healthCapacity -= 16;
@ -225,12 +230,16 @@ void RegisterPermanentHeartLoss() {
void RegisterDeleteFileOnDeath() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("DeleteFileOnDeath"), 0) || !GameInteractor::IsSaveLoaded() || gPlayState == NULL) return;
if (!CVarGetInteger(CVAR_ENHANCEMENT("DeleteFileOnDeath"), 0) || !GameInteractor::IsSaveLoaded() ||
gPlayState == NULL)
return;
if (gPlayState->gameOverCtx.state == GAMEOVER_DEATH_MENU && gPlayState->pauseCtx.state == 9) {
SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum);
hasAffectedHealth = false;
std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset");
std::reinterpret_pointer_cast<Ship::ConsoleWindow>(
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))
->Dispatch("reset");
}
});
}
@ -258,7 +267,10 @@ void RegisterDaytimeGoldSkultullas() {
// ZF
{ SCENE_ZORAS_FOUNTAIN, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } },
// GF
{ SCENE_GERUDOS_FORTRESS, 0, false, { { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } },
{ SCENE_GERUDOS_FORTRESS,
0,
false,
{ { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } },
{ SCENE_GERUDOS_FORTRESS, 1, false, { { ACTOR_EN_SW, { 3377, 1734, -4935 }, { 16384, 0, 0 }, -19199 } } },
// Kak
{ SCENE_KAKARIKO_VILLAGE, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } },
@ -293,7 +305,8 @@ void RegisterDaytimeGoldSkultullas() {
bool IsHyperBossesActive() {
return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) ||
(IS_BOSS_RUSH && gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
(IS_BOSS_RUSH &&
gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
}
void UpdateHyperBossesState() {
@ -304,53 +317,53 @@ void UpdateHyperBossesState() {
}
if (IsHyperBossesActive()) {
actorUpdateHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make bosses move and act twice as fast.
actorUpdateHookId =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make bosses move and act twice as fast.
Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor);
Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor);
uint8_t isBossActor =
actor->id == ACTOR_BOSS_GOMA || // Gohma
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath
actor->id == ACTOR_BOSS_VA || // Barinade
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder
actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse
actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying)
actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks
actor->id == ACTOR_BOSS_MO || // Morpha
actor->id == ACTOR_BOSS_SST || // Bongo Bongo
actor->id == ACTOR_BOSS_TW || // Twinrova
actor->id == ACTOR_BOSS_GANON || // Ganondorf
actor->id == ACTOR_BOSS_GANON2; // Ganon
uint8_t isBossActor = actor->id == ACTOR_BOSS_GOMA || // Gohma
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath
actor->id == ACTOR_BOSS_VA || // Barinade
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder
actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse
actor->id == ACTOR_BOSS_FD ||
actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying)
actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks
actor->id == ACTOR_BOSS_MO || // Morpha
actor->id == ACTOR_BOSS_SST || // Bongo Bongo
actor->id == ACTOR_BOSS_TW || // Twinrova
actor->id == ACTOR_BOSS_GANON || // Ganondorf
actor->id == ACTOR_BOSS_GANON2; // Ganon
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses.
if (IsHyperBossesActive() && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) {
// Barinade needs to be updated in sequence to avoid unintended behaviour.
if (actor->id == ACTOR_BOSS_VA) {
// params -1 is BOSSVA_BODY
if (actor->params == -1) {
Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head;
while (actorList != NULL) {
GameInteractor::RawAction::UpdateActor(actorList);
actorList = actorList->next;
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses.
if (IsHyperBossesActive() && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) {
// Barinade needs to be updated in sequence to avoid unintended behaviour.
if (actor->id == ACTOR_BOSS_VA) {
// params -1 is BOSSVA_BODY
if (actor->params == -1) {
Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head;
while (actorList != NULL) {
GameInteractor::RawAction::UpdateActor(actorList);
actorList = actorList->next;
}
}
} else {
GameInteractor::RawAction::UpdateActor(actor);
}
} else {
GameInteractor::RawAction::UpdateActor(actor);
}
}
});
});
}
}
void RegisterHyperBosses() {
UpdateHyperBossesState();
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int16_t fileNum) {
UpdateHyperBossesState();
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>(
[](int16_t fileNum) { UpdateHyperBossesState(); });
}
void UpdateHyperEnemiesState() {
@ -361,22 +374,23 @@ void UpdateHyperEnemiesState() {
}
if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0)) {
actorUpdateHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make enemies and minibosses move and act twice as fast.
actorUpdateHookId =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make enemies and minibosses move and act twice as fast.
Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor);
Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor);
// Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies.
bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2;
bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2;
// Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies.
bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2;
bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2;
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes.
if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0) && isEnemy && !isExcludedEnemy &&
!Player_InBlockingCsMode(gPlayState, player)) {
GameInteractor::RawAction::UpdateActor(actor);
}
});
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes.
if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0) && isEnemy && !isExcludedEnemy &&
!Player_InBlockingCsMode(gPlayState, player)) {
GameInteractor::RawAction::UpdateActor(actor);
}
});
}
}
@ -415,7 +429,7 @@ void RegisterBonkDamage() {
default:
break;
}
Health_ChangeBy(gPlayState, -bonkDamage);
// Set invincibility to make Link flash red as a visual damage indicator.
Player* player = GET_PLAYER(gPlayState);
@ -428,7 +442,8 @@ void UpdateDirtPathFixState(int32_t sceneNum) {
case SCENE_HYRULE_FIELD:
case SCENE_KOKIRI_FOREST:
case SCENE_HYRULE_CASTLE:
CVarSetInteger(CVAR_Z_FIGHTING_MODE, CVarGetInteger(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_DISABLED));
CVarSetInteger(CVAR_Z_FIGHTING_MODE,
CVarGetInteger(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_DISABLED));
return;
default:
CVarClear(CVAR_Z_FIGHTING_MODE);
@ -436,9 +451,8 @@ void UpdateDirtPathFixState(int32_t sceneNum) {
}
void RegisterMenuPathFix() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>([](int32_t sceneNum) {
UpdateDirtPathFixState(sceneNum);
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(
[](int32_t sceneNum) { UpdateDirtPathFixState(sceneNum); });
}
void UpdateMirrorModeState(int32_t sceneNum) {
@ -446,27 +460,28 @@ void UpdateMirrorModeState(int32_t sceneNum) {
bool nextMirroredWorld = false;
int16_t mirroredMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorldMode"), MIRRORED_WORLD_OFF);
int16_t inDungeon = (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_INSIDE_GANONS_CASTLE_COLLAPSE && sceneNum != SCENE_THIEVES_HIDEOUT) ||
int16_t inDungeon = (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_INSIDE_GANONS_CASTLE_COLLAPSE &&
sceneNum != SCENE_THIEVES_HIDEOUT) ||
(sceneNum >= SCENE_DEKU_TREE_BOSS && sceneNum <= SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) ||
(sceneNum == SCENE_GANON_BOSS);
if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) {
uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
: gSaveContext.ship.stats.fileCreatedAt);
uint32_t seed =
sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(seed);
}
bool randomMirror = Random(0, 2) == 1;
if (
mirroredMode == MIRRORED_WORLD_ALWAYS ||
if (mirroredMode == MIRRORED_WORLD_ALWAYS ||
((mirroredMode == MIRRORED_WORLD_RANDOM || mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED) && randomMirror) ||
// Dungeon modes
(inDungeon && (mirroredMode == MIRRORED_WORLD_DUNGEONS_ALL ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_VANILLA && !ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_MQ && ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
((mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) && randomMirror)))
) {
(inDungeon &&
(mirroredMode == MIRRORED_WORLD_DUNGEONS_ALL ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_VANILLA && !ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_MQ && ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
((mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) &&
randomMirror)))) {
nextMirroredWorld = true;
CVarSetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 1);
} else {
@ -481,25 +496,33 @@ void UpdateMirrorModeState(int32_t sceneNum) {
}
void RegisterMirrorModeHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) {
UpdateMirrorModeState(sceneNum);
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(
[](int32_t sceneNum) { UpdateMirrorModeState(sceneNum); });
}
void UpdatePatchHand() {
if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_CHILD) {
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1", 92, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1", 92,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer2", 93, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2", 85, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1", 51, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84,
gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2", 85,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1", 51,
gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow2", 52, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1", 104, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2", 105, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1", 79, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1", 104,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2", 105,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1", 79,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2", 80, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1", 76, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2", 77, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1", 76,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2", 77,
gsSPEndDisplayList());
} else {
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1");
@ -514,12 +537,16 @@ void UpdatePatchHand() {
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2");
ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1");
ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2");
}
}
if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_ADULT) {
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield", 49, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13,
gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13,
gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50,
gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield", 49,
gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
} else {
ResourceMgr_UnpatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword");
ResourceMgr_UnpatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot");
@ -527,7 +554,8 @@ void UpdatePatchHand() {
ResourceMgr_UnpatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield");
}
if (CVarGetInteger("gEnhancements.FixHammerHand", 0) && LINK_IS_ADULT) {
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1", 92, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1", 92,
gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand2", 93, gsSPEndDisplayList());
} else {
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1");
@ -536,62 +564,61 @@ void UpdatePatchHand() {
}
void RegisterPatchHandHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) {
UpdatePatchHand();
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(
[](int32_t sceneNum) { UpdatePatchHand(); });
}
void RegisterResetNaviTimer() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) {
if (CVarGetInteger(CVAR_ENHANCEMENT("ResetNaviTimer"), 0)) {
gSaveContext.naviTimer = 0;
}
});
if (CVarGetInteger(CVAR_ENHANCEMENT("ResetNaviTimer"), 0)) {
gSaveContext.naviTimer = 0;
}
});
}
//this map is used for enemies that can be uniquely identified by their id
//and that are always counted
//enemies that can't be uniquely identified by their id
//or only sometimes count (like ACTOR_EN_TP)
//have to be manually handled in RegisterEnemyDefeatCounts
// this map is used for enemies that can be uniquely identified by their id
// and that are always counted
// enemies that can't be uniquely identified by their id
// or only sometimes count (like ACTOR_EN_TP)
// have to be manually handled in RegisterEnemyDefeatCounts
static std::unordered_map<u16, u16> uniqueEnemyIdToStatCount = {
{ ACTOR_EN_ANUBICE, COUNT_ENEMIES_DEFEATED_ANUBIS },
{ ACTOR_EN_AM, COUNT_ENEMIES_DEFEATED_ARMOS },
{ ACTOR_EN_CLEAR_TAG, COUNT_ENEMIES_DEFEATED_ARWING },
{ ACTOR_EN_VALI, COUNT_ENEMIES_DEFEATED_BARI },
{ ACTOR_EN_VM, COUNT_ENEMIES_DEFEATED_BEAMOS },
{ ACTOR_EN_BIGOKUTA, COUNT_ENEMIES_DEFEATED_BIG_OCTO },
{ ACTOR_EN_BILI, COUNT_ENEMIES_DEFEATED_BIRI },
{ ACTOR_EN_DNS, COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB },
{ ACTOR_EN_TORCH, COUNT_ENEMIES_DEFEATED_DARK_LINK },
{ ACTOR_EN_DH, COUNT_ENEMIES_DEFEATED_DEAD_HAND },
{ ACTOR_EN_HINTNUTS, COUNT_ENEMIES_DEFEATED_DEKU_SCRUB },
{ ACTOR_EN_DODONGO, COUNT_ENEMIES_DEFEATED_DODONGO },
{ ACTOR_EN_DODOJR, COUNT_ENEMIES_DEFEATED_DODONGO_BABY },
{ ACTOR_DOOR_KILLER, COUNT_ENEMIES_DEFEATED_DOOR_TRAP },
{ ACTOR_EN_FD, COUNT_ENEMIES_DEFEATED_FLARE_DANCER },
{ ACTOR_EN_FLOORMAS, COUNT_ENEMIES_DEFEATED_FLOORMASTER },
{ ACTOR_EN_TUBO_TRAP, COUNT_ENEMIES_DEFEATED_FLYING_POT },
{ ACTOR_EN_YUKABYUN, COUNT_ENEMIES_DEFEATED_FLOOR_TILE },
{ ACTOR_EN_FZ, COUNT_ENEMIES_DEFEATED_FREEZARD },
{ ACTOR_EN_GELDB, COUNT_ENEMIES_DEFEATED_GERUDO_THIEF },
{ ACTOR_EN_GOMA, COUNT_ENEMIES_DEFEATED_GOHMA_LARVA },
{ ACTOR_EN_CROW, COUNT_ENEMIES_DEFEATED_GUAY },
{ ACTOR_EN_RR, COUNT_ENEMIES_DEFEATED_LIKE_LIKE },
{ ACTOR_EN_DEKUNUTS, COUNT_ENEMIES_DEFEATED_MAD_SCRUB },
{ ACTOR_EN_OKUTA, COUNT_ENEMIES_DEFEATED_OCTOROK },
{ ACTOR_EN_BA, COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE },
{ ACTOR_EN_ANUBICE, COUNT_ENEMIES_DEFEATED_ANUBIS },
{ ACTOR_EN_AM, COUNT_ENEMIES_DEFEATED_ARMOS },
{ ACTOR_EN_CLEAR_TAG, COUNT_ENEMIES_DEFEATED_ARWING },
{ ACTOR_EN_VALI, COUNT_ENEMIES_DEFEATED_BARI },
{ ACTOR_EN_VM, COUNT_ENEMIES_DEFEATED_BEAMOS },
{ ACTOR_EN_BIGOKUTA, COUNT_ENEMIES_DEFEATED_BIG_OCTO },
{ ACTOR_EN_BILI, COUNT_ENEMIES_DEFEATED_BIRI },
{ ACTOR_EN_DNS, COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB },
{ ACTOR_EN_TORCH, COUNT_ENEMIES_DEFEATED_DARK_LINK },
{ ACTOR_EN_DH, COUNT_ENEMIES_DEFEATED_DEAD_HAND },
{ ACTOR_EN_HINTNUTS, COUNT_ENEMIES_DEFEATED_DEKU_SCRUB },
{ ACTOR_EN_DODONGO, COUNT_ENEMIES_DEFEATED_DODONGO },
{ ACTOR_EN_DODOJR, COUNT_ENEMIES_DEFEATED_DODONGO_BABY },
{ ACTOR_DOOR_KILLER, COUNT_ENEMIES_DEFEATED_DOOR_TRAP },
{ ACTOR_EN_FD, COUNT_ENEMIES_DEFEATED_FLARE_DANCER },
{ ACTOR_EN_FLOORMAS, COUNT_ENEMIES_DEFEATED_FLOORMASTER },
{ ACTOR_EN_TUBO_TRAP, COUNT_ENEMIES_DEFEATED_FLYING_POT },
{ ACTOR_EN_YUKABYUN, COUNT_ENEMIES_DEFEATED_FLOOR_TILE },
{ ACTOR_EN_FZ, COUNT_ENEMIES_DEFEATED_FREEZARD },
{ ACTOR_EN_GELDB, COUNT_ENEMIES_DEFEATED_GERUDO_THIEF },
{ ACTOR_EN_GOMA, COUNT_ENEMIES_DEFEATED_GOHMA_LARVA },
{ ACTOR_EN_CROW, COUNT_ENEMIES_DEFEATED_GUAY },
{ ACTOR_EN_RR, COUNT_ENEMIES_DEFEATED_LIKE_LIKE },
{ ACTOR_EN_DEKUNUTS, COUNT_ENEMIES_DEFEATED_MAD_SCRUB },
{ ACTOR_EN_OKUTA, COUNT_ENEMIES_DEFEATED_OCTOROK },
{ ACTOR_EN_BA, COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE },
{ ACTOR_EN_PO_SISTERS, COUNT_ENEMIES_DEFEATED_POE_SISTERS },
{ ACTOR_EN_BUBBLE, COUNT_ENEMIES_DEFEATED_SHABOM },
{ ACTOR_EN_SB, COUNT_ENEMIES_DEFEATED_SHELLBLADE },
{ ACTOR_EN_SKJ, COUNT_ENEMIES_DEFEATED_SKULL_KID },
{ ACTOR_EN_NY, COUNT_ENEMIES_DEFEATED_SPIKE },
{ ACTOR_EN_SKB, COUNT_ENEMIES_DEFEATED_STALCHILD },
{ ACTOR_EN_TEST, COUNT_ENEMIES_DEFEATED_STALFOS },
{ ACTOR_EN_WEIYER, COUNT_ENEMIES_DEFEATED_STINGER },
{ ACTOR_EN_BW, COUNT_ENEMIES_DEFEATED_TORCH_SLUG },
{ ACTOR_EN_WALLMAS, COUNT_ENEMIES_DEFEATED_WALLMASTER },
{ ACTOR_EN_KAREBABA, COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA },
{ ACTOR_EN_BUBBLE, COUNT_ENEMIES_DEFEATED_SHABOM },
{ ACTOR_EN_SB, COUNT_ENEMIES_DEFEATED_SHELLBLADE },
{ ACTOR_EN_SKJ, COUNT_ENEMIES_DEFEATED_SKULL_KID },
{ ACTOR_EN_NY, COUNT_ENEMIES_DEFEATED_SPIKE },
{ ACTOR_EN_SKB, COUNT_ENEMIES_DEFEATED_STALCHILD },
{ ACTOR_EN_TEST, COUNT_ENEMIES_DEFEATED_STALFOS },
{ ACTOR_EN_WEIYER, COUNT_ENEMIES_DEFEATED_STINGER },
{ ACTOR_EN_BW, COUNT_ENEMIES_DEFEATED_TORCH_SLUG },
{ ACTOR_EN_WALLMAS, COUNT_ENEMIES_DEFEATED_WALLMASTER },
{ ACTOR_EN_KAREBABA, COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA },
};
void RegisterEnemyDefeatCounts() {
@ -655,16 +682,14 @@ void RegisterEnemyDefeatCounts() {
}
break;
case ACTOR_EN_REEBA:
{
EnReeba* reeba = (EnReeba*)actor;
if (reeba->isBig) {
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++;
} else {
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
}
case ACTOR_EN_REEBA: {
EnReeba* reeba = (EnReeba*)actor;
if (reeba->isBig) {
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++;
} else {
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
}
break;
} break;
case ACTOR_EN_MB:
if (actor->params == 0) {
@ -781,26 +806,25 @@ void RegisterBossDefeatTimestamps() {
}
void UpdateHurtContainerModeState(bool newState) {
static bool hurtEnabled = false;
if (hurtEnabled == newState) {
return;
}
static bool hurtEnabled = false;
if (hurtEnabled == newState) {
return;
}
hurtEnabled = newState;
uint16_t getHeartPieces = gSaveContext.ship.stats.heartPieces / 4;
uint16_t getHeartContainers = gSaveContext.ship.stats.heartContainers;
hurtEnabled = newState;
uint16_t getHeartPieces = gSaveContext.ship.stats.heartPieces / 4;
uint16_t getHeartContainers = gSaveContext.ship.stats.heartContainers;
if (hurtEnabled) {
gSaveContext.healthCapacity = 320 - ((getHeartPieces + getHeartContainers) * 16);
} else {
gSaveContext.healthCapacity = 48 + ((getHeartPieces + getHeartContainers) * 16);
}
if (hurtEnabled) {
gSaveContext.healthCapacity = 320 - ((getHeartPieces + getHeartContainers) * 16);
} else {
gSaveContext.healthCapacity = 48 + ((getHeartPieces + getHeartContainers) * 16);
}
}
void RegisterHurtContainerModeHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) {
UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0));
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>(
[](int32_t fileNum) { UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0)); });
}
void RegisterRandomizedEnemySizes() {
@ -820,7 +844,8 @@ void RegisterRandomizedEnemySizes() {
actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH;
// Only apply to enemies and bosses.
if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemySizes"), 0) || (actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) {
if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemySizes"), 0) ||
(actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) {
return;
}
@ -860,7 +885,8 @@ void RegisterOpenAllHours() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
Actor* actor = static_cast<Actor*>(refActor);
if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR) && (!IS_RANDO || !OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOCK_OVERWORLD_DOORS))) {
if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR) &&
(!IS_RANDO || !OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOCK_OVERWORLD_DOORS))) {
switch (actor->params) {
case 4753: // Night Market Bazaar
case 1678: // Night Potion Shop
@ -892,47 +918,65 @@ void PatchToTMedallions() {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_StartGrayscale", 7, gsSPGrayscale(true));
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16, gsDPSetGrayscaleColor(0, 161, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16,
gsDPSetGrayscaleColor(0, 161, 255, 255));
} else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16, gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16,
gsDPSetGrayscaleColor(255, 255, 255, 255));
}
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45, gsDPSetGrayscaleColor(255, 135, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45,
gsDPSetGrayscaleColor(255, 135, 0, 255));
} else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45, gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45,
gsDPSetGrayscaleColor(255, 255, 255, 255));
}
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69, gsDPSetGrayscaleColor(255, 255, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16, gsDPSetGrayscaleColor(255, 255, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69,
gsDPSetGrayscaleColor(255, 255, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16,
gsDPSetGrayscaleColor(255, 255, 0, 255));
} else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69, gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16, gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69,
gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16,
gsDPSetGrayscaleColor(255, 255, 255, 255));
}
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94, gsDPSetGrayscaleColor(0, 255, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94,
gsDPSetGrayscaleColor(0, 255, 0, 255));
} else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94, gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94,
gsDPSetGrayscaleColor(255, 255, 255, 255));
}
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118, gsDPSetGrayscaleColor(255, 0, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118,
gsDPSetGrayscaleColor(255, 0, 0, 255));
} else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118, gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118,
gsDPSetGrayscaleColor(255, 255, 255, 255));
}
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142, gsDPSetGrayscaleColor(212, 0, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27, gsDPSetGrayscaleColor(212, 0, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142,
gsDPSetGrayscaleColor(212, 0, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27,
gsDPSetGrayscaleColor(212, 0, 255, 255));
} else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142, gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27, gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142,
gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27,
gsDPSetGrayscaleColor(255, 255, 255, 255));
}
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_EndGrayscaleAndEndDlist", 160, gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_EndGrayscaleAndEndDlist", 51, gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_EndGrayscaleAndEndDlist", 160,
gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_EndGrayscaleAndEndDlist", 51,
gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
} else {
// Unpatch everything
ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_StartGrayscale");
@ -953,7 +997,8 @@ void PatchToTMedallions() {
void RegisterToTMedallions() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry _unused) {
if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || !gPlayState || gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) {
if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || !gPlayState ||
gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) {
return;
}
PatchToTMedallions();
@ -966,7 +1011,6 @@ void RegisterToTMedallions() {
});
}
void RegisterFloorSwitchesHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
Actor* actor = static_cast<Actor*>(refActor);
@ -991,10 +1035,10 @@ void RegisterPauseMenuHooks() {
return;
}
if (!pauseWarpHooksRegistered) {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoUpdate>([]() {PauseWarp_HandleSelection();});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
PauseWarp_Execute();
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoUpdate>(
[]() { PauseWarp_HandleSelection(); });
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(
[]() { PauseWarp_Execute(); });
pauseWarpHooksRegistered = true;
}
});
@ -1004,7 +1048,6 @@ void RegisterCustomSkeletons() {
static int8_t previousTunic = -1;
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded() || gPlayState == NULL) {
return;
}

View file

@ -19,15 +19,15 @@ extern PlayState* gPlayState;
typedef struct {
Actor* actor;
std::string text; // Original text
std::string text; // Original text
std::string processedText; // Text filtered for supported font textures
const char* tag; // Tag identifier
Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0
int16_t height; // Textbox height
int16_t width; // Textbox width
int16_t yOffset; // Addition Y offset
Mtx* mtx; // Allocated Mtx for rendering
Vtx* vtx; // Allocated Vtx for rendering
const char* tag; // Tag identifier
Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0
int16_t height; // Textbox height
int16_t width; // Textbox width
int16_t yOffset; // Addition Y offset
Mtx* mtx; // Allocated Mtx for rendering
Vtx* vtx; // Allocated Vtx for rendering
} NameTag;
static std::vector<NameTag> nameTags;
@ -69,7 +69,7 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
return;
}
Color_RGBA8 textboxColor = { 0, 0, 0, 80};
Color_RGBA8 textboxColor = { 0, 0, 0, 80 };
Color_RGBA8 textColor = { 255, 255, 255, 255 };
if (CVarGetInteger(CVAR_COSMETIC("HUD.NameTagActorBackground.Changed"), 0)) {
@ -130,9 +130,9 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
int16_t vertexStart = 4 * (i % 16);
// Multi-instruction macro, need to insert all to the dl buffer
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(
texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
nameTagDl.insert(nameTagDl.end(), std::begin(charTexture), std::end(charTexture));
nameTagDl.push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
@ -195,11 +195,14 @@ extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* te
std::string processedText = std::string(Interface_ReplaceSpecialCharacters((char*)text));
// Strip out unsupported characters
processedText.erase(std::remove_if(processedText.begin(), processedText.end(), [](const char& c) {
// 172 is max supported texture for the in-game font system,
// and filter anything less than a space but not the newline or nul characters
return (unsigned char)c > 172 || (c < ' ' && c != '\n' && c != '\0');
}), processedText.end());
processedText.erase(std::remove_if(processedText.begin(), processedText.end(),
[](const char& c) {
// 172 is max supported texture for the in-game font system,
// and filter anything less than a space but not the newline or nul
// characters
return (unsigned char)c > 172 || (c < ' ' && c != '\n' && c != '\0');
}),
processedText.end());
int16_t numChar = processedText.length();
int16_t numLines = 1;

View file

@ -3,8 +3,8 @@
#include <z64.h>
typedef struct {
const char* tag; // Tag identifier to filter/remove multiple tags
int16_t yOffset; // Additional Y offset to apply for the name tag
const char* tag; // Tag identifier to filter/remove multiple tags
int16_t yOffset; // Additional Y offset to apply for the name tag
Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0
} NameTagOptions;

View file

@ -4,49 +4,37 @@
#include "game-interactor/GameInteractor.h"
#include "soh/OTRGlobals.h"
static const int songMessageMap[] = {
TEXT_WARP_MINUET_OF_FOREST,
TEXT_WARP_BOLERO_OF_FIRE,
TEXT_WARP_SERENADE_OF_WATER,
TEXT_WARP_REQUIEM_OF_SPIRIT,
TEXT_WARP_NOCTURNE_OF_SHADOW,
TEXT_WARP_PRELUDE_OF_LIGHT,
static const int songMessageMap[] = {
TEXT_WARP_MINUET_OF_FOREST, TEXT_WARP_BOLERO_OF_FIRE, TEXT_WARP_SERENADE_OF_WATER,
TEXT_WARP_REQUIEM_OF_SPIRIT, TEXT_WARP_NOCTURNE_OF_SHADOW, TEXT_WARP_PRELUDE_OF_LIGHT,
};
static const int ocarinaSongMap[] = {
OCARINA_SONG_MINUET,
OCARINA_SONG_BOLERO,
OCARINA_SONG_SERENADE,
OCARINA_SONG_REQUIEM,
OCARINA_SONG_NOCTURNE,
OCARINA_SONG_PRELUDE,
OCARINA_SONG_MINUET, OCARINA_SONG_BOLERO, OCARINA_SONG_SERENADE,
OCARINA_SONG_REQUIEM, OCARINA_SONG_NOCTURNE, OCARINA_SONG_PRELUDE,
};
static const int entranceIndexMap[] = {
ENTR_SACRED_FOREST_MEADOW_WARP_PAD, // Minuet
ENTR_SACRED_FOREST_MEADOW_WARP_PAD, // Minuet
ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD, // Bolero
ENTR_LAKE_HYLIA_WARP_PAD, // Serenade
ENTR_DESERT_COLOSSUS_WARP_PAD, // Requiem
ENTR_GRAVEYARD_WARP_PAD, // Nocturne
ENTR_TEMPLE_OF_TIME_WARP_PAD, // Prelude
ENTR_LAKE_HYLIA_WARP_PAD, // Serenade
ENTR_DESERT_COLOSSUS_WARP_PAD, // Requiem
ENTR_GRAVEYARD_WARP_PAD, // Nocturne
ENTR_TEMPLE_OF_TIME_WARP_PAD, // Prelude
};
static const int songAudioMap[] = {
NA_BGM_OCA_MINUET,
NA_BGM_OCA_BOLERO,
NA_BGM_OCA_SERENADE,
NA_BGM_OCA_REQUIEM,
NA_BGM_OCA_NOCTURNE,
NA_BGM_OCA_LIGHT,
static const int songAudioMap[] = {
NA_BGM_OCA_MINUET, NA_BGM_OCA_BOLERO, NA_BGM_OCA_SERENADE,
NA_BGM_OCA_REQUIEM, NA_BGM_OCA_NOCTURNE, NA_BGM_OCA_LIGHT,
};
static bool isWarpActive = false;
static bool isWarpActive = false;
void PauseWarp_Execute() {
if (!isWarpActive || gPlayState->msgCtx.msgMode != MSGMODE_NONE) {
return;
}
isWarpActive = false;
isWarpActive = false;
GET_PLAYER(gPlayState)->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE;
if (gPlayState->msgCtx.choiceIndex != 0) {
return;
@ -88,41 +76,42 @@ void PauseWarp_HandleSelection() {
int song = gPlayState->pauseCtx.cursorPoint[PAUSE_QUEST];
if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE &&
gPlayState->pauseCtx.pageIndex == PAUSE_QUEST && gPlayState->pauseCtx.state == 6) {
if (gSaveContext.ship.quest.id == QUEST_RANDOMIZER && Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS)) {
if (gSaveContext.ship.quest.id == QUEST_RANDOMIZER &&
Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS)) {
bool canplay = false;
switch (song) {
case QUEST_SONG_MINUET:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP);
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP);
break;
case QUEST_SONG_BOLERO:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
break;
case QUEST_SONG_SERENADE:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
break;
case QUEST_SONG_REQUIEM:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
break;
case QUEST_SONG_NOCTURNE:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
break;
case QUEST_SONG_PRELUDE:
canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP);
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP);
break;
}
if (!canplay) {

View file

@ -5,40 +5,76 @@
namespace CustomMessages {
using namespace std::literals::string_literals;
std::string MESSAGE_END() { return "\x7F\x00"s; }
std::string WAIT_FOR_INPUT() { return "\x7F\x01"s; }
std::string HORIZONTAL_SPACE(uint8_t x) {
return "\x7F\x02"s + char(x);
}
std::string GO_TO(uint16_t x) {
return "\x7F\x03"s + char(x >> 8) + char(x & 0x00FF);
}
std::string INSTANT_TEXT_ON() { return "\x7F\x04"s; }
std::string INSTANT_TEXT_OFF() { return "\x7F\x05"s; }
std::string SHOP_MESSAGE_BOX() { return "\x7F\x06\x00"s; }
std::string EVENT_TRIGGER() { return "\x7F\x07"s; }
std::string DELAY_FRAMES(uint8_t x) {
return "\x7F\x08"s + char(x);
}
std::string CLOSE_AFTER(uint8_t x) {
return "\x7F\x0A"s + char(x);
}
std::string PLAYER_NAME() { return "\x7F\x0B"s; }
std::string PLAY_OCARINA() { return "\x7F\x0C"s; }
std::string ITEM_OBTAINED(uint8_t x) {
return "\x7F\x0F"s + char(x);
}
std::string SET_SPEED(uint8_t x) {
return "\x7F\x10"s + char(x);
}
std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"s; }
std::string CURRENT_TIME() { return "\x7F\x17"s; }
std::string UNSKIPPABLE() { return "\x7F\x19"s; }
std::string TWO_WAY_CHOICE() { return "\x1B"s; }
std::string NEWLINE() { return "\x7F\x1C"s; }
std::string COLOR(std::string x) { return "\x7F\x1D"s + x; }
std::string CENTER_TEXT() { return "\x7F\x1E"s; }
std::string IF_NOT_MQ() { return "\x7F\x29"s; }
std::string MQ_ELSE() { return "\x7F\x2A"s; }
std::string MQ_END() { return "\x7F\x2B"s; }
std::string MESSAGE_END() {
return "\x7F\x00"s;
}
std::string WAIT_FOR_INPUT() {
return "\x7F\x01"s;
}
std::string HORIZONTAL_SPACE(uint8_t x) {
return "\x7F\x02"s + char(x);
}
std::string GO_TO(uint16_t x) {
return "\x7F\x03"s + char(x >> 8) + char(x & 0x00FF);
}
std::string INSTANT_TEXT_ON() {
return "\x7F\x04"s;
}
std::string INSTANT_TEXT_OFF() {
return "\x7F\x05"s;
}
std::string SHOP_MESSAGE_BOX() {
return "\x7F\x06\x00"s;
}
std::string EVENT_TRIGGER() {
return "\x7F\x07"s;
}
std::string DELAY_FRAMES(uint8_t x) {
return "\x7F\x08"s + char(x);
}
std::string CLOSE_AFTER(uint8_t x) {
return "\x7F\x0A"s + char(x);
}
std::string PLAYER_NAME() {
return "\x7F\x0B"s;
}
std::string PLAY_OCARINA() {
return "\x7F\x0C"s;
}
std::string ITEM_OBTAINED(uint8_t x) {
return "\x7F\x0F"s + char(x);
}
std::string SET_SPEED(uint8_t x) {
return "\x7F\x10"s + char(x);
}
std::string SKULLTULAS_DESTROYED() {
return "\x7F\x15"s;
}
std::string CURRENT_TIME() {
return "\x7F\x17"s;
}
std::string UNSKIPPABLE() {
return "\x7F\x19"s;
}
std::string TWO_WAY_CHOICE() {
return "\x1B"s;
}
std::string NEWLINE() {
return "\x7F\x1C"s;
}
std::string COLOR(std::string x) {
return "\x7F\x1D"s + x;
}
std::string CENTER_TEXT() {
return "\x7F\x1E"s;
}
std::string IF_NOT_MQ() {
return "\x7F\x29"s;
}
std::string MQ_ELSE() {
return "\x7F\x2A"s;
}
std::string MQ_END() {
return "\x7F\x2B"s;
}
} // namespace CustomMessages

File diff suppressed because it is too large Load diff

View file

@ -2422,4 +2422,4 @@ void StaticData::HintTable_Init() {
// clang-format on
}
}
} // namespace Rando

View file

@ -2227,4 +2227,4 @@ void StaticData::HintTable_Init_Exclude_Dungeon() {
// clang-format on
}
}
} // namespace Rando

View file

@ -2017,4 +2017,4 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
// clang-format on
}
}
} // namespace Rando

View file

@ -2173,4 +2173,4 @@ void StaticData::HintTable_Init_Item() {
// clang-format on
}
}
} // namespace Rando

Some files were not shown because too many files have changed in this diff Show more