mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-11 20:15:07 -05:00
commit
4761b0e3cf
32
BUILDING.md
32
BUILDING.md
@ -2,9 +2,27 @@
|
||||
|
||||
## Windows
|
||||
|
||||
1. Requires Visual Studio 2022 Community Edition && `python3, cmake, git` (can be installed via chocolatey or manually)
|
||||
2. Clone the Ship of Harkinian repository
|
||||
3. Place one or more [compatible](#compatible-roms) roms in the `OTRExporter` directory with namings of your choice
|
||||
Requires:
|
||||
* At least 8GB of RAM (machines with 4GB have seen complier failures)
|
||||
* Visual Studio 2022 Community Edition with the C++ feature set
|
||||
* One of the Windows SDKs that comes with Visual Studio, for example the current Windows 10 version 10.0.19041.0
|
||||
* The `MSVC v142 - VS 2019 C++ build tools` component of Visual Studio
|
||||
* Python 3 (can be installed manually or as part of Visual Studio)
|
||||
* Git (can be installed manually or as part of Visual Studio)
|
||||
* Cmake (can be installed via chocolatey or manually)
|
||||
|
||||
During installation, check the "Desktop development with C++" feature set:
|
||||
|
||||
![image](https://user-images.githubusercontent.com/30329717/183511274-d11aceea-7900-46ec-acb6-3f2cc110021a.png)
|
||||
Doing so should also check one of the Windows SDKs by default. Then, in the installation details in the right-hand column, make sure you also check the v142 toolset.
|
||||
|
||||
You can also find the v142 toolset by searching through the individual components tab:
|
||||
|
||||
![image](https://user-images.githubusercontent.com/30329717/183521169-ead6a73b-a1bf-4e99-aab8-441746d8f08e.png)
|
||||
While you're there, you can also install Python 3 and Git if needed.
|
||||
|
||||
1. Clone the Ship of Harkinian repository
|
||||
2. Place one or more [compatible](#compatible-roms) roms in the `OTRExporter` directory with namings of your choice
|
||||
|
||||
_Note: Instructions assume using powershell_
|
||||
```powershell
|
||||
@ -30,8 +48,10 @@ With the cmake build system you have two options for working on the project:
|
||||
#### Visual Studio
|
||||
To develop using Visual Studio you only need to use cmake to generate the solution file:
|
||||
```powershell
|
||||
# Generates Ship.sln at `build/x64`
|
||||
# Generates Ship.sln at `build/x64` for Visual Studio 2022
|
||||
& 'C:\Program Files\CMake\bin\cmake' -S . -B "build/x64" -G "Visual Studio 17 2022" -T v142 -A x64
|
||||
# or for Visual Studio 2019
|
||||
& 'C:\Program Files\CMake\bin\cmake' -S . -B "build/x64" -G "Visual Studio 16 2019" -T v142 -A x64
|
||||
```
|
||||
|
||||
#### Visual Studio Code or another editor
|
||||
@ -53,7 +73,7 @@ cd "build/x64"
|
||||
```
|
||||
|
||||
## Linux
|
||||
1. Requires `gcc >= 10, x11, curl, python3, sdl2 >= 2.0.22, libpng, glew >= 2.2, ninja, cmake, lld`
|
||||
Requires `gcc >= 10, x11, curl, python3, sdl2 >= 2.0.22, libpng, glew >= 2.2, ninja, cmake, lld`
|
||||
|
||||
**Important: For maximum performance make sure you have ninja build tools installed!**
|
||||
|
||||
@ -91,7 +111,7 @@ cpack -G External (creates appimage)
|
||||
```
|
||||
|
||||
## macOS
|
||||
1. Requires Xcode (or xcode-tools) && `sdl2, libpng, glew, ninja, cmake` (can be installed via homebrew, macports, etc)
|
||||
Requires Xcode (or xcode-tools) && `sdl2, libpng, glew, ninja, cmake` (can be installed via homebrew, macports, etc)
|
||||
|
||||
**Important: For maximum performance make sure you have ninja build tools installed!**
|
||||
|
||||
|
5
CMake/genscript.cmake
Normal file
5
CMake/genscript.cmake
Normal file
@ -0,0 +1,5 @@
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/extract_assets.py filedata)
|
||||
string(REGEX REPLACE "zapd_exe = .*exec_cmd =" "zapd_exe = \"${program}\"\n exec_cmd =" filedata "${filedata}")
|
||||
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/extract_assets_cmake2.py" "${filedata}")
|
||||
file(CHMOD "${CMAKE_CURRENT_SOURCE_DIR}/extract_assets_cmake2.py" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
|
@ -20,6 +20,9 @@ add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
include(cmake/automate-vcpkg.cmake)
|
||||
|
||||
set(VCPKG_TRIPLET x64-windows-static)
|
||||
set(VCPKG_TARGET_TRIPLET x64-windows-static)
|
||||
|
||||
vcpkg_bootstrap()
|
||||
vcpkg_install_packages(zlib bzip2 libpng)
|
||||
endif()
|
||||
@ -42,11 +45,16 @@ endif()
|
||||
################################################################################
|
||||
# Global configuration types
|
||||
################################################################################
|
||||
set(CMAKE_CONFIGURATION_TYPES
|
||||
"Debug"
|
||||
"Release"
|
||||
CACHE STRING "" FORCE
|
||||
)
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
|
||||
set(CMAKE_C_FLAGS_DEBUG "-O3 -ffast-math")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-O3 -ffast-math")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -ffast-math -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -ffast-math -DNDEBUG")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
||||
set(CMAKE_OBJCXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE )
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE)
|
||||
@ -126,25 +134,19 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||
INSTALL(PROGRAMS "${CMAKE_SOURCE_DIR}/scripts/linux/appimage/soh.sh" DESTINATION . COMPONENT appimage)
|
||||
endif()
|
||||
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py filedata)
|
||||
string(REGEX REPLACE "../ZAPDTR/ZAPD.out" "${CMAKE_BINARY_DIR}/ZAPD/ZAPD.out" filedata "${filedata}")
|
||||
string(REGEX REPLACE "x64" "..\\\\\\\\x64" filedata "${filedata}")
|
||||
string(REGEX REPLACE "Release" "${CMAKE_BUILD_TYPE}" filedata "${filedata}")
|
||||
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets_cmake2.py" "${filedata}")
|
||||
file(CHMOD "${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets_cmake2.py" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
|
||||
find_package(Python3 COMPONENTS Interpreter)
|
||||
|
||||
add_custom_target(
|
||||
ExtractAssets
|
||||
COMMAND ${CMAKE_COMMAND} -Dprogram=$<TARGET_FILE:ZAPD> -P ${CMAKE_SOURCE_DIR}/CMake/genscript.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f oot.otr
|
||||
COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets_cmake2.py
|
||||
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets_cmake2.py
|
||||
COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${CMAKE_SOURCE_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${CMAKE_BINARY_DIR}/soh
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
|
||||
COMMENT "Running asset extraction..."
|
||||
DEPENDS ZAPD
|
||||
|
||||
BYPRODUCTS oot.otr ${CMAKE_SOURCE_DIR}/oot.otr ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets_cmake2.py
|
||||
)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
|
68
Jenkinsfile
vendored
68
Jenkinsfile
vendored
@ -8,12 +8,35 @@ pipeline {
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Generate Assets') {
|
||||
options {
|
||||
timeout(time: 10)
|
||||
}
|
||||
agent {
|
||||
label "SoH-Mac-Builders"
|
||||
}
|
||||
steps {
|
||||
checkout([
|
||||
$class: 'GitSCM',
|
||||
branches: scm.branches,
|
||||
doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
|
||||
extensions: scm.extensions,
|
||||
userRemoteConfigs: scm.userRemoteConfigs
|
||||
])
|
||||
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
||||
sh '''
|
||||
cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64
|
||||
|
||||
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release
|
||||
cmake --build build-cmake --target ExtractAssets --config Release
|
||||
'''
|
||||
stash includes: 'soh/assets/**/*', name: 'assets'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Build SoH') {
|
||||
parallel {
|
||||
stage ('Build Windows') {
|
||||
options {
|
||||
timeout(time: 20)
|
||||
}
|
||||
environment {
|
||||
PLATFORM='x64'
|
||||
PYTHON='C:\\Users\\jenkins\\AppData\\Local\\Programs\\Python\\Python310\\python.exe'
|
||||
@ -34,12 +57,9 @@ pipeline {
|
||||
])
|
||||
|
||||
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
||||
bat """
|
||||
|
||||
xcopy "..\\..\\ZELOOTD.z64" "OTRExporter\\"
|
||||
|
||||
unstash 'assets'
|
||||
bat """
|
||||
"${env.CMAKE}" -S . -B "build\\${env.PLATFORM}" -G "Visual Studio 17 2022" -T ${env.TOOLSET} -A ${env.PLATFORM} -D Python_EXECUTABLE=${env.PYTHON} -D CMAKE_BUILD_TYPE:STRING=Release
|
||||
"${env.CMAKE}" --build ".\\build\\${env.PLATFORM}" --target ExtractAssets --config Release
|
||||
"${env.CMAKE}" --build ".\\build\\${env.PLATFORM}" --config Release
|
||||
cd ".\\build\\${env.PLATFORM}"
|
||||
"${env.CPACK}" -G ZIP
|
||||
@ -47,8 +67,8 @@ pipeline {
|
||||
|
||||
move "_packages\\*.zip" "soh.zip"
|
||||
"""
|
||||
archiveArtifacts artifacts: 'soh.zip', followSymlinks: false, onlyIfSuccessful: true
|
||||
}
|
||||
archiveArtifacts artifacts: 'soh.zip', followSymlinks: false, onlyIfSuccessful: true
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@ -57,9 +77,6 @@ pipeline {
|
||||
}
|
||||
}
|
||||
stage ('Build Linux') {
|
||||
options {
|
||||
timeout(time: 20)
|
||||
}
|
||||
agent {
|
||||
label "SoH-Linux-Builders"
|
||||
}
|
||||
@ -72,9 +89,9 @@ pipeline {
|
||||
userRemoteConfigs: scm.userRemoteConfigs
|
||||
])
|
||||
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
||||
unstash 'assets'
|
||||
sh '''
|
||||
|
||||
cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64
|
||||
if docker ps -aq --filter "name=sohcont" | grep -q .; then docker rm -f sohcont; fi
|
||||
docker build . -t soh
|
||||
docker run --name sohcont -dit --rm -v $(pwd):/soh soh /bin/bash
|
||||
docker exec sohcont scripts/linux/appimage/build.sh
|
||||
@ -86,11 +103,12 @@ pipeline {
|
||||
|
||||
'''
|
||||
}
|
||||
sh 'sudo docker container stop sohcont'
|
||||
archiveArtifacts artifacts: 'soh-linux.7z', followSymlinks: false, onlyIfSuccessful: true
|
||||
}
|
||||
post {
|
||||
always {
|
||||
sh 'sudo docker container stop sohcont'
|
||||
sh 'docker images --quiet --filter=dangling=true | xargs --no-run-if-empty docker rmi' // Clean dangling docker images
|
||||
step([$class: 'WsCleanup']) // Clean workspace
|
||||
}
|
||||
}
|
||||
@ -108,11 +126,9 @@ pipeline {
|
||||
userRemoteConfigs: scm.userRemoteConfigs
|
||||
])
|
||||
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
||||
unstash 'assets'
|
||||
sh '''
|
||||
cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64
|
||||
|
||||
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
cmake --build build-cmake --target ExtractAssets --
|
||||
cmake --build build-cmake --config Release --
|
||||
(cd build-cmake && cpack)
|
||||
|
||||
@ -131,9 +147,6 @@ pipeline {
|
||||
}
|
||||
}
|
||||
stage ('Build Switch') {
|
||||
options {
|
||||
timeout(time: 20)
|
||||
}
|
||||
agent {
|
||||
label "SoH-Linux-Builders"
|
||||
}
|
||||
@ -146,12 +159,12 @@ pipeline {
|
||||
userRemoteConfigs: scm.userRemoteConfigs
|
||||
])
|
||||
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
||||
sh '''
|
||||
|
||||
cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64
|
||||
unstash 'assets'
|
||||
sh '''
|
||||
if docker ps -aq --filter "name=sohswitchcont" | grep -q .; then docker rm -f sohswitchcont; fi
|
||||
docker build . -t sohswitch
|
||||
docker run --name sohcont -dit --rm -v $(pwd):/soh sohswitch /bin/bash
|
||||
docker exec sohcont scripts/switch/build.sh
|
||||
docker run --name sohswitchcont -dit --rm -v $(pwd):/soh sohswitch /bin/bash
|
||||
docker exec sohswitchcont scripts/switch/build.sh
|
||||
|
||||
mv build-switch/soh/*.nro soh.nro
|
||||
mv README.md readme.txt
|
||||
@ -160,11 +173,12 @@ pipeline {
|
||||
|
||||
'''
|
||||
}
|
||||
sh 'sudo docker container stop sohcont'
|
||||
archiveArtifacts artifacts: 'soh-switch.7z', followSymlinks: false, onlyIfSuccessful: true
|
||||
}
|
||||
post {
|
||||
always {
|
||||
sh 'sudo docker container stop sohswitchcont'
|
||||
sh 'docker images --quiet --filter=dangling=true | xargs --no-run-if-empty docker rmi' // Clean dangling docker images
|
||||
step([$class: 'WsCleanup']) // Clean workspace
|
||||
}
|
||||
}
|
||||
|
@ -348,11 +348,14 @@ std::string ZResource::GetSourceOutputHeader([[maybe_unused]] const std::string&
|
||||
str += StringHelper::Sprintf("#define d%s \"__OTR__%s/%s\"", name.c_str(), outName.c_str(), nameStr.c_str());
|
||||
|
||||
if (nameSet && nameSet->find(name) == nameSet->end()) {
|
||||
str += StringHelper::Sprintf(R"(
|
||||
#ifdef _WIN32
|
||||
str += StringHelper::Sprintf("\nstatic const __declspec(align(2)) char %s[] = d%s;", name.c_str(), name.c_str());
|
||||
static const __declspec(align(2)) char %s[] = d%s;
|
||||
#else
|
||||
str += StringHelper::Sprintf("\nstatic const char %s[] __attribute__((aligned (2))) = d%s;", name.c_str(), name.c_str());
|
||||
static const char %s[] __attribute__((aligned (2))) = d%s;
|
||||
#endif
|
||||
)", name.c_str(), name.c_str(), name.c_str(), name.c_str());
|
||||
|
||||
if (nameSet) {
|
||||
nameSet->insert(name);
|
||||
}
|
||||
|
@ -100,11 +100,15 @@ namespace Ship {
|
||||
}
|
||||
|
||||
void Console::Draw() {
|
||||
if (!this->opened) {
|
||||
CVar_SetS32("gConsoleEnabled", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
bool input_focus = false;
|
||||
if (!this->opened) return;
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
|
||||
ImGui::Begin("Console", nullptr, ImGuiWindowFlags_NoFocusOnAppearing);
|
||||
ImGui::Begin("Console", &this->opened, ImGuiWindowFlags_NoFocusOnAppearing);
|
||||
const ImVec2 pos = ImGui::GetWindowPos();
|
||||
const ImVec2 size = ImGui::GetWindowSize();
|
||||
// SohImGui::ShowCursor(ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows | ImGuiHoveredFlags_RectOnly), SohImGui::Dialogues::dConsole);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "KeyboardController.h"
|
||||
#include "SDLController.h"
|
||||
#include <Utils/StringHelper.h>
|
||||
#include "Cvar.h"
|
||||
|
||||
namespace Ship {
|
||||
uint8_t* controllerBits;
|
||||
@ -51,18 +52,31 @@ namespace Ship {
|
||||
*controllerBits |= (backend->Connected()) << slot;
|
||||
}
|
||||
|
||||
void ControlDeck::WriteToPad(OSContPad* pad) const {
|
||||
for (size_t i = 0; i < virtualDevices.size(); i++) {
|
||||
const std::shared_ptr<Controller> backend = physicalDevices[virtualDevices[i]];
|
||||
if (backend->GetGuid() == "Auto") {
|
||||
for (const auto& device : physicalDevices) {
|
||||
device->Read(&pad[i], i);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
backend->Read(&pad[i], i);
|
||||
}
|
||||
}
|
||||
void ControlDeck::WriteToPad(OSContPad* pad) const {
|
||||
|
||||
#ifdef __SWITCH__
|
||||
bool shouldBlockGameInput = CVar_GetS32("gOpenMenuBar", 0);
|
||||
#else
|
||||
bool shouldBlockGameInput = CVar_GetS32("gOpenMenuBar", 0) && CVar_GetS32("gControlNav", 0);
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < virtualDevices.size(); i++) {
|
||||
const std::shared_ptr<Controller> backend = physicalDevices[virtualDevices[i]];
|
||||
if (backend->GetGuid() == "Auto") {
|
||||
for (const auto& device : physicalDevices) {
|
||||
if(shouldBlockGameInput && device->GetGuid() != "Keyboard") {
|
||||
continue;
|
||||
}
|
||||
device->Read(&pad[i], i);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(shouldBlockGameInput && backend->GetGuid() != "Keyboard") {
|
||||
continue;
|
||||
}
|
||||
backend->Read(&pad[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
#define NESTED(key, ...) StringHelper::Sprintf("Controllers.%s.Slot_%d." key, device->GetGuid().c_str(), slot, __VA_ARGS__)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -86,6 +86,12 @@ namespace SohImGui {
|
||||
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 DrawFramebufferAndGameInput(void);
|
||||
@ -106,6 +112,12 @@ namespace SohImGui {
|
||||
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);
|
||||
void PaddedText(const char* text, bool padTop = true, bool padBottom = true);
|
||||
std::string GetWindowButtonText(const char* text, bool menuOpen);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -166,10 +166,12 @@ static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen, uint32
|
||||
#ifdef __SWITCH__
|
||||
// For Switch we need to set the window width before creating the window
|
||||
Ship::Switch::GetDisplaySize(&window_width, &window_height);
|
||||
width = window_width;
|
||||
height = window_height;
|
||||
#endif
|
||||
|
||||
wnd = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
|
||||
#ifndef __SWITCH__
|
||||
SDL_GL_GetDrawableSize(wnd, &window_width, &window_height);
|
||||
|
@ -82,19 +82,14 @@ namespace Ship {
|
||||
break;
|
||||
}
|
||||
|
||||
//Lock.lock();
|
||||
std::shared_ptr<File> ToLoad = FileLoadQueue.front();
|
||||
FileLoadQueue.pop();
|
||||
//Lock.unlock();
|
||||
|
||||
OTR->LoadFile(ToLoad->path, true, ToLoad);
|
||||
//Lock.lock();
|
||||
|
||||
if (!ToLoad->bHasLoadError)
|
||||
FileCache[ToLoad->path] = ToLoad->bIsLoaded && !ToLoad->bHasLoadError ? ToLoad : nullptr;
|
||||
|
||||
//Lock.unlock();
|
||||
|
||||
SPDLOG_DEBUG("Loaded File {} on ResourceMgr thread", ToLoad->path);
|
||||
|
||||
ToLoad->FileLoadNotifier.notify_all();
|
||||
@ -117,10 +112,8 @@ namespace Ship {
|
||||
}
|
||||
|
||||
std::shared_ptr<ResourcePromise> ToLoad = nullptr;
|
||||
//ResLock.lock();
|
||||
ToLoad = ResourceLoadQueue.front();
|
||||
ResourceLoadQueue.pop();
|
||||
//ResLock.unlock();
|
||||
|
||||
// Wait for the underlying File to complete loading
|
||||
{
|
||||
@ -148,9 +141,6 @@ namespace Ship {
|
||||
|
||||
SPDLOG_DEBUG("Loaded Resource {} on ResourceMgr thread", ToLoad->file->path);
|
||||
|
||||
// Disabled for now because it can cause random crashes
|
||||
//FileCache[Res->File->path] = nullptr;
|
||||
//FileCache.erase(FileCache.find(Res->File->path));
|
||||
Res->file = nullptr;
|
||||
}
|
||||
else {
|
||||
@ -159,9 +149,6 @@ namespace Ship {
|
||||
|
||||
SPDLOG_ERROR("Resource load FAILED {} on ResourceMgr thread", ToLoad->file->path);
|
||||
}
|
||||
|
||||
//ResLock.lock();
|
||||
//ResLock.unlock();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include "Console.h"
|
||||
#include "Cvar.h"
|
||||
#include "ImGuiImpl.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -67,10 +67,9 @@ extern "C" {
|
||||
pad->gyro_x = 0;
|
||||
pad->gyro_y = 0;
|
||||
|
||||
if (!CVar_GetS32("gOpenMenuBar", 0)) {
|
||||
Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck()->WriteToPad(pad);
|
||||
}
|
||||
if (SohImGui::controller->Opened) return;
|
||||
|
||||
Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck()->WriteToPad(pad);
|
||||
Ship::ExecuteHooks<Ship::ControllerRead>(pad);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release
|
||||
cmake --build build-cmake --target ExtractAssets --
|
||||
cmake --build build-cmake --config Release --
|
||||
|
||||
(cd build-cmake && cpack -G External)
|
||||
|
@ -1,7 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
cmake --no-warn-unused-cli -H. -Bbuild-linux -GNinja
|
||||
cmake --build build-linux --target ExtractAssets
|
||||
|
||||
cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake
|
||||
cmake --build build-switch --target soh_nro
|
||||
|
@ -215,6 +215,13 @@ set(Header_Files__soh__Enhancements__randomizer__3drando
|
||||
)
|
||||
source_group("Header Files\\soh\\Enhancements\\randomizer\\3drando" FILES ${Header_Files__soh__Enhancements__randomizer__3drando})
|
||||
|
||||
set(Header_Files__soh__Enhancements__custom_message
|
||||
"soh/Enhancements/custom-message/CustomMessageTypes.h"
|
||||
"soh/Enhancements/custom-message/CustomMessageManager.h"
|
||||
)
|
||||
|
||||
source_group("Header Files\\soh\\Enhancements\\custom-message" FILES ${Header_Files__soh__Enhancements__custom_message})
|
||||
|
||||
set(Source_Files__soh
|
||||
"soh/GbiWrap.cpp"
|
||||
"soh/OTRAudio.h"
|
||||
@ -326,6 +333,12 @@ set(Source_Files__soh__Enhancements__randomizer__3drando__location_access
|
||||
)
|
||||
source_group("Source Files\\soh\\Enhancements\\randomizer\\3drando\\location_access" FILES ${Source_Files__soh__Enhancements__randomizer__3drando__location_access})
|
||||
|
||||
set(Source_Files__soh__Enhancements__custom_message
|
||||
"soh/Enhancements/custom-message/CustomMessageManager.cpp"
|
||||
)
|
||||
|
||||
source_group("Source Files\\soh\\Enhancements\\custom-message" FILES ${Source_Files__soh__Enhancements__custom_message})
|
||||
|
||||
set(Source_Files__src__boot
|
||||
"src/boot/assert.c"
|
||||
"src/boot/boot_main.c"
|
||||
@ -1534,6 +1547,7 @@ set(ALL_FILES
|
||||
${Header_Files__soh__Enhancements__debugger}
|
||||
${Header_Files__soh__Enhancements__randomizer}
|
||||
${Header_Files__soh__Enhancements__randomizer__3drando}
|
||||
${Header_Files__soh__Enhancements__custom_message}
|
||||
${Source_Files__soh}
|
||||
${Source_Files__soh__Enhancements}
|
||||
${Source_Files__soh__Enhancements__cosmetics}
|
||||
@ -1542,6 +1556,7 @@ set(ALL_FILES
|
||||
${Source_Files__soh__Enhancements__randomizer__3drando}
|
||||
${Source_Files__soh__Enhancements__randomizer__3drando__hint_list}
|
||||
${Source_Files__soh__Enhancements__randomizer__3drando__location_access}
|
||||
${Source_Files__soh__Enhancements__custom_message}
|
||||
${Source_Files__src__boot}
|
||||
${Source_Files__src__buffers}
|
||||
${Source_Files__src__code}
|
||||
@ -1805,7 +1820,6 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion>
|
||||
-pthread
|
||||
-O3 -ffast-math
|
||||
)
|
||||
|
||||
target_link_options(${PROJECT_NAME} PRIVATE
|
||||
@ -1979,13 +1993,16 @@ endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch")
|
||||
|
||||
set_target_properties(soh PROPERTIES
|
||||
APP_TITLE "Ship of Harkirian"
|
||||
APP_AUTHOR "Ship"
|
||||
APP_VERSION "3.0.0"
|
||||
ICON "icon.jpg")
|
||||
|
||||
nx_create_nro(soh)
|
||||
nx_generate_nacp(Ship.nacp
|
||||
NAME "Ship of Harkinian"
|
||||
AUTHOR "Harbour Masters"
|
||||
VERSION "3.1.0"
|
||||
)
|
||||
|
||||
nx_create_nro(soh
|
||||
NACP Ship.nacp
|
||||
ICON ${CMAKE_CURRENT_SOURCE_DIR}/icon.jpg
|
||||
)
|
||||
|
||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/soh.nro DESTINATION . COMPONENT ship)
|
||||
|
||||
|
@ -25,7 +25,7 @@ typedef struct {
|
||||
/* 0x0C */ Vec3f position;
|
||||
/* 0x18 */ Vec3s unkVelocity;
|
||||
/* 0x1E */ Vec3s unkPosition;
|
||||
/* 0x24 */ s32 epoch;
|
||||
/* 0x24 */ u32 epoch;
|
||||
} EffectSparkElement; // size = 0x28
|
||||
|
||||
typedef struct {
|
||||
@ -118,7 +118,7 @@ typedef struct {
|
||||
/* 0x10 */ f32 startX;
|
||||
/* 0x14 */ s16 yaw;
|
||||
/* 0x16 */ s16 pitch;
|
||||
/* 0x18 */ s32 epoch;
|
||||
/* 0x18 */ u32 epoch;
|
||||
} EffectShieldParticleElement; // size = 0x1C
|
||||
|
||||
typedef struct {
|
||||
|
@ -638,6 +638,7 @@ typedef struct Player {
|
||||
/* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position
|
||||
/* 0x0A89 */ bool pendingIceTrap;
|
||||
/* 0x0A95 */ PendingFlag pendingFlag;
|
||||
} Player; // size = 0xAA1
|
||||
/* 0x0AA1 */ u8 boomerangQuickRecall; // Has the player pressed the boomerang button while it's in the air still?
|
||||
} Player; // size = 0xAA2
|
||||
|
||||
#endif
|
||||
|
@ -1124,7 +1124,7 @@ void DrawCosmeticsEditor(bool& open) {
|
||||
return;
|
||||
}
|
||||
ImGui::SetNextWindowSize(ImVec2(465, 430), ImGuiCond_FirstUseEver);
|
||||
if (!ImGui::Begin("Cosmetics Editor", &open, ImGuiWindowFlags_NoFocusOnAppearing)) {
|
||||
if (!ImGui::Begin("Cosmetics Editor", &open)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
@ -1162,7 +1162,7 @@ void InitCosmeticsEditor() {
|
||||
//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
|
||||
//ImGui::SetNextItemWidth(0.0f);
|
||||
SohImGui::AddWindow("Cosmetics", "Rainbowfunction", LoadRainbowColor, true, true);
|
||||
SohImGui::AddWindow("Enhancements", "Rainbowfunction", LoadRainbowColor, true, true);
|
||||
//Draw the bar in the menu.
|
||||
SohImGui::AddWindow("Cosmetics", "Cosmetics Editor", DrawCosmeticsEditor);
|
||||
}
|
||||
SohImGui::AddWindow("Enhancements", "Cosmetics Editor", DrawCosmeticsEditor);
|
||||
}
|
||||
|
150
soh/soh/Enhancements/custom-message/CustomMessageManager.cpp
Normal file
150
soh/soh/Enhancements/custom-message/CustomMessageManager.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include "CustomMessageManager.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
CustomMessageManager::CustomMessageManager() {
|
||||
this->textBoxSpecialCharacters = { { "À", 0x80 }, { "î", 0x81 }, { "Â", 0x82 }, { "Ä", 0x83 }, { "Ç", 0x84 },
|
||||
{ "È", 0x85 }, { "É", 0x86 }, { "Ê", 0x87 }, { "Ë", 0x88 }, { "Ï", 0x89 },
|
||||
{ "Ô", 0x8A }, { "Ö", 0x8B }, { "Ù", 0x8C }, { "Û", 0x8D }, { "Ü", 0x8E },
|
||||
{ "ß", 0x8F }, { "à", 0x90 }, { "á", 0x91 }, { "â", 0x92 }, { "ä", 0x93 },
|
||||
{ "ç", 0x94 }, { "è", 0x95 }, { "é", 0x96 }, { "ê", 0x97 }, { "ë", 0x98 },
|
||||
{ "ï", 0x99 }, { "ô", 0x9A }, { "ö", 0x9B }, { "ù", 0x9C }, { "û", 0x9D },
|
||||
{ "ü", 0x9E } };
|
||||
this->colors = { { "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN }, { "b", QM_BLUE },
|
||||
{ "c", QM_LBLUE }, { "p", QM_PINK }, { "y", QM_YELLOW }, { "B", QM_BLACK } };
|
||||
}
|
||||
|
||||
CustomMessageManager::~CustomMessageManager() {
|
||||
this->textBoxSpecialCharacters.clear();
|
||||
this->colors.clear();
|
||||
this->messageTables.clear();
|
||||
}
|
||||
|
||||
void CustomMessageManager::ReplaceSpecialCharacters(std::string& string) {
|
||||
// add special characters
|
||||
for (auto specialCharacterPair : this->textBoxSpecialCharacters) {
|
||||
size_t start_pos = 0;
|
||||
std::string textBoxSpecialCharacterString = ""s;
|
||||
textBoxSpecialCharacterString += specialCharacterPair.second;
|
||||
while ((start_pos = string.find(specialCharacterPair.first, 0)) != std::string::npos) {
|
||||
string.replace(start_pos, specialCharacterPair.first.length(), textBoxSpecialCharacterString);
|
||||
start_pos += textBoxSpecialCharacterString.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CustomMessageManager::ReplaceColors(std::string& string) {
|
||||
for (auto colorPair : colors) {
|
||||
std::string textToReplace = "%";
|
||||
textToReplace += colorPair.first;
|
||||
size_t start_pos = 0;
|
||||
while ((start_pos = string.find(textToReplace)) != std::string::npos) {
|
||||
string.replace(start_pos, textToReplace.length(), COLOR(colorPair.second));
|
||||
start_pos += textToReplace.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CustomMessageManager::FormatCustomMessage(std::string& message, ItemID iid) {
|
||||
message.insert(0, ITEM_OBTAINED(iid));
|
||||
size_t start_pos = 0;
|
||||
std::replace(message.begin(), message.end(), '&', NEWLINE()[0]);
|
||||
while ((start_pos = message.find('^', start_pos)) != std::string::npos) {
|
||||
message.replace(start_pos, 1, WAIT_FOR_INPUT() + ITEM_OBTAINED(iid));
|
||||
start_pos += 3;
|
||||
}
|
||||
std::replace(message.begin(), message.end(), '@', PLAYER_NAME()[0]);
|
||||
ReplaceSpecialCharacters(message);
|
||||
ReplaceColors(message);
|
||||
message += MESSAGE_END();
|
||||
}
|
||||
|
||||
void CustomMessageManager::FormatCustomMessage(std::string& message) {
|
||||
size_t start_pos = 0;
|
||||
std::replace(message.begin(), message.end(), '&', NEWLINE()[0]);
|
||||
std::replace(message.begin(), message.end(), '^', WAIT_FOR_INPUT()[0]);
|
||||
std::replace(message.begin(), message.end(), '@', PLAYER_NAME()[0]);
|
||||
ReplaceSpecialCharacters(message);
|
||||
ReplaceColors(message);
|
||||
message += MESSAGE_END();
|
||||
}
|
||||
|
||||
bool CustomMessageManager::InsertCustomMessage(std::string tableID, uint16_t textID, CustomMessageEntry messages) {
|
||||
auto foundMessageTable = messageTables.find(tableID);
|
||||
if (foundMessageTable == messageTables.end()) {
|
||||
return false;
|
||||
}
|
||||
auto& messageTable = foundMessageTable->second;
|
||||
auto messageInsertResult = messageTable.emplace(textID, messages);
|
||||
return messageInsertResult.second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CustomMessageManager::CreateGetItemMessage(std::string tableID, GetItemID giid, ItemID iid, CustomMessageEntry messageEntry) {
|
||||
FormatCustomMessage(messageEntry.english, iid);
|
||||
FormatCustomMessage(messageEntry.german, iid);
|
||||
FormatCustomMessage(messageEntry.french, iid);
|
||||
const uint16_t textID = giid;
|
||||
return InsertCustomMessage(tableID, textID, messageEntry);
|
||||
}
|
||||
|
||||
bool CustomMessageManager::CreateMessage(std::string tableID, uint16_t textID, CustomMessageEntry messageEntry) {
|
||||
FormatCustomMessage(messageEntry.english);
|
||||
FormatCustomMessage(messageEntry.german);
|
||||
FormatCustomMessage(messageEntry.french);
|
||||
return InsertCustomMessage(tableID, textID, messageEntry);
|
||||
}
|
||||
|
||||
CustomMessageEntry CustomMessageManager::RetrieveMessage(std::string tableID, uint16_t textID) {
|
||||
std::unordered_map<std::string, CustomMessageTable>::const_iterator foundMessageTable = messageTables.find(tableID);
|
||||
if (foundMessageTable == messageTables.end()) {
|
||||
return NULL_CUSTOM_MESSAGE;
|
||||
}
|
||||
CustomMessageTable messageTable = foundMessageTable->second;
|
||||
std::unordered_map<uint16_t, CustomMessageEntry>::const_iterator foundMessage = messageTable.find(textID);
|
||||
if (foundMessage == messageTable.end()) {
|
||||
return NULL_CUSTOM_MESSAGE;
|
||||
}
|
||||
CustomMessageEntry message = foundMessage->second;
|
||||
return message;
|
||||
}
|
||||
|
||||
bool CustomMessageManager::ClearMessageTable(std::string tableID) {
|
||||
auto foundMessageTable = messageTables.find(tableID);
|
||||
if (foundMessageTable == messageTables.end()) {
|
||||
return false;
|
||||
}
|
||||
auto& messageTable = foundMessageTable->second;
|
||||
messageTable.clear();
|
||||
}
|
||||
|
||||
bool CustomMessageManager::AddCustomMessageTable(std::string tableID) {
|
||||
CustomMessageTable newMessageTable;
|
||||
return messageTables.emplace(tableID, newMessageTable).second;
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::MESSAGE_END() {
|
||||
return "\x02"s;
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::ITEM_OBTAINED(uint8_t x) {
|
||||
return "\x13"s + char(x);
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::NEWLINE() {
|
||||
return "\x01"s;
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::COLOR(uint8_t x) {
|
||||
return "\x05"s + char(x);
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::WAIT_FOR_INPUT() {
|
||||
return "\x04"s;
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::PLAYER_NAME() {
|
||||
return "\x0F"s;
|
||||
}
|
133
soh/soh/Enhancements/custom-message/CustomMessageManager.h
Normal file
133
soh/soh/Enhancements/custom-message/CustomMessageManager.h
Normal file
@ -0,0 +1,133 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "../../../include/z64item.h"
|
||||
|
||||
#undef MESSAGE_END
|
||||
|
||||
#define QM_WHITE 0x00
|
||||
#define QM_RED 0x41
|
||||
#define QM_GREEN 0x42
|
||||
#define QM_BLUE 0x43
|
||||
#define QM_LBLUE 0x44
|
||||
#define QM_PINK 0x45
|
||||
#define QM_YELLOW 0x46
|
||||
#define QM_BLACK 0x47
|
||||
|
||||
#ifndef MESSAGE_DATA_STATIC_H
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ TEXTBOX_TYPE_BLACK,
|
||||
/* 1 */ TEXTBOX_TYPE_WOODEN,
|
||||
/* 2 */ TEXTBOX_TYPE_BLUE,
|
||||
/* 3 */ TEXTBOX_TYPE_OCARINA,
|
||||
/* 4 */ TEXTBOX_TYPE_NONE_BOTTOM,
|
||||
/* 5 */ TEXTBOX_TYPE_NONE_NO_SHADOW,
|
||||
/* 11 */ TEXTBOX_TYPE_CREDITS = 11
|
||||
} TextBoxType;
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ TEXTBOX_BG_CROSS
|
||||
} TextBoxBackground;
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ TEXTBOX_POS_VARIABLE,
|
||||
/* 1 */ TEXTBOX_POS_TOP,
|
||||
/* 2 */ TEXTBOX_POS_MIDDLE,
|
||||
/* 3 */ TEXTBOX_POS_BOTTOM
|
||||
} TextBoxPosition;
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
TextBoxType textBoxType;
|
||||
TextBoxPosition textBoxPos;
|
||||
std::string english;
|
||||
std::string german;
|
||||
std::string french;
|
||||
} CustomMessageEntry;
|
||||
|
||||
// Message Entry without the text type and position, useful for when
|
||||
// you need an array of these to loop over for registration
|
||||
// that will all have the same textbox type and position.
|
||||
typedef struct {
|
||||
std::string english;
|
||||
std::string german;
|
||||
std::string french;
|
||||
} CustomMessageMinimal;
|
||||
|
||||
#define NULL_CUSTOM_MESSAGE \
|
||||
{ (TextBoxType)(-1), (TextBoxPosition)(-1), "", "", "" }
|
||||
|
||||
typedef std::unordered_map<uint16_t, CustomMessageEntry> CustomMessageTable;
|
||||
|
||||
class CustomMessageManager {
|
||||
private:
|
||||
std::unordered_map<std::string, char> textBoxSpecialCharacters;
|
||||
std::unordered_map<std::string, char> colors;
|
||||
std::unordered_map<std::string, CustomMessageTable> messageTables;
|
||||
|
||||
void ReplaceSpecialCharacters(std::string &string);
|
||||
void ReplaceColors(std::string& string);
|
||||
bool InsertCustomMessage(std::string tableID, uint16_t textID, CustomMessageEntry messages);
|
||||
|
||||
std::string MESSAGE_END();
|
||||
std::string ITEM_OBTAINED(uint8_t x);
|
||||
std::string NEWLINE();
|
||||
std::string COLOR(uint8_t x);
|
||||
std::string WAIT_FOR_INPUT();
|
||||
std::string PLAYER_NAME();
|
||||
|
||||
public:
|
||||
static CustomMessageManager* Instance;
|
||||
|
||||
CustomMessageManager();
|
||||
~CustomMessageManager();
|
||||
|
||||
/*
|
||||
Formats the provided Custom Message Entry and inserts it into the table with the provided tableID,
|
||||
with the provided giid (getItemID) as its key. This function also inserts the icon corresponding to
|
||||
the provided iid (itemID) at the beginning of each page of the textbox.
|
||||
*/
|
||||
bool CreateGetItemMessage(std::string tableID, GetItemID giid, ItemID iid, CustomMessageEntry messages);
|
||||
|
||||
/*
|
||||
Formats the provided Custom Message Entry and inserts it into the table with the provided tableID,
|
||||
with the provided textID as its key.
|
||||
*/
|
||||
bool CreateMessage(std::string tableID, uint16_t textID, CustomMessageEntry messages);
|
||||
|
||||
/*
|
||||
Retrieves a message from the table with id tableID with the provided textID.
|
||||
Returns a NULL_CUSTOM_MESSAGE if the message or table does not exist.
|
||||
*/
|
||||
CustomMessageEntry RetrieveMessage(std::string tableID, uint16_t textID);
|
||||
|
||||
/*
|
||||
Empties out the message table identified by tableID.
|
||||
Returns true if successful and false if not (for instance
|
||||
if a table with the provided tableID does not exist).
|
||||
*/
|
||||
bool ClearMessageTable(std::string tableID);
|
||||
|
||||
/*
|
||||
Creates an empty CustomMessageTable accessible at the provided
|
||||
tableID, returns true if creation was successful and false
|
||||
if not.
|
||||
*/
|
||||
bool AddCustomMessageTable(std::string tableID);
|
||||
|
||||
/*
|
||||
Replaces special characters and certain symbols with control codes
|
||||
& for newline, ^ for wait-for-input, and @ for the player name,
|
||||
as well as %<letter> for colors (i.e. %r for red and %w for white).
|
||||
*/
|
||||
void FormatCustomMessage(std::string& message, ItemID iid);
|
||||
|
||||
/*
|
||||
Replaces special characters and certain symbols with control codes
|
||||
& for newline, ^ for wait-for-input, and @ for the player name,
|
||||
as well as %<letter> for colors (i.e. %r for red and %w for white).
|
||||
*/
|
||||
void FormatCustomMessage(std::string& message);
|
||||
};
|
33
soh/soh/Enhancements/custom-message/CustomMessageTypes.h
Normal file
33
soh/soh/Enhancements/custom-message/CustomMessageTypes.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
TEXT_GS_NO_FREEZE = 0xB4,
|
||||
TEXT_GS_FREEZE = 0xB5,
|
||||
TEXT_RANDOMIZER_CUSTOM_ITEM = 0xF8,
|
||||
TEXT_SCRUB_POH = 0x10A2,
|
||||
TEXT_SCRUB_STICK_UPGRADE = 0x10DC,
|
||||
TEXT_SCRUB_NUT_UPGRADE = 0x10DD,
|
||||
TEXT_RANDOMIZER_GOSSIP_STONE_HINTS = 0x2053,
|
||||
TEXT_ALTAR_CHILD = 0x7040,
|
||||
TEXT_ALTAR_ADULT = 0x7088,
|
||||
TEXT_GANONDORF = 0x70CC,
|
||||
TEXT_GANONDORF_NOHINT = 0x70CD
|
||||
} TextIDs;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
typedef struct {
|
||||
GetItemID giid;
|
||||
ItemID iid;
|
||||
std::string english;
|
||||
std::string german;
|
||||
std::string french;
|
||||
} GetItemMessage;
|
||||
|
||||
#define GIMESSAGE(giid, iid, english, german, french) \
|
||||
{ giid, iid, english, german, french }
|
||||
|
||||
#define GIMESSAGE_UNTRANSLATED(giid, iid, message) \
|
||||
{ giid, iid, message, message, message }
|
||||
|
||||
#endif
|
@ -14,13 +14,20 @@
|
||||
#include "3drando/rando_main.hpp"
|
||||
#include <soh/Enhancements/debugger/ImGuiHelpers.h>
|
||||
#include "Lib/ImGui/imgui_internal.h"
|
||||
#include <soh/Enhancements/custom-message/CustomMessageManager.h>
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
std::unordered_map<uint8_t, Sprite> gSeedTextures;
|
||||
|
||||
u8 generated;
|
||||
|
||||
const std::string Randomizer::getItemMessageTableID = "Randomizer";
|
||||
const std::string Randomizer::hintMessageTableID = "RandomizerHints";
|
||||
const std::string Randomizer::scrubMessageTableID = "RandomizerScrubs";
|
||||
|
||||
Randomizer::Randomizer() {
|
||||
Sprite bowSprite = { dgFairyBowIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b, 0 };
|
||||
gSeedTextures[0] = bowSprite;
|
||||
@ -1399,14 +1406,15 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
|
||||
{ "Open Settings:Random Ganon's Trials", RSK_RANDOM_TRIALS },
|
||||
{ "Open Settings:Trial Count", RSK_TRIAL_COUNT },
|
||||
{ "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS },
|
||||
{ "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS },
|
||||
{ "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD },
|
||||
{ "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD },
|
||||
{ "Start with Fairy Ocarina", RSK_STARTING_OCARINA },
|
||||
{ "Shuffle Dungeon Items:Start with Maps/Compasses", RSK_STARTING_MAPS_COMPASSES },
|
||||
{ "Shuffle Dungeon Items:Ganon's Boss Key", RSK_GANONS_BOSS_KEY },
|
||||
{ "Misc Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS },
|
||||
{ "Misc Settings:Hint Clarity", RSK_HINT_CLARITY},
|
||||
{ "Misc Settings:Hint Distribution", RSK_HINT_DISTRIBUTION},
|
||||
{ "Misc Settings:Hint Clarity", RSK_HINT_CLARITY },
|
||||
{ "Misc Settings:Hint Distribution", RSK_HINT_DISTRIBUTION },
|
||||
{ "Skip Child Zelda", RSK_SKIP_CHILD_ZELDA },
|
||||
{ "Start with Consumables", RSK_STARTING_CONSUMABLES },
|
||||
{ "Start with Max Rupees", RSK_FULL_WALLETS },
|
||||
@ -1482,6 +1490,26 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
|
||||
ParseHintLocationsFile(spoilerFileName);
|
||||
}
|
||||
|
||||
CustomMessageManager::Instance->ClearMessageTable(Randomizer::hintMessageTableID);
|
||||
CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::hintMessageTableID);
|
||||
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, TEXT_ALTAR_CHILD,
|
||||
{ TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, gSaveContext.childAltarText,
|
||||
gSaveContext.childAltarText, gSaveContext.childAltarText });
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, TEXT_ALTAR_ADULT,
|
||||
{ TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, gSaveContext.adultAltarText,
|
||||
gSaveContext.adultAltarText, gSaveContext.adultAltarText });
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, TEXT_GANONDORF,
|
||||
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, gSaveContext.ganonHintText,
|
||||
gSaveContext.ganonHintText, gSaveContext.ganonHintText });
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, TEXT_GANONDORF_NOHINT,
|
||||
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, gSaveContext.ganonText,
|
||||
gSaveContext.ganonText, gSaveContext.ganonText });
|
||||
|
||||
this->childAltarText = gSaveContext.childAltarText;
|
||||
this->adultAltarText = gSaveContext.adultAltarText;
|
||||
this->ganonHintText = gSaveContext.ganonHintText;
|
||||
@ -1490,6 +1518,8 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
|
||||
for (auto hintLocation : gSaveContext.hintLocations) {
|
||||
if(hintLocation.check == RC_LINKS_POCKET) break;
|
||||
this->hintLocations[hintLocation.check] = hintLocation.hintText;
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, hintLocation.check, { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, hintLocation.hintText, hintLocation.hintText, hintLocation.hintText });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1702,6 +1732,18 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
||||
} else if (it.value() == "Skip") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
}
|
||||
break;
|
||||
case RSK_SHUFFLE_TOKENS:
|
||||
if (it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
} else if (it.value() == "Dungeons") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
} else if (it.value() == "Overworld") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
} else if (it.value() == "All Tokens") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
@ -1802,57 +1844,8 @@ std::string AltarIconString(char iconChar) {
|
||||
|
||||
std::string FormatJsonHintText(std::string jsonHint) {
|
||||
std::string formattedHintMessage = jsonHint;
|
||||
char newLine = 0x01;
|
||||
char playerName = 0x0F;
|
||||
char nextBox = 0x04;
|
||||
std::replace(formattedHintMessage.begin(), formattedHintMessage.end(), '&', newLine);
|
||||
std::replace(formattedHintMessage.begin(), formattedHintMessage.end(), '^', nextBox);
|
||||
std::replace(formattedHintMessage.begin(), formattedHintMessage.end(), '@', playerName);
|
||||
|
||||
std::unordered_map<std::string, char> textBoxSpecialCharacters = {
|
||||
{"À", 0x80 },
|
||||
{"î", 0x81 },
|
||||
{"Â", 0x82 },
|
||||
{"Ä", 0x83 },
|
||||
{"Ç", 0x84 },
|
||||
{"È", 0x85 },
|
||||
{"É", 0x86 },
|
||||
{"Ê", 0x87 },
|
||||
{"Ë", 0x88 },
|
||||
{"Ï", 0x89 },
|
||||
{"Ô", 0x8A },
|
||||
{"Ö", 0x8B },
|
||||
{"Ù", 0x8C },
|
||||
{"Û", 0x8D },
|
||||
{"Ü", 0x8E },
|
||||
{"ß", 0x8F },
|
||||
{"à", 0x90 },
|
||||
{"á", 0x91 },
|
||||
{"â", 0x92 },
|
||||
{"ä", 0x93 },
|
||||
{"ç", 0x94 },
|
||||
{"è", 0x95 },
|
||||
{"é", 0x96 },
|
||||
{"ê", 0x97 },
|
||||
{"ë", 0x98 },
|
||||
{"ï", 0x99 },
|
||||
{"ô", 0x9A },
|
||||
{"ö", 0x9B },
|
||||
{"ù", 0x9C },
|
||||
{"û", 0x9D },
|
||||
{"ü", 0x9E }
|
||||
};
|
||||
|
||||
// add special characters
|
||||
for (auto specialCharacterPair : textBoxSpecialCharacters) {
|
||||
size_t start_pos = 0;
|
||||
std::string textBoxSpecialCharacterString = "";
|
||||
textBoxSpecialCharacterString += specialCharacterPair.second;
|
||||
while((start_pos = formattedHintMessage.find(specialCharacterPair.first, start_pos)) != std::string::npos) {
|
||||
formattedHintMessage.replace(start_pos, specialCharacterPair.first.length(), textBoxSpecialCharacterString);
|
||||
start_pos += textBoxSpecialCharacterString.length();
|
||||
}
|
||||
}
|
||||
CustomMessageManager::Instance->FormatCustomMessage(formattedHintMessage);
|
||||
|
||||
// add icons to altar text
|
||||
for (char iconChar : {'0', '1', '2', '3', '4', '5', '6', '7', '8', 'o', 'c', 'i', 'l', 'b', 'L', 'k'}) {
|
||||
@ -2413,10 +2406,6 @@ std::string Randomizer::GetGanonHintText() const {
|
||||
return ganonHintText;
|
||||
}
|
||||
|
||||
std::string Randomizer::GetHintFromCheck(RandomizerCheck check) {
|
||||
return this->hintLocations[check];
|
||||
}
|
||||
|
||||
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
|
||||
return this->randoSettings[randoSettingKey];
|
||||
}
|
||||
@ -3449,7 +3438,8 @@ void GenerateRandomizerImgui() {
|
||||
|
||||
// if we skip child zelda, we start with zelda's letter, and malon starts
|
||||
// at the ranch, so we should *not* shuffle the weird egg
|
||||
cvarSettings[RSK_SHUFFLE_WEIRD_EGG] = ((CVar_GetS32("gRandomizeSkipChildZelda", 0) == 0) && CVar_GetS32("gRandomizeShuffleWeirdEgg", 0));
|
||||
cvarSettings[RSK_SHUFFLE_WEIRD_EGG] = ((CVar_GetS32("gRandomizeSkipChildZelda", 0) == 0) &&
|
||||
CVar_GetS32("gRandomizeShuffleWeirdEgg", 0));
|
||||
|
||||
cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = CVar_GetS32("gRandomizeShuffleGerudoToken", 0);
|
||||
cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES] = CVar_GetS32("gRandomizeShuffleFrogSongRupees", 0);
|
||||
@ -3477,7 +3467,10 @@ void GenerateRandomizerImgui() {
|
||||
cvarSettings[RSK_CUCCO_COUNT] = CVar_GetS32("gRandomizeCuccosToReturn", 7);
|
||||
cvarSettings[RSK_BIG_POE_COUNT] = CVar_GetS32("gRandomizeBigPoeTargetCount", 10);
|
||||
|
||||
cvarSettings[RSK_SKIP_CHILD_STEALTH] = CVar_GetS32("gRandomizeSkipChildStealth", 0);
|
||||
// If we skip child zelda, skip child stealth is pointless, so this needs to be reflected in the spoiler log
|
||||
cvarSettings[RSK_SKIP_CHILD_STEALTH] =
|
||||
!CVar_GetS32("gRandomizeSkipChildZelda", 0) && CVar_GetS32("gRandomizeSkipChildStealth", 0);
|
||||
|
||||
cvarSettings[RSK_SKIP_EPONA_RACE] = CVar_GetS32("gRandomizeSkipEponaRace", 0);
|
||||
cvarSettings[RSK_SKIP_TOWER_ESCAPE] = CVar_GetS32("gRandomizeSkipTowerEscape", 0);
|
||||
|
||||
@ -4390,8 +4383,74 @@ void DrawRandoEditor(bool& open) {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void CreateGetItemMessages(std::vector<GetItemMessage> messageEntries) {
|
||||
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
|
||||
customMessageManager->AddCustomMessageTable(Randomizer::getItemMessageTableID);
|
||||
for (GetItemMessage messageEntry : messageEntries) {
|
||||
if (messageEntry.giid == GI_ICE_TRAP) {
|
||||
customMessageManager->CreateMessage(Randomizer::getItemMessageTableID, messageEntry.giid,
|
||||
{ TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, messageEntry.english,
|
||||
messageEntry.german, messageEntry.french });
|
||||
} else {
|
||||
customMessageManager->CreateGetItemMessage(Randomizer::getItemMessageTableID, messageEntry.giid,
|
||||
messageEntry.iid,
|
||||
{ TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, messageEntry.english,
|
||||
messageEntry.german, messageEntry.french });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateScrubMessages() {
|
||||
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
|
||||
customMessageManager->AddCustomMessageTable(Randomizer::scrubMessageTableID);
|
||||
const std::vector<u8> prices = { 10, 40 };
|
||||
for (u8 price : prices) {
|
||||
customMessageManager->CreateMessage(Randomizer::scrubMessageTableID, price,
|
||||
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
|
||||
"\x12\x38\x82\All right! You win! In return for&sparing me, I will sell you a&%gmysterious item%w!&%r" +
|
||||
std::to_string(price) + " Rupees%w it is!\x07\x10\xA3",
|
||||
// RANDTODO: Translate the below string to German.
|
||||
"\x12\x38\x82\All right! You win! In return for&sparing me, I will sell you a&%gmysterious item%w!&%r" +
|
||||
std::to_string(price) + " Rupees%w it is!\x07\x10\xA3",
|
||||
"\x12\x38\x82J'abandonne! Tu veux bien m'acheter&un %gobjet mystérieux%w?&Ça fera %r" +
|
||||
std::to_string(price) + " Rubis%w!\x07\x10\xA3"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Randomizer::CreateCustomMessages() {
|
||||
// RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED
|
||||
// with GIMESSAGE(getItemID, itemID, english, german, french).
|
||||
const std::vector<GetItemMessage> getItemMessages = {
|
||||
GIMESSAGE(GI_ICE_TRAP, ITEM_NONE, "\x08\x06\x30You are a %bFOWL%w!\x0E\x20",
|
||||
"\x08\x06\x15 Du bist ein %bDUMMKOPF%w!\x0E\x20", "\x08\x06\x50%bIDIOT%w\x0E\x20"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE,
|
||||
"You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE,
|
||||
"You got a %rBig Poe in a Bottle%w!&Sell it to the Ghost Shop!"),
|
||||
GIMESSAGE_UNTRANSLATED(
|
||||
GI_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE,
|
||||
"You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!"),
|
||||
GIMESSAGE_UNTRANSLATED(
|
||||
GI_BOTTLE_WITH_FISH, ITEM_FISH,
|
||||
"You got a %rFish in a Bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_BUGS, ITEM_BUG,
|
||||
"You got a %rBug in a Bottle%w!&They love to burrow in&dirt holes!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_FAIRY, ITEM_FAIRY, "You got a %rFairy in a Bottle%w!&Use it wisely!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED,
|
||||
"You got a %rBottle of Red Potion%w!&Drink it to replenish your&%ghealth%w!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN,
|
||||
"You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_POE, ITEM_POE,
|
||||
"You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this..."),
|
||||
};
|
||||
CreateGetItemMessages(getItemMessages);
|
||||
CreateScrubMessages();
|
||||
}
|
||||
|
||||
void InitRando() {
|
||||
SohImGui::AddWindow("Randomizer", "Randomizer Settings", DrawRandoEditor);
|
||||
Randomizer::CreateCustomMessages();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
@ -4,7 +4,8 @@
|
||||
#include <string>
|
||||
#include "../../../include/ultra64.h"
|
||||
#include "../../../include/z64item.h"
|
||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||
#include <memory>
|
||||
#include <soh/Enhancements/randomizer/randomizerTypes.h>
|
||||
|
||||
class Randomizer {
|
||||
private:
|
||||
@ -25,6 +26,10 @@ class Randomizer {
|
||||
Randomizer();
|
||||
~Randomizer();
|
||||
|
||||
static const std::string getItemMessageTableID;
|
||||
static const std::string hintMessageTableID;
|
||||
static const std::string scrubMessageTableID;
|
||||
|
||||
static Sprite* GetSeedTexture(uint8_t index);
|
||||
s16 GetItemModelFromId(s16 itemId);
|
||||
s32 GetItemIDFromGetItemID(s32 getItemId);
|
||||
@ -38,9 +43,9 @@ class Randomizer {
|
||||
std::string GetAdultAltarText() const;
|
||||
std::string GetGanonText() const;
|
||||
std::string GetGanonHintText() const;
|
||||
std::string GetHintFromCheck(RandomizerCheck check);
|
||||
GetItemID GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||
GetItemID GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
|
||||
static void CreateCustomMessages();
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include "Enhancements/cosmetics/CosmeticsEditor.h"
|
||||
#include "Enhancements/debugconsole.h"
|
||||
#include "Enhancements/debugger/debugger.h"
|
||||
#include "Enhancements/randomizer/randomizer.h"
|
||||
#include <soh/Enhancements/randomizer/randomizer_item_tracker.h>
|
||||
#include "Enhancements/n64_weird_frame_data.inc"
|
||||
#include "soh/frame_interpolation.h"
|
||||
@ -40,6 +39,7 @@
|
||||
#include "macros.h"
|
||||
#include <Utils/StringHelper.h>
|
||||
#include "Hooks.h"
|
||||
#include <soh/Enhancements/custom-message/CustomMessageManager.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <SDL_scancode.h>
|
||||
@ -52,9 +52,12 @@
|
||||
#endif
|
||||
|
||||
#include <Audio.h>
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
#include <functions.h>
|
||||
|
||||
OTRGlobals* OTRGlobals::Instance;
|
||||
SaveManager* SaveManager::Instance;
|
||||
CustomMessageManager* CustomMessageManager::Instance;
|
||||
|
||||
OTRGlobals::OTRGlobals() {
|
||||
context = Ship::GlobalCtx2::CreateInstance("Ship of Harkinian");
|
||||
@ -171,6 +174,7 @@ extern "C" void InitOTR() {
|
||||
#endif
|
||||
OTRGlobals::Instance = new OTRGlobals();
|
||||
SaveManager::Instance = new SaveManager();
|
||||
CustomMessageManager::Instance = new CustomMessageManager();
|
||||
auto t = OTRGlobals::Instance->context->GetResourceManager()->LoadFile("version");
|
||||
|
||||
if (!t->bHasLoadError)
|
||||
@ -1431,99 +1435,39 @@ extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 sceneNum, s16 actorI
|
||||
return OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams);
|
||||
}
|
||||
|
||||
extern "C" int CopyScrubMessage(u16 scrubTextId, char* buffer, const int maxBufferSize) {
|
||||
std::string scrubText("");
|
||||
int language = CVar_GetS32("gLanguages", 0);
|
||||
extern "C" CustomMessageEntry Randomizer_GetScrubMessage(u16 scrubTextId) {
|
||||
int price = 0;
|
||||
switch (scrubTextId) {
|
||||
case 0x10A2:
|
||||
case TEXT_SCRUB_POH:
|
||||
price = 10;
|
||||
break;
|
||||
case 0x10DC:
|
||||
case 0x10DD:
|
||||
case TEXT_SCRUB_STICK_UPGRADE:
|
||||
case TEXT_SCRUB_NUT_UPGRADE:
|
||||
price = 40;
|
||||
break;
|
||||
}
|
||||
switch (language) {
|
||||
case 0: default:
|
||||
scrubText += 0x12; // add the sound
|
||||
scrubText += 0x38; // sound id
|
||||
scrubText += 0x82; // sound id
|
||||
scrubText += "All right! You win! In return for";
|
||||
scrubText += 0x01; // newline
|
||||
scrubText += "sparing me, I will sell you a";
|
||||
scrubText += 0x01; // newline
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x42; // green
|
||||
scrubText += "mysterious item";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x40; // white
|
||||
scrubText += "!";
|
||||
scrubText += 0x01; // newline
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x41; // red
|
||||
scrubText += std::to_string(price);
|
||||
scrubText += price > 1 ? " Rupees" : " Rupee";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x40; // white
|
||||
scrubText += " it is!";
|
||||
scrubText += 0x07; // go to a new message
|
||||
scrubText += 0x10; // message id
|
||||
scrubText += 0xA3; // message id
|
||||
break;
|
||||
case 2:
|
||||
scrubText += 0x12; // add the sound
|
||||
scrubText += 0x38; // sound id
|
||||
scrubText += 0x82; // sound id
|
||||
scrubText += "J'abandonne! Tu veux bien m'acheter";
|
||||
scrubText += 0x01; // newline
|
||||
scrubText += "un ";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x42; // green
|
||||
scrubText += "objet myst\x96rieux";
|
||||
//scrubText += ";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x40; // white
|
||||
scrubText += "?";
|
||||
scrubText += 0x01; // newline
|
||||
scrubText += "\x84";
|
||||
scrubText += "a fera ";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x41; // red
|
||||
scrubText += std::to_string(price) + " Rubis";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x40; // white
|
||||
scrubText += "!";
|
||||
scrubText += 0x07; // go to a new message
|
||||
scrubText += 0x10; // message id
|
||||
scrubText += 0xA3; // message id
|
||||
break;
|
||||
}
|
||||
|
||||
return CopyStringToCharBuffer(scrubText, buffer, maxBufferSize);
|
||||
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::scrubMessageTableID, price);
|
||||
}
|
||||
|
||||
extern "C" int Randomizer_CopyAltarMessage(char* buffer, const int maxBufferSize) {
|
||||
const std::string& altarText = (LINK_IS_ADULT) ? OTRGlobals::Instance->gRandomizer->GetAdultAltarText()
|
||||
: OTRGlobals::Instance->gRandomizer->GetChildAltarText();
|
||||
return CopyStringToCharBuffer(altarText, buffer, maxBufferSize);
|
||||
extern "C" CustomMessageEntry Randomizer_GetAltarMessage() {
|
||||
return (LINK_IS_ADULT)
|
||||
? CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_ALTAR_ADULT)
|
||||
: CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_ALTAR_CHILD);
|
||||
}
|
||||
|
||||
extern "C" int Randomizer_CopyGanonText(char* buffer, const int maxBufferSize) {
|
||||
const std::string& ganonText = OTRGlobals::Instance->gRandomizer->GetGanonText();
|
||||
return CopyStringToCharBuffer(ganonText, buffer, maxBufferSize);
|
||||
extern "C" CustomMessageEntry Randomizer_GetGanonText() {
|
||||
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_GANONDORF_NOHINT);
|
||||
}
|
||||
|
||||
extern "C" int Randomizer_CopyGanonHintText(char* buffer, const int maxBufferSize) {
|
||||
const std::string& ganonText = OTRGlobals::Instance->gRandomizer->GetGanonHintText();
|
||||
return CopyStringToCharBuffer(ganonText, buffer, maxBufferSize);
|
||||
extern "C" CustomMessageEntry Randomizer_GetGanonHintText() {
|
||||
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_GANONDORF);
|
||||
}
|
||||
|
||||
extern "C" int Randomizer_CopyHintFromCheck(RandomizerCheck check, char* buffer, const int maxBufferSize) {
|
||||
// we don't want to make a copy of the std::string returned from GetHintFromCheck
|
||||
extern "C" CustomMessageEntry Randomizer_GetHintFromCheck(RandomizerCheck check) {
|
||||
// we don't want to make a copy of the std::string returned from GetHintFromCheck
|
||||
// so we're just going to let RVO take care of it
|
||||
const std::string& hintText = OTRGlobals::Instance->gRandomizer->GetHintFromCheck(check);
|
||||
return CopyStringToCharBuffer(hintText, buffer, maxBufferSize);
|
||||
const CustomMessageEntry hintText = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, check);
|
||||
return hintText;
|
||||
}
|
||||
|
||||
extern "C" s32 Randomizer_GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) {
|
||||
@ -1542,3 +1486,97 @@ extern "C" bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomize
|
||||
extern "C" bool Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId) {
|
||||
return gSaveContext.n64ddFlag && Randomizer_GetItemIdFromKnownCheck(randomizerCheck, ogId) == GI_ICE_TRAP;
|
||||
}
|
||||
|
||||
extern "C" CustomMessageEntry Randomizer_GetCustomGetItemMessage(GetItemID giid, char* buffer, const int maxBufferSize) {
|
||||
const CustomMessageEntry getItemText = CustomMessageManager::Instance->RetrieveMessage(Randomizer::getItemMessageTableID, giid);
|
||||
return getItemText;
|
||||
}
|
||||
|
||||
extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) {
|
||||
MessageContext* msgCtx = &globalCtx->msgCtx;
|
||||
uint16_t textId = msgCtx->textId;
|
||||
Font* font = &msgCtx->font;
|
||||
char* buffer = font->msgBuf;
|
||||
const int maxBufferSize = sizeof(font->msgBuf);
|
||||
CustomMessageEntry messageEntry;
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
if (textId == TEXT_RANDOMIZER_CUSTOM_ITEM) {
|
||||
messageEntry =
|
||||
Randomizer_GetCustomGetItemMessage((GetItemID)GET_PLAYER(globalCtx)->getItemId, buffer, maxBufferSize);
|
||||
} else if (textId == TEXT_RANDOMIZER_GOSSIP_STONE_HINTS && Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != 0 &&
|
||||
(Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 1 ||
|
||||
(Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 2 &&
|
||||
Player_GetMask(globalCtx) == PLAYER_MASK_TRUTH) ||
|
||||
(Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 3 && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) {
|
||||
|
||||
s16 actorParams = msgCtx->talkActor->params;
|
||||
|
||||
// if we're in a generic grotto
|
||||
if (globalCtx->sceneNum == 62 && actorParams == 14360) {
|
||||
// look for the chest in the actorlist to determine
|
||||
// which grotto we're in
|
||||
int numOfActorLists =
|
||||
sizeof(globalCtx->actorCtx.actorLists) / sizeof(globalCtx->actorCtx.actorLists[0]);
|
||||
for (int i = 0; i < numOfActorLists; i++) {
|
||||
if (globalCtx->actorCtx.actorLists[i].length) {
|
||||
if (globalCtx->actorCtx.actorLists[i].head->id == 10) {
|
||||
// set the params for the hint check to be negative chest params
|
||||
actorParams = 0 - globalCtx->actorCtx.actorLists[i].head->params;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RandomizerCheck hintCheck =
|
||||
Randomizer_GetCheckFromActor(globalCtx->sceneNum, msgCtx->talkActor->id, actorParams);
|
||||
|
||||
messageEntry = Randomizer_GetHintFromCheck(hintCheck);
|
||||
} else if (textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT) {
|
||||
// rando hints at altar
|
||||
messageEntry = Randomizer_GetAltarMessage();
|
||||
} else if (textId == TEXT_GANONDORF) {
|
||||
if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) {
|
||||
messageEntry = Randomizer_GetGanonText();
|
||||
} else {
|
||||
messageEntry = Randomizer_GetGanonHintText();
|
||||
}
|
||||
} else if (textId == TEXT_SCRUB_POH || textId == TEXT_SCRUB_STICK_UPGRADE || textId == TEXT_SCRUB_NUT_UPGRADE) {
|
||||
messageEntry = Randomizer_GetScrubMessage(textId);
|
||||
}
|
||||
}
|
||||
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
|
||||
if (CVar_GetS32("gInjectSkulltulaCount", 0) != 0) {
|
||||
// The freeze text cannot be manually dismissed and must be auto-dismissed.
|
||||
// This is fine and even wanted when skull tokens are not shuffled, but when
|
||||
// when they are shuffled we don't want to be able to manually dismiss the box.
|
||||
// Otherwise if we get a token from a chest or an NPC we get stuck in the ItemGet
|
||||
// animation until the text box auto-dismisses.
|
||||
// RANDOTODO: Implement a way to determine if an item came from a skulltula and
|
||||
// inject the auto-dismiss control code if it did.
|
||||
if (CVar_GetS32("gSkulltulaFreeze", 0) != 0 &&
|
||||
!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) > 0)) {
|
||||
textId = TEXT_GS_NO_FREEZE;
|
||||
} else {
|
||||
textId = TEXT_GS_FREEZE;
|
||||
}
|
||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId);
|
||||
}
|
||||
}
|
||||
if (messageEntry.textBoxType != -1) {
|
||||
font->charTexBuf[0] = (messageEntry.textBoxType << 4) | messageEntry.textBoxPos;
|
||||
switch (gSaveContext.language) {
|
||||
case LANGUAGE_FRA:
|
||||
return msgCtx->msgLength = font->msgLength =
|
||||
CopyStringToCharBuffer(messageEntry.french, buffer, maxBufferSize);
|
||||
case LANGUAGE_GER:
|
||||
return msgCtx->msgLength = font->msgLength =
|
||||
CopyStringToCharBuffer(messageEntry.german, buffer, maxBufferSize);
|
||||
|
||||
case LANGUAGE_ENG:
|
||||
default:
|
||||
return msgCtx->msgLength = font->msgLength =
|
||||
CopyStringToCharBuffer(messageEntry.english, buffer, maxBufferSize);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "Enhancements/savestates.h"
|
||||
#include "Enhancements/randomizer/randomizer.h"
|
||||
|
||||
const std::string customMessageTableID = "BaseGameOverrides";
|
||||
|
||||
class OTRGlobals
|
||||
{
|
||||
public:
|
||||
@ -91,10 +93,6 @@ Sprite* GetSeedTexture(uint8_t index);
|
||||
void Randomizer_LoadSettings(const char* spoilerFileName);
|
||||
u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
|
||||
RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 actorParams, s16 sceneNum);
|
||||
int Randomizer_CopyAltarMessage(char* buffer, const int maxBufferSize);
|
||||
int Randomizer_CopyHintFromCheck(RandomizerCheck check, char* buffer, const int maxBufferSize);
|
||||
int Randomizer_CopyGanonText(char* buffer, const int maxBufferSize);
|
||||
int Randomizer_CopyGanonHintText(char* buffer, const int maxBufferSize);
|
||||
void Randomizer_LoadHintLocations(const char* spoilerFileName);
|
||||
void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent);
|
||||
s16 Randomizer_GetItemModelFromId(s16 itemId);
|
||||
@ -103,6 +101,7 @@ s32 Randomizer_GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams,
|
||||
s32 Randomizer_GetItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||
bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId, Actor* actor);
|
||||
bool Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||
int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,11 +1,13 @@
|
||||
#include "OTRGlobals.h"
|
||||
#include "ResourceMgr.h"
|
||||
#include "Scene.h"
|
||||
#include "message_data_static.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "global.h"
|
||||
#include "vt.h"
|
||||
#include <Text.h>
|
||||
#include <message_data_static.h>
|
||||
#include <soh/Enhancements/custom-message/CustomMessageManager.h>
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
|
||||
extern "C" MessageTableEntry* sNesMessageEntryTablePtr;
|
||||
extern "C" MessageTableEntry* sGerMessageEntryTablePtr;
|
||||
@ -92,4 +94,22 @@ extern "C" void OTRMessage_Init()
|
||||
sStaffMessageEntryTablePtr[i].segment = file2->messages[i].msg.c_str();
|
||||
sStaffMessageEntryTablePtr[i].msgSize = file2->messages[i].msg.size();
|
||||
}
|
||||
}
|
||||
|
||||
CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID);
|
||||
CustomMessageManager::Instance->CreateGetItemMessage(
|
||||
customMessageTableID, (GetItemID)TEXT_GS_NO_FREEZE, ITEM_SKULL_TOKEN,
|
||||
{
|
||||
TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM,
|
||||
"You got a %rGold Skulltula Token%w!&You've collected %r\x19%w tokens&in total!\x0E\x3C",
|
||||
"Du erhälst ein %rGoldene&Skulltula-Symbol%w! Du hast&insgesamt %r\x19%w symbol gesammelt!\x0E\x3C",
|
||||
"Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r\x19\%w symboles en tout!\x0E\x3C"
|
||||
}
|
||||
);
|
||||
CustomMessageManager::Instance->CreateGetItemMessage(
|
||||
customMessageTableID, (GetItemID)TEXT_GS_FREEZE, ITEM_SKULL_TOKEN,
|
||||
{
|
||||
TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM,
|
||||
"You got a %rGold Skulltula Token%w!&You've collected %r\x19%w tokens&in total!",
|
||||
"Du erhälst ein %rGoldene&Skulltula-Symbol%w! Du hast&insgesamt %r\x19%w symbol gesammelt!",
|
||||
"Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r\x19\%w symboles en tout!" });
|
||||
}
|
||||
|
@ -3961,7 +3961,7 @@ void Actor_DrawDoorLock(GlobalContext* globalCtx, s32 frame, s32 type) {
|
||||
f32 chainsTranslateX;
|
||||
f32 chainsTranslateY;
|
||||
f32 rotZStep;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
entry = &sDoorLocksInfo[type];
|
||||
|
@ -492,9 +492,10 @@ void Cutscene_Command_Terminator(GlobalContext* globalCtx, CutsceneContext* csCt
|
||||
s32 temp = 0;
|
||||
|
||||
// Automatically skip certain cutscenes when in rando
|
||||
// cmd->base == 33: Zelda escaping with impa cutscene
|
||||
// cmd->base == 8: Traveling back/forward in time cutscene
|
||||
bool randoCsSkip = (gSaveContext.n64ddFlag && (cmd->base == 33 || cmd->base == 8));
|
||||
// cmd->base == 24: Dropping a fish for Jabu Jabu
|
||||
// cmd->base == 33: Zelda escaping with impa cutscene
|
||||
bool randoCsSkip = (gSaveContext.n64ddFlag && (cmd->base == 8 || cmd->base == 24 || cmd->base == 33));
|
||||
bool debugCsSkip = (CHECK_BTN_ALL(globalCtx->state.input[0].press.button, BTN_START) &&
|
||||
(gSaveContext.fileNum != 0xFEDC) && CVar_GetS32("gDebugEnabled", 0));
|
||||
|
||||
@ -2090,6 +2091,8 @@ void Cutscene_HandleConditionalTriggers(GlobalContext* globalCtx) {
|
||||
osSyncPrintf("\ngame_info.mode=[%d] restart_flag", ((void)0, gSaveContext.respawnFlag));
|
||||
|
||||
if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) {
|
||||
const bool bShouldTowerRandoSkip =
|
||||
(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE));
|
||||
if ((gSaveContext.entranceIndex == 0x01E1) && !Flags_GetEventChkInf(0xAC)) {
|
||||
if (!gSaveContext.n64ddFlag) {
|
||||
Flags_SetEventChkInf(0xAC);
|
||||
@ -2118,14 +2121,15 @@ void Cutscene_HandleConditionalTriggers(GlobalContext* globalCtx) {
|
||||
gSaveContext.entranceIndex = 0x0053;
|
||||
gSaveContext.cutsceneIndex = 0xFFF8;
|
||||
}
|
||||
} else if (!Flags_GetEventChkInf(0xC7) &&
|
||||
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_DEMO)) {
|
||||
} else if ((!Flags_GetEventChkInf(0xC7) &&
|
||||
gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_DEMO) ||
|
||||
(bShouldTowerRandoSkip &&
|
||||
gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_FINAL)) {
|
||||
Flags_SetEventChkInf(0xC7);
|
||||
gSaveContext.entranceIndex = 0x0517;
|
||||
|
||||
// If we are rando and tower escape skip is on, then set the flag to say we saw the towers fall
|
||||
// and exit.
|
||||
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE)) {
|
||||
if (bShouldTowerRandoSkip) {
|
||||
return;
|
||||
}
|
||||
gSaveContext.cutsceneIndex = 0xFFF0;
|
||||
|
@ -1459,7 +1459,7 @@ void Environment_DrawLensFlare(GlobalContext* globalCtx, EnvironmentContext* env
|
||||
LENS_FLARE_RING, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1,
|
||||
LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1,
|
||||
};
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(gfxCtx);
|
||||
@ -1642,7 +1642,7 @@ void Environment_DrawRain(GlobalContext* globalCtx, View* view, GraphicsContext*
|
||||
Vec3f unused = { 0.0f, 0.0f, 0.0f };
|
||||
Vec3f windDirection = { 0.0f, 0.0f, 0.0f };
|
||||
Player* player = GET_PLAYER(globalCtx);
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
if (!(globalCtx->cameraPtrs[0]->unk_14C & 0x100) && (globalCtx->envCtx.unk_EE[2] == 0)) {
|
||||
@ -1925,7 +1925,7 @@ void Environment_DrawLightning(GlobalContext* globalCtx, s32 unused) {
|
||||
s32 pad[2];
|
||||
Vec3f unused1 = { 0.0f, 0.0f, 0.0f };
|
||||
Vec3f unused2 = { 0.0f, 0.0f, 0.0f };
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
@ -413,7 +413,7 @@ void HealthMeter_Draw(GlobalContext* globalCtx) {
|
||||
s32 curCombineModeSet = 0;
|
||||
u8* curBgImgLoaded = NULL;
|
||||
s32 ddHeartCountMinusOne = gSaveContext.inventory.defenseHearts - 1;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(gfxCtx);
|
||||
|
@ -277,11 +277,15 @@ void Gameplay_Init(GameState* thisx) {
|
||||
u8 tempSetupIndex;
|
||||
s32 pad[2];
|
||||
|
||||
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_CHILD_STEALTH)) {
|
||||
// Skip Child Stealth when option is enabled, Zelda's Letter isn't obtained and Impa's reward hasn't been received
|
||||
// eventChkInf[4] & 1 = Got Zelda's Letter
|
||||
// eventChkInf[5] & 0x200 = Got Impa's reward
|
||||
// entranceIndex 0x7A, Castle Courtyard - Day from crawlspace
|
||||
// entranceIndex 0x400, Zelda's Courtyard
|
||||
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_CHILD_STEALTH) &&
|
||||
!(gSaveContext.eventChkInf[4] & 1) && !(gSaveContext.eventChkInf[5] & 0x200)) {
|
||||
if (gSaveContext.entranceIndex == 0x7A) {
|
||||
gSaveContext.entranceIndex = 0x400;
|
||||
} else if (gSaveContext.entranceIndex == 0x296) {
|
||||
gSaveContext.entranceIndex = 0x23D;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -799,12 +799,12 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
||||
gSaveContext.eventChkInf[1] |= (1 << 3);
|
||||
gSaveContext.eventChkInf[1] |= (1 << 4);
|
||||
|
||||
// Set "Got Zelda's Letter" flag. Also ensures Saria is back at SFM. TODO: Is this flag used for anything else?
|
||||
gSaveContext.eventChkInf[4] |= 1;
|
||||
|
||||
// Got item from impa
|
||||
gSaveContext.eventChkInf[5] |= 0x200;
|
||||
|
||||
// make sure saria is at SFM
|
||||
gSaveContext.eventChkInf[4] |= (1 << 0);
|
||||
|
||||
// set this at the end to ensure we always start with the letter
|
||||
// this is for the off chance we got the weird egg from impa (which should never happen)
|
||||
INV_CONTENT(ITEM_LETTER_ZELDA) = ITEM_LETTER_ZELDA;
|
||||
|
@ -24,7 +24,7 @@ typedef struct {
|
||||
/* 0x36 */ f32 pitch;
|
||||
/* 0x36 */ f32 yaw;
|
||||
/* 0x40 */ f32 roll;
|
||||
/* 0x44 */ s32 epoch;
|
||||
/* 0x44 */ u32 epoch;
|
||||
} BgDyYoseizoParticle; // size = 0x48
|
||||
|
||||
typedef struct BgDyYoseizo {
|
||||
|
@ -13,7 +13,7 @@ typedef struct {
|
||||
/* 0x0C */ Vec3f vel;
|
||||
/* 0x18 */ s16 rotVelX;
|
||||
/* 0x1A */ s16 rotVelY;
|
||||
/* 0x1C */ s32 epoch;
|
||||
/* 0x1C */ u32 epoch;
|
||||
} BgJyaMegamiPiece; // size = 0x20
|
||||
|
||||
typedef struct BgJyaMegami {
|
||||
|
@ -261,7 +261,7 @@ void BgSpot00Hanebasi_DrawTorches(Actor* thisx, GlobalContext* globalCtx2) {
|
||||
GlobalContext* globalCtx = globalCtx2;
|
||||
f32 angle;
|
||||
s32 i;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
@ -17,7 +17,7 @@ typedef struct {
|
||||
/* 0x26 */ Color_RGB8 color;
|
||||
/* 0x2A */ s16 alpha;
|
||||
/* 0x2C */ f32 unk_2C;
|
||||
/* 0x30 */ s32 epoch;
|
||||
/* 0x30 */ u32 epoch;
|
||||
} BossDodongoEffect; // Size = 0x34
|
||||
|
||||
typedef struct BossDodongo {
|
||||
|
@ -1835,7 +1835,7 @@ void BossFd_DrawBody(GlobalContext* globalCtx, BossFd* this) {
|
||||
s16 i;
|
||||
f32 temp_float;
|
||||
Mtx* tempMat = Graph_Alloc(globalCtx->state.gfxCtx, 18 * sizeof(Mtx));
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
@ -87,7 +87,7 @@ typedef struct BossFd2 {
|
||||
/* 0x1394 */ BossFd2Cam camData;
|
||||
/* 0x141C */ ColliderJntSph collider;
|
||||
/* 0x143C */ ColliderJntSphElement elements[9];
|
||||
/* 0x167C */ s32 epoch;
|
||||
/* 0x167C */ u32 epoch;
|
||||
} BossFd2; // size = 0x1680
|
||||
|
||||
#endif
|
||||
|
@ -3356,7 +3356,7 @@ void BossGanon_DrawShock(BossGanon* this, GlobalContext* globalCtx) {
|
||||
s32 pad;
|
||||
GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
|
||||
s16 i;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(gfxCtx);
|
||||
@ -3463,7 +3463,7 @@ void BossGanon_DrawBigMagicCharge(BossGanon* this, GlobalContext* globalCtx) {
|
||||
f32 yRot;
|
||||
GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
|
||||
s16 i;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(gfxCtx);
|
||||
@ -4158,7 +4158,7 @@ void BossGanon_LightBall_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||||
s16 i;
|
||||
f32 alpha;
|
||||
s32 pad;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
@ -2464,7 +2464,7 @@ void func_80904340(BossGanon2* this, GlobalContext* globalCtx) {
|
||||
f32 angle;
|
||||
f32 sin;
|
||||
f32 cos;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
@ -2637,7 +2637,7 @@ void BossGanon2_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dLis
|
||||
void func_80904D88(BossGanon2* this, GlobalContext* globalCtx) {
|
||||
s32 pad;
|
||||
s16 i;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
@ -2701,7 +2701,7 @@ void func_80904FC8(BossGanon2* this, GlobalContext* globalCtx) {
|
||||
void func_8090523C(BossGanon2* this, GlobalContext* globalCtx) {
|
||||
Player* player;
|
||||
f32 phi_f20;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
@ -2933,7 +2933,7 @@ void func_809060E8(GlobalContext* globalCtx) {
|
||||
BossGanon2Effect* effect;
|
||||
s16 i;
|
||||
BossGanon2Effect* effects;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
effects = effect = globalCtx->specialEffects;
|
||||
|
@ -2443,7 +2443,7 @@ void BossMo_DrawTentacle(BossMo* this, GlobalContext* globalCtx) {
|
||||
f32 phi_f20;
|
||||
f32 phi_f22;
|
||||
Vec3f sp110;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
@ -2706,7 +2706,7 @@ s32 BossSst_OverrideHandTrailDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx**
|
||||
|
||||
void BossSst_DrawHand(Actor* thisx, GlobalContext* globalCtx) {
|
||||
BossSst* this = (BossSst*)thisx;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
@ -17,7 +17,7 @@ typedef struct {
|
||||
/* 0x0020 */ s16 move;
|
||||
/* 0x0022 */ s16 status;
|
||||
/* 0x0024 */ u8 alpha;
|
||||
/* 0x0028 */ s32 epoch;
|
||||
/* 0x0028 */ u32 epoch;
|
||||
} BossSstEffect; // size = 0x2C
|
||||
|
||||
typedef struct {
|
||||
|
@ -3329,7 +3329,7 @@ void func_80942180(BossTw* this, GlobalContext* globalCtx) {
|
||||
void func_809426F0(BossTw* this, GlobalContext* globalCtx) {
|
||||
s32 pad;
|
||||
s16 i;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
@ -4418,7 +4418,7 @@ void BossTw_BlastDraw(Actor* thisx, GlobalContext* globalCtx2) {
|
||||
f32 scaleFactor;
|
||||
s16 tailIdx;
|
||||
s16 i;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
@ -4492,7 +4492,7 @@ void BossTw_DrawDeathBall(Actor* thisx, GlobalContext* globalCtx2) {
|
||||
f32 scaleFactor;
|
||||
s16 tailIdx;
|
||||
s16 i;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
@ -43,7 +43,7 @@ typedef struct {
|
||||
/* 0x002E */ s16 work[EFF_WORK_MAX];
|
||||
/* 0x0034 */ f32 workf[EFF_FWORK_MAX];
|
||||
/* 0x0044 */ Actor* target;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} BossTwEffect;
|
||||
|
||||
typedef enum {
|
||||
|
@ -4006,7 +4006,7 @@ void BossVa_DrawDoor(GlobalContext* globalCtx, s16 scale) {
|
||||
f32 yScale;
|
||||
f32 segAngle = 0.0f;
|
||||
s32 i;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
@ -564,7 +564,7 @@ void func_80967FFC(Actor* thisx, GlobalContext* globalCtx) {
|
||||
Demo6K* this = (Demo6K*)thisx;
|
||||
s32 pad;
|
||||
u16 timer1 = this->timer1;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
@ -695,7 +695,7 @@ void func_809688C4(Actor* thisx, GlobalContext* globalCtx2) {
|
||||
GlobalContext* globalCtx = globalCtx2;
|
||||
u32 frames = globalCtx->state.frames;
|
||||
s32 i;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
if ((i = (globalCtx->csCtx.state != CS_STATE_IDLE) && (globalCtx->csCtx.npcActions[1] != NULL)) &&
|
||||
|
@ -522,7 +522,7 @@ void DemoKankyo_DrawRain(Actor* thisx, GlobalContext* globalCtx) {
|
||||
f32 translateY;
|
||||
f32 translateZ;
|
||||
s16 j;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
@ -663,7 +663,7 @@ void DemoKankyo_DrawClouds(Actor* thisx, GlobalContext* globalCtx) {
|
||||
f32 dx;
|
||||
f32 dy;
|
||||
f32 dz;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
@ -784,7 +784,7 @@ void DemoKankyo_DrawWarpSparkles(Actor* thisx, GlobalContext* globalCtx) {
|
||||
f32 translateZ;
|
||||
PosRot posRot;
|
||||
u8 linkAge = gSaveContext.linkAge;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
@ -933,7 +933,7 @@ void DemoKankyo_DrawSparkles(Actor* thisx, GlobalContext* globalCtx) {
|
||||
f32 scale;
|
||||
s16 i;
|
||||
PosRot posRot;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
@ -19,7 +19,7 @@ typedef struct {
|
||||
/* 0x30 */ char unk_2C[4];
|
||||
/* 0x34 */ f32 scale;
|
||||
/* 0x38 */ char unk_34[8];
|
||||
/* 0x3C */ s32 epoch;
|
||||
/* 0x3C */ u32 epoch;
|
||||
} EfcErupcParticles; // size 0x40
|
||||
|
||||
#define EFC_ERUPC_NUM_PARTICLES 100
|
||||
|
@ -269,7 +269,7 @@ void EffDust_DrawFunc_8099E4F4(Actor* thisx, GlobalContext* globalCtx2) {
|
||||
f32* distanceTraveled;
|
||||
s32 i;
|
||||
f32 aux;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(gfxCtx);
|
||||
@ -321,7 +321,7 @@ void EffDust_DrawFunc_8099E784(Actor* thisx, GlobalContext* globalCtx2) {
|
||||
s32 i;
|
||||
f32 aux;
|
||||
Player* player = GET_PLAYER(globalCtx);
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(gfxCtx);
|
||||
|
@ -19,7 +19,7 @@ typedef struct EnAnubiceFire {
|
||||
/* 0x015E */ s16 unk_15E;
|
||||
/* 0x0178 */ Vec3f unk_160[6];
|
||||
/* 0x01A8 */ ColliderCylinder cylinder;
|
||||
/* 0x01F4 */ s32 epoch;
|
||||
/* 0x01F4 */ u32 epoch;
|
||||
} EnAnubiceFire; // size = 0x01F8
|
||||
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@ typedef struct EnBa {
|
||||
/* 0x031C */ s16 unk31C;
|
||||
/* 0x0320 */ ColliderJntSph collider;
|
||||
/* 0x0340 */ ColliderJntSphElement colliderItems[2];
|
||||
/* 0x03C0 */ s32 epoch;
|
||||
/* 0x03C0 */ u32 epoch;
|
||||
} EnBa; // size = 0x03C4
|
||||
|
||||
#endif
|
||||
|
@ -167,12 +167,12 @@ void EnBoom_Fly(EnBoom* this, GlobalContext* globalCtx) {
|
||||
|
||||
// Decrement the return timer and check if it's 0. If it is, check if Link can catch it and handle accordingly.
|
||||
// Otherwise handle grabbing and colliding.
|
||||
if (DECR(this->returnTimer) == 0) {
|
||||
if (DECR(this->returnTimer) == 0 || player->boomerangQuickRecall) {
|
||||
distFromLink = Math_Vec3f_DistXYZ(&this->actor.world.pos, &player->actor.focus.pos);
|
||||
this->moveTo = &player->actor;
|
||||
|
||||
// If the boomerang is less than 40 units away from Link, he can catch it.
|
||||
if (distFromLink < 40.0f) {
|
||||
if (distFromLink < 40.0f || player->boomerangQuickRecall) {
|
||||
target = this->grabbed;
|
||||
if (target != NULL) {
|
||||
Math_Vec3f_Copy(&target->world.pos, &player->actor.world.pos);
|
||||
@ -187,7 +187,8 @@ void EnBoom_Fly(EnBoom* this, GlobalContext* globalCtx) {
|
||||
}
|
||||
}
|
||||
// Set player flags and kill the boomerang beacause Link caught it.
|
||||
player->stateFlags1 &= ~0x02000000;
|
||||
player->stateFlags1 &= ~PLAYER_STATE1_25;
|
||||
player->boomerangQuickRecall = false;
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
} else {
|
||||
|
@ -16,7 +16,7 @@ typedef struct EnBx {
|
||||
/* 0x01B4 */ Vec3s unk_1B4[4];
|
||||
/* 0x01CC */ ColliderCylinder collider;
|
||||
/* 0x0218 */ ColliderQuad colliderQuad;
|
||||
/* 0x0298 */ s32 epoch;
|
||||
/* 0x0298 */ u32 epoch;
|
||||
} EnBx; // size = 0x029C
|
||||
|
||||
#endif
|
||||
|
@ -88,7 +88,7 @@ typedef struct EnClearTagEffect {
|
||||
/* 0x0058 */ f32 rotationX;
|
||||
/* 0x005C */ f32 floorHeight;
|
||||
/* 0x0060 */ Vec3f floorTangent;
|
||||
/* 0x006C */ s32 epoch;
|
||||
/* 0x006C */ u32 epoch;
|
||||
} EnClearTagEffect; // size = 0x70
|
||||
|
||||
#define CLEAR_TAG_EFFECT_MAX_COUNT 100
|
||||
|
@ -14,7 +14,7 @@ typedef struct {
|
||||
/* 0x0010 */ u8 isAlive;
|
||||
/* 0x0014 */ Vec3f moveDirection;
|
||||
/* 0x0020 */ Vec3f rot;
|
||||
/* 0x002C */ s32 epoch;
|
||||
/* 0x002C */ u32 epoch;
|
||||
} EnEncount2Particle; // size = 0x30
|
||||
|
||||
typedef struct EnEncount2 {
|
||||
|
@ -25,7 +25,7 @@ typedef struct {
|
||||
/* 0x0014 */ Vec3f pos;
|
||||
/* 0x0020 */ Vec3f velocity;
|
||||
/* 0x002C */ Vec3f accel;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnFdEffect; // size = 0x38
|
||||
|
||||
typedef struct EnFd {
|
||||
|
@ -19,7 +19,7 @@ typedef struct {
|
||||
/* 0x0014 */ Vec3f pos;
|
||||
/* 0x0020 */ Vec3f velocity;
|
||||
/* 0x002C */ Vec3f accel;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnFwEffect;
|
||||
|
||||
typedef struct EnFw {
|
||||
|
@ -21,7 +21,7 @@ typedef struct {
|
||||
/* 0x0030 */ f32 xyScale; //
|
||||
/* 0x0034 */ f32 xyScaleTarget;
|
||||
/* 0x0038 */ u8 isTimerMod8; // conditional, used to run CollisionCheck_SetAT
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnFzEffectSsIceSmoke; // size = 0x3C
|
||||
|
||||
typedef struct EnFz {
|
||||
|
@ -32,7 +32,7 @@ typedef struct {
|
||||
/* 0x12 */ u8 flag;
|
||||
/* 0x14 */ Vec3f velocity;
|
||||
/* 0x20 */ Vec3f rot;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnGSwitchEffect; // size = 0x2C
|
||||
|
||||
typedef struct EnGSwitch {
|
||||
|
@ -27,7 +27,7 @@ typedef struct {
|
||||
/* 0x20 */ f32 unk_20;
|
||||
/* 0x24 */ f32 unk_24;
|
||||
/* 0x28 */ f32 unk_28;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnGbCagedSoul; // size = 0x2C
|
||||
|
||||
typedef struct EnGb {
|
||||
|
@ -34,7 +34,7 @@ typedef struct {
|
||||
/* 0x0014 */ Vec3f pos;
|
||||
/* 0x0020 */ Vec3f velocity;
|
||||
/* 0x002C */ Vec3f accel;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnGoEffect; // size = 0x38
|
||||
|
||||
typedef struct EnGo {
|
||||
|
@ -112,14 +112,23 @@ void EnHeishi1_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||
}
|
||||
}
|
||||
|
||||
// eventChkInf[4] & 1 = Got Zelda's Letter
|
||||
// eventChkInf[5] & 0x200 = Got item from impa
|
||||
// eventChkInf[8] & 1 = Ocarina thrown in moat
|
||||
bool metZelda = (gSaveContext.eventChkInf[4] & 1) && (gSaveContext.eventChkInf[5] & 0x200);
|
||||
|
||||
if (this->type != 5) {
|
||||
if (((gSaveContext.dayTime < 0xB888) || IS_DAY) && (gSaveContext.n64ddFlag || !(gSaveContext.eventChkInf[8] & 1))) {
|
||||
if ((gSaveContext.dayTime < 0xB888 || IS_DAY) &&
|
||||
((!gSaveContext.n64ddFlag && !(gSaveContext.eventChkInf[8] & 1)) ||
|
||||
(gSaveContext.n64ddFlag && !metZelda))) {
|
||||
this->actionFunc = EnHeishi1_SetupWalk;
|
||||
} else {
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
} else {
|
||||
if ((gSaveContext.dayTime >= 0xB889) || !IS_DAY || (!gSaveContext.n64ddFlag && (gSaveContext.eventChkInf[8] & 1))) {
|
||||
if ((gSaveContext.dayTime >= 0xB889) || !IS_DAY ||
|
||||
(!gSaveContext.n64ddFlag && gSaveContext.eventChkInf[8] & 1) ||
|
||||
(gSaveContext.n64ddFlag && metZelda)) {
|
||||
this->actionFunc = EnHeishi1_SetupWaitNight;
|
||||
} else {
|
||||
Actor_Kill(&this->actor);
|
||||
|
@ -18,7 +18,7 @@ typedef struct {
|
||||
/* 0x002C */ f32 scale;
|
||||
/* 0x0030 */ f32 unk_30;
|
||||
/* 0x0034 */ u8 timer;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnNiwFeather; // size = 0x0038
|
||||
|
||||
typedef struct EnNiw {
|
||||
|
@ -23,7 +23,7 @@ typedef struct EnNwcChick {
|
||||
/* 0x36 */ u16 height;
|
||||
/* 0x38 */ CollisionPoly* floorPoly;
|
||||
/* 0x44 */ char unk_3C[0x20];
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnNwcChick; // size = 0x5C
|
||||
|
||||
typedef struct EnNwc {
|
||||
|
@ -30,7 +30,7 @@ typedef struct EnNy {
|
||||
/* 0x01F0 */ f32 unk_1F0;
|
||||
/* 0x01F4 */ f32 unk_1F4;
|
||||
/* 0x01F8 */ Vec3f unk_1F8[16];
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnNy; // size = 0x02B8
|
||||
|
||||
#endif
|
||||
|
@ -29,7 +29,7 @@ typedef struct EnPoSisters {
|
||||
/* 0x029C */ LightInfo lightInfo;
|
||||
/* 0x02AC */ ColliderCylinder collider;
|
||||
/* 0x02F8 */ MtxF unk_2F8;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnPoSisters; // size = 0x0338
|
||||
|
||||
#endif
|
||||
|
@ -760,6 +760,14 @@ void func_80AEC2C0(EnRu1* this, GlobalContext* globalCtx) {
|
||||
func_80AEC070(this, globalCtx, something);
|
||||
}
|
||||
|
||||
// Convenience function used so that Ruto always spawns in Jabu in rando, even after she's been kidnapped
|
||||
// Equivalent to !(gSaveContext.infTable[20] & 0x20) in vanilla
|
||||
bool shouldSpawnRuto() {
|
||||
// gSaveContext.infTable[20] & 0x40 check is to prevent Ruto from spawning during the short period of time when
|
||||
// she's on the Zora's Sapphire pedestal but hasn't been kidnapped yet (would result in multiple Rutos otherwise)
|
||||
return !(gSaveContext.infTable[20] & 0x20) || (gSaveContext.n64ddFlag && (gSaveContext.infTable[20] & 0x40));
|
||||
}
|
||||
|
||||
void func_80AEC320(EnRu1* this, GlobalContext* globalCtx) {
|
||||
s8 actorRoom;
|
||||
|
||||
@ -767,8 +775,7 @@ void func_80AEC320(EnRu1* this, GlobalContext* globalCtx) {
|
||||
func_80AEB264(this, &gRutoChildWait2Anim, 0, 0, 0);
|
||||
this->action = 7;
|
||||
EnRu1_SetMouthIndex(this, 1);
|
||||
} else if ((gSaveContext.infTable[20] & 0x80) && !(gSaveContext.infTable[20] & 1) &&
|
||||
!(gSaveContext.infTable[20] & 0x20)) {
|
||||
} else if ((gSaveContext.infTable[20] & 0x80) && !(gSaveContext.infTable[20] & 1) && shouldSpawnRuto()) {
|
||||
if (!func_80AEB020(this, globalCtx)) {
|
||||
func_80AEB264(this, &gRutoChildWait2Anim, 0, 0, 0);
|
||||
actorRoom = this->actor.room;
|
||||
@ -1172,7 +1179,7 @@ void func_80AED414(EnRu1* this, GlobalContext* globalCtx) {
|
||||
void func_80AED44C(EnRu1* this, GlobalContext* globalCtx) {
|
||||
s8 actorRoom;
|
||||
|
||||
if ((gSaveContext.infTable[20] & 2) && !(gSaveContext.infTable[20] & 0x20) && !(gSaveContext.infTable[20] & 1) &&
|
||||
if ((gSaveContext.infTable[20] & 2) && shouldSpawnRuto() && !(gSaveContext.infTable[20] & 1) &&
|
||||
!(gSaveContext.infTable[20] & 0x80)) {
|
||||
if (!func_80AEB020(this, globalCtx)) {
|
||||
func_80AEB264(this, &gRutoChildWait2Anim, 0, 0, 0);
|
||||
@ -2179,7 +2186,7 @@ void func_80AEFF40(EnRu1* this, GlobalContext* globalCtx) {
|
||||
void func_80AEFF94(EnRu1* this, GlobalContext* globalCtx) {
|
||||
s8 actorRoom;
|
||||
|
||||
if ((gSaveContext.infTable[20] & 2) && (gSaveContext.infTable[20] & 1) && !(gSaveContext.infTable[20] & 0x20) &&
|
||||
if ((gSaveContext.infTable[20] & 2) && (gSaveContext.infTable[20] & 1) && shouldSpawnRuto() &&
|
||||
(!(func_80AEB020(this, globalCtx)))) {
|
||||
func_80AEB264(this, &gRutoChildWait2Anim, 0, 0, 0);
|
||||
actorRoom = this->actor.room;
|
||||
|
@ -108,6 +108,7 @@ void func_80AFB768(EnSi* this, GlobalContext* globalCtx) {
|
||||
giveItemId = sGetItemTable[getItemId - 1].itemId;
|
||||
Item_Give(globalCtx, giveItemId);
|
||||
}
|
||||
player->getItemId = getItemId;
|
||||
} else {
|
||||
Item_Give(globalCtx, giveItemId);
|
||||
}
|
||||
@ -150,6 +151,7 @@ void func_80AFB89C(EnSi* this, GlobalContext* globalCtx) {
|
||||
giveItemId = sGetItemTable[getItemId - 1].itemId;
|
||||
Item_Give(globalCtx, giveItemId);
|
||||
}
|
||||
player->getItemId = getItemId;
|
||||
} else {
|
||||
Item_Give(globalCtx, giveItemId);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ typedef struct {
|
||||
/* 0x2C */ f32 unk_2C;
|
||||
/* 0x30 */ f32 unk_30;
|
||||
/* 0x34 */ u8 unk_34;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnSyatekiNiw_1; // size = 0x38
|
||||
|
||||
typedef struct EnSyatekiNiw {
|
||||
|
@ -460,10 +460,13 @@ void func_80B14AF4(EnTa* this, GlobalContext* globalCtx) {
|
||||
|
||||
void func_80B14B6C(EnTa* this, GlobalContext* globalCtx) {
|
||||
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT) {
|
||||
OnePointCutscene_Init(globalCtx, 4175, -99, &this->actor, MAIN_CAM);
|
||||
s16 csCamIdx = OnePointCutscene_Init(globalCtx, 4175, -99, &this->actor, MAIN_CAM);
|
||||
func_80B13AA0(this, func_80B14AF4, func_80B167C0);
|
||||
this->unk_2CC = 5;
|
||||
gSaveContext.eventChkInf[1] |= 0x10;
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
OnePointCutscene_EndCutscene(globalCtx, csCamIdx);
|
||||
}
|
||||
Animation_PlayOnce(&this->skelAnime, &gTalonRunTransitionAnim);
|
||||
this->currentAnimation = &gTalonRunAnim;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ typedef struct EnTkEff {
|
||||
/* 0x0014 */ Vec3f pos;
|
||||
/* 0x0020 */ Vec3f speed;
|
||||
/* 0x002C */ Vec3f accel;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnTkEff; // size = 0x0038
|
||||
|
||||
struct EnTk;
|
||||
|
@ -56,7 +56,7 @@ typedef struct {
|
||||
/* 0x28 */ f32 scale;
|
||||
/* 0x2C */ f32 lerpFactor;
|
||||
/* 0x30 */ u8 state;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} EnViewerFireEffect; // size = 0x34
|
||||
|
||||
typedef struct EnViewer {
|
||||
|
@ -90,7 +90,7 @@ typedef struct {
|
||||
/* 0x32 */ s16 timer;
|
||||
/* 0x34 */ u8 shouldDraw;
|
||||
/* 0x38 */ f32 drawDistance;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} FishingProp; // size = 0x3C
|
||||
|
||||
typedef enum {
|
||||
@ -116,7 +116,7 @@ typedef struct {
|
||||
/* 0x40 */ s16 unk_40;
|
||||
/* 0x42 */ s16 unk_42;
|
||||
/* 0x44 */ u8 shouldDraw;
|
||||
s32 epoch;
|
||||
u32 epoch;
|
||||
} FishingGroupFish; // size = 0x48
|
||||
|
||||
#define LINE_SEG_COUNT 200
|
||||
@ -1766,7 +1766,7 @@ static f32 sSinkingLureSizes[] = {
|
||||
void Fishing_DrawSinkingLure(GlobalContext* globalCtx) {
|
||||
s16 i;
|
||||
f32 scale;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
@ -482,7 +482,7 @@ void MirRay_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||||
s32 i;
|
||||
MirRayShieldReflection reflection[6];
|
||||
s32 temp;
|
||||
static s32 epoch = 0;
|
||||
static u32 epoch = 0;
|
||||
epoch++;
|
||||
|
||||
this->reflectIntensity = 0.0f;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||
#include "objects/object_link_child/object_link_child.h"
|
||||
#include "textures/icon_item_24_static/icon_item_24_static.h"
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
|
||||
#define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim) \
|
||||
{ itemId, field, (chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1), textId, objectId }
|
||||
@ -138,10 +139,10 @@ s32 func_808353D8(Player* this, GlobalContext* globalCtx);
|
||||
s32 func_80835588(Player* this, GlobalContext* globalCtx);
|
||||
s32 func_808356E8(Player* this, GlobalContext* globalCtx);
|
||||
s32 func_80835800(Player* this, GlobalContext* globalCtx);
|
||||
s32 func_80835884(Player* this, GlobalContext* globalCtx);
|
||||
s32 func_808358F0(Player* this, GlobalContext* globalCtx);
|
||||
s32 func_808359FC(Player* this, GlobalContext* globalCtx);
|
||||
s32 func_80835B60(Player* this, GlobalContext* globalCtx);
|
||||
s32 func_80835884(Player* this, GlobalContext* globalCtx); // Start aiming boomerang
|
||||
s32 func_808358F0(Player* this, GlobalContext* globalCtx); // Aim boomerang
|
||||
s32 func_808359FC(Player* this, GlobalContext* globalCtx); // Throw boomerang
|
||||
s32 func_80835B60(Player* this, GlobalContext* globalCtx); // Boomerang active
|
||||
s32 func_80835C08(Player* this, GlobalContext* globalCtx);
|
||||
void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item);
|
||||
void func_80839F90(Player* this, GlobalContext* globalCtx);
|
||||
@ -479,8 +480,8 @@ static s32 D_80853604 = 0;
|
||||
static s32 D_80853608 = 0;
|
||||
static s32 D_8085360C = 0;
|
||||
static s16 D_80853610 = 0;
|
||||
static s32 D_80853614 = 0;
|
||||
static s32 D_80853618 = 0;
|
||||
static s32 D_80853614 = 0; // Held item button just pressed?
|
||||
static s32 D_80853618 = 0; // Held item button currently down?
|
||||
|
||||
static u16 D_8085361C[] = {
|
||||
NA_SE_VO_LI_SWEAT,
|
||||
@ -645,15 +646,15 @@ GetItemEntry sGetItemTable[] = {
|
||||
GET_ITEM(ITEM_DOUBLE_MAGIC, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xE9, 0x80, CHEST_ANIM_LONG),
|
||||
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, 0xF9, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
|
||||
GET_ITEM_NONE,
|
||||
GET_ITEM_NONE,
|
||||
@ -947,6 +948,7 @@ static s8 sItemActionParams[] = {
|
||||
|
||||
static u8 sMaskMemory;
|
||||
|
||||
// Used to map action params to update functions
|
||||
static s32(*D_80853EDC[])(Player* this, GlobalContext* globalCtx) = {
|
||||
func_8083485C, func_8083485C, func_8083485C, func_808349DC, func_808349DC, func_808349DC, func_8083485C,
|
||||
func_8083485C, func_8083501C, func_8083501C, func_8083501C, func_8083501C, func_8083501C, func_8083501C,
|
||||
@ -2721,6 +2723,10 @@ s32 func_80835B60(Player* this, GlobalContext* globalCtx) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (D_80853614 && CVar_GetS32("gFastBoomerang", 0)) {
|
||||
this->boomerangQuickRecall = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ typedef struct {
|
||||
/* 0x24 */ s16 scale;
|
||||
/* 0x26 */ s16 scaleStep;
|
||||
/* 0x28 */ u8 drawMode;
|
||||
/* 0x29 */ s32 epoch;
|
||||
/* 0x29 */ u32 epoch;
|
||||
} EffectSsBomb2InitParams; // size = 0x30
|
||||
|
||||
#endif
|
||||
|
@ -12,12 +12,12 @@ static s16 sEquipMoveTimer = 10;
|
||||
bool gSelectingMask;
|
||||
|
||||
static s16 sAmmoVtxOffset[] = {
|
||||
0, 2, 4, 6, 99, 99, 8, 99, 99, 10, 99, 99, 99, 99, 99, 99, 12,
|
||||
0, 2, 4, 6, 99, 99, 8, 99, 10, 99, 99, 99, 99, 99, 12,
|
||||
};
|
||||
|
||||
extern const char* _gAmmoDigit0Tex[];
|
||||
|
||||
void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, s16 item) {
|
||||
void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, s16 item, int slot) {
|
||||
s16 ammo;
|
||||
s16 i;
|
||||
|
||||
@ -51,7 +51,7 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx,
|
||||
gDPPipeSync(POLY_KAL_DISP++);
|
||||
|
||||
if (i != 0) {
|
||||
gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[(sAmmoVtxOffset[item] + 31) * 4], 4, 0);
|
||||
gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[(sAmmoVtxOffset[slot] + 31) * 4], 4, 0);
|
||||
|
||||
gDPLoadTextureBlock(POLY_KAL_DISP++, ((u8*)_gAmmoDigit0Tex[i]), G_IM_FMT_IA, G_IM_SIZ_8b, 8, 8, 0,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
|
||||
@ -60,7 +60,7 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx,
|
||||
gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0);
|
||||
}
|
||||
|
||||
gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[(sAmmoVtxOffset[item] + 32) * 4], 4, 0);
|
||||
gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[(sAmmoVtxOffset[slot] + 32) * 4], 4, 0);
|
||||
|
||||
gDPLoadTextureBlock(POLY_KAL_DISP++, ((u8*)_gAmmoDigit0Tex[ammo]), G_IM_FMT_IA, G_IM_SIZ_8b, 8, 8, 0,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
|
||||
@ -499,7 +499,7 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
|
||||
|
||||
for (i = 0; i < 15; i++) {
|
||||
if ((gAmmoItems[i] != ITEM_NONE) && (gSaveContext.inventory.items[i] != ITEM_NONE)) {
|
||||
KaleidoScope_DrawAmmoCount(pauseCtx, globalCtx->state.gfxCtx, gSaveContext.inventory.items[i]);
|
||||
KaleidoScope_DrawAmmoCount(pauseCtx, globalCtx->state.gfxCtx, gSaveContext.inventory.items[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user