mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-05-24 23:31:34 -04:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0bc6ca08e0 | |||
| 16aaf2f939 | |||
| 3971e3696e | |||
| f11f97e84e | |||
| 7a00658be9 | |||
| 7bc2259c82 | |||
| 3d73faa9a0 | |||
| 134aba4aa0 | |||
| 79a29a62ef | |||
| 3f67fed073 | |||
| cbeec006ec | |||
| fd9cd9c5eb | |||
| 4a576f45ee | |||
| 32bf8cc53c | |||
| 02f7310c16 | |||
| bfe13906e9 | |||
| 32288be744 | |||
| 19be6e9b99 | |||
| 0b8cc71d0d | |||
| ced34ab68a | |||
| e163d5bc3d |
@@ -235,7 +235,6 @@ jobs:
|
||||
- name: Install dependencies
|
||||
if: ${{ !vars.LINUX_RUNNER }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ninja-build
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
|
||||
+3
-3
@@ -5,9 +5,9 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
||||
|
||||
project(Ship VERSION 8.0.5 LANGUAGES C CXX)
|
||||
set(PROJECT_BUILD_NAME "MacReady Foxtrot" CACHE STRING "")
|
||||
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
|
||||
project(Ship VERSION 8.0.6 LANGUAGES C CXX)
|
||||
set(PROJECT_BUILD_NAME "MacReady Golf" CACHE STRING "" FORCE)
|
||||
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "" FORCE)
|
||||
|
||||
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
|
||||
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)
|
||||
|
||||
+1
-1
Submodule libultraship updated: 96c8a8929c...1ca7d0fa78
@@ -28,4 +28,10 @@
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<asmv3:windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- legacy -->
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back to pm if pmv2 is not available -->
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
|
||||
@@ -46,10 +46,18 @@ template<> struct is_char_type<std::byte>: public boost::true_type {};
|
||||
|
||||
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
|
||||
|
||||
#if BOOST_USE_STD_TYPES
|
||||
#define BOOST_ENABLE_IF std::enable_if
|
||||
#define BOOST_IS_SAME std::is_same
|
||||
#else
|
||||
#define BOOST_ENABLE_IF boost::enable_if_
|
||||
#define BOOST_IS_SAME is_same
|
||||
#endif
|
||||
|
||||
template<class It>
|
||||
inline typename boost::enable_if_<
|
||||
inline typename BOOST_ENABLE_IF<
|
||||
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
|
||||
is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value,
|
||||
BOOST_IS_SAME<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value,
|
||||
std::size_t>::type
|
||||
hash_range_32( uint32_t seed, It first, It last )
|
||||
{
|
||||
@@ -114,4 +122,7 @@ std::size_t>::type
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#undef BOOST_ENABLE_IF
|
||||
#undef BOOST_IS_SAME
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
|
||||
|
||||
@@ -23,6 +23,18 @@
|
||||
|
||||
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
|
||||
|
||||
#if BOOST_USE_STD_TYPES
|
||||
#define BOOST_ENABLE_IF std::enable_if
|
||||
#define BOOST_IS_INTEGRAL hash_detail::is_integral
|
||||
#define BOOST_IS_UNSIGNED is_unsigned
|
||||
#define BOOST_MAKE_UNSIGNED make_unsigned
|
||||
#else
|
||||
#define BOOST_ENABLE_IF boost::enable_if_
|
||||
#define BOOST_IS_INTEGRAL boost::is_integral
|
||||
#define BOOST_IS_UNSIGNED boost::is_unsigned
|
||||
#define BOOST_MAKE_UNSIGNED boost::make_unsigned
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
@@ -36,7 +48,7 @@ namespace boost
|
||||
{
|
||||
template<class T,
|
||||
bool bigger_than_size_t = (sizeof(T) > sizeof(uint32_t)),
|
||||
bool is_unsigned = boost::is_unsigned<T>::value,
|
||||
bool is_unsigned = BOOST_IS_UNSIGNED<T>::value,
|
||||
std::size_t size_t_bits = sizeof(uint32_t) * CHAR_BIT,
|
||||
std::size_t type_bits = sizeof(T) * CHAR_BIT>
|
||||
struct hash_integral_impl_32;
|
||||
@@ -53,7 +65,7 @@ namespace boost
|
||||
{
|
||||
static uint32_t fn( T v )
|
||||
{
|
||||
typedef typename boost::make_unsigned<T>::type U;
|
||||
typedef typename BOOST_MAKE_UNSIGNED<T>::type U;
|
||||
|
||||
if( v >= 0 )
|
||||
{
|
||||
@@ -97,7 +109,7 @@ namespace boost
|
||||
} // namespace hash_detail
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if_<boost::is_integral<T>::value, uint32_t>::type
|
||||
typename BOOST_ENABLE_IF<BOOST_IS_INTEGRAL<T>::value, uint32_t>::type
|
||||
hash_value_32( T v )
|
||||
{
|
||||
return hash_detail::hash_integral_impl_32<T>::fn( v );
|
||||
@@ -106,7 +118,7 @@ namespace boost
|
||||
// contiguous ranges (string, vector, array)
|
||||
#if BOOST_VERSION_HAS_HASH_RANGE
|
||||
template <typename T>
|
||||
typename boost::enable_if_<container_hash::is_contiguous_range<T>::value, uint32_t>::type
|
||||
typename BOOST_ENABLE_IF<container_hash::is_contiguous_range<T>::value, uint32_t>::type
|
||||
hash_value_32( T const& v )
|
||||
{
|
||||
return boost::hash_range_32( v.data(), v.data() + v.size() );
|
||||
@@ -168,5 +180,9 @@ namespace boost
|
||||
} // namespace boost
|
||||
|
||||
#undef BOOST_HASH_CHAR_TRAITS
|
||||
#undef BOOST_ENABLE_IF
|
||||
#undef BOOST_IS_INTEGRAL
|
||||
#undef BOOST_IS_UNSIGNED
|
||||
#undef BOOST_MAKE_UNSIGNED
|
||||
|
||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP
|
||||
|
||||
@@ -6,4 +6,6 @@
|
||||
|
||||
#define BOOST_VERSION_HAS_HASH_RANGE ((BOOST_VERSION / 100 % 1000) >= 81)
|
||||
|
||||
#define BOOST_USE_STD_TYPES ((BOOST_VERSION / 100 % 1000) >= 84)
|
||||
|
||||
#endif // #ifndef BOOST_CONTAINER_HASH_VERSION_HPP
|
||||
|
||||
@@ -1259,6 +1259,8 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable,
|
||||
s32 dListIndex);
|
||||
void SkelAnime_DrawSkeletonOpa(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw,
|
||||
PostLimbDrawOpa postLimbDraw, void* arg);
|
||||
Gfx* SkelAnime_DrawSkeleton2(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw,
|
||||
PostLimbDrawOpa postLimbDraw, void* arg, Gfx* gfx);
|
||||
void SkelAnime_DrawOpa(PlayState* play, void** skeleton, Vec3s* jointTable,
|
||||
OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, void* arg);
|
||||
void SkelAnime_DrawFlexOpa(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dListCount,
|
||||
@@ -2458,6 +2460,8 @@ void Message_DrawText(PlayState* play, Gfx** gfxP);
|
||||
|
||||
void Interface_CreateQuadVertexGroup(Vtx* vtxList, s32 xStart, s32 yStart, s32 width, s32 height, u8 flippedH);
|
||||
void Interface_RandoRestoreSwordless(void);
|
||||
s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw,
|
||||
bool* shouldUpdate);
|
||||
|
||||
// #endregion
|
||||
|
||||
|
||||
@@ -1405,6 +1405,8 @@ typedef struct PlayState {
|
||||
/* 0x1242B */ u8 unk_1242B;
|
||||
/* 0x1242C */ SceneTableEntry* loadedScene;
|
||||
/* 0x12430 */ char unk_12430[0xE8];
|
||||
// SOH [Custom Models] MTX tracker for flex based skeletons
|
||||
Mtx** flexLimbOverrideMTX;
|
||||
} PlayState; // size = 0x12518
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -782,7 +782,7 @@ void DrawFlagTableArray16(const FlagTable& flagTable, uint16_t row, uint16_t& fl
|
||||
ImGui::PopStyleColor();
|
||||
if (ImGui::IsItemHovered() && hasDescription) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("%s", UIWidgets::WrappedText(flagTable.flagDescriptions.at(row * 16 + flagIndex), 60));
|
||||
ImGui::Text("%s", UIWidgets::WrappedText(flagTable.flagDescriptions.at(row * 16 + flagIndex), 60).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopID();
|
||||
|
||||
@@ -211,6 +211,8 @@ const std::vector<const char*> enhancementsCvars = {
|
||||
"gDisableLOD",
|
||||
"gDisableDrawDistance",
|
||||
"gDisableKokiriDrawDistance",
|
||||
"gEnhancements.WidescreenActorCulling",
|
||||
"gEnhancements.ExtendedCullingExcludeGlitchActors",
|
||||
"gLowResMode",
|
||||
"gDrawLineupTick",
|
||||
"gQuickBongoKill",
|
||||
|
||||
@@ -846,10 +846,10 @@ static void RandomizeDungeonItems() {
|
||||
}
|
||||
|
||||
if (GerudoKeys.Is(GERUDOKEYS_ANY_DUNGEON)) {
|
||||
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY; });
|
||||
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY || i == GERUDO_FORTRESS_KEY_RING; });
|
||||
AddElementsToPool(anyDungeonItems, gerudoKeys);
|
||||
} else if (GerudoKeys.Is(GERUDOKEYS_OVERWORLD)) {
|
||||
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY; });
|
||||
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY || i == GERUDO_FORTRESS_KEY_RING; });
|
||||
AddElementsToPool(overworldItems, gerudoKeys);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,23 @@ std::map<SceneID, RandomizerCheckArea> DungeonRCAreasBySceneID = {
|
||||
{SCENE_INSIDE_GANONS_CASTLE, RCAREA_GANONS_CASTLE},
|
||||
};
|
||||
|
||||
// Dungeon entrances with obvious visual differences between MQ and vanilla qualifying as spoiling on sight
|
||||
std::vector<uint32_t> spoilingEntrances = {
|
||||
0x0000, // ENTR_DEKU_TREE_0
|
||||
0x0467, // ENTR_DODONGOS_CAVERN_1
|
||||
0x0028, // ENTR_JABU_JABU_0
|
||||
0x0407, // ENTR_JABU_JABU_1
|
||||
0x0169, // ENTR_FOREST_TEMPLE_0
|
||||
0x0165, // ENTR_FIRE_TEMPLE_0
|
||||
0x0175, // ENTR_FIRE_TEMPLE_1
|
||||
0x0423, // ENTR_WATER_TEMPLE_1
|
||||
0x0082, // ENTR_SPIRIT_TEMPLE_0
|
||||
0x02B2, // ENTR_SHADOW_TEMPLE_1
|
||||
0x0088, // ENTR_ICE_CAVERN_0
|
||||
0x0008, // ENTR_GERUDO_TRAINING_GROUNDS_0
|
||||
0x0467 // ENTR_INSIDE_GANONS_CASTLE_0
|
||||
};
|
||||
|
||||
std::map<RandomizerCheckArea, std::vector<RandomizerCheckObject>> checksByArea;
|
||||
bool areasFullyChecked[RCAREA_INVALID];
|
||||
u32 areasSpoiled = 0;
|
||||
@@ -263,6 +280,10 @@ void SetCheckCollected(RandomizerCheck rc) {
|
||||
}
|
||||
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true);
|
||||
|
||||
if (!IsAreaSpoiled(rcObj.rcArea)) {
|
||||
SetAreaSpoiled(rcObj.rcArea);
|
||||
}
|
||||
|
||||
doAreaScroll = true;
|
||||
UpdateOrdering(rcObj.rcArea);
|
||||
UpdateInventoryChecks();
|
||||
@@ -467,9 +488,14 @@ void CheckTrackerLoadGame(int32_t fileNum) {
|
||||
areaChecksGotten[realRcObj.rcArea]++;
|
||||
}
|
||||
}
|
||||
|
||||
if (areaChecksGotten[realRcObj.rcArea] != 0 || RandomizerCheckObjects::AreaIsOverworld(realRcObj.rcArea)) {
|
||||
areasSpoiled |= (1 << realRcObj.rcArea);
|
||||
}
|
||||
for (int i = RCAREA_KOKIRI_FOREST; i < RCAREA_INVALID; i++) {
|
||||
if (!IsAreaSpoiled(static_cast<RandomizerCheckArea>(i)) && (RandomizerCheckObjects::AreaIsOverworld(static_cast<RandomizerCheckArea>(i)) || !IS_RANDO ||
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_NONE ||
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SELECTION ||
|
||||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SET_NUMBER &&
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12))) {
|
||||
SetAreaSpoiled(static_cast<RandomizerCheckArea>(i));
|
||||
}
|
||||
}
|
||||
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) {
|
||||
@@ -539,6 +565,9 @@ void CheckTrackerTransition(uint32_t sceneNum) {
|
||||
SetShopSeen(sceneNum, false);
|
||||
break;
|
||||
}
|
||||
if (!IsAreaSpoiled(currentArea) && (RandomizerCheckObjects::AreaIsOverworld(currentArea) || std::find(spoilingEntrances.begin(), spoilingEntrances.end(), gPlayState->nextEntranceIndex) != spoilingEntrances.end())) {
|
||||
SetAreaSpoiled(currentArea);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckTrackerFrame() {
|
||||
@@ -756,6 +785,7 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) {
|
||||
|
||||
void InitTrackerData(bool isDebug) {
|
||||
TrySetAreas();
|
||||
areasSpoiled = 0;
|
||||
for (auto& [rc, rco] : RandomizerCheckObjects::GetAllRCObjects()) {
|
||||
if (rc != RC_UNKNOWN_CHECK && rc != RC_MAX) {
|
||||
DefaultCheckData(rc);
|
||||
@@ -783,6 +813,7 @@ void SaveTrackerData(SaveContext* saveContext, int sectionID, bool gameSave) {
|
||||
SaveManager::Instance->SaveData("hintItem", saveContext->checkTrackerData[i].hintItem);
|
||||
});
|
||||
});
|
||||
SaveManager::Instance->SaveData("areasSpoiled", areasSpoiled);
|
||||
}
|
||||
|
||||
void SaveFile(SaveContext* saveContext, int sectionID, bool fullSave) {
|
||||
@@ -798,6 +829,7 @@ void LoadFile() {
|
||||
SaveManager::Instance->LoadData("hintItem", gSaveContext.checkTrackerData[i].hintItem);
|
||||
});
|
||||
});
|
||||
SaveManager::Instance->LoadData("areasSpoiled", areasSpoiled);
|
||||
}
|
||||
|
||||
void Teardown() {
|
||||
@@ -809,6 +841,15 @@ void Teardown() {
|
||||
lastLocationChecked = RC_UNKNOWN_CHECK;
|
||||
}
|
||||
|
||||
bool IsAreaSpoiled(RandomizerCheckArea rcArea) {
|
||||
return areasSpoiled & (1 << rcArea);
|
||||
}
|
||||
|
||||
void SetAreaSpoiled(RandomizerCheckArea rcArea) {
|
||||
areasSpoiled |= (1 << rcArea);
|
||||
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true);
|
||||
}
|
||||
|
||||
void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) {
|
||||
auto area = RandomizerCheckObjects::GetAllRCObjects().find(static_cast<RandomizerCheck>(check))->second.rcArea;
|
||||
if ((!gSaveContext.checkTrackerData[check].skipped && data.skipped) ||
|
||||
@@ -827,10 +868,6 @@ void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) {
|
||||
void CheckTrackerWindow::DrawElement() {
|
||||
ImGui::SetNextWindowSize(ImVec2(400, 540), ImGuiCond_FirstUseEver);
|
||||
|
||||
if (!initialized && (gPlayState == nullptr || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CVarGetInteger("gCheckTrackerWindowType", TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) {
|
||||
if (CVarGetInteger("gCheckTrackerShowOnlyPaused", 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) {
|
||||
return;
|
||||
@@ -851,7 +888,7 @@ void CheckTrackerWindow::DrawElement() {
|
||||
|
||||
BeginFloatWindows("Check Tracker", mIsVisible, ImGuiWindowFlags_NoScrollbar);
|
||||
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
if (!GameInteractor::IsSaveLoaded() || !initialized) {
|
||||
ImGui::Text("Waiting for file load..."); //TODO Language
|
||||
EndFloatWindows();
|
||||
return;
|
||||
@@ -862,8 +899,6 @@ void CheckTrackerWindow::DrawElement() {
|
||||
sceneId = (SceneID)gPlayState->sceneNum;
|
||||
}
|
||||
|
||||
areasSpoiled |= (1 << currentArea);
|
||||
|
||||
//Quick Options
|
||||
#ifdef __WIIU__
|
||||
float headerHeight = 40.0f;
|
||||
@@ -925,7 +960,6 @@ void CheckTrackerWindow::DrawElement() {
|
||||
Color_RGBA8 mainColor;
|
||||
Color_RGBA8 extraColor;
|
||||
std::string stemp;
|
||||
s32 areaMask = 1;
|
||||
|
||||
for (auto& [rcArea, objs] : checksByArea) {
|
||||
RandomizerCheckArea thisArea = currentArea;
|
||||
@@ -978,11 +1012,7 @@ void CheckTrackerWindow::DrawElement() {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f,
|
||||
extraColor.b / 255.0f, extraColor.a / 255.0f));
|
||||
|
||||
isThisAreaSpoiled = areasSpoiled & areaMask || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0) || !IS_RANDO ||
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_NONE ||
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SELECTION ||
|
||||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SET_NUMBER &&
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12);
|
||||
isThisAreaSpoiled = IsAreaSpoiled(rcArea) || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0);
|
||||
|
||||
if (isThisAreaSpoiled) {
|
||||
if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) {
|
||||
@@ -1015,7 +1045,6 @@ void CheckTrackerWindow::DrawElement() {
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
areaMask <<= 1;
|
||||
}
|
||||
|
||||
ImGui::EndTable(); //Checks Lead-out
|
||||
@@ -1219,10 +1248,10 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) {
|
||||
}
|
||||
|
||||
void UpdateInventoryChecks() {
|
||||
//For all the areas with compasses, if you have one, spoil the area
|
||||
//For all the areas with maps, if you have one, spoil the area
|
||||
for (auto [scene, area] : DungeonRCAreasBySceneID) {
|
||||
if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, scene)) {
|
||||
areasSpoiled |= (1 << area);
|
||||
SetAreaSpoiled(area);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1232,9 +1261,6 @@ void UpdateAreaFullyChecked(RandomizerCheckArea area) {
|
||||
|
||||
void UpdateAreas(RandomizerCheckArea area) {
|
||||
areasFullyChecked[area] = areaChecksGotten[area] == checksByArea.find(area)->second.size();
|
||||
if (areaChecksGotten[area] != 0 || RandomizerCheckObjects::AreaIsOverworld(area)) {
|
||||
areasSpoiled |= (1 << area);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAllOrdering() {
|
||||
|
||||
@@ -50,6 +50,8 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj);
|
||||
void InitTrackerData(bool isDebug);
|
||||
RandomizerCheckArea GetCheckArea();
|
||||
void UpdateCheck(uint32_t, RandomizerCheckTrackerData);
|
||||
bool IsAreaSpoiled(RandomizerCheckArea rcArea);
|
||||
void SetAreaSpoiled(RandomizerCheckArea rcArea);
|
||||
} // namespace CheckTracker
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <vector>
|
||||
#include <libultraship/libultraship.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "randomizer_check_tracker.h"
|
||||
#include <algorithm>
|
||||
|
||||
extern "C" {
|
||||
@@ -290,15 +291,15 @@ bool IsValidSaveFile() {
|
||||
}
|
||||
|
||||
bool HasSong(ItemTrackerItem item) {
|
||||
return (1 << item.id) & gSaveContext.inventory.questItems;
|
||||
return GameInteractor::IsSaveLoaded() ? ((1 << item.id) & gSaveContext.inventory.questItems) : false;
|
||||
}
|
||||
|
||||
bool HasQuestItem(ItemTrackerItem item) {
|
||||
return (item.data & gSaveContext.inventory.questItems) != 0;
|
||||
return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.questItems) : false;
|
||||
}
|
||||
|
||||
bool HasEquipment(ItemTrackerItem item) {
|
||||
return (item.data & gSaveContext.inventory.equipment) != 0;
|
||||
return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.equipment) : false;
|
||||
}
|
||||
|
||||
ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
|
||||
@@ -406,8 +407,12 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
|
||||
#define IM_COL_GREEN IM_COL32(0, 255, 0, 255)
|
||||
#define IM_COL_GRAY IM_COL32(155, 155, 155, 255)
|
||||
#define IM_COL_PURPLE IM_COL32(180, 90, 200, 255)
|
||||
#define IM_COL_LIGHT_YELLOW IM_COL32(255, 255, 130, 255)
|
||||
|
||||
void DrawItemCount(ItemTrackerItem item) {
|
||||
void DrawItemCount(ItemTrackerItem item, bool hideMax) {
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
return;
|
||||
}
|
||||
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
|
||||
ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item);
|
||||
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||
@@ -416,7 +421,7 @@ void DrawItemCount(ItemTrackerItem item) {
|
||||
|
||||
if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) {
|
||||
std::string currentString = "";
|
||||
std::string maxString = std::to_string(currentAndMax.maxCapacity);
|
||||
std::string maxString = hideMax ? "???" : std::to_string(currentAndMax.maxCapacity);
|
||||
ImU32 currentColor = IM_COL_WHITE;
|
||||
ImU32 maxColor = IM_COL_GREEN;
|
||||
// "Collected / Max", "Current / Collected / Max", "Current / Max"
|
||||
@@ -548,7 +553,7 @@ void DrawQuest(ItemTrackerItem item) {
|
||||
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
|
||||
|
||||
if (item.id == QUEST_SKULL_TOKEN) {
|
||||
DrawItemCount(item);
|
||||
DrawItemCount(item, false);
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
@@ -558,7 +563,7 @@ void DrawQuest(ItemTrackerItem item) {
|
||||
|
||||
void DrawItem(ItemTrackerItem item) {
|
||||
|
||||
uint32_t actualItemId = INV_CONTENT(item.id);
|
||||
uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE;
|
||||
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
|
||||
bool hasItem = actualItemId != ITEM_NONE;
|
||||
std::string itemName = "";
|
||||
@@ -617,7 +622,7 @@ void DrawItem(ItemTrackerItem item) {
|
||||
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded),
|
||||
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
|
||||
|
||||
DrawItemCount(item);
|
||||
DrawItemCount(item, false);
|
||||
ImGui::EndGroup();
|
||||
|
||||
if (itemName == "") {
|
||||
@@ -628,7 +633,7 @@ void DrawItem(ItemTrackerItem item) {
|
||||
}
|
||||
|
||||
void DrawBottle(ItemTrackerItem item) {
|
||||
uint32_t actualItemId = gSaveContext.inventory.items[SLOT(item.id) + item.data];
|
||||
uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? (gSaveContext.inventory.items[SLOT(item.id) + item.data]) : false;
|
||||
bool hasItem = actualItemId != ITEM_NONE;
|
||||
|
||||
if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) {
|
||||
@@ -647,8 +652,8 @@ void DrawDungeonItem(ItemTrackerItem item) {
|
||||
ImU32 dungeonColor = IM_COL_WHITE;
|
||||
uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential
|
||||
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
|
||||
bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[item.data]) != 0;
|
||||
bool hasSmallKey = (gSaveContext.inventory.dungeonKeys[item.data]) >= 0;
|
||||
bool hasItem = GameInteractor::IsSaveLoaded() ? (bitMask & gSaveContext.inventory.dungeonItems[item.data]) : false;
|
||||
bool hasSmallKey = GameInteractor::IsSaveLoaded() ? ((gSaveContext.inventory.dungeonKeys[item.data]) >= 0) : false;
|
||||
ImGui::BeginGroup();
|
||||
if (itemId == ITEM_KEY_SMALL) {
|
||||
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.name : item.nameFaded),
|
||||
@@ -659,16 +664,18 @@ void DrawDungeonItem(ItemTrackerItem item) {
|
||||
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
|
||||
}
|
||||
|
||||
if (ResourceMgr_IsSceneMasterQuest(item.data) && (CHECK_DUNGEON_ITEM(DUNGEON_MAP, item.data) || item.data == SCENE_GERUDO_TRAINING_GROUND || item.data == SCENE_INSIDE_GANONS_CASTLE)) {
|
||||
dungeonColor = IM_COL_PURPLE;
|
||||
if (CheckTracker::IsAreaSpoiled(RandomizerCheckObjects::GetRCAreaBySceneID(static_cast<SceneID>(item.data))) && GameInteractor::IsSaveLoaded()) {
|
||||
dungeonColor = (ResourceMgr_IsSceneMasterQuest(item.data) ? IM_COL_PURPLE : IM_COL_LIGHT_YELLOW);
|
||||
}
|
||||
|
||||
if (itemId == ITEM_KEY_SMALL) {
|
||||
DrawItemCount(item);
|
||||
DrawItemCount(item, !CheckTracker::IsAreaSpoiled(RandomizerCheckObjects::GetRCAreaBySceneID(static_cast<SceneID>(item.data))));
|
||||
|
||||
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||
// offset puts the text at the correct level. for some reason, if the save is loaded, the margin is 3 pixels higher only for small keys, so we use 16 then. Otherwise, 13 is where everything else is
|
||||
int offset = GameInteractor::IsSaveLoaded() ? 16 : 13;
|
||||
std::string dungeonName = itemTrackerDungeonShortNames[item.data];
|
||||
ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + 16)));
|
||||
ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + offset)));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, dungeonColor);
|
||||
ImGui::Text("%s", dungeonName.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
@@ -725,13 +732,15 @@ void DrawNotes(bool resizeable = false) {
|
||||
}
|
||||
};
|
||||
ImVec2 size = resizeable ? ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y) : ImVec2(((iconSize + iconSpacing) * 6) - 8, 200);
|
||||
if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput)) {
|
||||
notesNeedSave = true;
|
||||
notesIdleFrames = 0;
|
||||
}
|
||||
if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) {
|
||||
notesNeedSave = false;
|
||||
SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true);
|
||||
if (GameInteractor::IsSaveLoaded()) {
|
||||
if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput)) {
|
||||
notesNeedSave = true;
|
||||
notesIdleFrames = 0;
|
||||
}
|
||||
if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) {
|
||||
notesNeedSave = false;
|
||||
SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true);
|
||||
}
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
+16
-8
@@ -137,6 +137,8 @@ Color_RGB8 zoraColor = { 0x00, 0xEC, 0x64 };
|
||||
|
||||
float previousImGuiScale;
|
||||
|
||||
bool prevAltAssets = false;
|
||||
|
||||
// Same as NaviColor type from OoT src (z_actor.c), but modified to be sans alpha channel for Controller LED.
|
||||
typedef struct {
|
||||
Color_RGB8 inner;
|
||||
@@ -297,6 +299,8 @@ OTRGlobals::OTRGlobals() {
|
||||
};
|
||||
// tell LUS to reserve 3 SoH specific threads (Game, Audio, Save)
|
||||
context = LUS::Context::CreateInstance("Ship of Harkinian", appShortName, "shipofharkinian.json", OTRFiles, {}, 3);
|
||||
prevAltAssets = CVarGetInteger("gAltAssets", 0);
|
||||
context->GetResourceManager()->SetAltAssetsEnabled(prevAltAssets);
|
||||
SPDLOG_INFO("Starting Ship of Harkinian version {}", (char*)gBuildVersion);
|
||||
|
||||
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Animation, "Animation", std::make_shared<LUS::AnimationFactory>());
|
||||
@@ -1235,7 +1239,7 @@ extern "C" void Graph_StartFrame() {
|
||||
}
|
||||
#endif
|
||||
case KbScancode::LUS_KB_TAB: {
|
||||
ToggleAltAssetsAtEndOfFrame = true;
|
||||
CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1315,11 +1319,10 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ToggleAltAssetsAtEndOfFrame) {
|
||||
ToggleAltAssetsAtEndOfFrame = false;
|
||||
|
||||
// Actually update the CVar now before runing the alt asset update listeners
|
||||
CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0));
|
||||
bool curAltAssets = CVarGetInteger("gAltAssets", 0);
|
||||
if (prevAltAssets != curAltAssets) {
|
||||
prevAltAssets = curAltAssets;
|
||||
LUS::Context::GetInstance()->GetResourceManager()->SetAltAssetsEnabled(curAltAssets);
|
||||
gfx_texture_cache_clear();
|
||||
LUS::SkeletonPatcher::UpdateSkeletons();
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnAssetAltChange>();
|
||||
@@ -1495,10 +1498,14 @@ extern "C" uint8_t ResourceMgr_FileAltExists(const char* filePath) {
|
||||
return ExtensionCache.contains(path);
|
||||
}
|
||||
|
||||
extern "C" bool ResourceMgr_IsAltAssetsEnabled() {
|
||||
return LUS::Context::GetInstance()->GetResourceManager()->IsAltAssetsEnabled();
|
||||
}
|
||||
|
||||
// Unloads a resource if an alternate version exists when alt assets are enabled
|
||||
// The resource is only removed from the internal cache to prevent it from used in the next resource lookup
|
||||
extern "C" void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName) {
|
||||
if (CVarGetInteger("gAltAssets", 0) && ResourceMgr_FileAltExists((char*) resName)) {
|
||||
if (ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileAltExists((char*) resName)) {
|
||||
ResourceMgr_UnloadResource((char*) resName);
|
||||
}
|
||||
}
|
||||
@@ -1735,6 +1742,7 @@ extern "C" char* ResourceMgr_LoadArrayByName(const char* path)
|
||||
return (char*)res->Scalars.data();
|
||||
}
|
||||
|
||||
// Return of LoadArrayByNameAsVec3s must be freed by the caller
|
||||
extern "C" char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path) {
|
||||
auto res = std::static_pointer_cast<LUS::Array>(GetResourceByNameHandlingMQ(path));
|
||||
|
||||
@@ -1867,7 +1875,7 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel
|
||||
pathStr = pathStr.substr(sOtr.length());
|
||||
}
|
||||
|
||||
bool isAlt = CVarGetInteger("gAltAssets", 0);
|
||||
bool isAlt = ResourceMgr_IsAltAssetsEnabled();
|
||||
|
||||
if (isAlt) {
|
||||
pathStr = LUS::IResource::gAltAssetPrefix + pathStr;
|
||||
|
||||
@@ -120,6 +120,7 @@ void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size);
|
||||
void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size);
|
||||
|
||||
uint64_t GetPerfCounter();
|
||||
bool ResourceMgr_IsAltAssetsEnabled();
|
||||
struct SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, SkelAnime* skelAnime);
|
||||
void ResourceMgr_UnregisterSkeleton(SkelAnime* skelAnime);
|
||||
void ResourceMgr_ClearSkeletons();
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "Enhancements/cosmetics/authenticGfxPatches.h"
|
||||
|
||||
bool ToggleAltAssetsAtEndOfFrame = false;
|
||||
bool isBetaQuestEnabled = false;
|
||||
|
||||
extern "C" {
|
||||
|
||||
+66
-36
@@ -28,7 +28,6 @@
|
||||
#include "Enhancements/randomizer/randomizer_item_tracker.h"
|
||||
#include "Enhancements/randomizer/randomizer_settings_window.h"
|
||||
|
||||
extern bool ToggleAltAssetsAtEndOfFrame;
|
||||
extern bool isBetaQuestEnabled;
|
||||
|
||||
extern "C" PlayState* gPlayState;
|
||||
@@ -50,6 +49,13 @@ std::string GetWindowButtonText(const char* text, bool menuOpen) {
|
||||
if (!menuOpen) { strcat(buttonText, " "); }
|
||||
return buttonText;
|
||||
}
|
||||
|
||||
static std::unordered_map<LUS::WindowBackend, const char*> windowBackendNames = {
|
||||
{ LUS::WindowBackend::DX11, "DirectX" },
|
||||
{ LUS::WindowBackend::SDL_OPENGL, "OpenGL"},
|
||||
{ LUS::WindowBackend::SDL_METAL, "Metal" },
|
||||
{ LUS::WindowBackend::GX2, "GX2"}
|
||||
};
|
||||
|
||||
static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large" };
|
||||
|
||||
@@ -102,6 +108,24 @@ extern "C" SaveContext gSaveContext;
|
||||
|
||||
namespace SohGui {
|
||||
|
||||
std::unordered_map<LUS::WindowBackend, const char*> availableWindowBackendsMap;
|
||||
LUS::WindowBackend configWindowBackend;
|
||||
|
||||
void UpdateWindowBackendObjects() {
|
||||
LUS::WindowBackend runningWindowBackend = LUS::Context::GetInstance()->GetWindow()->GetWindowBackend();
|
||||
int32_t configWindowBackendId = LUS::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1);
|
||||
if (configWindowBackendId != -1 && configWindowBackendId < static_cast<int>(LUS::WindowBackend::BACKEND_COUNT)) {
|
||||
configWindowBackend = static_cast<LUS::WindowBackend>(configWindowBackendId);
|
||||
} else {
|
||||
configWindowBackend = runningWindowBackend;
|
||||
}
|
||||
|
||||
auto availableWindowBackends = LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends();
|
||||
for (auto& backend : *availableWindowBackends) {
|
||||
availableWindowBackendsMap[backend] = windowBackendNames[backend];
|
||||
}
|
||||
}
|
||||
|
||||
void DrawMenuBarIcon() {
|
||||
static bool gameIconLoaded = false;
|
||||
if (!gameIconLoaded) {
|
||||
@@ -391,40 +415,24 @@ void DrawSettingsMenu() {
|
||||
UIWidgets::Tooltip("Changes the scaling of the ImGui menu elements.");
|
||||
|
||||
UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
|
||||
|
||||
static std::unordered_map<LUS::WindowBackend, const char*> windowBackendNames = {
|
||||
{ LUS::WindowBackend::DX11, "DirectX" },
|
||||
{ LUS::WindowBackend::SDL_OPENGL, "OpenGL"},
|
||||
{ LUS::WindowBackend::SDL_METAL, "Metal" },
|
||||
{ LUS::WindowBackend::GX2, "GX2"}
|
||||
};
|
||||
|
||||
ImGui::Text("Renderer API (Needs reload)");
|
||||
LUS::WindowBackend runningWindowBackend = LUS::Context::GetInstance()->GetWindow()->GetWindowBackend();
|
||||
LUS::WindowBackend configWindowBackend;
|
||||
int configWindowBackendId = LUS::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1);
|
||||
if (configWindowBackendId != -1 && configWindowBackendId < static_cast<int>(LUS::WindowBackend::BACKEND_COUNT)) {
|
||||
configWindowBackend = static_cast<LUS::WindowBackend>(configWindowBackendId);
|
||||
} else {
|
||||
configWindowBackend = runningWindowBackend;
|
||||
}
|
||||
|
||||
if (LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) {
|
||||
if (availableWindowBackendsMap.size() <= 1) {
|
||||
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
|
||||
}
|
||||
if (ImGui::BeginCombo("##RApi", windowBackendNames[configWindowBackend])) {
|
||||
for (size_t i = 0; i < LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size(); i++) {
|
||||
auto backend = LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->data()[i];
|
||||
if (ImGui::Selectable(windowBackendNames[backend], backend == configWindowBackend)) {
|
||||
LUS::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast<int>(backend));
|
||||
LUS::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name",
|
||||
windowBackendNames[backend]);
|
||||
if (ImGui::BeginCombo("##RApi", availableWindowBackendsMap[configWindowBackend])) {
|
||||
for (auto backend : availableWindowBackendsMap) {
|
||||
if (ImGui::Selectable(backend.second, backend.first == configWindowBackend)) {
|
||||
LUS::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast<int>(backend.first));
|
||||
LUS::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name", backend.second);
|
||||
LUS::Context::GetInstance()->GetConfig()->Save();
|
||||
UpdateWindowBackendObjects();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
if (LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) {
|
||||
if (availableWindowBackendsMap.size() <= 1) {
|
||||
UIWidgets::ReEnableComponent("");
|
||||
}
|
||||
|
||||
@@ -907,12 +915,7 @@ void DrawEnhancementsMenu() {
|
||||
if (ImGui::BeginMenu("Graphics"))
|
||||
{
|
||||
if (ImGui::BeginMenu("Mods")) {
|
||||
if (UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", "gAltAssets", false, false)) {
|
||||
// The checkbox will flip the alt asset CVar, but we instead want it to change at the end of the game frame
|
||||
// We toggle it back while setting the flag to update the CVar later
|
||||
CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0));
|
||||
ToggleAltAssetsAtEndOfFrame = true;
|
||||
}
|
||||
UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", "gAltAssets", false, false);
|
||||
UIWidgets::Tooltip("Toggle between standard assets and alternate assets. Usually mods will indicate if this setting has to be used or not.");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Disable Bomb Billboarding", "gDisableBombBillboarding", true, false);
|
||||
UIWidgets::Tooltip("Disables bombs always rotating to face the camera. To be used in conjunction with mods that want to replace bombs with 3D objects.");
|
||||
@@ -925,16 +928,39 @@ void DrawEnhancementsMenu() {
|
||||
}
|
||||
UIWidgets::PaddedEnhancementCheckbox("Disable LOD", "gDisableLOD", true, false);
|
||||
UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance");
|
||||
if (UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false)) {
|
||||
if (CVarGetInteger("gDisableDrawDistance", 0) == 0) {
|
||||
if (UIWidgets::EnhancementSliderInt("Increase Actor Draw Distance: %dx", "##IncreaseActorDrawDistance",
|
||||
"gDisableDrawDistance", 1, 5, "", 1, true, false)) {
|
||||
if (CVarGetInteger("gDisableDrawDistance", 1) <= 1) {
|
||||
CVarSetInteger("gDisableKokiriDrawDistance", 0);
|
||||
}
|
||||
}
|
||||
UIWidgets::Tooltip("Turns off the objects draw distance, making objects being visible from a longer range");
|
||||
if (CVarGetInteger("gDisableDrawDistance", 0) == 1) {
|
||||
UIWidgets::Tooltip("Increases the range in which actors/objects are drawn");
|
||||
if (CVarGetInteger("gDisableDrawDistance", 1) > 1) {
|
||||
UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false);
|
||||
UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance");
|
||||
UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this "
|
||||
"will remove their draw distance");
|
||||
}
|
||||
UIWidgets::PaddedEnhancementCheckbox("Widescreen Actor Culling", "gEnhancements.WidescreenActorCulling",
|
||||
true, false);
|
||||
UIWidgets::Tooltip("Adjusts the horizontal culling plane to account for widescreen resolutions");
|
||||
UIWidgets::PaddedEnhancementCheckbox(
|
||||
"Cull Glitch Useful Actors", "gEnhancements.ExtendedCullingExcludeGlitchActors", true, false,
|
||||
!CVarGetInteger("gEnhancements.WidescreenActorCulling", 0) &&
|
||||
CVarGetInteger("gDisableDrawDistance", 1) <= 1,
|
||||
"Requires Actor Draw Distance to be increased or Widescreen Actor Culling enabled");
|
||||
UIWidgets::Tooltip(
|
||||
"Exclude actors that are useful for glitches from the extended culling ranges.\n"
|
||||
"Some actors may still draw in the extended ranges, but will not \"update\" so that certain "
|
||||
"glitches that leverage the original culling requirements will still work.\n"
|
||||
"\n"
|
||||
"The following actors are excluded:\n"
|
||||
"- White clothed Gerudos\n"
|
||||
"- King Zora\n"
|
||||
"- Gossip Stones\n"
|
||||
"- Boulders\n"
|
||||
"- Blue Warps\n"
|
||||
"- Darunia\n"
|
||||
"- Gold Skulltulas");
|
||||
UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gLowResMode", true, false);
|
||||
UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", "gDrawLineupTick", true, false);
|
||||
@@ -1610,6 +1636,10 @@ void DrawRandomizerMenu() {
|
||||
}
|
||||
}
|
||||
|
||||
void SohMenuBar::InitElement() {
|
||||
UpdateWindowBackendObjects();
|
||||
}
|
||||
|
||||
void SohMenuBar::DrawElement() {
|
||||
if (ImGui::BeginMenuBar()) {
|
||||
DrawMenuBarIcon();
|
||||
|
||||
@@ -10,7 +10,7 @@ class SohMenuBar : public LUS::GuiMenuBar {
|
||||
using LUS::GuiMenuBar::GuiMenuBar;
|
||||
protected:
|
||||
void DrawElement() override;
|
||||
void InitElement() override {};
|
||||
void InitElement() override;
|
||||
void UpdateElement() override {};
|
||||
};
|
||||
} // namespace SohGui
|
||||
@@ -21,7 +21,7 @@ namespace UIWidgets {
|
||||
// Automatically adds newlines to break up text longer than a specified number of characters
|
||||
// Manually included newlines will still be respected and reset the line length
|
||||
// If line is midword when it hits the limit, text should break at the last encountered space
|
||||
char* WrappedText(const char* text, unsigned int charactersPerLine) {
|
||||
std::string WrappedText(const char* text, unsigned int charactersPerLine) {
|
||||
std::string newText(text);
|
||||
const size_t tipLength = newText.length();
|
||||
int lastSpace = -1;
|
||||
@@ -43,17 +43,17 @@ namespace UIWidgets {
|
||||
currentLineLength++;
|
||||
}
|
||||
|
||||
return strdup(newText.c_str());
|
||||
return newText;
|
||||
}
|
||||
|
||||
char* WrappedText(const std::string& text, unsigned int charactersPerLine) {
|
||||
std::string WrappedText(const std::string& text, unsigned int charactersPerLine) {
|
||||
return WrappedText(text.c_str(), charactersPerLine);
|
||||
}
|
||||
|
||||
void SetLastItemHoverText(const std::string& text) {
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("%s", WrappedText(text, 60));
|
||||
ImGui::Text("%s", WrappedText(text, 60).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ namespace UIWidgets {
|
||||
void SetLastItemHoverText(const char* text) {
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("%s", WrappedText(text, 60));
|
||||
ImGui::Text("%s", WrappedText(text, 60).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ namespace UIWidgets {
|
||||
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("%s", WrappedText(text, 60));
|
||||
ImGui::Text("%s", WrappedText(text, 60).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ namespace UIWidgets {
|
||||
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("%s", WrappedText(text, 60));
|
||||
ImGui::Text("%s", WrappedText(text, 60).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ namespace UIWidgets {
|
||||
|
||||
void Tooltip(const char* text) {
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("%s", WrappedText(text));
|
||||
ImGui::SetTooltip("%s", WrappedText(text).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ namespace UIWidgets {
|
||||
constexpr float sliderButtonWidth = 30.0f;
|
||||
#endif
|
||||
|
||||
char* WrappedText(const char* text, unsigned int charactersPerLine = 60);
|
||||
char* WrappedText(const std::string& text, unsigned int charactersPerLine);
|
||||
std::string WrappedText(const char* text, unsigned int charactersPerLine = 60);
|
||||
std::string WrappedText(const std::string& text, unsigned int charactersPerLine);
|
||||
|
||||
void SetLastItemHoverText(const std::string& text);
|
||||
void SetLastItemHoverText(const char* text);
|
||||
|
||||
+7
-1
@@ -99,8 +99,14 @@ void aClearBufferImpl(uint16_t addr, int nbytes) {
|
||||
memset(BUF_U8(addr), 0, nbytes);
|
||||
}
|
||||
|
||||
void aLoadBufferImpl(const void *source_addr, uint16_t dest_addr, uint16_t nbytes) {
|
||||
void aLoadBufferImpl(const void* source_addr, uint16_t dest_addr, uint16_t nbytes) {
|
||||
#if __SANITIZE_ADDRESS__
|
||||
for (size_t i = 0; i < ROUND_DOWN_16(nbytes); i++) {
|
||||
BUF_U8(dest_addr)[i] = ((const unsigned char*)source_addr)[i];
|
||||
}
|
||||
#else
|
||||
memcpy(BUF_U8(dest_addr), source_addr, ROUND_DOWN_16(nbytes));
|
||||
#endif
|
||||
}
|
||||
|
||||
void aSaveBufferImpl(uint16_t source_addr, int16_t *dest_addr, uint16_t nbytes) {
|
||||
|
||||
@@ -65,12 +65,11 @@ void SkeletonPatcher::ClearSkeletons()
|
||||
}
|
||||
|
||||
void SkeletonPatcher::UpdateSkeletons() {
|
||||
bool isHD = CVarGetInteger("gAltAssets", 0);
|
||||
auto resourceMgr = LUS::Context::GetInstance()->GetResourceManager();
|
||||
bool isHD = resourceMgr->IsAltAssetsEnabled();
|
||||
for (auto skel : skeletons) {
|
||||
Skeleton* newSkel =
|
||||
(Skeleton*)LUS::Context::GetInstance()->GetResourceManager()
|
||||
->LoadResource((isHD ? LUS::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true)
|
||||
.get();
|
||||
(Skeleton*)resourceMgr->LoadResource((isHD ? LUS::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true).get();
|
||||
|
||||
if (newSkel != nullptr) {
|
||||
skel.skelAnime->skeleton = newSkel->skeletonData.skeletonHeader.segment;
|
||||
|
||||
+1
-1
@@ -467,7 +467,7 @@ void GameState_Destroy(GameState* gameState) {
|
||||
// Performing clear skeletons before unload resources fixes an actor heap corruption crash due to the skeleton patching system.
|
||||
ResourceMgr_ClearSkeletons();
|
||||
|
||||
if (CVarGetInteger("gAltAssets", 0)) {
|
||||
if (ResourceMgr_IsAltAssetsEnabled()) {
|
||||
ResourceUnloadDirectory("alt/*");
|
||||
gfx_texture_cache_clear();
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ static const ALIGN_ASSET(2) char rGfxPrintFontDataAlt[] = drGfxPrintFontDataAlt;
|
||||
// https://github.com/HarbourMasters/Shipwright/issues/2762
|
||||
typedef enum {hardcoded, otrDefault, otrAlt} font_texture_t;
|
||||
font_texture_t GfxPrint_TextureToUse() {
|
||||
if (CVarGetInteger("gAltAssets", 0) && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) {
|
||||
if (ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) {
|
||||
// If we have alt assets enabled, and we have alt prefixed font texture, use that
|
||||
return otrAlt;
|
||||
} else if (ResourceMgr_FileExists(rGfxPrintFontData)) {
|
||||
|
||||
+106
-31
@@ -1208,19 +1208,11 @@ void Actor_Init(Actor* actor, PlayState* play) {
|
||||
actor->uncullZoneForward = 1000.0f;
|
||||
actor->uncullZoneScale = 350.0f;
|
||||
actor->uncullZoneDownward = 700.0f;
|
||||
if (CVarGetInteger("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room
|
||||
&& actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence
|
||||
&& actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning
|
||||
&& (play->sceneNum != SCENE_DODONGOS_CAVERN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room
|
||||
actor->uncullZoneForward = 32767.0f;
|
||||
actor->uncullZoneScale = 32767.0f;
|
||||
actor->uncullZoneDownward = 32767.0f;
|
||||
}
|
||||
CollisionCheck_InitInfo(&actor->colChkInfo);
|
||||
actor->floorBgId = BGCHECK_SCENE;
|
||||
ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f);
|
||||
if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
|
||||
//Actor_SetObjectDependency(play, actor);
|
||||
Actor_SetObjectDependency(play, actor);
|
||||
actor->init(actor, play);
|
||||
actor->init = NULL;
|
||||
|
||||
@@ -2548,6 +2540,13 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
|
||||
Actor_SetObjectDependency(play, actor);
|
||||
actor->init(actor, play);
|
||||
actor->init = NULL;
|
||||
|
||||
GameInteractor_ExecuteOnActorInit(actor);
|
||||
|
||||
// For enemy health bar we need to know the max health during init
|
||||
if (actor->category == ACTORCAT_ENEMY) {
|
||||
actor->maximumHealth = actor->colChkInfo.health;
|
||||
}
|
||||
}
|
||||
actor = actor->next;
|
||||
} else if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
|
||||
@@ -2850,34 +2849,93 @@ s32 func_800314B0(PlayState* play, Actor* actor) {
|
||||
s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) {
|
||||
f32 var;
|
||||
|
||||
if (CVarGetInteger("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room
|
||||
&& actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence
|
||||
&& actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning
|
||||
&& (play->sceneNum != SCENE_DODONGOS_CAVERN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((arg2->z > -actor->uncullZoneScale) && (arg2->z < (actor->uncullZoneForward + actor->uncullZoneScale))) {
|
||||
var = (arg3 < 1.0f) ? 1.0f : 1.0f / arg3;
|
||||
|
||||
// #region SoH [Widescreen support]
|
||||
// Doors will cull quite noticeably on wider screens. For these actors the zone is increased
|
||||
f32 limit = 1.0f;
|
||||
if (((actor->id == ACTOR_EN_DOOR) || (actor->id == ACTOR_DOOR_SHUTTER)) && CVarGetInteger("gIncreaseDoorUncullZones", 1)) {
|
||||
limit = 2.0f;
|
||||
}
|
||||
|
||||
if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < limit) &&
|
||||
(((arg2->y + actor->uncullZoneDownward) * var) > -limit) &&
|
||||
(((arg2->y - actor->uncullZoneScale) * var) < limit)) {
|
||||
if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < 1.0f) &&
|
||||
(((arg2->y + actor->uncullZoneDownward) * var) > -1.0f) &&
|
||||
(((arg2->y - actor->uncullZoneScale) * var) < 1.0f)) {
|
||||
return true;
|
||||
}
|
||||
// #endregion
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// #region SOH [Enhancements] Allows us to increase the draw and update distance independently,
|
||||
// mostly a modified version of the function above and additional tweaks for some specfic actors
|
||||
s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw,
|
||||
bool* shouldUpdate) {
|
||||
f32 clampedProjectedW;
|
||||
|
||||
// Check if the actor passes its original/vanilla culling requirements
|
||||
if (func_800314D4(play, actor, projectedPos, projectedW)) {
|
||||
*shouldUpdate = true;
|
||||
*shouldDraw = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip cutscne actors that depend on culling to hide from camera pans
|
||||
if (actor->id == ACTOR_EN_VIEWER) {
|
||||
return false;
|
||||
}
|
||||
|
||||
s32 multiplier = CVarGetInteger("gDisableDrawDistance", 1);
|
||||
multiplier = MAX(multiplier, 1);
|
||||
|
||||
// Some actors have a really short forward value, so we need to add to it before the multiplier to increase the
|
||||
// final strength of the forward culling
|
||||
f32 adder = (actor->uncullZoneForward < 500) ? 1000.0f : 0.0f;
|
||||
|
||||
if ((projectedPos->z > -actor->uncullZoneScale) &&
|
||||
(projectedPos->z < (((actor->uncullZoneForward + adder) * multiplier) + actor->uncullZoneScale))) {
|
||||
clampedProjectedW = (projectedW < 1.0f) ? 1.0f : 1.0f / projectedW;
|
||||
|
||||
f32 ratioAdjusted = 1.0f;
|
||||
|
||||
if (CVarGetInteger("gEnhancements.WidescreenActorCulling", 0)) {
|
||||
f32 originalAspectRatio = 4.0f / 3.0f;
|
||||
f32 currentAspectRatio = OTRGetAspectRatio();
|
||||
ratioAdjusted = MAX(currentAspectRatio / originalAspectRatio, 1.0f);
|
||||
}
|
||||
|
||||
if ((((fabsf(projectedPos->x) - actor->uncullZoneScale) * (clampedProjectedW / ratioAdjusted)) < 1.0f) &&
|
||||
(((projectedPos->y + actor->uncullZoneDownward) * clampedProjectedW) > -1.0f) &&
|
||||
(((projectedPos->y - actor->uncullZoneScale) * clampedProjectedW) < 1.0f)) {
|
||||
|
||||
if (CVarGetInteger("gEnhancements.ExtendedCullingExcludeGlitchActors", 0)) {
|
||||
// These actors are safe to draw without impacting glitches
|
||||
if ((actor->id == ACTOR_OBJ_BOMBIWA || actor->id == ACTOR_OBJ_HAMISHI ||
|
||||
actor->id == ACTOR_EN_ISHI) || // Boulders (hookshot through collision)
|
||||
actor->id == ACTOR_EN_GS || // Gossip stones (text delay)
|
||||
actor->id == ACTOR_EN_GE1 || // White gerudos (gate clip/archery room transition)
|
||||
actor->id == ACTOR_EN_KZ || // King Zora (unfreeze glitch)
|
||||
actor->id == ACTOR_EN_DU || // Darunia (Fire temple BK skip)
|
||||
actor->id == ACTOR_DOOR_WARP1 // Blue warps (wrong warps)
|
||||
) {
|
||||
*shouldDraw = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip these actors entirely as their draw funcs impacts glitches
|
||||
if ((actor->id == ACTOR_EN_SW &&
|
||||
(((actor->params & 0xE000) >> 0xD) == 1 ||
|
||||
((actor->params & 0xE000) >> 0xD) == 2)) // Gold Skulltulas (hitbox at 0,0)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*shouldDraw = true;
|
||||
*shouldUpdate = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// #endregion
|
||||
|
||||
void func_800315AC(PlayState* play, ActorContext* actorCtx) {
|
||||
s32 invisibleActorCounter;
|
||||
Actor* invisibleActors[INVISIBLE_ACTOR_MAX];
|
||||
@@ -2913,18 +2971,35 @@ void func_800315AC(PlayState* play, ActorContext* actorCtx) {
|
||||
}
|
||||
}
|
||||
|
||||
// #region SOH [Enhancement] Extended culling updates
|
||||
bool shipShouldDraw = false;
|
||||
bool shipShouldUpdate = false;
|
||||
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(70) == 0)) {
|
||||
if (func_800314B0(play, actor)) {
|
||||
actor->flags |= ACTOR_FLAG_ACTIVE;
|
||||
if (CVarGetInteger("gDisableDrawDistance", 1) > 1 ||
|
||||
CVarGetInteger("gEnhancements.WidescreenActorCulling", 0)) {
|
||||
Ship_CalcShouldDrawAndUpdate(play, actor, &actor->projectedPos, actor->projectedW, &shipShouldDraw,
|
||||
&shipShouldUpdate);
|
||||
|
||||
if (shipShouldUpdate) {
|
||||
actor->flags |= ACTOR_FLAG_ACTIVE;
|
||||
} else {
|
||||
actor->flags &= ~ACTOR_FLAG_ACTIVE;
|
||||
}
|
||||
} else {
|
||||
actor->flags &= ~ACTOR_FLAG_ACTIVE;
|
||||
if (func_800314B0(play, actor)) {
|
||||
actor->flags |= ACTOR_FLAG_ACTIVE;
|
||||
} else {
|
||||
actor->flags &= ~ACTOR_FLAG_ACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actor->isDrawn = false;
|
||||
|
||||
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(71) == 0)) {
|
||||
if ((actor->init == NULL) && (actor->draw != NULL) && (actor->flags & (ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_ACTIVE))) {
|
||||
if ((actor->init == NULL) && (actor->draw != NULL) &&
|
||||
((actor->flags & (ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_ACTIVE)) || shipShouldDraw)) {
|
||||
// #endregion
|
||||
if ((actor->flags & ACTOR_FLAG_LENS) &&
|
||||
((play->roomCtx.curRoom.lensMode == LENS_MODE_HIDE_ACTORS) ||
|
||||
play->actorCtx.lensActive || (actor->room != play->roomCtx.curRoom.num))) {
|
||||
|
||||
@@ -398,7 +398,7 @@ s32 CollisionPoly_LineVsPoly(CollisionPoly* poly, Vec3s* vtxList, Vec3f* posA, V
|
||||
(poly->normal.x * posB->x + poly->normal.y * posB->y + poly->normal.z * posB->z) * COLPOLY_NORMAL_FRAC +
|
||||
plane.originDist;
|
||||
|
||||
#ifdef __WIIU__
|
||||
#if defined(__SWITCH__) || defined(__WIIU__)
|
||||
// on some platforms this ends up as very small numbers due to rounding issues
|
||||
if (IS_ZERO(planeDistA)) {
|
||||
planeDistA = 0.0f;
|
||||
|
||||
@@ -1115,7 +1115,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) {
|
||||
}
|
||||
}
|
||||
if (msgCtx->textDelayTimer == 0) {
|
||||
msgCtx->textDrawPos = i + CVarGetInteger("gTextSpeed", 2);
|
||||
msgCtx->textDrawPos = i + CVarGetInteger("gTextSpeed", 1);
|
||||
msgCtx->textDelayTimer = msgCtx->textDelay;
|
||||
} else {
|
||||
msgCtx->textDelayTimer--;
|
||||
|
||||
+178
-100
@@ -1436,64 +1436,62 @@ Gfx* Gfx_TextureI8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 te
|
||||
return displayListHead;
|
||||
}
|
||||
|
||||
void Inventory_SwapAgeEquipment(void) {
|
||||
void Rando_Inventory_SwapAgeEquipment(void) {
|
||||
s16 i;
|
||||
u16 shieldEquipValue;
|
||||
|
||||
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
|
||||
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
if (i != 0) {
|
||||
gSaveContext.childEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i];
|
||||
gSaveContext.childEquips.buttonItems[i] =
|
||||
gSaveContext.equips.buttonItems[i];
|
||||
} else {
|
||||
gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI;
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
gSaveContext.childEquips.cButtonSlots[i - 1] = gSaveContext.equips.cButtonSlots[i - 1];
|
||||
gSaveContext.childEquips.cButtonSlots[i - 1] =
|
||||
gSaveContext.equips.cButtonSlots[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
// When becoming adult, remove swordless flag since we'll get master sword
|
||||
// (Unless Master Sword is shuffled)
|
||||
// Only in rando to keep swordless link bugs in vanilla
|
||||
if (IS_RANDO && !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) {
|
||||
Flags_UnsetInfTable(INFTABLE_SWORDLESS);
|
||||
}
|
||||
|
||||
gSaveContext.childEquips.equipment = gSaveContext.equips.equipment;
|
||||
|
||||
if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE && !(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && gSaveContext.adultEquips.equipment)) {
|
||||
if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) {
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER;
|
||||
} else {
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_NONE;
|
||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
||||
}
|
||||
// When becoming adult, remove swordless flag since we'll get master sword
|
||||
// This gets set back appropriately later in the case of master sword shuffle
|
||||
Flags_UnsetInfTable(INFTABLE_SWORDLESS);
|
||||
|
||||
// This section sets up the equipment on the first time going adult.
|
||||
// On master sword shuffle the check for the B button is insufficient, and so checking the equipment is completely zero-ed is needed
|
||||
// (Could just always use `gSaveContext.adultEquips.equipment == 0` for rando?)
|
||||
if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE && ((IS_RANDO && !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) || (gSaveContext.adultEquips.equipment == 0))) {
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER;
|
||||
|
||||
if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) {
|
||||
gSaveContext.equips.buttonItems[1] = ITEM_NUT;
|
||||
gSaveContext.equips.cButtonSlots[0] = SLOT_NUT;
|
||||
} else {
|
||||
gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = ITEM_NONE;
|
||||
gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] =
|
||||
ITEM_NONE;
|
||||
}
|
||||
|
||||
gSaveContext.equips.buttonItems[2] = ITEM_BOMB;
|
||||
gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA];
|
||||
gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB;
|
||||
gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA;
|
||||
|
||||
gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) |
|
||||
(EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) |
|
||||
(EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) |
|
||||
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
||||
(EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) |
|
||||
(EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) |
|
||||
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
||||
|
||||
// In Master Sword Shuffle we want to override the equip of the master sword from the vanilla code
|
||||
// First check we have the Master sword in our inventory, and if not, then unequip
|
||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
|
||||
gSaveContext.equips.buttonItems[0] == ITEM_NONE) {
|
||||
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) {
|
||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_NONE;
|
||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
||||
}
|
||||
|
||||
// Set the dpad to nothing
|
||||
gSaveContext.equips.buttonItems[4] = ITEM_NONE;
|
||||
gSaveContext.equips.buttonItems[5] = ITEM_NONE;
|
||||
@@ -1505,25 +1503,25 @@ void Inventory_SwapAgeEquipment(void) {
|
||||
gSaveContext.equips.cButtonSlots[6] = SLOT_NONE;
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
gSaveContext.equips.buttonItems[i] = gSaveContext.adultEquips.buttonItems[i];
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.adultEquips.buttonItems[i];
|
||||
|
||||
if (i != 0) {
|
||||
gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.adultEquips.cButtonSlots[i - 1];
|
||||
gSaveContext.equips.cButtonSlots[i - 1] =
|
||||
gSaveContext.adultEquips.cButtonSlots[i - 1];
|
||||
}
|
||||
|
||||
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_POE)) ||
|
||||
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
|
||||
osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]);
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||
}
|
||||
}
|
||||
|
||||
// In Rando, when switching to adult for the second+ time, if a sword was not previously
|
||||
// equiped in MS shuffle, then we need to set the swordless flag again
|
||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
|
||||
// In Master Sword Shuffle we want to set the swordless flag if no item is on the B button
|
||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
|
||||
gSaveContext.equips.buttonItems[0] == ITEM_NONE) {
|
||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
||||
}
|
||||
@@ -1531,90 +1529,43 @@ void Inventory_SwapAgeEquipment(void) {
|
||||
gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment;
|
||||
}
|
||||
} else {
|
||||
// When becoming child, set swordless flag if player doesn't have kokiri sword
|
||||
// Only in rando to keep swordless link bugs in vanilla
|
||||
if (IS_RANDO && CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) {
|
||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
||||
}
|
||||
|
||||
// When using enhancements, set swordless flag if player doesn't have kokiri sword or hasn't equipped a sword yet.
|
||||
// Then set the child equips button items to item none to ensure kokiri sword is not equipped
|
||||
if ((CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) && (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) {
|
||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
||||
gSaveContext.childEquips.buttonItems[0] = ITEM_NONE;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i];
|
||||
|
||||
if (i != 0) {
|
||||
gSaveContext.adultEquips.cButtonSlots[i - 1] = gSaveContext.equips.cButtonSlots[i - 1];
|
||||
gSaveContext.adultEquips.cButtonSlots[i - 1] =
|
||||
gSaveContext.equips.cButtonSlots[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment;
|
||||
// Switching age using enhancements separated out to make vanilla flow clear
|
||||
if (CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) {
|
||||
|
||||
if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) {
|
||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i];
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.childEquips.buttonItems[i];
|
||||
|
||||
if (i != 0) {
|
||||
gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.childEquips.cButtonSlots[i - 1];
|
||||
gSaveContext.equips.cButtonSlots[i - 1] =
|
||||
gSaveContext.childEquips.cButtonSlots[i - 1];
|
||||
}
|
||||
|
||||
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_POE)) ||
|
||||
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
|
||||
osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]);
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||
}
|
||||
}
|
||||
|
||||
gSaveContext.equips.equipment = gSaveContext.childEquips.equipment;
|
||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||
// Equips kokiri sword in the inventory screen only if kokiri sword exists in inventory and a sword has been equipped already
|
||||
if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) && !Flags_GetInfTable(INFTABLE_SWORDLESS)) {
|
||||
gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4);
|
||||
}
|
||||
} else if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) {
|
||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i];
|
||||
|
||||
if (i != 0) {
|
||||
gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.childEquips.cButtonSlots[i - 1];
|
||||
}
|
||||
|
||||
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_POE)) ||
|
||||
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
|
||||
osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]);
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||
}
|
||||
}
|
||||
|
||||
// In Rando, when switching to child from a swordless adult, and child Link previously had a
|
||||
// sword equiped, then we need to unset the swordless flag to match
|
||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
|
||||
gSaveContext.equips.buttonItems[0] != ITEM_NONE) {
|
||||
Flags_UnsetInfTable(INFTABLE_SWORDLESS);
|
||||
}
|
||||
|
||||
gSaveContext.equips.equipment = gSaveContext.childEquips.equipment;
|
||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||
gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4);
|
||||
} else if (IS_RANDO && Randomizer_GetSettingValue(RSK_STARTING_AGE) == RO_AGE_ADULT) {
|
||||
/*If in rando and starting age is adult, childEquips is not initialized and buttonItems[0]
|
||||
will be ITEM_NONE. When changing age from adult -> child, reset equips to "default"
|
||||
(only kokiri tunic/boots equipped, no sword, no C-button items, no D-Pad items).
|
||||
When becoming child, set swordless flag if player doesn't have kokiri sword
|
||||
Only in rando to keep swordless link bugs in vanilla*/
|
||||
if (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) {
|
||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
||||
}
|
||||
}
|
||||
// In Rando we need an extra case to handle starting as adult. We can use the fact that the childEquips will be uninitialised (i.e. 0) at this point
|
||||
else if (gSaveContext.childEquips.equipment == 0) {
|
||||
|
||||
//zero out items
|
||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
@@ -1629,20 +1580,147 @@ void Inventory_SwapAgeEquipment(void) {
|
||||
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
||||
}
|
||||
|
||||
if ((CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) &&
|
||||
(gSaveContext.equips.buttonItems[0] == ITEM_NONE)) {
|
||||
// When becoming child in rando, set swordless flag and clear B button if player doesn't have kokiri sword
|
||||
// Otherwise, equip sword and unset flag
|
||||
if (!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI)) {
|
||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_NONE;
|
||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
||||
if (gSaveContext.childEquips.equipment == 0) {
|
||||
// force equip kokiri tunic and boots in scenario gSaveContext.childEquips.equipment is uninitialized
|
||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||
gSaveContext.equips.equipment |= (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) |
|
||||
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
||||
}
|
||||
} else {
|
||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||
gSaveContext.equips.equipment |= (EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4));
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KOKIRI;
|
||||
Flags_UnsetInfTable(INFTABLE_SWORDLESS);
|
||||
}
|
||||
}
|
||||
CVarSetInteger("gSwitchTimeline", 0);
|
||||
|
||||
shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment;
|
||||
if (shieldEquipValue != 0) {
|
||||
if (shieldEquipValue) {
|
||||
shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD];
|
||||
if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) {
|
||||
gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory_SwapAgeEquipment(void) {
|
||||
s16 i;
|
||||
u16 shieldEquipValue;
|
||||
|
||||
// Mod Enhancments can utilise the rando flow path
|
||||
if (IS_RANDO || CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) {
|
||||
Rando_Inventory_SwapAgeEquipment();
|
||||
CVarSetInteger("gSwitchTimeline", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
|
||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
if (i != 0) {
|
||||
gSaveContext.childEquips.buttonItems[i] =
|
||||
gSaveContext.equips.buttonItems[i];
|
||||
} else {
|
||||
gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI;
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
gSaveContext.childEquips.cButtonSlots[i - 1] =
|
||||
gSaveContext.equips.cButtonSlots[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
gSaveContext.childEquips.equipment = gSaveContext.equips.equipment;
|
||||
|
||||
if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE) {
|
||||
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER;
|
||||
|
||||
if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) {
|
||||
gSaveContext.equips.buttonItems[1] = ITEM_NUT;
|
||||
gSaveContext.equips.cButtonSlots[0] = SLOT_NUT;
|
||||
} else {
|
||||
gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] =
|
||||
ITEM_NONE;
|
||||
}
|
||||
|
||||
gSaveContext.equips.buttonItems[2] = ITEM_BOMB;
|
||||
gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA];
|
||||
gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB;
|
||||
gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA;
|
||||
gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) |
|
||||
(EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) |
|
||||
(EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) |
|
||||
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
||||
// Set the dpad to nothing
|
||||
gSaveContext.equips.buttonItems[4] = ITEM_NONE;
|
||||
gSaveContext.equips.buttonItems[5] = ITEM_NONE;
|
||||
gSaveContext.equips.buttonItems[6] = ITEM_NONE;
|
||||
gSaveContext.equips.buttonItems[7] = ITEM_NONE;
|
||||
gSaveContext.equips.cButtonSlots[3] = SLOT_NONE;
|
||||
gSaveContext.equips.cButtonSlots[4] = SLOT_NONE;
|
||||
gSaveContext.equips.cButtonSlots[5] = SLOT_NONE;
|
||||
gSaveContext.equips.cButtonSlots[6] = SLOT_NONE;
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.adultEquips.buttonItems[i];
|
||||
|
||||
if (i != 0) {
|
||||
gSaveContext.equips.cButtonSlots[i - 1] =
|
||||
gSaveContext.adultEquips.cButtonSlots[i - 1];
|
||||
}
|
||||
|
||||
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_POE)) ||
|
||||
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
|
||||
osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]);
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||
}
|
||||
}
|
||||
|
||||
gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i];
|
||||
|
||||
if (i != 0) {
|
||||
gSaveContext.adultEquips.cButtonSlots[i - 1] =
|
||||
gSaveContext.equips.cButtonSlots[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment;
|
||||
|
||||
if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) {
|
||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.childEquips.buttonItems[i];
|
||||
|
||||
if (i != 0) {
|
||||
gSaveContext.equips.cButtonSlots[i - 1] =
|
||||
gSaveContext.childEquips.cButtonSlots[i - 1];
|
||||
}
|
||||
|
||||
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_POE)) ||
|
||||
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
|
||||
osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]);
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||
}
|
||||
}
|
||||
|
||||
gSaveContext.equips.equipment = gSaveContext.childEquips.equipment;
|
||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||
gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4);
|
||||
}
|
||||
}
|
||||
|
||||
shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment;
|
||||
if (shieldEquipValue) {
|
||||
shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD];
|
||||
if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) {
|
||||
gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD];
|
||||
|
||||
@@ -2307,10 +2307,12 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f*
|
||||
}
|
||||
|
||||
srcTable = ResourceMgr_LoadArrayByNameAsVec3s(srcTable);
|
||||
Vec3s* ogSrcTable = srcTable;
|
||||
destTable = skelAnime->jointTable;
|
||||
for (i = 0; i < skelAnime->limbCount; i++) {
|
||||
*destTable++ = *srcTable++;
|
||||
}
|
||||
free(ogSrcTable);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -78,6 +78,10 @@ void SkelAnime_DrawLod(PlayState* play, void** skeleton, Vec3s* jointTable,
|
||||
Vec3f pos;
|
||||
Vec3s rot;
|
||||
|
||||
if (CVarGetInteger("gDisableLOD", 0)) {
|
||||
lod = 0;
|
||||
}
|
||||
|
||||
if (skeleton == NULL) {
|
||||
osSyncPrintf(VT_FGCOL(RED));
|
||||
osSyncPrintf("Si2_Lod_draw():skelがNULLです。\n"); // "skel is NULL."
|
||||
@@ -144,6 +148,8 @@ void SkelAnime_DrawFlexLimbLod(PlayState* play, s32 limbIndex, void** skeleton,
|
||||
|
||||
newDList = limbDList = limb->dLists[lod];
|
||||
|
||||
play->flexLimbOverrideMTX = mtx;
|
||||
|
||||
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &newDList, &pos, &rot, arg)) {
|
||||
Matrix_TranslateRotateZYX(&pos, &rot);
|
||||
if (newDList != NULL) {
|
||||
@@ -191,6 +197,10 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable,
|
||||
Vec3s rot;
|
||||
Mtx* mtx = Graph_Alloc(play->state.gfxCtx, dListCount * sizeof(Mtx));
|
||||
|
||||
if (CVarGetInteger("gDisableLOD", 0)) {
|
||||
lod = 0;
|
||||
}
|
||||
|
||||
if (skeleton == NULL) {
|
||||
osSyncPrintf(VT_FGCOL(RED));
|
||||
osSyncPrintf("Si2_Lod_draw_SV():skelがNULLです。\n"); // "skel is NULL."
|
||||
@@ -212,6 +222,8 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable,
|
||||
|
||||
newDList = limbDList = rootLimb->dLists[lod];
|
||||
|
||||
play->flexLimbOverrideMTX = &mtx;
|
||||
|
||||
if ((overrideLimbDraw == 0) || !overrideLimbDraw(play, 1, &newDList, &pos, &rot, arg)) {
|
||||
Matrix_TranslateRotateZYX(&pos, &rot);
|
||||
if (newDList != NULL) {
|
||||
@@ -298,6 +310,20 @@ void SkelAnime_DrawSkeletonOpa(PlayState* play, SkelAnime* skelAnime, OverrideLi
|
||||
}
|
||||
}
|
||||
|
||||
Gfx* SkelAnime_DrawSkeleton2(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw,
|
||||
PostLimbDrawOpa postLimbDraw, void* arg, Gfx* gfx)
|
||||
{
|
||||
if (skelAnime->skeletonHeader->skeletonType == SKELANIME_TYPE_NORMAL) {
|
||||
return SkelAnime_Draw(play, skelAnime->skeleton, skelAnime->jointTable, overrideLimbDraw, postLimbDraw, arg, gfx);
|
||||
} else if (skelAnime->skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||
FlexSkeletonHeader* flexHeader = (FlexSkeletonHeader*)skelAnime->skeletonHeader;
|
||||
return SkelAnime_DrawFlex(play, skelAnime->skeleton, skelAnime->jointTable, flexHeader->dListCount,
|
||||
overrideLimbDraw, postLimbDraw, arg, gfx);
|
||||
}
|
||||
|
||||
return gfx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw all limbs of type `StandardLimb` in a given skeleton to the polyOpa buffer
|
||||
*/
|
||||
@@ -375,6 +401,8 @@ void SkelAnime_DrawFlexLimbOpa(PlayState* play, s32 limbIndex, void** skeleton,
|
||||
|
||||
newDList = limbDList = limb->dList;
|
||||
|
||||
play->flexLimbOverrideMTX = limbMatricies;
|
||||
|
||||
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &newDList, &pos, &rot, arg)) {
|
||||
Matrix_TranslateRotateZYX(&pos, &rot);
|
||||
if (newDList != NULL) {
|
||||
|
||||
@@ -1288,6 +1288,10 @@ block_1:
|
||||
if (*dList != NULL) {
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
|
||||
if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||
MATRIX_TOMTX(*play->flexLimbOverrideMTX);
|
||||
}
|
||||
|
||||
mtxScaleZ = 1.0f;
|
||||
mtxScaleY = 1.0f;
|
||||
|
||||
@@ -1308,11 +1312,20 @@ block_1:
|
||||
Matrix_RotateX(-(this->unk_25C[limbIndex] * 0.115f), MTXMODE_APPLY);
|
||||
}
|
||||
|
||||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||
gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD);
|
||||
} else {
|
||||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
gSPDisplayList(POLY_OPA_DISP++, *dList);
|
||||
Matrix_Pop();
|
||||
|
||||
if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||
(*play->flexLimbOverrideMTX)++;
|
||||
}
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
{ s32 pad; } // Required to match
|
||||
|
||||
@@ -2015,12 +2015,26 @@ s32 BossGoma_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f
|
||||
Matrix_TranslateRotateZYX(pos, rot);
|
||||
|
||||
if (*dList != NULL) {
|
||||
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||
MATRIX_TOMTX(*play->flexLimbOverrideMTX);
|
||||
}
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_Scale(this->eyeIrisScaleX, this->eyeIrisScaleY, 1.0f, MTXMODE_APPLY);
|
||||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||
gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD);
|
||||
} else {
|
||||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
gSPDisplayList(POLY_OPA_DISP++, *dList);
|
||||
Matrix_Pop();
|
||||
|
||||
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||
(*play->flexLimbOverrideMTX)++;
|
||||
}
|
||||
}
|
||||
|
||||
doNotDrawLimb = true;
|
||||
@@ -2034,14 +2048,28 @@ s32 BossGoma_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f
|
||||
Matrix_TranslateRotateZYX(pos, rot);
|
||||
|
||||
if (*dList != NULL) {
|
||||
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||
MATRIX_TOMTX(*play->flexLimbOverrideMTX);
|
||||
}
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_Scale(this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4],
|
||||
this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4],
|
||||
this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4], MTXMODE_APPLY);
|
||||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||
gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD);
|
||||
} else {
|
||||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
gSPDisplayList(POLY_OPA_DISP++, *dList);
|
||||
Matrix_Pop();
|
||||
|
||||
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||
(*play->flexLimbOverrideMTX)++;
|
||||
}
|
||||
}
|
||||
|
||||
doNotDrawLimb = true;
|
||||
|
||||
@@ -1055,7 +1055,7 @@ void DoorWarp1_DrawBlueCrystal(DoorWarp1* this, PlayState* play) {
|
||||
gDPSetPrimColor(POLY_XLU_DISP++, 0xFF, 0xFF, 200, 255, 255, (u8)this->crystalAlpha);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, (u8)this->crystalAlpha);
|
||||
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, NULL,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, NULL, NULL,
|
||||
&this->actor, POLY_XLU_DISP);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
@@ -1079,7 +1079,7 @@ void DoorWarp1_DrawPurpleCrystal(DoorWarp1* this, PlayState* play) {
|
||||
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)this->crystalAlpha);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 150, 0, 100, (u8)this->crystalAlpha);
|
||||
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, NULL,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, NULL, NULL,
|
||||
&this->actor, POLY_XLU_DISP);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
|
||||
@@ -768,7 +768,7 @@ void EnBili_Draw(Actor* thisx, PlayState* play) {
|
||||
gSPSegment(POLY_XLU_DISP++, 0x09, D_809C1700);
|
||||
}
|
||||
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnBili_OverrideLimbDraw, NULL, this, POLY_XLU_DISP);
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
|
||||
@@ -947,7 +947,7 @@ void EnBox_Draw(Actor* thisx, PlayState* play) {
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
|
||||
gSPSegment(POLY_OPA_DISP++, 0x08, EnBox_EmptyDList(play->state.gfxCtx));
|
||||
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
||||
POLY_OPA_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, NULL,
|
||||
POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, NULL,
|
||||
EnBox_PostLimbDraw, this, POLY_OPA_DISP);
|
||||
} else if (this->alpha != 0) {
|
||||
gDPPipeSync(POLY_XLU_DISP++);
|
||||
@@ -958,7 +958,7 @@ void EnBox_Draw(Actor* thisx, PlayState* play) {
|
||||
} else {
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08, func_809CA4A0(play->state.gfxCtx));
|
||||
}
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, NULL,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, NULL,
|
||||
EnBox_PostLimbDraw, this, POLY_XLU_DISP);
|
||||
}
|
||||
|
||||
|
||||
@@ -856,7 +856,7 @@ void EnBw_Draw(Actor* thisx, PlayState* play2) {
|
||||
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, this->color1.r, this->color1.g, this->color1.b, this->color1.a);
|
||||
gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]);
|
||||
POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnBw_OverrideLimbDraw, NULL, this, POLY_OPA_DISP);
|
||||
} else {
|
||||
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
||||
@@ -864,7 +864,7 @@ void EnBw_Draw(Actor* thisx, PlayState* play2) {
|
||||
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 0, 0, 0, this->color1.a);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, this->color1.r, this->color1.g, this->color1.b, this->color1.a);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08, &D_80116280[0]);
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnBw_OverrideLimbDraw, NULL, this, POLY_XLU_DISP);
|
||||
}
|
||||
|
||||
|
||||
@@ -708,14 +708,14 @@ void EnEiyer_Draw(Actor* thisx, PlayState* play) {
|
||||
gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]);
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
|
||||
|
||||
POLY_OPA_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable,
|
||||
POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime,
|
||||
EnEiyer_OverrideLimbDraw, NULL, this, POLY_OPA_DISP);
|
||||
} else {
|
||||
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08, D_80116280);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->actor.shape.shadowAlpha);
|
||||
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime,
|
||||
EnEiyer_OverrideLimbDraw, NULL, this, POLY_XLU_DISP);
|
||||
}
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
|
||||
@@ -1540,7 +1540,7 @@ void EnElf_Draw(Actor* thisx, PlayState* play) {
|
||||
gSPEndDisplayList(dListHead++);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, (u8)this->outerColor.r, (u8)this->outerColor.g, (u8)this->outerColor.b,
|
||||
(u8)(envAlpha * alphaScale));
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnElf_OverrideLimbDraw, NULL, this, POLY_XLU_DISP);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
|
||||
@@ -837,8 +837,9 @@ void EnFirefly_Draw(Actor* thisx, PlayState* play) {
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
|
||||
}
|
||||
|
||||
POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
EnFirefly_OverrideLimbDraw, EnFirefly_PostLimbDraw, &this->actor, POLY_OPA_DISP);
|
||||
POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnFirefly_OverrideLimbDraw, EnFirefly_PostLimbDraw,
|
||||
&this->actor, POLY_OPA_DISP);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
|
||||
@@ -854,7 +855,7 @@ void EnFirefly_DrawInvisible(Actor* thisx, PlayState* play) {
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, 255);
|
||||
}
|
||||
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnFirefly_OverrideLimbDraw, EnFirefly_PostLimbDraw, this, POLY_XLU_DISP);
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
|
||||
@@ -858,7 +858,7 @@ void EnPartner_Draw(Actor* thisx, PlayState* play) {
|
||||
gSPEndDisplayList(dListHead++);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, (u8)this->outerColor.r, (u8)this->outerColor.g, (u8)this->outerColor.b,
|
||||
(u8)(envAlpha * alphaScale));
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnPartner_OverrideLimbDraw, NULL, this, POLY_XLU_DISP);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
|
||||
@@ -267,7 +267,7 @@ void EnPoDesert_Draw(Actor* thisx, PlayState* play) {
|
||||
} else {
|
||||
gSPSegment(POLY_XLU_DISP++, 0x0C, D_80116280 + 2);
|
||||
}
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnPoDesert_OverrideLimbDraw, EnPoDesert_PostLimbDraw, &this->actor, POLY_XLU_DISP);
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
|
||||
@@ -944,15 +944,14 @@ void EnPoField_Draw(Actor* thisx, PlayState* play) {
|
||||
this->lightColor.a));
|
||||
gSPSegment(POLY_OPA_DISP++, 0x0C, D_80116280 + 2);
|
||||
POLY_OPA_DISP =
|
||||
SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnPoField_OverrideLimbDraw2, EnPoField_PostLimDraw2, &this->actor, POLY_OPA_DISP);
|
||||
} else {
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08,
|
||||
Gfx_EnvColor(play->state.gfxCtx, this->lightColor.r, this->lightColor.g, this->lightColor.b,
|
||||
this->lightColor.a));
|
||||
gSPSegment(POLY_XLU_DISP++, 0x0C, D_80116280);
|
||||
POLY_XLU_DISP =
|
||||
SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnPoField_OverrideLimbDraw2, EnPoField_PostLimDraw2, &this->actor, POLY_XLU_DISP);
|
||||
}
|
||||
gDPPipeSync(POLY_OPA_DISP++);
|
||||
|
||||
@@ -1373,14 +1373,12 @@ void EnPoSisters_Draw(Actor* thisx, PlayState* play) {
|
||||
if (this->unk_22E.a == 255 || this->unk_22E.a == 0) {
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, this->unk_22E.r, this->unk_22E.g, this->unk_22E.b, this->unk_22E.a);
|
||||
gSPSegment(POLY_OPA_DISP++, 0x09, D_80116280 + 2);
|
||||
POLY_OPA_DISP =
|
||||
SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
EnPoSisters_OverrideLimbDraw, EnPoSisters_PostLimbDraw, &this->actor, POLY_OPA_DISP);
|
||||
POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoSisters_OverrideLimbDraw,
|
||||
EnPoSisters_PostLimbDraw, &this->actor, POLY_OPA_DISP);
|
||||
} else {
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->unk_22E.a);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x09, D_80116280);
|
||||
POLY_XLU_DISP =
|
||||
SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnPoSisters_OverrideLimbDraw, EnPoSisters_PostLimbDraw, &this->actor, POLY_XLU_DISP);
|
||||
}
|
||||
if (!(this->unk_199 & 0x80)) {
|
||||
|
||||
@@ -1085,12 +1085,12 @@ void EnPoh_DrawRegular(Actor* thisx, PlayState* play) {
|
||||
if (this->lightColor.a == 255 || this->lightColor.a == 0) {
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, this->lightColor.r, this->lightColor.g, this->lightColor.b, this->lightColor.a);
|
||||
gSPSegment(POLY_OPA_DISP++, 0x08, D_80116280 + 2);
|
||||
POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnPoh_OverrideLimbDraw, EnPoh_PostLimbDraw, &this->actor, POLY_OPA_DISP);
|
||||
} else {
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->lightColor.a);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08, D_80116280);
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnPoh_OverrideLimbDraw, EnPoh_PostLimbDraw, &this->actor, POLY_XLU_DISP);
|
||||
}
|
||||
gDPPipeSync(POLY_OPA_DISP++);
|
||||
|
||||
@@ -814,7 +814,7 @@ void EnVali_Draw(Actor* thisx, PlayState* play) {
|
||||
|
||||
EnVali_DrawBody(this, play);
|
||||
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnVali_OverrideLimbDraw, EnVali_PostLimbDraw, this, POLY_XLU_DISP);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
|
||||
@@ -640,13 +640,13 @@ void EnWeiyer_Draw(Actor* thisx, PlayState* play) {
|
||||
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
||||
gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]);
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
|
||||
POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
EnWeiyer_OverrideLimbDraw, NULL, &this->actor, POLY_OPA_DISP);
|
||||
POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnWeiyer_OverrideLimbDraw, NULL, &this->actor,
|
||||
POLY_OPA_DISP);
|
||||
} else {
|
||||
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08, &D_80116280[0]);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->actor.shape.shadowAlpha);
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnWeiyer_OverrideLimbDraw, NULL, &this->actor, POLY_XLU_DISP);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,13 +101,18 @@ static f32 sSpawnSin;
|
||||
s32 EnWood02_SpawnZoneCheck(EnWood02* this, PlayState* play, Vec3f* pos) {
|
||||
f32 phi_f12;
|
||||
|
||||
if (CVarGetInteger("gDisableDrawDistance", 0) != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, pos, &this->actor.projectedPos,
|
||||
&this->actor.projectedW);
|
||||
|
||||
// #region SOH [Enhancement] Use the extended culling calculation
|
||||
if (CVarGetInteger("gDisableDrawDistance", 0) || CVarGetInteger("gEnhancements.WidescreenActorCulling", 0)) {
|
||||
bool shipShouldDraw = false;
|
||||
bool shipShouldUpdate = false;
|
||||
return Ship_CalcShouldDrawAndUpdate(play, &this->actor, &this->actor.projectedPos, this->actor.projectedW,
|
||||
&shipShouldDraw, &shipShouldUpdate);
|
||||
}
|
||||
// #endregion
|
||||
|
||||
phi_f12 = ((this->actor.projectedW == 0.0f) ? 1000.0f : fabsf(1.0f / this->actor.projectedW));
|
||||
|
||||
if ((-this->actor.uncullZoneScale < this->actor.projectedPos.z) &&
|
||||
|
||||
@@ -2252,7 +2252,7 @@ void EnZf_Draw(Actor* thisx, PlayState* play) {
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, this->alpha);
|
||||
gSPSegment(POLY_OPA_DISP++, 0x09, &D_80116280[2]);
|
||||
|
||||
POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnZf_OverrideLimbDraw, EnZf_PostLimbDraw, this, POLY_OPA_DISP);
|
||||
|
||||
if (this->iceTimer != 0) {
|
||||
@@ -2271,7 +2271,7 @@ void EnZf_Draw(Actor* thisx, PlayState* play) {
|
||||
gDPPipeSync(POLY_XLU_DISP++);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->alpha);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x09, &D_80116280[0]);
|
||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
||||
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||
EnZf_OverrideLimbDraw, EnZf_PostLimbDraw, this, POLY_XLU_DISP);
|
||||
}
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
|
||||
@@ -275,7 +275,12 @@ void ObjMure_InitialAction(ObjMure* this, PlayState* play) {
|
||||
}
|
||||
|
||||
void ObjMure_CulledState(ObjMure* this, PlayState* play) {
|
||||
if (fabsf(this->actor.projectedPos.z) < sZClip[this->type] || CVarGetInteger("gDisableDrawDistance", 0) != 0) {
|
||||
// #region SOH [Enhancements] Extended draw distance
|
||||
s32 distanceMultiplier = CVarGetInteger("gDisableDrawDistance", 1);
|
||||
distanceMultiplier = MAX(distanceMultiplier, 1);
|
||||
|
||||
if (fabsf(this->actor.projectedPos.z) < sZClip[this->type] * distanceMultiplier) {
|
||||
// #endregion
|
||||
this->actionFunc = ObjMure_ActiveState;
|
||||
this->actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED;
|
||||
ObjMure_SpawnActors(this, play);
|
||||
@@ -398,8 +403,13 @@ static ObjMureActionFunc sTypeGroupBehaviorFunc[] = {
|
||||
|
||||
void ObjMure_ActiveState(ObjMure* this, PlayState* play) {
|
||||
ObjMure_CheckChildren(this, play);
|
||||
if (sZClip[this->type] + 40.0f <= fabsf(this->actor.projectedPos.z) &&
|
||||
CVarGetInteger("gDisableDrawDistance", 1) != 0) {
|
||||
|
||||
// #region SOH [Enhancements] Extended draw distance
|
||||
s32 distanceMultiplier = CVarGetInteger("gDisableDrawDistance", 1);
|
||||
distanceMultiplier = MAX(distanceMultiplier, 1);
|
||||
|
||||
if ((sZClip[this->type] + 40.0f) * distanceMultiplier <= fabsf(this->actor.projectedPos.z)) {
|
||||
// #endregion
|
||||
this->actionFunc = ObjMure_CulledState;
|
||||
this->actor.flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED;
|
||||
ObjMure_KillActors(this, play);
|
||||
|
||||
@@ -190,8 +190,7 @@ void func_80B9A658(ObjMure2* this) {
|
||||
|
||||
void func_80B9A668(ObjMure2* this, PlayState* play) {
|
||||
if (Math3D_Dist1DSq(this->actor.projectedPos.x, this->actor.projectedPos.z) <
|
||||
(sDistSquared1[this->actor.params & 3] * this->unk_184) ||
|
||||
CVarGetInteger("gDisableDrawDistance", 0) != 0) {
|
||||
(sDistSquared1[this->actor.params & 3] * this->unk_184)) {
|
||||
this->actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED;
|
||||
ObjMure2_SpawnActors(this, play);
|
||||
func_80B9A6E8(this);
|
||||
@@ -205,12 +204,8 @@ void func_80B9A6E8(ObjMure2* this) {
|
||||
void func_80B9A6F8(ObjMure2* this, PlayState* play) {
|
||||
func_80B9A534(this);
|
||||
|
||||
if (CVarGetInteger("gDisableDrawDistance", 0) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((sDistSquared2[this->actor.params & 3] * this->unk_184) <=
|
||||
Math3D_Dist1DSq(this->actor.projectedPos.x, this->actor.projectedPos.z)) {
|
||||
Math3D_Dist1DSq(this->actor.projectedPos.x, this->actor.projectedPos.z)) {
|
||||
this->actor.flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED;
|
||||
ObjMure2_CleanupAndDie(this, play);
|
||||
func_80B9A658(this);
|
||||
@@ -225,5 +220,20 @@ void ObjMure2_Update(Actor* thisx, PlayState* play) {
|
||||
} else {
|
||||
this->unk_184 = 4.0f;
|
||||
}
|
||||
|
||||
// SOH [Enhancements] Extended draw distance
|
||||
s32 distanceMultiplier = CVarGetInteger("gDisableDrawDistance", 1);
|
||||
if (CVarGetInteger("gEnhancements.WidescreenActorCulling", 0) || distanceMultiplier > 1) {
|
||||
f32 originalAspectRatio = 4.0f / 3.0f;
|
||||
f32 currentAspectRatio = OTRGetAspectRatio();
|
||||
// Adjust ratio difference based on field of view testing
|
||||
f32 ratioAdjusted = 1.0f + (MAX(currentAspectRatio / originalAspectRatio, 1.0f) / 1.5f);
|
||||
// Distance multiplier is squared due to the checks above for squared distances
|
||||
distanceMultiplier = SQ(MAX(distanceMultiplier, 1));
|
||||
|
||||
// Prefer the largest of the three values
|
||||
this->unk_184 = MAX(MAX((f32)distanceMultiplier, ratioAdjusted), this->unk_184);
|
||||
}
|
||||
|
||||
this->actionFunc(this, play);
|
||||
}
|
||||
|
||||
@@ -11339,10 +11339,6 @@ void Player_Draw(Actor* thisx, PlayState* play2) {
|
||||
lod = 1;
|
||||
}
|
||||
|
||||
if (CVarGetInteger("gDisableLOD", 0) != 0) {
|
||||
lod = 0;
|
||||
}
|
||||
|
||||
func_80093C80(play);
|
||||
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
||||
|
||||
|
||||
@@ -692,6 +692,7 @@ void FileChoose_UpdateOptionsMenu(GameState* thisx) {
|
||||
sLastOptionButtonIndex = -1;
|
||||
osSyncPrintf("SAVE");
|
||||
Save_SaveGlobal();
|
||||
CVarSave();
|
||||
osSyncPrintf(VT_FGCOL(YELLOW));
|
||||
osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting);
|
||||
osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting);
|
||||
|
||||
@@ -237,8 +237,8 @@ void KaleidoScope_DrawItemSelect(PlayState* play) {
|
||||
s16 oldCursorPoint;
|
||||
s16 moveCursorResult;
|
||||
bool dpad = (CVarGetInteger("gDpadPause", 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP));
|
||||
bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) ||
|
||||
(CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON);
|
||||
bool pauseAnyCursor = pauseCtx->cursorSpecialPos == 0 && ((CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) ||
|
||||
(CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON));
|
||||
|
||||
// only allow mask select when:
|
||||
// the shop is open:
|
||||
|
||||
Reference in New Issue
Block a user