Merge branch 'rando-next' of https://github.com/HarbourMasters/Shipwright into shopsanity

This commit is contained in:
Garrett Cox 2022-09-03 09:49:50 -05:00
commit c037bfc16b
64 changed files with 3268 additions and 3344 deletions

View File

@ -121,6 +121,7 @@ set(Source_Files__CustomImpl
source_group("Source Files\\CustomImpl" FILES ${Source_Files__CustomImpl}) source_group("Source Files\\CustomImpl" FILES ${Source_Files__CustomImpl})
set(Source_Files__CustomImpl__Hooks set(Source_Files__CustomImpl__Hooks
"Hooks.cpp"
"Hooks.h" "Hooks.h"
) )
source_group("Source Files\\CustomImpl\\Hooks" FILES ${Source_Files__CustomImpl__Hooks}) source_group("Source Files\\CustomImpl\\Hooks" FILES ${Source_Files__CustomImpl__Hooks})

View File

@ -1,6 +1,9 @@
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include "Utils/StringHelper.h" #include "Utils/StringHelper.h"
#include "CrashHandler.h" #include "CrashHandler.h"
#include "Window.h"
extern "C" void DeinitOTR(void);
#if defined(__linux__) #if defined(__linux__)
#include <csignal> #include <csignal>
@ -10,163 +13,343 @@
#include <execinfo.h> #include <execinfo.h>
#include <unistd.h> #include <unistd.h>
extern "C" void DeinitOTR(void);
static void PrintRegisters(ucontext_t* ctx) { static void PrintRegisters(ucontext_t* ctx) {
char regbuffer[1024]; char regbuffer[1024];
SPDLOG_CRITICAL("Registers:"); SPDLOG_CRITICAL("Registers:");
#if defined(__x86_64__) #if defined(__x86_64__)
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RAX]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RAX]);
SPDLOG_CRITICAL("RAX: {} ", regbuffer); SPDLOG_CRITICAL("RAX: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDI]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDI]);
SPDLOG_CRITICAL("RDI: {} ", regbuffer); SPDLOG_CRITICAL("RDI: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSI]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSI]);
SPDLOG_CRITICAL("RSI: {} ", regbuffer); SPDLOG_CRITICAL("RSI: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDX]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDX]);
SPDLOG_CRITICAL("RDX: {} ", regbuffer); SPDLOG_CRITICAL("RDX: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RCX]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RCX]);
SPDLOG_CRITICAL("RCX: {} ", regbuffer); SPDLOG_CRITICAL("RCX: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R8]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R8]);
SPDLOG_CRITICAL("R8 : {} ", regbuffer); SPDLOG_CRITICAL("R8 : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R9]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R9]);
SPDLOG_CRITICAL("R9 : {} ", regbuffer); SPDLOG_CRITICAL("R9 : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R10]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R10]);
SPDLOG_CRITICAL("R10: {} ", regbuffer); SPDLOG_CRITICAL("R10: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R11]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R11]);
SPDLOG_CRITICAL("R11: {} ", regbuffer); SPDLOG_CRITICAL("R11: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSP]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSP]);
SPDLOG_CRITICAL("RSP: {} ", regbuffer); SPDLOG_CRITICAL("RSP: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBX]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBX]);
SPDLOG_CRITICAL("RBX: {} ", regbuffer); SPDLOG_CRITICAL("RBX: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBP]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBP]);
SPDLOG_CRITICAL("RBP: {} ", regbuffer); SPDLOG_CRITICAL("RBP: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R12]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R12]);
SPDLOG_CRITICAL("R12: {} ", regbuffer); SPDLOG_CRITICAL("R12: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R13]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R13]);
SPDLOG_CRITICAL("R13: {} ", regbuffer); SPDLOG_CRITICAL("R13: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R14]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R14]);
SPDLOG_CRITICAL("R14: {} ", regbuffer); SPDLOG_CRITICAL("R14: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R15]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R15]);
SPDLOG_CRITICAL("R15: {} ", regbuffer); SPDLOG_CRITICAL("R15: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RIP]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RIP]);
SPDLOG_CRITICAL("RIP: {} ", regbuffer); SPDLOG_CRITICAL("RIP: {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_EFL]); snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_EFL]);
SPDLOG_CRITICAL("EFLAGS: {} ", regbuffer); SPDLOG_CRITICAL("EFLAGS: {} ", regbuffer);
#else #else
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDI]); snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDI]);
SPDLOG_CRITICAL("EDI : {} ", regbuffer); SPDLOG_CRITICAL("EDI : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESI]); snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESI]);
SPDLOG_CRITICAL("ESI : {} ", regbuffer); SPDLOG_CRITICAL("ESI : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBP]); snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBP]);
SPDLOG_CRITICAL("EBP : {} ", regbuffer); SPDLOG_CRITICAL("EBP : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESP]); snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESP]);
SPDLOG_CRITICAL("ESP : {} ", regbuffer); SPDLOG_CRITICAL("ESP : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBX]); snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBX]);
SPDLOG_CRITICAL("EBX : {} ", regbuffer); SPDLOG_CRITICAL("EBX : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDX]); snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDX]);
SPDLOG_CRITICAL("EDX : {} ", regbuffer); SPDLOG_CRITICAL("EDX : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ECX]); snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ECX]);
SPDLOG_CRITICAL("ECX : {} ", regbuffer); SPDLOG_CRITICAL("ECX : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EAX]); snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EAX]);
SPDLOG_CRITICAL("EAX : {} ", regbuffer); SPDLOG_CRITICAL("EAX : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EIP]); snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EIP]);
SPDLOG_CRITICAL("EIP : {} ", regbuffer); SPDLOG_CRITICAL("EIP : {} ", regbuffer);
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EFL]); snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EFL]);
SPDLOG_CRITICAL("EFL : {} ", regbuffer); SPDLOG_CRITICAL("EFL : {} ", regbuffer);
#endif #endif
} }
static void ErrorHandler(int sig, siginfo_t* sigInfo, void* data) static void ErrorHandler(int sig, siginfo_t* sigInfo, void* data) {
{ std::array<void*, 4096> arr;
std::array<void*, 4096> arr; ucontext_t* ctx = static_cast<ucontext_t*>(data);
ucontext_t* ctx = static_cast<ucontext_t*>(data); constexpr size_t nMaxFrames = arr.size();
constexpr size_t nMaxFrames = arr.size(); size_t size = backtrace(arr.data(), nMaxFrames);
size_t size = backtrace(arr.data(), nMaxFrames); char** symbols = backtrace_symbols(arr.data(), nMaxFrames);
char** symbols = backtrace_symbols(arr.data(), nMaxFrames);
SPDLOG_CRITICAL("(Signal: {})\n", sig); SPDLOG_CRITICAL("(Signal: {})", sig);
switch (sig) { switch (sig) {
case SIGILL: case SIGILL:
SPDLOG_CRITICAL("ILLEGAL INSTRUCTION"); SPDLOG_CRITICAL("ILLEGAL INSTRUCTION");
break; break;
case SIGABRT: case SIGABRT:
SPDLOG_CRITICAL("ABORT"); SPDLOG_CRITICAL("ABORT");
break; break;
case SIGFPE: case SIGFPE:
SPDLOG_CRITICAL("ERRONEUS ARITHEMETIC OPERATION"); SPDLOG_CRITICAL("ERRONEUS ARITHEMETIC OPERATION");
break; break;
case SIGSEGV: case SIGSEGV:
SPDLOG_CRITICAL("INVALID ACCESS TO STORAGE"); SPDLOG_CRITICAL("INVALID ACCESS TO STORAGE");
break; break;
} }
PrintRegisters(ctx); PrintRegisters(ctx);
SPDLOG_CRITICAL("Traceback:\n"); SPDLOG_CRITICAL("Traceback:");
for (size_t i = 1; i < size; i++) for (size_t i = 1; i < size; i++) {
{ Dl_info info;
Dl_info info; int gotAddress = dladdr(arr[i], &info);
int gotAddress = dladdr(arr[i], &info); std::string functionName(symbols[i]);
std::string functionName(symbols[i]);
if (gotAddress != 0 && info.dli_sname != nullptr) if (gotAddress != 0 && info.dli_sname != nullptr) {
{
FILE* pipe; FILE* pipe;
int32_t status; int32_t status;
char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status);
const char* nameFound = info.dli_sname; const char* nameFound = info.dli_sname;
if (status == 0) if (status == 0) {
{ nameFound = demangled;
nameFound = demangled; }
}
#if 0 #if 0
char command[256]; char command[256];
char addrLine[128]; char addrLine[128];
snprintf(command, sizeof(command), "addr2line -e soh.elf %s + 0x%lX", nameFound, (uintptr_t)arr[i] - (uintptr_t)info.dli_saddr); snprintf(command, sizeof(command), "addr2line -e soh.elf %s + 0x%lX", nameFound, (uintptr_t)arr[i] - (uintptr_t)info.dli_saddr);
pipe = popen(command, "r"); pipe = popen(command, "r");
fgets(addrLine, 128, pipe); fgets(addrLine, 128, pipe);
#endif #endif
functionName = StringHelper::Sprintf("%s (+0x%X)", nameFound, functionName = StringHelper::Sprintf("%s (+0x%X)", nameFound,
(char*)arr[i] - (char*)info.dli_saddr); (char*)arr[i] - (char*)info.dli_saddr);
free(demangled); free(demangled);
} }
SPDLOG_CRITICAL("{} {}", i, functionName.c_str()); SPDLOG_CRITICAL("{} {}", i, functionName.c_str());
} }
free(symbols); free(symbols);
DeinitOTR(); DeinitOTR();
exit(1); exit(1);
} }
static void ShutdownHandler(int sig, siginfo_t* sigInfo, void* data) { static void ShutdownHandler(int sig, siginfo_t* sigInfo, void* data) {
DeinitOTR(); DeinitOTR();
exit(1); exit(1);
} }
extern "C" void SetupHandlerLinux() { extern "C" void SetupHandlerLinux() {
struct sigaction action; struct sigaction action;
struct sigaction shutdownAction; struct sigaction shutdownAction;
action.sa_flags = SA_SIGINFO; action.sa_flags = SA_SIGINFO;
action.sa_sigaction = ErrorHandler; action.sa_sigaction = ErrorHandler;
sigaction(SIGILL, &action, nullptr);
sigaction(SIGABRT, &action, nullptr);
sigaction(SIGFPE, &action, nullptr);
sigaction(SIGSEGV, &action, nullptr);
shutdownAction.sa_flags = SA_SIGINFO;
shutdownAction.sa_sigaction = ShutdownHandler;
sigaction(SIGINT, &shutdownAction, nullptr);
sigaction(SIGTERM, &shutdownAction, nullptr);
sigaction(SIGQUIT, &shutdownAction, nullptr);
sigaction(SIGKILL, &shutdownAction, nullptr);
sigaction(SIGILL, &action, nullptr);
sigaction(SIGABRT, &action, nullptr);
sigaction(SIGFPE, &action, nullptr);
sigaction(SIGSEGV, &action, nullptr);
shutdownAction.sa_flags = SA_SIGINFO;
shutdownAction.sa_sigaction = ShutdownHandler;
sigaction(SIGINT, &shutdownAction, nullptr);
sigaction(SIGTERM, &shutdownAction, nullptr);
sigaction(SIGQUIT, &shutdownAction, nullptr);
sigaction(SIGKILL, &shutdownAction, nullptr);
} }
#elif _WIN32
#if defined(_WIN32) && !defined(_WIN64)
#define WINDOWS_32_BIT
#endif
static void PrintRegisters(CONTEXT* ctx) {
SPDLOG_CRITICAL("Register dump");
char regBuff[50];
#if defined(_M_AMD64)
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rax);
SPDLOG_CRITICAL("RAX: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rcx);
SPDLOG_CRITICAL("RCX: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rdx);
SPDLOG_CRITICAL("RDX: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rbx);
SPDLOG_CRITICAL("RBX: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rsp);
SPDLOG_CRITICAL("RSP: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rbp);
SPDLOG_CRITICAL("RBP: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rsi);
SPDLOG_CRITICAL("RSI: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rdi);
SPDLOG_CRITICAL("RDI: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R9);
SPDLOG_CRITICAL("R9: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R10);
SPDLOG_CRITICAL("R10: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R11);
SPDLOG_CRITICAL("R11: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R12);
SPDLOG_CRITICAL("R12: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R13);
SPDLOG_CRITICAL("R13: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R14);
SPDLOG_CRITICAL("R14: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R15);
SPDLOG_CRITICAL("R15: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rip);
SPDLOG_CRITICAL("RIP: {}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->EFlags);
SPDLOG_CRITICAL("EFLAGS: {}", regBuff);
#elif WINDOWS_32_BIT
snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Edi);
SPDLOG_CRITICAL("EDI: 0x{}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Esi);
SPDLOG_CRITICAL("ESI: 0x{}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Ebx);
SPDLOG_CRITICAL("EBX: 0x{}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Ecx);
SPDLOG_CRITICAL("ECX: 0x{}", ctx->Ecx);
snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Eax);
SPDLOG_CRITICAL("EAX: 0x{}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Ebp);
SPDLOG_CRITICAL("EBP: 0x{}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Esp);
SPDLOG_CRITICAL("ESP: 0x{}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->EFlags);
SPDLOG_CRITICAL("EFLAGS: 0x{}", regBuff);
snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Eip);
SPDLOG_CRITICAL("EIP: 0x{}", regBuff);
#endif
}
static void printStack(CONTEXT* ctx) {
BOOL result;
HANDLE process;
HANDLE thread;
HMODULE hModule;
ULONG frame;
DWORD64 displacement;
DWORD disp;
#if defined(_M_AMD64)
STACKFRAME64 stack;
memset(&stack, 0, sizeof(STACKFRAME64));
#elif WINDOWS_32_BIT
STACKFRAME stack;
memset(&stack, 0, sizeof(STACKFRAME));
stack.AddrPC.Offset = (*ctx).Eip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = (*ctx).Esp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = (*ctx).Ebp;
stack.AddrFrame.Mode = AddrModeFlat;
#endif
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME + sizeof(TCHAR)];
char module[512];
PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
CONTEXT ctx2;
memcpy(&ctx2, ctx, sizeof(CONTEXT));
PrintRegisters(&ctx2);
process = GetCurrentProcess();
thread = GetCurrentThread();
SymInitialize(process, nullptr, true);
constexpr DWORD machineType =
#if defined(_M_AMD64)
IMAGE_FILE_MACHINE_AMD64;
#elif WINDOWS_32_BIT
IMAGE_FILE_MACHINE_I386;
#endif
displacement = 0;
for (frame = 0;; frame++) {
result = StackWalk(machineType, process, thread, &stack, &ctx2, nullptr, SymFunctionTableAccess,
SymGetModuleBase, nullptr);
if (!result) {
break;
}
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME;
SymFromAddr(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbol);
#if defined(_M_AMD64)
IMAGEHLP_LINE64 line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
#elif WINDOWS_32_BIT
IMAGEHLP_LINE line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE);
#endif
if (SymGetLineFromAddr(process, stack.AddrPC.Offset, &disp, &line)) {
SPDLOG_CRITICAL("{} in {}: line: {}: ", symbol->Name, line.FileName, line.LineNumber);
}
else {
char addrString[25];
snprintf(addrString, std::size(addrString), "0x%016llX", symbol->Address);
SPDLOG_CRITICAL("at {}, addr 0x{}", symbol->Name, addrString);
hModule = nullptr;
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)(stack.AddrPC.Offset), &hModule);
if (hModule != nullptr) {
GetModuleFileNameA(hModule, module, sizeof(module));
}
SPDLOG_CRITICAL("In {}", module);
}
}
Ship::Window::GetInstance()->GetLogger()->flush();
spdlog::shutdown();
DeinitOTR();
}
extern "C" LONG seh_filter(struct _EXCEPTION_POINTERS* ex) {
char exceptionString[20];
snprintf(exceptionString, std::size(exceptionString), "0x%x", ex->ExceptionRecord->ExceptionCode);
SPDLOG_CRITICAL("EXCEPTION {} occurred", exceptionString);
printStack(ex->ContextRecord);
MessageBox(nullptr, L"SoH Has crashed. Please upload the logs to the support channel in discord.", L"Crash", MB_OK | MB_ICONERROR);
return EXCEPTION_EXECUTE_HANDLER;
}
#endif #endif

View File

@ -13,6 +13,25 @@ void SetupHandlerLinux(void);
} }
#endif #endif
#endif // __linux__ #elif _WIN32 // __linux__ ^^^^ _WIN32 vvvvv
#include <windows.h>
#include <DbgHelp.h>
#include <inttypes.h>
#include <excpt.h>
#ifdef __cplusplus
extern "C" {
#endif
LONG seh_filter(struct _EXCEPTION_POINTERS* ex);
#ifdef __cplusplus
}
#endif
#pragma comment(lib, "Dbghelp.lib")
#endif
#endif // CRASH_HANDLER_H #endif // CRASH_HANDLER_H

View File

@ -16,28 +16,28 @@ namespace Ship {
if (CVar_Get(args[2].c_str()) != nullptr) { if (CVar_Get(args[2].c_str()) != nullptr) {
const char* key = args[2].c_str(); const char* key = args[2].c_str();
GameOverlay* overlay = SohImGui::overlay; GameOverlay* overlay = SohImGui::GetGameOverlay();
if (args[1] == "add") { if (args[1] == "add") {
if (!overlay->RegisteredOverlays.contains(key)) { if (!overlay->RegisteredOverlays.contains(key)) {
overlay->RegisteredOverlays[key] = new Overlay({ OverlayType::TEXT, ImStrdup(key), -1.0f }); overlay->RegisteredOverlays[key] = new Overlay({ OverlayType::TEXT, ImStrdup(key), -1.0f });
SohImGui::console->SendInfoMessage("Added overlay: %s", key); SohImGui::GetConsole()->SendInfoMessage("Added overlay: %s", key);
} }
else { else {
SohImGui::console->SendErrorMessage("Overlay already exists: %s", key); SohImGui::GetConsole()->SendErrorMessage("Overlay already exists: %s", key);
} }
} }
else if (args[1] == "remove") { else if (args[1] == "remove") {
if (overlay->RegisteredOverlays.contains(key)) { if (overlay->RegisteredOverlays.contains(key)) {
overlay->RegisteredOverlays.erase(key); overlay->RegisteredOverlays.erase(key);
SohImGui::console->SendInfoMessage("Removed overlay: %s", key); SohImGui::GetConsole()->SendInfoMessage("Removed overlay: %s", key);
} }
else { else {
SohImGui::console->SendErrorMessage("Overlay not found: %s", key); SohImGui::GetConsole()->SendErrorMessage("Overlay not found: %s", key);
} }
} }
} }
else { else {
SohImGui::console->SendErrorMessage("CVar {} does not exist", args[2].c_str()); SohImGui::GetConsole()->SendErrorMessage("CVar {} does not exist", args[2].c_str());
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -124,7 +124,7 @@ namespace Ship {
else else
text_display_end = text_end; text_display_end = text_end;
GameOverlay* overlay = SohImGui::overlay; GameOverlay* overlay = SohImGui::GetGameOverlay();
ImFont* font = overlay->CurrentFont == "Default" ? g.Font : overlay->Fonts[overlay->CurrentFont]; ImFont* font = overlay->CurrentFont == "Default" ? g.Font : overlay->Fonts[overlay->CurrentFont];
const float font_size = font->FontSize; const float font_size = font->FontSize;
@ -157,7 +157,7 @@ namespace Ship {
} }
} }
SohImGui::console->AddCommand("overlay", { OverlayCommand, "Draw an overlay using a cvar value" }); SohImGui::GetConsole()->AddCommand("overlay", { OverlayCommand, "Draw an overlay using a cvar value" });
} }
void GameOverlay::DrawSettings() { void GameOverlay::DrawSettings() {
@ -167,7 +167,7 @@ namespace Ship {
if (ImGui::Selectable(name.c_str(), name == this->CurrentFont)) { if (ImGui::Selectable(name.c_str(), name == this->CurrentFont)) {
this->CurrentFont = name; this->CurrentFont = name;
CVar_SetString("gOverlayFont", ImStrdup(name.c_str())); CVar_SetString("gOverlayFont", ImStrdup(name.c_str()));
SohImGui::needs_save = true; SohImGui::RequestCvarSaveOnNextTick();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,5 @@
#pragma once #pragma once
#ifdef __cplusplus
extern "C" {
#endif
void enableBetaQuest();
void disableBetaQuest();
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
#include "GameOverlay.h" #include "GameOverlay.h"
#include "Lib/ImGui/imgui.h" #include "Lib/ImGui/imgui.h"
@ -34,14 +25,6 @@ namespace SohImGui {
dLoadSettings, dLoadSettings,
}; };
// Enumeration for disabled checkbox graphics
enum class ImGuiCheckboxGraphics
{
Cross,
Checkmark,
None
};
typedef struct { typedef struct {
Backend backend; Backend backend;
union { union {
@ -76,8 +59,6 @@ namespace SohImGui {
} gx2; } gx2;
} EventImpl; } EventImpl;
extern WindowImpl impl;
using WindowDrawFunc = void(*)(bool& enabled); using WindowDrawFunc = void(*)(bool& enabled);
typedef struct { typedef struct {
@ -85,55 +66,49 @@ namespace SohImGui {
WindowDrawFunc drawFunc; WindowDrawFunc drawFunc;
} CustomWindow; } CustomWindow;
extern std::shared_ptr<Ship::Console> console;
extern Ship::InputEditor* controller;
extern Ship::GameOverlay* overlay;
extern bool needs_save;
void Init(WindowImpl window_impl); void Init(WindowImpl window_impl);
void Update(EventImpl event); void Update(EventImpl event);
void Tooltip(const char* text);
void EnhancementRadioButton(const char* text, const char* cvarName, int id);
void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", ImGuiCheckboxGraphics disabledGraphic = ImGuiCheckboxGraphics::Cross);
void EnhancementButton(const char* text, const char* cvarName);
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false);
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false);
void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue);
void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false);
void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector<std::string>& items, int defaultValue = 0);
void applyEnhancementPresets(void);
void applyEnhancementPresetDefault(void);
void applyEnhancementPresetVanillaPlus(void);
void applyEnhancementPresetEnhanced(void);
void applyEnhancementPresetRandomizer(void);
void DrawMainMenuAndCalculateGameSize(void); void DrawMainMenuAndCalculateGameSize(void);
void RegisterMenuDrawMethod(std::function<void(void)> drawMethod);
void AddSetupHooksDelegate(std::function<void(void)> setupHooksMethod);
void DrawFramebufferAndGameInput(void); void DrawFramebufferAndGameInput(void);
void Render(void); void Render(void);
void CancelFrame(void); void CancelFrame(void);
void ShowCursor(bool hide, Dialogues w); void DrawSettings();
void BindCmd(const std::string& cmd, Ship::CommandEntry entry);
void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc, bool isEnabled=false, bool isHidden=false); Backend WindowBackend();
void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint = ImVec4(1, 1, 1, 1)); float WindowRefreshRate();
void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha=false); std::pair<const char*, const char*>* GetAvailableRenderingBackends();
int ClampFloatToInt(float value, int min, int max); std::pair<const char*, const char*> GetCurrentRenderingBackend();
void RandomizeColor(const char* cvarName, ImVec4* colors); void SetCurrentRenderingBackend(uint8_t index, std::pair<const char*, const char*>);
void RainbowColor(const char* cvarName, ImVec4* colors); const char** GetSupportedTextureFilters();
void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha); void SetResolutionMultiplier(float multiplier);
void SetMSAALevel(uint32_t value);
void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc, bool isEnabled = false, bool isHidden = false);
void EnableWindow(const std::string& name, bool isEnabled = true);
Ship::GameOverlay* GetGameOverlay();
Ship::InputEditor* GetInputEditor();
void ToggleInputEditorWindow(bool isOpen = true);
void ToggleStatisticsWindow(bool isOpen = true);
std::shared_ptr<Ship::Console> GetConsole();
void ToggleConsoleWindow(bool isOpen = true);
void DispatchConsoleCommand(const std::string& line);
void RequestCvarSaveOnNextTick();
ImTextureID GetTextureByID(int id); ImTextureID GetTextureByID(int id);
ImTextureID GetTextureByName(const std::string& name); ImTextureID GetTextureByName(const std::string& name);
void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint = ImVec4(1, 1, 1, 1));
void ShowCursor(bool hide, Dialogues w);
void BeginGroupPanel(const char* name, const ImVec2 & size = ImVec2(0.0f, 0.0f)); void BeginGroupPanel(const char* name, const ImVec2 & size = ImVec2(0.0f, 0.0f));
void EndGroupPanel(float minHeight = 0.0f); void EndGroupPanel(float minHeight = 0.0f);
std::string BreakTooltip(const char* text, int lineLength = 60);
std::string BreakTooltip(const std::string& text, int lineLength = 60);
void InsertPadding(float extraVerticalPadding = 0.0f);
void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f);
void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true);
void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", ImGuiCheckboxGraphics disabledGraphic = ImGuiCheckboxGraphics::Cross);
void PaddedText(const char* text, bool padTop = true, bool padBottom = true);
std::string GetWindowButtonText(const char* text, bool menuOpen);
} }
#endif #endif

View File

@ -2134,6 +2134,10 @@ static void gfx_run_dl(Gfx* cmd) {
switch (opcode) { switch (opcode) {
// RSP commands: // RSP commands:
case G_LOAD_UCODE:
rsp.fog_mul = 0;
rsp.fog_offset = 0;
break;
case G_MARKER: case G_MARKER:
{ {
cmd++; cmd++;

View File

@ -41,8 +41,8 @@ protected:
} }
formatted.push_back('\0'); formatted.push_back('\0');
const char* msg_output = formatted.data(); const char* msg_output = formatted.data();
if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::console->IsOpened()) { if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::GetConsole()->IsOpened()) {
SohImGui::console->Append("Logs", msg.level, "%s", msg_output); SohImGui::GetConsole()->Append("Logs", msg.level, "%s", msg_output);
} }
} }

View File

@ -86,7 +86,7 @@ extern "C" {
pad->gyro_x = 0; pad->gyro_x = 0;
pad->gyro_y = 0; pad->gyro_y = 0;
if (SohImGui::controller->IsOpened()) return; if (SohImGui::GetInputEditor()->IsOpened()) return;
Ship::Window::GetInstance()->GetControlDeck()->WriteToPad(pad); Ship::Window::GetInstance()->GetControlDeck()->WriteToPad(pad);
Ship::ExecuteHooks<Ship::ControllerRead>(pad); Ship::ExecuteHooks<Ship::ControllerRead>(pad);

View File

@ -165,6 +165,7 @@ set(Header_Files__soh__Enhancements__controls
) )
source_group("Header Files\\soh\\Enhancements\\controls" FILES ${Header_Files__soh__Enhancements__controls}) source_group("Header Files\\soh\\Enhancements\\controls" FILES ${Header_Files__soh__Enhancements__controls})
set(Header_Files__soh__Enhancements__cosmetics set(Header_Files__soh__Enhancements__cosmetics
"soh/Enhancements/cosmetics/CosmeticsEditor.h" "soh/Enhancements/cosmetics/CosmeticsEditor.h"
) )
@ -175,7 +176,6 @@ set(Header_Files__soh__Enhancements__debugger
"soh/Enhancements/debugger/colViewer.h" "soh/Enhancements/debugger/colViewer.h"
"soh/Enhancements/debugger/debugger.h" "soh/Enhancements/debugger/debugger.h"
"soh/Enhancements/debugger/debugSaveEditor.h" "soh/Enhancements/debugger/debugSaveEditor.h"
"soh/Enhancements/debugger/ImGuiHelpers.h"
) )
source_group("Header Files\\soh\\Enhancements\\debugger" FILES ${Header_Files__soh__Enhancements__debugger}) source_group("Header Files\\soh\\Enhancements\\debugger" FILES ${Header_Files__soh__Enhancements__debugger})
@ -258,6 +258,10 @@ set(Source_Files__soh
"soh/z_message_OTR.cpp" "soh/z_message_OTR.cpp"
"soh/z_play_otr.cpp" "soh/z_play_otr.cpp"
"soh/z_scene_otr.cpp" "soh/z_scene_otr.cpp"
"soh/GameMenuBar.hpp"
"soh/GameMenuBar.cpp"
"soh/UIWidgets.hpp"
"soh/UIWidgets.cpp"
) )
source_group("Source Files\\soh" FILES ${Source_Files__soh}) source_group("Source Files\\soh" FILES ${Source_Files__soh})
@ -284,7 +288,6 @@ set(Source_Files__soh__Enhancements__debugger
"soh/Enhancements/debugger/colViewer.cpp" "soh/Enhancements/debugger/colViewer.cpp"
"soh/Enhancements/debugger/debugger.cpp" "soh/Enhancements/debugger/debugger.cpp"
"soh/Enhancements/debugger/debugSaveEditor.cpp" "soh/Enhancements/debugger/debugSaveEditor.cpp"
"soh/Enhancements/debugger/ImGuiHelpers.cpp"
) )
source_group("Source Files\\soh\\Enhancements\\debugger" FILES ${Source_Files__soh__Enhancements__debugger}) source_group("Source Files\\soh\\Enhancements\\debugger" FILES ${Source_Files__soh__Enhancements__debugger})
@ -1679,14 +1682,13 @@ set(SDL2-INCLUDE ${SDL2_INCLUDE_DIRS})
target_include_directories(${PROJECT_NAME} PRIVATE assets target_include_directories(${PROJECT_NAME} PRIVATE assets
${CMAKE_CURRENT_SOURCE_DIR}/include/ ${CMAKE_CURRENT_SOURCE_DIR}/include/
${CMAKE_CURRENT_SOURCE_DIR}/src/ ${CMAKE_CURRENT_SOURCE_DIR}/src/
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/libjpeg/include/ ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/libjpeg/include/
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/spdlog/include/ ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/spdlog/include/
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/Fast3D/U64/PR
${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPDUtils ${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPDUtils
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/Fast3D/U64
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/Fast3D/U64/PR
${SDL2-INCLUDE} ${SDL2-INCLUDE}
${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/
${CMAKE_CURRENT_SOURCE_DIR}/assets/ ${CMAKE_CURRENT_SOURCE_DIR}/assets/
. .
) )

View File

@ -6,7 +6,7 @@
#include "macros.h" #include "macros.h"
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "soh/Enhancements/gameconsole.h" #include "soh/Enhancements/gameconsole.h"
#include "Cvar.h" #include <libultraship/Cvar.h>

View File

@ -1,7 +1,7 @@
#ifndef MACROS_H #ifndef MACROS_H
#define MACROS_H #define MACROS_H
#include "endianness.h" #include <libultraship/endianness.h>
#define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0])) #define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0]))
#define ARRAY_COUNTU(arr) (u32)(sizeof(arr) / sizeof(arr[0])) #define ARRAY_COUNTU(arr) (u32)(sizeof(arr) / sizeof(arr[0]))

View File

@ -26,7 +26,7 @@
#include "z64interface.h" #include "z64interface.h"
#include "sequence.h" #include "sequence.h"
#include "sfx.h" #include "sfx.h"
#include "color.h" #include <libultraship/color.h>
#include "ichain.h" #include "ichain.h"
#include "regs.h" #include "regs.h"

View File

@ -1,7 +1,7 @@
#ifndef Z64_AUDIO_H #ifndef Z64_AUDIO_H
#define Z64_AUDIO_H #define Z64_AUDIO_H
#include "endianness.h" #include <libultraship/endianness.h>
#define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0)) #define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0))
@ -815,7 +815,7 @@ typedef struct {
/* 0x0E */ u8 ttl; // duration after which the DMA can be discarded /* 0x0E */ u8 ttl; // duration after which the DMA can be discarded
} SampleDma; // size = 0x10 } SampleDma; // size = 0x10
#include <PR/ultra64/abi.h> #include <ultra64/abi.h>
typedef struct { typedef struct {
/* 0x0000 */ char unk_0000; /* 0x0000 */ char unk_0000;

View File

@ -1,7 +1,7 @@
#ifndef Z64EFFECT_H #ifndef Z64EFFECT_H
#define Z64EFFECT_H #define Z64EFFECT_H
#include "color.h" #include <libultraship/color.h>
struct GraphicsContext; struct GraphicsContext;
struct GlobalContext; struct GlobalContext;

View File

@ -4,7 +4,7 @@
#include "ultra64.h" #include "ultra64.h"
#include "ultra64/gbi.h" #include "ultra64/gbi.h"
#include "z64math.h" #include "z64math.h"
#include "color.h" #include <libultraship/color.h>
typedef struct { typedef struct {
/* 0x0 */ s16 x; /* 0x0 */ s16 x;

View File

@ -2,7 +2,7 @@
#define Z64TRANSITION_H #define Z64TRANSITION_H
#include "ultra64.h" #include "ultra64.h"
#include "color.h" #include <libultraship/color.h>
typedef struct { typedef struct {
f32 unk_0; f32 unk_0;

View File

@ -6,12 +6,14 @@
#include <utility> #include <utility>
#include <iterator> #include <iterator>
#include "Lib/ImGui/imgui.h" #include <ImGui/imgui.h>
#include "Lib/ImGui/imgui_internal.h" #include <ImGui/imgui_internal.h>
#include "Cvar.h" #include <libultraship/Cvar.h>
#include "UltraController.h" #include <libultraship/UltraController.h>
#include "Utils/StringHelper.h" #include <Utils/StringHelper.h>
#include "../libultraship/ImGuiImpl.h" #include <libultraship/ImGuiImpl.h>
#include "../../UIWidgets.hpp"
namespace GameControlEditor { namespace GameControlEditor {
const ImGuiTableFlags PANEL_TABLE_FLAGS = const ImGuiTableFlags PANEL_TABLE_FLAGS =
@ -50,7 +52,11 @@ namespace GameControlEditor {
// place the ? button to the most of the right side of the cell it is using. // place the ? button to the most of the right side of the cell it is using.
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 15); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 15);
ImGui::SmallButton("?"); ImGui::SmallButton("?");
SohImGui::Tooltip(helptext.c_str());
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", helptext.c_str());
}
if (sameline) { if (sameline) {
//I do not use ImGui::SameLine(); because it make some element vanish. //I do not use ImGui::SameLine(); because it make some element vanish.
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 22); ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 22);
@ -119,7 +125,7 @@ namespace GameControlEditor {
preview = "Unknown"; preview = "Unknown";
} }
SohImGui::InsertPadding(); UIWidgets::Spacer(0);
ImVec2 cursorPos = ImGui::GetCursorPos(); ImVec2 cursorPos = ImGui::GetCursorPos();
ImVec2 textSize = ImGui::CalcTextSize(mapping.label); ImVec2 textSize = ImGui::CalcTextSize(mapping.label);
ImGui::SetCursorPosY(cursorPos.y + textSize.y / 4); ImGui::SetCursorPosY(cursorPos.y + textSize.y / 4);
@ -140,7 +146,7 @@ namespace GameControlEditor {
} }
ImGui::EndCombo(); ImGui::EndCombo();
} }
SohImGui::InsertPadding(); UIWidgets::Spacer(0);
} }
void DrawOcarinaControlPanel() { void DrawOcarinaControlPanel() {
@ -157,7 +163,7 @@ namespace GameControlEditor {
ImVec2 cursor = ImGui::GetCursorPos(); ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
SohImGui::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls"); UIWidgets::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls");
if (CVar_GetS32("gCustomOcarinaControls", 0) == 1) { if (CVar_GetS32("gCustomOcarinaControls", 0) == 1) {
if (ImGui::BeginTable("tableCustomMainOcarinaControls", 2, ImGuiTableFlags_SizingStretchProp)) { if (ImGui::BeginTable("tableCustomMainOcarinaControls", 2, ImGuiTableFlags_SizingStretchProp)) {
@ -194,10 +200,10 @@ namespace GameControlEditor {
ImGui::EndTable(); ImGui::EndTable();
} }
} else { } else {
SohImGui::InsertPadding(); UIWidgets::Spacer(0);
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextWrapped("To modify the main ocarina controls, select the \"Customize Ocarina Controls\" checkbox."); ImGui::TextWrapped("To modify the main ocarina controls, select the \"Customize Ocarina Controls\" checkbox.");
SohImGui::InsertPadding(); UIWidgets::Spacer(0);
} }
SohImGui::BeginGroupPanel("Alternate controls", ImGui::GetContentRegionAvail()); SohImGui::BeginGroupPanel("Alternate controls", ImGui::GetContentRegionAvail());
@ -206,9 +212,9 @@ namespace GameControlEditor {
ImGui::TableSetupColumn("Right stick", PANEL_TABLE_COLUMN_FLAGS); ImGui::TableSetupColumn("Right stick", PANEL_TABLE_COLUMN_FLAGS);
TableHelper::InitHeader(false); TableHelper::InitHeader(false);
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
SohImGui::EnhancementCheckbox("Play with D-pad", "gDpadOcarina"); UIWidgets::EnhancementCheckbox("Play with D-pad", "gDpadOcarina");
TableHelper::NextCol(); TableHelper::NextCol();
SohImGui::EnhancementCheckbox("Play with camera stick", "gRStickOcarina"); UIWidgets::EnhancementCheckbox("Play with camera stick", "gRStickOcarina");
ImGui::EndTable(); ImGui::EndTable();
} }
SohImGui::EndGroupPanel(); SohImGui::EndGroupPanel();
@ -223,17 +229,17 @@ namespace GameControlEditor {
ImVec2 cursor = ImGui::GetCursorPos(); ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
SohImGui::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis"); UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis");
SohImGui::Tooltip("Inverts the Camera X Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming"); UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
SohImGui::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis"); UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis");
SohImGui::Tooltip("Inverts the Camera Y Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming"); UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
SohImGui::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming"); UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming");
SohImGui::Tooltip("Allows for aiming with the rights stick when:\n-Aiming in the C-Up view\n-Aiming with weapons"); UIWidgets::Tooltip("Allows for aiming with the rights stick when:\n-Aiming in the C-Up view\n-Aiming with weapons");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
SohImGui::PaddedEnhancementCheckbox("Auto-Center First Person View", "gAutoCenterView"); UIWidgets::PaddedEnhancementCheckbox("Auto-Center First Person View", "gAutoCenterView");
SohImGui::Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"); UIWidgets::Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming");
} }
void DrawUI(bool& open) { void DrawUI(bool& open) {

View File

@ -1,11 +1,13 @@
#include "CosmeticsEditor.h" #include "CosmeticsEditor.h"
#include "../libultraship/ImGuiImpl.h" #include <libultraship/ImGuiImpl.h>
#include <string> #include <string>
#include <Cvar.h> #include <libultraship/Cvar.h>
#include <random> #include <random>
#include <algorithm> #include <algorithm>
#include <PR/ultra64/types.h> #include <ultra64/types.h>
#include "../../UIWidgets.hpp"
const char* RainbowColorCvarList[] = { const char* RainbowColorCvarList[] = {
//This is the list of possible CVars that has rainbow effect. //This is the list of possible CVars that has rainbow effect.
@ -51,9 +53,9 @@ void GetRandomColorRGB(CosmeticsColorSection* ColorSection, int SectionSize){
std::string cvarName = Element->CvarName; std::string cvarName = Element->CvarName;
std::string Cvar_RBM = cvarName + "RBM"; std::string Cvar_RBM = cvarName + "RBM";
colors = RANDOMIZE_32(255); colors = RANDOMIZE_32(255);
NewColors.r = SohImGui::ClampFloatToInt(colors.x * 255, 0, 255); NewColors.r = fmin(fmax(colors.x * 255, 0), 255);
NewColors.g = SohImGui::ClampFloatToInt(colors.y * 255, 0, 255); NewColors.g = fmin(fmax(colors.y * 255, 0), 255);
NewColors.b = SohImGui::ClampFloatToInt(colors.z * 255, 0, 255); NewColors.b = fmin(fmax(colors.z * 255, 0), 255);
Element->ModifiedColor = colors; Element->ModifiedColor = colors;
CVar_SetRGBA(cvarName.c_str(), NewColors); CVar_SetRGBA(cvarName.c_str(), NewColors);
CVar_SetS32(Cvar_RBM.c_str(), 0); CVar_SetS32(Cvar_RBM.c_str(), 0);
@ -149,9 +151,9 @@ void LoadRainbowColor(bool& open) {
case 6: NewColor.x = 255; NewColor.y = 0; NewColor.z = a; break; case 6: NewColor.x = 255; NewColor.y = 0; NewColor.z = a; break;
} }
Color_RGBA8 NewColorRGB = { Color_RGBA8 NewColorRGB = {
SohImGui::ClampFloatToInt(NewColor.x, 0, 255), fmin(fmax(NewColor.x, 0), 255),
SohImGui::ClampFloatToInt(NewColor.y, 0, 255), fmin(fmax(NewColor.y, 0), 255),
SohImGui::ClampFloatToInt(NewColor.z, 0, 255), fmin(fmax(NewColor.z, 0), 255),
255 255
}; };
if (CVar_GetS32(Cvar_RBM.c_str(), 0) != 0) { if (CVar_GetS32(Cvar_RBM.c_str(), 0) != 0) {
@ -187,7 +189,7 @@ void Draw_HelpIcon(const std::string& helptext, bool sameline = true, int Pos =
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x-60); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x-60);
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 15); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 15);
ImGui::SmallButton("?"); ImGui::SmallButton("?");
SohImGui::Tooltip(helptext.c_str()); UIWidgets::Tooltip(helptext.c_str());
if (sameline) { if (sameline) {
//I do not use ImGui::SameLine(); because it make some element vanish. //I do not use ImGui::SameLine(); because it make some element vanish.
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 22); ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 22);
@ -197,96 +199,96 @@ void Draw_HelpIcon(const std::string& helptext, bool sameline = true, int Pos =
void DrawUseMarginsSlider(const std::string ElementName, const std::string CvarName){ void DrawUseMarginsSlider(const std::string ElementName, const std::string CvarName){
std::string CvarLabel = CvarName + "UseMargins"; std::string CvarLabel = CvarName + "UseMargins";
std::string Label = ElementName + " use margins"; std::string Label = ElementName + " use margins";
SohImGui::EnhancementCheckbox(Label.c_str(), CvarLabel.c_str()); UIWidgets::EnhancementCheckbox(Label.c_str(), CvarLabel.c_str());
SohImGui::Tooltip("Using this allow you move the element with General margins sliders"); UIWidgets::Tooltip("Using this allow you move the element with General margins sliders");
} }
void DrawPositionsRadioBoxes(const std::string CvarName, bool NoAnchorEnabled = true){ void DrawPositionsRadioBoxes(const std::string CvarName, bool NoAnchorEnabled = true){
std::string CvarLabel = CvarName + "PosType"; std::string CvarLabel = CvarName + "PosType";
SohImGui::EnhancementRadioButton("Original position", CvarLabel.c_str(), 0); UIWidgets::EnhancementRadioButton("Original position", CvarLabel.c_str(), 0);
SohImGui::Tooltip("This will use original intended elements position"); UIWidgets::Tooltip("This will use original intended elements position");
SohImGui::EnhancementRadioButton("Anchor to the left", CvarLabel.c_str(), 1); UIWidgets::EnhancementRadioButton("Anchor to the left", CvarLabel.c_str(), 1);
SohImGui::Tooltip("This will make your elements follow the left side of your game window"); UIWidgets::Tooltip("This will make your elements follow the left side of your game window");
SohImGui::EnhancementRadioButton("Anchor to the right", CvarLabel.c_str(), 2); UIWidgets::EnhancementRadioButton("Anchor to the right", CvarLabel.c_str(), 2);
SohImGui::Tooltip("This will make your elements follow the right side of your game window"); UIWidgets::Tooltip("This will make your elements follow the right side of your game window");
if (NoAnchorEnabled) { if (NoAnchorEnabled) {
SohImGui::EnhancementRadioButton("No anchors", CvarLabel.c_str(), 3); UIWidgets::EnhancementRadioButton("No anchors", CvarLabel.c_str(), 3);
SohImGui::Tooltip("This will make your elements to not follow any side\nBetter used for center elements"); UIWidgets::Tooltip("This will make your elements to not follow any side\nBetter used for center elements");
} }
SohImGui::EnhancementRadioButton("Hidden", CvarLabel.c_str(), 4); UIWidgets::EnhancementRadioButton("Hidden", CvarLabel.c_str(), 4);
SohImGui::Tooltip("This will make your elements hidden"); UIWidgets::Tooltip("This will make your elements hidden");
} }
void DrawTransitions(const std::string CvarName){ void DrawTransitions(const std::string CvarName){
SohImGui::EnhancementRadioButton("Really slow fade (white)", CvarName.c_str(), 8); UIWidgets::EnhancementRadioButton("Really slow fade (white)", CvarName.c_str(), 8);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Really slow fade (black)", CvarName.c_str(), 7); UIWidgets::EnhancementRadioButton("Really slow fade (black)", CvarName.c_str(), 7);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Slow fade (white)", CvarName.c_str(), 10); UIWidgets::EnhancementRadioButton("Slow fade (white)", CvarName.c_str(), 10);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Slow fade (black)", CvarName.c_str(), 9); UIWidgets::EnhancementRadioButton("Slow fade (black)", CvarName.c_str(), 9);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Normal fade (white)", CvarName.c_str(), 3); UIWidgets::EnhancementRadioButton("Normal fade (white)", CvarName.c_str(), 3);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Normal fade (black)", CvarName.c_str(), 2); UIWidgets::EnhancementRadioButton("Normal fade (black)", CvarName.c_str(), 2);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Fast fade (white)", CvarName.c_str(), 5); UIWidgets::EnhancementRadioButton("Fast fade (white)", CvarName.c_str(), 5);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Fast fade (black)", CvarName.c_str(), 4); UIWidgets::EnhancementRadioButton("Fast fade (black)", CvarName.c_str(), 4);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Fast circle (white)", CvarName.c_str(), 40); UIWidgets::EnhancementRadioButton("Fast circle (white)", CvarName.c_str(), 40);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Normal circle (black)", CvarName.c_str(), 32); UIWidgets::EnhancementRadioButton("Normal circle (black)", CvarName.c_str(), 32);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Slow circle (white)", CvarName.c_str(), 41); UIWidgets::EnhancementRadioButton("Slow circle (white)", CvarName.c_str(), 41);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Slow circle (black)", CvarName.c_str(), 33); UIWidgets::EnhancementRadioButton("Slow circle (black)", CvarName.c_str(), 33);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Fast noise circle (white)", CvarName.c_str(), 42); UIWidgets::EnhancementRadioButton("Fast noise circle (white)", CvarName.c_str(), 42);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Fast noise circle (black)", CvarName.c_str(), 34); UIWidgets::EnhancementRadioButton("Fast noise circle (black)", CvarName.c_str(), 34);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Slow noise circle (white)", CvarName.c_str(), 43); UIWidgets::EnhancementRadioButton("Slow noise circle (white)", CvarName.c_str(), 43);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Slow noise circle (black)", CvarName.c_str(), 35); UIWidgets::EnhancementRadioButton("Slow noise circle (black)", CvarName.c_str(), 35);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Normal waves circle (white)", CvarName.c_str(), 44); UIWidgets::EnhancementRadioButton("Normal waves circle (white)", CvarName.c_str(), 44);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Normal waves circle (black)", CvarName.c_str(), 36); UIWidgets::EnhancementRadioButton("Normal waves circle (black)", CvarName.c_str(), 36);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Slow waves circle (white)", CvarName.c_str(), 45); UIWidgets::EnhancementRadioButton("Slow waves circle (white)", CvarName.c_str(), 45);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Slow waves circle (black)", CvarName.c_str(), 37); UIWidgets::EnhancementRadioButton("Slow waves circle (black)", CvarName.c_str(), 37);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Normal close circle (white)", CvarName.c_str(), 46); UIWidgets::EnhancementRadioButton("Normal close circle (white)", CvarName.c_str(), 46);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Normal close circle (black)", CvarName.c_str(), 38); UIWidgets::EnhancementRadioButton("Normal close circle (black)", CvarName.c_str(), 38);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Slow close circle (white)", CvarName.c_str(), 47); UIWidgets::EnhancementRadioButton("Slow close circle (white)", CvarName.c_str(), 47);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Slow close circle (black)", CvarName.c_str(), 39); UIWidgets::EnhancementRadioButton("Slow close circle (black)", CvarName.c_str(), 39);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Super fast circle (white)", CvarName.c_str(), 56); UIWidgets::EnhancementRadioButton("Super fast circle (white)", CvarName.c_str(), 56);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Super fast circle (black)", CvarName.c_str(), 58); UIWidgets::EnhancementRadioButton("Super fast circle (black)", CvarName.c_str(), 58);
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Super fast noise circle (white)", CvarName.c_str(), 57); UIWidgets::EnhancementRadioButton("Super fast noise circle (white)", CvarName.c_str(), 57);
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Super fast noise circle (black)", CvarName.c_str(), 59); UIWidgets::EnhancementRadioButton("Super fast noise circle (black)", CvarName.c_str(), 59);
} }
void DrawPositionSlider(const std::string CvarName, int MinY, int MaxY, int MinX, int MaxX){ void DrawPositionSlider(const std::string CvarName, int MinY, int MaxY, int MinX, int MaxX){
std::string PosXCvar = CvarName+"PosX"; std::string PosXCvar = CvarName+"PosX";
std::string PosYCvar = CvarName+"PosY"; std::string PosYCvar = CvarName+"PosY";
std::string InvisibleLabelX = "##"+PosXCvar; std::string InvisibleLabelX = "##"+PosXCvar;
std::string InvisibleLabelY = "##"+PosYCvar; std::string InvisibleLabelY = "##"+PosYCvar;
SohImGui::EnhancementSliderInt("Up <-> Down : %d", InvisibleLabelY.c_str(), PosYCvar.c_str(), MinY, MaxY, "", 0, true); UIWidgets::EnhancementSliderInt("Up <-> Down : %d", InvisibleLabelY.c_str(), PosYCvar.c_str(), MinY, MaxY, "", 0, true);
SohImGui::Tooltip("This slider is used to move Up and Down your elements."); UIWidgets::Tooltip("This slider is used to move Up and Down your elements.");
SohImGui::EnhancementSliderInt("Left <-> Right : %d", InvisibleLabelX.c_str(), PosXCvar.c_str(), MinX, MaxX, "", 0, true); UIWidgets::EnhancementSliderInt("Left <-> Right : %d", InvisibleLabelX.c_str(), PosXCvar.c_str(), MinX, MaxX, "", 0, true);
SohImGui::Tooltip("This slider is used to move Left and Right your elements."); UIWidgets::Tooltip("This slider is used to move Left and Right your elements.");
} }
void DrawScaleSlider(const std::string CvarName,float DefaultValue){ void DrawScaleSlider(const std::string CvarName,float DefaultValue){
std::string InvisibleLabel = "##"+CvarName; std::string InvisibleLabel = "##"+CvarName;
std::string CvarLabel = CvarName+"Scale"; std::string CvarLabel = CvarName+"Scale";
//Disabled for now. feature not done and several fixes needed to be merged. //Disabled for now. feature not done and several fixes needed to be merged.
//SohImGui::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true,true); //UIWidgets::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true,true);
} }
void DrawColorSection(CosmeticsColorSection* ColorSection, int SectionSize) { void DrawColorSection(CosmeticsColorSection* ColorSection, int SectionSize) {
for (s16 i = 0; i < SectionSize; i++) { for (s16 i = 0; i < SectionSize; i++) {
@ -308,7 +310,7 @@ void DrawColorSection(CosmeticsColorSection* ColorSection, int SectionSize) {
Table_NextLine(); Table_NextLine();
} }
Draw_HelpIcon(Tooltip.c_str()); Draw_HelpIcon(Tooltip.c_str());
SohImGui::EnhancementColor(Name.c_str(), Cvar.c_str(), ModifiedColor, DefaultColor, canRainbow, hasAlpha, sameLine); UIWidgets::EnhancementColor(Name.c_str(), Cvar.c_str(), ModifiedColor, DefaultColor, canRainbow, hasAlpha, sameLine);
} }
} }
void DrawRandomizeResetButton(const std::string Identifier, CosmeticsColorSection* ColorSection, int SectionSize, bool isAllCosmetics = false){ void DrawRandomizeResetButton(const std::string Identifier, CosmeticsColorSection* ColorSection, int SectionSize, bool isAllCosmetics = false){
@ -335,21 +337,21 @@ void DrawRandomizeResetButton(const std::string Identifier, CosmeticsColorSectio
CVar_SetS32("gCCparated", 1); CVar_SetS32("gCCparated", 1);
GetRandomColorRGB(ColorSection, SectionSize); GetRandomColorRGB(ColorSection, SectionSize);
} }
SohImGui::Tooltip(Tooltip_RNG.c_str()); UIWidgets::Tooltip(Tooltip_RNG.c_str());
Table_NextCol(); Table_NextCol();
if(ImGui::Button(Reset_BtnText.c_str(), ImVec2( ImGui::GetContentRegionAvail().x, 20.0f))){ if(ImGui::Button(Reset_BtnText.c_str(), ImVec2( ImGui::GetContentRegionAvail().x, 20.0f))){
GetDefaultColorRGB(ColorSection, SectionSize); GetDefaultColorRGB(ColorSection, SectionSize);
} }
SohImGui::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics."); UIWidgets::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics.");
SohImGui::Tooltip(Tooltip_RNG.c_str()); UIWidgets::Tooltip(Tooltip_RNG.c_str());
ImGui::EndTable(); ImGui::EndTable();
} }
} }
void Draw_Npcs(){ void Draw_Npcs(){
DrawRandomizeResetButton("all NPCs", NPCs_section, SECTION_SIZE(NPCs_section)); DrawRandomizeResetButton("all NPCs", NPCs_section, SECTION_SIZE(NPCs_section));
SohImGui::EnhancementCheckbox("Custom colors for Navi", "gUseNaviCol"); UIWidgets::EnhancementCheckbox("Custom colors for Navi", "gUseNaviCol");
SohImGui::Tooltip("Enable/Disable custom Navi colors\nIf disabled, default colors will be used\nColors go into effect when Navi goes back into your pockets"); UIWidgets::Tooltip("Enable/Disable custom Navi colors\nIf disabled, default colors will be used\nColors go into effect when Navi goes back into your pockets");
if (CVar_GetS32("gUseNaviCol",0)) { if (CVar_GetS32("gUseNaviCol",0)) {
DrawRandomizeResetButton("Navi's", Navi_Section, SECTION_SIZE(Navi_Section)); DrawRandomizeResetButton("Navi's", Navi_Section, SECTION_SIZE(Navi_Section));
}; };
@ -360,8 +362,8 @@ void Draw_Npcs(){
DrawColorSection(Navi_Section, SECTION_SIZE(Navi_Section)); DrawColorSection(Navi_Section, SECTION_SIZE(Navi_Section));
ImGui::EndTable(); ImGui::EndTable();
} }
SohImGui::EnhancementCheckbox("Custom colors for Keese", "gUseKeeseCol"); UIWidgets::EnhancementCheckbox("Custom colors for Keese", "gUseKeeseCol");
SohImGui::Tooltip("Enable/Disable custom Keese element colors\nIf disabled, default element colors will be used\nColors go into effect when Keese respawn (or when the room is reloaded)"); UIWidgets::Tooltip("Enable/Disable custom Keese element colors\nIf disabled, default element colors will be used\nColors go into effect when Keese respawn (or when the room is reloaded)");
if (CVar_GetS32("gUseKeeseCol",0) && ImGui::BeginTable("tableKeese", 2, FlagsTable)) { if (CVar_GetS32("gUseKeeseCol",0) && ImGui::BeginTable("tableKeese", 2, FlagsTable)) {
ImGui::TableSetupColumn("Fire colors##Keese", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("Fire colors##Keese", FlagsCell, TablesCellsWidth/2);
ImGui::TableSetupColumn("Ice colors##Keese", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("Ice colors##Keese", FlagsCell, TablesCellsWidth/2);
@ -369,8 +371,8 @@ void Draw_Npcs(){
DrawColorSection(Keese_Section, SECTION_SIZE(Keese_Section)); DrawColorSection(Keese_Section, SECTION_SIZE(Keese_Section));
ImGui::EndTable(); ImGui::EndTable();
} }
SohImGui::EnhancementCheckbox("Custom colors for Dogs", "gUseDogsCol"); UIWidgets::EnhancementCheckbox("Custom colors for Dogs", "gUseDogsCol");
SohImGui::Tooltip("Enable/Disable custom colors for the two Dog variants\nIf disabled, default colors will be used"); UIWidgets::Tooltip("Enable/Disable custom colors for the two Dog variants\nIf disabled, default colors will be used");
if (CVar_GetS32("gUseDogsCol",0) && ImGui::BeginTable("tableDogs", 2, FlagsTable)) { if (CVar_GetS32("gUseDogsCol",0) && ImGui::BeginTable("tableDogs", 2, FlagsTable)) {
ImGui::TableSetupColumn("White Dog color", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("White Dog color", FlagsCell, TablesCellsWidth/2);
ImGui::TableSetupColumn("Brown Dog color", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("Brown Dog color", FlagsCell, TablesCellsWidth/2);
@ -381,8 +383,8 @@ void Draw_Npcs(){
} }
void Draw_ItemsSkills(){ void Draw_ItemsSkills(){
DrawRandomizeResetButton("all skills and items", AllItemsSkills_section, SECTION_SIZE(AllItemsSkills_section)); DrawRandomizeResetButton("all skills and items", AllItemsSkills_section, SECTION_SIZE(AllItemsSkills_section));
SohImGui::EnhancementCheckbox("Custom tunics color", "gUseTunicsCol"); UIWidgets::EnhancementCheckbox("Custom tunics color", "gUseTunicsCol");
SohImGui::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics."); UIWidgets::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics.");
if (CVar_GetS32("gUseTunicsCol",0)) { if (CVar_GetS32("gUseTunicsCol",0)) {
DrawRandomizeResetButton("Link's tunics", Tunics_Section, SECTION_SIZE(Tunics_Section)); DrawRandomizeResetButton("Link's tunics", Tunics_Section, SECTION_SIZE(Tunics_Section));
}; };
@ -394,7 +396,7 @@ void Draw_ItemsSkills(){
DrawColorSection(Tunics_Section, SECTION_SIZE(Tunics_Section)); DrawColorSection(Tunics_Section, SECTION_SIZE(Tunics_Section));
ImGui::EndTable(); ImGui::EndTable();
} }
SohImGui::EnhancementCheckbox("Custom arrows colors", "gUseArrowsCol"); UIWidgets::EnhancementCheckbox("Custom arrows colors", "gUseArrowsCol");
if (CVar_GetS32("gUseArrowsCol",0)) { if (CVar_GetS32("gUseArrowsCol",0)) {
DrawRandomizeResetButton("elemental arrows", Arrows_section, SECTION_SIZE(Arrows_section)); DrawRandomizeResetButton("elemental arrows", Arrows_section, SECTION_SIZE(Arrows_section));
} }
@ -405,7 +407,7 @@ void Draw_ItemsSkills(){
DrawColorSection(Arrows_section, SECTION_SIZE(Arrows_section)); DrawColorSection(Arrows_section, SECTION_SIZE(Arrows_section));
ImGui::EndTable(); ImGui::EndTable();
} }
SohImGui::EnhancementCheckbox("Custom spells colors", "gUseSpellsCol"); UIWidgets::EnhancementCheckbox("Custom spells colors", "gUseSpellsCol");
if (CVar_GetS32("gUseSpellsCol",0)) { if (CVar_GetS32("gUseSpellsCol",0)) {
DrawRandomizeResetButton("spells", Spells_section, SECTION_SIZE(Spells_section)); DrawRandomizeResetButton("spells", Spells_section, SECTION_SIZE(Spells_section));
} }
@ -416,7 +418,7 @@ void Draw_ItemsSkills(){
DrawColorSection(Spells_section, SECTION_SIZE(Spells_section)); DrawColorSection(Spells_section, SECTION_SIZE(Spells_section));
ImGui::EndTable(); ImGui::EndTable();
} }
SohImGui::EnhancementCheckbox("Custom spin attack colors", "gUseChargedCol"); UIWidgets::EnhancementCheckbox("Custom spin attack colors", "gUseChargedCol");
if (CVar_GetS32("gUseChargedCol",0)) { if (CVar_GetS32("gUseChargedCol",0)) {
DrawRandomizeResetButton("spins attack", SpinAtk_section, SECTION_SIZE(SpinAtk_section)); DrawRandomizeResetButton("spins attack", SpinAtk_section, SECTION_SIZE(SpinAtk_section));
} }
@ -427,13 +429,13 @@ void Draw_ItemsSkills(){
DrawColorSection(SpinAtk_section, SECTION_SIZE(SpinAtk_section)); DrawColorSection(SpinAtk_section, SECTION_SIZE(SpinAtk_section));
ImGui::EndTable(); ImGui::EndTable();
} }
SohImGui::EnhancementCheckbox("Custom trails color", "gUseTrailsCol"); UIWidgets::EnhancementCheckbox("Custom trails color", "gUseTrailsCol");
if (CVar_GetS32("gUseTrailsCol",0) && ImGui::BeginTable("tabletrails", 1, FlagsTable)) { if (CVar_GetS32("gUseTrailsCol",0) && ImGui::BeginTable("tabletrails", 1, FlagsTable)) {
ImGui::TableSetupColumn("Custom Trails", FlagsCell, TablesCellsWidth); ImGui::TableSetupColumn("Custom Trails", FlagsCell, TablesCellsWidth);
Table_InitHeader(); Table_InitHeader();
DrawColorSection(Trails_section, SECTION_SIZE(Trails_section)); DrawColorSection(Trails_section, SECTION_SIZE(Trails_section));
SohImGui::EnhancementSliderInt("Trails duration: %dx", "##TrailsMul", "gTrailDurantion", 1, 5, ""); UIWidgets::EnhancementSliderInt("Trails duration: %dx", "##TrailsMul", "gTrailDurantion", 1, 5, "");
SohImGui::Tooltip("The longer the trails the weirder it become"); UIWidgets::Tooltip("The longer the trails the weirder it become");
ImGui::NewLine(); ImGui::NewLine();
ImGui::EndTable(); ImGui::EndTable();
} }
@ -455,18 +457,18 @@ void Draw_Placements(){
if (ImGui::BeginTable("tableMargins", 1, FlagsTable)) { if (ImGui::BeginTable("tableMargins", 1, FlagsTable)) {
ImGui::TableSetupColumn("General margins settings", FlagsCell, TablesCellsWidth); ImGui::TableSetupColumn("General margins settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(); Table_InitHeader();
SohImGui::EnhancementSliderInt("Top : %dx", "##UIMARGINT", "gHUDMargin_T", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true); UIWidgets::EnhancementSliderInt("Top : %dx", "##UIMARGINT", "gHUDMargin_T", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true);
SohImGui::EnhancementSliderInt("Left: %dx", "##UIMARGINL", "gHUDMargin_L", -25, ImGui::GetWindowViewport()->Size.x, "", 0, true); UIWidgets::EnhancementSliderInt("Left: %dx", "##UIMARGINL", "gHUDMargin_L", -25, ImGui::GetWindowViewport()->Size.x, "", 0, true);
SohImGui::EnhancementSliderInt("Right: %dx", "##UIMARGINR", "gHUDMargin_R", (ImGui::GetWindowViewport()->Size.x)*-1, 25, "", 0, true); UIWidgets::EnhancementSliderInt("Right: %dx", "##UIMARGINR", "gHUDMargin_R", (ImGui::GetWindowViewport()->Size.x)*-1, 25, "", 0, true);
SohImGui::EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", "gHUDMargin_B", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true); UIWidgets::EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", "gHUDMargin_B", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true);
SetMarginAll("All margins on",true); SetMarginAll("All margins on",true);
SohImGui::Tooltip("Set most of the element to use margin\nSome elements with default position will not be affected\nElements without Archor or Hidden will not be turned on"); UIWidgets::Tooltip("Set most of the element to use margin\nSome elements with default position will not be affected\nElements without Archor or Hidden will not be turned on");
ImGui::SameLine(); ImGui::SameLine();
SetMarginAll("All margins off",false); SetMarginAll("All margins off",false);
SohImGui::Tooltip("Set all of the element to not use margin"); UIWidgets::Tooltip("Set all of the element to not use margin");
ImGui::SameLine(); ImGui::SameLine();
ResetPositionAll(); ResetPositionAll();
SohImGui::Tooltip("Revert every element to use their original position and no margins"); UIWidgets::Tooltip("Revert every element to use their original position and no margins");
ImGui::NewLine(); ImGui::NewLine();
ImGui::EndTable(); ImGui::EndTable();
} }
@ -775,7 +777,7 @@ void Draw_HUDButtons(){
DrawColorSection(C_Btn_Unified_section, SECTION_SIZE(C_Btn_Unified_section)); DrawColorSection(C_Btn_Unified_section, SECTION_SIZE(C_Btn_Unified_section));
ImGui::EndTable(); ImGui::EndTable();
} }
SohImGui::EnhancementCheckbox("C-Buttons use separate colors", "gCCparated"); UIWidgets::EnhancementCheckbox("C-Buttons use separate colors", "gCCparated");
if (CVar_GetS32("gCCparated",0) && ImGui::CollapsingHeader("C Button individual colors")) { if (CVar_GetS32("gCCparated",0) && ImGui::CollapsingHeader("C Button individual colors")) {
if (ImGui::BeginTable("tableBTN_CSep", 1, FlagsTable)) { if (ImGui::BeginTable("tableBTN_CSep", 1, FlagsTable)) {
ImGui::TableSetupColumn("C-Buttons individual colors", FlagsCell, TablesCellsWidth); ImGui::TableSetupColumn("C-Buttons individual colors", FlagsCell, TablesCellsWidth);
@ -813,19 +815,19 @@ void Draw_General(){
ImGui::TableSetupColumn("Custom Schemes", FlagsCell, TablesCellsWidth); ImGui::TableSetupColumn("Custom Schemes", FlagsCell, TablesCellsWidth);
Table_InitHeader(); Table_InitHeader();
Draw_HelpIcon("Change interface color to N64 style"); Draw_HelpIcon("Change interface color to N64 style");
SohImGui::EnhancementRadioButton("N64 Colors", "gHudColors", 0); UIWidgets::EnhancementRadioButton("N64 Colors", "gHudColors", 0);
Table_NextCol(); Table_NextCol();
Draw_HelpIcon("Change interface color to GameCube style"); Draw_HelpIcon("Change interface color to GameCube style");
SohImGui::EnhancementRadioButton("GCN Colors", "gHudColors", 1); UIWidgets::EnhancementRadioButton("GCN Colors", "gHudColors", 1);
Table_NextCol(); Table_NextCol();
Draw_HelpIcon("Lets you change every interface color to your liking"); Draw_HelpIcon("Lets you change every interface color to your liking");
SohImGui::EnhancementRadioButton("Custom Colors", "gHudColors", 2); UIWidgets::EnhancementRadioButton("Custom Colors", "gHudColors", 2);
ImGui::EndTable(); ImGui::EndTable();
} }
if (CVar_GetS32("gHudColors",0) ==2 ){ if (CVar_GetS32("gHudColors",0) ==2 ){
DrawRandomizeResetButton("interface (excluding buttons)", Misc_Interface_section, SECTION_SIZE(Misc_Interface_section)); DrawRandomizeResetButton("interface (excluding buttons)", Misc_Interface_section, SECTION_SIZE(Misc_Interface_section));
if (ImGui::CollapsingHeader("Hearts colors")) { if (ImGui::CollapsingHeader("Hearts colors")) {
SohImGui::Tooltip("Hearts colors in general\nDD stand for Double Defense"); UIWidgets::Tooltip("Hearts colors in general\nDD stand for Double Defense");
if (ImGui::BeginTable("tableHearts", 3, FlagsTable | ImGuiTableFlags_Hideable)) { if (ImGui::BeginTable("tableHearts", 3, FlagsTable | ImGuiTableFlags_Hideable)) {
ImGui::TableSetupColumn("Hearts (normal)", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable, TablesCellsWidth/3); ImGui::TableSetupColumn("Hearts (normal)", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable, TablesCellsWidth/3);
ImGui::TableSetupColumn("Hearts (DD)", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable, TablesCellsWidth/3); ImGui::TableSetupColumn("Hearts (DD)", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable, TablesCellsWidth/3);
@ -874,25 +876,25 @@ void Draw_General(){
ImGui::TableSetupColumn("transitionother1", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("transitionother1", FlagsCell, TablesCellsWidth/2);
ImGui::TableSetupColumn("transitionother2", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("transitionother2", FlagsCell, TablesCellsWidth/2);
Table_InitHeader(false); Table_InitHeader(false);
SohImGui::EnhancementRadioButton("Originals", "gSceneTransitions", 255); UIWidgets::EnhancementRadioButton("Originals", "gSceneTransitions", 255);
SohImGui::Tooltip("This will make the game use original scenes transitions"); UIWidgets::Tooltip("This will make the game use original scenes transitions");
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("None", "gSceneTransitions", 11); UIWidgets::EnhancementRadioButton("None", "gSceneTransitions", 11);
SohImGui::Tooltip("This will make the game use no any scenes transitions"); UIWidgets::Tooltip("This will make the game use no any scenes transitions");
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Desert mode (persistant)", "gSceneTransitions", 14); UIWidgets::EnhancementRadioButton("Desert mode (persistant)", "gSceneTransitions", 14);
SohImGui::Tooltip("This will make the game use the sand storm scenes transitions that will persist in map"); UIWidgets::Tooltip("This will make the game use the sand storm scenes transitions that will persist in map");
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Desert mode (non persistant)", "gSceneTransitions", 15); UIWidgets::EnhancementRadioButton("Desert mode (non persistant)", "gSceneTransitions", 15);
SohImGui::Tooltip("This will make the game use the sand storm scenes transitions"); UIWidgets::Tooltip("This will make the game use the sand storm scenes transitions");
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Normal fade (green)", "gSceneTransitions", 18); UIWidgets::EnhancementRadioButton("Normal fade (green)", "gSceneTransitions", 18);
SohImGui::Tooltip("This will make the game use a greenish fade in/out scenes transitions"); UIWidgets::Tooltip("This will make the game use a greenish fade in/out scenes transitions");
Table_NextCol(); Table_NextCol();
SohImGui::EnhancementRadioButton("Normal fade (blue)", "gSceneTransitions", 19); UIWidgets::EnhancementRadioButton("Normal fade (blue)", "gSceneTransitions", 19);
SohImGui::Tooltip("This will make the game use a blue fade in/out scenes transitions"); UIWidgets::Tooltip("This will make the game use a blue fade in/out scenes transitions");
Table_NextLine(); Table_NextLine();
SohImGui::EnhancementRadioButton("Triforce", "gSceneTransitions", 1); UIWidgets::EnhancementRadioButton("Triforce", "gSceneTransitions", 1);
ImGui::EndTable(); ImGui::EndTable();
} }
if (ImGui::BeginTable("tabletransitionCol", 2, FlagsTable | ImGuiTableFlags_Hideable)) { if (ImGui::BeginTable("tabletransitionCol", 2, FlagsTable | ImGuiTableFlags_Hideable)) {
@ -948,6 +950,7 @@ void DrawCosmeticsEditor(bool& open) {
} }
ImGui::End(); ImGui::End();
} }
void InitCosmeticsEditor() { void InitCosmeticsEditor() {
//This allow to hide a window without disturbing the player nor adding things in menu //This allow to hide a window without disturbing the player nor adding things in menu
//LoadRainbowColor() will this way run in background once it's window is activated //LoadRainbowColor() will this way run in background once it's window is activated

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "../libultraship/ImGuiImpl.h" #include <libultraship/ImGuiImpl.h>
#define SECTION_SIZE(arr) (s32)(sizeof(arr) / sizeof(arr[0])) #define SECTION_SIZE(arr) (s32)(sizeof(arr) / sizeof(arr[0]))
#define RANDOMIZE_32(Max) GetRandomValue(Max); #define RANDOMIZE_32(Max) GetRandomValue(Max);
#define CATEGORY_NPC 0 #define CATEGORY_NPC 0

View File

@ -1,7 +1,7 @@
#include "debugconsole.h" #include "debugconsole.h"
#include "../libultraship/ImGuiImpl.h" #include <libultraship/ImGuiImpl.h>
#include "savestates.h" #include "savestates.h"
#include "Console.h" #include <libultraship/Console.h>
#include <vector> #include <vector>
#include <string> #include <string>
@ -12,8 +12,8 @@
#define PATH_HACK #define PATH_HACK
#include <Utils/StringHelper.h> #include <Utils/StringHelper.h>
#include "Window.h" #include <libultraship/Window.h>
#include "Lib/ImGui/imgui_internal.h" #include <ImGui/imgui_internal.h>
#undef PATH_HACK #undef PATH_HACK
#undef Path #undef Path
@ -25,18 +25,18 @@ extern "C" {
extern GlobalContext* gGlobalCtx; extern GlobalContext* gGlobalCtx;
} }
#include "Cvar.h" #include <libultraship/Cvar.h>
#define CMD_REGISTER SohImGui::BindCmd #define CMD_REGISTER SohImGui::GetConsole()->AddCommand
static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) { static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) { if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) {
SohImGui::console->SendErrorMessage("Not enough arguments passed to actorspawn"); SohImGui::GetConsole()->SendErrorMessage("Not enough arguments passed to actorspawn");
return CMD_FAILED; return CMD_FAILED;
} }
if (gGlobalCtx == nullptr) { if (gGlobalCtx == nullptr) {
SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); SohImGui::GetConsole()->SendErrorMessage("GlobalCtx == nullptr");
return CMD_FAILED; return CMD_FAILED;
} }
@ -72,7 +72,7 @@ static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std:
if (Actor_Spawn(&gGlobalCtx->actorCtx, gGlobalCtx, actorId, spawnPoint.pos.x, spawnPoint.pos.y, spawnPoint.pos.z, if (Actor_Spawn(&gGlobalCtx->actorCtx, gGlobalCtx, actorId, spawnPoint.pos.x, spawnPoint.pos.y, spawnPoint.pos.z,
spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params) == NULL) { spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params) == NULL) {
SohImGui::console->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL"); SohImGui::GetConsole()->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL");
return CMD_FAILED; return CMD_FAILED;
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -81,13 +81,13 @@ static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std:
static bool KillPlayerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&) { static bool KillPlayerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&) {
gSaveContext.health = 0; gSaveContext.health = 0;
SohImGui::console->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?"); SohImGui::GetConsole()->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?");
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static bool SetPlayerHealthHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) { static bool SetPlayerHealthHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (args.size() != 2) { if (args.size() != 2) {
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED; return CMD_FAILED;
} }
@ -96,18 +96,18 @@ static bool SetPlayerHealthHandler(std::shared_ptr<Ship::Console> Console, const
try { try {
health = std::stoi(args[1]); health = std::stoi(args[1]);
} catch (std::invalid_argument const& ex) { } catch (std::invalid_argument const& ex) {
SohImGui::console->SendErrorMessage("[SOH] Health value must be an integer."); SohImGui::GetConsole()->SendErrorMessage("[SOH] Health value must be an integer.");
return CMD_FAILED; return CMD_FAILED;
} }
if (health < 0) { if (health < 0) {
SohImGui::console->SendErrorMessage("[SOH] Health value must be a positive integer"); SohImGui::GetConsole()->SendErrorMessage("[SOH] Health value must be a positive integer");
return CMD_SUCCESS; return CMD_SUCCESS;
} }
gSaveContext.health = health * 0x10; gSaveContext.health = health * 0x10;
SohImGui::console->SendInfoMessage("[SOH] Player health updated to %d", health); SohImGui::GetConsole()->SendInfoMessage("[SOH] Player health updated to %d", health);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -129,31 +129,31 @@ static bool RuppeHandler(std::shared_ptr<Ship::Console> Console, const std::vect
rupeeAmount = std::stoi(args[1]); rupeeAmount = std::stoi(args[1]);
} }
catch (std::invalid_argument const& ex) { catch (std::invalid_argument const& ex) {
SohImGui::console->SendErrorMessage("[SOH] Rupee count must be an integer."); SohImGui::GetConsole()->SendErrorMessage("[SOH] Rupee count must be an integer.");
return CMD_FAILED; return CMD_FAILED;
} }
if (rupeeAmount < 0) { if (rupeeAmount < 0) {
SohImGui::console->SendErrorMessage("[SOH] Rupee count must be positive"); SohImGui::GetConsole()->SendErrorMessage("[SOH] Rupee count must be positive");
return CMD_FAILED; return CMD_FAILED;
} }
gSaveContext.rupees = rupeeAmount; gSaveContext.rupees = rupeeAmount;
SohImGui::console->SendInfoMessage("Set rupee count to %u", rupeeAmount); SohImGui::GetConsole()->SendInfoMessage("Set rupee count to %u", rupeeAmount);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static bool SetPosHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string> args) { static bool SetPosHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string> args) {
if (gGlobalCtx == nullptr) { if (gGlobalCtx == nullptr) {
SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); SohImGui::GetConsole()->SendErrorMessage("GlobalCtx == nullptr");
return CMD_FAILED; return CMD_FAILED;
} }
Player* player = GET_PLAYER(gGlobalCtx); Player* player = GET_PLAYER(gGlobalCtx);
if (args.size() == 1) { if (args.size() == 1) {
SohImGui::console->SendInfoMessage("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, SohImGui::GetConsole()->SendInfoMessage("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x,
player->actor.world.pos.y, player->actor.world.pos.y,
player->actor.world.pos.z); player->actor.world.pos.z);
return CMD_SUCCESS; return CMD_SUCCESS;
@ -165,7 +165,7 @@ static bool SetPosHandler(std::shared_ptr<Ship::Console> Console, const std::vec
player->actor.world.pos.y = std::stof(args[2]); player->actor.world.pos.y = std::stof(args[2]);
player->actor.world.pos.z = std::stof(args[3]); player->actor.world.pos.z = std::stof(args[3]);
SohImGui::console->SendInfoMessage("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, SohImGui::GetConsole()->SendInfoMessage("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x,
player->actor.world.pos.y, player->actor.world.pos.y,
player->actor.world.pos.z); player->actor.world.pos.z);
return CMD_SUCCESS; return CMD_SUCCESS;
@ -173,7 +173,7 @@ static bool SetPosHandler(std::shared_ptr<Ship::Console> Console, const std::vec
static bool ResetHandler(std::shared_ptr<Ship::Console> Console, std::vector<std::string> args) { static bool ResetHandler(std::shared_ptr<Ship::Console> Console, std::vector<std::string> args) {
if (gGlobalCtx == nullptr) { if (gGlobalCtx == nullptr) {
SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); SohImGui::GetConsole()->SendErrorMessage("GlobalCtx == nullptr");
return CMD_FAILED; return CMD_FAILED;
} }
@ -194,7 +194,7 @@ const static std::map<std::string, uint16_t> ammoItems{
static bool AmmoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) { static bool AmmoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (args.size() != 3) { if (args.size() != 3) {
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED; return CMD_FAILED;
} }
@ -203,19 +203,19 @@ static bool AmmoHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
try { try {
count = std::stoi(args[2]); count = std::stoi(args[2]);
} catch (std::invalid_argument const& ex) { } catch (std::invalid_argument const& ex) {
SohImGui::console->SendErrorMessage("Ammo count must be an integer"); SohImGui::GetConsole()->SendErrorMessage("Ammo count must be an integer");
return CMD_FAILED; return CMD_FAILED;
} }
if (count < 0) { if (count < 0) {
SohImGui::console->SendErrorMessage("Ammo count must be positive"); SohImGui::GetConsole()->SendErrorMessage("Ammo count must be positive");
return CMD_FAILED; return CMD_FAILED;
} }
const auto& it = ammoItems.find(args[1]); const auto& it = ammoItems.find(args[1]);
if (it == ammoItems.end()) { if (it == ammoItems.end()) {
SohImGui::console->SendErrorMessage("Invalid item passed"); SohImGui::GetConsole()->SendErrorMessage("Invalid item passed");
return CMD_FAILED; return CMD_FAILED;
} }
@ -237,7 +237,7 @@ const static std::map<std::string, uint16_t> bottleItems{
static bool BottleHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) { static bool BottleHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (args.size() != 3) { if (args.size() != 3) {
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED; return CMD_FAILED;
} }
@ -245,19 +245,19 @@ static bool BottleHandler(std::shared_ptr<Ship::Console> Console, const std::vec
try { try {
slot = std::stoi(args[2]); slot = std::stoi(args[2]);
} catch (std::invalid_argument const& ex) { } catch (std::invalid_argument const& ex) {
SohImGui::console->SendErrorMessage("[SOH] Bottle slot must be an integer."); SohImGui::GetConsole()->SendErrorMessage("[SOH] Bottle slot must be an integer.");
return CMD_FAILED; return CMD_FAILED;
} }
if ((slot < 1) || (slot > 4)) { if ((slot < 1) || (slot > 4)) {
SohImGui::console->SendErrorMessage("Invalid slot passed"); SohImGui::GetConsole()->SendErrorMessage("Invalid slot passed");
return CMD_FAILED; return CMD_FAILED;
} }
const auto& it = bottleItems.find(args[1]); const auto& it = bottleItems.find(args[1]);
if (it == bottleItems.end()) { if (it == bottleItems.end()) {
SohImGui::console->SendErrorMessage("Invalid item passed"); SohImGui::GetConsole()->SendErrorMessage("Invalid item passed");
return CMD_FAILED; return CMD_FAILED;
} }
@ -269,7 +269,7 @@ static bool BottleHandler(std::shared_ptr<Ship::Console> Console, const std::vec
static bool BHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) { static bool BHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (args.size() != 2) { if (args.size() != 2) {
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED; return CMD_FAILED;
} }
@ -279,7 +279,7 @@ static bool BHandler(std::shared_ptr<Ship::Console> Console, const std::vector<s
static bool ItemHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) { static bool ItemHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (args.size() != 3) { if (args.size() != 3) {
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED; return CMD_FAILED;
} }
@ -290,7 +290,7 @@ static bool ItemHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
static bool EntranceHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) { static bool EntranceHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (args.size() != 2) { if (args.size() != 2) {
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED; return CMD_FAILED;
} }
@ -299,7 +299,7 @@ static bool EntranceHandler(std::shared_ptr<Ship::Console> Console, const std::v
try { try {
entrance = std::stoi(args[1], nullptr, 16); entrance = std::stoi(args[1], nullptr, 16);
} catch (std::invalid_argument const& ex) { } catch (std::invalid_argument const& ex) {
SohImGui::console->SendErrorMessage("[SOH] Entrance value must be a Hex number."); SohImGui::GetConsole()->SendErrorMessage("[SOH] Entrance value must be a Hex number.");
return CMD_FAILED; return CMD_FAILED;
} }
@ -319,7 +319,7 @@ static bool VoidHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
gGlobalCtx->fadeTransition = 2; gGlobalCtx->fadeTransition = 2;
gSaveContext.nextTransition = 2; gSaveContext.nextTransition = 2;
} else { } else {
SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr");
return CMD_FAILED; return CMD_FAILED;
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -332,7 +332,7 @@ static bool ReloadHandler(std::shared_ptr<Ship::Console> Console, const std::vec
gGlobalCtx->fadeTransition = 11; gGlobalCtx->fadeTransition = 11;
gSaveContext.nextTransition = 11; gSaveContext.nextTransition = 11;
} else { } else {
SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr");
return CMD_FAILED; return CMD_FAILED;
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -345,11 +345,11 @@ static bool FWHandler(std::shared_ptr<Ship::Console> Console, const std::vector<
gGlobalCtx->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_TOP].entranceIndex; gGlobalCtx->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_TOP].entranceIndex;
gGlobalCtx->fadeTransition = 5; gGlobalCtx->fadeTransition = 5;
} else { } else {
SohImGui::console->SendErrorMessage("Farore's wind not set!"); SohImGui::GetConsole()->SendErrorMessage("Farore's wind not set!");
} }
} }
else { else {
SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr");
return CMD_FAILED; return CMD_FAILED;
} }
@ -361,7 +361,7 @@ static bool FileSelectHandler(std::shared_ptr<Ship::Console> Console, const std:
SET_NEXT_GAMESTATE(&gGlobalCtx->state, FileChoose_Init, FileChooseContext); SET_NEXT_GAMESTATE(&gGlobalCtx->state, FileChoose_Init, FileChooseContext);
gGlobalCtx->state.running = 0; gGlobalCtx->state.running = 0;
} else { } else {
SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr");
return CMD_FAILED; return CMD_FAILED;
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -378,10 +378,10 @@ static bool SaveStateHandler(std::shared_ptr<Ship::Console> Console, const std::
switch (rtn) { switch (rtn) {
case SaveStateReturn::SUCCESS: case SaveStateReturn::SUCCESS:
SohImGui::console->SendInfoMessage("[SOH] Saved state to slot %u", slot); SohImGui::GetConsole()->SendInfoMessage("[SOH] Saved state to slot %u", slot);
return CMD_SUCCESS; return CMD_SUCCESS;
case SaveStateReturn::FAIL_WRONG_GAMESTATE: case SaveStateReturn::FAIL_WRONG_GAMESTATE:
SohImGui::console->SendErrorMessage("[SOH] Can not save a state outside of \"GamePlay\""); SohImGui::GetConsole()->SendErrorMessage("[SOH] Can not save a state outside of \"GamePlay\"");
return CMD_FAILED; return CMD_FAILED;
} }
} }
@ -392,16 +392,16 @@ static bool LoadStateHandler(std::shared_ptr<Ship::Console> Console, const std::
switch (rtn) { switch (rtn) {
case SaveStateReturn::SUCCESS: case SaveStateReturn::SUCCESS:
SohImGui::console->SendInfoMessage("[SOH] Loaded state from slot (%u)", slot); SohImGui::GetConsole()->SendInfoMessage("[SOH] Loaded state from slot (%u)", slot);
return CMD_SUCCESS; return CMD_SUCCESS;
case SaveStateReturn::FAIL_INVALID_SLOT: case SaveStateReturn::FAIL_INVALID_SLOT:
SohImGui::console->SendErrorMessage("[SOH] Invalid State Slot Number (%u)", slot); SohImGui::GetConsole()->SendErrorMessage("[SOH] Invalid State Slot Number (%u)", slot);
return CMD_FAILED; return CMD_FAILED;
case SaveStateReturn::FAIL_STATE_EMPTY: case SaveStateReturn::FAIL_STATE_EMPTY:
SohImGui::console->SendErrorMessage("[SOH] State Slot (%u) is empty", slot); SohImGui::GetConsole()->SendErrorMessage("[SOH] State Slot (%u) is empty", slot);
return CMD_FAILED; return CMD_FAILED;
case SaveStateReturn::FAIL_WRONG_GAMESTATE: case SaveStateReturn::FAIL_WRONG_GAMESTATE:
SohImGui::console->SendErrorMessage("[SOH] Can not load a state outside of \"GamePlay\""); SohImGui::GetConsole()->SendErrorMessage("[SOH] Can not load a state outside of \"GamePlay\"");
return CMD_FAILED; return CMD_FAILED;
} }
@ -409,7 +409,7 @@ static bool LoadStateHandler(std::shared_ptr<Ship::Console> Console, const std::
static bool StateSlotSelectHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) { static bool StateSlotSelectHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (args.size() != 2) { if (args.size() != 2) {
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED; return CMD_FAILED;
} }
int slot; int slot;
@ -417,17 +417,17 @@ static bool StateSlotSelectHandler(std::shared_ptr<Ship::Console> Console, const
try { try {
slot = std::stoi(args[1], nullptr, 10); slot = std::stoi(args[1], nullptr, 10);
} catch (std::invalid_argument const& ex) { } catch (std::invalid_argument const& ex) {
SohImGui::console->SendErrorMessage("[SOH] SaveState slot value must be a number."); SohImGui::GetConsole()->SendErrorMessage("[SOH] SaveState slot value must be a number.");
return CMD_FAILED; return CMD_FAILED;
} }
if (slot < 0) { if (slot < 0) {
SohImGui::console->SendErrorMessage("[SOH] Invalid slot passed. Slot must be between 0 and 2"); SohImGui::GetConsole()->SendErrorMessage("[SOH] Invalid slot passed. Slot must be between 0 and 2");
return CMD_FAILED; return CMD_FAILED;
} }
OTRGlobals::Instance->gSaveStateMgr->SetCurrentSlot(slot); OTRGlobals::Instance->gSaveStateMgr->SetCurrentSlot(slot);
SohImGui::console->SendInfoMessage("[SOH] Slot %u selected", SohImGui::GetConsole()->SendInfoMessage("[SOH] Slot %u selected",
OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot()); OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot());
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -488,7 +488,7 @@ static bool SetCVarHandler(std::shared_ptr<Ship::Console> Console, const std::ve
CVar_Save(); CVar_Save();
//SohImGui::console->SendInfoMessage("[SOH] Updated player position to [ %.2f, %.2f, %.2f ]", pos.x, pos.y, pos.z); //SohImGui::GetConsole()->SendInfoMessage("[SOH] Updated player position to [ %.2f, %.2f, %.2f ]", pos.x, pos.y, pos.z);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -502,17 +502,17 @@ static bool GetCVarHandler(std::shared_ptr<Ship::Console> Console, const std::ve
if (cvar != nullptr) if (cvar != nullptr)
{ {
if (cvar->type == CVarType::S32) if (cvar->type == CVarType::S32)
SohImGui::console->SendInfoMessage("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32); SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32);
else if (cvar->type == CVarType::Float) else if (cvar->type == CVarType::Float)
SohImGui::console->SendInfoMessage("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat); SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat);
else if (cvar->type == CVarType::String) else if (cvar->type == CVarType::String)
SohImGui::console->SendInfoMessage("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr); SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr);
else if (cvar->type == CVarType::RGBA) else if (cvar->type == CVarType::RGBA)
SohImGui::console->SendInfoMessage("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA); SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA);
} }
else else
{ {
SohImGui::console->SendInfoMessage("[SOH] Could not find variable %s", args[1].c_str()); SohImGui::GetConsole()->SendInfoMessage("[SOH] Could not find variable %s", args[1].c_str());
} }

View File

@ -1,32 +0,0 @@
#include "ImGuiHelpers.h"
#include "../../../../libultraship/libultraship/ImGuiImpl.h"
// Adds a text tooltip for the previous ImGui item
void SetLastItemHoverText(const std::string& text) {
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text(SohImGui::BreakTooltip(text, 60).c_str());
ImGui::EndTooltip();
}
}
// Adds a "?" next to the previous ImGui item with a custom tooltip
void InsertHelpHoverText(const std::string& text) {
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text(SohImGui::BreakTooltip(text, 60).c_str());
ImGui::EndTooltip();
}
}
void PaddedSeparator(bool padTop, bool padBottom, float extraVerticalPadding) {
if (padTop) {
ImGui::Dummy(ImVec2(0.0f, extraVerticalPadding));
}
ImGui::Separator();
if (padBottom) {
ImGui::Dummy(ImVec2(0.0f, extraVerticalPadding));
}
}

View File

@ -1,10 +0,0 @@
#pragma once
#include "../libultraship/Lib/ImGui/imgui.h"
#include <string>
void SetLastItemHoverText(const std::string& text);
void InsertHelpHoverText(const std::string& text);
void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalPadding = 0);

View File

@ -1,13 +1,13 @@
#include "actorViewer.h" #include "actorViewer.h"
#include "../../util.h" #include "../../util.h"
#include "../libultraship/ImGuiImpl.h" #include "../../UIWidgets.hpp"
#include "ImGuiHelpers.h" #include <libultraship/ImGuiImpl.h>
#include <array> #include <array>
#include <bit> #include <bit>
#include <map> #include <map>
#include <string> #include <string>
#include <Cvar.h> #include <libultraship/Cvar.h>
extern "C" { extern "C" {
#include <z64.h> #include <z64.h>
@ -632,7 +632,7 @@ void DrawActorViewer(bool& open) {
if (display.category == ACTORCAT_BOSS || display.category == ACTORCAT_ENEMY) { if (display.category == ACTORCAT_BOSS || display.category == ACTORCAT_ENEMY) {
ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display.colChkInfo.health); ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display.colChkInfo.health);
InsertHelpHoverText("Some actors might not use this!"); UIWidgets::InsertHelpHoverText("Some actors might not use this!");
} }
if (ImGui::Button("Refresh")) { if (ImGui::Button("Refresh")) {
@ -667,7 +667,7 @@ void DrawActorViewer(bool& open) {
rm = TARGET; rm = TARGET;
} }
} }
InsertHelpHoverText("Grabs actor with target arrow above it. You might need C-Up for enemies"); UIWidgets::InsertHelpHoverText("Grabs actor with target arrow above it. You might need C-Up for enemies");
if (ImGui::Button("Fetch from Held")) { if (ImGui::Button("Fetch from Held")) {
Player* player = GET_PLAYER(gGlobalCtx); Player* player = GET_PLAYER(gGlobalCtx);
fetch = player->heldActor; fetch = player->heldActor;
@ -678,7 +678,7 @@ void DrawActorViewer(bool& open) {
rm = HELD; rm = HELD;
} }
} }
InsertHelpHoverText("Grabs actor that Link is holding"); UIWidgets::InsertHelpHoverText("Grabs actor that Link is holding");
if (ImGui::Button("Fetch from Interaction")) { if (ImGui::Button("Fetch from Interaction")) {
Player* player = GET_PLAYER(gGlobalCtx); Player* player = GET_PLAYER(gGlobalCtx);
fetch = player->interactRangeActor; fetch = player->interactRangeActor;
@ -689,7 +689,7 @@ void DrawActorViewer(bool& open) {
rm = INTERACT; rm = INTERACT;
} }
} }
InsertHelpHoverText("Grabs actor from \"interaction range\""); UIWidgets::InsertHelpHoverText("Grabs actor from \"interaction range\"");
ImGui::TreePop(); ImGui::TreePop();
} }

View File

@ -1,12 +1,12 @@
#include "colViewer.h" #include "colViewer.h"
#include "../libultraship/ImGuiImpl.h" #include <libultraship/ImGuiImpl.h>
#include "ImGuiHelpers.h"
#include "../../frame_interpolation.h" #include "../../frame_interpolation.h"
#include "../../UIWidgets.hpp"
#include <vector> #include <vector>
#include <string> #include <string>
#include <cmath> #include <cmath>
#include <Cvar.h> #include <libultraship/Cvar.h>
extern "C" { extern "C" {
#include <z64.h> #include <z64.h>
@ -62,42 +62,42 @@ void DrawColViewerWindow(bool& open) {
ImGui::End(); ImGui::End();
return; return;
} }
SohImGui::EnhancementCheckbox("Enabled", "gColViewerEnabled"); UIWidgets::EnhancementCheckbox("Enabled", "gColViewerEnabled");
SohImGui::EnhancementCombo("Scene", "gColViewerScene", ColRenderSettingNames); UIWidgets::EnhancementCombo("Scene", "gColViewerScene", ColRenderSettingNames);
SohImGui::EnhancementCombo("Bg Actors", "gColViewerBgActors", ColRenderSettingNames); UIWidgets::EnhancementCombo("Bg Actors", "gColViewerBgActors", ColRenderSettingNames);
SohImGui::EnhancementCombo("Col Check", "gColViewerColCheck", ColRenderSettingNames); UIWidgets::EnhancementCombo("Col Check", "gColViewerColCheck", ColRenderSettingNames);
SohImGui::EnhancementCombo("Waterbox", "gColViewerWaterbox", ColRenderSettingNames); UIWidgets::EnhancementCombo("Waterbox", "gColViewerWaterbox", ColRenderSettingNames);
SohImGui::EnhancementCheckbox("Apply as decal", "gColViewerDecal"); UIWidgets::EnhancementCheckbox("Apply as decal", "gColViewerDecal");
InsertHelpHoverText("Applies the collision as a decal display. This can be useful if there is z-fighting occuring " UIWidgets::InsertHelpHoverText("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."); "with the scene geometry, but can cause other artifacts.");
SohImGui::EnhancementCheckbox("Shaded", "gColViewerShaded"); UIWidgets::EnhancementCheckbox("Shaded", "gColViewerShaded");
InsertHelpHoverText("Applies the scene's shading to the collision display."); UIWidgets::InsertHelpHoverText("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() // 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."; const std::string colorHelpText = "View and change the colors used for collision display.";
if (ImGui::TreeNode("Colors")) { if (ImGui::TreeNode("Colors")) {
InsertHelpHoverText(colorHelpText); UIWidgets::InsertHelpHoverText(colorHelpText);
SohImGui::EnhancementColor("Normal", "gColViewerColorNormal", scene_col, ImVec4(255, 255, 255, 255), false); UIWidgets::EnhancementColor("Normal", "gColViewerColorNormal", scene_col, ImVec4(255, 255, 255, 255), false);
SohImGui::EnhancementColor("Hookshot", "gColViewerColorHookshot", hookshot_col, ImVec4(128, 128, 255, 255), UIWidgets::EnhancementColor("Hookshot", "gColViewerColorHookshot", hookshot_col, ImVec4(128, 128, 255, 255),
false); false);
SohImGui::EnhancementColor("Entrance", "gColViewerColorEntrance", entrance_col, ImVec4(0, 255, 0, 255), false); UIWidgets::EnhancementColor("Entrance", "gColViewerColorEntrance", entrance_col, ImVec4(0, 255, 0, 255), false);
SohImGui::EnhancementColor("Special Surface (Grass/Sand/Etc)", "gColViewerColorSpecialSurface", UIWidgets::EnhancementColor("Special Surface (Grass/Sand/Etc)", "gColViewerColorSpecialSurface",
specialSurface_col, ImVec4(192, 255, 192, 255), false); specialSurface_col, ImVec4(192, 255, 192, 255), false);
SohImGui::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", "gColViewerColorInteractable", UIWidgets::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", "gColViewerColorInteractable",
interactable_col, ImVec4(192, 0, 192, 255), false); interactable_col, ImVec4(192, 0, 192, 255), false);
SohImGui::EnhancementColor("Slope", "gColViewerColorSlope", slope_col, ImVec4(255, 255, 128, 255), false); UIWidgets::EnhancementColor("Slope", "gColViewerColorSlope", slope_col, ImVec4(255, 255, 128, 255), false);
SohImGui::EnhancementColor("Void", "gColViewerColorVoid", void_col, ImVec4(255, 0, 0, 255), false); UIWidgets::EnhancementColor("Void", "gColViewerColorVoid", void_col, ImVec4(255, 0, 0, 255), false);
SohImGui::EnhancementColor("OC", "gColViewerColorOC", oc_col, ImVec4(255, 255, 255, 255), false); UIWidgets::EnhancementColor("OC", "gColViewerColorOC", oc_col, ImVec4(255, 255, 255, 255), false);
SohImGui::EnhancementColor("AC", "gColViewerColorAC", ac_col, ImVec4(0, 0, 255, 255), false); UIWidgets::EnhancementColor("AC", "gColViewerColorAC", ac_col, ImVec4(0, 0, 255, 255), false);
SohImGui::EnhancementColor("AT", "gColViewerColorAT", at_col, ImVec4(255, 0, 0, 255), false); UIWidgets::EnhancementColor("AT", "gColViewerColorAT", at_col, ImVec4(255, 0, 0, 255), false);
SohImGui::EnhancementColor("Waterbox", "gColViewerColorWaterbox", waterbox_col, ImVec4(0, 0, 255, 255), false); UIWidgets::EnhancementColor("Waterbox", "gColViewerColorWaterbox", waterbox_col, ImVec4(0, 0, 255, 255), false);
ImGui::TreePop(); ImGui::TreePop();
} else { } else {
InsertHelpHoverText(colorHelpText); UIWidgets::InsertHelpHoverText(colorHelpText);
} }
ImGui::End(); ImGui::End();

View File

@ -1,14 +1,14 @@
#include "debugSaveEditor.h" #include "debugSaveEditor.h"
#include "../../util.h" #include "../../util.h"
#include "../../OTRGlobals.h" #include "../../OTRGlobals.h"
#include "../libultraship/ImGuiImpl.h" #include <libultraship/ImGuiImpl.h>
#include "ImGuiHelpers.h" #include "../../UIWidgets.hpp"
#include <array> #include <array>
#include <bit> #include <bit>
#include <map> #include <map>
#include <string> #include <string>
#include <Cvar.h> #include <libultraship/Cvar.h>
extern "C" { extern "C" {
#include <z64.h> #include <z64.h>
@ -311,7 +311,7 @@ void DrawInfoTab() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::Text("Name: %s", name.c_str()); ImGui::Text("Name: %s", name.c_str());
InsertHelpHoverText("Player Name"); UIWidgets::InsertHelpHoverText("Player Name");
std::string nameID; std::string nameID;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
nameID = z2ASCII(i); nameID = z2ASCII(i);
@ -328,7 +328,7 @@ void DrawInfoTab() {
if (ImGui::IsItemDeactivated()) { if (ImGui::IsItemDeactivated()) {
gSaveContext.healthCapacity = healthIntermediary; gSaveContext.healthCapacity = healthIntermediary;
} }
InsertHelpHoverText("Maximum health. 16 units per full heart"); UIWidgets::InsertHelpHoverText("Maximum health. 16 units per full heart");
if (gSaveContext.health > gSaveContext.healthCapacity) { if (gSaveContext.health > gSaveContext.healthCapacity) {
gSaveContext.health = gSaveContext.healthCapacity; // Clamp health to new max gSaveContext.health = gSaveContext.healthCapacity; // Clamp health to new max
} }
@ -337,7 +337,7 @@ void DrawInfoTab() {
const uint16_t healthMax = gSaveContext.healthCapacity; const uint16_t healthMax = gSaveContext.healthCapacity;
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
ImGui::SliderScalar("Health", ImGuiDataType_S16, &gSaveContext.health, &healthMin, &healthMax); ImGui::SliderScalar("Health", ImGuiDataType_S16, &gSaveContext.health, &healthMin, &healthMax);
InsertHelpHoverText("Current health. 16 units per full heart"); UIWidgets::InsertHelpHoverText("Current health. 16 units per full heart");
bool doubleDefense = gSaveContext.doubleDefense != 0; bool doubleDefense = gSaveContext.doubleDefense != 0;
if (ImGui::Checkbox("Double Defense", &doubleDefense)) { if (ImGui::Checkbox("Double Defense", &doubleDefense)) {
@ -345,7 +345,7 @@ void DrawInfoTab() {
gSaveContext.inventory.defenseHearts = gSaveContext.inventory.defenseHearts =
gSaveContext.doubleDefense ? 20 : 0; // Set to get the border drawn in the UI gSaveContext.doubleDefense ? 20 : 0; // Set to get the border drawn in the UI
} }
InsertHelpHoverText("Is double defense unlocked?"); UIWidgets::InsertHelpHoverText("Is double defense unlocked?");
std::string magicName; std::string magicName;
if (gSaveContext.magicLevel == 2) { if (gSaveContext.magicLevel == 2) {
@ -375,7 +375,7 @@ void DrawInfoTab() {
ImGui::EndCombo(); ImGui::EndCombo();
} }
InsertHelpHoverText("Current magic level"); UIWidgets::InsertHelpHoverText("Current magic level");
gSaveContext.unk_13F4 = gSaveContext.magicLevel * 0x30; // Set to get the bar drawn in the UI gSaveContext.unk_13F4 = gSaveContext.magicLevel * 0x30; // Set to get the bar drawn in the UI
if (gSaveContext.magic > gSaveContext.unk_13F4) { if (gSaveContext.magic > gSaveContext.unk_13F4) {
gSaveContext.magic = gSaveContext.unk_13F4; // Clamp magic to new max gSaveContext.magic = gSaveContext.unk_13F4; // Clamp magic to new max
@ -385,16 +385,16 @@ void DrawInfoTab() {
const uint8_t magicMax = gSaveContext.unk_13F4; const uint8_t magicMax = gSaveContext.unk_13F4;
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
ImGui::SliderScalar("Magic", ImGuiDataType_S8, &gSaveContext.magic, &magicMin, &magicMax); ImGui::SliderScalar("Magic", ImGuiDataType_S8, &gSaveContext.magic, &magicMin, &magicMax);
InsertHelpHoverText("Current magic. 48 units per magic level"); UIWidgets::InsertHelpHoverText("Current magic. 48 units per magic level");
ImGui::InputScalar("Rupees", ImGuiDataType_S16, &gSaveContext.rupees); ImGui::InputScalar("Rupees", ImGuiDataType_S16, &gSaveContext.rupees);
InsertHelpHoverText("Current rupees"); UIWidgets::InsertHelpHoverText("Current rupees");
const uint16_t dayTimeMin = 0; const uint16_t dayTimeMin = 0;
const uint16_t dayTimeMax = 0xFFFF; const uint16_t dayTimeMax = 0xFFFF;
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
ImGui::SliderScalar("Time", ImGuiDataType_U16, &gSaveContext.dayTime, &dayTimeMin, &dayTimeMax); ImGui::SliderScalar("Time", ImGuiDataType_U16, &gSaveContext.dayTime, &dayTimeMin, &dayTimeMax);
InsertHelpHoverText("Time of day"); UIWidgets::InsertHelpHoverText("Time of day");
if (ImGui::Button("Dawn")) { if (ImGui::Button("Dawn")) {
gSaveContext.dayTime = 0x4000; gSaveContext.dayTime = 0x4000;
} }
@ -412,43 +412,43 @@ void DrawInfoTab() {
} }
ImGui::InputScalar("Total Days", ImGuiDataType_S32, &gSaveContext.totalDays); ImGui::InputScalar("Total Days", ImGuiDataType_S32, &gSaveContext.totalDays);
InsertHelpHoverText("Total number of days elapsed since the start of the game"); UIWidgets::InsertHelpHoverText("Total number of days elapsed since the start of the game");
ImGui::InputScalar("Deaths", ImGuiDataType_U16, &gSaveContext.deaths); ImGui::InputScalar("Deaths", ImGuiDataType_U16, &gSaveContext.deaths);
InsertHelpHoverText("Total number of deaths"); UIWidgets::InsertHelpHoverText("Total number of deaths");
bool bgsFlag = gSaveContext.bgsFlag != 0; bool bgsFlag = gSaveContext.bgsFlag != 0;
if (ImGui::Checkbox("Has BGS", &bgsFlag)) { if (ImGui::Checkbox("Has BGS", &bgsFlag)) {
gSaveContext.bgsFlag = bgsFlag; gSaveContext.bgsFlag = bgsFlag;
} }
InsertHelpHoverText("Is Biggoron sword unlocked? Replaces Giant's knife"); UIWidgets::InsertHelpHoverText("Is Biggoron sword unlocked? Replaces Giant's knife");
ImGui::InputScalar("Sword Health", ImGuiDataType_U16, &gSaveContext.swordHealth); ImGui::InputScalar("Sword Health", ImGuiDataType_U16, &gSaveContext.swordHealth);
InsertHelpHoverText("Giant's knife health. Default is 8. Must be >0 for Biggoron sword to work"); UIWidgets::InsertHelpHoverText("Giant's knife health. Default is 8. Must be >0 for Biggoron sword to work");
ImGui::InputScalar("Bgs Day Count", ImGuiDataType_S32, &gSaveContext.bgsDayCount); ImGui::InputScalar("Bgs Day Count", ImGuiDataType_S32, &gSaveContext.bgsDayCount);
InsertHelpHoverText("Total number of days elapsed since giving Biggoron the claim check"); UIWidgets::InsertHelpHoverText("Total number of days elapsed since giving Biggoron the claim check");
ImGui::InputScalar("Entrance Index", ImGuiDataType_S32, &gSaveContext.entranceIndex); ImGui::InputScalar("Entrance Index", ImGuiDataType_S32, &gSaveContext.entranceIndex);
InsertHelpHoverText("From which entrance did Link arrive?"); UIWidgets::InsertHelpHoverText("From which entrance did Link arrive?");
ImGui::InputScalar("Cutscene Index", ImGuiDataType_S32, &gSaveContext.cutsceneIndex); ImGui::InputScalar("Cutscene Index", ImGuiDataType_S32, &gSaveContext.cutsceneIndex);
InsertHelpHoverText("Which cutscene is this?"); UIWidgets::InsertHelpHoverText("Which cutscene is this?");
ImGui::InputScalar("Navi Timer", ImGuiDataType_U16, &gSaveContext.naviTimer); ImGui::InputScalar("Navi Timer", ImGuiDataType_U16, &gSaveContext.naviTimer);
InsertHelpHoverText("Navi wants to talk at 600 units, decides not to at 3000."); UIWidgets::InsertHelpHoverText("Navi wants to talk at 600 units, decides not to at 3000.");
ImGui::InputScalar("Timer 1 State", ImGuiDataType_S16, &gSaveContext.timer1State); ImGui::InputScalar("Timer 1 State", ImGuiDataType_S16, &gSaveContext.timer1State);
InsertHelpHoverText("Heat timer, race timer, etc. Has white font"); UIWidgets::InsertHelpHoverText("Heat timer, race timer, etc. Has white font");
ImGui::InputScalar("Timer 1 Value", ImGuiDataType_S16, &gSaveContext.timer1Value, &one, NULL); ImGui::InputScalar("Timer 1 Value", ImGuiDataType_S16, &gSaveContext.timer1Value, &one, NULL);
InsertHelpHoverText("Time, in seconds"); UIWidgets::InsertHelpHoverText("Time, in seconds");
ImGui::InputScalar("Timer 2 State", ImGuiDataType_S16, &gSaveContext.timer2State); ImGui::InputScalar("Timer 2 State", ImGuiDataType_S16, &gSaveContext.timer2State);
InsertHelpHoverText("Trade timer, Ganon collapse timer, etc. Has yellow font"); UIWidgets::InsertHelpHoverText("Trade timer, Ganon collapse timer, etc. Has yellow font");
ImGui::InputScalar("Timer 2 Value", ImGuiDataType_S16, &gSaveContext.timer2Value, &one, NULL); ImGui::InputScalar("Timer 2 Value", ImGuiDataType_S16, &gSaveContext.timer2Value, &one, NULL);
InsertHelpHoverText("Time, in seconds"); UIWidgets::InsertHelpHoverText("Time, in seconds");
const char* audioName; const char* audioName;
switch (gSaveContext.audioSetting) { switch (gSaveContext.audioSetting) {
@ -483,13 +483,13 @@ void DrawInfoTab() {
ImGui::EndCombo(); ImGui::EndCombo();
} }
InsertHelpHoverText("Sound setting"); UIWidgets::InsertHelpHoverText("Sound setting");
bool n64DDFlag = gSaveContext.n64ddFlag != 0; bool n64DDFlag = gSaveContext.n64ddFlag != 0;
if (ImGui::Checkbox("64 DD file?", &n64DDFlag)) { if (ImGui::Checkbox("64 DD file?", &n64DDFlag)) {
gSaveContext.n64ddFlag = n64DDFlag; gSaveContext.n64ddFlag = n64DDFlag;
} }
InsertHelpHoverText("WARNING! If you save, your file may be locked! Use caution!"); UIWidgets::InsertHelpHoverText("WARNING! If you save, your file may be locked! Use caution!");
if (ImGui::BeginCombo("Z Target Mode", gSaveContext.zTargetSetting ? "Hold" : "Switch")) { if (ImGui::BeginCombo("Z Target Mode", gSaveContext.zTargetSetting ? "Hold" : "Switch")) {
if (ImGui::Selectable("Switch")) { if (ImGui::Selectable("Switch")) {
@ -500,7 +500,7 @@ void DrawInfoTab() {
} }
ImGui::EndCombo(); ImGui::EndCombo();
} }
InsertHelpHoverText("Z-Targeting behavior"); UIWidgets::InsertHelpHoverText("Z-Targeting behavior");
ImGui::PushItemWidth(ImGui::GetFontSize() * 10); ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
@ -552,7 +552,7 @@ void DrawInventoryTab() {
static bool restrictToValid = true; static bool restrictToValid = true;
ImGui::Checkbox("Restrict to valid items", &restrictToValid); ImGui::Checkbox("Restrict to valid items", &restrictToValid);
InsertHelpHoverText("Restricts items and ammo to only what is possible to legally acquire in-game"); UIWidgets::InsertHelpHoverText("Restricts items and ammo to only what is possible to legally acquire in-game");
for (int32_t y = 0; y < 4; y++) { for (int32_t y = 0; y < 4; y++) {
for (int32_t x = 0; x < 6; x++) { for (int32_t x = 0; x < 6; x++) {
@ -594,7 +594,7 @@ void DrawInventoryTab() {
} }
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
SetLastItemHoverText("None"); UIWidgets::SetLastItemHoverText("None");
std::vector<ItemMapEntry> possibleItems; std::vector<ItemMapEntry> possibleItems;
if (restrictToValid) { if (restrictToValid) {
@ -624,14 +624,14 @@ void DrawInventoryTab() {
gSaveContext.inventory.items[selectedIndex] = slotEntry.id; gSaveContext.inventory.items[selectedIndex] = slotEntry.id;
// Set adult trade item flag if you're playing adult trade shuffle in rando // Set adult trade item flag if you're playing adult trade shuffle in rando
if (gSaveContext.n64ddFlag && if (gSaveContext.n64ddFlag &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE); OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE) &&
selectedIndex == SLOT_TRADE_ADULT && selectedIndex == SLOT_TRADE_ADULT &&
slotEntry.id >= ITEM_POCKET_EGG && slotEntry.id <= ITEM_CLAIM_CHECK) { slotEntry.id >= ITEM_POCKET_EGG && slotEntry.id <= ITEM_CLAIM_CHECK) {
gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(slotEntry.id); gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(slotEntry.id);
} }
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id));
} }
ImGui::EndPopup(); ImGui::EndPopup();
@ -725,7 +725,7 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Switch"); ImGui::Text("Switch");
InsertHelpHoverText("Permanently-saved switch flags"); UIWidgets::InsertHelpHoverText("Permanently-saved switch flags");
DrawFlagArray32("Switch", act->flags.swch); DrawFlagArray32("Switch", act->flags.swch);
}); });
@ -733,13 +733,13 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Temp Switch"); ImGui::Text("Temp Switch");
InsertHelpHoverText("Temporary switch flags. Unset on scene transitions"); UIWidgets::InsertHelpHoverText("Temporary switch flags. Unset on scene transitions");
DrawFlagArray32("Temp Switch", act->flags.tempSwch); DrawFlagArray32("Temp Switch", act->flags.tempSwch);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Clear"); ImGui::Text("Clear");
InsertHelpHoverText("Permanently-saved room-clear flags"); UIWidgets::InsertHelpHoverText("Permanently-saved room-clear flags");
DrawFlagArray32("Clear", act->flags.clear); DrawFlagArray32("Clear", act->flags.clear);
}); });
@ -747,13 +747,13 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Temp Clear"); ImGui::Text("Temp Clear");
InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions"); UIWidgets::InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions");
DrawFlagArray32("Temp Clear", act->flags.tempClear); DrawFlagArray32("Temp Clear", act->flags.tempClear);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Collect"); ImGui::Text("Collect");
InsertHelpHoverText("Permanently-saved collect flags"); UIWidgets::InsertHelpHoverText("Permanently-saved collect flags");
DrawFlagArray32("Collect", act->flags.collect); DrawFlagArray32("Collect", act->flags.collect);
}); });
@ -761,13 +761,13 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Temp Collect"); ImGui::Text("Temp Collect");
InsertHelpHoverText("Temporary collect flags. Unset on scene transitions"); UIWidgets::InsertHelpHoverText("Temporary collect flags. Unset on scene transitions");
DrawFlagArray32("Temp Collect", act->flags.tempCollect); DrawFlagArray32("Temp Collect", act->flags.tempCollect);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Chest"); ImGui::Text("Chest");
InsertHelpHoverText("Permanently-saved chest flags"); UIWidgets::InsertHelpHoverText("Permanently-saved chest flags");
DrawFlagArray32("Chest", act->flags.chest); DrawFlagArray32("Chest", act->flags.chest);
}); });
@ -781,7 +781,7 @@ void DrawFlagsTab() {
act->flags.collect = gSaveContext.sceneFlags[gGlobalCtx->sceneNum].collect; act->flags.collect = gSaveContext.sceneFlags[gGlobalCtx->sceneNum].collect;
act->flags.chest = gSaveContext.sceneFlags[gGlobalCtx->sceneNum].chest; act->flags.chest = gSaveContext.sceneFlags[gGlobalCtx->sceneNum].chest;
} }
SetLastItemHoverText("Load flags from saved scene flags. Normally happens on scene load"); UIWidgets::SetLastItemHoverText("Load flags from saved scene flags. Normally happens on scene load");
if (ImGui::Button("Save Flags")) { if (ImGui::Button("Save Flags")) {
gSaveContext.sceneFlags[gGlobalCtx->sceneNum].swch = act->flags.swch; gSaveContext.sceneFlags[gGlobalCtx->sceneNum].swch = act->flags.swch;
@ -789,7 +789,7 @@ void DrawFlagsTab() {
gSaveContext.sceneFlags[gGlobalCtx->sceneNum].collect = act->flags.collect; gSaveContext.sceneFlags[gGlobalCtx->sceneNum].collect = act->flags.collect;
gSaveContext.sceneFlags[gGlobalCtx->sceneNum].chest = act->flags.chest; gSaveContext.sceneFlags[gGlobalCtx->sceneNum].chest = act->flags.chest;
} }
SetLastItemHoverText("Save current scene flags. Normally happens on scene exit"); UIWidgets::SetLastItemHoverText("Save current scene flags. Normally happens on scene exit");
ImGui::EndGroup(); ImGui::EndGroup();
} else { } else {
@ -819,12 +819,12 @@ void DrawFlagsTab() {
if (ImGui::Button("Current")) { if (ImGui::Button("Current")) {
selectedSceneFlagMap = gGlobalCtx->sceneNum; selectedSceneFlagMap = gGlobalCtx->sceneNum;
} }
SetLastItemHoverText("Open flags for current scene"); UIWidgets::SetLastItemHoverText("Open flags for current scene");
} }
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Switch"); ImGui::Text("Switch");
InsertHelpHoverText("Switch flags"); UIWidgets::InsertHelpHoverText("Switch flags");
DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch); DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch);
}); });
@ -832,13 +832,13 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Clear"); ImGui::Text("Clear");
InsertHelpHoverText("Room-clear flags"); UIWidgets::InsertHelpHoverText("Room-clear flags");
DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear); DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Collect"); ImGui::Text("Collect");
InsertHelpHoverText("Collect flags"); UIWidgets::InsertHelpHoverText("Collect flags");
DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect); DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect);
}); });
@ -846,13 +846,13 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Chest"); ImGui::Text("Chest");
InsertHelpHoverText("Chest flags"); UIWidgets::InsertHelpHoverText("Chest flags");
DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest); DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Rooms"); ImGui::Text("Rooms");
InsertHelpHoverText("Flags for visted rooms"); UIWidgets::InsertHelpHoverText("Flags for visted rooms");
DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms); DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms);
}); });
@ -860,7 +860,7 @@ void DrawFlagsTab() {
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Floors"); ImGui::Text("Floors");
InsertHelpHoverText("Flags for visted floors"); UIWidgets::InsertHelpHoverText("Flags for visted floors");
DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors); DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors);
}); });
@ -916,7 +916,7 @@ void DrawFlagsTab() {
if (!(gSaveContext.n64ddFlag && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TOKENS))) { if (!(gSaveContext.n64ddFlag && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TOKENS))) {
static bool keepGsCountUpdated = true; static bool keepGsCountUpdated = true;
ImGui::Checkbox("Keep GS Count Updated", &keepGsCountUpdated); ImGui::Checkbox("Keep GS Count Updated", &keepGsCountUpdated);
InsertHelpHoverText("Automatically adjust the number of gold skulltula tokens acquired based on set flags."); UIWidgets::InsertHelpHoverText("Automatically adjust the number of gold skulltula tokens acquired based on set flags.");
int32_t gsCount = 0; int32_t gsCount = 0;
if (keepGsCountUpdated) { if (keepGsCountUpdated) {
for (int32_t gsFlagIndex = 0; gsFlagIndex < 6; gsFlagIndex++) { for (int32_t gsFlagIndex = 0; gsFlagIndex < 6; gsFlagIndex++) {
@ -930,85 +930,85 @@ void DrawFlagsTab() {
if (ImGui::TreeNode("Event Check Inf Flags")) { if (ImGui::TreeNode("Event Check Inf Flags")) {
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("0"); ImGui::Text("0");
InsertHelpHoverText("Mostly Kokiri Forest related"); UIWidgets::InsertHelpHoverText("Mostly Kokiri Forest related");
DrawFlagArray16("eci0", gSaveContext.eventChkInf[0]); DrawFlagArray16("eci0", gSaveContext.eventChkInf[0]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("1"); ImGui::Text("1");
InsertHelpHoverText("Mostly Lon Lon Ranch related"); UIWidgets::InsertHelpHoverText("Mostly Lon Lon Ranch related");
DrawFlagArray16("eci1", gSaveContext.eventChkInf[1]); DrawFlagArray16("eci1", gSaveContext.eventChkInf[1]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("2"); ImGui::Text("2");
InsertHelpHoverText("Dodongo Related?"); UIWidgets::InsertHelpHoverText("Dodongo Related?");
DrawFlagArray16("eci2", gSaveContext.eventChkInf[2]); DrawFlagArray16("eci2", gSaveContext.eventChkInf[2]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("3"); ImGui::Text("3");
InsertHelpHoverText("Mostly Zora related"); UIWidgets::InsertHelpHoverText("Mostly Zora related");
DrawFlagArray16("eci3", gSaveContext.eventChkInf[3]); DrawFlagArray16("eci3", gSaveContext.eventChkInf[3]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("4"); ImGui::Text("4");
InsertHelpHoverText("Random"); UIWidgets::InsertHelpHoverText("Random");
DrawFlagArray16("eci4", gSaveContext.eventChkInf[4]); DrawFlagArray16("eci4", gSaveContext.eventChkInf[4]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("5"); ImGui::Text("5");
InsertHelpHoverText("Mostly song learning related"); UIWidgets::InsertHelpHoverText("Mostly song learning related");
DrawFlagArray16("eci5", gSaveContext.eventChkInf[5]); DrawFlagArray16("eci5", gSaveContext.eventChkInf[5]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("6"); ImGui::Text("6");
InsertHelpHoverText("Random"); UIWidgets::InsertHelpHoverText("Random");
DrawFlagArray16("eci6", gSaveContext.eventChkInf[6]); DrawFlagArray16("eci6", gSaveContext.eventChkInf[6]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("7"); ImGui::Text("7");
InsertHelpHoverText("Boss Battle related"); UIWidgets::InsertHelpHoverText("Boss Battle related");
DrawFlagArray16("eci7", gSaveContext.eventChkInf[7]); DrawFlagArray16("eci7", gSaveContext.eventChkInf[7]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("8"); ImGui::Text("8");
InsertHelpHoverText("Mask related?"); UIWidgets::InsertHelpHoverText("Mask related?");
DrawFlagArray16("eci8", gSaveContext.eventChkInf[8]); DrawFlagArray16("eci8", gSaveContext.eventChkInf[8]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("9"); ImGui::Text("9");
InsertHelpHoverText("Mostly carpenter related"); UIWidgets::InsertHelpHoverText("Mostly carpenter related");
DrawFlagArray16("eci9", gSaveContext.eventChkInf[9]); DrawFlagArray16("eci9", gSaveContext.eventChkInf[9]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("A"); ImGui::Text("A");
InsertHelpHoverText("First-time overworld entrance cs related"); UIWidgets::InsertHelpHoverText("First-time overworld entrance cs related");
DrawFlagArray16("eci10", gSaveContext.eventChkInf[10]); DrawFlagArray16("eci10", gSaveContext.eventChkInf[10]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("B"); ImGui::Text("B");
InsertHelpHoverText("First-time dungeon entrance cs/trial cs related"); UIWidgets::InsertHelpHoverText("First-time dungeon entrance cs/trial cs related");
DrawFlagArray16("eci11", gSaveContext.eventChkInf[11]); DrawFlagArray16("eci11", gSaveContext.eventChkInf[11]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("C"); ImGui::Text("C");
InsertHelpHoverText("Random"); UIWidgets::InsertHelpHoverText("Random");
DrawFlagArray16("eci12", gSaveContext.eventChkInf[12]); DrawFlagArray16("eci12", gSaveContext.eventChkInf[12]);
}); });
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("D"); ImGui::Text("D");
InsertHelpHoverText("Frog songs/GS rewards"); UIWidgets::InsertHelpHoverText("Frog songs/GS rewards");
DrawFlagArray16("eci13", gSaveContext.eventChkInf[13]); DrawFlagArray16("eci13", gSaveContext.eventChkInf[13]);
}); });
@ -1061,7 +1061,7 @@ void DrawUpgrade(const std::string& categoryName, int32_t categoryId, const std:
ImGui::EndCombo(); ImGui::EndCombo();
} }
ImGui::PopID(); ImGui::PopID();
SetLastItemHoverText(categoryName.c_str()); UIWidgets::SetLastItemHoverText(categoryName.c_str());
} }
// Draws a combo that lets you choose and upgrade value from a popup grid of icons // Draws a combo that lets you choose and upgrade value from a popup grid of icons
@ -1086,7 +1086,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const
} }
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::PopStyleColor(); ImGui::PopStyleColor();
SetLastItemHoverText(categoryName.c_str()); UIWidgets::SetLastItemHoverText(categoryName.c_str());
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
if (ImGui::BeginPopup(upgradePopupPicker)) { if (ImGui::BeginPopup(upgradePopupPicker)) {
@ -1100,7 +1100,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const
Inventory_ChangeUpgrade(categoryId, pickerIndex); Inventory_ChangeUpgrade(categoryId, pickerIndex);
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
SetLastItemHoverText("None"); UIWidgets::SetLastItemHoverText("None");
} else { } else {
const ItemMapEntry& slotEntry = itemMapping[items[pickerIndex]]; const ItemMapEntry& slotEntry = itemMapping[items[pickerIndex]];
if (ImGui::ImageButton(SohImGui::GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), if (ImGui::ImageButton(SohImGui::GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0),
@ -1108,7 +1108,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const
Inventory_ChangeUpgrade(categoryId, pickerIndex); Inventory_ChangeUpgrade(categoryId, pickerIndex);
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id));
} }
} }
@ -1150,7 +1150,7 @@ void DrawEquipmentTab() {
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::PopID(); ImGui::PopID();
SetLastItemHoverText(SohUtils::GetItemName(entry.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id));
} }
const std::vector<uint8_t> bulletBagValues = { const std::vector<uint8_t> bulletBagValues = {
@ -1240,7 +1240,7 @@ void DrawQuestItemButton(uint32_t item) {
} }
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id));
} }
// Draws a toggleable icon for a dungeon item that is faded when disabled // Draws a toggleable icon for a dungeon item that is faded when disabled
@ -1258,7 +1258,7 @@ void DrawDungeonItemButton(uint32_t item, uint32_t scene) {
} }
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
SetLastItemHoverText(SohUtils::GetItemName(entry.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id));
} }
void DrawQuestStatusTab() { void DrawQuestStatusTab() {
@ -1305,11 +1305,11 @@ void DrawQuestStatusTab() {
} }
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id));
} }
ImGui::InputScalar("GS Count", ImGuiDataType_S16, &gSaveContext.inventory.gsTokens); ImGui::InputScalar("GS Count", ImGuiDataType_S16, &gSaveContext.inventory.gsTokens);
InsertHelpHoverText("Number of gold skulltula tokens aquired"); UIWidgets::InsertHelpHoverText("Number of gold skulltula tokens aquired");
uint32_t bitMask = 1 << QUEST_SKULL_TOKEN; uint32_t bitMask = 1 << QUEST_SKULL_TOKEN;
bool gsUnlocked = (bitMask & gSaveContext.inventory.questItems) != 0; bool gsUnlocked = (bitMask & gSaveContext.inventory.questItems) != 0;
@ -1320,7 +1320,7 @@ void DrawQuestStatusTab() {
gSaveContext.inventory.questItems &= ~bitMask; gSaveContext.inventory.questItems &= ~bitMask;
} }
} }
InsertHelpHoverText("If unlocked, enables showing the gold skulltula count in the quest status menu"); UIWidgets::InsertHelpHoverText("If unlocked, enables showing the gold skulltula count in the quest status menu");
int32_t pohCount = (gSaveContext.inventory.questItems & 0xF0000000) >> 28; int32_t pohCount = (gSaveContext.inventory.questItems & 0xF0000000) >> 28;
if (ImGui::BeginCombo("PoH count", std::to_string(pohCount).c_str())) { if (ImGui::BeginCombo("PoH count", std::to_string(pohCount).c_str())) {
@ -1332,7 +1332,7 @@ void DrawQuestStatusTab() {
} }
ImGui::EndCombo(); ImGui::EndCombo();
} }
InsertHelpHoverText("The number of pieces of heart acquired towards the next heart container"); UIWidgets::InsertHelpHoverText("The number of pieces of heart acquired towards the next heart container");
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Dungeon Items"); ImGui::Text("Dungeon Items");
@ -1457,7 +1457,7 @@ void DrawPlayerTab() {
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Link's Rotation"); ImGui::Text("Link's Rotation");
InsertHelpHoverText("For Link's rotation in relation to the world"); UIWidgets::InsertHelpHoverText("For Link's rotation in relation to the world");
ImGui::InputScalar("X Rot", ImGuiDataType_S16, &player->actor.world.rot.x); ImGui::InputScalar("X Rot", ImGuiDataType_S16, &player->actor.world.rot.x);
ImGui::SameLine(); ImGui::SameLine();
ImGui::InputScalar("Y Rot", ImGuiDataType_S16, &player->actor.world.rot.y); ImGui::InputScalar("Y Rot", ImGuiDataType_S16, &player->actor.world.rot.y);
@ -1467,7 +1467,7 @@ void DrawPlayerTab() {
DrawGroupWithBorder([&]() { DrawGroupWithBorder([&]() {
ImGui::Text("Link's Model Rotation"); ImGui::Text("Link's Model Rotation");
InsertHelpHoverText("For Link's actual model"); UIWidgets::InsertHelpHoverText("For Link's actual model");
ImGui::InputScalar("X ModRot", ImGuiDataType_S16, &player->actor.shape.rot.x); ImGui::InputScalar("X ModRot", ImGuiDataType_S16, &player->actor.shape.rot.x);
ImGui::SameLine(); ImGui::SameLine();
ImGui::InputScalar("Y ModRot", ImGuiDataType_S16, &player->actor.shape.rot.y); ImGui::InputScalar("Y ModRot", ImGuiDataType_S16, &player->actor.shape.rot.y);
@ -1476,19 +1476,19 @@ void DrawPlayerTab() {
}); });
ImGui::InputScalar("Linear Velocity", ImGuiDataType_Float, &player->linearVelocity); ImGui::InputScalar("Linear Velocity", ImGuiDataType_Float, &player->linearVelocity);
InsertHelpHoverText("Link's speed along the XZ plane"); UIWidgets::InsertHelpHoverText("Link's speed along the XZ plane");
ImGui::InputScalar("Y Velocity", ImGuiDataType_Float, &player->actor.velocity.y); ImGui::InputScalar("Y Velocity", ImGuiDataType_Float, &player->actor.velocity.y);
InsertHelpHoverText("Link's speed along the Y plane. Caps at -20"); UIWidgets::InsertHelpHoverText("Link's speed along the Y plane. Caps at -20");
ImGui::InputScalar("Wall Height", ImGuiDataType_Float, &player->wallHeight); ImGui::InputScalar("Wall Height", ImGuiDataType_Float, &player->wallHeight);
InsertHelpHoverText("Height used to determine whether Link can climb or grab a ledge at the top"); UIWidgets::InsertHelpHoverText("Height used to determine whether Link can climb or grab a ledge at the top");
ImGui::InputScalar("Invincibility Timer", ImGuiDataType_S8, &player->invincibilityTimer); ImGui::InputScalar("Invincibility Timer", ImGuiDataType_S8, &player->invincibilityTimer);
InsertHelpHoverText("Can't take damage while this is nonzero"); UIWidgets::InsertHelpHoverText("Can't take damage while this is nonzero");
ImGui::InputScalar("Gravity", ImGuiDataType_Float, &player->actor.gravity); ImGui::InputScalar("Gravity", ImGuiDataType_Float, &player->actor.gravity);
InsertHelpHoverText("Rate at which Link falls. Default -4.0f"); UIWidgets::InsertHelpHoverText("Rate at which Link falls. Default -4.0f");
if (ImGui::BeginCombo("Link Age on Load", gGlobalCtx->linkAgeOnLoad == 0 ? "Adult" : "Child")) { if (ImGui::BeginCombo("Link Age on Load", gGlobalCtx->linkAgeOnLoad == 0 ? "Adult" : "Child")) {
if (ImGui::Selectable("Adult")) { if (ImGui::Selectable("Adult")) {
@ -1500,7 +1500,7 @@ void DrawPlayerTab() {
ImGui::EndCombo(); ImGui::EndCombo();
} }
InsertHelpHoverText("This will change Link's age when you load a map"); UIWidgets::InsertHelpHoverText("This will change Link's age when you load a map");
ImGui::Separator(); ImGui::Separator();

View File

@ -3,7 +3,7 @@
#include <ultra64.h> #include <ultra64.h>
#include <z64.h> #include <z64.h>
#include "Cvar.h" #include <libultraship/Cvar.h>
#define MAX_CVARS 2048 #define MAX_CVARS 2048

View File

@ -14,7 +14,7 @@
#include <utility> #include <utility>
#include <set> #include <set>
#include <map> #include <map>
#include <Lib/spdlog/include/spdlog/spdlog.h> #include <spdlog/spdlog.h>
std::list<EntranceOverride> entranceOverrides = {}; std::list<EntranceOverride> entranceOverrides = {};
bool noRandomEntrances = false; bool noRandomEntrances = false;

View File

@ -17,7 +17,7 @@
#include <vector> #include <vector>
#include <list> #include <list>
#include <Lib/spdlog/include/spdlog/spdlog.h> #include <spdlog/spdlog.h>
using namespace CustomMessages; using namespace CustomMessages;
using namespace Logic; using namespace Logic;

View File

@ -12,7 +12,7 @@
#include "trial.hpp" #include "trial.hpp"
#include "entrance.hpp" #include "entrance.hpp"
#include "z64item.h" #include "z64item.h"
#include <Lib/spdlog/include/spdlog/spdlog.h> #include <spdlog/spdlog.h>
using namespace CustomMessages; using namespace CustomMessages;
using namespace Logic; using namespace Logic;

View File

@ -6,7 +6,7 @@
#include "shops.hpp" #include "shops.hpp"
#include "debug.hpp" #include "debug.hpp"
#include "keys.hpp" #include "keys.hpp"
#include <Lib/spdlog/include/spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include "../randomizerTypes.h" #include "../randomizerTypes.h"
//Location definitions //Location definitions

View File

@ -9,7 +9,7 @@
#include "settings.hpp" #include "settings.hpp"
#include "spoiler_log.hpp" #include "spoiler_log.hpp"
#include "z64item.h" #include "z64item.h"
#include <Lib/spdlog/include/spdlog/spdlog.h> #include <spdlog/spdlog.h>
using namespace Settings; using namespace Settings;

View File

@ -13,8 +13,8 @@
#include "spoiler_log.hpp" #include "spoiler_log.hpp"
#include "location_access.hpp" #include "location_access.hpp"
#include "debug.hpp" #include "debug.hpp"
#include <Lib/spdlog/include/spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include "soh/Enhancements/randomizer/randomizerTypes.h" #include "../../randomizer/randomizerTypes.h"
namespace { namespace {
bool seedChanged; bool seedChanged;

View File

@ -5,9 +5,9 @@
#include "location_access.hpp" #include "location_access.hpp"
#include "rando_main.hpp" #include "rando_main.hpp"
// #include <soh/Enhancements/randomizer.h> // #include <soh/Enhancements/randomizer.h>
#include <Cvar.h> #include <libultraship/Cvar.h>
#include <Window.h> #include <libultraship/Window.h>
#include <PR/ultra64/types.h> #include <ultra64/types.h>
#define TICKS_PER_SEC 268123480.0 #define TICKS_PER_SEC 268123480.0

View File

@ -2593,6 +2593,8 @@ namespace Settings {
NightGSExpectSuns.SetSelectedIndex(cvarSettings[RSK_SKULLS_SUNS_SONG]); NightGSExpectSuns.SetSelectedIndex(cvarSettings[RSK_SKULLS_SUNS_SONG]);
LinksPocketItem.SetSelectedIndex(cvarSettings[RSK_LINKS_POCKET]);
// RANDOTODO implement chest shuffle with keysanity // RANDOTODO implement chest shuffle with keysanity
// ShuffleChestMinigame.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME]); // ShuffleChestMinigame.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME]);

View File

@ -11,7 +11,7 @@
#include "utils.hpp" #include "utils.hpp"
#include "shops.hpp" #include "shops.hpp"
#include "hints.hpp" #include "hints.hpp"
#include "Lib/nlohmann/json.hpp" #include <nlohmann/json.hpp>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
@ -26,7 +26,7 @@
#include <filesystem> #include <filesystem>
#include <variables.h> #include <variables.h>
#include "Window.h" #include <libultraship/Window.h>
using json = nlohmann::json; using json = nlohmann::json;

View File

@ -1,21 +1,21 @@
#include "randomizer.h" #include "randomizer.h"
#include "Lib/nlohmann/json.hpp" #include <nlohmann/json.hpp>
#include "3drando/settings.hpp" #include "3drando/settings.hpp"
#include <fstream> #include <fstream>
#include <variables.h> #include <variables.h>
#include <macros.h> #include <macros.h>
#include <objects/gameplay_keep/gameplay_keep.h> #include <objects/gameplay_keep/gameplay_keep.h>
#include <functions.h> #include <functions.h>
#include <Cvar.h> #include <libultraship/Cvar.h>
#include <textures/icon_item_static/icon_item_static.h> #include <textures/icon_item_static/icon_item_static.h>
#include <textures/icon_item_24_static/icon_item_24_static.h> #include <textures/icon_item_24_static/icon_item_24_static.h>
#include "../libultraship/ImGuiImpl.h" #include <libultraship/ImGuiImpl.h>
#include <thread> #include <thread>
#include "3drando/rando_main.hpp" #include "3drando/rando_main.hpp"
#include <soh/Enhancements/debugger/ImGuiHelpers.h> #include "../../UIWidgets.hpp"
#include "Lib/ImGui/imgui_internal.h" #include <ImGui/imgui_internal.h>
#include <soh/Enhancements/custom-message/CustomMessageTypes.h> #include "../custom-message/CustomMessageTypes.h"
#include <soh/Enhancements/item-tables/ItemTableManager.h> #include "../item-tables/ItemTableManager.h"
#include <stdexcept> #include <stdexcept>
#include "randomizer_check_objects.h" #include "randomizer_check_objects.h"
#include <sstream> #include <sstream>
@ -567,13 +567,14 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
{ "Open Settings:Token Count", RSK_RAINBOW_BRIDGE_TOKEN_COUNT }, { "Open Settings:Token Count", RSK_RAINBOW_BRIDGE_TOKEN_COUNT },
{ "Open Settings:Random Ganon's Trials", RSK_RANDOM_TRIALS }, { "Open Settings:Random Ganon's Trials", RSK_RANDOM_TRIALS },
{ "Open Settings:Trial Count", RSK_TRIAL_COUNT }, { "Open Settings:Trial Count", RSK_TRIAL_COUNT },
{ "Shuffle Settings:Link's Pocket", RSK_LINKS_POCKET},
{ "Shuffle Settings:Shuffle Gerudo Card", RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD }, { "Shuffle Settings:Shuffle Gerudo Card", RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD },
{ "Shuffle Settings:Shopsanity", RSK_SHOPSANITY }, { "Shuffle Settings:Shopsanity", RSK_SHOPSANITY },
{ "Shuffle Settings:Scrub Shuffle", RSK_SHUFFLE_SCRUBS }, { "Shuffle Settings:Scrub Shuffle", RSK_SHUFFLE_SCRUBS },
{ "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS }, { "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS },
{ "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS }, { "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS },
{ "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE }, { "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE },
{ "Shuffle Settings:Shuffle Magic Beans", RSK_SHUFFLE_MAGIC_BEANS}, { "Shuffle Settings:Shuffle Magic Beans", RSK_SHUFFLE_MAGIC_BEANS },
{ "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD }, { "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD },
{ "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD }, { "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD },
{ "Start with Fairy Ocarina", RSK_STARTING_OCARINA }, { "Start with Fairy Ocarina", RSK_STARTING_OCARINA },
@ -1123,6 +1124,17 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
gSaveContext.randoSettings[index].value = 3; gSaveContext.randoSettings[index].value = 3;
} }
break; break;
case RSK_LINKS_POCKET:
if (it.value() == "Dungeon Reward") {
gSaveContext.randoSettings[index].value = 0;
} else if (it.value() == "Advancement") {
gSaveContext.randoSettings[index].value = 1;
} else if (it.value() == "Anything") {
gSaveContext.randoSettings[index].value = 2;
} else if (it.value() == "Nothing") {
gSaveContext.randoSettings[index].value = 3;
}
break;
} }
index++; index++;
} }
@ -1290,6 +1302,8 @@ void Randomizer::ParseRequiredTrialsFile(const char* spoilerFileName) {
return; return;
} }
this->trialsRequired.clear();
try { try {
json spoilerFileJson; json spoilerFileJson;
spoilerFileStream >> spoilerFileJson; spoilerFileStream >> spoilerFileJson;
@ -3987,6 +4001,9 @@ void GenerateRandomizerImgui() {
cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES] = CVar_GetS32("gRandomizeEnableGlitchCutscenes", 0); cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES] = CVar_GetS32("gRandomizeEnableGlitchCutscenes", 0);
cvarSettings[RSK_SKULLS_SUNS_SONG] = CVar_GetS32("gRandomizeGsExpectSunsSong", 0); cvarSettings[RSK_SKULLS_SUNS_SONG] = CVar_GetS32("gRandomizeGsExpectSunsSong", 0);
// Link's Pocket has to have a dungeon reward if the other rewards are shuffled to end of dungeon.
cvarSettings[RSK_LINKS_POCKET] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0) != 0 ?
CVar_GetS32("gRandomizeLinksPocket", 0) : 0;
// todo: this efficently when we build out cvar array support // todo: this efficently when we build out cvar array support
std::set<RandomizerCheck> excludedLocations; std::set<RandomizerCheck> excludedLocations;
@ -4082,7 +4099,7 @@ void DrawRandoEditor(bool& open) {
bool disableEditingRandoSettings = CVar_GetS32("gRandoGenerating", 0) || CVar_GetS32("gOnFileSelectNameEntry", 0); bool disableEditingRandoSettings = CVar_GetS32("gRandoGenerating", 0) || CVar_GetS32("gOnFileSelectNameEntry", 0);
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, disableEditingRandoSettings); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, disableEditingRandoSettings);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * (disableEditingRandoSettings ? 0.5f : 1.0f)); ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * (disableEditingRandoSettings ? 0.5f : 1.0f));
SohImGui::EnhancementCheckbox("Enable Randomizer", "gRandomizer"); UIWidgets::EnhancementCheckbox("Enable Randomizer", "gRandomizer");
if (CVar_GetS32("gRandomizer", 0)) { if (CVar_GetS32("gRandomizer", 0)) {
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
@ -4100,7 +4117,7 @@ void DrawRandoEditor(bool& open) {
// ImGui::Text("Settings File: %s", presetfilepath.c_str()); // ImGui::Text("Settings File: %s", presetfilepath.c_str());
} }
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGuiWindow* window = ImGui::GetCurrentWindow(); ImGuiWindow* window = ImGui::GetCurrentWindow();
static ImVec2 cellPadding(8.0f, 8.0f); static ImVec2 cellPadding(8.0f, 8.0f);
@ -4126,7 +4143,7 @@ void DrawRandoEditor(bool& open) {
// Forest // Forest
ImGui::Text(Settings::OpenForest.GetName().c_str()); ImGui::Text(Settings::OpenForest.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Closed - Kokiri sword & shield are required to access " "Closed - Kokiri sword & shield are required to access "
"the Deku Tree, and completing the Deku Tree is required to " "the Deku Tree, and completing the Deku Tree is required to "
"access the Hyrule Field exit.\n" "access the Hyrule Field exit.\n"
@ -4138,26 +4155,26 @@ void DrawRandoEditor(bool& open) {
"Open - Mido no longer blocks the path to the Deku Tree. Kokiri " "Open - Mido no longer blocks the path to the Deku Tree. Kokiri "
"boy no longer blocks the path out of the forest." "boy no longer blocks the path out of the forest."
); );
SohImGui::EnhancementCombobox("gRandomizeForest", randoForest, 3, 0); UIWidgets::EnhancementCombobox("gRandomizeForest", randoForest, 3, 0);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Kakariko Gate // Kakariko Gate
ImGui::Text(Settings::OpenKakariko.GetName().c_str()); ImGui::Text(Settings::OpenKakariko.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Closed - The gate will remain closed until Zelda's letter " "Closed - The gate will remain closed until Zelda's letter "
"is shown to the guard.\n" "is shown to the guard.\n"
"\n" "\n"
"Open - The gate is always open. The happy mask shop " "Open - The gate is always open. The happy mask shop "
"will open immediately after obtaining Zelda's letter." "will open immediately after obtaining Zelda's letter."
); );
SohImGui::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 0); UIWidgets::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 0);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Door of Time // Door of Time
ImGui::Text(Settings::OpenDoorOfTime.GetName().c_str()); ImGui::Text(Settings::OpenDoorOfTime.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Closed - The Ocarina of Time, the Song of Time and all " "Closed - The Ocarina of Time, the Song of Time and all "
"three spiritual stones are required to open the Door of Time.\n" "three spiritual stones are required to open the Door of Time.\n"
"\n" "\n"
@ -4166,13 +4183,13 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Open - The Door of Time is permanently open with no requirements." "Open - The Door of Time is permanently open with no requirements."
); );
SohImGui::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); UIWidgets::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Zora's Fountain // Zora's Fountain
ImGui::Text(Settings::ZorasFountain.GetName().c_str()); ImGui::Text(Settings::ZorasFountain.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Closed - King Zora obstructs the way to Zora's Fountain. " "Closed - King Zora obstructs the way to Zora's Fountain. "
"Ruto's letter must be shown as child Link in order to move " "Ruto's letter must be shown as child Link in order to move "
"him in both time periods.\n" "him in both time periods.\n"
@ -4183,9 +4200,9 @@ void DrawRandoEditor(bool& open) {
"Open - King Zora has already mweeped out of the way in both " "Open - King Zora has already mweeped out of the way in both "
"time periods. Ruto's Letter is removed from the item pool." "time periods. Ruto's Letter is removed from the item pool."
); );
SohImGui::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); UIWidgets::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0);
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::EndChild(); ImGui::EndChild();
@ -4197,7 +4214,7 @@ void DrawRandoEditor(bool& open) {
// Gerudo Fortress // Gerudo Fortress
ImGui::Text("Gerudo Fortress Carpenters"); ImGui::Text("Gerudo Fortress Carpenters");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Sets the amount of carpenters required to repair the bridge " "Sets the amount of carpenters required to repair the bridge "
"in Gerudo Valley.\n" "in Gerudo Valley.\n"
"\n" "\n"
@ -4207,13 +4224,13 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Open - The bridge is repaired from the start." "Open - The bridge is repaired from the start."
); );
SohImGui::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 0); UIWidgets::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 0);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Rainbow Bridge // Rainbow Bridge
ImGui::Text("Rainbow Bridge Requirements"); ImGui::Text("Rainbow Bridge Requirements");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Alters the requirements to open the bridge to Ganon's Castle.\n" "Alters the requirements to open the bridge to Ganon's Castle.\n"
"\n" "\n"
"Vanilla - Obtain the Shadow Medallion, Spirit Medallion and Light Arrows.\n" "Vanilla - Obtain the Shadow Medallion, Spirit Medallion and Light Arrows.\n"
@ -4234,7 +4251,7 @@ void DrawRandoEditor(bool& open) {
"Tokens - Obtain the specified amount of Skulltula tokens." "Tokens - Obtain the specified amount of Skulltula tokens."
); );
SohImGui::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 0); UIWidgets::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 0);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
switch (CVar_GetS32("gRandomizeRainbowBridge", 0)) { switch (CVar_GetS32("gRandomizeRainbowBridge", 0)) {
case 0: case 0:
@ -4243,37 +4260,37 @@ void DrawRandoEditor(bool& open) {
break; break;
case 2: case 2:
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
SohImGui::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", UIWidgets::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount",
"gRandomizeStoneCount", 1, 3, "", 3, true); "gRandomizeStoneCount", 1, 3, "", 3, true);
break; break;
case 3: case 3:
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
SohImGui::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", UIWidgets::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount",
"gRandomizeMedallionCount", 1, 6, "", 6, true); "gRandomizeMedallionCount", 1, 6, "", 6, true);
break; break;
case 4: case 4:
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
SohImGui::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", UIWidgets::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount",
"gRandomizeRewardCount", 1, 9, "", 9, true); "gRandomizeRewardCount", 1, 9, "", 9, true);
break; break;
case 5: case 5:
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
SohImGui::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", UIWidgets::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount",
"gRandomizeDungeonCount", 1, 8, "", 8, true); "gRandomizeDungeonCount", 1, 8, "", 8, true);
break; break;
case 6: case 6:
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
SohImGui::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount", UIWidgets::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount",
"gRandomizeTokenCount", 1, 100, "", 100, true); "gRandomizeTokenCount", 1, 100, "", 100, true);
break; break;
} }
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Ganon's Trials // Ganon's Trials
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
ImGui::Text("Ganon's Trials"); ImGui::Text("Ganon's Trials");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Sets the number of Ganon's Trials required to dispel the barrier.\n" "Sets the number of Ganon's Trials required to dispel the barrier.\n"
"\n" "\n"
"Skip - No Trials are required and the barrier is already dispelled.\n" "Skip - No Trials are required and the barrier is already dispelled.\n"
@ -4283,16 +4300,16 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Random Number - A Random number and set of trials will be required." "Random Number - A Random number and set of trials will be required."
); );
SohImGui::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, 3, 0); UIWidgets::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, 3, 0);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
if (CVar_GetS32("gRandomizeGanonTrial", 0) == 1) { if (CVar_GetS32("gRandomizeGanonTrial", 0) == 1) {
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
SohImGui::EnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount", UIWidgets::EnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount",
"gRandomizeGanonTrialCount", 1, 6, "", 6, true); "gRandomizeGanonTrialCount", 1, 6, "", 6, true);
InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); UIWidgets::InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower.");
} }
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::EndChild(); ImGui::EndChild();
@ -4304,7 +4321,7 @@ void DrawRandoEditor(bool& open) {
ImGui::Text("Coming soon"); ImGui::Text("Coming soon");
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::EndChild(); ImGui::EndChild();
@ -4334,7 +4351,7 @@ void DrawRandoEditor(bool& open) {
// Shuffle Songs // Shuffle Songs
ImGui::Text(Settings::ShuffleSongs.GetName().c_str()); ImGui::Text(Settings::ShuffleSongs.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Song locations - Songs will only appear at locations that normally teach songs.\n" "Song locations - Songs will only appear at locations that normally teach songs.\n"
"\n" "\n"
"Dungeon rewards - Songs appear after beating a major dungeon boss.\n" "Dungeon rewards - Songs appear after beating a major dungeon boss.\n"
@ -4346,13 +4363,13 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Anywhere - Songs can appear at any location." "Anywhere - Songs can appear at any location."
); );
SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); UIWidgets::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Shuffle Tokens // Shuffle Tokens
ImGui::Text(Settings::Tokensanity.GetName().c_str()); ImGui::Text(Settings::Tokensanity.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Shuffles Golden Skulltula Tokens into the item pool. This means " "Shuffles Golden Skulltula Tokens into the item pool. This means "
"Golden Skulltulas can contain other items as well.\n" "Golden Skulltulas can contain other items as well.\n"
"\n" "\n"
@ -4364,53 +4381,53 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"All Tokens - Shuffle all 100 GS tokens." "All Tokens - Shuffle all 100 GS tokens."
); );
SohImGui::EnhancementCombobox("gRandomizeShuffleTokens", randoTokensanity, 4, 0); UIWidgets::EnhancementCombobox("gRandomizeShuffleTokens", randoTokensanity, 4, 0);
ImGui::Dummy(ImVec2(0,0)); ImGui::Dummy(ImVec2(0,0));
SohImGui::EnhancementCheckbox("Nighttime GS expect Sun's Song", "gRandomizeGsExpectSunsSong"); UIWidgets::EnhancementCheckbox("Nighttime GS expect Sun's Song", "gRandomizeGsExpectSunsSong");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"All Golden Skulltulas that require nighttime to appear will only be " "All Golden Skulltulas that require nighttime to appear will only be "
"expected to be collected after getting Sun's Song." "expected to be collected after getting Sun's Song."
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Shuffle Kokiri Sword // Shuffle Kokiri Sword
// Disabled when Start with Kokiri Sword is active // Disabled when Start with Kokiri Sword is active
bool disableShuffleKokiriSword = CVar_GetS32("gRandomizeStartingKokiriSword", 0); bool disableShuffleKokiriSword = CVar_GetS32("gRandomizeStartingKokiriSword", 0);
const char* disableShuffleKokiriSwordText = "This option is disabled because \"Start with Kokiri Sword\" is enabled."; const char* disableShuffleKokiriSwordText = "This option is disabled because \"Start with Kokiri Sword\" is enabled.";
SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), "gRandomizeShuffleKokiriSword", UIWidgets::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), "gRandomizeShuffleKokiriSword",
disableShuffleKokiriSword, disableShuffleKokiriSwordText); disableShuffleKokiriSword, disableShuffleKokiriSwordText);
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Shuffles the Kokiri Sword into the item pool.\n" "Shuffles the Kokiri Sword into the item pool.\n"
"\n" "\n"
"This will require the use of sticks until the Kokiri Sword is found." "This will require the use of sticks until the Kokiri Sword is found."
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Shuffle Ocarinas // Shuffle Ocarinas
// Disabled when Start with Ocarina is active // Disabled when Start with Ocarina is active
bool disableShuffleOcarinas = CVar_GetS32("gRandomizeStartingOcarina", 0); bool disableShuffleOcarinas = CVar_GetS32("gRandomizeStartingOcarina", 0);
const char* disableShuffleOcarinasText = "This option is disabled because \"Start with Fairy Ocarina\" is enabled."; const char* disableShuffleOcarinasText = "This option is disabled because \"Start with Fairy Ocarina\" is enabled.";
SohImGui::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), "gRandomizeShuffleOcarinas", UIWidgets::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), "gRandomizeShuffleOcarinas",
disableShuffleOcarinas, disableShuffleOcarinasText); disableShuffleOcarinas, disableShuffleOcarinasText);
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n" "Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n"
"\n" "\n"
"This will require finding an Ocarina before being able to play songs." "This will require finding an Ocarina before being able to play songs."
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Shuffle Weird Egg // Shuffle Weird Egg
// Disabled when Skip Child Zelda is active // Disabled when Skip Child Zelda is active
bool disableShuffleWeirdEgg = CVar_GetS32("gRandomizeSkipChildZelda", 0); bool disableShuffleWeirdEgg = CVar_GetS32("gRandomizeSkipChildZelda", 0);
const char* disableShuffleWeirdEggText = "This option is disabled because \"Skip Child Zelda\" is enabled."; const char* disableShuffleWeirdEggText = "This option is disabled because \"Skip Child Zelda\" is enabled.";
SohImGui::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), "gRandomizeShuffleWeirdEgg", UIWidgets::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), "gRandomizeShuffleWeirdEgg",
disableShuffleWeirdEgg, disableShuffleWeirdEggText); disableShuffleWeirdEgg, disableShuffleWeirdEggText);
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Shuffles the Weird Egg from Malon in to the item pool. Enabling " "Shuffles the Weird Egg from Malon in to the item pool. Enabling "
"\"Skip Child Zelda\" disables this feature.\n" "\"Skip Child Zelda\" disables this feature.\n"
"\n" "\n"
@ -4422,19 +4439,19 @@ void DrawRandoEditor(bool& open) {
" - Happy Mask Shop sidequest\n" " - Happy Mask Shop sidequest\n"
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Shuffle Gerudo Membership Card // Shuffle Gerudo Membership Card
SohImGui::EnhancementCheckbox(Settings::ShuffleGerudoToken.GetName().c_str(), UIWidgets::EnhancementCheckbox(Settings::ShuffleGerudoToken.GetName().c_str(),
"gRandomizeShuffleGerudoToken"); "gRandomizeShuffleGerudoToken");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Shuffles the Gerudo Membership Card into the item pool.\n" "Shuffles the Gerudo Membership Card into the item pool.\n"
"\n" "\n"
"The Gerudo Card is required to enter the Gerudo Training Grounds, opening " "The Gerudo Card is required to enter the Gerudo Training Grounds, opening "
"the gate to Haunted Wasteland and the Horseback Archery minigame." "the gate to Haunted Wasteland and the Horseback Archery minigame."
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::EndChild(); ImGui::EndChild();
@ -4462,7 +4479,7 @@ void DrawRandoEditor(bool& open) {
// Shuffle Scrubs // Shuffle Scrubs
ImGui::Text(Settings::Scrubsanity.GetName().c_str()); ImGui::Text(Settings::Scrubsanity.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game " "Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game "
"(PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n" "(PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n"
"\n" "\n"
@ -4471,27 +4488,27 @@ void DrawRandoEditor(bool& open) {
"Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n" "Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n"
"\n" "\n"
"Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n"); "Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n");
SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0); UIWidgets::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Shuffle Cows // Shuffle Cows
SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows"); UIWidgets::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows");
InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); UIWidgets::InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them.");
PaddedSeparator(); UIWidgets::PaddedSeparator();
SohImGui::EnhancementCheckbox(Settings::ShuffleMagicBeans.GetName().c_str(), "gRandomizeShuffleBeans"); UIWidgets::EnhancementCheckbox(Settings::ShuffleMagicBeans.GetName().c_str(), "gRandomizeShuffleBeans");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Enabling this adds a pack of 10 beans to the item pool and changes the Magic Bean " "Enabling this adds a pack of 10 beans to the item pool and changes the Magic Bean "
"Salesman to sell a random item at a price of 60 rupees." "Salesman to sell a random item at a price of 60 rupees."
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Shuffle Frog Song Rupees // Shuffle Frog Song Rupees
SohImGui::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), "gRandomizeShuffleFrogSongRupees"); UIWidgets::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), "gRandomizeShuffleFrogSongRupees");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Shuffles 5 Purple Rupees into to the item pool, and allows\n" "Shuffles 5 Purple Rupees into to the item pool, and allows\n"
"you to earn items by playing songs at the Frog Choir.\n" "you to earn items by playing songs at the Frog Choir.\n"
"\n" "\n"
@ -4499,12 +4516,12 @@ void DrawRandoEditor(bool& open) {
"the Song of Storms and the frog song minigame." "the Song of Storms and the frog song minigame."
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Shuffle Adult Trade Quest // Shuffle Adult Trade Quest
SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), UIWidgets::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(),
"gRandomizeShuffleAdultTrade"); "gRandomizeShuffleAdultTrade");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Adds all of the adult trade quest items into the pool, each of which " "Adds all of the adult trade quest items into the pool, each of which "
"can be traded for a unique reward.\n" "can be traded for a unique reward.\n"
"\n" "\n"
@ -4515,7 +4532,7 @@ void DrawRandoEditor(bool& open) {
"If disabled, only the Claim Check will be found in the pool." "If disabled, only the Claim Check will be found in the pool."
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::EndChild(); ImGui::EndChild();
@ -4528,7 +4545,7 @@ void DrawRandoEditor(bool& open) {
// Shuffle Dungeon Rewards // Shuffle Dungeon Rewards
ImGui::Text(Settings::ShuffleRewards.GetName().c_str()); ImGui::Text(Settings::ShuffleRewards.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Shuffles the location of spiritual stones and medallions.\n" "Shuffles the location of spiritual stones and medallions.\n"
"\n" "\n"
"End of dungeons - Spiritual stones and medallions will be given as rewards " "End of dungeons - Spiritual stones and medallions will be given as rewards "
@ -4540,13 +4557,13 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Anywhere - Spiritual stones and medallions can appear anywhere." "Anywhere - Spiritual stones and medallions can appear anywhere."
); );
SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0); UIWidgets::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Maps & Compasses // Maps & Compasses
ImGui::Text(Settings::MapsAndCompasses.GetName().c_str()); ImGui::Text(Settings::MapsAndCompasses.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Start with - You will start with Maps & Compasses from all dungeons.\n" "Start with - You will start with Maps & Compasses from all dungeons.\n"
"\n" "\n"
"Vanilla - Maps & Compasses will appear in their vanilla locations.\n" "Vanilla - Maps & Compasses will appear in their vanilla locations.\n"
@ -4559,13 +4576,13 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Anywhere - Maps & Compasses can appear anywhere in the world." "Anywhere - Maps & Compasses can appear anywhere in the world."
); );
SohImGui::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 2); UIWidgets::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 2);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Keysanity // Keysanity
ImGui::Text(Settings::Keysanity.GetName().c_str()); ImGui::Text(Settings::Keysanity.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Start with - You will start with all Small Keys from all dungeons.\n" "Start with - You will start with all Small Keys from all dungeons.\n"
"\n" "\n"
"Vanilla - Small Keys will appear in their vanilla locations.\n" "Vanilla - Small Keys will appear in their vanilla locations.\n"
@ -4578,13 +4595,13 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Anywhere - Small Keys can appear anywhere in the world." "Anywhere - Small Keys can appear anywhere in the world."
); );
SohImGui::EnhancementCombobox("gRandomizeKeysanity", randoShuffleSmallKeys, 6, 2); UIWidgets::EnhancementCombobox("gRandomizeKeysanity", randoShuffleSmallKeys, 6, 2);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Gerudo Keys // Gerudo Keys
ImGui::Text(Settings::GerudoKeys.GetName().c_str()); ImGui::Text(Settings::GerudoKeys.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Vanilla - Thieve's Hideout Keys will appear in their vanilla locations.\n" "Vanilla - Thieve's Hideout Keys will appear in their vanilla locations.\n"
"\n" "\n"
"Any dungeon - Thieve's Hideout Keys can only appear inside of any dungon.\n" "Any dungeon - Thieve's Hideout Keys can only appear inside of any dungon.\n"
@ -4593,13 +4610,13 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Anywhere - Thieve's Hideout Keys can appear anywhere in the world." "Anywhere - Thieve's Hideout Keys can appear anywhere in the world."
); );
SohImGui::EnhancementCombobox("gRandomizeGerudoKeys", randoShuffleGerudoFortressKeys, 4, 0); UIWidgets::EnhancementCombobox("gRandomizeGerudoKeys", randoShuffleGerudoFortressKeys, 4, 0);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Boss Keysanity // Boss Keysanity
ImGui::Text(Settings::BossKeysanity.GetName().c_str()); ImGui::Text(Settings::BossKeysanity.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Start with - You will start with Boss keys from all dungeons.\n" "Start with - You will start with Boss keys from all dungeons.\n"
"\n" "\n"
"Vanilla - Boss Keys will appear in their vanilla locations.\n" "Vanilla - Boss Keys will appear in their vanilla locations.\n"
@ -4612,13 +4629,13 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Anywhere - Boss Keys can appear anywhere in the world." "Anywhere - Boss Keys can appear anywhere in the world."
); );
SohImGui::EnhancementCombobox("gRandomizeBossKeysanity", randoShuffleBossKeys, 6, 2); UIWidgets::EnhancementCombobox("gRandomizeBossKeysanity", randoShuffleBossKeys, 6, 2);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Ganon's Boss Key // Ganon's Boss Key
ImGui::Text(Settings::GanonsBossKey.GetName().c_str()); ImGui::Text(Settings::GanonsBossKey.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Vanilla - Ganon's Boss Key will appear in the vanilla location.\n" "Vanilla - Ganon's Boss Key will appear in the vanilla location.\n"
"\n" "\n"
"Own dungeon - Ganon's Boss Key can appear anywhere inside Ganon's Castle.\n" "Own dungeon - Ganon's Boss Key can appear anywhere inside Ganon's Castle.\n"
@ -4631,9 +4648,9 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Anywhere - Ganon's Boss Key Key can appear anywhere in the world." "Anywhere - Ganon's Boss Key Key can appear anywhere in the world."
); );
SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 6, 1); UIWidgets::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 6, 1);
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::EndChild(); ImGui::EndChild();
@ -4660,53 +4677,53 @@ void DrawRandoEditor(bool& open) {
ImGui::BeginChild("ChildTimeSavers", ImVec2(0, -8)); ImGui::BeginChild("ChildTimeSavers", ImVec2(0, -8));
// Cuccos to return // Cuccos to return
SohImGui::EnhancementSliderInt("Cuccos to return: %d", "##RandoCuccosToReturn", UIWidgets::EnhancementSliderInt("Cuccos to return: %d", "##RandoCuccosToReturn",
"gRandomizeCuccosToReturn", 0, 7, "", 7, true); "gRandomizeCuccosToReturn", 0, 7, "", 7, true);
InsertHelpHoverText("The amount of cuccos needed to claim the reward from Anju the cucco lady"); UIWidgets::InsertHelpHoverText("The amount of cuccos needed to claim the reward from Anju the cucco lady");
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Big Poe Target Count // Big Poe Target Count
SohImGui::EnhancementSliderInt("Big Poe Target Count: %d", "##RandoBigPoeTargetCount", UIWidgets::EnhancementSliderInt("Big Poe Target Count: %d", "##RandoBigPoeTargetCount",
"gRandomizeBigPoeTargetCount", 1, 10, "", 10, true); "gRandomizeBigPoeTargetCount", 1, 10, "", 10, true);
InsertHelpHoverText("The Poe collector will give a reward for turning in this many Big Poes."); UIWidgets::InsertHelpHoverText("The Poe collector will give a reward for turning in this many Big Poes.");
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Skip child stealth // Skip child stealth
// Disabled when Skip Child Zelda is active // Disabled when Skip Child Zelda is active
bool disableChildStealth = CVar_GetS32("gRandomizeSkipChildZelda", 0); bool disableChildStealth = CVar_GetS32("gRandomizeSkipChildZelda", 0);
const char* disableChildStealthText = "This option is disabled because \"Skip Child Zelda\" is enabled"; const char* disableChildStealthText = "This option is disabled because \"Skip Child Zelda\" is enabled";
SohImGui::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), "gRandomizeSkipChildStealth", disableChildStealth, disableChildStealthText); UIWidgets::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), "gRandomizeSkipChildStealth", disableChildStealth, disableChildStealthText);
InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); UIWidgets::InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards.");
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Skip child zelda // Skip child zelda
SohImGui::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); UIWidgets::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda");
InsertHelpHoverText("Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up " UIWidgets::InsertHelpHoverText("Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up "
"until after meeting Zelda. Disables the ability to shuffle Weird Egg."); "until after meeting Zelda. Disables the ability to shuffle Weird Egg.");
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Skip Epona race // Skip Epona race
SohImGui::EnhancementCheckbox(Settings::SkipEponaRace.GetName().c_str(), "gRandomizeSkipEponaRace"); UIWidgets::EnhancementCheckbox(Settings::SkipEponaRace.GetName().c_str(), "gRandomizeSkipEponaRace");
InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); UIWidgets::InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo.");
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Skip tower escape // Skip tower escape
SohImGui::EnhancementCheckbox(Settings::SkipTowerEscape.GetName().c_str(), "gRandomizeSkipTowerEscape"); UIWidgets::EnhancementCheckbox(Settings::SkipTowerEscape.GetName().c_str(), "gRandomizeSkipTowerEscape");
InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); UIWidgets::InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped.");
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Complete mask quest // Complete mask quest
SohImGui::EnhancementCheckbox(Settings::CompleteMaskQuest.GetName().c_str(), UIWidgets::EnhancementCheckbox(Settings::CompleteMaskQuest.GetName().c_str(),
"gRandomizeCompleteMaskQuest"); "gRandomizeCompleteMaskQuest");
InsertHelpHoverText("Once the happy mask shop is opened, all masks will be available to be borrowed."); UIWidgets::InsertHelpHoverText("Once the happy mask shop is opened, all masks will be available to be borrowed.");
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::EndChild(); ImGui::EndChild();
@ -4718,7 +4735,7 @@ void DrawRandoEditor(bool& open) {
// Item Pool Settings // Item Pool Settings
ImGui::Text(Settings::ItemPoolValue.GetName().c_str()); ImGui::Text(Settings::ItemPoolValue.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Sets how many major items appear in the item pool.\n" "Sets how many major items appear in the item pool.\n"
"\n" "\n"
"Plentiful - Extra major items are added to the pool.\n" "Plentiful - Extra major items are added to the pool.\n"
@ -4729,12 +4746,12 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Minimal - Most excess items are removed." "Minimal - Most excess items are removed."
); );
SohImGui::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); UIWidgets::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Ice Traps // Ice Traps
ImGui::Text(Settings::IceTrapValue.GetName().c_str()); ImGui::Text(Settings::IceTrapValue.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Sets how many items are replaced by ice traps.\n" "Sets how many items are replaced by ice traps.\n"
"\n" "\n"
"Off - No ice traps.\n" "Off - No ice traps.\n"
@ -4748,13 +4765,13 @@ void DrawRandoEditor(bool& open) {
"Onslaught - All junk items will be replaced by Ice Traps, even those " "Onslaught - All junk items will be replaced by Ice Traps, even those "
"in the base pool." "in the base pool."
); );
SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); UIWidgets::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Gossip Stone Hints // Gossip Stone Hints
ImGui::Text(Settings::GossipStoneHints.GetName().c_str()); ImGui::Text(Settings::GossipStoneHints.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Allows Gossip Stones to provide hints on item locations. Hints mentioning " "Allows Gossip Stones to provide hints on item locations. Hints mentioning "
"\"Way of the Hero\" indicate a location that holds an item required to beat " "\"Way of the Hero\" indicate a location that holds an item required to beat "
"the seed.\n" "the seed.\n"
@ -4766,13 +4783,13 @@ void DrawRandoEditor(bool& open) {
"Need Stone of Agony - Hints are only available after obtaining the Stone of Agony.\n" "Need Stone of Agony - Hints are only available after obtaining the Stone of Agony.\n"
"\n" "\n"
"Need Mask of Truth - Hints are only available whilst wearing the Mask of Truth.\n"); "Need Mask of Truth - Hints are only available whilst wearing the Mask of Truth.\n");
SohImGui::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1); UIWidgets::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1);
if (CVar_GetS32("gRandomizeGossipStoneHints", 1) != 0) { if (CVar_GetS32("gRandomizeGossipStoneHints", 1) != 0) {
// Hint Clarity // Hint Clarity
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
ImGui::Indent(); ImGui::Indent();
ImGui::Text(Settings::ClearerHints.GetName().c_str()); ImGui::Text(Settings::ClearerHints.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Sets the difficulty of hints.\n" "Sets the difficulty of hints.\n"
"\n" "\n"
"Obscure - Hints are unique for each item, but the writing may be cryptic.\n" "Obscure - Hints are unique for each item, but the writing may be cryptic.\n"
@ -4784,12 +4801,12 @@ void DrawRandoEditor(bool& open) {
"Clear - Hints are clearly written and are unique for each item.\n" "Clear - Hints are clearly written and are unique for each item.\n"
"Ex: Kokiri Sword > the Kokiri Sword" "Ex: Kokiri Sword > the Kokiri Sword"
); );
SohImGui::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2); UIWidgets::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2);
// Hint Distribution // Hint Distribution
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
ImGui::Text(Settings::HintDistribution.GetName().c_str()); ImGui::Text(Settings::HintDistribution.GetName().c_str());
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Sets how many hints will be useful.\n" "Sets how many hints will be useful.\n"
"\n" "\n"
"Useless - Only junk hints.\n" "Useless - Only junk hints.\n"
@ -4800,11 +4817,11 @@ void DrawRandoEditor(bool& open) {
"\n" "\n"
"Very Strong - Many powerful hints." "Very Strong - Many powerful hints."
); );
SohImGui::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1); UIWidgets::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1);
ImGui::Unindent(); ImGui::Unindent();
} }
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::EndChild(); ImGui::EndChild();
@ -4815,14 +4832,14 @@ void DrawRandoEditor(bool& open) {
ImGui::BeginChild("ChildAdditionalFeatures", ImVec2(0, -8)); ImGui::BeginChild("ChildAdditionalFeatures", ImVec2(0, -8));
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
SohImGui::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); UIWidgets::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets");
InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); UIWidgets::InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees.");
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Bombchus in Logic // Bombchus in Logic
SohImGui::EnhancementCheckbox(Settings::BombchusInLogic.GetName().c_str(), "gRandomizeBombchusInLogic"); UIWidgets::EnhancementCheckbox(Settings::BombchusInLogic.GetName().c_str(), "gRandomizeBombchusInLogic");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Bombchus are properly considered in logic.\n" "Bombchus are properly considered in logic.\n"
"\n" "\n"
"The first Bombchu pack will always be 20, and subsequent packs will be " "The first Bombchu pack will always be 20, and subsequent packs will be "
@ -4832,23 +4849,23 @@ void DrawRandoEditor(bool& open) {
"Bombchu Bowling is opened by obtaining Bombchus." "Bombchu Bowling is opened by obtaining Bombchus."
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
SohImGui::EnhancementCheckbox("WIP - Blue Fire Arrows", "gRandomizeBlueIceArrows", true, "In development"); UIWidgets::EnhancementCheckbox("WIP - Blue Fire Arrows", "gRandomizeBlueIceArrows", true, "In development");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Ice Arrows act like Blue Fire, making them able to melt red ice. " "Ice Arrows act like Blue Fire, making them able to melt red ice. "
"Item placement logic will respect this option, so it might be required to use this to progress." "Item placement logic will respect this option, so it might be required to use this to progress."
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
SohImGui::EnhancementCheckbox("WIP - Sunlight Arrows", "gRandomizeSunlightArrows", true, "In development"); UIWidgets::EnhancementCheckbox("WIP - Sunlight Arrows", "gRandomizeSunlightArrows", true, "In development");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. " "Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. "
"Item placement logic will respect this option, so it might be required to use this to progress." "Item placement logic will respect this option, so it might be required to use this to progress."
); );
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::EndChild(); ImGui::EndChild();
@ -4916,7 +4933,7 @@ void DrawRandoEditor(bool& open) {
excludedLocationString += ","; excludedLocationString += ",";
} }
CVar_SetString("gRandomizeExcludedLocations", excludedLocationString.c_str()); CVar_SetString("gRandomizeExcludedLocations", excludedLocationString.c_str());
SohImGui::needs_save = true; SohImGui::RequestCvarSaveOnNextTick();
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text(locationIt.rcShortName.c_str()); ImGui::Text(locationIt.rcShortName.c_str());
@ -4957,7 +4974,7 @@ void DrawRandoEditor(bool& open) {
excludedLocationString += ","; excludedLocationString += ",";
} }
CVar_SetString("gRandomizeExcludedLocations", excludedLocationString.c_str()); CVar_SetString("gRandomizeExcludedLocations", excludedLocationString.c_str());
SohImGui::needs_save = true; SohImGui::RequestCvarSaveOnNextTick();
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text(locationIt.rcShortName.c_str()); ImGui::Text(locationIt.rcShortName.c_str());
@ -4985,19 +5002,19 @@ void DrawRandoEditor(bool& open) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::PushItemWidth(170.0); ImGui::PushItemWidth(170.0);
ImGui::Text("Logic Rules"); ImGui::Text("Logic Rules");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"Glitchless - No glitches are required, but may require some minor tricks.\n" "Glitchless - No glitches are required, but may require some minor tricks.\n"
"\n" "\n"
"No logic - Item placement is completely random. MAY BE IMPOSSIBLE TO BEAT." "No logic - Item placement is completely random. MAY BE IMPOSSIBLE TO BEAT."
); );
SohImGui::EnhancementCombobox("gRandomizeLogicRules", randoLogicRules, 2, 0); UIWidgets::EnhancementCombobox("gRandomizeLogicRules", randoLogicRules, 2, 0);
PaddedSeparator(); UIWidgets::PaddedSeparator();
// Enable Glitch-Useful Cutscenes // Enable Glitch-Useful Cutscenes
SohImGui::EnhancementCheckbox(Settings::EnableGlitchCutscenes.GetName().c_str(), UIWidgets::EnhancementCheckbox(Settings::EnableGlitchCutscenes.GetName().c_str(),
"gRandomizeEnableGlitchCutscenes"); "gRandomizeEnableGlitchCutscenes");
InsertHelpHoverText( UIWidgets::InsertHelpHoverText(
"The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. " "The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. "
"These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise."); "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise.");
@ -5051,14 +5068,21 @@ void DrawRandoEditor(bool& open) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
window->DC.CurrLineTextBaseOffset = 0.0f; window->DC.CurrLineTextBaseOffset = 0.0f;
ImGui::BeginChild("ChildStartingEquipment", ImVec2(0, -8)); ImGui::BeginChild("ChildStartingEquipment", ImVec2(0, -8));
// Don't display this option if Dungeon Rewards are Shuffled to End of Dungeon.
// TODO: Show this but disabled when we have options for disabled Comboboxes.
if (CVar_GetS32("gRandomizeShuffleDungeonReward", 0) != 0) {
ImGui::Text(Settings::LinksPocketItem.GetName().c_str());
UIWidgets::EnhancementCombobox("gRandomizeLinksPocket", randoLinksPocket, 4, 0);
UIWidgets::PaddedSeparator();
}
SohImGui::EnhancementCheckbox(Settings::StartingKokiriSword.GetName().c_str(), UIWidgets::EnhancementCheckbox(Settings::StartingKokiriSword.GetName().c_str(),
"gRandomizeStartingKokiriSword"); "gRandomizeStartingKokiriSword");
PaddedSeparator(); UIWidgets::PaddedSeparator();
SohImGui::EnhancementCheckbox(Settings::StartingDekuShield.GetName().c_str(), UIWidgets::EnhancementCheckbox(Settings::StartingDekuShield.GetName().c_str(),
"gRandomizeStartingDekuShield"); "gRandomizeStartingDekuShield");
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::EndChild(); ImGui::EndChild();
@ -5067,11 +5091,11 @@ void DrawRandoEditor(bool& open) {
window->DC.CurrLineTextBaseOffset = 0.0f; window->DC.CurrLineTextBaseOffset = 0.0f;
ImGui::BeginChild("ChildStartingItems", ImVec2(0, -8)); ImGui::BeginChild("ChildStartingItems", ImVec2(0, -8));
SohImGui::EnhancementCheckbox(Settings::StartingOcarina.GetName().c_str(), "gRandomizeStartingOcarina"); UIWidgets::EnhancementCheckbox(Settings::StartingOcarina.GetName().c_str(), "gRandomizeStartingOcarina");
PaddedSeparator(); UIWidgets::PaddedSeparator();
SohImGui::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(), UIWidgets::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(),
"gRandomizeStartingConsumables"); "gRandomizeStartingConsumables");
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::EndChild(); ImGui::EndChild();
@ -5082,7 +5106,7 @@ void DrawRandoEditor(bool& open) {
ImGui::Text("Coming soon"); ImGui::Text("Coming soon");
PaddedSeparator(); UIWidgets::PaddedSeparator();
ImGui::EndChild(); ImGui::EndChild();
ImGui::EndTable(); ImGui::EndTable();
@ -5235,7 +5259,7 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = {
"%cSi tu es coincé sur cette seed,&tu peux toujours jeter l'éponge&et regader le %wSpoiler log%c..." }, "%cSi tu es coincé sur cette seed,&tu peux toujours jeter l'éponge&et regader le %wSpoiler log%c..." },
{ "%cDid you know that the %yHover&Boots %ccan be used to cross&%wquicksand%c?", { "%cDid you know that the %yHover&Boots %ccan be used to cross&%wquicksand%c?",
"%cWusstest du, dass du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?", "%cWußtest du, daß du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?",
"%cEst-ce que tu savais que les %rBottes&des airs %cpouvaient être utilisées&pour traverser les %wsables mouvants%c?" }, "%cEst-ce que tu savais que les %rBottes&des airs %cpouvaient être utilisées&pour traverser les %wsables mouvants%c?" },
{ "%cYou can reach the back of %wImpa's&House %cby jumping from the&unfinished house with a %rcucco%c!", { "%cYou can reach the back of %wImpa's&House %cby jumping from the&unfinished house with a %rcucco%c!",
@ -5243,15 +5267,15 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = {
"%cTu peux atteindre l'arrière de la&%wMaison d'Impa %cen sautant depuis la&maison en construction avec une&%rcocotte%c!" }, "%cTu peux atteindre l'arrière de la&%wMaison d'Impa %cen sautant depuis la&maison en construction avec une&%rcocotte%c!" },
{ "%cThe %ySpirit Trial %cin %pGanon's Castle&%chas a %whidden chest %csomewhere.&Did you already know that?", { "%cThe %ySpirit Trial %cin %pGanon's Castle&%chas a %whidden chest %csomewhere.&Did you already know that?",
"%cDie %yGeister-Prüfung %cin %pGanons&Schloss %chat irgendwo eine&%wversteckte Kiste%c. Weißt du schon&wo?", "%cDie %yGeister-Prüfung %cin %pGanons&Schloß %chat irgendwo eine&%wversteckte Kiste%c. Weißt du schon&wo?",
"%cL'%yÉpreuve de l'Esprit%c dans le %pChâteau&de Ganon %ca un coffre caché quelque&part. Je suppose que tu le savais&déjà?" }, "%cL'%yÉpreuve de l'Esprit%c dans le %pChâteau&de Ganon %ca un coffre caché quelque&part. Je suppose que tu le savais&déjà?" },
{ "%cYou know the %wBombchu Bowling&Alley%c? I heard %wonly two of the &prizes %care worthwhile. The rest &is junk!", { "%cYou know the %wBombchu Bowling&Alley%c? I heard %wonly two of the &prizes %care worthwhile. The rest &is junk!",
"%cKennst du die %wMinenbowlingbahn%c?&Ich habe gehört dass sich nur &%wzwei der Preise%c lohnen. Der Rest&ist Krimskrams!", "%cKennst du die %wMinenbowlingbahn%c?&Ich habe gehört daß sich nur &%wzwei der Preise%c lohnen. Der Rest&ist Krimskrams!",
"%cEst-ce que tu savais qu'au %wBowling&Teigneux%c, il n'y a que les %wdeux&premiers prix %cqui sont intéréssant?" }, "%cEst-ce que tu savais qu'au %wBowling&Teigneux%c, il n'y a que les %wdeux&premiers prix %cqui sont intéréssant?" },
{ "%cHave you been using %wDeku Nuts&%cenough? I've seen them blow up&a %rBombchu%c!", { "%cHave you been using %wDeku Nuts&%cenough? I've seen them blow up&a %rBombchu%c!",
"%cBenutzt du auch genügend %wDeku&Nüsse%c? Ich habe mal gesehen dass&man damit %rKrabbelminen %cdetonieren&kann!", "%cBenutzt du auch genügend %wDeku&Nüsse%c? Ich habe mal gesehen daß&man damit %rKrabbelminen %cdetonieren&kann!",
"%cTu es sûr d'utiliser tes %wNoix Mojo &%ccorrectement? J'en ai déjà vu&exploser des %rChoux-Péteurs%c!" }, "%cTu es sûr d'utiliser tes %wNoix Mojo &%ccorrectement? J'en ai déjà vu&exploser des %rChoux-Péteurs%c!" },
{ "%cYou might end up with an %wextra&key %cfor the %bWater Temple %cor the&%rFire Temple%c. It's for your safety!", { "%cYou might end up with an %wextra&key %cfor the %bWater Temple %cor the&%rFire Temple%c. It's for your safety!",
@ -5267,7 +5291,7 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = {
"%cMême un adulte ne peut pas pousser&de grands blocs sans un petit %wgain&de force%c!" }, "%cMême un adulte ne peut pas pousser&de grands blocs sans un petit %wgain&de force%c!" },
{ "%cI've heard that %rFlare Dancer&%cis weak to the %wMaster Sword%c!&Have you tried it?", { "%cI've heard that %rFlare Dancer&%cis weak to the %wMaster Sword%c!&Have you tried it?",
"%cIch habe gehört dass der&%rFlammenderwisch %ceine Schwäche für&das %wMasterschwert %caufweist. Hast du&es schonmal versucht einzusetzen?", "%cIch habe gehört daß der&%rFlammenderwisch %ceine Schwäche für&das %wMasterschwert %caufweist. Hast du&es schonmal versucht einzusetzen?",
"%cJ'ai entendu dire que les %rDanse-&Flammes %csont faîbles face à l'%wÉpée de&Légende%c! Est-ce que tu as essayé?" }, "%cJ'ai entendu dire que les %rDanse-&Flammes %csont faîbles face à l'%wÉpée de&Légende%c! Est-ce que tu as essayé?" },
{ "%cDon't have a weapon to kill a&%rspider%c? Try throwing a %wpot&%cat it!", { "%cDon't have a weapon to kill a&%rspider%c? Try throwing a %wpot&%cat it!",
@ -5275,8 +5299,24 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = {
"%cSi tu n'as pas d'arme pour tuer&une %raraignée%c, pourquoi n'essayerais&-tu pas de lui jetter une %wjarre&%cà la figure?" }, "%cSi tu n'as pas d'arme pour tuer&une %raraignée%c, pourquoi n'essayerais&-tu pas de lui jetter une %wjarre&%cà la figure?" },
{ "%cI hear the patch of %wsoft soil&%cin %bZora's River %cis the only one&that isn't home to a %rspider%c!", { "%cI hear the patch of %wsoft soil&%cin %bZora's River %cis the only one&that isn't home to a %rspider%c!",
"%cIch habe gehört dass die Stelle&%wfeuchten Bodens %cim %bZora-Fluss %cals&einzige keine %rSkulltula %cbeherbergt.", "%cIch habe gehört daß die Stelle&%wfeuchten Bodens %cim %bZora-Fluß %cals&einzige keine %rSkulltula %cbeherbergt.",
"%cJ'ai entendu dire que la %wterre meuble&%cqui se trouve à la %bRivière Zora %cest&la seule qui ne contienne pas&d'%raraignée%c." }, "%cJ'ai entendu dire que la %wterre meuble&%cqui se trouve à la %bRivière Zora %cest&la seule qui ne contienne pas&d'%raraignée%c." },
{ "%cThe people of Hyrule sometimes&have %witems %cfor you, but they won't&like it if you're %wwearing a mask%c!",
"%cDie Bewohner Hyrules haben manchmal&%wGegenstände %cfür dich, aber Sie mögen&es nicht wenn du %wMasken trägst%c!",
"%cIl se peut que les habitants d'Hyrule&aient des %wobjets %cpour toi. Par contre,&ils risquent de ne pas trop apprécier&le fait que tu %wportes un masque%c!" },
{ "%cIf you get trapped somewhere, you&might have to %wsave your game %cand&%wreset%c!",
"%cSolltest du irgendwo eingeschloßen&sein, mußt du vielleicht dein %wSpiel&speichern %cund %wneustarten%c!",
"%cSi tu es coincé quelque part, tu&devrais %wsauvegarder ta partie %cet&faire un %wreset%c!" },
{ "%cSheik will meet you in a %rburning&village %conce you have %gForest%c,&%rFire%c, and %bWater %cMedallions!",
"%cSheik wird dich in einem %rbrennenden&Dorf %ctreffen sobald du das Amulett&des %gWaldes%c, %rFeuers %cund %bWassers&%cbesitzt.",
"%cSheik t'attendra dans un %rvillage&en feu %clorsque tu auras récupéré&les médaillons de la %gForêt%c, du %rFeu&%cet de l'%bEau%c!" },
{ "%cIf you don't have a %wsword %cas a&child, try buying %wDeku Sticks%c!&They're effective against your foes!",
"%cSolltest du als Kind kein %wSchwert&%cbesitzen, empfehle ich %wDeku Stäbe&%czu kaufen! Diese sind effektiv gegen&Widersacher!",
"%cSi tu n'as pas d'%wépée %cen tant&qu'enfant, pourquoi n'irais-tu pas&acheter quelques %wBâtons Mojo%c? Ils&sont efficaces contre tes ennemis!" }
}; };
void CreateNaviRandoMessages() { void CreateNaviRandoMessages() {

View File

@ -8,7 +8,7 @@
#include <soh/Enhancements/randomizer/randomizerTypes.h> #include <soh/Enhancements/randomizer/randomizerTypes.h>
#include <soh/Enhancements/custom-message/CustomMessageManager.h> #include <soh/Enhancements/custom-message/CustomMessageManager.h>
#define NUM_NAVI_MESSAGES 15 #define NUM_NAVI_MESSAGES 19
class Randomizer { class Randomizer {
private: private:

View File

@ -1019,7 +1019,8 @@ typedef enum {
RSK_SKULLS_SUNS_SONG, RSK_SKULLS_SUNS_SONG,
RSK_SHUFFLE_ADULT_TRADE, RSK_SHUFFLE_ADULT_TRADE,
RSK_SHUFFLE_MAGIC_BEANS, RSK_SHUFFLE_MAGIC_BEANS,
RSK_BOMBCHUS_IN_LOGIC RSK_BOMBCHUS_IN_LOGIC,
RSK_LINKS_POCKET
} RandomizerSettingKey; } RandomizerSettingKey;
typedef enum { typedef enum {

View File

@ -2,7 +2,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include <Cvar.h> #include <libultraship/Cvar.h>
/* /*
typedef struct { typedef struct {

View File

@ -1,14 +1,13 @@
#include "randomizer_item_tracker.h" #include "randomizer_item_tracker.h"
#include "../../util.h" #include "../../util.h"
#include "../libultraship/ImGuiImpl.h" #include <libultraship/ImGuiImpl.h>
#include "../libultraship/Hooks.h" #include "../../UIWidgets.hpp"
#include "../libultraship/UltraController.h"
#include "../debugger/ImGuiHelpers.h"
#include <map> #include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include <Cvar.h> #include <libultraship/Cvar.h>
#include <libultraship/Hooks.h>
extern "C" { extern "C" {
#include <z64.h> #include <z64.h>
@ -351,7 +350,7 @@ void DrawEquip(ItemTrackerItem item) {
ImGui::Image(SohImGui::GetTextureByName(hasEquip && IsValidSaveFile() ? item.name : item.nameFaded), ImGui::Image(SohImGui::GetTextureByName(hasEquip && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
SetLastItemHoverText(SohUtils::GetItemName(item.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id));
} }
void DrawQuest(ItemTrackerItem item) { void DrawQuest(ItemTrackerItem item) {
@ -367,7 +366,7 @@ void DrawQuest(ItemTrackerItem item) {
ImGui::EndGroup(); ImGui::EndGroup();
SetLastItemHoverText(SohUtils::GetQuestItemName(item.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(item.id));
}; };
void DrawItem(ItemTrackerItem item) { void DrawItem(ItemTrackerItem item) {
@ -418,7 +417,7 @@ void DrawItem(ItemTrackerItem item) {
DrawItemCount(item); DrawItemCount(item);
ImGui::EndGroup(); ImGui::EndGroup();
SetLastItemHoverText(SohUtils::GetItemName(item.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id));
} }
void DrawBottle(ItemTrackerItem item) { void DrawBottle(ItemTrackerItem item) {
@ -433,7 +432,7 @@ void DrawBottle(ItemTrackerItem item) {
ImGui::Image(SohImGui::GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), ImGui::Image(SohImGui::GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
SetLastItemHoverText(SohUtils::GetItemName(item.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id));
}; };
void DrawDungeonItem(ItemTrackerItem item) { void DrawDungeonItem(ItemTrackerItem item) {
@ -471,7 +470,7 @@ void DrawDungeonItem(ItemTrackerItem item) {
} }
ImGui::EndGroup(); ImGui::EndGroup();
SetLastItemHoverText(SohUtils::GetItemName(item.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id));
} }
void DrawSong(ItemTrackerItem item) { void DrawSong(ItemTrackerItem item) {
@ -482,7 +481,7 @@ void DrawSong(ItemTrackerItem item) {
ImGui::SetCursorScreenPos(ImVec2(p.x + 6, p.y)); ImGui::SetCursorScreenPos(ImVec2(p.x + 6, p.y));
ImGui::Image(SohImGui::GetTextureByName(hasSong && IsValidSaveFile() ? item.name : item.nameFaded), ImGui::Image(SohImGui::GetTextureByName(hasSong && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize / 1.5, iconSize), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(iconSize / 1.5, iconSize), ImVec2(0, 0), ImVec2(1, 1));
SetLastItemHoverText(SohUtils::GetQuestItemName(item.id)); UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(item.id));
} }
void DrawNotes(bool resizeable = false) { void DrawNotes(bool resizeable = false) {
@ -647,7 +646,7 @@ void LabeledComboBoxRightAligned(const char* label, const char* cvar, std::vecto
for (int i = 0; i < options.size(); i++) { for (int i = 0; i < options.size(); i++) {
if (ImGui::Selectable(options[i].c_str())) { if (ImGui::Selectable(options[i].c_str())) {
CVar_SetS32(cvar, i); CVar_SetS32(cvar, i);
SohImGui::needs_save = true; SohImGui::RequestCvarSaveOnNextTick();
shouldUpdateVectors = true; shouldUpdateVectors = true;
} }
} }
@ -664,7 +663,7 @@ void PaddedEnhancementCheckbox(const char* text, const char* cvarName, s32 defau
bool val = (bool)CVar_GetS32(cvarName, defaultValue); bool val = (bool)CVar_GetS32(cvarName, defaultValue);
if (ImGui::Checkbox(text, &val)) { if (ImGui::Checkbox(text, &val)) {
CVar_SetS32(cvarName, val); CVar_SetS32(cvarName, val);
SohImGui::needs_save = true; SohImGui::RequestCvarSaveOnNextTick();
shouldUpdateVectors = true; shouldUpdateVectors = true;
} }
if (padBottom) { if (padBottom) {
@ -858,7 +857,7 @@ void DrawItemTrackerOptions(bool& open) {
CVar_SetFloat("gItemTrackerBgColorG", ChromaKeyBackground.y); CVar_SetFloat("gItemTrackerBgColorG", ChromaKeyBackground.y);
CVar_SetFloat("gItemTrackerBgColorB", ChromaKeyBackground.z); CVar_SetFloat("gItemTrackerBgColorB", ChromaKeyBackground.z);
CVar_SetFloat("gItemTrackerBgColorA", ChromaKeyBackground.w); CVar_SetFloat("gItemTrackerBgColorA", ChromaKeyBackground.w);
SohImGui::needs_save = true; SohImGui::RequestCvarSaveOnNextTick();
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();
@ -873,9 +872,9 @@ void DrawItemTrackerOptions(bool& open) {
LabeledComboBoxRightAligned("Combo Button 2", "gItemTrackerComboButton2", { "A", "B", "C-Up", "C-Down", "C-Left", "C-Right", "L", "Z", "R", "Start", "D-Up", "D-Down", "D-Left", "D-Right" }, 8); LabeledComboBoxRightAligned("Combo Button 2", "gItemTrackerComboButton2", { "A", "B", "C-Up", "C-Down", "C-Left", "C-Right", "L", "Z", "R", "Start", "D-Up", "D-Down", "D-Left", "D-Right" }, 8);
} }
} }
PaddedSeparator(); UIWidgets::PaddedSeparator();
SohImGui::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gItemTrackerIconSize", 25, 128, "", 36, true); UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gItemTrackerIconSize", 25, 128, "", 36, true);
SohImGui::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", "gItemTrackerIconSpacing", -5, 50, "", 12, true); UIWidgets::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", "gItemTrackerIconSpacing", -5, 50, "", 12, true);
PaddedEnhancementCheckbox("Display \"Current/Max\" values", "gItemTrackerDisplayCurrentMax", 0); PaddedEnhancementCheckbox("Display \"Current/Max\" values", "gItemTrackerDisplayCurrentMax", 0);
if (CVar_GetS32("gItemTrackerDisplayCurrentMax", 0) == 0) { if (CVar_GetS32("gItemTrackerDisplayCurrentMax", 0) == 0) {
PaddedEnhancementCheckbox("Align count to left side", "gItemTrackerCurrentOnLeft", 0); PaddedEnhancementCheckbox("Align count to left side", "gItemTrackerCurrentOnLeft", 0);

View File

@ -1,6 +1,6 @@
#include "savestates.h" #include "savestates.h"
#include "GameVersions.h" #include <libultraship/GameVersions.h>
#include <cstdio> // std::sprintf #include <cstdio> // std::sprintf
@ -9,7 +9,7 @@
#include <soh/OTRGlobals.h> #include <soh/OTRGlobals.h>
#include <soh/OTRAudio.h> #include <soh/OTRAudio.h>
#include <ImGuiImpl.h> #include <libultraship/ImGuiImpl.h>
#include "z64.h" #include "z64.h"
#include "z64save.h" #include "z64save.h"
@ -823,7 +823,7 @@ extern "C" void ProcessSaveStateRequests(void) {
} }
void SaveStateMgr::SetCurrentSlot(unsigned int slot) { void SaveStateMgr::SetCurrentSlot(unsigned int slot) {
SohImGui::overlay->TextDrawNotification(1.0f, true, "slot %u set", slot); SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "slot %u set", slot);
this->currentSlot = slot; this->currentSlot = slot;
} }
@ -841,12 +841,12 @@ void SaveStateMgr::ProcessSaveStateRequests(void) {
this->states[request.slot] = std::make_shared<SaveState>(OTRGlobals::Instance->gSaveStateMgr, request.slot); this->states[request.slot] = std::make_shared<SaveState>(OTRGlobals::Instance->gSaveStateMgr, request.slot);
} }
this->states[request.slot]->Save(); this->states[request.slot]->Save();
SohImGui::overlay->TextDrawNotification(1.0f, true, "saved state %u", request.slot); SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "saved state %u", request.slot);
break; break;
case RequestType::LOAD: case RequestType::LOAD:
if (this->states.contains(request.slot)) { if (this->states.contains(request.slot)) {
this->states[request.slot]->Load(); this->states[request.slot]->Load();
SohImGui::overlay->TextDrawNotification(1.0f, true, "loaded state %u", request.slot); SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "loaded state %u", request.slot);
} else { } else {
SPDLOG_ERROR("Invalid SaveState slot: {}", request.type); SPDLOG_ERROR("Invalid SaveState slot: {}", request.type);
} }
@ -862,7 +862,7 @@ void SaveStateMgr::ProcessSaveStateRequests(void) {
SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) { SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) {
if (gGlobalCtx == nullptr) { if (gGlobalCtx == nullptr) {
SPDLOG_ERROR("[SOH] Can not save or load a state outside of \"GamePlay\""); SPDLOG_ERROR("[SOH] Can not save or load a state outside of \"GamePlay\"");
SohImGui::overlay->TextDrawNotification(1.0f, true, "states not available here", request.slot); SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "states not available here", request.slot);
return SaveStateReturn::FAIL_WRONG_GAMESTATE; return SaveStateReturn::FAIL_WRONG_GAMESTATE;
} }
@ -876,7 +876,7 @@ SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) {
return SaveStateReturn::SUCCESS; return SaveStateReturn::SUCCESS;
} else { } else {
SPDLOG_ERROR("Invalid SaveState slot: {}", request.type); SPDLOG_ERROR("Invalid SaveState slot: {}", request.type);
SohImGui::overlay->TextDrawNotification(1.0f, true, "state slot %u empty", request.slot); SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "state slot %u empty", request.slot);
return SaveStateReturn::FAIL_INVALID_SLOT; return SaveStateReturn::FAIL_INVALID_SLOT;
} }
[[unlikely]] default: [[unlikely]] default:

1400
soh/soh/GameMenuBar.cpp Normal file

File diff suppressed because it is too large Load Diff

27
soh/soh/GameMenuBar.hpp Normal file
View File

@ -0,0 +1,27 @@
//
// GameMenuBar.hpp
// soh
//
// Created by David Chavez on 24.08.22.
//
#ifndef GameMenuBar_hpp
#define GameMenuBar_hpp
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
void enableBetaQuest();
void disableBetaQuest();
#ifdef __cplusplus
}
#endif
namespace GameMenuBar {
void SetupHooks();
void Draw();
}
#endif /* GameMenuBar_hpp */

View File

@ -5,46 +5,46 @@
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include "ResourceMgr.h" #include <libultraship/ResourceMgr.h>
#include "DisplayList.h" #include <libultraship/DisplayList.h>
#include "PlayerAnimation.h" #include <libultraship/PlayerAnimation.h>
#include "Skeleton.h" #include <libultraship/Skeleton.h>
#include "Window.h" #include <libultraship/Window.h>
#include "z64animation.h" #include "z64animation.h"
#include "z64bgcheck.h" #include "z64bgcheck.h"
#include "Enhancements/gameconsole.h" #include "Enhancements/gameconsole.h"
#include <ultra64/gbi.h> #include <ultra64/gbi.h>
#include <Animation.h> #include <libultraship/Animation.h>
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> #include <Windows.h>
#else #else
#include <time.h> #include <time.h>
#endif #endif
#include <CollisionHeader.h> #include <libultraship/CollisionHeader.h>
#include <Array.h> #include <libultraship/Array.h>
#include <Cutscene.h> #include <libultraship/Cutscene.h>
#include "Lib/stb/stb_image.h" #include <stb/stb_image.h>
#define DRMP3_IMPLEMENTATION #define DRMP3_IMPLEMENTATION
#include "Lib/dr_libs/mp3.h" #include <dr_libs/mp3.h>
#define DRWAV_IMPLEMENTATION #define DRWAV_IMPLEMENTATION
#include "Lib/dr_libs/wav.h" #include <dr_libs/wav.h>
#include "AudioPlayer.h" #include <libultraship/AudioPlayer.h>
#include "Enhancements/controls/GameControlEditor.h" #include "Enhancements/controls/GameControlEditor.h"
#include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/cosmetics/CosmeticsEditor.h"
#include "Enhancements/debugconsole.h" #include "Enhancements/debugconsole.h"
#include "Enhancements/debugger/debugger.h" #include "Enhancements/debugger/debugger.h"
#include <soh/Enhancements/randomizer/randomizer.h> #include "Enhancements/randomizer/randomizer.h"
#include <soh/Enhancements/randomizer/randomizer_item_tracker.h> #include "Enhancements/randomizer/randomizer_item_tracker.h"
#include "Enhancements/n64_weird_frame_data.inc" #include "Enhancements/n64_weird_frame_data.inc"
#include "soh/frame_interpolation.h" #include "frame_interpolation.h"
#include "variables.h" #include "variables.h"
#include "macros.h" #include "macros.h"
#include <Utils/StringHelper.h> #include <Utils/StringHelper.h>
#include "Hooks.h" #include <libultraship/Hooks.h>
#include <soh/Enhancements/custom-message/CustomMessageManager.h> #include "Enhancements/custom-message/CustomMessageManager.h"
#include "Lib/Fast3D/gfx_pc.h" #include <Fast3D/gfx_pc.h>
#include "Lib/Fast3D/gfx_rendering_api.h" #include <Fast3D/gfx_rendering_api.h>
#ifdef __APPLE__ #ifdef __APPLE__
#include <SDL_scancode.h> #include <SDL_scancode.h>
@ -53,15 +53,16 @@
#endif #endif
#ifdef __SWITCH__ #ifdef __SWITCH__
#include "SwitchImpl.h" #include <libultraship/SwitchImpl.h>
#elif defined(__WIIU__) #elif defined(__WIIU__)
#include "WiiUImpl.h" #include <libultraship/WiiUImpl.h>
#endif #endif
#include <Audio.h> #include <libultraship/Audio.h>
#include <soh/Enhancements/custom-message/CustomMessageTypes.h> #include "Enhancements/custom-message/CustomMessageTypes.h"
#include <functions.h> #include <functions.h>
#include <soh/Enhancements/item-tables/ItemTableManager.h> #include "Enhancements/item-tables/ItemTableManager.h"
#include "GameMenuBar.hpp"
OTRGlobals* OTRGlobals::Instance; OTRGlobals* OTRGlobals::Instance;
SaveManager* SaveManager::Instance; SaveManager* SaveManager::Instance;
@ -290,6 +291,7 @@ extern "C" void VanillaItemTable_Init() {
GET_ITEM(ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG_50, 0x6C, 0x80, CHEST_ANIM_LONG, MOD_NONE, GI_BULLET_BAG_50), GET_ITEM(ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG_50, 0x6C, 0x80, CHEST_ANIM_LONG, MOD_NONE, GI_BULLET_BAG_50),
GET_ITEM_NONE, GET_ITEM_NONE,
GET_ITEM_NONE, GET_ITEM_NONE,
GET_ITEM_NONE // GI_MAX - if you need to add to this table insert it before this entry.
}; };
ItemTableManager::Instance->AddItemTable(MOD_NONE); ItemTableManager::Instance->AddItemTable(MOD_NONE);
for (uint8_t i = 0; i < ARRAY_COUNT(getItemTable); i++) { for (uint8_t i = 0; i < ARRAY_COUNT(getItemTable); i++) {
@ -321,6 +323,9 @@ extern "C" void InitOTR() {
#elif defined(__WIIU__) #elif defined(__WIIU__)
Ship::WiiU::Init(); Ship::WiiU::Init();
#endif #endif
SohImGui::AddSetupHooksDelegate(GameMenuBar::SetupHooks);
SohImGui::RegisterMenuDrawMethod(GameMenuBar::Draw);
OTRGlobals::Instance = new OTRGlobals(); OTRGlobals::Instance = new OTRGlobals();
SaveManager::Instance = new SaveManager(); SaveManager::Instance = new SaveManager();
CustomMessageManager::Instance = new CustomMessageManager(); CustomMessageManager::Instance = new CustomMessageManager();
@ -1633,7 +1638,7 @@ extern "C" CustomMessageEntry Randomizer_GetHintFromCheck(RandomizerCheck check)
} }
extern "C" GetItemEntry ItemTable_Retrieve(int16_t getItemID) { extern "C" GetItemEntry ItemTable_Retrieve(int16_t getItemID) {
GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(OTRGlobals::Instance->getItemModIndex, getItemID); GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, getItemID);
return giEntry; return giEntry;
} }

View File

@ -7,7 +7,7 @@
#include <soh/Enhancements/item-tables/ItemTableTypes.h> #include <soh/Enhancements/item-tables/ItemTableTypes.h>
#ifdef __cplusplus #ifdef __cplusplus
#include "Window.h" #include <libultraship/Window.h>
#include "Enhancements/savestates.h" #include "Enhancements/savestates.h"
#include "Enhancements/randomizer/randomizer.h" #include "Enhancements/randomizer/randomizer.h"
@ -21,7 +21,6 @@ public:
std::shared_ptr<Ship::Window> context; std::shared_ptr<Ship::Window> context;
std::shared_ptr<SaveStateMgr> gSaveStateMgr; std::shared_ptr<SaveStateMgr> gSaveStateMgr;
std::shared_ptr<Randomizer> gRandomizer; std::shared_ptr<Randomizer> gRandomizer;
uint16_t getItemModIndex;
OTRGlobals(); OTRGlobals();
~OTRGlobals(); ~OTRGlobals();

View File

@ -4,7 +4,7 @@
#include "z64.h" #include "z64.h"
#include "functions.h" #include "functions.h"
#include "macros.h" #include "macros.h"
#include "Cvar.h" #include <libultraship/Cvar.h>
#define NOGDI // avoid various windows defines that conflict with things in z64.h #define NOGDI // avoid various windows defines that conflict with things in z64.h
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"

View File

@ -23,7 +23,7 @@ typedef struct {
#include <vector> #include <vector>
#include <filesystem> #include <filesystem>
#include "Lib/nlohmann/json.hpp" #include <nlohmann/json.hpp>
class SaveManager { class SaveManager {
public: public:

523
soh/soh/UIWidgets.cpp Normal file
View File

@ -0,0 +1,523 @@
//
// UIWidgets.cpp
// soh
//
// Created by David Chavez on 25.08.22.
//
#include "UIWidgets.hpp"
#define IMGUI_DEFINE_MATH_OPERATORS
#include <ImGui/imgui_internal.h>
#include <libultraship/ImGuiImpl.h>
#include <libultraship/Cvar.h>
#include <ultra64/types.h>
namespace UIWidgets {
// MARK: - Layout Helper
// Automatically adds newlines to break up text longer than a specified number of characters
// Manually included newlines will still be respected and reset the line length
// If line is midword when it hits the limit, text should break at the last encountered space
char* WrappedText(const char* text, unsigned int charactersPerLine) {
std::string newText(text);
const size_t tipLength = newText.length();
int lastSpace = -1;
int currentLineLength = 0;
for (unsigned int currentCharacter = 0; currentCharacter < tipLength; currentCharacter++) {
if (newText[currentCharacter] == '\n') {
currentLineLength = 0;
lastSpace = -1;
continue;
} else if (newText[currentCharacter] == ' ') {
lastSpace = currentCharacter;
}
if ((currentLineLength >= charactersPerLine) && (lastSpace >= 0)) {
newText[lastSpace] = '\n';
currentLineLength = currentCharacter - lastSpace - 1;
lastSpace = -1;
}
currentLineLength++;
}
return strdup(newText.c_str());
}
char* WrappedText(const std::string& text, unsigned int charactersPerLine) {
return WrappedText(text.c_str(), charactersPerLine);
}
void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha)
{
Color_RGBA8 defaultColors;
defaultColors.r = default_colors.x;
defaultColors.g = default_colors.y;
defaultColors.b = default_colors.z;
defaultColors.a = default_colors.w;
Color_RGBA8 cvarColor = CVar_GetRGBA(cvarname, defaultColors);
ColorArray.x = cvarColor.r / 255.0;
ColorArray.y = cvarColor.g / 255.0;
ColorArray.z = cvarColor.b / 255.0;
ColorArray.w = cvarColor.a / 255.0;
}
void SetLastItemHoverText(const std::string& text) {
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("%s", WrappedText(text, 60));
ImGui::EndTooltip();
}
}
// Adds a "?" next to the previous ImGui item with a custom tooltip
void InsertHelpHoverText(const std::string& text) {
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("%s", WrappedText(text, 60));
ImGui::EndTooltip();
}
}
// MARK: - UI Elements
void Tooltip(const char* text) {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", WrappedText(text));
}
}
void Spacer(float height) {
ImGui::Dummy(ImVec2(0.0f, height));
}
void PaddedSeparator(bool padTop, bool padBottom, float extraVerticalTopPadding, float extraVerticalBottomPadding) {
if (padTop)
Spacer(0);
ImGui::Separator();
if (padBottom)
Spacer(0);
}
void RenderCross(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz) {
float thickness = ImMax(sz / 5.0f, 1.0f);
sz -= thickness * 0.5f;
pos += ImVec2(thickness * 0.25f, thickness * 0.25f);
draw_list->PathLineTo(ImVec2(pos.x, pos.y));
draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y + sz));
draw_list->PathStroke(col, 0, thickness);
draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y));
draw_list->PathLineTo(ImVec2(pos.x, pos.y + sz));
draw_list->PathStroke(col, 0, thickness);
}
bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic) {
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
const float square_sz = ImGui::GetFrameHeight();
const ImVec2 pos = window->DC.CursorPos;
const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
ImGui::ItemSize(total_bb, style.FramePadding.y);
if (!ImGui::ItemAdd(total_bb, id)) {
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return false;
}
bool hovered, held;
bool pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held);
if (pressed) {
*v = !(*v);
ImGui::MarkItemEdited(id);
}
const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
ImGui::RenderNavHighlight(total_bb, id);
ImGui::RenderFrame(check_bb.Min, check_bb.Max, ImGui::GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
ImU32 check_col = ImGui::GetColorU32(ImGuiCol_CheckMark);
ImU32 cross_col = ImGui::GetColorU32(ImVec4(0.50f, 0.50f, 0.50f, 1.00f));
bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0;
if (mixed_value) {
// Undocumented tristate/mixed/indeterminate checkbox (#2644)
// This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox)
ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)));
window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding);
} else if ((!disabled && *v) || (disabled && disabledGraphic == CheckboxGraphics::Checkmark)) {
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
ImGui::RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f);
} else if (disabled && disabledGraphic == CheckboxGraphics::Cross) {
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), cross_col, square_sz - pad * 2.0f);
}
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
if (g.LogEnabled)
ImGui::LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]");
if (label_size.x > 0.0f)
ImGui::RenderText(label_pos, label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return pressed;
}
void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic) {
if (disabled) {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
}
bool val = (bool)CVar_GetS32(cvarName, 0);
if (CustomCheckbox(text, &val, disabled, disabledGraphic)) {
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
if (disabled) {
ImGui::PopStyleVar(1);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && strcmp(disabledTooltipText, "") != 0) {
ImGui::SetTooltip("%s", disabledTooltipText);
}
ImGui::PopItemFlag();
}
}
void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic) {
if (padTop) Spacer(0);
EnhancementCheckbox(text, cvarName, disabled, disabledTooltipText, disabledGraphic);
if (padBottom) Spacer(0);
}
void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector<std::string>& items, int defaultValue) {
if (ImGui::BeginCombo(name.c_str(), items[static_cast<int>(CVar_GetS32(cvarName, defaultValue))].c_str())) {
for (int settingIndex = 0; settingIndex < (int) items.size(); settingIndex++) {
if (ImGui::Selectable(items[settingIndex].c_str())) {
CVar_SetS32(cvarName, settingIndex);
SohImGui::RequestCvarSaveOnNextTick();
}
}
ImGui::EndCombo();
}
}
void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue) {
if (FirstTimeValue <= 0) {
FirstTimeValue = 0;
}
uint8_t selected = CVar_GetS32(name, FirstTimeValue);
uint8_t DefaultValue = selected;
std::string comboName = std::string("##") + std::string(name);
if (ImGui::BeginCombo(comboName.c_str(), ComboArray[DefaultValue])) {
for (uint8_t i = 0; i < arraySize; i++) {
if (strlen(ComboArray[i]) > 1) {
if (ImGui::Selectable(ComboArray[i], i == selected)) {
CVar_SetS32(name, i);
selected = i;
SohImGui::RequestCvarSaveOnNextTick();
}
}
}
ImGui::EndCombo();
}
}
void PaddedText(const char* text, bool padTop, bool padBottom) {
if (padTop)
Spacer(0);
ImGui::Text("%s", text);
if (padBottom)
Spacer(0);
}
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton) {
int val = CVar_GetS32(cvarName, defaultValue);
ImGui::Text(text, val);
if(PlusMinusButton) {
std::string MinusBTNName = " - ##";
MinusBTNName += cvarName;
if (ImGui::Button(MinusBTNName.c_str())) {
val--;
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
}
if (ImGui::SliderInt(id, &val, min, max, format))
{
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
if(PlusMinusButton) {
std::string PlusBTNName = " + ##";
PlusBTNName += cvarName;
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
if (ImGui::Button(PlusBTNName.c_str())) {
val++;
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
}
if (val < min)
{
val = min;
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
if (val > max)
{
val = max;
CVar_SetS32(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
}
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton) {
float val = CVar_GetFloat(cvarName, defaultValue);
if (!isPercentage)
ImGui::Text(text, val);
else
ImGui::Text(text, static_cast<int>(100 * val));
Spacer(0);
if(PlusMinusButton) {
std::string MinusBTNName = " - ##";
MinusBTNName += cvarName;
if (ImGui::Button(MinusBTNName.c_str())) {
if (!isPercentage)
val -= 0.1f;
else
val -= 0.01f;
CVar_SetFloat(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
}
if (PlusMinusButton) {
#ifdef __WIIU__
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2);
#else
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f);
#endif
}
if (ImGui::SliderFloat(id, &val, min, max, format))
{
CVar_SetFloat(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
if (PlusMinusButton) {
ImGui::PopItemWidth();
}
if(PlusMinusButton) {
std::string PlusBTNName = " + ##";
PlusBTNName += cvarName;
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
if (ImGui::Button(PlusBTNName.c_str())) {
if (!isPercentage)
val += 0.1f;
else
val += 0.01f;
CVar_SetFloat(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
}
if (val < min)
{
val = min;
CVar_SetFloat(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
if (val > max)
{
val = max;
CVar_SetFloat(cvarName, val);
SohImGui::RequestCvarSaveOnNextTick();
}
}
void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool padTop, bool padBottom) {
if (padTop)
Spacer(0);
EnhancementSliderInt(text, id, cvarName, min, max, format, defaultValue, PlusMinusButton);
if (padBottom)
Spacer(0);
}
void EnhancementRadioButton(const char* text, const char* cvarName, int id) {
/*Usage :
EnhancementRadioButton("My Visible Name","gMyCVarName", MyID);
First arg is the visible name of the Radio button
Second is the cvar name where MyID will be saved.
Note: the CVar name should be the same to each Buddies.
Example :
EnhancementRadioButton("English", "gLanguages", 0);
EnhancementRadioButton("German", "gLanguages", 1);
EnhancementRadioButton("French", "gLanguages", 2);
*/
std::string make_invisible = "##";
make_invisible += text;
make_invisible += cvarName;
int val = CVar_GetS32(cvarName, 0);
if (ImGui::RadioButton(make_invisible.c_str(), id == val)) {
CVar_SetS32(cvarName, id);
SohImGui::RequestCvarSaveOnNextTick();
}
ImGui::SameLine();
ImGui::Text("%s", text);
}
void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha) {
std::string Cvar_RBM = cvarName;
Cvar_RBM += "RBM";
std::string MakeInvisible = "Reset";
MakeInvisible += "##";
MakeInvisible += cvarName;
MakeInvisible += "Reset";
if (ImGui::Button(MakeInvisible.c_str())) {
colors->x = defaultcolors.x;
colors->y = defaultcolors.y;
colors->z = defaultcolors.z;
if (has_alpha) { colors->w = defaultcolors.w; };
Color_RGBA8 colorsRGBA;
colorsRGBA.r = defaultcolors.x;
colorsRGBA.g = defaultcolors.y;
colorsRGBA.b = defaultcolors.z;
if (has_alpha) { colorsRGBA.a = defaultcolors.w; };
CVar_SetRGBA(cvarName, colorsRGBA);
CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode.
SohImGui::RequestCvarSaveOnNextTick();
}
Tooltip("Revert colors to the game's original colors (GameCube version)\nOverwrites previously chosen color");
}
void RandomizeColor(const char* cvarName, ImVec4* colors) {
Color_RGBA8 NewColors = {0,0,0,255};
std::string Cvar_RBM = cvarName;
Cvar_RBM += "RBM";
std::string MakeInvisible = "##";
MakeInvisible += cvarName;
MakeInvisible += "Random";
std::string FullName = "Random";
FullName += MakeInvisible;
if (ImGui::Button(FullName.c_str())) {
s16 RND_R = rand() % (255 - 0);
s16 RND_G = rand() % (255 - 0);
s16 RND_B = rand() % (255 - 0);
colors->x = (float)RND_R / 255;
colors->y = (float)RND_G / 255;
colors->z = (float)RND_B / 255;
NewColors.r = fmin(fmax(colors->x, 0), 255);
NewColors.g = fmin(fmax(colors->y, 0), 255);
NewColors.b = fmin(fmax(colors->z, 0), 255);
CVar_SetRGBA(cvarName, NewColors);
CVar_SetS32(Cvar_RBM.c_str(), 0); // On click disable rainbow mode.
SohImGui::RequestCvarSaveOnNextTick();
}
Tooltip("Chooses a random color\nOverwrites previously chosen color");
}
void RainbowColor(const char* cvarName, ImVec4* colors) {
std::string Cvar_RBM = cvarName;
Cvar_RBM += "RBM";
std::string MakeInvisible = "Rainbow";
MakeInvisible += "##";
MakeInvisible += cvarName;
MakeInvisible += "Rainbow";
EnhancementCheckbox(MakeInvisible.c_str(), Cvar_RBM.c_str());
Tooltip("Cycles through colors on a timer\nOverwrites previously chosen color");
}
void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow, bool has_alpha, bool TitleSameLine) {
LoadPickersColors(ColorRGBA, cvarName, default_colors, has_alpha);
ImGuiColorEditFlags flags = ImGuiColorEditFlags_None;
if (!TitleSameLine) {
ImGui::Text("%s", text);
flags = ImGuiColorEditFlags_NoLabel;
}
ImGui::PushID(cvarName);
if (!has_alpha) {
if (ImGui::ColorEdit3(text, (float*)&ColorRGBA, flags))
{
Color_RGBA8 colors;
colors.r = ColorRGBA.x * 255.0;
colors.g = ColorRGBA.y * 255.0;
colors.b = ColorRGBA.z * 255.0;
colors.a = ColorRGBA.w * 255.0;
CVar_SetRGBA(cvarName, colors);
SohImGui::RequestCvarSaveOnNextTick();
}
}
else
{
if (ImGui::ColorEdit4(text, (float*)&ColorRGBA, flags))
{
Color_RGBA8 colors;
colors.r = ColorRGBA.x / 255;
colors.g = ColorRGBA.y / 255;
colors.b = ColorRGBA.z / 255;
colors.a = ColorRGBA.w / 255;
CVar_SetRGBA(cvarName, colors);
SohImGui::RequestCvarSaveOnNextTick();
}
}
ImGui::PopID();
//ImGui::SameLine(); // Removing that one to gain some width spacing on the HUD editor
ImGui::PushItemWidth(-FLT_MIN);
ResetColor(cvarName, &ColorRGBA, default_colors, has_alpha);
ImGui::SameLine();
RandomizeColor(cvarName, &ColorRGBA);
if (allow_rainbow) {
if (ImGui::GetContentRegionAvail().x > 185) {
ImGui::SameLine();
}
RainbowColor(cvarName, &ColorRGBA);
}
ImGui::NewLine();
ImGui::PopItemWidth();
}
}

49
soh/soh/UIWidgets.hpp Normal file
View File

@ -0,0 +1,49 @@
//
// UIWidgets.hpp
// soh
//
// Created by David Chavez on 25.08.22.
//
#ifndef UIWidgets_hpp
#define UIWidgets_hpp
#include <string>
#include <vector>
#include <stdint.h>
#include <ImGui/imgui.h>
namespace UIWidgets {
// MARK: - Enums
enum class CheckboxGraphics {
Cross,
Checkmark,
None
};
char* WrappedText(const char* text, unsigned int charactersPerLine = 60);
char* WrappedText(const std::string& text, unsigned int charactersPerLine);
void SetLastItemHoverText(const std::string& text);
void InsertHelpHoverText(const std::string& text);
void Tooltip(const char* text);
void Spacer(float height);
void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f);
void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross);
void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross);
void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector<std::string>& items, int defaultValue = 0);
void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue);
void PaddedText(const char* text, bool padTop = true, bool padBottom = true);
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false);
void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true);
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false);
void EnhancementRadioButton(const char* text, const char* cvarName, int id);
void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false);
}
#endif /* UIWidgets_hpp */

View File

@ -1,4 +1,4 @@
#include "Cvar.h" #include <libultraship/Cvar.h>
#include <vector> #include <vector>
#include <map> #include <map>

View File

@ -1,13 +1,13 @@
#include "OTRGlobals.h" #include "OTRGlobals.h"
#include "ResourceMgr.h" #include <libultraship/ResourceMgr.h>
#include "Scene.h" #include <libultraship/Scene.h>
#include "Utils/StringHelper.h" #include <Utils/StringHelper.h>
#include "global.h" #include "global.h"
#include "vt.h" #include "vt.h"
#include <Text.h> #include <libultraship/Text.h>
#include <message_data_static.h> #include <message_data_static.h>
#include <soh/Enhancements/custom-message/CustomMessageManager.h> #include "Enhancements/custom-message/CustomMessageManager.h"
#include <soh/Enhancements/custom-message/CustomMessageTypes.h> #include "Enhancements/custom-message/CustomMessageTypes.h"
extern "C" MessageTableEntry* sNesMessageEntryTablePtr; extern "C" MessageTableEntry* sNesMessageEntryTablePtr;
extern "C" MessageTableEntry* sGerMessageEntryTablePtr; extern "C" MessageTableEntry* sGerMessageEntryTablePtr;

View File

@ -1,10 +1,10 @@
#include "OTRGlobals.h" #include "OTRGlobals.h"
#include "ResourceMgr.h" #include <libultraship/ResourceMgr.h>
#include "Scene.h" #include <libultraship/Scene.h>
#include "Utils/StringHelper.h" #include <Utils/StringHelper.h>
#include "global.h" #include "global.h"
#include "vt.h" #include "vt.h"
#include "Vertex.h" #include <libultraship/Vertex.h>
extern "C" void Gameplay_InitScene(GlobalContext * globalCtx, s32 spawn); extern "C" void Gameplay_InitScene(GlobalContext * globalCtx, s32 spawn);
extern "C" void Gameplay_InitEnvironment(GlobalContext * globalCtx, s16 skyboxId); extern "C" void Gameplay_InitEnvironment(GlobalContext * globalCtx, s16 skyboxId);
@ -60,7 +60,6 @@ void OTRGameplay_InitScene(GlobalContext* globalCtx, s32 spawn) {
globalCtx->cUpElfMsgs = nullptr; globalCtx->cUpElfMsgs = nullptr;
globalCtx->setupPathList = nullptr; globalCtx->setupPathList = nullptr;
globalCtx->numSetupActors = 0; globalCtx->numSetupActors = 0;
OTRGlobals::Instance->getItemModIndex = MOD_NONE;
Object_InitBank(globalCtx, &globalCtx->objectCtx); Object_InitBank(globalCtx, &globalCtx->objectCtx);
LightContext_Init(globalCtx, &globalCtx->lightCtx); LightContext_Init(globalCtx, &globalCtx->lightCtx);
TransitionActor_InitContext(&globalCtx->state, &globalCtx->transiActorCtx); TransitionActor_InitContext(&globalCtx->state, &globalCtx->transiActorCtx);

View File

@ -1,15 +1,15 @@
#include "OTRGlobals.h" #include "OTRGlobals.h"
#include "ResourceMgr.h" #include <libultraship/ResourceMgr.h>
#include "Scene.h" #include <libultraship/Scene.h>
#include "Utils/StringHelper.h" #include <Utils/StringHelper.h>
#include "global.h" #include "global.h"
#include "vt.h" #include "vt.h"
#include <CollisionHeader.h> #include <libultraship/CollisionHeader.h>
#include <DisplayList.h> #include <libultraship/DisplayList.h>
#include <Cutscene.h> #include <libultraship/Cutscene.h>
#include <Path.h> #include <libultraship/Path.h>
#include <Text.h> #include <libultraship/Text.h>
#include <Blob.h> #include <libultraship/Blob.h>
extern Ship::Resource* OTRGameplay_LoadFile(GlobalContext* globalCtx, const char* fileName); extern Ship::Resource* OTRGameplay_LoadFile(GlobalContext* globalCtx, const char* fileName);
extern "C" s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId); extern "C" s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId);

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "Cvar.h" #include <libultraship/Cvar.h>
extern bool gUseLegacySD; extern bool gUseLegacySD;

View File

@ -1,6 +1,6 @@
#include "ultra64.h" #include "ultra64.h"
#include "global.h" #include "global.h"
#include "mixer.h" #include <libultraship/mixer.h>
#define DEFAULT_LEN_1CH 0x1A0 #define DEFAULT_LEN_1CH 0x1A0
#define DEFAULT_LEN_2CH 0x340 #define DEFAULT_LEN_2CH 0x340

View File

@ -1,7 +1,7 @@
#include "ultra64.h" #include "ultra64.h"
#include "global.h" #include "global.h"
#include "ultra64/abi.h" #include <ultra64/abi.h>
#include "mixer.h" #include <libultraship/mixer.h>
typedef struct { typedef struct {
u8 unk_0; u8 unk_0;

View File

@ -3,7 +3,7 @@
#include <soh/Enhancements/bootcommands.h> #include <soh/Enhancements/bootcommands.h>
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "../libultraship/CrashHandler.h" #include <libultraship/CrashHandler.h>
s32 gScreenWidth = SCREEN_WIDTH; s32 gScreenWidth = SCREEN_WIDTH;
@ -42,6 +42,8 @@ int main(int argc, char** argv)
{ {
#ifdef __linux__ #ifdef __linux__
SetupHandlerLinux(); SetupHandlerLinux();
#elif _WIN32
SetUnhandledExceptionFilter(seh_filter);
#endif #endif
GameConsole_Init(); GameConsole_Init();

View File

@ -515,13 +515,13 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) {
} }
if (!Actor_HasParent(&this->actor, globalCtx)) { if (!Actor_HasParent(&this->actor, globalCtx)) {
if (!gSaveContext.n64ddFlag) { if (getItemId != GI_NONE) {
if (getItemId != GI_NONE) { if (!gSaveContext.n64ddFlag) {
func_8002F554(&this->actor, globalCtx, getItemId); func_8002F554(&this->actor, globalCtx, getItemId);
} else {
getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, getItemId);
GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem);
} }
} else {
getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, getItemId);
GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem);
} }
} }

View File

@ -1575,6 +1575,17 @@ void func_80084BF4(GlobalContext* globalCtx, u16 flag) {
} }
} }
/**
* @brief Adds the given item to Link's inventory.
*
* NOTE: This function has been edited to be safe to use with a NULL globalCtx.
* If you need to add to this function, be sure you check if the globalCtx is not
* NULL before doing any operations requiring it.
*
* @param globalCtx
* @param item
* @return u8
*/
u8 Item_Give(GlobalContext* globalCtx, u8 item) { u8 Item_Give(GlobalContext* globalCtx, u8 item) {
static s16 sAmmoRefillCounts[] = { 5, 10, 20, 30, 5, 10, 30, 0, 5, 20, 1, 5, 20, 50, 200, 10 }; static s16 sAmmoRefillCounts[] = { 5, 10, 20, 30, 5, 10, 30, 0, 5, 20, 1, 5, 20, 50, 200, 10 };
s16 i; s16 i;
@ -1654,7 +1665,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
if (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KNIFE) { if (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KNIFE) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS; gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
Interface_LoadItemIcon1(globalCtx, 0); if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, 0);
}
} }
} }
@ -1662,7 +1675,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER;
gSaveContext.equips.equipment &= 0xFFF0; gSaveContext.equips.equipment &= 0xFFF0;
gSaveContext.equips.equipment |= 0x0002; gSaveContext.equips.equipment |= 0x0002;
Interface_LoadItemIcon1(globalCtx, 0); if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, 0);
}
} }
return ITEM_NONE; return ITEM_NONE;
@ -1677,7 +1692,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
return ITEM_NONE; return ITEM_NONE;
} else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) { } else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) {
// Boss Key, Compass, and Dungeon Map exceptions for rando. // Boss Key, Compass, and Dungeon Map exceptions for rando.
if (gSaveContext.n64ddFlag) { // Rando should never be able to get here for Link's Pocket unless something goes wrong,
// but we check for a globalCtx here so the game won't crash if we do somehow get here.
if (gSaveContext.n64ddFlag && globalCtx != NULL) {
if (globalCtx->sceneNum == 13) { // ganon's castle -> ganon's tower if (globalCtx->sceneNum == 13) { // ganon's castle -> ganon's tower
gSaveContext.inventory.dungeonItems[10] |= 1; gSaveContext.inventory.dungeonItems[10] |= 1;
} else if (globalCtx->sceneNum == 92) { // Desert Colossus -> Spirit Temple. } else if (globalCtx->sceneNum == 92) { // Desert Colossus -> Spirit Temple.
@ -1691,7 +1708,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
return ITEM_NONE; return ITEM_NONE;
} else if (item == ITEM_KEY_SMALL) { } else if (item == ITEM_KEY_SMALL) {
// Small key exceptions for rando with keysanity off. // Small key exceptions for rando with keysanity off.
if (gSaveContext.n64ddFlag) { // Rando should never be able to get here for Link's Pocket unless something goes wrong,
// but we check for a globalCtx here so the game won't crash if we do somehow get here.
if (gSaveContext.n64ddFlag && globalCtx != NULL) {
if (globalCtx->sceneNum == 10) { // ganon's tower -> ganon's castle if (globalCtx->sceneNum == 10) { // ganon's tower -> ganon's castle
if (gSaveContext.inventory.dungeonKeys[13] < 0) { if (gSaveContext.inventory.dungeonKeys[13] < 0) {
gSaveContext.inventory.dungeonKeys[13] = 1; gSaveContext.inventory.dungeonKeys[13] = 1;
@ -1828,7 +1847,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
if (gSaveContext.equips.buttonItems[i] == ITEM_HOOKSHOT) { if (gSaveContext.equips.buttonItems[i] == ITEM_HOOKSHOT) {
gSaveContext.equips.buttonItems[i] = ITEM_LONGSHOT; gSaveContext.equips.buttonItems[i] = ITEM_LONGSHOT;
Interface_LoadItemIcon1(globalCtx, i); if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
} }
} }
// update the adult/child equips when rando'd (accounting for equp swapped hookshot as child) // update the adult/child equips when rando'd (accounting for equp swapped hookshot as child)
@ -1836,7 +1857,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) { for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) {
if (gSaveContext.adultEquips.buttonItems[i] == ITEM_HOOKSHOT) { if (gSaveContext.adultEquips.buttonItems[i] == ITEM_HOOKSHOT) {
gSaveContext.adultEquips.buttonItems[i] = ITEM_LONGSHOT; gSaveContext.adultEquips.buttonItems[i] = ITEM_LONGSHOT;
Interface_LoadItemIcon1(globalCtx, i); if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
} }
} }
} }
@ -1844,7 +1867,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (i = 1; i < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); i++) { for (i = 1; i < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); i++) {
if (gSaveContext.childEquips.buttonItems[i] == ITEM_HOOKSHOT) { if (gSaveContext.childEquips.buttonItems[i] == ITEM_HOOKSHOT) {
gSaveContext.childEquips.buttonItems[i] = ITEM_LONGSHOT; gSaveContext.childEquips.buttonItems[i] = ITEM_LONGSHOT;
Interface_LoadItemIcon1(globalCtx, i); if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
} }
} }
} }
@ -1989,7 +2014,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) { for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) {
if (gSaveContext.adultEquips.buttonItems[i] == ITEM_OCARINA_FAIRY) { if (gSaveContext.adultEquips.buttonItems[i] == ITEM_OCARINA_FAIRY) {
gSaveContext.adultEquips.buttonItems[i] = ITEM_OCARINA_TIME; gSaveContext.adultEquips.buttonItems[i] = ITEM_OCARINA_TIME;
Interface_LoadItemIcon1(globalCtx, i); if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
} }
} }
} }
@ -1997,7 +2024,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (i = 1; i < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); i++) { for (i = 1; i < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); i++) {
if (gSaveContext.childEquips.buttonItems[i] == ITEM_OCARINA_FAIRY) { if (gSaveContext.childEquips.buttonItems[i] == ITEM_OCARINA_FAIRY) {
gSaveContext.childEquips.buttonItems[i] = ITEM_OCARINA_TIME; gSaveContext.childEquips.buttonItems[i] = ITEM_OCARINA_TIME;
Interface_LoadItemIcon1(globalCtx, i); if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
} }
} }
} }
@ -2021,14 +2050,20 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
return ITEM_NONE; return ITEM_NONE;
} else if (item == ITEM_HEART) { } else if (item == ITEM_HEART) {
osSyncPrintf("回復ハート回復ハート回復ハート\n"); // "Recovery Heart" osSyncPrintf("回復ハート回復ハート回復ハート\n"); // "Recovery Heart"
Health_ChangeBy(globalCtx, 0x10); if (globalCtx != NULL) {
Health_ChangeBy(globalCtx, 0x10);
}
return item; return item;
} else if (item == ITEM_MAGIC_SMALL) { } else if (item == ITEM_MAGIC_SMALL) {
if (gSaveContext.unk_13F0 != 10) { if (gSaveContext.unk_13F0 != 10) {
Magic_Fill(globalCtx); if (globalCtx != NULL) {
Magic_Fill(globalCtx);
}
} }
func_80087708(globalCtx, 12, 5); if (globalCtx != NULL) {
func_80087708(globalCtx, 12, 5);
}
if (!(gSaveContext.infTable[25] & 0x100)) { if (!(gSaveContext.infTable[25] & 0x100)) {
gSaveContext.infTable[25] |= 0x100; gSaveContext.infTable[25] |= 0x100;
@ -2038,10 +2073,13 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
return item; return item;
} else if (item == ITEM_MAGIC_LARGE) { } else if (item == ITEM_MAGIC_LARGE) {
if (gSaveContext.unk_13F0 != 10) { if (gSaveContext.unk_13F0 != 10) {
Magic_Fill(globalCtx); if (globalCtx != NULL) {
Magic_Fill(globalCtx);
}
}
if (globalCtx != NULL) {
func_80087708(globalCtx, 24, 5);
} }
func_80087708(globalCtx, 24, 5);
if (!(gSaveContext.infTable[25] & 0x100)) { if (!(gSaveContext.infTable[25] & 0x100)) {
gSaveContext.infTable[25] |= 0x100; gSaveContext.infTable[25] |= 0x100;
@ -2080,7 +2118,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (int buttonIndex = 1; buttonIndex < ARRAY_COUNT(gSaveContext.equips.buttonItems); buttonIndex++) { for (int buttonIndex = 1; buttonIndex < ARRAY_COUNT(gSaveContext.equips.buttonItems); buttonIndex++) {
if ((temp + i) == gSaveContext.equips.cButtonSlots[buttonIndex - 1]) { if ((temp + i) == gSaveContext.equips.cButtonSlots[buttonIndex - 1]) {
gSaveContext.equips.buttonItems[buttonIndex] = item; gSaveContext.equips.buttonItems[buttonIndex] = item;
Interface_LoadItemIcon2(globalCtx, buttonIndex); if (globalCtx != NULL) {
Interface_LoadItemIcon2(globalCtx, buttonIndex);
}
gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(buttonIndex)] = BTN_ENABLED; gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(buttonIndex)] = BTN_ENABLED;
break; break;
} }
@ -2115,7 +2155,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
if (temp == gSaveContext.equips.buttonItems[i]) { if (temp == gSaveContext.equips.buttonItems[i]) {
if (item != ITEM_SOLD_OUT) { if (item != ITEM_SOLD_OUT) {
gSaveContext.equips.buttonItems[i] = item; gSaveContext.equips.buttonItems[i] = item;
Interface_LoadItemIcon1(globalCtx, i); if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
} else { } else {
gSaveContext.equips.buttonItems[i] = ITEM_NONE; gSaveContext.equips.buttonItems[i] = ITEM_NONE;
} }
@ -2132,7 +2174,7 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
INV_CONTENT(item) = item; INV_CONTENT(item) = item;
// Autosave after getting items by default (cvars are not shown in the UI) // Autosave after getting items by default (cvars are not shown in the UI)
if (CVar_GetS32("gAutosave", 0)) { if (CVar_GetS32("gAutosave", 0) && globalCtx != NULL) {
if (CVar_GetS32("gAutosaveAllItems", 1)) { if (CVar_GetS32("gAutosaveAllItems", 1)) {
Gameplay_PerformSave(globalCtx); Gameplay_PerformSave(globalCtx);
} }

View File

@ -4,7 +4,7 @@
#include <string.h> #include <string.h>
#include "soh/Enhancements/gameconsole.h" #include "soh/Enhancements/gameconsole.h"
#include "../libultraship/ImGuiImpl.h" #include <libultraship/ImGuiImpl.h>
#include "soh/frame_interpolation.h" #include "soh/frame_interpolation.h"
#include <time.h> #include <time.h>

View File

@ -54,31 +54,6 @@ void GiveLinkRupees(int numOfRupees) {
} }
} }
void GiveLinkRupeesByGetItemId(GetItemID giid) {
if (giid == GI_RUPEE_GREEN) {
GiveLinkRupees(1);
} else if (giid == GI_RUPEE_BLUE) {
GiveLinkRupees(5);
} else if (giid == GI_RUPEE_RED) {
GiveLinkRupees(20);
} else if (giid == GI_RUPEE_PURPLE) {
GiveLinkRupees(50);
} else if (giid == GI_RUPEE_GOLD) {
GiveLinkRupees(100);
}
}
void GiveLinkBombchus(GetItemID giid) {
INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU;
if (giid == GI_BOMBCHUS_5) {
AMMO(ITEM_BOMBCHU) += 5;
} else if (giid == GI_BOMBCHUS_10) {
AMMO(ITEM_BOMBCHU) += 10;
} else if (giid == GI_BOMBCHUS_20) {
AMMO(ITEM_BOMBCHU) += 20;
}
}
void GiveLinkDekuSticks(int howManySticks) { void GiveLinkDekuSticks(int howManySticks) {
int maxStickCount; int maxStickCount;
if (CUR_UPG_VALUE(UPG_STICKS) == 0) { if (CUR_UPG_VALUE(UPG_STICKS) == 0) {
@ -100,16 +75,6 @@ void GiveLinkDekuSticks(int howManySticks) {
} }
} }
void GiveLinkDekuSticksByGetItemId(GetItemID giid) {
if (giid == GI_STICKS_1) {
GiveLinkDekuSticks(1);
} else if (giid == GI_STICKS_5) {
GiveLinkDekuSticks(5);
} else if (giid == GI_STICKS_10) {
GiveLinkDekuSticks(10);
}
}
void GiveLinkDekuNuts(int howManyNuts) { void GiveLinkDekuNuts(int howManyNuts) {
int maxNutCount; int maxNutCount;
if (CUR_UPG_VALUE(UPG_NUTS) == 0) { if (CUR_UPG_VALUE(UPG_NUTS) == 0) {
@ -131,441 +96,18 @@ void GiveLinkDekuNuts(int howManyNuts) {
} }
} }
void GiveLinkDekuNutsByGetItemId(GetItemID giid) { void GiveLinksPocketItem() {
if (giid == GI_NUTS_5) { if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) < 3) {
GiveLinkDekuNuts(5); GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE);
} else if (giid == GI_NUTS_10) {
GiveLinkDekuNuts(10);
}
}
void GiveLinkBeans() { if (getItemEntry.modIndex == MOD_NONE) {
INV_CONTENT(ITEM_BEAN) = ITEM_BEAN; Item_Give(NULL, getItemEntry.itemId);
AMMO(ITEM_BEAN)++; } else if (getItemEntry.modIndex == MOD_RANDOMIZER) {
} Randomizer_Item_Give(NULL, getItemEntry);
void GiveLinkKokiriSword() {
uint32_t bitMask = 1 << 0;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkGiantsKnife() {
gSaveContext.bgsFlag = 0;
gSaveContext.swordHealth = 8;
uint32_t bitMask = 1 << 2;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkBiggoronSword() {
gSaveContext.bgsFlag = 1;
gSaveContext.swordHealth = 8;
uint32_t bitMask = 1 << 2;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkDekuShield() {
uint32_t bitMask = 1 << 4;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkHylianShield() {
uint32_t bitMask = 1 << 5;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkMirrorShield() {
uint32_t bitMask = 1 << 6;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkGoronTunic() {
uint32_t bitMask = 1 << 9;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkZoraTunic() {
uint32_t bitMask = 1 << 10;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkIronBoots() {
uint32_t bitMask = 1 << 13;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkHoverBoots() {
uint32_t bitMask = 1 << 14;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkStoneOfAgony() {
uint32_t bitMask = 1 << QUEST_STONE_OF_AGONY;
gSaveContext.inventory.questItems |= bitMask;
}
void GiveLinkGerudoCard() {
uint32_t bitMask = 1 << QUEST_GERUDO_CARD;
gSaveContext.inventory.questItems |= bitMask;
}
void GiveLinkPieceOfHeart() {
int32_t pohCount = (gSaveContext.inventory.questItems & 0xF0000000) >> 28;
pohCount++;
gSaveContext.inventory.questItems |= (pohCount << 28);
}
void GiveLinkHeartContainer() {
gSaveContext.healthCapacity += 16;
gSaveContext.health += 16;
}
void GiveLinkBulletBagUpgrade(GetItemID giid) {
if (giid == GI_SLINGSHOT) {
INV_CONTENT(ITEM_SLINGSHOT) = ITEM_SLINGSHOT;
AMMO(ITEM_SLINGSHOT) = 30;
Inventory_ChangeUpgrade(UPG_BULLET_BAG, 1);
} else if (giid == GI_BULLET_BAG_40) {
Inventory_ChangeUpgrade(UPG_BULLET_BAG, 2);
AMMO(ITEM_SLINGSHOT) = 40;
} else if (giid == GI_BULLET_BAG_50) {
Inventory_ChangeUpgrade(UPG_BULLET_BAG, 3);
AMMO(ITEM_SLINGSHOT) = 50;
}
}
void GiveLinkQuiverUpgrade(GetItemID giid) {
if (giid == GI_BOW) {
INV_CONTENT(ITEM_BOW) = ITEM_BOW;
Inventory_ChangeUpgrade(UPG_QUIVER, 1);
AMMO(ITEM_BOW) = 30;
} else if (giid == GI_QUIVER_40) {
Inventory_ChangeUpgrade(UPG_QUIVER, 2);
AMMO(ITEM_BOW) = 40;
} else if (giid == GI_QUIVER_50) {
Inventory_ChangeUpgrade(UPG_QUIVER, 3);
AMMO(ITEM_BOW) = 50;
}
}
void GiveLinkBombBagUpgrade(GetItemID giid) {
if (giid == GI_BOMB_BAG_20) {
INV_CONTENT(ITEM_BOMB) = ITEM_BOMB;
Inventory_ChangeUpgrade(UPG_BOMB_BAG, 1);
AMMO(ITEM_BOMB) = 20;
} else if (giid == GI_BOMB_BAG_30) {
Inventory_ChangeUpgrade(UPG_BOMB_BAG, 2);
AMMO(ITEM_BOMB) = 30;
} else if (giid == GI_BOMB_BAG_40) {
Inventory_ChangeUpgrade(UPG_BOMB_BAG, 3);
AMMO(ITEM_BOMB) = 40;
}
}
void GiveLinkStrengthUpgrade(GetItemID giid) {
if (giid == GI_BRACELET) {
Inventory_ChangeUpgrade(UPG_STRENGTH, 1);
} else if (giid == GI_GAUNTLETS_SILVER) {
Inventory_ChangeUpgrade(UPG_STRENGTH, 2);
} else if (giid == GI_GAUNTLETS_GOLD) {
Inventory_ChangeUpgrade(UPG_STRENGTH, 3);
}
}
void GiveLinkScaleUpgrade(GetItemID giid) {
if (giid == GI_SCALE_SILVER) {
Inventory_ChangeUpgrade(UPG_SCALE, 1);
} else if (giid == GI_SCALE_GOLD) {
Inventory_ChangeUpgrade(UPG_SCALE, 2);
}
}
void GiveLinkWalletUpgrade(GetItemID giid) {
if (giid == GI_WALLET_ADULT) {
Inventory_ChangeUpgrade(UPG_WALLET, 1);
} else if (giid == GI_WALLET_GIANT) {
Inventory_ChangeUpgrade(UPG_WALLET, 2);
}
}
void GiveLinkDekuStickUpgrade(GetItemID giid) {
if (giid == GI_STICK_UPGRADE_20) {
INV_CONTENT(ITEM_STICK) = ITEM_STICK;
Inventory_ChangeUpgrade(UPG_STICKS, 2);
AMMO(ITEM_STICK) = 20;
} else if (giid == GI_STICK_UPGRADE_30) {
Inventory_ChangeUpgrade(UPG_STICKS, 3);
AMMO(ITEM_STICK) = 30;
}
}
void GiveLinkDekuNutUpgrade(GetItemID giid) {
if (giid == GI_NUT_UPGRADE_30) {
INV_CONTENT(ITEM_NUT) = ITEM_NUT;
Inventory_ChangeUpgrade(UPG_NUTS, 2);
AMMO(ITEM_NUT) = 30;
} else if (giid == GI_NUT_UPGRADE_40) {
Inventory_ChangeUpgrade(UPG_NUTS, 3);
AMMO(ITEM_NUT) = 40;
}
}
void GiveLinkSkullToken() {
gSaveContext.inventory.questItems |= gBitFlags[QUEST_SKULL_TOKEN];
gSaveContext.inventory.gsTokens++;
}
void GiveLinkMagic(GetItemID giid) {
if (giid == RG_MAGIC_SINGLE) {
gSaveContext.magicLevel = 1;
gSaveContext.magicAcquired = true;
gSaveContext.doubleMagic = false;
} else if (giid == RG_MAGIC_DOUBLE) {
gSaveContext.magicLevel = 2;
gSaveContext.magicAcquired = true;
gSaveContext.doubleMagic = true;
}
}
void GiveLinkDoubleDefense() {
gSaveContext.doubleDefense = 1;
gSaveContext.inventory.defenseHearts = 20;
}
void GiveLinkSong(GetItemID getItemId) {
uint32_t bitMask;
switch (getItemId) {
case RG_ZELDAS_LULLABY:
bitMask = 1 << QUEST_SONG_LULLABY;
break;
case RG_SUNS_SONG:
bitMask = 1 << QUEST_SONG_SUN;
break;
case RG_EPONAS_SONG:
bitMask = 1 << QUEST_SONG_EPONA;
break;
case RG_SONG_OF_STORMS:
bitMask = 1 << QUEST_SONG_STORMS;
break;
case RG_SONG_OF_TIME:
bitMask = 1 << QUEST_SONG_TIME;
break;
case RG_SARIAS_SONG:
bitMask = 1 << QUEST_SONG_SARIA;
break;
case RG_MINUET_OF_FOREST:
bitMask = 1 << QUEST_SONG_MINUET;
break;
case RG_BOLERO_OF_FIRE:
bitMask = 1 << QUEST_SONG_BOLERO;
break;
case RG_SERENADE_OF_WATER:
bitMask = 1 << QUEST_SONG_SERENADE;
break;
case RG_NOCTURNE_OF_SHADOW:
bitMask = 1 << QUEST_SONG_NOCTURNE;
break;
case RG_REQUIEM_OF_SPIRIT:
bitMask = 1 << QUEST_SONG_REQUIEM;
break;
case RG_PRELUDE_OF_LIGHT:
bitMask = 1 << QUEST_SONG_PRELUDE;
break;
}
gSaveContext.inventory.questItems |= bitMask;
}
void GiveLinkDungeonReward(uint16_t getItemId) {
s16 item;
u8 medallion = 0;
switch (getItemId) {
case RG_FOREST_MEDALLION:
item = ITEM_MEDALLION_FOREST;
medallion = 1;
break;
case RG_FIRE_MEDALLION:
item = ITEM_MEDALLION_FIRE;
medallion = 1;
break;
case RG_WATER_MEDALLION:
item = ITEM_MEDALLION_WATER;
medallion = 1;
break;
case RG_SHADOW_MEDALLION:
item = ITEM_MEDALLION_SHADOW;
medallion = 1;
break;
case RG_SPIRIT_MEDALLION:
item = ITEM_MEDALLION_SPIRIT;
medallion = 1;
break;
case RG_LIGHT_MEDALLION:
item = ITEM_MEDALLION_LIGHT;
medallion = 1;
break;
case RG_KOKIRI_EMERALD:
item = ITEM_KOKIRI_EMERALD;
break;
case RG_GORON_RUBY:
item = ITEM_GORON_RUBY;
break;
case RG_ZORA_SAPPHIRE:
item = ITEM_ZORA_SAPPHIRE;
break;
}
if (medallion == 1) {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST];
} else {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_KOKIRI_EMERALD + QUEST_KOKIRI_EMERALD];
}
}
void GiveLinkDungeonItem(GetItemID getItemId) {
int mapIndex;
switch (getItemId) {
case RG_DEKU_TREE_MAP:
case RG_DEKU_TREE_COMPASS:
mapIndex = SCENE_YDAN;
break;
case RG_DODONGOS_CAVERN_MAP:
case RG_DODONGOS_CAVERN_COMPASS:
mapIndex = SCENE_DDAN;
break;
case RG_JABU_JABUS_BELLY_MAP:
case RG_JABU_JABUS_BELLY_COMPASS:
mapIndex = SCENE_BDAN;
break;
case RG_FOREST_TEMPLE_MAP:
case RG_FOREST_TEMPLE_COMPASS:
case RG_FOREST_TEMPLE_SMALL_KEY:
case RG_FOREST_TEMPLE_BOSS_KEY:
mapIndex = SCENE_BMORI1;
break;
case RG_FIRE_TEMPLE_MAP:
case RG_FIRE_TEMPLE_COMPASS:
case RG_FIRE_TEMPLE_SMALL_KEY:
case RG_FIRE_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HIDAN;
break;
case RG_WATER_TEMPLE_MAP:
case RG_WATER_TEMPLE_COMPASS:
case RG_WATER_TEMPLE_SMALL_KEY:
case RG_WATER_TEMPLE_BOSS_KEY:
mapIndex = SCENE_MIZUSIN;
break;
case RG_SPIRIT_TEMPLE_MAP:
case RG_SPIRIT_TEMPLE_COMPASS:
case RG_SPIRIT_TEMPLE_SMALL_KEY:
case RG_SPIRIT_TEMPLE_BOSS_KEY:
mapIndex = SCENE_JYASINZOU;
break;
case RG_SHADOW_TEMPLE_MAP:
case RG_SHADOW_TEMPLE_COMPASS:
case RG_SHADOW_TEMPLE_SMALL_KEY:
case RG_SHADOW_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HAKADAN;
break;
case RG_BOTTOM_OF_THE_WELL_MAP:
case RG_BOTTOM_OF_THE_WELL_COMPASS:
case RG_BOTTOM_OF_THE_WELL_SMALL_KEY:
mapIndex = SCENE_HAKADANCH;
break;
case RG_ICE_CAVERN_MAP:
case RG_ICE_CAVERN_COMPASS:
mapIndex = SCENE_ICE_DOUKUTO;
break;
case RG_GANONS_CASTLE_BOSS_KEY:
mapIndex = SCENE_GANON;
break;
case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY:
mapIndex = SCENE_MEN;
break;
case RG_GERUDO_FORTRESS_SMALL_KEY:
mapIndex = SCENE_GERUDOWAY;
break;
case RG_GANONS_CASTLE_SMALL_KEY:
mapIndex = SCENE_GANONTIKA;
break;
}
if ((getItemId >= RG_GERUDO_FORTRESS_SMALL_KEY) && (getItemId <= RG_GANONS_CASTLE_SMALL_KEY)) {
if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[mapIndex] = 1;
} else {
gSaveContext.inventory.dungeonKeys[mapIndex]++;
} }
} else {
int bitmask;
if ((getItemId >= RG_DEKU_TREE_MAP) && (getItemId <= RG_ICE_CAVERN_MAP)) {
bitmask = gBitFlags[2];
} else if ((getItemId >= RG_DEKU_TREE_COMPASS) && (getItemId <= RG_ICE_CAVERN_COMPASS)) {
bitmask = gBitFlags[1];
} else {
bitmask = gBitFlags[0];
}
gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask;
} }
} }
void GiveLinkAdultTradeItem(GetItemID giid) {
ItemID item;
switch (giid) {
case GI_POCKET_EGG:
item = ITEM_POCKET_EGG;
break;
case GI_POCKET_CUCCO:
item = ITEM_POCKET_CUCCO;
break;
case GI_COJIRO:
item = ITEM_COJIRO;
break;
case GI_ODD_MUSHROOM:
item = ITEM_ODD_MUSHROOM;
break;
case GI_ODD_POTION:
item = ITEM_ODD_POTION;
break;
case GI_SAW:
item = ITEM_SAW;
break;
case GI_SWORD_BROKEN:
item = ITEM_SWORD_BROKEN;
break;
case GI_PRESCRIPTION:
item = ITEM_PRESCRIPTION;
break;
case GI_FROG:
item = ITEM_FROG;
break;
case GI_EYEDROPS:
item = ITEM_EYEDROPS;
break;
case GI_CLAIM_CHECK:
item = ITEM_CLAIM_CHECK;
break;
}
if ((item == ITEM_SAW) && CVar_GetS32("gDekuNutUpgradeFix", 0) == 0) {
gSaveContext.itemGetInf[1] |= 0x8000;
}
if (item >= ITEM_POCKET_EGG) {
gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(item);
}
INV_CONTENT(ITEM_TRADE_ADULT) = item;
}
void GiveLinksPocketMedallion() {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE);
GiveLinkDungeonReward(getItemEntry.getItemId);
}
/** /**
* Copy save currently on the buffer to Save Context and complete various tasks to open the save. * Copy save currently on the buffer to Save Context and complete various tasks to open the save.
* This includes: * This includes:
@ -802,7 +344,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
} }
// Give Link's pocket item // Give Link's pocket item
GiveLinksPocketMedallion(); GiveLinksPocketItem();
int openForest = Randomizer_GetSettingValue(RSK_FOREST); int openForest = Randomizer_GetSettingValue(RSK_FOREST);
switch (openForest) { switch (openForest) {
@ -831,8 +373,8 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
break; break;
} }
if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) GiveLinkKokiriSword(); if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) Item_Give(NULL, ITEM_SWORD_KOKIRI);
if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) GiveLinkDekuShield(); if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) Item_Give(NULL, ITEM_SHIELD_DEKU);
if(Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) { if(Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) {
INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY;
@ -858,73 +400,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
s32 giid = getItem.getItemId; s32 giid = getItem.getItemId;
if (getItem.modIndex == MOD_NONE) { if (getItem.modIndex == MOD_NONE) {
if (getItem.itemId >= ITEM_MEDALLION_FOREST && getItem.itemId <= ITEM_ZORA_SAPPHIRE) { Item_Give(NULL, getItem.itemId);
GiveLinkDungeonReward(getItem.getItemId);
} else if (getItem.itemId >= ITEM_SONG_MINUET && getItem.itemId <= ITEM_SONG_STORMS) {
GiveLinkSong(getItem.getItemId);
} else if (giid == GI_RUPEE_GREEN || giid == GI_RUPEE_BLUE || giid == GI_RUPEE_RED ||
giid == GI_RUPEE_PURPLE || giid == GI_RUPEE_GOLD) {
GiveLinkRupeesByGetItemId(giid);
} else if (giid == GI_BOMBCHUS_10 || giid == GI_BOMBCHUS_5 || giid == GI_BOMBCHUS_20) {
GiveLinkBombchus(giid);
} else if (giid == GI_STICKS_1 || giid == GI_STICKS_5 || giid == GI_STICKS_10) {
GiveLinkDekuSticksByGetItemId(giid);
} else if (giid == GI_NUTS_5 || giid == GI_NUTS_10) {
GiveLinkDekuNutsByGetItemId(giid);
} else if (giid == GI_BEAN) {
GiveLinkBeans();
} else if (giid == GI_SWORD_KOKIRI) {
GiveLinkKokiriSword();
} else if (giid == GI_SWORD_BGS) {
GiveLinkBiggoronSword();
} else if (giid == GI_SWORD_KNIFE) {
GiveLinkGiantsKnife();
} else if (giid == GI_SHIELD_DEKU) {
GiveLinkDekuShield();
} else if (giid == GI_SHIELD_HYLIAN) {
GiveLinkHylianShield();
} else if (giid == GI_SHIELD_MIRROR) {
GiveLinkMirrorShield();
} else if (giid == GI_TUNIC_GORON) {
GiveLinkGoronTunic();
} else if (giid == GI_TUNIC_ZORA) {
GiveLinkZoraTunic();
} else if (giid == GI_BOOTS_IRON) {
GiveLinkIronBoots();
} else if (giid == GI_BOOTS_HOVER) {
GiveLinkHoverBoots();
} else if (giid == GI_SLINGSHOT || giid == GI_BULLET_BAG_40 || giid == GI_BULLET_BAG_50) {
GiveLinkBulletBagUpgrade(giid);
} else if (giid == GI_BOW || giid == GI_QUIVER_40 || giid == GI_QUIVER_50) {
GiveLinkQuiverUpgrade(giid);
} else if (giid == GI_BOMB_BAG_20 || giid == GI_BOMB_BAG_30 || giid == GI_BOMB_BAG_40) {
GiveLinkBombBagUpgrade(giid);
} else if (giid == GI_BRACELET || giid == GI_GAUNTLETS_SILVER || giid == GI_GAUNTLETS_GOLD) {
GiveLinkStrengthUpgrade(giid);
} else if (giid == GI_SCALE_SILVER || giid == GI_SCALE_GOLD) {
GiveLinkScaleUpgrade(giid);
} else if (giid == GI_WALLET_ADULT || giid == GI_WALLET_GIANT) {
GiveLinkWalletUpgrade(giid);
} else if (giid == GI_STONE_OF_AGONY) {
GiveLinkStoneOfAgony();
} else if (giid == GI_GERUDO_CARD) {
GiveLinkGerudoCard();
} else if (giid == GI_HEART_PIECE) {
GiveLinkPieceOfHeart();
} else if (giid == GI_HEART_CONTAINER) {
GiveLinkHeartContainer();
} else if (giid == GI_STICK_UPGRADE_20 || giid == GI_STICK_UPGRADE_30) {
GiveLinkDekuStickUpgrade(giid);
} else if (giid == GI_NUT_UPGRADE_30 || giid == GI_NUT_UPGRADE_40) {
GiveLinkDekuNutUpgrade(giid);
} else if (giid == GI_SKULL_TOKEN) {
GiveLinkSkullToken();
} else if (giid >= GI_POCKET_EGG && giid <= GI_CLAIM_CHECK || giid == GI_COJIRO) {
GiveLinkAdultTradeItem(giid);
} else {
s32 iid = getItem.itemId;
if (iid != -1) INV_CONTENT(iid) = iid;
}
} else if (getItem.modIndex == MOD_RANDOMIZER) { } else if (getItem.modIndex == MOD_RANDOMIZER) {
Randomizer_Item_Give(NULL, getItem); Randomizer_Item_Give(NULL, getItem);
} }
@ -1033,7 +509,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
gSaveContext.sceneFlags[12].collect |= (1 << 0x0C); gSaveContext.sceneFlags[12].collect |= (1 << 0x0C);
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
GiveLinkGerudoCard(); Item_Give(NULL, ITEM_GERUDO_CARD);
} }
} }

View File

@ -88,7 +88,7 @@ s32 DemoKekkai_CheckEventFlag(s32 params) {
if ((params < KEKKAI_TOWER) || (params > KEKKAI_FOREST)) { if ((params < KEKKAI_TOWER) || (params > KEKKAI_FOREST)) {
return true; return true;
} }
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag && params > KEKKAI_TOWER) {
return Flags_GetRandomizerInf(trialParamToRandInf(params)); return Flags_GetRandomizerInf(trialParamToRandInf(params));
} }
return Flags_GetEventChkInf(eventFlags[params]); return Flags_GetEventChkInf(eventFlags[params]);

View File

@ -10,7 +10,7 @@
#include "alloca.h" #include "alloca.h"
#include "textures/nintendo_rogo_static/nintendo_rogo_static.h" #include "textures/nintendo_rogo_static/nintendo_rogo_static.h"
#include <soh/Enhancements/bootcommands.h> #include <soh/Enhancements/bootcommands.h>
#include "GameVersions.h" #include <libultraship/GameVersions.h>
#include <soh/SaveManager.h> #include <soh/SaveManager.h>
const char* GetGameVersionString(); const char* GetGameVersionString();
@ -301,6 +301,9 @@ void Title_Init(GameState* thisx) {
saveloading = true; saveloading = true;
gSaveContext.fileNum = selectedfile; gSaveContext.fileNum = selectedfile;
Sram_OpenSave(); Sram_OpenSave();
Randomizer_LoadSettings("");
Randomizer_LoadHintLocations("");
Randomizer_LoadItemLocations("", true);
gSaveContext.gameMode = 0; gSaveContext.gameMode = 0;
gSaveContext.magic = gSaveContext.magic; gSaveContext.magic = gSaveContext.magic;
SET_NEXT_GAMESTATE(&this->state, Gameplay_Init, GlobalContext); SET_NEXT_GAMESTATE(&this->state, Gameplay_Init, GlobalContext);