mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-22 14:23:44 -07:00
Merge branch 'develop' into hud_color_mod
This commit is contained in:
commit
c351d81d4d
23 changed files with 341 additions and 187 deletions
12
BUILDING.md
12
BUILDING.md
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Windows
|
||||
|
||||
1. Install [Python](https://www.python.org/downloads/) >= 3.6.
|
||||
1. Requires [Python](https://www.python.org/downloads/) >= 3.6.
|
||||
2. Install [Visual Studio 2022 Community Edition](https://visualstudio.microsoft.com/vs/community/)
|
||||
3. In the Visual Studio Installer, install `MSVC v142 - VS 2019 C++`.
|
||||
4. Clone the Ship of Harkinian repository.
|
||||
|
@ -57,10 +57,10 @@ OOT_PAL_GC_DBG1 checksum 0x871E1C92 (debug non-master quest)
|
|||
The OTRExporter exports an `oot.otr` archive file which Ship of Harkinian requires to play.
|
||||
|
||||
Use the `extract_assets.py` script file to run the exporter using any of the following methods:
|
||||
1) Double click on the script after placing one or more roms in the directory.
|
||||
2) Drag & Drop a rom onto the script.
|
||||
3) In a terminal run `python3 extract_assets.py` after placing one or more roms in the directory.
|
||||
4) In a terminal run `python3 extract_assets.py <path_to_rom>`
|
||||
|
||||
1. Double click on the script after placing one or more roms in the directory.
|
||||
2. Drag & Drop a rom onto the script.
|
||||
3. In a terminal run `python3 extract_assets.py` after placing one or more roms in the directory.
|
||||
4. In a terminal run `python3 extract_assets.py <path_to_rom>`
|
||||
If the script finds multiple roms the user is prompted which to use. Selection is done using the number keys and then pressing the carriage return key.
|
||||
|
||||
If the script finds multiple roms the user is prompted which to use. Selection is done using the number keys and then pressing the carriage return key.
|
|
@ -64,6 +64,9 @@ Refer to the [building instructions](BUILDING.md) to compile SoH.
|
|||
- Affirm that you have an `/assets` folder filled with XMLs in the same directory as OTRGui.exe
|
||||
- Affirm that `zapd.exe` exists in the `/assets/extractor` folder
|
||||
|
||||
## Nightly Builds
|
||||
Nightly builds of Ship of Harkinian are available at [https://builds.shipofharkinian.com/job/SoH_Multibranch/job/develop]
|
||||
|
||||
|
||||
## The Harbour Masters Are...
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ namespace Ship {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::vector<SFILE_FIND_DATA> Archive::ListFiles(const std::string& searchMask) {
|
||||
std::vector<SFILE_FIND_DATA> Archive::ListFiles(const std::string& searchMask) const {
|
||||
auto fileList = std::vector<SFILE_FIND_DATA>();
|
||||
SFILE_FIND_DATA findContext;
|
||||
HANDLE hFind;
|
||||
|
@ -248,7 +248,7 @@ namespace Ship {
|
|||
return fileList;
|
||||
}
|
||||
|
||||
bool Archive::HasFile(const std::string& filename) {
|
||||
bool Archive::HasFile(const std::string& filename) const {
|
||||
bool result = false;
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
|
@ -267,8 +267,9 @@ namespace Ship {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string Archive::HashToString(uint64_t hash) {
|
||||
return hashes[hash];
|
||||
const std::string* Archive::HashToString(uint64_t hash) const {
|
||||
auto it = hashes.find(hash);
|
||||
return it != hashes.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
bool Archive::Load(bool enableWriting, bool genCRCMap) {
|
||||
|
|
|
@ -34,9 +34,9 @@ namespace Ship
|
|||
bool AddFile(const std::string& path, uintptr_t fileData, DWORD dwFileSize);
|
||||
bool RemoveFile(const std::string& path);
|
||||
bool RenameFile(const std::string& oldPath, const std::string& newPath);
|
||||
std::vector<SFILE_FIND_DATA> ListFiles(const std::string& searchMask);
|
||||
bool HasFile(const std::string& searchMask);
|
||||
std::string HashToString(uint64_t hash);
|
||||
std::vector<SFILE_FIND_DATA> ListFiles(const std::string& searchMask) const;
|
||||
bool HasFile(const std::string& searchMask) const;
|
||||
const std::string* HashToString(uint64_t hash) const;
|
||||
protected:
|
||||
bool Load(bool enableWriting, bool genCRCMap);
|
||||
bool Unload();
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
// OTRTODO: fix header files for these
|
||||
extern "C" {
|
||||
char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc);
|
||||
const char* ResourceMgr_GetNameByCRC(uint64_t crc);
|
||||
int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc);
|
||||
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc);
|
||||
Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc);
|
||||
|
@ -88,7 +88,7 @@ struct LoadedVertex {
|
|||
|
||||
static struct {
|
||||
TextureCacheMap map;
|
||||
list<TextureCacheMap::iterator> lru;
|
||||
list<TextureCacheMapIter> lru;
|
||||
vector<uint32_t> free_texture_ids;
|
||||
} gfx_texture_cache;
|
||||
|
||||
|
@ -134,14 +134,14 @@ static struct RDP {
|
|||
const uint8_t *addr;
|
||||
uint8_t siz;
|
||||
uint32_t width;
|
||||
char* otr_path;
|
||||
const char* otr_path;
|
||||
} texture_to_load;
|
||||
struct {
|
||||
const uint8_t *addr;
|
||||
uint32_t size_bytes;
|
||||
uint32_t full_image_line_size_bytes;
|
||||
uint32_t line_size_bytes;
|
||||
char* otr_path;
|
||||
const char* otr_path;
|
||||
} loaded_texture[2];
|
||||
struct {
|
||||
uint8_t fmt;
|
||||
|
@ -527,18 +527,18 @@ static bool gfx_texture_cache_lookup(int i, int tile) {
|
|||
key = { orig_addr, { }, fmt, siz, palette_index };
|
||||
}
|
||||
|
||||
auto it = gfx_texture_cache.map.find(key);
|
||||
TextureCacheMap::iterator it = gfx_texture_cache.map.find(key);
|
||||
|
||||
if (it != gfx_texture_cache.map.end()) {
|
||||
gfx_rapi->select_texture(i, it->second.texture_id);
|
||||
*n = &*it;
|
||||
gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru, *(list<TextureCacheMap::iterator>::iterator*)&it->second.lru_location); // move to back
|
||||
gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru, it->second.lru_location); // move to back
|
||||
return true;
|
||||
}
|
||||
|
||||
if (gfx_texture_cache.map.size() >= TEXTURE_CACHE_MAX_SIZE) {
|
||||
// Remove the texture that was least recently used
|
||||
it = gfx_texture_cache.lru.front();
|
||||
it = gfx_texture_cache.lru.front().it;
|
||||
gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id);
|
||||
gfx_texture_cache.map.erase(it);
|
||||
gfx_texture_cache.lru.pop_front();
|
||||
|
@ -555,7 +555,7 @@ static bool gfx_texture_cache_lookup(int i, int tile) {
|
|||
it = gfx_texture_cache.map.insert(make_pair(key, TextureCacheValue())).first;
|
||||
TextureCacheNode* node = &*it;
|
||||
node->second.texture_id = texture_id;
|
||||
*(list<TextureCacheMap::iterator>::iterator*)&node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), it);
|
||||
node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), { it });
|
||||
|
||||
gfx_rapi->select_texture(i, texture_id);
|
||||
gfx_rapi->set_sampler_parameters(i, false, 0, 0);
|
||||
|
@ -571,7 +571,7 @@ static void gfx_texture_cache_delete(const uint8_t* orig_addr)
|
|||
bool again = false;
|
||||
for (auto it = gfx_texture_cache.map.begin(bucket); it != gfx_texture_cache.map.end(bucket); ++it) {
|
||||
if (it->first.texture_addr == orig_addr) {
|
||||
gfx_texture_cache.lru.erase(*(list<TextureCacheMap::iterator>::iterator*)&it->second.lru_location);
|
||||
gfx_texture_cache.lru.erase(it->second.lru_location);
|
||||
gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id);
|
||||
gfx_texture_cache.map.erase(it->first);
|
||||
again = true;
|
||||
|
@ -1636,11 +1636,11 @@ static void gfx_dp_set_scissor(uint32_t mode, uint32_t ulx, uint32_t uly, uint32
|
|||
rdp.viewport_or_scissor_changed = true;
|
||||
}
|
||||
|
||||
static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr, char* otr_path) {
|
||||
static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr, const char* otr_path) {
|
||||
rdp.texture_to_load.addr = (const uint8_t*)addr;
|
||||
rdp.texture_to_load.siz = size;
|
||||
rdp.texture_to_load.width = width;
|
||||
if ( otr_path != nullptr && !strncmp(otr_path, "__OTR__", 7)) otr_path = otr_path + 7;
|
||||
if (otr_path != nullptr && !strncmp(otr_path, "__OTR__", 7)) otr_path = otr_path + 7;
|
||||
rdp.texture_to_load.otr_path = otr_path;
|
||||
}
|
||||
|
||||
|
@ -2114,7 +2114,7 @@ static void gfx_run_dl(Gfx* cmd) {
|
|||
//puts("dl");
|
||||
int dummy = 0;
|
||||
char dlName[128];
|
||||
char fileName[128];
|
||||
const char* fileName;
|
||||
|
||||
Gfx* dListStart = cmd;
|
||||
uint64_t ourHash = -1;
|
||||
|
@ -2437,7 +2437,7 @@ static void gfx_run_dl(Gfx* cmd) {
|
|||
uintptr_t addr = cmd->words.w1;
|
||||
cmd++;
|
||||
uint64_t hash = ((uint64_t)cmd->words.w0 << 32) + (uint64_t)cmd->words.w1;
|
||||
ResourceMgr_GetNameByCRC(hash, fileName);
|
||||
fileName = ResourceMgr_GetNameByCRC(hash);
|
||||
#if _DEBUG && 0
|
||||
char* tex = ResourceMgr_LoadTexByCRC(hash);
|
||||
ResourceMgr_GetNameByCRC(hash, fileName);
|
||||
|
|
|
@ -46,12 +46,11 @@ struct TextureCacheValue {
|
|||
uint8_t cms, cmt;
|
||||
bool linear_filter;
|
||||
|
||||
// Old versions of libstdc++ fail to compile this
|
||||
#ifdef _MSC_VER
|
||||
std::list<TextureCacheMap::iterator>::iterator lru_location;
|
||||
#else
|
||||
std::list<int>::iterator lru_location;
|
||||
#endif
|
||||
std::list<struct TextureCacheMapIter>::iterator lru_location;
|
||||
};
|
||||
|
||||
struct TextureCacheMapIter {
|
||||
TextureCacheMap::iterator it;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
|
|
@ -40,8 +40,11 @@ namespace Ship
|
|||
|
||||
for (size_t i = 0; i < patches.size(); i++)
|
||||
{
|
||||
std::string hashStr = resMgr->HashToString(patches[i].crc);
|
||||
auto resShared = resMgr->GetCachedFile(hashStr);
|
||||
const std::string* hashStr = resMgr->HashToString(patches[i].crc);
|
||||
if (hashStr == nullptr)
|
||||
continue;
|
||||
|
||||
auto resShared = resMgr->GetCachedFile(hashStr->c_str());
|
||||
if (resShared != nullptr)
|
||||
{
|
||||
auto res = (Ship::DisplayList*)resShared.get();
|
||||
|
|
|
@ -215,7 +215,7 @@ namespace Ship {
|
|||
return ToLoad;
|
||||
}
|
||||
|
||||
std::shared_ptr<Ship::Resource> ResourceMgr::GetCachedFile(std::string FilePath) {
|
||||
std::shared_ptr<Ship::Resource> ResourceMgr::GetCachedFile(const char* FilePath) const {
|
||||
auto resCacheFind = ResourceCache.find(FilePath);
|
||||
|
||||
if (resCacheFind != ResourceCache.end() &&
|
||||
|
@ -227,8 +227,13 @@ namespace Ship {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Resource> ResourceMgr::LoadResource(std::string FilePath) {
|
||||
auto Promise = LoadResourceAsync(FilePath);
|
||||
std::shared_ptr<Resource> ResourceMgr::LoadResource(const char* FilePath) {
|
||||
auto Res = LoadResourceAsync(FilePath);
|
||||
|
||||
if (std::holds_alternative<std::shared_ptr<Resource>>(Res))
|
||||
return std::get<std::shared_ptr<Resource>>(Res);
|
||||
|
||||
auto& Promise = std::get<std::shared_ptr<ResourcePromise>>(Res);
|
||||
|
||||
if (!Promise->bHasResourceLoaded)
|
||||
{
|
||||
|
@ -241,21 +246,18 @@ namespace Ship {
|
|||
return Promise->resource;
|
||||
}
|
||||
|
||||
std::shared_ptr<ResourcePromise> ResourceMgr::LoadResourceAsync(std::string FilePath) {
|
||||
StringHelper::ReplaceOriginal(FilePath, "\\", "/");
|
||||
|
||||
if (StringHelper::StartsWith(FilePath, "__OTR__"))
|
||||
FilePath = StringHelper::Split(FilePath, "__OTR__")[1];
|
||||
|
||||
std::shared_ptr<ResourcePromise> Promise = std::make_shared<ResourcePromise>();
|
||||
std::variant<std::shared_ptr<Resource>, std::shared_ptr<ResourcePromise>> ResourceMgr::LoadResourceAsync(const char* FilePath) {
|
||||
if (FilePath[0] == '_' && FilePath[1] == '_' && FilePath[2] == 'O' && FilePath[3] == 'T' && FilePath[4] == 'R' && FilePath[5] == '_' && FilePath[6] == '_')
|
||||
FilePath += 7;
|
||||
|
||||
const std::lock_guard<std::mutex> ResLock(ResourceLoadMutex);
|
||||
auto resCacheFind = ResourceCache.find(FilePath);
|
||||
if (resCacheFind == ResourceCache.end() || resCacheFind->second->isDirty/* || !FileData->bIsLoaded*/) {
|
||||
if (resCacheFind == ResourceCache.end()) {
|
||||
SPDLOG_TRACE("Cache miss on Resource load: {}", FilePath.c_str());
|
||||
SPDLOG_TRACE("Cache miss on Resource load: {}", FilePath);
|
||||
}
|
||||
|
||||
std::shared_ptr<ResourcePromise> Promise = std::make_shared<ResourcePromise>();
|
||||
std::shared_ptr<File> FileData = LoadFile(FilePath);
|
||||
Promise->file = FileData;
|
||||
|
||||
|
@ -269,12 +271,13 @@ namespace Ship {
|
|||
ResourceLoadQueue.push(Promise);
|
||||
ResourceLoadNotifier.notify_all();
|
||||
}
|
||||
} else {
|
||||
Promise->bHasResourceLoaded = true;
|
||||
Promise->resource = resCacheFind->second;
|
||||
}
|
||||
|
||||
return Promise;
|
||||
return Promise;
|
||||
}
|
||||
else
|
||||
{
|
||||
return resCacheFind->second;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::shared_ptr<ResourcePromise>>> ResourceMgr::CacheDirectoryAsync(std::string SearchMask) {
|
||||
|
@ -282,10 +285,15 @@ namespace Ship {
|
|||
auto fileList = OTR->ListFiles(SearchMask);
|
||||
|
||||
for (DWORD i = 0; i < fileList.size(); i++) {
|
||||
auto file = LoadResourceAsync(fileList.operator[](i).cFileName);
|
||||
if (file != nullptr) {
|
||||
loadedList->push_back(file);
|
||||
auto resource = LoadResourceAsync(fileList.operator[](i).cFileName);
|
||||
if (std::holds_alternative<std::shared_ptr<Resource>>(resource))
|
||||
{
|
||||
auto promise = std::make_shared<ResourcePromise>();
|
||||
promise->bHasResourceLoaded = true;
|
||||
promise->resource = std::get<std::shared_ptr<Resource>>(resource);
|
||||
resource = promise;
|
||||
}
|
||||
loadedList->push_back(std::get<std::shared_ptr<ResourcePromise>>(resource));
|
||||
}
|
||||
|
||||
return loadedList;
|
||||
|
@ -335,7 +343,7 @@ namespace Ship {
|
|||
ResourceCache.clear();
|
||||
}
|
||||
|
||||
std::string ResourceMgr::HashToString(uint64_t Hash) {
|
||||
const std::string* ResourceMgr::HashToString(uint64_t Hash) const {
|
||||
return OTR->HashToString(Hash);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
#include <string>
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
#include <variant>
|
||||
#include "Resource.h"
|
||||
#include "GlobalCtx2.h"
|
||||
|
||||
|
@ -25,7 +26,7 @@ namespace Ship
|
|||
std::shared_ptr<Archive> GetArchive() { return OTR; }
|
||||
std::shared_ptr<GlobalCtx2> GetContext() { return Context.lock(); }
|
||||
|
||||
std::string HashToString(uint64_t Hash);
|
||||
const std::string* HashToString(uint64_t Hash) const;
|
||||
|
||||
void InvalidateResourceCache();
|
||||
|
||||
|
@ -33,9 +34,10 @@ namespace Ship
|
|||
void SetGameVersion(uint32_t newGameVersion);
|
||||
std::shared_ptr<File> LoadFileAsync(std::string FilePath);
|
||||
std::shared_ptr<File> LoadFile(std::string FilePath);
|
||||
std::shared_ptr<Ship::Resource> GetCachedFile(std::string FilePath);
|
||||
std::shared_ptr<Resource> LoadResource(std::string FilePath);
|
||||
std::shared_ptr<ResourcePromise> LoadResourceAsync(std::string FilePath);
|
||||
std::shared_ptr<Ship::Resource> GetCachedFile(const char* FilePath) const;
|
||||
std::shared_ptr<Resource> LoadResource(const char* FilePath);
|
||||
std::shared_ptr<Resource> LoadResource(const std::string& FilePath) { return LoadResource(FilePath.c_str()); }
|
||||
std::variant<std::shared_ptr<Resource>, std::shared_ptr<ResourcePromise>> LoadResourceAsync(const char* FilePath);
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Resource>>> CacheDirectory(std::string SearchMask);
|
||||
std::shared_ptr<std::vector<std::shared_ptr<ResourcePromise>>> CacheDirectoryAsync(std::string SearchMask);
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Resource>>> DirtyDirectory(std::string SearchMask);
|
||||
|
@ -50,7 +52,7 @@ namespace Ship
|
|||
std::weak_ptr<GlobalCtx2> Context;
|
||||
volatile bool bIsRunning;
|
||||
std::map<std::string, std::shared_ptr<File>> FileCache;
|
||||
std::map<std::string, std::shared_ptr<Resource>> ResourceCache;
|
||||
std::map<std::string, std::shared_ptr<Resource>, std::less<>> ResourceCache;
|
||||
std::queue<std::shared_ptr<File>> FileLoadQueue;
|
||||
std::queue<std::shared_ptr<ResourcePromise>> ResourceLoadQueue;
|
||||
std::shared_ptr<Archive> OTR;
|
||||
|
|
|
@ -407,7 +407,7 @@ namespace SohImGui {
|
|||
|
||||
ModInternal::registerHookListener({ CONTROLLER_READ, [](const HookEvent ev) {
|
||||
pads = static_cast<OSContPad*>(ev->baseArgs["cont_pad"]);
|
||||
}});
|
||||
} });
|
||||
Game::InitSettings();
|
||||
}
|
||||
|
||||
|
@ -446,7 +446,7 @@ namespace SohImGui {
|
|||
EnhancementRadioButton("French", "gLanguages", 2);
|
||||
*/
|
||||
int val = CVar_GetS32(cvarName.c_str(), 0);
|
||||
if (ImGui::RadioButton(text.c_str(), id==val)) {
|
||||
if (ImGui::RadioButton(text.c_str(), id == val)) {
|
||||
CVar_SetS32(cvarName.c_str(), (int)id);
|
||||
needs_save = true;
|
||||
}
|
||||
|
@ -546,14 +546,14 @@ namespace SohImGui {
|
|||
}
|
||||
}
|
||||
|
||||
void Tooltip(std::string text){
|
||||
if (ImGui::IsItemHovered()) {
|
||||
|
||||
void Tooltip(std::string text) {
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("%s", text.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void DrawMainMenuAndCalculateGameSize() {
|
||||
|
||||
console->Update();
|
||||
ImGuiBackendNewFrame();
|
||||
ImGuiWMNewFrame();
|
||||
|
@ -685,7 +685,7 @@ namespace SohImGui {
|
|||
INFO("New Filter: %s", filters[fId]);
|
||||
gapi->set_texture_filter((FilteringMode)fId);
|
||||
|
||||
CVar_SetS32("gTextureFilter", (int) fId);
|
||||
CVar_SetS32("gTextureFilter", (int)fId);
|
||||
needs_save = true;
|
||||
}
|
||||
|
||||
|
@ -705,47 +705,57 @@ namespace SohImGui {
|
|||
|
||||
if (ImGui::BeginMenu("Enhancements"))
|
||||
{
|
||||
ImGui::Text("Gameplay");
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginMenu("Gameplay"))
|
||||
{
|
||||
EnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "");
|
||||
EnhancementSliderInt("King Zora Speed: %dx", "##WEEPSPEED", "gMweepSpeed", 1, 5, "");
|
||||
|
||||
EnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "");
|
||||
EnhancementSliderInt("King Zora Speed: %dx", "##WEEPSPEED", "gMweepSpeed", 1, 5, "");
|
||||
EnhancementCheckbox("Skip Text", "gSkipText");
|
||||
Tooltip("Holding down B skips text");
|
||||
EnhancementCheckbox("Mute Low HP Alarm", "gLowHpAlarm");
|
||||
Tooltip("Disable the low HP beeping sound");
|
||||
EnhancementCheckbox("Minimal UI", "gMinimalUI");
|
||||
Tooltip("Hides most of the UI when not needed");
|
||||
EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony");
|
||||
Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble");
|
||||
EnhancementCheckbox("Faster Block Push", "gFasterBlockPush");
|
||||
EnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots");
|
||||
Tooltip("Allows equiping the tunic and boots to c-buttons");
|
||||
EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood");
|
||||
Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask");
|
||||
|
||||
EnhancementCheckbox("Skip Text", "gSkipText");
|
||||
Tooltip("Holding down B skips text");
|
||||
EnhancementCheckbox("Minimal UI", "gMinimalUI");
|
||||
Tooltip("Hides most of the UI when not needed");
|
||||
EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood");
|
||||
Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask");
|
||||
EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony");
|
||||
Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble");
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::Text("Graphics");
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginMenu("Graphics"))
|
||||
{
|
||||
EnhancementCheckbox("N64 Mode", "gN64Mode");
|
||||
Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution");
|
||||
EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink");
|
||||
EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops");
|
||||
EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon");
|
||||
Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have");
|
||||
EnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon");
|
||||
Tooltip("Always shows dungeon entrance icons on the minimap");
|
||||
|
||||
EnhancementCheckbox("N64 Mode", "gN64Mode");
|
||||
Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution");
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink");
|
||||
EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops");
|
||||
EnhancementCheckbox("Faster Block Push", "gFasterBlockPush");
|
||||
EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon");
|
||||
Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have");
|
||||
EnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon");
|
||||
Tooltip("Always shows dungeon entrance icons on the minimap");
|
||||
if (ImGui::BeginMenu("Fixes"))
|
||||
{
|
||||
EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR");
|
||||
Tooltip("Makes the L and R buttons in the pause menu the same color");
|
||||
EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon");
|
||||
Tooltip("Show dungeon entrances icon only when it should be");
|
||||
EnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle");
|
||||
Tooltip("Makes two handed idle animation play, a seemingly finished animation that was disabled on accident in the original game");
|
||||
|
||||
ImGui::Text("Fixes");
|
||||
ImGui::Separator();
|
||||
EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR");
|
||||
Tooltip("Makes the L and R buttons in the pause menu the same color");
|
||||
EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon");
|
||||
Tooltip("Show dungeon entrances icon only when it should be");
|
||||
EnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle");
|
||||
Tooltip("Makes two handed idle animation play, a seemingly finished animation that was disabled on accident in the original game");
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
EXPERIMENTAL();
|
||||
|
||||
EnhancementCheckbox("60 fps interpolation", "g60FPS");
|
||||
EnhancementCheckbox("60FPS Interpolation", "g60FPS");
|
||||
EnhancementCheckbox("Disable LOD", "gDisableLOD");
|
||||
Tooltip("Turns off the level of detail setting, making models always use their higher poly variants");
|
||||
|
||||
|
@ -792,7 +802,7 @@ namespace SohImGui {
|
|||
EnhancementCheckbox("Easy ISG", "gEzISG");
|
||||
Tooltip("Automatically activates the Infinite Sword glitch, making you constantly swing your sword");
|
||||
EnhancementCheckbox("Unrestricted Items", "gNoRestrictItems");
|
||||
Tooltip("Allows you to use all items at any age");
|
||||
Tooltip("Allows you to use any item at any location");
|
||||
EnhancementCheckbox("Freeze Time", "gFreezeTime");
|
||||
Tooltip("Freezes the time of day");
|
||||
|
||||
|
@ -937,7 +947,7 @@ namespace SohImGui {
|
|||
if (ImGui::BeginMenu(category.first.c_str())) {
|
||||
for (const std::string& name : category.second) {
|
||||
std::string varName(name);
|
||||
varName.erase(std::ranges::remove_if(varName, isspace).begin(), varName.end());
|
||||
varName.erase(std::ranges::remove_if(varName, isspace).begin(), varName.end());
|
||||
std::string toggleName = "g" + varName + "Enabled";
|
||||
|
||||
EnhancementCheckbox(name, toggleName);
|
||||
|
|
|
@ -119,17 +119,16 @@ extern "C" {
|
|||
ModInternal::callBindHook(0);
|
||||
}
|
||||
|
||||
char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc) {
|
||||
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
|
||||
strcpy(alloc, hashStr.c_str());
|
||||
return (char*)hashStr.c_str();
|
||||
const char* ResourceMgr_GetNameByCRC(uint64_t crc) {
|
||||
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
|
||||
return hashStr != nullptr ? hashStr->c_str() : nullptr;
|
||||
}
|
||||
|
||||
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc) {
|
||||
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
|
||||
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
|
||||
|
||||
if (hashStr != "") {
|
||||
auto res = std::static_pointer_cast<Ship::Array>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr));
|
||||
if (hashStr != nullptr) {
|
||||
auto res = std::static_pointer_cast<Ship::Array>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
|
||||
|
||||
//if (res != nullptr)
|
||||
return (Vtx*)res->vertices.data();
|
||||
|
@ -142,10 +141,10 @@ extern "C" {
|
|||
}
|
||||
|
||||
int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc) {
|
||||
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
|
||||
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
|
||||
|
||||
if (hashStr != "") {
|
||||
auto res = std::static_pointer_cast<Ship::Matrix>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr));
|
||||
if (hashStr != nullptr) {
|
||||
auto res = std::static_pointer_cast<Ship::Matrix>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
|
||||
return (int32_t*)res->mtx.data();
|
||||
} else {
|
||||
return nullptr;
|
||||
|
@ -153,10 +152,10 @@ extern "C" {
|
|||
}
|
||||
|
||||
Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc) {
|
||||
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
|
||||
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
|
||||
|
||||
if (hashStr != "") {
|
||||
auto res = std::static_pointer_cast<Ship::DisplayList>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr));
|
||||
if (hashStr != nullptr) {
|
||||
auto res = std::static_pointer_cast<Ship::DisplayList>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
|
||||
return (Gfx*)&res->instructions[0];
|
||||
} else {
|
||||
return nullptr;
|
||||
|
@ -164,14 +163,14 @@ extern "C" {
|
|||
}
|
||||
|
||||
char* ResourceMgr_LoadTexByCRC(uint64_t crc) {
|
||||
const std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
|
||||
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
|
||||
|
||||
if (!hashStr.empty()) {
|
||||
const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get());
|
||||
if (hashStr != nullptr) {
|
||||
const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get());
|
||||
|
||||
ModInternal::bindHook(LOAD_TEXTURE);
|
||||
ModInternal::initBindHook(2,
|
||||
HookParameter({.name = "path", .parameter = (void*)hashStr.c_str() }),
|
||||
HookParameter({.name = "path", .parameter = (void*)hashStr->c_str() }),
|
||||
HookParameter({.name = "texture", .parameter = static_cast<void*>(&res->imageData) })
|
||||
);
|
||||
ModInternal::callBindHook(0);
|
||||
|
@ -184,11 +183,11 @@ extern "C" {
|
|||
|
||||
void ResourceMgr_RegisterResourcePatch(uint64_t hash, uint32_t instrIndex, uintptr_t origData)
|
||||
{
|
||||
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash);
|
||||
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash);
|
||||
|
||||
if (hashStr != "")
|
||||
if (hashStr != nullptr)
|
||||
{
|
||||
auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get();
|
||||
auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get();
|
||||
|
||||
Ship::Patch patch;
|
||||
patch.crc = hash;
|
||||
|
|
|
@ -78,6 +78,12 @@ typedef enum {
|
|||
/* 0x15 */ SLOT_BOTTLE_4,
|
||||
/* 0x16 */ SLOT_TRADE_ADULT,
|
||||
/* 0x17 */ SLOT_TRADE_CHILD,
|
||||
/* 0x18 */ SLOT_TUNIC_KOKIRI,
|
||||
/* 0x19 */ SLOT_TUNIC_GORON,
|
||||
/* 0x1A */ SLOT_TUNIC_ZORA,
|
||||
/* 0x1B */ SLOT_BOOTS_KOKIRI,
|
||||
/* 0x1C */ SLOT_BOOTS_IRON,
|
||||
/* 0x1D */ SLOT_BOOTS_HOVER,
|
||||
/* 0xFF */ SLOT_NONE = 0xFF
|
||||
} InventorySlot;
|
||||
|
||||
|
|
|
@ -128,7 +128,16 @@ typedef enum {
|
|||
/* 0x40 */ PLAYER_AP_MASK_GERUDO,
|
||||
/* 0x41 */ PLAYER_AP_MASK_TRUTH,
|
||||
/* 0x42 */ PLAYER_AP_LENS,
|
||||
/* 0x43 */ PLAYER_AP_MAX
|
||||
/* 0x43 */ PLAYER_AP_SHIELD_DEKU,
|
||||
/* 0x44 */ PLAYER_AP_SHIELD_HYLIAN,
|
||||
/* 0x45 */ PLAYER_AP_SHIELD_MIRROR,
|
||||
/* 0x46 */ PLAYER_AP_TUNIC_KOKIRI,
|
||||
/* 0x47 */ PLAYER_AP_TUNIC_GORON,
|
||||
/* 0x48 */ PLAYER_AP_TUNIC_ZORA,
|
||||
/* 0x49 */ PLAYER_AP_BOOTS_KOKIRI,
|
||||
/* 0x4A */ PLAYER_AP_BOOTS_IRON,
|
||||
/* 0x4B */ PLAYER_AP_BOOTS_HOVER,
|
||||
/* 0x4C */ PLAYER_AP_MAX
|
||||
} PlayerActionParam;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -478,7 +478,10 @@ static void RunFrame()
|
|||
|
||||
Graph_StartFrame();
|
||||
|
||||
PadMgr_ThreadEntry(&gPadMgr);
|
||||
// TODO: Workaround for rumble being too long. Implement os thread functions.
|
||||
for (int i = 0; i < 3; i++) {
|
||||
PadMgr_ThreadEntry(&gPadMgr);
|
||||
}
|
||||
|
||||
Graph_Update(&runFrameContext.gfxCtx, runFrameContext.gameState);
|
||||
ticksB = GetPerfCounter();
|
||||
|
|
|
@ -588,8 +588,8 @@ void HealthMeter_HandleCriticalAlarm(GlobalContext* globalCtx) {
|
|||
if (interfaceCtx->unk_22A <= 0) {
|
||||
interfaceCtx->unk_22A = 0;
|
||||
interfaceCtx->unk_22C = 0;
|
||||
if (!Player_InCsMode(globalCtx) && (globalCtx->pauseCtx.state == 0) &&
|
||||
(globalCtx->pauseCtx.debugState == 0) && HealthMeter_IsCritical() && !Gameplay_InCsMode(globalCtx)) {
|
||||
if (CVar_GetS32("gLowHpAlarm", 0) == 0 && !Player_InCsMode(globalCtx) && (globalCtx->pauseCtx.state == 0) &&
|
||||
(globalCtx->pauseCtx.debugState == 0) && HealthMeter_IsCritical() && !Gameplay_InCsMode(globalCtx)) {
|
||||
func_80078884(NA_SE_SY_HITPOINT_ALARM);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -758,7 +758,15 @@ void func_80083108(GlobalContext* globalCtx) {
|
|||
gSaveContext.buttonStatus[0] = BTN_DISABLED;
|
||||
|
||||
for (i = 1; i < 4; i++) {
|
||||
if (func_8008F2F8(globalCtx) == 2) {
|
||||
if ((gSaveContext.equips.buttonItems[i] >= ITEM_SHIELD_DEKU) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_BOOTS_HOVER)) {
|
||||
// Equipment on c-buttons is always enabled
|
||||
if (gSaveContext.buttonStatus[i] == BTN_DISABLED) {
|
||||
sp28 = 1;
|
||||
}
|
||||
|
||||
gSaveContext.buttonStatus[i] = BTN_ENABLED;
|
||||
} else if (func_8008F2F8(globalCtx) == 2) {
|
||||
if ((gSaveContext.equips.buttonItems[i] != ITEM_HOOKSHOT) &&
|
||||
(gSaveContext.equips.buttonItems[i] != ITEM_LONGSHOT)) {
|
||||
if (gSaveContext.buttonStatus[i] == BTN_ENABLED) {
|
||||
|
|
|
@ -29,7 +29,8 @@ s16 sBootData[PLAYER_BOOTS_MAX][17] = {
|
|||
// Used to map action params to model groups
|
||||
u8 sActionModelGroups[] = {
|
||||
3, 15, 10, 2, 2, 5, 10, 11, 6, 6, 6, 6, 6, 6, 6, 6, 9, 9, 7, 7, 8, 3, 3, 6, 3, 3, 3, 3, 12, 13, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3
|
||||
};
|
||||
|
||||
TextTriggerEntry sTextTriggers[] = {
|
||||
|
|
|
@ -427,7 +427,8 @@ void EnFloormas_SetupFreeze(EnFloormas* this) {
|
|||
}
|
||||
|
||||
void EnFloormas_Die(EnFloormas* this, GlobalContext* globalCtx) {
|
||||
if (this->actor.scale.x > 0.004f) {
|
||||
//Originally was doing > 0.004f, better fix thanks Gary :D
|
||||
if (this->actor.scale.x > (f32)0.004f) {
|
||||
// split
|
||||
this->actor.shape.rot.y = this->actor.yawTowardsPlayer + 0x8000;
|
||||
EnFloormas_SetupSplit((EnFloormas*)this->actor.child);
|
||||
|
|
|
@ -898,6 +898,15 @@ static s8 sItemActionParams[] = {
|
|||
PLAYER_AP_SWORD_KOKIRI,
|
||||
PLAYER_AP_SWORD_MASTER,
|
||||
PLAYER_AP_SWORD_BGS,
|
||||
PLAYER_AP_SHIELD_DEKU,
|
||||
PLAYER_AP_SHIELD_HYLIAN,
|
||||
PLAYER_AP_SHIELD_MIRROR,
|
||||
PLAYER_AP_TUNIC_KOKIRI,
|
||||
PLAYER_AP_TUNIC_GORON,
|
||||
PLAYER_AP_TUNIC_ZORA,
|
||||
PLAYER_AP_BOOTS_KOKIRI,
|
||||
PLAYER_AP_BOOTS_IRON,
|
||||
PLAYER_AP_BOOTS_HOVER,
|
||||
};
|
||||
|
||||
static s32(*D_80853EDC[])(Player* this, GlobalContext* globalCtx) = {
|
||||
|
@ -910,7 +919,8 @@ static s32(*D_80853EDC[])(Player* this, GlobalContext* globalCtx) = {
|
|||
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
|
||||
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
|
||||
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
|
||||
func_8083485C, func_8083485C, func_8083485C, func_8083485C,
|
||||
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
|
||||
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
|
||||
};
|
||||
|
||||
static void (*D_80853FE8[])(GlobalContext* globalCtx, Player* this) = {
|
||||
|
@ -923,7 +933,8 @@ static void (*D_80853FE8[])(GlobalContext* globalCtx, Player* this) = {
|
|||
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
|
||||
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
|
||||
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
|
||||
func_80833770, func_80833770, func_80833770, func_80833770,
|
||||
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
|
||||
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -2752,7 +2763,8 @@ void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item) {
|
|||
|
||||
if ((actionParam == PLAYER_AP_NONE) || !(this->stateFlags1 & PLAYER_STATE1_27) ||
|
||||
((this->actor.bgCheckFlags & 1) &&
|
||||
((actionParam == PLAYER_AP_HOOKSHOT) || (actionParam == PLAYER_AP_LONGSHOT)))) {
|
||||
((actionParam == PLAYER_AP_HOOKSHOT) || (actionParam == PLAYER_AP_LONGSHOT))) ||
|
||||
((actionParam >= PLAYER_AP_SHIELD_DEKU) && (actionParam <= PLAYER_AP_BOOTS_HOVER))) {
|
||||
|
||||
if ((globalCtx->bombchuBowlingStatus == 0) &&
|
||||
(((actionParam == PLAYER_AP_STICK) && (AMMO(ITEM_STICK) == 0)) ||
|
||||
|
@ -2764,6 +2776,33 @@ void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (actionParam >= PLAYER_AP_BOOTS_KOKIRI) {
|
||||
u16 bootsValue = actionParam - PLAYER_AP_BOOTS_KOKIRI + 1;
|
||||
if (CUR_EQUIP_VALUE(EQUIP_BOOTS) == bootsValue) {
|
||||
Inventory_ChangeEquipment(EQUIP_BOOTS, 1);
|
||||
} else {
|
||||
Inventory_ChangeEquipment(EQUIP_BOOTS, bootsValue);
|
||||
}
|
||||
Player_SetEquipmentData(globalCtx, this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionParam >= PLAYER_AP_TUNIC_KOKIRI) {
|
||||
u16 tunicValue = actionParam - PLAYER_AP_TUNIC_KOKIRI + 1;
|
||||
if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == tunicValue) {
|
||||
Inventory_ChangeEquipment(EQUIP_TUNIC, 1);
|
||||
} else {
|
||||
Inventory_ChangeEquipment(EQUIP_TUNIC, tunicValue);
|
||||
}
|
||||
Player_SetEquipmentData(globalCtx, this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionParam >= PLAYER_AP_SHIELD_DEKU) {
|
||||
// Changing shields through action commands is unimplemented
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionParam == PLAYER_AP_LENS) {
|
||||
if (func_80087708(globalCtx, 0, 3)) {
|
||||
if (globalCtx->actorCtx.unk_03 != 0) {
|
||||
|
|
|
@ -471,39 +471,76 @@ void KaleidoScope_DrawEquipment(GlobalContext* globalCtx) {
|
|||
KaleidoScope_SetCursorVtx(pauseCtx, cursorSlot * 4, pauseCtx->equipVtx);
|
||||
|
||||
if ((pauseCtx->cursorSpecialPos == 0) && (cursorItem != PAUSE_ITEM_NONE) && (pauseCtx->state == 6) &&
|
||||
(pauseCtx->unk_1E4 == 0) && CHECK_BTN_ALL(input->press.button, BTN_A) &&
|
||||
(pauseCtx->unk_1E4 == 0) &&
|
||||
CHECK_BTN_ANY(input->press.button, BTN_A | BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT) &&
|
||||
(pauseCtx->cursorX[PAUSE_EQUIP] != 0)) {
|
||||
|
||||
if ((gEquipAgeReqs[pauseCtx->cursorY[PAUSE_EQUIP]][pauseCtx->cursorX[PAUSE_EQUIP]] == 9) ||
|
||||
(gEquipAgeReqs[pauseCtx->cursorY[PAUSE_EQUIP]][pauseCtx->cursorX[PAUSE_EQUIP]] ==
|
||||
((void)0, gSaveContext.linkAge))) {
|
||||
Inventory_ChangeEquipment(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP]);
|
||||
if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
|
||||
Inventory_ChangeEquipment(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP]);
|
||||
|
||||
if (pauseCtx->cursorY[PAUSE_EQUIP] == 0) {
|
||||
gSaveContext.infTable[29] = 0;
|
||||
gSaveContext.equips.buttonItems[0] = cursorItem;
|
||||
if (pauseCtx->cursorY[PAUSE_EQUIP] == 0) {
|
||||
gSaveContext.infTable[29] = 0;
|
||||
gSaveContext.equips.buttonItems[0] = cursorItem;
|
||||
|
||||
if ((pauseCtx->cursorX[PAUSE_EQUIP] == 3) && (gSaveContext.bgsFlag != 0)) {
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
|
||||
gSaveContext.swordHealth = 8;
|
||||
} else {
|
||||
if (gSaveContext.equips.buttonItems[0] == ITEM_HEART_PIECE_2) {
|
||||
if ((pauseCtx->cursorX[PAUSE_EQUIP] == 3) && (gSaveContext.bgsFlag != 0)) {
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
|
||||
gSaveContext.swordHealth = 8;
|
||||
} else {
|
||||
if (gSaveContext.equips.buttonItems[0] == ITEM_HEART_PIECE_2) {
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
|
||||
}
|
||||
if ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS) && (gSaveContext.bgsFlag == 0) &&
|
||||
(gBitFlags[3] & gSaveContext.inventory.equipment)) {
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE;
|
||||
}
|
||||
}
|
||||
if ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS) && (gSaveContext.bgsFlag == 0) &&
|
||||
(gBitFlags[3] & gSaveContext.inventory.equipment)) {
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE;
|
||||
}
|
||||
|
||||
Interface_LoadItemIcon1(globalCtx, 0);
|
||||
}
|
||||
|
||||
Interface_LoadItemIcon1(globalCtx, 0);
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
pauseCtx->unk_1E4 = 7;
|
||||
sEquipTimer = 10;
|
||||
} else if (CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) {
|
||||
// Only allow assigning tunic and boots to c-buttons
|
||||
if (pauseCtx->cursorY[PAUSE_EQUIP] > 1) {
|
||||
u16 slot = 0;
|
||||
switch (cursorItem) {
|
||||
case ITEM_TUNIC_KOKIRI:
|
||||
slot = SLOT_TUNIC_KOKIRI;
|
||||
break;
|
||||
case ITEM_TUNIC_GORON:
|
||||
slot = SLOT_TUNIC_GORON;
|
||||
break;
|
||||
case ITEM_TUNIC_ZORA:
|
||||
slot = SLOT_TUNIC_ZORA;
|
||||
break;
|
||||
case ITEM_BOOTS_KOKIRI:
|
||||
slot = SLOT_BOOTS_KOKIRI;
|
||||
break;
|
||||
case ITEM_BOOTS_IRON:
|
||||
slot = SLOT_BOOTS_IRON;
|
||||
break;
|
||||
case ITEM_BOOTS_HOVER:
|
||||
slot = SLOT_BOOTS_HOVER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
KaleidoScope_SetupItemEquip(globalCtx, cursorItem, slot,
|
||||
pauseCtx->equipVtx[cursorSlot * 4].v.ob[0] * 10,
|
||||
pauseCtx->equipVtx[cursorSlot * 4].v.ob[1] * 10);
|
||||
}
|
||||
}
|
||||
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
pauseCtx->unk_1E4 = 7;
|
||||
sEquipTimer = 10;
|
||||
} else {
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
} else if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (pauseCtx->cursorY[PAUSE_EQUIP] > 1)) {
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -351,43 +351,9 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
|
|||
if (((gSlotAgeReqs[cursorSlot] == 9) ||
|
||||
(gSlotAgeReqs[cursorSlot] == ((void)0, gSaveContext.linkAge))) &&
|
||||
(cursorItem != ITEM_SOLD_OUT)) {
|
||||
if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) {
|
||||
pauseCtx->equipTargetCBtn = 0;
|
||||
} else if (CHECK_BTN_ALL(input->press.button, BTN_CDOWN)) {
|
||||
pauseCtx->equipTargetCBtn = 1;
|
||||
} else if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) {
|
||||
pauseCtx->equipTargetCBtn = 2;
|
||||
}
|
||||
|
||||
pauseCtx->equipTargetItem = cursorItem;
|
||||
pauseCtx->equipTargetSlot = cursorSlot;
|
||||
pauseCtx->unk_1E4 = 3;
|
||||
pauseCtx->equipAnimX = pauseCtx->itemVtx[index].v.ob[0] * 10;
|
||||
pauseCtx->equipAnimY = pauseCtx->itemVtx[index].v.ob[1] * 10;
|
||||
pauseCtx->equipAnimAlpha = 255;
|
||||
sEquipAnimTimer = 0;
|
||||
sEquipState = 3;
|
||||
sEquipMoveTimer = 10;
|
||||
if ((pauseCtx->equipTargetItem == ITEM_ARROW_FIRE) ||
|
||||
(pauseCtx->equipTargetItem == ITEM_ARROW_ICE) ||
|
||||
(pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT)) {
|
||||
index = 0;
|
||||
if (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) {
|
||||
index = 1;
|
||||
}
|
||||
if (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) {
|
||||
index = 2;
|
||||
}
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW + index, &D_801333D4, 4, &D_801333E0,
|
||||
&D_801333E0, &D_801333E8);
|
||||
pauseCtx->equipTargetItem = 0xBF + index;
|
||||
sEquipState = 0;
|
||||
pauseCtx->equipAnimAlpha = 0;
|
||||
sEquipMoveTimer = 6;
|
||||
} else {
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0,
|
||||
&D_801333E8);
|
||||
}
|
||||
KaleidoScope_SetupItemEquip(globalCtx, cursorItem, cursorSlot,
|
||||
pauseCtx->itemVtx[index].v.ob[0] * 10,
|
||||
pauseCtx->itemVtx[index].v.ob[1] * 10);
|
||||
} else {
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
|
||||
&D_801333E8);
|
||||
|
@ -419,7 +385,9 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
|
|||
gDPSetEnvColor(POLY_KAL_DISP++, 0, 0, 0, 0);
|
||||
|
||||
for (i = 0, j = 24 * 4; i < 3; i++, j += 4) {
|
||||
if (gSaveContext.equips.buttonItems[i + 1] != ITEM_NONE) {
|
||||
if ((gSaveContext.equips.buttonItems[i + 1] != ITEM_NONE) &&
|
||||
!((gSaveContext.equips.buttonItems[i + 1] >= ITEM_SHIELD_DEKU) &&
|
||||
(gSaveContext.equips.buttonItems[i + 1] <= ITEM_BOOTS_HOVER))) {
|
||||
gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[j], 4, 0);
|
||||
POLY_KAL_DISP = KaleidoScope_QuadTextureIA8(POLY_KAL_DISP, gEquippedItemOutlineTex, 32, 32, 0);
|
||||
}
|
||||
|
@ -496,6 +464,46 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
|
|||
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kaleido_item.c", 516);
|
||||
}
|
||||
|
||||
void KaleidoScope_SetupItemEquip(GlobalContext* globalCtx, u16 item, u16 slot, s16 animX, s16 animY) {
|
||||
Input* input = &globalCtx->state.input[0];
|
||||
PauseContext* pauseCtx = &globalCtx->pauseCtx;
|
||||
|
||||
if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) {
|
||||
pauseCtx->equipTargetCBtn = 0;
|
||||
} else if (CHECK_BTN_ALL(input->press.button, BTN_CDOWN)) {
|
||||
pauseCtx->equipTargetCBtn = 1;
|
||||
} else if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) {
|
||||
pauseCtx->equipTargetCBtn = 2;
|
||||
}
|
||||
|
||||
pauseCtx->equipTargetItem = item;
|
||||
pauseCtx->equipTargetSlot = slot;
|
||||
pauseCtx->unk_1E4 = 3;
|
||||
pauseCtx->equipAnimX = animX;
|
||||
pauseCtx->equipAnimY = animY;
|
||||
pauseCtx->equipAnimAlpha = 255;
|
||||
sEquipAnimTimer = 0;
|
||||
sEquipState = 3;
|
||||
sEquipMoveTimer = 10;
|
||||
if ((pauseCtx->equipTargetItem == ITEM_ARROW_FIRE) || (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) ||
|
||||
(pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT)) {
|
||||
u16 index = 0;
|
||||
if (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) {
|
||||
index = 1;
|
||||
}
|
||||
if (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) {
|
||||
index = 2;
|
||||
}
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW + index, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
pauseCtx->equipTargetItem = 0xBF + index;
|
||||
sEquipState = 0;
|
||||
pauseCtx->equipAnimAlpha = 0;
|
||||
sEquipMoveTimer = 6;
|
||||
} else {
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
}
|
||||
}
|
||||
|
||||
static s16 sCButtonPosX[] = { 66, 90, 114 };
|
||||
static s16 sCButtonPosY[] = { 110, 92, 110 };
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx);
|
|||
void KaleidoScope_DrawEquipment(GlobalContext* globalCtx);
|
||||
void KaleidoScope_SetCursorVtx(PauseContext* pauseCtx, u16 index, Vtx* vtx);
|
||||
void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx);
|
||||
void KaleidoScope_SetupItemEquip(GlobalContext* globalCtx, u16 item, u16 slot, s16 animX, s16 animY);
|
||||
void KaleidoScope_UpdateItemEquip(GlobalContext* globalCtx);
|
||||
void KaleidoScope_DrawDungeonMap(GlobalContext* globalCtx, GraphicsContext* gfxCtx);
|
||||
void KaleidoScope_DrawWorldMap(GlobalContext* globalCtx, GraphicsContext* gfxCtx);
|
||||
|
|
|
@ -916,6 +916,13 @@ void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 pt) {
|
|||
gSaveContext.buttonStatus[3] = D_8082AB6C[pauseCtx->pageIndex + pt][3];
|
||||
gSaveContext.buttonStatus[4] = D_8082AB6C[pauseCtx->pageIndex + pt][4];
|
||||
|
||||
if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (D_8082ABEC[pauseCtx->mode] == PAUSE_EQUIP)) {
|
||||
gSaveContext.buttonStatus[1] = BTN_ENABLED;
|
||||
gSaveContext.buttonStatus[2] = BTN_ENABLED;
|
||||
gSaveContext.buttonStatus[3] = BTN_ENABLED;
|
||||
gSaveContext.buttonStatus[4] = BTN_ENABLED;
|
||||
}
|
||||
|
||||
osSyncPrintf("kscope->kscp_pos+pt = %d\n", pauseCtx->pageIndex + pt);
|
||||
|
||||
gSaveContext.unk_13EA = 0;
|
||||
|
@ -2983,7 +2990,16 @@ void func_808265BC(GlobalContext* globalCtx) {
|
|||
gSaveContext.buttonStatus[2] = D_8082AB6C[pauseCtx->pageIndex][2];
|
||||
gSaveContext.buttonStatus[3] = D_8082AB6C[pauseCtx->pageIndex][3];
|
||||
gSaveContext.buttonStatus[4] = D_8082AB6C[pauseCtx->pageIndex][4];
|
||||
|
||||
pauseCtx->pageIndex = D_8082ABEC[pauseCtx->mode];
|
||||
|
||||
if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (pauseCtx->pageIndex == PAUSE_EQUIP)) {
|
||||
gSaveContext.buttonStatus[1] = BTN_ENABLED;
|
||||
gSaveContext.buttonStatus[2] = BTN_ENABLED;
|
||||
gSaveContext.buttonStatus[3] = BTN_ENABLED;
|
||||
gSaveContext.buttonStatus[4] = BTN_ENABLED;
|
||||
}
|
||||
|
||||
pauseCtx->unk_1E4 = 0;
|
||||
pauseCtx->state++;
|
||||
pauseCtx->alpha = 255;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue