@@ -6,7 +6,7 @@ set(CMAKE_C_STANDARD 23 CACHE STRING "The C standard to use")
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
||||
|
||||
project(Ship VERSION 9.1.1 LANGUAGES C CXX)
|
||||
project(Ship VERSION 9.1.2 LANGUAGES C CXX)
|
||||
include(CMake/soh-cvars.cmake)
|
||||
include(CMake/lus-cvars.cmake)
|
||||
set(SPDLOG_LEVEL_TRACE 0)
|
||||
|
||||
@@ -239,7 +239,7 @@ cmake --build build-cmake --target ExtractAssetHeaders
|
||||
```
|
||||
|
||||
## macOS
|
||||
Requires Xcode (or xcode-tools) && `sdl2, libpng, glew, ninja, cmake, tinyxml2, nlohmann-json, libzip` (can be installed via [homebrew](https://brew.sh/), macports, etc)
|
||||
Requires Xcode (or xcode-tools) && `sdl2, libpng, glew, ninja, cmake, tinyxml2, nlohmann-json, libzip, opusfile, libvorbis` (can be installed via [homebrew](https://brew.sh/), macports, etc)
|
||||
|
||||
**Important: For maximum performance make sure you have ninja build tools installed!**
|
||||
|
||||
@@ -254,7 +254,7 @@ cd ShipWright
|
||||
git submodule update --init
|
||||
|
||||
# Install development dependencies (assuming homebrew)
|
||||
brew install sdl2 libpng glew ninja cmake tinyxml2 nlohmann-json libzip
|
||||
brew install sdl2 libpng glew ninja cmake tinyxml2 nlohmann-json libzip opusfile libvorbis
|
||||
|
||||
# Generate Ninja project
|
||||
# Add `-DCMAKE_BUILD_TYPE:STRING=Release` if you're packaging
|
||||
|
||||
88
soh/soh/Enhancements/ExtraModes/RandomizedEnemySizes.cpp
Normal file
88
soh/soh/Enhancements/ExtraModes/RandomizedEnemySizes.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ObjectExtension/ActorMaximumHealth.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "functions.h"
|
||||
#include "src/overlays/actors/ovl_En_Fz/z_en_fz.h"
|
||||
}
|
||||
|
||||
static constexpr int32_t CVAR_RANDO_ENEMY_SIZE_DEFAULT = 0;
|
||||
#define CVAR_RANDO_ENEMY_SIZE_NAME CVAR_ENHANCEMENT("RandomizedEnemySizes")
|
||||
#define CVAR_RANDO_ENEMY_SIZE_VALUE CVarGetInteger(CVAR_RANDO_ENEMY_SIZE_NAME, CVAR_RANDO_ENEMY_SIZE_DEFAULT)
|
||||
|
||||
static constexpr int32_t CVAR_ENEMY_SCALE_HEALTH_DEFAULT = 0;
|
||||
#define CVAR_ENEMY_SCALE_HEALTH_NAME CVAR_ENHANCEMENT("EnemySizeScalesHealth")
|
||||
#define CVAR_ENEMY_SCALE_HEALTH_VALUE CVarGetInteger(CVAR_ENEMY_SCALE_HEALTH_NAME, CVAR_ENEMY_SCALE_HEALTH_DEFAULT)
|
||||
|
||||
static void RandomizedEnemySizes(void* refActor) {
|
||||
// Randomized Enemy Sizes
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
|
||||
// Exclude wobbly platforms in Jabu because they need to act like platforms.
|
||||
// Exclude demo effect for Zora sapphire being re-categorized as a "boss".
|
||||
// Exclude Dead Hand hands and Bongo Bongo main body because they make the fights (near) impossible.
|
||||
bool excludedEnemy = actor->id == ACTOR_EN_BROB || actor->id == ACTOR_EN_DHA || actor->id == ACTOR_DEMO_EFFECT ||
|
||||
(actor->id == ACTOR_BOSS_SST && actor->params == -1);
|
||||
|
||||
// Only apply to enemies and bosses.
|
||||
if ((actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) {
|
||||
return;
|
||||
}
|
||||
|
||||
float randomNumber;
|
||||
float randomScale;
|
||||
|
||||
// Dodongo, Volvagia and Dead Hand are always smaller because they're impossible when bigger.
|
||||
bool smallOnlyEnemy = actor->id == ACTOR_BOSS_DODONGO || actor->id == ACTOR_BOSS_FD ||
|
||||
actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH;
|
||||
|
||||
bool bigActor = !smallOnlyEnemy && (rand() % 2);
|
||||
|
||||
// Big actor
|
||||
if (bigActor) {
|
||||
randomNumber = rand() % 200;
|
||||
// Between 100% and 300% size.
|
||||
randomScale = 1.0f + (randomNumber / 100);
|
||||
} else {
|
||||
// Small actor
|
||||
randomNumber = rand() % 90;
|
||||
// Between 10% and 100% size.
|
||||
randomScale = 0.1f + (randomNumber / 100);
|
||||
}
|
||||
|
||||
Actor_SetScale(actor, actor->scale.z * randomScale);
|
||||
|
||||
if (CVAR_ENEMY_SCALE_HEALTH_VALUE && (actor->category == ACTORCAT_ENEMY)) {
|
||||
// Scale the health based on a smaller factor than randomScale
|
||||
float healthScalingFactor = 0.8f; // Adjust this factor as needed
|
||||
float scaledHealth = actor->colChkInfo.health * (randomScale * healthScalingFactor);
|
||||
|
||||
// Ensure the scaled health doesn't go below zero
|
||||
actor->colChkInfo.health = fmax(scaledHealth, 1.0f);
|
||||
|
||||
// Ensure maximum health gets set
|
||||
SetActorMaximumHealth(actor, actor->colChkInfo.health);
|
||||
}
|
||||
}
|
||||
|
||||
static void RegisterRandomizedEnemySizes() {
|
||||
COND_HOOK(OnActorInit, CVAR_RANDO_ENEMY_SIZE_VALUE, RandomizedEnemySizes);
|
||||
}
|
||||
|
||||
static void RegisterFreezardHealthScale() {
|
||||
COND_VB_SHOULD(VB_FREEZARD_SCALE_HEALTH_WITH_SIZE, CVAR_RANDO_ENEMY_SIZE_VALUE && CVAR_ENEMY_SCALE_HEALTH_VALUE, {
|
||||
// With enemy health scaling, the Freezard's health could cause an index out of bounds for the displayLists, so
|
||||
// we need to recompute the index based on the scaled health (using the maximum health value) and clamp the
|
||||
// final result for safety.
|
||||
Actor* actor = va_arg(args, Actor*);
|
||||
s32* index = va_arg(args, s32*);
|
||||
|
||||
u8 scaledHealth = (u8)(((f32)actor->colChkInfo.health / GetActorMaximumHealth(actor)) * 6);
|
||||
*index = CLAMP((6 - scaledHealth) >> 1, 0, 2);
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc_EnemySizes(RegisterRandomizedEnemySizes, { CVAR_RANDO_ENEMY_SIZE_NAME });
|
||||
static RegisterShipInitFunc initFunc_Freezard(RegisterFreezardHealthScale,
|
||||
{ CVAR_RANDO_ENEMY_SIZE_NAME, CVAR_ENEMY_SCALE_HEALTH_NAME });
|
||||
59
soh/soh/Enhancements/Fixes/FixTwoHandedIdleAnim.cpp
Normal file
59
soh/soh/Enhancements/Fixes/FixTwoHandedIdleAnim.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
#include "functions.h"
|
||||
}
|
||||
|
||||
#define FIDGET_SWORD_SWING 9
|
||||
#define FIDGET_ADJUST_SHIELD 12
|
||||
|
||||
static constexpr int32_t CVAR_FIX_TWO_HANDED_IDLE_DEFAULT = 0;
|
||||
#define CVAR_FIX_TWO_HANDED_IDLE_NAME CVAR_ENHANCEMENT("TwoHandedIdle")
|
||||
#define CVAR_FIX_TWO_HANDED_IDLE_VALUE CVarGetInteger(CVAR_FIX_TWO_HANDED_IDLE_NAME, CVAR_FIX_TWO_HANDED_IDLE_DEFAULT)
|
||||
|
||||
// clang-format off
|
||||
static RegisterShipInitFunc initFunc([]() {
|
||||
COND_VB_SHOULD(VB_SET_IDLE_ANIM, CVAR_FIX_TWO_HANDED_IDLE_VALUE, {
|
||||
Player* player = va_arg(args, Player*);
|
||||
s32 commonType = va_arg(args, s32);
|
||||
|
||||
// Fixes a bug here where the condition for reaching two-handed idle animation was impossible. Original condition:
|
||||
/*
|
||||
(
|
||||
(
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)
|
||||
) ||
|
||||
(
|
||||
(player->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||
(
|
||||
(commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD) ||
|
||||
// This should not have been grouped here, because two handed melee weapons do not have shield.
|
||||
(Player_GetMeleeWeaponHeld2(player) != 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
*/
|
||||
|
||||
*should = (
|
||||
// Animation is not FIDGET_SWORD_SWING and FIDGET_ADJUST_SHIELD (So it's either FIDGET_ADJUST_TUNIC or FIDGET_TAP_FEET)
|
||||
(
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)
|
||||
) ||
|
||||
// Animation is FIDGET_ADJUST_SHIELD and player is holding a shield in right hand
|
||||
(
|
||||
(player->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||
(commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD)
|
||||
) ||
|
||||
// Animation is FIDGET_SWORD_SWING and player is holding a melee weapon
|
||||
(
|
||||
(commonType + FIDGET_SWORD_SWING == FIDGET_SWORD_SWING) &&
|
||||
(Player_GetMeleeWeaponHeld(player) != 0)
|
||||
)
|
||||
);
|
||||
});
|
||||
}, { CVAR_FIX_TWO_HANDED_IDLE_NAME });
|
||||
// clang-format on
|
||||
223
soh/soh/Enhancements/GameplayStats/EnemyDefeatCounts.cpp
Normal file
223
soh/soh/Enhancements/GameplayStats/EnemyDefeatCounts.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "src/overlays/actors/ovl_En_Bb/z_en_bb.h"
|
||||
#include "src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.h"
|
||||
#include "src/overlays/actors/ovl_En_Mb/z_en_mb.h"
|
||||
#include "src/overlays/actors/ovl_En_Tite/z_en_tite.h"
|
||||
#include "src/overlays/actors/ovl_En_Zf/z_en_zf.h"
|
||||
#include "src/overlays/actors/ovl_En_Wf/z_en_wf.h"
|
||||
#include "src/overlays/actors/ovl_En_Reeba/z_en_reeba.h"
|
||||
#include "src/overlays/actors/ovl_En_Peehat/z_en_peehat.h"
|
||||
#include "src/overlays/actors/ovl_En_Po_Field/z_en_po_field.h"
|
||||
#include "src/overlays/actors/ovl_En_Poh/z_en_poh.h"
|
||||
#include "src/overlays/actors/ovl_En_Tp/z_en_tp.h"
|
||||
#include "src/overlays/actors/ovl_En_Firefly/z_en_firefly.h"
|
||||
|
||||
extern SaveContext gSaveContext;
|
||||
}
|
||||
|
||||
static void IncrementEnemyDefeatCount(GameplayStatCount countType) {
|
||||
gSaveContext.ship.stats.count[countType]++;
|
||||
}
|
||||
|
||||
#define ENEMY_DEFEAT_COUNT(actorID, func) \
|
||||
COND_ID_HOOK(OnEnemyDefeat, actorID, true, [](void* refActor) { func(static_cast<Actor*>(refActor)); });
|
||||
|
||||
#define ENEMY_DEFEAT_COUNT_UNIQUE(actorID, countType) \
|
||||
COND_ID_HOOK(OnEnemyDefeat, actorID, true, [](void*) { IncrementEnemyDefeatCount(countType); });
|
||||
|
||||
static void EnemyDefeatCounts_EnBb(Actor* actor) {
|
||||
GameplayStatCount countType;
|
||||
switch (actor->params) {
|
||||
case ENBB_GREEN:
|
||||
case ENBB_GREEN_BIG:
|
||||
countType = COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN;
|
||||
break;
|
||||
case ENBB_BLUE:
|
||||
countType = COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE;
|
||||
break;
|
||||
case ENBB_WHITE:
|
||||
countType = COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE;
|
||||
break;
|
||||
case ENBB_RED:
|
||||
countType = COUNT_ENEMIES_DEFEATED_BUBBLE_RED;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnDekubaba(Actor* actor) {
|
||||
GameplayStatCount countType =
|
||||
(actor->params == DEKUBABA_BIG) ? COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG : COUNT_ENEMIES_DEFEATED_DEKU_BABA;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnZf(Actor* actor) {
|
||||
GameplayStatCount countType =
|
||||
(actor->params == ENZF_TYPE_DINOLFOS) ? COUNT_ENEMIES_DEFEATED_DINOLFOS : COUNT_ENEMIES_DEFEATED_LIZALFOS;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnRd(Actor* actor) {
|
||||
GameplayStatCount countType = (actor->params >= -1) ? COUNT_ENEMIES_DEFEATED_REDEAD : COUNT_ENEMIES_DEFEATED_GIBDO;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnIk(Actor* actor) {
|
||||
GameplayStatCount countType =
|
||||
(actor->params == 0) ? COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU : COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnFirefly(Actor* actor) {
|
||||
GameplayStatCount countType;
|
||||
switch (actor->params) {
|
||||
case KEESE_NORMAL_FLY:
|
||||
case KEESE_NORMAL_PERCH:
|
||||
countType = COUNT_ENEMIES_DEFEATED_KEESE;
|
||||
break;
|
||||
case KEESE_FIRE_FLY:
|
||||
case KEESE_FIRE_PERCH:
|
||||
countType = COUNT_ENEMIES_DEFEATED_KEESE_FIRE;
|
||||
break;
|
||||
case KEESE_ICE_FLY:
|
||||
countType = COUNT_ENEMIES_DEFEATED_KEESE_ICE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnTp(Actor* actor) {
|
||||
// Only count the head, otherwise each body segment will increment
|
||||
if (actor->params == TAILPASARAN_HEAD) {
|
||||
IncrementEnemyDefeatCount(COUNT_ENEMIES_DEFEATED_TAILPASARAN);
|
||||
}
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnReeba(Actor* actor) {
|
||||
EnReeba* reeba = (EnReeba*)actor;
|
||||
GameplayStatCount countType = reeba->isBig ? COUNT_ENEMIES_DEFEATED_LEEVER_BIG : COUNT_ENEMIES_DEFEATED_LEEVER;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnMb(Actor* actor) {
|
||||
GameplayStatCount countType =
|
||||
(actor->params == 0) ? COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB : COUNT_ENEMIES_DEFEATED_MOBLIN;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnPeehat(Actor* actor) {
|
||||
GameplayStatCount countType =
|
||||
(actor->params == PEAHAT_TYPE_LARVA) ? COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA : COUNT_ENEMIES_DEFEATED_PEAHAT;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnPoh(Actor* actor) {
|
||||
GameplayStatCount countType = (actor->params == EN_POH_FLAT || actor->params == EN_POH_SHARP)
|
||||
? COUNT_ENEMIES_DEFEATED_POE_COMPOSER
|
||||
: COUNT_ENEMIES_DEFEATED_POE;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnPoField(Actor* actor) {
|
||||
GameplayStatCount countType =
|
||||
(actor->params == EN_PO_FIELD_BIG) ? COUNT_ENEMIES_DEFEATED_POE_BIG : COUNT_ENEMIES_DEFEATED_POE;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnSt(Actor* actor) {
|
||||
GameplayStatCount countType =
|
||||
(actor->params == 1) ? COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG : COUNT_ENEMIES_DEFEATED_SKULLTULA;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnSw(Actor* actor) {
|
||||
GameplayStatCount countType;
|
||||
if (((actor->params & 0xE000) >> 0xD) != 0) {
|
||||
countType = COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD;
|
||||
} else {
|
||||
countType = COUNT_ENEMIES_DEFEATED_SKULLWALLTULA;
|
||||
}
|
||||
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnTite(Actor* actor) {
|
||||
GameplayStatCount countType =
|
||||
(actor->params == TEKTITE_BLUE) ? COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE : COUNT_ENEMIES_DEFEATED_TEKTITE_RED;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void EnemyDefeatCounts_EnWf(Actor* actor) {
|
||||
GameplayStatCount countType =
|
||||
(actor->params == WOLFOS_WHITE) ? COUNT_ENEMIES_DEFEATED_WOLFOS_WHITE : COUNT_ENEMIES_DEFEATED_WOLFOS;
|
||||
IncrementEnemyDefeatCount(countType);
|
||||
}
|
||||
|
||||
static void RegisterEnemyDefeatCounts() {
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_ANUBICE, COUNT_ENEMIES_DEFEATED_ANUBIS);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_AM, COUNT_ENEMIES_DEFEATED_ARMOS);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_CLEAR_TAG, COUNT_ENEMIES_DEFEATED_ARWING);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_VALI, COUNT_ENEMIES_DEFEATED_BARI);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_VM, COUNT_ENEMIES_DEFEATED_BEAMOS);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_BIGOKUTA, COUNT_ENEMIES_DEFEATED_BIG_OCTO);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_BILI, COUNT_ENEMIES_DEFEATED_BIRI);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_DNS, COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_TORCH2, COUNT_ENEMIES_DEFEATED_DARK_LINK);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_DH, COUNT_ENEMIES_DEFEATED_DEAD_HAND);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_HINTNUTS, COUNT_ENEMIES_DEFEATED_DEKU_SCRUB);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_DODONGO, COUNT_ENEMIES_DEFEATED_DODONGO);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_DODOJR, COUNT_ENEMIES_DEFEATED_DODONGO_BABY);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_DOOR_KILLER, COUNT_ENEMIES_DEFEATED_DOOR_TRAP);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_FD, COUNT_ENEMIES_DEFEATED_FLARE_DANCER);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_FLOORMAS, COUNT_ENEMIES_DEFEATED_FLOORMASTER);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_TUBO_TRAP, COUNT_ENEMIES_DEFEATED_FLYING_POT);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_YUKABYUN, COUNT_ENEMIES_DEFEATED_FLOOR_TILE);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_FZ, COUNT_ENEMIES_DEFEATED_FREEZARD);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_GELDB, COUNT_ENEMIES_DEFEATED_GERUDO_THIEF);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_GOMA, COUNT_ENEMIES_DEFEATED_GOHMA_LARVA);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_CROW, COUNT_ENEMIES_DEFEATED_GUAY);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_RR, COUNT_ENEMIES_DEFEATED_LIKE_LIKE);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_DEKUNUTS, COUNT_ENEMIES_DEFEATED_MAD_SCRUB);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_OKUTA, COUNT_ENEMIES_DEFEATED_OCTOROK);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_BA, COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_PO_SISTERS, COUNT_ENEMIES_DEFEATED_POE_SISTERS);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_BUBBLE, COUNT_ENEMIES_DEFEATED_SHABOM);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_SB, COUNT_ENEMIES_DEFEATED_SHELLBLADE);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_SKJ, COUNT_ENEMIES_DEFEATED_SKULL_KID);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_NY, COUNT_ENEMIES_DEFEATED_SPIKE);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_SKB, COUNT_ENEMIES_DEFEATED_STALCHILD);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_TEST, COUNT_ENEMIES_DEFEATED_STALFOS);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_EIYER, COUNT_ENEMIES_DEFEATED_STINGER);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_WEIYER, COUNT_ENEMIES_DEFEATED_STINGER);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_BW, COUNT_ENEMIES_DEFEATED_TORCH_SLUG);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_WALLMAS, COUNT_ENEMIES_DEFEATED_WALLMASTER);
|
||||
ENEMY_DEFEAT_COUNT_UNIQUE(ACTOR_EN_KAREBABA, COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA);
|
||||
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_BB, EnemyDefeatCounts_EnBb);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_DEKUBABA, EnemyDefeatCounts_EnDekubaba);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_ZF, EnemyDefeatCounts_EnZf);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_RD, EnemyDefeatCounts_EnRd);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_IK, EnemyDefeatCounts_EnIk);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_FIREFLY, EnemyDefeatCounts_EnFirefly);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_TP, EnemyDefeatCounts_EnTp);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_REEBA, EnemyDefeatCounts_EnReeba);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_MB, EnemyDefeatCounts_EnMb);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_PEEHAT, EnemyDefeatCounts_EnPeehat);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_POH, EnemyDefeatCounts_EnPoh);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_PO_FIELD, EnemyDefeatCounts_EnPoField);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_ST, EnemyDefeatCounts_EnSt);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_SW, EnemyDefeatCounts_EnSw);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_TITE, EnemyDefeatCounts_EnTite);
|
||||
ENEMY_DEFEAT_COUNT(ACTOR_EN_WF, EnemyDefeatCounts_EnWf);
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterEnemyDefeatCounts);
|
||||
@@ -1377,12 +1377,11 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
|
||||
CheckboxOptions()
|
||||
.Color(THEME_COLOR)
|
||||
.Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming"));
|
||||
if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) {
|
||||
CVarCheckbox("Allow moving while in first-person mode", CVAR_SETTING("MoveInFirstPerson"),
|
||||
CheckboxOptions()
|
||||
.Color(THEME_COLOR)
|
||||
.Tooltip("Changes the left stick to move the player while in first-person mode"));
|
||||
}
|
||||
CVarCheckbox("Allow moving while in first-person mode", CVAR_SETTING("MoveInFirstPerson"),
|
||||
CheckboxOptions({ { .disabled = !CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0),
|
||||
.disabledTooltip = "Forced off because Right Stick Aiming is disabled." } })
|
||||
.Color(THEME_COLOR)
|
||||
.Tooltip("Changes the left stick to move the player while in first-person mode"));
|
||||
CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"),
|
||||
CheckboxOptions()
|
||||
.Color(THEME_COLOR)
|
||||
|
||||
@@ -578,6 +578,15 @@ typedef enum {
|
||||
// - None
|
||||
VB_FIX_SAW_SOFTLOCK,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// false
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*EnFz`
|
||||
// - `*s32`
|
||||
VB_FREEZARD_SCALE_HEALTH_WITH_SIZE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
@@ -2543,6 +2552,27 @@ typedef enum {
|
||||
// - `uint16_t` (cursorItem - promoted from `u16`)
|
||||
VB_EQUIP_ITEM_TO_C_BUTTON,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// (
|
||||
// (
|
||||
// (commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||
// (commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)
|
||||
// ) ||
|
||||
// (
|
||||
// (player->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||
// (
|
||||
// (commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD) ||
|
||||
// (Player_GetMeleeWeaponHeld2(player) != 0)
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `Player*`
|
||||
// - `s32` commonType
|
||||
VB_SET_IDLE_ANIM,
|
||||
|
||||
} GIVanillaBehavior;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -137,97 +137,97 @@ const char* const sceneMappings[] = {
|
||||
};
|
||||
|
||||
const char* const countMappings[] = {
|
||||
"Anubis:",
|
||||
"Armos:",
|
||||
"Arwing:",
|
||||
"Bari:",
|
||||
"Biri:",
|
||||
"Beamos:",
|
||||
"Big Octo:",
|
||||
"Bubble (Blue):",
|
||||
"Bubble (Green):",
|
||||
"Bubble (Red):",
|
||||
"Bubble (White):",
|
||||
"Business Scrub:",
|
||||
"Dark Link:",
|
||||
"Dead Hand:",
|
||||
"Deku Baba:",
|
||||
"Deku Baba (Big):",
|
||||
"Deku Scrub:",
|
||||
"Dinolfos:",
|
||||
"Dodongo:",
|
||||
"Dodongo (Baby):",
|
||||
"Door Mimic:",
|
||||
"Flare Dancer:",
|
||||
"Floormaster:",
|
||||
"Flying Floor Tile:",
|
||||
"Flying Pot:",
|
||||
"Freezard:",
|
||||
"Gerudo Thief:",
|
||||
"Gibdo:",
|
||||
"Gohma Larva:",
|
||||
"Guay:",
|
||||
"Iron Knuckle:",
|
||||
"Iron Knuckle (Nab):",
|
||||
"Keese:",
|
||||
"Keese (Fire):",
|
||||
"Keese (Ice):",
|
||||
"Leever:",
|
||||
"Leever (Big):",
|
||||
"Like-Like:",
|
||||
"Lizalfos:",
|
||||
"Mad Scrub:",
|
||||
"Moblin:",
|
||||
"Moblin (Club):",
|
||||
"Octorok:",
|
||||
"Parasitic Tentacle:",
|
||||
"Peahat:",
|
||||
"Peahat Larva:",
|
||||
"Poe:",
|
||||
"Poe (Big):",
|
||||
"Poe (Composer):",
|
||||
"Poe Sisters:",
|
||||
"Redead:",
|
||||
"Shabom:",
|
||||
"Shell Blade:",
|
||||
"Skull Kid:",
|
||||
"Skulltula:",
|
||||
"Skulltula (Big):",
|
||||
"Skulltula (Gold):",
|
||||
"Skullwalltula:",
|
||||
"Spike:",
|
||||
"Stalchild:",
|
||||
"Stalfos:",
|
||||
"Stinger:",
|
||||
"Tailpasaran:",
|
||||
"Tektite (Blue):",
|
||||
"Tektite (Red):",
|
||||
"Torch Slug:",
|
||||
"Wallmaster:",
|
||||
"Withered Deku Baba:",
|
||||
"Wolfos:",
|
||||
"Wolfos (White):",
|
||||
"Deku Sticks:",
|
||||
"Deku Nuts:",
|
||||
"Bombs:",
|
||||
"Arrows:",
|
||||
"Deku Seeds:",
|
||||
"Bombchus:",
|
||||
"Beans:",
|
||||
"A:",
|
||||
"B:",
|
||||
"L:",
|
||||
"R:",
|
||||
"Z:",
|
||||
"C-Up:",
|
||||
"C-Right:",
|
||||
"C-Down:",
|
||||
"C-Left:",
|
||||
"D-Up:",
|
||||
"D-Right:",
|
||||
"D-Down:",
|
||||
"D-Left:",
|
||||
"Start:",
|
||||
"Anubis:", // COUNT_ENEMIES_DEFEATED_ANUBIS
|
||||
"Armos:", // COUNT_ENEMIES_DEFEATED_ARMOS
|
||||
"Arwing:", // COUNT_ENEMIES_DEFEATED_ARWING
|
||||
"Bari:", // COUNT_ENEMIES_DEFEATED_BARI
|
||||
"Beamos:", // COUNT_ENEMIES_DEFEATED_BEAMOS
|
||||
"Big Octo:", // COUNT_ENEMIES_DEFEATED_BIG_OCTO
|
||||
"Biri:", // COUNT_ENEMIES_DEFEATED_BIRI
|
||||
"Bubble (Green):", // COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN
|
||||
"Bubble (Blue):", // COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE
|
||||
"Bubble (White):", // COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE
|
||||
"Bubble (Red):", // COUNT_ENEMIES_DEFEATED_BUBBLE_RED
|
||||
"Business Scrub:", // COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB
|
||||
"Dark Link:", // COUNT_ENEMIES_DEFEATED_DARK_LINK
|
||||
"Dead Hand:", // COUNT_ENEMIES_DEFEATED_DEAD_HAND
|
||||
"Deku Baba:", // COUNT_ENEMIES_DEFEATED_DEKU_BABA
|
||||
"Deku Baba (Big):", // COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG
|
||||
"Deku Scrub:", // COUNT_ENEMIES_DEFEATED_DEKU_SCRUB
|
||||
"Dinolfos:", // COUNT_ENEMIES_DEFEATED_DINOLFOS
|
||||
"Dodongo:", // COUNT_ENEMIES_DEFEATED_DODONGO
|
||||
"Dodongo (Baby):", // COUNT_ENEMIES_DEFEATED_DODONGO_BABY
|
||||
"Door Mimic:", // COUNT_ENEMIES_DEFEATED_DOOR_TRAP
|
||||
"Flare Dancer:", // COUNT_ENEMIES_DEFEATED_FLARE_DANCER
|
||||
"Floormaster:", // COUNT_ENEMIES_DEFEATED_FLOORMASTER
|
||||
"Flying Pot:", // COUNT_ENEMIES_DEFEATED_FLYING_POT
|
||||
"Flying Floor Tile:", // COUNT_ENEMIES_DEFEATED_FLOOR_TILE
|
||||
"Freezard:", // COUNT_ENEMIES_DEFEATED_FREEZARD
|
||||
"Gerudo Thief:", // COUNT_ENEMIES_DEFEATED_GERUDO_THIEF
|
||||
"Gibdo:", // COUNT_ENEMIES_DEFEATED_GIBDO
|
||||
"Gohma Larva:", // COUNT_ENEMIES_DEFEATED_GOHMA_LARVA
|
||||
"Guay:", // COUNT_ENEMIES_DEFEATED_GUAY
|
||||
"Iron Knuckle:", // COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE
|
||||
"Iron Knuckle (Nab):", // COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU
|
||||
"Keese:", // COUNT_ENEMIES_DEFEATED_KEESE
|
||||
"Keese (Fire):", // COUNT_ENEMIES_DEFEATED_KEESE_FIRE
|
||||
"Keese (Ice):", // COUNT_ENEMIES_DEFEATED_KEESE_ICE
|
||||
"Leever:", // COUNT_ENEMIES_DEFEATED_LEEVER
|
||||
"Leever (Big):", // COUNT_ENEMIES_DEFEATED_LEEVER_BIG
|
||||
"Like-Like:", // COUNT_ENEMIES_DEFEATED_LIKE_LIKE
|
||||
"Lizalfos:", // COUNT_ENEMIES_DEFEATED_LIZALFOS
|
||||
"Mad Scrub:", // COUNT_ENEMIES_DEFEATED_MAD_SCRUB
|
||||
"Moblin:", // COUNT_ENEMIES_DEFEATED_MOBLIN
|
||||
"Moblin (Club):", // COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB
|
||||
"Octorok:", // COUNT_ENEMIES_DEFEATED_OCTOROK
|
||||
"Parasitic Tentacle:", // COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE
|
||||
"Peahat:", // COUNT_ENEMIES_DEFEATED_PEAHAT
|
||||
"Peahat Larva:", // COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA
|
||||
"Poe:", // COUNT_ENEMIES_DEFEATED_POE
|
||||
"Poe (Big):", // COUNT_ENEMIES_DEFEATED_POE_BIG
|
||||
"Poe (Composer):", // COUNT_ENEMIES_DEFEATED_POE_COMPOSER
|
||||
"Poe Sisters:", // COUNT_ENEMIES_DEFEATED_POE_SISTERS
|
||||
"Redead:", // COUNT_ENEMIES_DEFEATED_REDEAD
|
||||
"Shabom:", // COUNT_ENEMIES_DEFEATED_SHABOM
|
||||
"Shell Blade:", // COUNT_ENEMIES_DEFEATED_SHELLBLADE
|
||||
"Skulltula:", // COUNT_ENEMIES_DEFEATED_SKULLTULA
|
||||
"Skulltula (Big):", // COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG
|
||||
"Skulltula (Gold):", // COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD
|
||||
"Skullwalltula:", // COUNT_ENEMIES_DEFEATED_SKULLWALLTULA
|
||||
"Skull Kid:", // COUNT_ENEMIES_DEFEATED_SKULL_KID
|
||||
"Spike:", // COUNT_ENEMIES_DEFEATED_SPIKE
|
||||
"Stalchild:", // COUNT_ENEMIES_DEFEATED_STALCHILD
|
||||
"Stalfos:", // COUNT_ENEMIES_DEFEATED_STALFOS
|
||||
"Stinger:", // COUNT_ENEMIES_DEFEATED_STINGER
|
||||
"Tailpasaran:", // COUNT_ENEMIES_DEFEATED_TAILPASARAN
|
||||
"Tektite (Blue):", // COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE
|
||||
"Tektite (Red):", // COUNT_ENEMIES_DEFEATED_TEKTITE_RED
|
||||
"Torch Slug:", // COUNT_ENEMIES_DEFEATED_TORCH_SLUG
|
||||
"Wallmaster:", // COUNT_ENEMIES_DEFEATED_WALLMASTER
|
||||
"Withered Deku Baba:", // COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA
|
||||
"Wolfos:", // COUNT_ENEMIES_DEFEATED_WOLFOS
|
||||
"Wolfos (White):", // COUNT_ENEMIES_DEFEATED_WOLFOS_WHITE
|
||||
"Deku Sticks:", // COUNT_AMMO_USED_STICK
|
||||
"Deku Nuts:", // COUNT_AMMO_USED_NUT
|
||||
"Bombs:", // COUNT_AMMO_USED_BOMB
|
||||
"Arrows:", // COUNT_AMMO_USED_ARROW
|
||||
"Deku Seeds:", // COUNT_AMMO_USED_SEED
|
||||
"Bombchus:", // COUNT_AMMO_USED_BOMBCHU
|
||||
"Beans:", // COUNT_AMMO_USED_BEAN
|
||||
"A:", // COUNT_BUTTON_PRESSES_A
|
||||
"B:", // COUNT_BUTTON_PRESSES_B
|
||||
"L:", // COUNT_BUTTON_PRESSES_L
|
||||
"R:", // COUNT_BUTTON_PRESSES_R
|
||||
"Z:", // COUNT_BUTTON_PRESSES_Z
|
||||
"C-Up:", // COUNT_BUTTON_PRESSES_CUP
|
||||
"C-Right:", // COUNT_BUTTON_PRESSES_CRIGHT
|
||||
"C-Down:", // COUNT_BUTTON_PRESSES_CDOWN
|
||||
"C-Left:", // COUNT_BUTTON_PRESSES_CLEFT
|
||||
"D-Up:", // COUNT_BUTTON_PRESSES_DUP
|
||||
"D-Right:", // COUNT_BUTTON_PRESSES_DRIGHT
|
||||
"D-Down:", // COUNT_BUTTON_PRESSES_DDOWN
|
||||
"D-Left:", // COUNT_BUTTON_PRESSES_DLEFT
|
||||
"Start:", // COUNT_BUTTON_PRESSES_START
|
||||
};
|
||||
|
||||
#define COLOR_WHITE ImVec4(1.00f, 1.00f, 1.00f, 1.00f)
|
||||
|
||||
@@ -95,6 +95,8 @@ void ModsHandleDragAndDrop(std::vector<std::string>& objectList, int targetIndex
|
||||
|
||||
std::vector<std::string> GetEnabledModsFromCVar() {
|
||||
std::string enabledModsCVarValue = CVAR_ENABLED_MODS_VALUE;
|
||||
if (enabledModsCVarValue.empty())
|
||||
return {};
|
||||
return StringHelper::Split(enabledModsCVarValue, SEPARATOR);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +1,12 @@
|
||||
#include "mods.h"
|
||||
#include <libultraship/bridge.h>
|
||||
#include "game-interactor/GameInteractor.h"
|
||||
#include "soh/ResourceManagerHelpers.h"
|
||||
#include "soh/Enhancements/boss-rush/BossRush.h"
|
||||
#include "soh/Enhancements/enhancementTypes.h"
|
||||
#include <soh/Enhancements/item-tables/ItemTableManager.h>
|
||||
|
||||
#include "src/overlays/actors/ovl_En_Bb/z_en_bb.h"
|
||||
#include "src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.h"
|
||||
#include "src/overlays/actors/ovl_En_Mb/z_en_mb.h"
|
||||
#include "src/overlays/actors/ovl_En_Tite/z_en_tite.h"
|
||||
#include "src/overlays/actors/ovl_En_Zf/z_en_zf.h"
|
||||
#include "src/overlays/actors/ovl_En_Wf/z_en_wf.h"
|
||||
#include "src/overlays/actors/ovl_En_Reeba/z_en_reeba.h"
|
||||
#include "src/overlays/actors/ovl_En_Peehat/z_en_peehat.h"
|
||||
#include "src/overlays/actors/ovl_En_Po_Field/z_en_po_field.h"
|
||||
#include "src/overlays/actors/ovl_En_Poh/z_en_poh.h"
|
||||
#include "src/overlays/actors/ovl_En_Tp/z_en_tp.h"
|
||||
#include "src/overlays/actors/ovl_En_Firefly/z_en_firefly.h"
|
||||
#include "src/overlays/actors/ovl_En_Xc/z_en_xc.h"
|
||||
#include "src/overlays/actors/ovl_Door_Shutter/z_door_shutter.h"
|
||||
#include "src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.h"
|
||||
#include "src/overlays/actors/ovl_En_Elf/z_en_elf.h"
|
||||
#include "soh_assets.h"
|
||||
|
||||
extern "C" {
|
||||
#include <z64.h>
|
||||
#include "align_asset_macro.h"
|
||||
#include "macros.h"
|
||||
#include "soh/cvar_prefixes.h"
|
||||
#include "variables.h"
|
||||
@@ -87,7 +67,6 @@ void SwitchAge() {
|
||||
|
||||
/// Switches Link's age and respawns him at the last entrance he entered.
|
||||
void RegisterOcarinaTimeTravel() {
|
||||
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnOcarinaSongAction>([]() {
|
||||
if (!GameInteractor::IsSaveLoaded(true) || !CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0)) {
|
||||
return;
|
||||
@@ -194,253 +173,7 @@ void RegisterHyperBosses() {
|
||||
[](int16_t fileNum) { UpdateHyperBossesState(); });
|
||||
}
|
||||
|
||||
// this map is used for enemies that can be uniquely identified by their id
|
||||
// and that are always counted
|
||||
// enemies that can't be uniquely identified by their id
|
||||
// or only sometimes count (like ACTOR_EN_TP)
|
||||
// have to be manually handled in RegisterEnemyDefeatCounts
|
||||
static std::unordered_map<u16, u16> uniqueEnemyIdToStatCount = {
|
||||
{ ACTOR_EN_ANUBICE, COUNT_ENEMIES_DEFEATED_ANUBIS },
|
||||
{ ACTOR_EN_AM, COUNT_ENEMIES_DEFEATED_ARMOS },
|
||||
{ ACTOR_EN_CLEAR_TAG, COUNT_ENEMIES_DEFEATED_ARWING },
|
||||
{ ACTOR_EN_VALI, COUNT_ENEMIES_DEFEATED_BARI },
|
||||
{ ACTOR_EN_VM, COUNT_ENEMIES_DEFEATED_BEAMOS },
|
||||
{ ACTOR_EN_BIGOKUTA, COUNT_ENEMIES_DEFEATED_BIG_OCTO },
|
||||
{ ACTOR_EN_BILI, COUNT_ENEMIES_DEFEATED_BIRI },
|
||||
{ ACTOR_EN_DNS, COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB },
|
||||
{ ACTOR_EN_TORCH, COUNT_ENEMIES_DEFEATED_DARK_LINK },
|
||||
{ ACTOR_EN_DH, COUNT_ENEMIES_DEFEATED_DEAD_HAND },
|
||||
{ ACTOR_EN_HINTNUTS, COUNT_ENEMIES_DEFEATED_DEKU_SCRUB },
|
||||
{ ACTOR_EN_DODONGO, COUNT_ENEMIES_DEFEATED_DODONGO },
|
||||
{ ACTOR_EN_DODOJR, COUNT_ENEMIES_DEFEATED_DODONGO_BABY },
|
||||
{ ACTOR_DOOR_KILLER, COUNT_ENEMIES_DEFEATED_DOOR_TRAP },
|
||||
{ ACTOR_EN_FD, COUNT_ENEMIES_DEFEATED_FLARE_DANCER },
|
||||
{ ACTOR_EN_FLOORMAS, COUNT_ENEMIES_DEFEATED_FLOORMASTER },
|
||||
{ ACTOR_EN_TUBO_TRAP, COUNT_ENEMIES_DEFEATED_FLYING_POT },
|
||||
{ ACTOR_EN_YUKABYUN, COUNT_ENEMIES_DEFEATED_FLOOR_TILE },
|
||||
{ ACTOR_EN_FZ, COUNT_ENEMIES_DEFEATED_FREEZARD },
|
||||
{ ACTOR_EN_GELDB, COUNT_ENEMIES_DEFEATED_GERUDO_THIEF },
|
||||
{ ACTOR_EN_GOMA, COUNT_ENEMIES_DEFEATED_GOHMA_LARVA },
|
||||
{ ACTOR_EN_CROW, COUNT_ENEMIES_DEFEATED_GUAY },
|
||||
{ ACTOR_EN_RR, COUNT_ENEMIES_DEFEATED_LIKE_LIKE },
|
||||
{ ACTOR_EN_DEKUNUTS, COUNT_ENEMIES_DEFEATED_MAD_SCRUB },
|
||||
{ ACTOR_EN_OKUTA, COUNT_ENEMIES_DEFEATED_OCTOROK },
|
||||
{ ACTOR_EN_BA, COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE },
|
||||
{ ACTOR_EN_PO_SISTERS, COUNT_ENEMIES_DEFEATED_POE_SISTERS },
|
||||
{ ACTOR_EN_BUBBLE, COUNT_ENEMIES_DEFEATED_SHABOM },
|
||||
{ ACTOR_EN_SB, COUNT_ENEMIES_DEFEATED_SHELLBLADE },
|
||||
{ ACTOR_EN_SKJ, COUNT_ENEMIES_DEFEATED_SKULL_KID },
|
||||
{ ACTOR_EN_NY, COUNT_ENEMIES_DEFEATED_SPIKE },
|
||||
{ ACTOR_EN_SKB, COUNT_ENEMIES_DEFEATED_STALCHILD },
|
||||
{ ACTOR_EN_TEST, COUNT_ENEMIES_DEFEATED_STALFOS },
|
||||
{ ACTOR_EN_WEIYER, COUNT_ENEMIES_DEFEATED_STINGER },
|
||||
{ ACTOR_EN_BW, COUNT_ENEMIES_DEFEATED_TORCH_SLUG },
|
||||
{ ACTOR_EN_WALLMAS, COUNT_ENEMIES_DEFEATED_WALLMASTER },
|
||||
{ ACTOR_EN_KAREBABA, COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA },
|
||||
};
|
||||
|
||||
void RegisterEnemyDefeatCounts() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnEnemyDefeat>([](void* refActor) {
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
if (uniqueEnemyIdToStatCount.contains(actor->id)) {
|
||||
gSaveContext.ship.stats.count[uniqueEnemyIdToStatCount[actor->id]]++;
|
||||
} else {
|
||||
switch (actor->id) {
|
||||
case ACTOR_EN_BB:
|
||||
if (actor->params == ENBB_GREEN || actor->params == ENBB_GREEN_BIG) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN]++;
|
||||
} else if (actor->params == ENBB_BLUE) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE]++;
|
||||
} else if (actor->params == ENBB_WHITE) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE]++;
|
||||
} else if (actor->params == ENBB_RED) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_RED]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_DEKUBABA:
|
||||
if (actor->params == DEKUBABA_BIG) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_ZF:
|
||||
if (actor->params == ENZF_TYPE_DINOLFOS) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_DINOLFOS]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LIZALFOS]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_RD:
|
||||
if (actor->params >= -1) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_REDEAD]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_GIBDO]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_IK:
|
||||
if (actor->params == 0) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_FIREFLY:
|
||||
if (actor->params == KEESE_NORMAL_FLY || actor->params == KEESE_NORMAL_PERCH) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_KEESE]++;
|
||||
} else if (actor->params == KEESE_FIRE_FLY || actor->params == KEESE_FIRE_PERCH) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_KEESE_FIRE]++;
|
||||
} else if (actor->params == KEESE_ICE_FLY) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_KEESE_ICE]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_REEBA: {
|
||||
EnReeba* reeba = (EnReeba*)actor;
|
||||
if (reeba->isBig) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ACTOR_EN_MB:
|
||||
if (actor->params == 0) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_MOBLIN]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_PEEHAT:
|
||||
if (actor->params == PEAHAT_TYPE_LARVA) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_PEAHAT]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_POH:
|
||||
if (actor->params == EN_POH_FLAT || actor->params == EN_POH_SHARP) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_POE_COMPOSER]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_POE]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_PO_FIELD:
|
||||
if (actor->params == EN_PO_FIELD_BIG) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_POE_BIG]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_POE]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_ST:
|
||||
if (actor->params == 1) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_SW:
|
||||
if (((actor->params & 0xE000) >> 0xD) != 0) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_SKULLWALLTULA]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_TP:
|
||||
// Only count the head, otherwise each body segment will increment
|
||||
if (actor->params == TAILPASARAN_HEAD) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_TAILPASARAN]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_TITE:
|
||||
if (actor->params == TEKTITE_BLUE) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_RED]++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTOR_EN_WF:
|
||||
if (actor->params == WOLFOS_WHITE) {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_WOLFOS_WHITE]++;
|
||||
} else {
|
||||
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_WOLFOS]++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void RegisterRandomizedEnemySizes() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
|
||||
// Randomized Enemy Sizes
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
|
||||
// Exclude wobbly platforms in Jabu because they need to act like platforms.
|
||||
// Exclude demo effect for Zora sapphire being re-categorized as a "boss".
|
||||
// Exclude Dead Hand hands and Bongo Bongo main body because they make the fights (near) impossible.
|
||||
uint8_t excludedEnemy = actor->id == ACTOR_EN_BROB || actor->id == ACTOR_EN_DHA ||
|
||||
actor->id == ACTOR_DEMO_EFFECT || (actor->id == ACTOR_BOSS_SST && actor->params == -1);
|
||||
|
||||
// Dodongo, Volvagia and Dead Hand are always smaller because they're impossible when bigger.
|
||||
uint8_t smallOnlyEnemy = actor->id == ACTOR_BOSS_DODONGO || actor->id == ACTOR_BOSS_FD ||
|
||||
actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH;
|
||||
|
||||
// Only apply to enemies and bosses.
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemySizes"), 0) ||
|
||||
(actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) {
|
||||
return;
|
||||
}
|
||||
|
||||
float randomNumber;
|
||||
float randomScale;
|
||||
|
||||
uint8_t bigActor = rand() % 2;
|
||||
|
||||
// Big actor
|
||||
if (bigActor && !smallOnlyEnemy) {
|
||||
randomNumber = rand() % 200;
|
||||
// Between 100% and 300% size.
|
||||
randomScale = 1.0f + (randomNumber / 100);
|
||||
} else {
|
||||
// Small actor
|
||||
randomNumber = rand() % 90;
|
||||
// Between 10% and 100% size.
|
||||
randomScale = 0.1f + (randomNumber / 100);
|
||||
}
|
||||
|
||||
Actor_SetScale(actor, actor->scale.z * randomScale);
|
||||
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("EnemySizeScalesHealth"), 0) && (actor->category == ACTORCAT_ENEMY)) {
|
||||
// Scale the health based on a smaller factor than randomScale
|
||||
float healthScalingFactor = 0.8f; // Adjust this factor as needed
|
||||
float scaledHealth = actor->colChkInfo.health * (randomScale * healthScalingFactor);
|
||||
|
||||
// Ensure the scaled health doesn't go below zero
|
||||
actor->colChkInfo.health = fmax(scaledHealth, 1.0f);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void InitMods() {
|
||||
RegisterOcarinaTimeTravel();
|
||||
RegisterHyperBosses();
|
||||
RegisterEnemyDefeatCounts();
|
||||
RegisterRandomizedEnemySizes();
|
||||
}
|
||||
|
||||
@@ -366,6 +366,7 @@ bool GetTimePassFromScene(SceneID scene) {
|
||||
case SCENE_POTION_SHOP_GRANNY:
|
||||
case SCENE_GANON_BOSS:
|
||||
case SCENE_HOUSE_OF_SKULLTULA:
|
||||
case SCENE_KAKARIKO_VILLAGE:
|
||||
case SCENE_KOKIRI_FOREST:
|
||||
case SCENE_SACRED_FOREST_MEADOW:
|
||||
case SCENE_LOST_WOODS:
|
||||
@@ -377,6 +378,7 @@ bool GetTimePassFromScene(SceneID scene) {
|
||||
case SCENE_GERUDOS_FORTRESS:
|
||||
case SCENE_HAUNTED_WASTELAND:
|
||||
case SCENE_DEATH_MOUNTAIN_CRATER:
|
||||
case SCENE_LON_LON_RANCH:
|
||||
case SCENE_ID_MAX:
|
||||
return false;
|
||||
|
||||
@@ -387,14 +389,12 @@ bool GetTimePassFromScene(SceneID scene) {
|
||||
return false;
|
||||
|
||||
case SCENE_HYRULE_FIELD:
|
||||
case SCENE_KAKARIKO_VILLAGE:
|
||||
case SCENE_ZORAS_RIVER:
|
||||
case SCENE_LAKE_HYLIA:
|
||||
case SCENE_GERUDO_VALLEY:
|
||||
case SCENE_DESERT_COLOSSUS:
|
||||
case SCENE_HYRULE_CASTLE:
|
||||
case SCENE_DEATH_MOUNTAIN_TRAIL:
|
||||
case SCENE_LON_LON_RANCH:
|
||||
return true;
|
||||
|
||||
case SCENE_TEST01:
|
||||
|
||||
@@ -258,7 +258,8 @@ bool Logic::HasItem(RandomizerGet itemName) {
|
||||
case RG_OPEN_CHEST:
|
||||
return CheckRandoInf(RAND_INF_CAN_OPEN_CHEST);
|
||||
case RG_POCKET_EGG:
|
||||
return CheckRandoInf(RAND_INF_ADULT_TRADES_HAS_POCKET_EGG);
|
||||
return CheckRandoInf(RAND_INF_ADULT_TRADES_HAS_POCKET_EGG) ||
|
||||
CheckRandoInf(RAND_INF_ADULT_TRADES_HAS_POCKET_CUCCO);
|
||||
case RG_COJIRO:
|
||||
case RG_ODD_MUSHROOM:
|
||||
case RG_ODD_POTION:
|
||||
@@ -2334,6 +2335,21 @@ void Logic::SetQuestItem(uint32_t item, bool state) {
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>& GetThievesHideoutSmallKeyDoors() {
|
||||
// Retrieved from scenes/shared/gerudoway_scene/gerudoway_room_%d
|
||||
// SOH::SceneCommandID::SetActorList, actor.id == ACTOR_DOOR_GERUDO, actor.params & 0x3F
|
||||
static const std::vector<uint8_t> normalSmallKeyDoors{ 1, 2, 3, 4 };
|
||||
static const std::vector<uint8_t> fastSmallKeyDoors{ 1 };
|
||||
static const std::vector<uint8_t> freeSmallKeyDoors{};
|
||||
|
||||
if (RAND_GET_OPTION(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL)) {
|
||||
return normalSmallKeyDoors;
|
||||
} else if (RAND_GET_OPTION(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST)) {
|
||||
return fastSmallKeyDoors;
|
||||
}
|
||||
return freeSmallKeyDoors;
|
||||
}
|
||||
|
||||
// Get the swch bit positions for the dungeon
|
||||
const std::vector<uint8_t>& GetDungeonSmallKeyDoors(SceneID sceneId) {
|
||||
static const std::vector<uint8_t> emptyVector;
|
||||
@@ -2399,7 +2415,8 @@ const std::vector<uint8_t>& GetDungeonSmallKeyDoors(SceneID sceneId) {
|
||||
}
|
||||
|
||||
int8_t Logic::GetUsedSmallKeyCount(SceneID sceneId) {
|
||||
const auto& smallKeyDoors = GetDungeonSmallKeyDoors(sceneId);
|
||||
const auto& smallKeyDoors =
|
||||
(sceneId == SCENE_THIEVES_HIDEOUT) ? GetThievesHideoutSmallKeyDoors() : GetDungeonSmallKeyDoors(sceneId);
|
||||
|
||||
// Get the swch value for the scene
|
||||
uint32_t swch;
|
||||
|
||||
@@ -787,6 +787,14 @@ void DrawQuest(ItemTrackerItem item) {
|
||||
Tooltip(SohUtils::GetQuestItemName(item.id).c_str());
|
||||
};
|
||||
|
||||
bool HasBossSoul(RandomizerInf bossSoul) {
|
||||
uint8_t soulSetting = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BOSS_SOULS);
|
||||
bool isSoulRandomized = IS_RANDO && (soulSetting == RO_BOSS_SOULS_ON_PLUS_GANON ||
|
||||
(soulSetting == RO_BOSS_SOULS_ON && bossSoul != RAND_INF_GANON_SOUL));
|
||||
|
||||
return isSoulRandomized ? Flags_GetRandomizerInf(bossSoul) : true;
|
||||
}
|
||||
|
||||
void DrawItem(ItemTrackerItem item) {
|
||||
|
||||
uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE;
|
||||
@@ -904,50 +912,47 @@ void DrawItem(ItemTrackerItem item) {
|
||||
break;
|
||||
case RG_GOHMA_SOUL:
|
||||
actualItemId = item.id;
|
||||
hasItem = Flags_GetRandomizerInf(RAND_INF_GOHMA_SOUL);
|
||||
hasItem = HasBossSoul(RAND_INF_GOHMA_SOUL);
|
||||
itemName = "Gohma's Soul";
|
||||
break;
|
||||
case RG_KING_DODONGO_SOUL:
|
||||
actualItemId = item.id;
|
||||
hasItem = Flags_GetRandomizerInf(RAND_INF_KING_DODONGO_SOUL);
|
||||
hasItem = HasBossSoul(RAND_INF_KING_DODONGO_SOUL);
|
||||
itemName = "King Dodongo's Soul";
|
||||
break;
|
||||
case RG_BARINADE_SOUL:
|
||||
actualItemId = item.id;
|
||||
hasItem = Flags_GetRandomizerInf(RAND_INF_BARINADE_SOUL);
|
||||
hasItem = HasBossSoul(RAND_INF_BARINADE_SOUL);
|
||||
itemName = "Barinade's Soul";
|
||||
break;
|
||||
case RG_PHANTOM_GANON_SOUL:
|
||||
actualItemId = item.id;
|
||||
hasItem = Flags_GetRandomizerInf(RAND_INF_PHANTOM_GANON_SOUL);
|
||||
hasItem = HasBossSoul(RAND_INF_PHANTOM_GANON_SOUL);
|
||||
itemName = "Phantom Ganon's Soul";
|
||||
break;
|
||||
case RG_VOLVAGIA_SOUL:
|
||||
actualItemId = item.id;
|
||||
hasItem = Flags_GetRandomizerInf(RAND_INF_VOLVAGIA_SOUL);
|
||||
hasItem = HasBossSoul(RAND_INF_VOLVAGIA_SOUL);
|
||||
itemName = "Volvagia's Soul";
|
||||
break;
|
||||
case RG_MORPHA_SOUL:
|
||||
actualItemId = item.id;
|
||||
hasItem = Flags_GetRandomizerInf(RAND_INF_MORPHA_SOUL);
|
||||
hasItem = HasBossSoul(RAND_INF_MORPHA_SOUL);
|
||||
itemName = "Morpha's Soul";
|
||||
break;
|
||||
case RG_BONGO_BONGO_SOUL:
|
||||
actualItemId = item.id;
|
||||
hasItem = Flags_GetRandomizerInf(RAND_INF_BONGO_BONGO_SOUL);
|
||||
hasItem = HasBossSoul(RAND_INF_BONGO_BONGO_SOUL);
|
||||
itemName = "Bongo Bongo's Soul";
|
||||
break;
|
||||
case RG_TWINROVA_SOUL:
|
||||
actualItemId = item.id;
|
||||
hasItem = Flags_GetRandomizerInf(RAND_INF_TWINROVA_SOUL);
|
||||
hasItem = HasBossSoul(RAND_INF_TWINROVA_SOUL);
|
||||
itemName = "Twinrova's Soul";
|
||||
break;
|
||||
case RG_GANON_SOUL:
|
||||
actualItemId = item.id;
|
||||
hasItem = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BOSS_SOULS) ==
|
||||
RO_BOSS_SOULS_ON_PLUS_GANON
|
||||
? Flags_GetRandomizerInf(RAND_INF_GANON_SOUL)
|
||||
: true;
|
||||
hasItem = HasBossSoul(RAND_INF_GANON_SOUL);
|
||||
itemName = "Ganon's Soul";
|
||||
break;
|
||||
|
||||
|
||||
@@ -26,18 +26,12 @@
|
||||
#include "Enhancements/speechsynthesizer/SpeechSynthesizer.h"
|
||||
#include "Enhancements/controls/SohInputEditorWindow.h"
|
||||
#include "Enhancements/audio/AudioCollection.h"
|
||||
#include "Enhancements/enhancementTypes.h"
|
||||
#include "Enhancements/debugconsole.h"
|
||||
#include "Enhancements/randomizer/entrance.h"
|
||||
#include "Enhancements/randomizer/location_access.h"
|
||||
#include "Enhancements/randomizer/randomizer.h"
|
||||
#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
|
||||
#include "Enhancements/randomizer/randomizer_item_tracker.h"
|
||||
#include "Enhancements/randomizer/randomizer_check_tracker.h"
|
||||
#include "Enhancements/randomizer/3drando/random.hpp"
|
||||
#include "Enhancements/randomizer/static_data.h"
|
||||
#include "Enhancements/gameplaystats.h"
|
||||
#include "ObjectExtension/ObjectExtension.h"
|
||||
#include "frame_interpolation.h"
|
||||
#include "SohGui/SohMenu.h"
|
||||
#include "SohGui/SohGui.hpp"
|
||||
@@ -49,7 +43,6 @@
|
||||
#include <ship/window/gui/resource/Font.h>
|
||||
#include <ship/utils/StringHelper.h>
|
||||
#include "Enhancements/custom-message/CustomMessageManager.h"
|
||||
#include "Enhancements/Presets/Presets.h"
|
||||
#include "util.h"
|
||||
|
||||
#if not defined(__SWITCH__) && not defined(__WIIU__)
|
||||
@@ -1474,6 +1467,7 @@ extern "C" void InitOTR(int argc, char* argv[]) {
|
||||
conf->RegisterVersionUpdater(std::make_shared<SOH::ConfigVersion2Updater>());
|
||||
conf->RegisterVersionUpdater(std::make_shared<SOH::ConfigVersion3Updater>());
|
||||
conf->RegisterVersionUpdater(std::make_shared<SOH::ConfigVersion4Updater>());
|
||||
conf->RegisterVersionUpdater(std::make_shared<SOH::ConfigVersion5Updater>());
|
||||
conf->RunVersionUpdates();
|
||||
|
||||
SohGui::SetupGuiElements();
|
||||
@@ -2165,7 +2159,7 @@ Color_RGB8 GetColorForControllerLED() {
|
||||
if (HealthMeter_IsCritical()) {
|
||||
color = { 0xFF, 0, 0 };
|
||||
} else if (gSaveContext.healthCapacity != 0 && source == LED_SOURCE_HEALTH) {
|
||||
if (gSaveContext.health / gSaveContext.healthCapacity <= 0.4f) {
|
||||
if (gSaveContext.health / (float)gSaveContext.healthCapacity <= 0.4f) {
|
||||
color = { 0xFF, 0xFF, 0 };
|
||||
} else {
|
||||
color = { 0, 0xFF, 0 };
|
||||
|
||||
@@ -659,18 +659,15 @@ void Menu::DrawElement() {
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
float centerX = pos.x + windowWidth / 2 - (style.ItemSpacing.x * (menuEntries.size() + 1));
|
||||
std::vector<ImVec2> headerSizes;
|
||||
float headerWidth = style.ItemSpacing.x + 20;
|
||||
float headerWidth = 0.0f;
|
||||
bool headerSearch = !CVarGetInteger(CVAR_SETTING("Menu.SidebarSearch"), 0);
|
||||
if (headerSearch) {
|
||||
headerWidth += 200.0f + style.ItemSpacing.x + style.FramePadding.x;
|
||||
headerWidth += 200.0f;
|
||||
}
|
||||
for (auto& label : menuOrder) {
|
||||
ImVec2 size = ImGui::CalcTextSize(label.c_str());
|
||||
headerSizes.push_back(size);
|
||||
headerWidth += size.x + style.FramePadding.x * 2;
|
||||
if (label == headerIndex) {
|
||||
headerWidth += style.ItemSpacing.x;
|
||||
}
|
||||
headerWidth += size.x + style.FramePadding.x * 2 + style.ItemSpacing.x;
|
||||
}
|
||||
|
||||
// Full screen menu with widths below 1280, heights below 800.
|
||||
|
||||
@@ -11,6 +11,8 @@ ConfigVersion3Updater::ConfigVersion3Updater() : ConfigVersionUpdater(3) {
|
||||
}
|
||||
ConfigVersion4Updater::ConfigVersion4Updater() : ConfigVersionUpdater(4) {
|
||||
}
|
||||
ConfigVersion5Updater::ConfigVersion5Updater() : ConfigVersionUpdater(5) {
|
||||
}
|
||||
|
||||
void ConfigVersion1Updater::Update(Ship::Config* conf) {
|
||||
if (conf->GetInt("Window.Width", 640) == 640) {
|
||||
@@ -122,4 +124,11 @@ void ConfigVersion4Updater::Update(Ship::Config* conf) {
|
||||
CVarClear(migration.from.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigVersion5Updater::Update(Ship::Config* conf) {
|
||||
// After removal of Vanilla, make sure it doesn't crash because of an out of range on the combobox
|
||||
if (CVarGetInteger("gRandoSettings.LogicRules", 0) == 2) {
|
||||
CVarSetInteger("gRandoSettings.LogicRules", 0);
|
||||
}
|
||||
}
|
||||
} // namespace SOH
|
||||
|
||||
@@ -24,4 +24,10 @@ class ConfigVersion4Updater final : public Ship::ConfigVersionUpdater {
|
||||
ConfigVersion4Updater();
|
||||
void Update(Ship::Config* conf);
|
||||
};
|
||||
|
||||
class ConfigVersion5Updater final : public Ship::ConfigVersionUpdater {
|
||||
public:
|
||||
ConfigVersion5Updater();
|
||||
void Update(Ship::Config* conf);
|
||||
};
|
||||
} // namespace SOH
|
||||
|
||||
@@ -725,11 +725,7 @@ void EnFz_Draw(Actor* thisx, PlayState* play) {
|
||||
// SOH [Enhancement] - With enemy health scaling, the Freezards health could cause an index out of bounds for the
|
||||
// displayLists, so we need to recompute the index based on the scaled health (using the maximum health value) and
|
||||
// clamp the final result for safety.
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("EnemySizeScalesHealth"), 0)) {
|
||||
u8 scaledHealth = (u8)(((f32)this->actor.colChkInfo.health / GetActorMaximumHealth(this)) * 6);
|
||||
index = (6 - scaledHealth) >> 1;
|
||||
index = CLAMP(index, 0, 2);
|
||||
}
|
||||
GameInteractor_Should(VB_FREEZARD_SCALE_HEALTH_WITH_SIZE, false, this, &index);
|
||||
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
|
||||
|
||||
@@ -8307,19 +8307,20 @@ void Player_ChooseNextIdleAnim(PlayState* play, Player* this) {
|
||||
//
|
||||
// Note that `FIDGET_SWORD_SWING` is the first common fidget type, which is why
|
||||
// all operations are done relative to this type.
|
||||
if (((commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)) ||
|
||||
((this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||
((commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD) ||
|
||||
(Player_GetMeleeWeaponHeld2(this) != 0)))) {
|
||||
if (GameInteractor_Should(VB_SET_IDLE_ANIM,
|
||||
(((commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)) ||
|
||||
((this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||
((commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD) ||
|
||||
(Player_GetMeleeWeaponHeld2(this) != 0)))),
|
||||
this, commonType)) {
|
||||
//! @bug It is possible for `FIDGET_ADJUST_SHIELD` to be used even if
|
||||
//! a shield is not currently equipped. This is because of how being shieldless
|
||||
//! is implemented. There is no sword-only model type, only
|
||||
//! `PLAYER_MODELGROUP_SWORD_AND_SHIELD` exists. Therefore, the right hand type will be
|
||||
//! `PLAYER_MODELTYPE_RH_SHIELD` if sword is in hand, even if no shield is equipped.
|
||||
if ((commonType + FIDGET_SWORD_SWING == FIDGET_SWORD_SWING) &&
|
||||
Player_HoldsTwoHandedWeapon(this) &&
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TwoHandedIdle"), 0) == 1) {
|
||||
Player_HoldsTwoHandedWeapon(this)) {
|
||||
//! @bug This code is unreachable.
|
||||
//! The check above groups the `Player_GetMeleeWeaponHeld2` check and
|
||||
//! `PLAYER_MODELTYPE_RH_SHIELD` conditions together, meaning sword and shield must be
|
||||
@@ -12767,7 +12768,8 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) {
|
||||
|
||||
if (!func_8002DD78(this) && !func_808334B4(this) && (arg2 == 0)) { // First person without weapon
|
||||
// Y Axis
|
||||
if (!CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0)) {
|
||||
if (!(CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0) &&
|
||||
CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0))) {
|
||||
temp2 += sControlInput->rel.stick_y * 240.0f * invertYAxisMulti * yAxisMulti;
|
||||
}
|
||||
if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) {
|
||||
@@ -12785,7 +12787,8 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) {
|
||||
|
||||
// X Axis
|
||||
temp2 = 0;
|
||||
if (!CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0)) {
|
||||
if (!(CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0) &&
|
||||
CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0))) {
|
||||
temp2 += sControlInput->rel.stick_x * -16.0f * invertXAxisMulti * xAxisMulti;
|
||||
}
|
||||
if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) {
|
||||
@@ -12800,7 +12803,8 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) {
|
||||
// Y Axis
|
||||
temp1 = (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) ? 3500 : 14000;
|
||||
|
||||
if (!CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0)) {
|
||||
if (!(CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0) &&
|
||||
CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0))) {
|
||||
temp3 += ((sControlInput->rel.stick_y >= 0) ? 1 : -1) *
|
||||
(s32)((1.0f - Math_CosS(sControlInput->rel.stick_y * 200)) * 1500.0f) * invertYAxisMulti *
|
||||
yAxisMulti;
|
||||
@@ -12820,7 +12824,8 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) {
|
||||
temp1 = 19114;
|
||||
temp2 = this->actor.focus.rot.y - this->actor.shape.rot.y;
|
||||
temp3 = 0;
|
||||
if (!CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0)) {
|
||||
if (!(CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0) &&
|
||||
CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0))) {
|
||||
temp3 = ((sControlInput->rel.stick_x >= 0) ? 1 : -1) *
|
||||
(s32)((1.0f - Math_CosS(sControlInput->rel.stick_x * 200)) * -1500.0f) * invertXAxisMulti *
|
||||
xAxisMulti;
|
||||
@@ -12837,7 +12842,8 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) {
|
||||
this->actor.focus.rot.y = CLAMP(temp2, -temp1, temp1) + this->actor.shape.rot.y;
|
||||
}
|
||||
|
||||
if (CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0)) {
|
||||
if (CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0) &&
|
||||
CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) {
|
||||
f32 movementSpeed = LINK_IS_ADULT ? 9.0f : 8.25f;
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA &&
|
||||
this->currentMask == PLAYER_MASK_BUNNY) {
|
||||
|
||||
Reference in New Issue
Block a user