Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer

This commit is contained in:
gymnast86
2026-04-14 03:17:46 -07:00
26 changed files with 660 additions and 86 deletions
+30 -4
View File
@@ -115,7 +115,14 @@ static Z2WolfHowlLine sNewSong3[9] = {
{HOWL_LINE_MID, 45},
};
static Z2WolfHowlData sGuideData[9] = {
#if TARGET_PC
static Z2WolfHowlLine sHowlTimeSong[6] = {
{HOWL_LINE_MID, 20}, {HOWL_LINE_LOW, 20}, {HOWL_LINE_HIGH, 40},
{HOWL_LINE_MID, 20}, {HOWL_LINE_LOW, 20}, {HOWL_LINE_HIGH, 40},
};
#endif
static Z2WolfHowlData sGuideData[9 IF_DUSK(+1)] = {
{ARRAY_SIZE(sHowlTobikusa), sHowlTobikusa},
{ARRAY_SIZE(sHowlUmakusa), sHowlUmakusa},
{ARRAY_SIZE(sHowlZeldaSong), sHowlZeldaSong},
@@ -125,6 +132,9 @@ static Z2WolfHowlData sGuideData[9] = {
{ARRAY_SIZE(sNewSong1), sNewSong1},
{ARRAY_SIZE(sNewSong2), sNewSong2},
{ARRAY_SIZE(sNewSong3), sNewSong3},
#if TARGET_PC
{ARRAY_SIZE(sHowlTimeSong), sHowlTimeSong},
#endif
};
Z2WolfHowlMgr::Z2WolfHowlMgr() : JASGlobalInstance(true) {
@@ -356,6 +366,13 @@ void Z2WolfHowlMgr::setCorrectData(s8 curveID, Z2WolfHowlData* data) {
cPitchCenter = 0.94387f;
cPitchDown = 0.74915f;
break;
#if TARGET_PC
case Z2WOLFHOWL_TIMESONG:
cPitchUp = 1.259906f;
cPitchCenter = 0.94387f;
cPitchDown = 0.840885f;
break;
#endif
default:
cPitchUp = 1.1892f;
cPitchCenter = 1.0f;
@@ -400,7 +417,7 @@ u8 Z2WolfHowlMgr::getCorrectLineNum() {
return 0;
}
static JAISoundID sCorrectPhrase[9] = {
static JAISoundID sCorrectPhrase[9 IF_DUSK(+1)] = {
Z2BGM_HOWL_TOBIKUSA,
Z2BGM_HOWL_UMAKUSA,
Z2BGM_HOWL_ZELDASONG,
@@ -410,9 +427,12 @@ static JAISoundID sCorrectPhrase[9] = {
Z2BGM_NEW_01_HOWL,
Z2BGM_NEW_02_HOWL,
Z2BGM_NEW_03_HOWL,
#if TARGET_PC
0xFFFFFFFF,
#endif
};
static JAISoundID sWindStoneSound[9] = {
static JAISoundID sWindStoneSound[9 IF_DUSK(+1)] = {
0xFFFFFFFF,
0xFFFFFFFF,
Z2BGM_STONE_ZELDASONG,
@@ -422,9 +442,12 @@ static JAISoundID sWindStoneSound[9] = {
Z2BGM_NEW_01_STONE,
Z2BGM_NEW_02_STONE,
Z2BGM_NEW_03_STONE,
#if TARGET_PC
0xFFFFFFFF,
#endif
};
static JAISoundID sCorrectDuo[9] = {
static JAISoundID sCorrectDuo[9 IF_DUSK(+1)] = {
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
@@ -434,6 +457,9 @@ static JAISoundID sCorrectDuo[9] = {
Z2BGM_NEW_01_DUO,
Z2BGM_NEW_02_DUO,
Z2BGM_NEW_03_DUO,
#if TARGET_PC
0xFFFFFFFF,
#endif
};
s8 Z2WolfHowlMgr::checkLine() {
+20
View File
@@ -19316,11 +19316,20 @@ void daAlink_c::setWaterDropColor(const J3DGXColorS10* i_color) {
if (!checkNoResetFlg2(FLG2_UNK_80000)) {
if (checkZoraWearAbility()) {
#if TARGET_PC
if (field_0x064C->getMaterialNum() >= 14)
#endif
{
field_0x064C->getMaterialNodePointer(13)->setTevColor(1, i_color);
field_0x064C->getMaterialNodePointer(0)->setTevColor(1, i_color);
field_0x064C->getMaterialNodePointer(1)->setTevColor(1, i_color);
mpLinkHatModel->getModelData()->getMaterialNodePointer(1)->setTevColor(1, i_color);
}
} else if (checkMagicArmorWearAbility()) {
#if TARGET_PC
if (field_0x064C->getMaterialNum() >= 12)
#endif
{
field_0x064C->getMaterialNodePointer(11)->setTevColor(1, i_color);
field_0x064C->getMaterialNodePointer(10)->setTevColor(1, i_color);
field_0x064C->getMaterialNodePointer(9)->setTevColor(1, i_color);
@@ -19328,11 +19337,21 @@ void daAlink_c::setWaterDropColor(const J3DGXColorS10* i_color) {
field_0x064C->getMaterialNodePointer(6)->setTevColor(1, i_color);
mpLinkHatModel->getModelData()->getMaterialNodePointer(2)->setTevColor(1, i_color);
mpLinkHatModel->getModelData()->getMaterialNodePointer(1)->setTevColor(1, i_color);
}
} else if (checkCasualWearFlg()) {
#if TARGET_PC
if (field_0x064C->getMaterialNum() >= 8)
#endif
{
field_0x064C->getMaterialNodePointer(7)->setTevColor(1, i_color);
mpLinkHatModel->getModelData()->getMaterialNodePointer(0)->setTevColor(1, i_color);
field_0x064C->getMaterialNodePointer(5)->setTevColor(1, var_r31);
}
} else {
#if TARGET_PC
if (field_0x064C->getMaterialNum() >= 18)
#endif
{
field_0x064C->getMaterialNodePointer(17)->setTevColor(1, i_color);
field_0x064C->getMaterialNodePointer(9)->setTevColor(1, i_color);
field_0x064C->getMaterialNodePointer(0)->setTevColor(1, i_color);
@@ -19342,6 +19361,7 @@ void daAlink_c::setWaterDropColor(const J3DGXColorS10* i_color) {
field_0x064C->getMaterialNodePointer(16)->setTevColor(1, var_r31);
field_0x064C->getMaterialNodePointer(15)->setTevColor(1, var_r31);
field_0x064C->getMaterialNodePointer(14)->setTevColor(1, var_r31);
}
}
}
}
+59
View File
@@ -4,6 +4,65 @@
#include "d/d_meter2_draw.h"
#include "d/d_meter2_info.h"
void daAlink_c::handleWolfHowl() {
if (checkWolf()) {
if (!dusk::getSettings().game.sunsSong) {
return;
}
// Check to see if Link has the ability to transform.
if (!dComIfGs_isEventBit(dSv_event_flag_c::M_077)) {
return;
}
// Ensure there is a proper pointer to the mMeterClass and mpMeterDraw structs in
// g_meter2_info.
const auto meterClassPtr = g_meter2_info.getMeterClass();
if (!meterClassPtr) {
return;
}
const auto meterDrawPtr = meterClassPtr->getMeterDrawPtr();
if (!meterDrawPtr) {
return;
}
// Ensure that link is not in a cutscene.
if (checkEventRun()) {
Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
return;
}
mDoCPd_c::getCpadInfo(PAD_1).mPressedButtonFlags = 0;
// Ensure that the Z Button is not dimmed
if (meterDrawPtr->getButtonZAlpha() != 1.f) {
Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
return;
}
bool canTransform = false;
if (mLinkAcch.ChkGroundHit() && !checkModeFlg(MODE_PLAYER_FLY) && !checkMagneBootsOn()) {
if (!checkForestOldCentury()) {
if (checkMidnaRide()) {
if ((checkWolf() &&
(checkModeFlg(MODE_UNK_1000) || dComIfGp_checkPlayerStatus0(0, 0x10))) ||
(!checkWolf() &&
(checkEventRun() || getMidnaActor()->checkMetamorphoseEnable()) &&
(checkModeFlg(4) || dComIfGp_checkPlayerStatus0(0, 0x10))))
{
canTransform = true;
}
}
}
}
getWolfHowlMgrP()->setCorrectCurve(9);
procWolfHowlDemoInit();
}
}
void daAlink_c::handleQuickTransform() {
if (!dusk::getSettings().game.enableQuickTransform) {
return;
+19
View File
@@ -3954,7 +3954,13 @@ int daAlink_c::procWolfHowlDemoInit() {
mZ2WolfHowlMgr.setCorrectCurve(-1);
}
} else {
#if TARGET_PC
if (mZ2WolfHowlMgr.getCorrectCurveID() != 9) {
mZ2WolfHowlMgr.setCorrectCurve(-1);
}
#else
mZ2WolfHowlMgr.setCorrectCurve(-1);
#endif
}
mNormalSpeed = 0.0f;
@@ -4095,6 +4101,19 @@ int daAlink_c::procWolfHowlDemo() {
dStage_changeScene(mProcVar0.mHowlExitID, 0.0f, 0, fopAcM_GetRoomNo(this),
shape_angle.y, -1);
} else {
#if TARGET_PC
if (daAlink_getAlinkActorClass()->getCorrectCurveID() == 9) {
if (dComIfGp_roomControl_getTimePass()) {
g_env_light.time_change_rate = 1.0f;
dComIfGp_event_reset();
dCam_getBody()->EndEventCamera(fopAcM_GetID(this));
} else {
setWolfHowlNotHappen(isSkipEdge);
}
return 1;
}
#endif
fopAc_ac_c* actor_p = NULL;
if (gwolf_p == NULL) {
fopAcIt_Executor((fopAcIt_ExecutorFunc)daAlink_searchWolfHowl,
+1 -1
View File
@@ -1459,7 +1459,7 @@ void dDlst_shadowControl_c::init() {
#else
u32 buffer_size = GXGetTexBufferSize(size, size, 5, GX_DISABLE, 0);
#endif
delete mShadowTexData[i];
JKR_DELETE_ARRAY(mShadowTexData[i]);
mShadowTexData[i] = JKR_NEW_ARRAY_ARGS(u8, buffer_size, 0x20);
mShadowTexObj[i].reset();
+13
View File
@@ -1540,8 +1540,21 @@ void dScnKy_env_light_c::setDaytime() {
}
if (dComIfGp_roomControl_getTimePass() && !field_0x130a && temp_r29) {
#if TARGET_PC
f32 prev = daytime;
#endif
daytime += time_change_rate;
#if TARGET_PC
if (time_change_rate == 1.0f &&
(std::fmod(daytime - 90.0f + 360.0f, 360.0f) < std::fmod(prev - 90.0f + 360.0f, 360.0f) ||
std::fmod(daytime - 285.0f + 360.0f, 360.0f) < std::fmod(prev - 285.0f + 360.0f, 360.0f)))
{
g_env_light.time_change_rate = 0.012f;
}
#endif
// Stage is Fishing Pond or Hena's Hut
if (!strcmp(dComIfGp_getStartStageName(), "F_SP127") ||
!strcmp(dComIfGp_getStartStageName(), "R_SP127"))
+16 -2
View File
@@ -69,6 +69,13 @@ std::filesystem::path GetSentryDatabasePath() {
return std::filesystem::path(configPath) / "sentry";
}
std::filesystem::path GetLogAttachmentPath() {
if (const char* logPath = GetLogFilePath()) {
return logPath;
}
return {};
}
std::filesystem::path GetCrashpadHandlerPath() {
const char* basePath = SDL_GetBasePath();
if (!basePath) {
@@ -76,8 +83,6 @@ std::filesystem::path GetCrashpadHandlerPath() {
}
const std::filesystem::path handlerDir(basePath);
SDL_free(const_cast<char*>(basePath));
#if _WIN32
return handlerDir / "crashpad_handler.exe";
#else
@@ -113,6 +118,15 @@ void ConfigurePathOptions(sentry_options_t* options) {
sentry_options_set_handler_path(options, handlerPathUtf8.c_str());
}
#endif
const auto logPath = GetLogAttachmentPath();
if (!logPath.empty()) {
#if _WIN32
sentry_options_add_attachmentw(options, logPath.wstring().c_str());
#else
sentry_options_add_attachment(options, logPath.string().c_str());
#endif
}
}
#endif
+1
View File
@@ -39,6 +39,7 @@ static void ApplyPresetDusk() {
s.game.instantSaves.setValue(true);
s.game.midnasLamentNonStop.setValue(true);
s.game.enableFrameInterpolation.setValue(true);
s.game.sunsSong.setValue(true);
s.game.bloomMode.setValue(BloomMode::Dusk);
}
+9
View File
@@ -11,6 +11,15 @@ namespace dusk {
if (ImGui::BeginMenu("Enhancements")) {
if (ImGui::BeginMenu("Quality of Life")) {
config::ImGuiCheckbox("Quick Transform (R+Y)", getSettings().game.enableQuickTransform);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Allows you to quickly transform between forms\n"
"without having to talk to Midna.");
}
config::ImGuiCheckbox("Sun's Song (R+X)", getSettings().game.sunsSong);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Allows Wolf Link to howl and change the time of day.");
}
config::ImGuiCheckbox("Bigger Wallets", getSettings().game.biggerWallets);
if (ImGui::IsItemHovered()) {
+119 -1
View File
@@ -16,6 +16,7 @@
#include "m_Do/m_Do_graphic.h"
#include <aurora/gfx.h>
#include <SDL3/SDL_gamepad.h>
#include "dusk/main.h"
@@ -174,6 +175,122 @@ namespace dusk {
ImGui::EndChild();
}
struct SpecificButtonName {
SDL_GamepadType Type;
const char* Name;
};
struct ButtonNames {
SDL_GamepadButton Button;
std::vector<SpecificButtonName> Names;
};
// clang-format off
static const std::vector<ButtonNames> GamepadButtonNames = {
{ SDL_GAMEPAD_BUTTON_LEFT_STICK, {
{SDL_GAMEPAD_TYPE_PS3, "L3"},
{SDL_GAMEPAD_TYPE_PS4, "L3"},
{SDL_GAMEPAD_TYPE_PS5, "L3"},
{SDL_GAMEPAD_TYPE_XBOX360, "Left Stick"},
{SDL_GAMEPAD_TYPE_XBOXONE, "Left Stick"},
{SDL_GAMEPAD_TYPE_GAMECUBE, "Control Stick"},
}},
{ SDL_GAMEPAD_BUTTON_RIGHT_STICK, {
{SDL_GAMEPAD_TYPE_PS3, "R3"},
{SDL_GAMEPAD_TYPE_PS4, "R3"},
{SDL_GAMEPAD_TYPE_PS5, "R3"},
{SDL_GAMEPAD_TYPE_XBOX360, "Right Stick"},
{SDL_GAMEPAD_TYPE_XBOXONE, "Right Stick"},
{SDL_GAMEPAD_TYPE_GAMECUBE, "C Stick"},
}},
{ SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, {
{SDL_GAMEPAD_TYPE_PS3, "L1"},
{SDL_GAMEPAD_TYPE_PS4, "L1"},
{SDL_GAMEPAD_TYPE_PS5, "L1"},
{SDL_GAMEPAD_TYPE_XBOX360, "LB"},
{SDL_GAMEPAD_TYPE_XBOXONE, "LB"},
}},
{ SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, {
{SDL_GAMEPAD_TYPE_PS3, "R1"},
{SDL_GAMEPAD_TYPE_PS4, "R1"},
{SDL_GAMEPAD_TYPE_PS5, "R1"},
{SDL_GAMEPAD_TYPE_XBOX360, "RB"},
{SDL_GAMEPAD_TYPE_XBOXONE, "RB"},
{SDL_GAMEPAD_TYPE_GAMECUBE, "Z"},
}},
{ SDL_GAMEPAD_BUTTON_BACK, {
{SDL_GAMEPAD_TYPE_PS3, "Select"},
{SDL_GAMEPAD_TYPE_PS4, "Share"},
{SDL_GAMEPAD_TYPE_PS5, "Create"},
{SDL_GAMEPAD_TYPE_XBOX360, "Back"},
{SDL_GAMEPAD_TYPE_XBOXONE, "View"},
}},
{ SDL_GAMEPAD_BUTTON_START, {
{SDL_GAMEPAD_TYPE_PS3, "Start"},
{SDL_GAMEPAD_TYPE_PS4, "Options"},
{SDL_GAMEPAD_TYPE_PS5, "Options"},
{SDL_GAMEPAD_TYPE_XBOX360, "Start"},
{SDL_GAMEPAD_TYPE_XBOXONE, "Menu"},
{SDL_GAMEPAD_TYPE_GAMECUBE, "Start/Pause"},
}},
};
// clang-format on
static const char* GetNameForGamepadButton(SDL_Gamepad* gamepad, u32 buttonUntyped) {
if (buttonUntyped == PAD_NATIVE_BUTTON_INVALID) {
return "Not bound";
}
auto button = static_cast<SDL_GamepadButton>(buttonUntyped);
auto label = SDL_GetGamepadButtonLabel(gamepad, button);
switch (label) {
case SDL_GAMEPAD_BUTTON_LABEL_A:
return "A";
case SDL_GAMEPAD_BUTTON_LABEL_B:
return "B";
case SDL_GAMEPAD_BUTTON_LABEL_X:
return "X";
case SDL_GAMEPAD_BUTTON_LABEL_Y:
return "Y";
case SDL_GAMEPAD_BUTTON_LABEL_CROSS:
return "Cross";
case SDL_GAMEPAD_BUTTON_LABEL_CIRCLE:
return "Circle";
case SDL_GAMEPAD_BUTTON_LABEL_TRIANGLE:
return "Triangle";
case SDL_GAMEPAD_BUTTON_LABEL_SQUARE:
return "Square";
default:; // Fall through
}
auto padType = SDL_GetGamepadType(gamepad);
for (const auto& buttonNames : GamepadButtonNames) {
if (buttonNames.Button != button) {
continue;
}
for (const auto& name : buttonNames.Names) {
if (name.Type == padType) {
return name.Name;
}
}
}
switch (button) {
case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
return "D-pad left";
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
return "D-pad right";
case SDL_GAMEPAD_BUTTON_DPAD_UP:
return "D-pad up";
case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
return "D-pad down";
default:
return PADGetNativeButtonName(buttonUntyped);
}
}
void ImGuiMenuGame::windowControllerConfig() {
if (!m_showControllerConfig) {
return;
@@ -303,6 +420,7 @@ namespace dusk {
ImGuiBeginGroupPanel("Buttons", ImVec2(150 * scale, 20 * scale));
SDL_Gamepad* gamepad = PADGetSDLGamepadForIndex(PADGetIndexForPort(m_controllerConfig.m_selectedPort));
u32 buttonCount;
PADButtonMapping* btnMappingList = PADGetButtonMappings(m_controllerConfig.m_selectedPort, &buttonCount);
if (btnMappingList != nullptr) {
@@ -322,7 +440,7 @@ namespace dusk {
if (m_controllerConfig.m_isReading && m_controllerConfig.m_pendingButtonMapping == &btnMappingList[i]) {
dispName = fmt::format("Press a Key...##{}", btnName);
} else {
const char* nativeName = PADGetNativeButtonName(btnMappingList[i].nativeButton);
const char* nativeName = GetNameForGamepadButton(gamepad, btnMappingList[i].nativeButton);
if (nativeName == nullptr) {
nativeName = "[unbound]";
}
+118 -22
View File
@@ -1,6 +1,11 @@
#include "dusk/logging.h"
#include <array>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <filesystem>
#include <mutex>
#include <string>
#include "tracy/Tracy.hpp"
@@ -20,6 +25,60 @@ static constexpr std::string_view StubFragments[] = {
"but selective updates are not implemented"sv,
};
namespace {
std::mutex g_logMutex;
FILE* g_logFile = nullptr;
std::string g_logFilePath;
const char* LogLevelString(AuroraLogLevel level) {
switch (level) {
case LOG_DEBUG:
return "DEBUG";
case LOG_INFO:
return "INFO";
case LOG_WARNING:
return "WARNING";
case LOG_ERROR:
return "ERROR";
case LOG_FATAL:
return "FATAL";
}
return "??";
}
FILE* LogStreamForLevel(AuroraLogLevel level) {
return level >= LOG_ERROR ? stderr : stdout;
}
std::string MakeTimestampedLogName() {
const auto now = std::chrono::system_clock::now();
const std::time_t nowTime = std::chrono::system_clock::to_time_t(now);
std::tm localTime{};
#if _WIN32
localtime_s(&localTime, &nowTime);
#else
localtime_r(&nowTime, &localTime);
#endif
std::array<char, 32> buffer{};
std::strftime(buffer.data(), buffer.size(), "dusk-%Y%m%d-%H%M%S.log", &localTime);
return buffer.data();
}
void WriteLogLine(FILE* out, const char* levelStr, const char* module, const char* message, unsigned int len) {
if (out == nullptr) {
return;
}
std::fprintf(out, "[%s | %s] ", levelStr, module);
std::fwrite(message, 1, len, out);
std::fputc('\n', out);
std::fflush(out);
}
} // namespace
static bool IsForStubLog(const char* message) {
std::string_view msg_view(message);
@@ -40,32 +99,69 @@ void aurora_log_callback(AuroraLogLevel level, const char* module, const char* m
return;
}
const char* levelStr = "??";
FILE* out = stdout;
switch (level) {
case LOG_DEBUG:
levelStr = "DEBUG";
break;
case LOG_INFO:
levelStr = "INFO";
break;
case LOG_WARNING:
levelStr = "WARNING";
break;
case LOG_ERROR:
levelStr = "ERROR";
out = stderr;
break;
case LOG_FATAL:
levelStr = "FATAL";
out = stderr;
break;
if (module == nullptr) {
module = "";
}
fprintf(out, "[%s | %s] %s\n", levelStr, module, message);
const char* levelStr = LogLevelString(level);
FILE* out = LogStreamForLevel(level);
WriteLogLine(out, levelStr, module, message, len);
{
std::lock_guard lock(g_logMutex);
if (g_logFile != nullptr) {
WriteLogLine(g_logFile, levelStr, module, message, len);
}
}
if (level == LOG_FATAL) {
fflush(out);
abort();
}
}
aurora::Module DuskLog("dusk");
void dusk::InitializeFileLogging(const char* configDir, AuroraLogLevel logLevel) {
std::lock_guard lock(g_logMutex);
if (g_logFile != nullptr || configDir == nullptr) {
return;
}
std::error_code ec;
const std::filesystem::path logsDir = std::filesystem::path(configDir) / "logs";
std::filesystem::create_directories(logsDir, ec);
if (ec) {
std::fprintf(stderr, "[WARNING | dusk] Failed to create log directory '%s': %s\n",
logsDir.string().c_str(), ec.message().c_str());
return;
}
const std::filesystem::path logPath = logsDir / MakeTimestampedLogName();
g_logFile = std::fopen(logPath.string().c_str(), "wb");
if (g_logFile == nullptr) {
std::fprintf(stderr, "[WARNING | dusk] Failed to open log file '%s'\n",
logPath.string().c_str());
return;
}
g_logFilePath = logPath.string();
aurora::g_config.logCallback = &aurora_log_callback;
aurora::g_config.logLevel = logLevel;
WriteLogLine(g_logFile, "INFO", "dusk", "File logging initialized", 24);
}
void dusk::ShutdownFileLogging() {
std::lock_guard lock(g_logMutex);
if (g_logFile == nullptr) {
return;
}
std::fflush(g_logFile);
std::fclose(g_logFile);
g_logFile = nullptr;
}
const char* dusk::GetLogFilePath() {
std::lock_guard lock(g_logMutex);
return g_logFilePath.empty() ? nullptr : g_logFilePath.c_str();
}
+2
View File
@@ -35,6 +35,7 @@ UserSettings g_userSettings = {
.noMissClimbing {"game.noMissClimbing", false},
.fastTears {"game.fastTears", false},
.instantSaves {"game.instantSaves", false},
.sunsSong {"game.sunsSong", false},
// Preferences
.enableMirrorMode {"game.enableMirrorMode", false},
@@ -113,6 +114,7 @@ void registerSettings() {
Register(g_userSettings.game.fastClimbing);
Register(g_userSettings.game.fastTears);
Register(g_userSettings.game.instantSaves);
Register(g_userSettings.game.sunsSong);
Register(g_userSettings.game.enableMirrorMode);
Register(g_userSettings.game.invertCameraXAxis);
Register(g_userSettings.game.bloomMode);
+6
View File
@@ -748,6 +748,12 @@ void fapGm_Execute() {
#endif
#if TARGET_PC
if (mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getTrigX(PAD_1)) {
if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) {
dynamic_cast<daAlink_c*>(link)->handleWolfHowl();
}
}
if (mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getTrigY(PAD_1)) {
if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) {
dynamic_cast<daAlink_c*>(link)->handleQuickTransform();
+49 -1
View File
@@ -43,6 +43,8 @@
#include <cstring>
#include <chrono>
#include <filesystem>
#include <system_error>
#include <thread>
#include "SSystem/SComponent/c_API.h"
#include "dusk/app_info.hpp"
@@ -371,6 +373,48 @@ static const char* CalculateConfigPath() {
return result;
}
static void EnsureInitialPipelineCache(const char* configDir) {
if (configDir == nullptr) {
return;
}
const std::filesystem::path configPathFs(configDir);
const std::filesystem::path pipelineCachePath = configPathFs / "pipeline_cache.db";
if (std::filesystem::exists(pipelineCachePath)) {
return;
}
const char* basePath = SDL_GetBasePath();
if (basePath == nullptr) {
DuskLog.warn("Unable to resolve base path while seeding pipeline cache: {}", SDL_GetError());
return;
}
const std::filesystem::path initialPipelineCachePath =
std::filesystem::path(basePath) / "initial_pipeline_cache.db";
if (!std::filesystem::exists(initialPipelineCachePath)) {
DuskLog.info("No bundled initial pipeline cache found at '{}'", initialPipelineCachePath.string());
return;
}
std::error_code ec;
std::filesystem::create_directories(configPathFs, ec);
if (ec) {
DuskLog.warn("Failed to create config directory '{}' for pipeline cache: {}",
configPathFs.string(), ec.message());
return;
}
std::filesystem::copy_file(initialPipelineCachePath, pipelineCachePath, std::filesystem::copy_options::none, ec);
if (ec) {
DuskLog.warn("Failed to seed pipeline cache from '{}' to '{}': {}",
initialPipelineCachePath.string(), pipelineCachePath.string(), ec.message());
return;
}
DuskLog.info("Seeded pipeline cache from '{}'", initialPipelineCachePath.string());
}
static constexpr PADDefaultMapping defaultPadMapping = {
.buttons = {
{SDL_GAMEPAD_BUTTON_SOUTH, PAD_BUTTON_A},
@@ -460,10 +504,13 @@ int game_main(int argc, char* argv[]) {
}
configPath = CalculateConfigPath();
const auto startupLogLevel = static_cast<AuroraLogLevel>(parsed_arg_options["log-level"].as<uint8_t>());
dusk::InitializeFileLogging(configPath, startupLogLevel);
dusk::config::LoadFromUserPreferences();
ApplyCVarOverrides(parsed_arg_options["cvar"]);
dusk::InitializeCrashReporting();
EnsureInitialPipelineCache(configPath);
AuroraConfig config{};
config.appName = dusk::AppName;
@@ -476,7 +523,7 @@ int game_main(int argc, char* argv[]) {
config.windowHeight = defaultWindowHeight * 2;
config.desiredBackend = ResolveDesiredBackend(parsed_arg_options);
config.logCallback = &aurora_log_callback;
config.logLevel = (AuroraLogLevel)parsed_arg_options["log-level"].as<uint8_t>();
config.logLevel = startupLogLevel;
config.mem1Size = 256 * 1024 * 1024;
config.mem2Size = 24 * 1024 * 1024;
config.allowJoystickBackgroundEvents = true;
@@ -558,6 +605,7 @@ int game_main(int argc, char* argv[]) {
main01();
dusk::ShutdownCrashReporting();
dusk::ShutdownFileLogging();
fflush(stdout);
fflush(stderr);