Merge remote-tracking branch 'origin/develop' into rando-dev-merge-feb

This commit is contained in:
Adam Bird 2024-02-21 02:01:25 -05:00
commit b5c601f43e
333 changed files with 5019 additions and 4558 deletions

View File

@ -0,0 +1,61 @@
name: test-builds-on-distros
on:
workflow_dispatch: # by request
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
matrix:
image: ["archlinux:base", "opensuse/tumbleweed:latest", "ubuntu:mantic", "debian:bookworm", "fedora:39"]
cc: ["gcc", "clang"]
include:
- cxx: g++
cc: gcc
- cxx: clang++
cc: clang
runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }}
container:
image: ${{ matrix.image }}
steps:
- name: Install dependencies (pacman)
if: ${{ matrix.image == 'archlinux:base' }}
run: |
echo arch
echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng sdl2_net boost
pacman -Syu --noconfirm
pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng sdl2_net boost
- name: Install dependencies (dnf)
if: ${{ matrix.image == 'fedora:39' }}
run: |
echo fedora
echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel
dnf -y upgrade
dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel
- name: Install dependencies (apt)
if: ${{ matrix.image == 'ubuntu:mantic' || matrix.image == 'debian:bookworm' }}
run: |
echo debian based
echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev
apt-get update
apt-get -y full-upgrade
apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev
- name: Install dependencies (zypper)
if: ${{ matrix.image == 'opensuse/tumbleweed:latest' }}
run: |
echo openSUSE
echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel
zypper --non-interactive dup
zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel
- uses: actions/checkout@v3
with:
submodules: true
- name: Build SoH
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_REMOTE_CONTROL=1
cmake --build build-cmake --config Release -j3
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}

@ -1 +1 @@
Subproject commit d8f3c4dd4a46fb46c4f69cd387afadfa711606e9
Subproject commit e93bd2be062b13106fdb29d98cf4ada4d7ad6827

View File

@ -84,17 +84,49 @@ cd "build/x64"
```
## Linux
Requires `gcc >= 10, x11, curl, python3, sdl2 >= 2.0.22, libpng, glew >= 2.2, ninja, cmake, lld, pulseaudio-libs`
### Install dependencies
#### Debian/Ubuntu
```sh
# using gcc
apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev
**Important: For maximum performance make sure you have ninja build tools installed!**
# or using clang
apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev
```
#### Arch
```sh
# using gcc
pacman -S gcc git cmake ninja lsb-release sdl2 libpng sdl2_net boost
_Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
# or using clang
pacman -S clang git cmake ninja lsb-release sdl2 libpng sdl2_net boost
```
#### Fedora
```sh
# using gcc
dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel
# or using clang
dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel
```
#### openSUSE
```sh
# using gcc
zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel boost
# or using clang
zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel boost
```
### Build
_Note: If you're using Visual Studio Code, the [CMake Tools plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
```bash
# Clone the repo
git clone https://github.com/HarbourMasters/Shipwright.git
cd Shipwright
# Clone the submodule libultraship
# Clone the submodules
git submodule update --init
# Copy the baserom to the OTRExporter folder
cp <path to your ROM> OTRExporter

@ -1 +1 @@
Subproject commit d5a39635a118f814613c0fdd1601f80c809a742d
Subproject commit a516b66ce0c89fe4e33c55b1fbfbde845d0bf129

View File

@ -356,7 +356,13 @@ set(SDL2-INCLUDE ${SDL2_INCLUDE_DIRS})
if (BUILD_REMOTE_CONTROL)
find_package(SDL2_net)
set(SDL2-NET-INCLUDE ${SDL_NET_INCLUDE_DIRS})
if(NOT SDL2_net_FOUND)
message(STATUS "SDL2_net not found (it's possible the version installed is too old). Disabling BUILD_REMOTE_CONTROL.")
set(BUILD_REMOTE_CONTROL 0)
else()
set(SDL2-NET-INCLUDE ${SDL_NET_INCLUDE_DIRS})
endif()
endif()
target_include_directories(${PROJECT_NAME} PRIVATE assets
@ -623,6 +629,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
-Wno-parentheses
-Wno-narrowing
-Wno-missing-braces
-Wno-int-conversion
-Wno-implicit-int
$<$<COMPILE_LANGUAGE:C>:
-Werror-implicit-function-declaration
-Wno-incompatible-pointer-types

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 984 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 922 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 379 B

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 973 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -345,7 +345,7 @@ typedef enum {
#define PLAYER_LIMB_BUF_COUNT LIMB_BUF_COUNT(PLAYER_LIMB_MAX)
typedef struct {
/* 0x00 */ f32 unk_00;
/* 0x00 */ f32 ceilingCheckHeight;
/* 0x04 */ f32 unk_04;
/* 0x08 */ f32 unk_08;
/* 0x0C */ f32 unk_0C;
@ -359,7 +359,7 @@ typedef struct {
/* 0x2C */ f32 unk_2C;
/* 0x30 */ f32 unk_30;
/* 0x34 */ f32 unk_34;
/* 0x38 */ f32 unk_38;
/* 0x38 */ f32 wallCheckRadius;
/* 0x3C */ f32 unk_3C;
/* 0x40 */ f32 unk_40;
/* 0x44 */ Vec3s unk_44;
@ -489,180 +489,187 @@ typedef s32 (*UpperActionFunc)(struct Player*, struct PlayState*);
typedef void (*PlayerFuncA74)(struct PlayState*, struct Player*);
typedef struct Player {
/* 0x0000 */ Actor actor;
/* 0x014C */ s8 currentTunic; // current tunic from `PlayerTunic`
/* 0x014D */ s8 currentSwordItemId;
/* 0x014E */ s8 currentShield; // current shield from `PlayerShield`
/* 0x014F */ s8 currentBoots; // current boots from `PlayerBoots`
/* 0x0150 */ s8 heldItemButton; // Button index for the item currently used
/* 0x0151 */ s8 heldItemAction; // Item action for the item currently used
/* 0x0152 */ u8 heldItemId; // Item id for the item currently used
/* 0x0153 */ s8 prevBoots; // previous boots from `PlayerBoots`
/* 0x0154 */ s8 itemAction; // the difference between this and heldItemAction is unclear
/* 0x0155 */ char unk_155[0x003];
/* 0x0158 */ u8 modelGroup;
/* 0x0159 */ u8 nextModelGroup;
/* 0x015A */ s8 itemChangeType;
/* 0x015B */ u8 modelAnimType;
/* 0x015C */ u8 leftHandType;
/* 0x015D */ u8 rightHandType;
/* 0x015E */ u8 sheathType;
/* 0x015F */ u8 currentMask; // current mask equipped from `PlayerMask`
/* 0x0160 */ Gfx** rightHandDLists;
/* 0x0164 */ Gfx** leftHandDLists;
/* 0x0168 */ Gfx** sheathDLists;
/* 0x016C */ Gfx** waistDLists;
/* 0x0170 */ u8 giObjectLoading;
/* 0x0000 */ Actor actor;
/* 0x014C */ s8 currentTunic; // current tunic from `PlayerTunic`
/* 0x014D */ s8 currentSwordItemId;
/* 0x014E */ s8 currentShield; // current shield from `PlayerShield`
/* 0x014F */ s8 currentBoots; // current boots from `PlayerBoots`
/* 0x0150 */ s8 heldItemButton; // Button index for the item currently used
/* 0x0151 */ s8 heldItemAction; // Item action for the item currently used
/* 0x0152 */ u8 heldItemId; // Item id for the item currently used
/* 0x0153 */ s8 prevBoots; // previous boots from `PlayerBoots`
/* 0x0154 */ s8 itemAction; // the difference between this and heldItemAction is unclear
/* 0x0155 */ char unk_155[0x003];
/* 0x0158 */ u8 modelGroup;
/* 0x0159 */ u8 nextModelGroup;
/* 0x015A */ s8 itemChangeType;
/* 0x015B */ u8 modelAnimType;
/* 0x015C */ u8 leftHandType;
/* 0x015D */ u8 rightHandType;
/* 0x015E */ u8 sheathType;
/* 0x015F */ u8 currentMask; // current mask equipped from `PlayerMask`
/* 0x0160 */ Gfx** rightHandDLists;
/* 0x0164 */ Gfx** leftHandDLists;
/* 0x0168 */ Gfx** sheathDLists;
/* 0x016C */ Gfx** waistDLists;
/* 0x0170 */ u8 giObjectLoading;
/* 0x0174 */ DmaRequest giObjectDmaRequest;
/* 0x0194 */ OSMesgQueue giObjectLoadQueue;
/* 0x01AC */ OSMesg giObjectLoadMsg;
/* 0x01B0 */ void* giObjectSegment; // also used for title card textures
/* 0x01B4 */ SkelAnime skelAnime;
/* 0x01F8 */ Vec3s jointTable[PLAYER_LIMB_BUF_COUNT];
/* 0x0288 */ Vec3s morphTable[PLAYER_LIMB_BUF_COUNT];
/* 0x0318 */ Vec3s blendTable[PLAYER_LIMB_BUF_COUNT];
/* 0x03A8 */ s16 unk_3A8[2];
/* 0x03AC */ Actor* heldActor;
/* 0x03B0 */ Vec3f leftHandPos;
/* 0x03BC */ Vec3s unk_3BC;
/* 0x03C4 */ Actor* unk_3C4;
/* 0x03C8 */ Vec3f unk_3C8;
/* 0x03D4 */ char unk_3D4[0x058];
/* 0x042C */ s8 doorType;
/* 0x042D */ s8 doorDirection;
/* 0x042E */ s16 doorTimer;
/* 0x0430 */ Actor* doorActor;
/* 0x0434 */ s16 getItemId; // Upstream TODO: Document why this is s16 while it's s8 upstream
/* 0x0436 */ u16 getItemDirection;
/* 0x0438 */ Actor* interactRangeActor;
/* 0x043C */ s8 mountSide;
/* 0x043D */ char unk_43D[0x003];
/* 0x0440 */ Actor* rideActor;
/* 0x0444 */ u8 csAction;
/* 0x0445 */ u8 prevCsAction;
/* 0x0446 */ u8 cueId;
/* 0x0447 */ u8 unk_447;
/* 0x0448 */ Actor* csActor;
/* 0x044C */ char unk_44C[0x004];
/* 0x0450 */ Vec3f unk_450;
/* 0x045C */ Vec3f unk_45C;
/* 0x0468 */ char unk_468[0x002];
/* 0x046A */ s16 doorBgCamIndex;
/* 0x046C */ s16 subCamId;
/* 0x046E */ char unk_46E[0x02A];
/* 0x01AC */ OSMesg giObjectLoadMsg;
/* 0x01B0 */ void* giObjectSegment; // also used for title card textures
/* 0x01B4 */ SkelAnime skelAnime;
/* 0x01F8 */ Vec3s jointTable[PLAYER_LIMB_BUF_COUNT];
/* 0x0288 */ Vec3s morphTable[PLAYER_LIMB_BUF_COUNT];
/* 0x0318 */ Vec3s blendTable[PLAYER_LIMB_BUF_COUNT];
/* 0x03A8 */ s16 unk_3A8[2];
/* 0x03AC */ Actor* heldActor;
/* 0x03B0 */ Vec3f leftHandPos;
/* 0x03BC */ Vec3s unk_3BC;
/* 0x03C4 */ Actor* unk_3C4;
/* 0x03C8 */ Vec3f unk_3C8;
/* 0x03D4 */ char unk_3D4[0x058];
/* 0x042C */ s8 doorType;
/* 0x042D */ s8 doorDirection;
/* 0x042E */ s16 doorTimer;
/* 0x0430 */ Actor* doorActor;
/* 0x0434 */ s16 getItemId; // Upstream TODO: Document why this is s16 while it's s8 upstream
/* 0x0436 */ u16 getItemDirection;
/* 0x0438 */ Actor* interactRangeActor;
/* 0x043C */ s8 mountSide;
/* 0x043D */ char unk_43D[0x003];
/* 0x0440 */ Actor* rideActor;
/* 0x0444 */ u8 csAction;
/* 0x0445 */ u8 prevCsAction;
/* 0x0446 */ u8 cueId;
/* 0x0447 */ u8 unk_447;
/* 0x0448 */ Actor* csActor; // Actor involved in a `csAction`. Typically the actor that invoked the cutscene.
/* 0x044C */ char unk_44C[0x004];
/* 0x0450 */ Vec3f unk_450;
/* 0x045C */ Vec3f unk_45C;
/* 0x0468 */ char unk_468[0x002];
/* 0x046A */ s16 doorBgCamIndex;
/* 0x046C */ s16 subCamId;
/* 0x046E */ char unk_46E[0x02A];
/* 0x0498 */ ColliderCylinder cylinder;
/* 0x04E4 */ ColliderQuad meleeWeaponQuads[2];
/* 0x05E4 */ ColliderQuad shieldQuad;
/* 0x0664 */ Actor* unk_664;
/* 0x0668 */ char unk_668[0x004];
/* 0x066C */ s32 unk_66C;
/* 0x0670 */ s32 meleeWeaponEffectIndex;
/* 0x0664 */ Actor* unk_664;
/* 0x0668 */ char unk_668[0x004];
/* 0x066C */ s32 unk_66C;
/* 0x0670 */ s32 meleeWeaponEffectIndex;
/* 0x0674 */ PlayerActionFunc actionFunc;
/* 0x0678 */ PlayerAgeProperties* ageProperties;
/* 0x067C */ u32 stateFlags1;
/* 0x0680 */ u32 stateFlags2;
/* 0x0684 */ Actor* unk_684;
/* 0x0688 */ Actor* boomerangActor;
/* 0x068C */ Actor* naviActor;
/* 0x0690 */ s16 naviTextId;
/* 0x0692 */ u8 stateFlags3;
/* 0x0693 */ s8 exchangeItemId;
/* 0x0694 */ Actor* targetActor;
/* 0x0698 */ f32 targetActorDistance;
/* 0x069C */ char unk_69C[0x004];
/* 0x06A0 */ f32 unk_6A0;
/* 0x06A4 */ f32 closestSecretDistSq;
/* 0x06A8 */ Actor* unk_6A8;
/* 0x06AC */ s8 unk_6AC;
/* 0x06AD */ u8 unk_6AD;
/* 0x06AE */ u16 unk_6AE;
/* 0x06B0 */ s16 unk_6B0;
/* 0x06B2 */ char unk_6B4[0x004];
/* 0x06B6 */ s16 unk_6B6;
/* 0x06B8 */ s16 unk_6B8;
/* 0x06BA */ s16 unk_6BA;
/* 0x06BC */ s16 unk_6BC;
/* 0x06BE */ s16 unk_6BE;
/* 0x06C0 */ s16 unk_6C0;
/* 0x06C2 */ s16 unk_6C2;
/* 0x06C4 */ f32 unk_6C4;
/* 0x06C8 */ SkelAnime upperSkelAnime;
/* 0x070C */ Vec3s upperJointTable[PLAYER_LIMB_BUF_COUNT];
/* 0x079C */ Vec3s upperMorphTable[PLAYER_LIMB_BUF_COUNT];
/* 0x067C */ u32 stateFlags1;
/* 0x0680 */ u32 stateFlags2;
/* 0x0684 */ Actor* unk_684;
/* 0x0688 */ Actor* boomerangActor;
/* 0x068C */ Actor* naviActor;
/* 0x0690 */ s16 naviTextId;
/* 0x0692 */ u8 stateFlags3;
/* 0x0693 */ s8 exchangeItemId;
/* 0x0694 */ Actor* targetActor;
/* 0x0698 */ f32 targetActorDistance;
/* 0x069C */ char unk_69C[0x004];
/* 0x06A0 */ f32 unk_6A0;
/* 0x06A4 */ f32 closestSecretDistSq;
/* 0x06A8 */ Actor* unk_6A8;
/* 0x06AC */ s8 unk_6AC;
/* 0x06AD */ u8 unk_6AD;
/* 0x06AE */ u16 unk_6AE;
/* 0x06B0 */ s16 unk_6B0;
/* 0x06B2 */ char unk_6B4[0x004];
/* 0x06B6 */ s16 unk_6B6;
/* 0x06B8 */ s16 unk_6B8;
/* 0x06BA */ s16 unk_6BA;
/* 0x06BC */ s16 unk_6BC;
/* 0x06BE */ s16 unk_6BE;
/* 0x06C0 */ s16 unk_6C0;
/* 0x06C2 */ s16 unk_6C2;
/* 0x06C4 */ f32 unk_6C4;
/* 0x06C8 */ SkelAnime upperSkelAnime;
/* 0x070C */ Vec3s upperJointTable[PLAYER_LIMB_BUF_COUNT];
/* 0x079C */ Vec3s upperMorphTable[PLAYER_LIMB_BUF_COUNT];
/* 0x082C */ UpperActionFunc upperActionFunc;
/* 0x0830 */ f32 upperAnimBlendWeight;
/* 0x0834 */ s16 unk_834;
/* 0x0836 */ s8 unk_836;
/* 0x0837 */ u8 unk_837;
/* 0x0838 */ f32 linearVelocity;
/* 0x083C */ s16 currentYaw;
/* 0x083E */ s16 targetYaw;
/* 0x0840 */ u16 underwaterTimer;
/* 0x0842 */ s8 meleeWeaponAnimation;
/* 0x0843 */ s8 meleeWeaponState;
/* 0x0844 */ s8 unk_844;
/* 0x0845 */ u8 unk_845;
/* 0x0846 */ u8 unk_846;
/* 0x0847 */ s8 unk_847[4];
/* 0x084B */ s8 unk_84B[4];
/* 0x084F */ s8 unk_84F;
/* 0x0850 */ s16 unk_850; // multipurpose timer
/* 0x0854 */ f32 unk_854;
/* 0x0858 */ f32 unk_858;
/* 0x085C */ f32 unk_85C; // stick length among other things
/* 0x0860 */ s16 unk_860; // stick flame timer among other things
/* 0x0862 */ s16 unk_862; // get item draw ID + 1
/* 0x0864 */ f32 unk_864;
/* 0x0868 */ f32 unk_868;
/* 0x086C */ f32 unk_86C;
/* 0x0870 */ f32 unk_870;
/* 0x0874 */ f32 unk_874;
/* 0x0878 */ f32 unk_878;
/* 0x087C */ s16 unk_87C;
/* 0x087E */ s16 unk_87E;
/* 0x0880 */ f32 unk_880;
/* 0x0884 */ f32 yDistToLedge; // y distance to ground above an interact wall. LEDGE_DIST_MAX if no ground is found
/* 0x0888 */ f32 distToInteractWall; // distance to the colliding wall plane
/* 0x088C */ u8 unk_88C;
/* 0x088D */ u8 unk_88D;
/* 0x088E */ u8 unk_88E;
/* 0x088F */ u8 unk_88F;
/* 0x0890 */ u8 unk_890;
/* 0x0891 */ u8 shockTimer;
/* 0x0892 */ u8 unk_892;
/* 0x0893 */ u8 hoverBootsTimer;
/* 0x0894 */ s16 fallStartHeight; // last truncated Y position before falling
/* 0x0896 */ s16 fallDistance; // truncated Y distance the player has fallen so far (positive is down)
/* 0x0898 */ s16 floorPitch; // angle of the floor slope in the direction of current world yaw (positive for ascending slope)
/* 0x089A */ s16 floorPitchAlt; // the calculation for this value is bugged and doesn't represent anything meaningful
/* 0x089C */ s16 unk_89C;
/* 0x089E */ u16 floorSfxOffset;
/* 0x08A0 */ u8 unk_8A0;
/* 0x08A1 */ u8 unk_8A1;
/* 0x08A2 */ s16 unk_8A2;
/* 0x08A4 */ f32 unk_8A4;
/* 0x08A8 */ f32 unk_8A8;
/* 0x08AC */ f32 pushedSpeed; // Pushing player, examples include water currents, floor conveyors, climbing sloped surfaces
/* 0x08B0 */ s16 pushedYaw; // Yaw direction of player being pushed
/* 0x0830 */ f32 upperAnimBlendWeight;
/* 0x0834 */ s16 unk_834;
/* 0x0836 */ s8 unk_836;
/* 0x0837 */ u8 unk_837;
/* 0x0838 */ f32 linearVelocity;
/* 0x083C */ s16 yaw; // General yaw value, used both for world and shape rotation. Current or target value depending on context.
/* 0x083E */ s16 zTargetYaw; // yaw relating to Z targeting/"parallel" mode
/* 0x0840 */ u16 underwaterTimer;
/* 0x0842 */ s8 meleeWeaponAnimation;
/* 0x0843 */ s8 meleeWeaponState;
/* 0x0844 */ s8 unk_844;
/* 0x0845 */ u8 unk_845;
/* 0x0846 */ u8 unk_846;
/* 0x0847 */ s8 unk_847[4];
/* 0x084B */ s8 unk_84B[4];
/* 0x084F */ union {
s8 actionVar1;
} av1; // "Action Variable 1": context dependent variable that has different meanings depending on what action is currently running
/* 0x0850 */ union {
s16 actionVar2;
} av2; // "Action Variable 2": context dependent variable that has different meanings depending on what action is currently running
/* 0x0854 */ f32 unk_854;
/* 0x0858 */ f32 unk_858;
/* 0x085C */ f32 unk_85C; // stick length among other things
/* 0x0860 */ s16 unk_860; // stick flame timer among other things
/* 0x0862 */ s16 unk_862; // get item draw ID + 1
/* 0x0864 */ f32 unk_864;
/* 0x0868 */ f32 unk_868;
/* 0x086C */ f32 unk_86C;
/* 0x0870 */ f32 unk_870;
/* 0x0874 */ f32 unk_874;
/* 0x0878 */ f32 unk_878;
/* 0x087C */ s16 unk_87C;
/* 0x087E */ s16 unk_87E;
/* 0x0880 */ f32 unk_880;
/* 0x0884 */ f32 yDistToLedge; // y distance to ground above an interact wall. LEDGE_DIST_MAX if no ground is found
/* 0x0888 */ f32 distToInteractWall; // xyz distance to the interact wall
/* 0x088C */ u8 ledgeClimbType;
/* 0x088D */ u8 ledgeClimbDelayTimer;
/* 0x088E */ u8 unk_88E;
/* 0x088F */ u8 unk_88F;
/* 0x0890 */ u8 unk_890;
/* 0x0891 */ u8 bodyShockTimer;
/* 0x0892 */ u8 unk_892;
/* 0x0893 */ u8 hoverBootsTimer;
/* 0x0894 */ s16 fallStartHeight; // last truncated Y position before falling
/* 0x0896 */ s16 fallDistance; // truncated Y distance the player has fallen so far (positive is down)
/* 0x0898 */ s16 floorPitch; // angle of the floor slope in the direction of current world yaw (positive for ascending slope)
/* 0x089A */ s16 floorPitchAlt; // the calculation for this value is bugged and doesn't represent anything meaningful
/* 0x089C */ s16 unk_89C;
/* 0x089E */ u16 floorSfxOffset;
/* 0x08A0 */ u8 unk_8A0;
/* 0x08A1 */ u8 unk_8A1;
/* 0x08A2 */ s16 unk_8A2;
/* 0x08A4 */ f32 unk_8A4;
/* 0x08A8 */ f32 unk_8A8;
/* 0x08AC */ f32 pushedSpeed; // Pushing player, examples include water currents, floor conveyors, climbing sloped surfaces
/* 0x08B0 */ s16 pushedYaw; // Yaw direction of player being pushed
/* 0x08B4 */ WeaponInfo meleeWeaponInfo[3];
/* 0x0908 */ Vec3f bodyPartsPos[PLAYER_BODYPART_MAX];
/* 0x09E0 */ MtxF mf_9E0;
/* 0x0A20 */ MtxF shieldMf;
/* 0x0A60 */ u8 isBurning;
/* 0x0A61 */ u8 flameTimers[PLAYER_BODYPART_MAX]; // one flame per body part
/* 0x0A73 */ u8 unk_A73;
/* 0x0908 */ Vec3f bodyPartsPos[PLAYER_BODYPART_MAX];
/* 0x09E0 */ MtxF mf_9E0;
/* 0x0A20 */ MtxF shieldMf;
/* 0x0A60 */ u8 bodyIsBurning;
/* 0x0A61 */ u8 bodyFlameTimers[PLAYER_BODYPART_MAX]; // one flame per body part
/* 0x0A73 */ u8 unk_A73;
/* 0x0A74 */ PlayerFuncA74 func_A74;
/* 0x0A78 */ s8 invincibilityTimer; // prevents damage when nonzero (positive = visible, counts towards zero each frame)
/* 0x0A79 */ u8 unk_A79;
/* 0x0A7A */ u8 unk_A7A;
/* 0x0A7B */ u8 unk_A7B;
/* 0x0A7C */ f32 unk_A7C;
/* 0x0A80 */ s16 unk_A80;
/* 0x0A82 */ u16 unk_A82;
/* 0x0A84 */ s16 unk_A84;
/* 0x0A86 */ s8 unk_A86;
/* 0x0A87 */ u8 unk_A87;
/* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position
/* 0x0A78 */ s8 invincibilityTimer; // prevents damage when nonzero (positive = visible, counts towards zero each frame)
/* 0x0A79 */ u8 floorTypeTimer; // counts up every frame the current floor type is the same as the last frame
/* 0x0A7A */ u8 floorProperty;
/* 0x0A7B */ u8 prevFloorType;
/* 0x0A7C */ f32 prevControlStickMagnitude;
/* 0x0A80 */ s16 prevControlStickAngle;
/* 0x0A82 */ u16 prevFloorSfxOffset;
/* 0x0A84 */ s16 unk_A84;
/* 0x0A86 */ s8 unk_A86;
/* 0x0A87 */ u8 unk_A87;
/* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position
// #region SOH [General]
// Upstream TODO: Rename these to be more obviously SoH specific
/* */ PendingFlag pendingFlag;
@ -670,7 +677,7 @@ typedef struct Player {
// #endregion
// #region SOH [Enhancements]
// Upstream TODO: Rename this to make it more obvious it is apart of an enhancement
/* */ u8 boomerangQuickRecall; // Has the player pressed the boomerang button while it's in the air still?
/* */ u8 boomerangQuickRecall; // Has the player pressed the boomerang button while it's in the air still?
// #endregion
u8 ivanFloating;
u8 ivanDamageMultiplier;

View File

@ -0,0 +1,519 @@
#include "InputViewer.h"
#include "public/bridge/consolevariablebridge.h"
#include "libultraship/libultra/controller.h"
#include "Context.h"
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include <ImGui/imgui.h>
#include <spdlog/spdlog.h>
#include <cmath>
#include "../../UIWidgets.hpp"
// Text colors
static ImVec4 textColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
static ImVec4 range1Color = ImVec4(1.0f, 0.7f, 0, 1.0f);
static ImVec4 range2Color = ImVec4(0, 1.0f, 0, 1.0f);
static const char* buttonOutlineOptions[4] = { "Always Shown", "Shown Only While Not Pressed",
"Shown Only While Pressed", "Always Hidden" };
static const char* stickModeOptions[3] = { "Always", "While In Use", "Never" };
static Color_RGBA8 vec2Color(ImVec4 vec) {
Color_RGBA8 color;
color.r = vec.x * 255.0;
color.g = vec.y * 255.0;
color.b = vec.z * 255.0;
color.a = vec.w * 255.0;
return color;
}
static ImVec4 color2Vec(Color_RGBA8 color) {
return ImVec4(color.r / 255.0, color.g / 255.0, color.b / 255.0, color.a / 255.0);
}
InputViewer::~InputViewer() {
SPDLOG_TRACE("destruct input viewer");
}
void InputViewer::RenderButton(std::string btnTexture, std::string btnOutlineTexture, int state, ImVec2 size,
int outlineMode) {
const ImVec2 pos = ImGui::GetCursorPos();
ImGui::SetNextItemAllowOverlap();
// Render Outline based on settings
if (outlineMode == BUTTON_OUTLINE_ALWAYS_SHOWN || (outlineMode == BUTTON_OUTLINE_NOT_PRESSED && !state) ||
(outlineMode == BUTTON_OUTLINE_PRESSED && state)) {
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnOutlineTexture), size,
ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
}
// Render button if pressed
if (state) {
ImGui::SetCursorPos(pos);
ImGui::SetNextItemAllowOverlap();
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnTexture), size,
ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
}
}
void InputViewer::DrawElement() {
if (CVarGetInteger("gOpenWindows.InputViewer", 0)) {
static bool sButtonTexturesLoaded = false;
if (!sButtonTexturesLoaded) {
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Input-Viewer-Background", "textures/buttons/InputViewerBackground.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn",
"textures/buttons/StartBtn.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick",
"textures/buttons/AnalogStick.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left",
"textures/buttons/DPadLeft.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right",
"textures/buttons/DPadRight.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down",
"textures/buttons/DPadDown.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick",
"textures/buttons/RightStick.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline",
"textures/buttons/ABtnOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn Outline",
"textures/buttons/BBtnOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn Outline",
"textures/buttons/LBtnOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn Outline",
"textures/buttons/RBtnOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn Outline",
"textures/buttons/ZBtnOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn Outline",
"textures/buttons/StartBtnOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left Outline",
"textures/buttons/CLeftOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right Outline",
"textures/buttons/CRightOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up Outline",
"textures/buttons/CUpOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down Outline",
"textures/buttons/CDownOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick Outline",
"textures/buttons/AnalogStickOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left Outline",
"textures/buttons/DPadLeftOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right Outline",
"textures/buttons/DPadRightOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up Outline",
"textures/buttons/DPadUpOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline",
"textures/buttons/DPadDownOutline.png");
LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline",
"textures/buttons/RightStickOutline.png");
sButtonTexturesLoaded = true;
}
ImVec2 mainPos = ImGui::GetWindowPos();
ImVec2 size = ImGui::GetContentRegionAvail();
#ifdef __WIIU__
const float scale = CVarGetFloat("gInputViewer.Scale", 1.0f) * 2.0f;
#else
const float scale = CVarGetFloat("gInputViewer.Scale", 1.0f);
#endif
const int showAnalogAngles = CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0);
const int buttonOutlineMode = CVarGetInteger("gInputViewer.ButtonOutlineMode", BUTTON_OUTLINE_NOT_PRESSED);
ImVec2 bgSize = LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background");
ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale);
ImGui::SetNextWindowSize(ImVec2(
scaledBGSize.x + 20,
scaledBGSize.y +
(showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f) + 20));
ImGui::SetNextWindowContentSize(
ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale *
CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f)));
ImGui::SetNextWindowPos(
ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30),
ImGuiCond_FirstUseEver);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
OSContPad* pads = LUS::Context::GetInstance()->GetControlDeck()->GetPads();
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoFocusOnAppearing;
if (!CVarGetInteger("gInputViewer.EnableDragging", 1)) {
windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove;
}
if (pads != nullptr && ImGui::Begin("Input Viewer", nullptr, windowFlags)) {
ImGui::SetCursorPos(ImVec2(10, 10));
const ImVec2 aPos = ImGui::GetCursorPos();
if (CVarGetInteger("gInputViewer.ShowBackground", 1)) {
ImGui::SetNextItemAllowOverlap();
// Background
ImGui::Image(
LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Input-Viewer-Background"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
}
// A/B
if (CVarGetInteger("gInputViewer.BBtn", 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, buttonOutlineMode);
}
if (CVarGetInteger("gInputViewer.ABtn", 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, buttonOutlineMode);
}
// C buttons
if (CVarGetInteger("gInputViewer.CUp", 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, buttonOutlineMode);
}
if (CVarGetInteger("gInputViewer.CLeft", 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, buttonOutlineMode);
}
if (CVarGetInteger("gInputViewer.CRight", 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize,
buttonOutlineMode);
}
if (CVarGetInteger("gInputViewer.CDown", 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, buttonOutlineMode);
}
// L/R/Z
if (CVarGetInteger("gInputViewer.LBtn", 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, buttonOutlineMode);
}
if (CVarGetInteger("gInputViewer.RBtn", 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, buttonOutlineMode);
}
if (CVarGetInteger("gInputViewer.ZBtn", 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, buttonOutlineMode);
}
// Start
if (CVarGetInteger("gInputViewer.StartBtn", 1)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize,
buttonOutlineMode);
}
// Dpad
if (CVarGetInteger("gInputViewer.Dpad", 0)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize,
buttonOutlineMode);
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize,
buttonOutlineMode);
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, buttonOutlineMode);
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize,
buttonOutlineMode);
}
const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y;
const bool rightStickIsInDeadzone = !pads[0].right_stick_x && !pads[0].right_stick_y;
// Analog Stick
const int analogOutlineMode =
CVarGetInteger("gInputViewer.AnalogStick.OutlineMode", STICK_MODE_ALWAYS_SHOWN);
const float maxStickDistance = CVarGetInteger("gInputViewer.AnalogStick.Movement", 12);
if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN ||
(analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
ImGui::Image(
LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick Outline"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
}
const int analogStickMode =
CVarGetInteger("gInputViewer.AnalogStick.VisibilityMode", STICK_MODE_ALWAYS_SHOWN);
if (analogStickMode == STICK_MODE_ALWAYS_SHOWN ||
(analogStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(
ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale,
aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale));
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
}
// Right Stick
const float maxRightStickDistance = CVarGetInteger("gInputViewer.RightStick.Movement", 7);
const int rightOutlineMode =
CVarGetInteger("gInputViewer.RightStick.OutlineMode", STICK_MODE_ALWAYS_HIDDEN);
if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN ||
(rightOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
ImGui::Image(
LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick Outline"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
}
const int rightStickMode =
CVarGetInteger("gInputViewer.RightStick.VisibilityMode", STICK_MODE_ALWAYS_HIDDEN);
if (rightStickMode == STICK_MODE_ALWAYS_SHOWN ||
(rightStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(
ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale,
aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale));
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255));
}
// Analog stick angle text
if (showAnalogAngles) {
ImGui::SetCursorPos(ImVec2(aPos.x + 10 + CVarGetInteger("gInputViewer.AnalogAngles.Offset", 0) * scale,
scaledBGSize.y + aPos.y + 10));
// Scale font with input viewer scale
float oldFontScale = ImGui::GetFont()->Scale;
ImGui::GetFont()->Scale *= scale * CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f);
ImGui::PushFont(ImGui::GetFont());
// Calculate polar R coordinate from X and Y angles, squared to avoid sqrt
const float rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y;
// ESS range
const int range1Min = CVarGetInteger("gInputViewer.AnalogAngles.Range1.Min", 8);
const int range1Max = CVarGetInteger("gInputViewer.AnalogAngles.Range1.Max", 27);
// Walking speed range
const int range2Min = CVarGetInteger("gInputViewer.AnalogAngles.Range2.Min", 27);
const int range2Max = CVarGetInteger("gInputViewer.AnalogAngles.Range2.Max", 62);
// Push color based on angle ranges
if (CVarGetInteger("gInputViewer.AnalogAngles.Range1.Enabled", 0) &&
(rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) {
ImGui::PushStyleColor(
ImGuiCol_Text,
color2Vec(CVarGetColor("gInputViewer.AnalogAngles.Range1.Color", vec2Color(range1Color))));
} else if (CVarGetInteger("gInputViewer.AnalogAngles.Range2.Enabled", 0) &&
(rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) {
ImGui::PushStyleColor(
ImGuiCol_Text,
color2Vec(CVarGetColor("gInputViewer.AnalogAngles.Range2.Color", vec2Color(range2Color))));
} else {
ImGui::PushStyleColor(ImGuiCol_Text, color2Vec(CVarGetColor("gInputViewer.AnalogAngles.TextColor",
vec2Color(textColor))));
}
// Render text
ImGui::Text("X: %-3d Y: %-3d", pads[0].stick_x, pads[0].stick_y);
// Restore original color
ImGui::PopStyleColor();
// Restore original font scale
ImGui::GetFont()->Scale = oldFontScale;
ImGui::PopFont();
}
ImGui::End();
}
ImGui::PopStyleVar();
ImGui::PopStyleColor();
}
}
InputViewerSettingsWindow::~InputViewerSettingsWindow() {
SPDLOG_TRACE("destruct input viewer settings window");
}
void InputViewerSettingsWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(450, 525), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Input Viewer Settings", &mIsVisible)) {
// gInputViewer.Scale
UIWidgets::EnhancementSliderFloat("Input Viewer Scale: %.2f", "##Input", "gInputViewer.Scale", 0.1f, 5.0f, "",
1.0f, false, true);
UIWidgets::Tooltip("Sets the on screen size of the input viewer");
// gInputViewer.EnableDragging
UIWidgets::EnhancementCheckbox("Enable Dragging", "gInputViewer.EnableDragging", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
UIWidgets::PaddedSeparator(true, true);
// gInputViewer.ShowBackground
UIWidgets::EnhancementCheckbox("Show Background Layer", "gInputViewer.ShowBackground", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
UIWidgets::PaddedSeparator(true, true);
if (ImGui::CollapsingHeader("Buttons")) {
// gInputViewer.ABtn
UIWidgets::EnhancementCheckbox("Show A-Button Layers", "gInputViewer.ABtn", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
// gInputViewer.BBtn
UIWidgets::EnhancementCheckbox("Show B-Button Layers", "gInputViewer.BBtn", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
// gInputViewer.CUp
UIWidgets::EnhancementCheckbox("Show C-Up Layers", "gInputViewer.CUp", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
// gInputViewer.CRight
UIWidgets::EnhancementCheckbox("Show C-Right Layers", "gInputViewer.CRight", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
// gInputViewer.CDown
UIWidgets::EnhancementCheckbox("Show C-Down Layers", "gInputViewer.CDown", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
// gInputViewer.CLeft
UIWidgets::EnhancementCheckbox("Show C-Left Layers", "gInputViewer.CLeft", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
// gInputViewer.LBtn
UIWidgets::EnhancementCheckbox("Show L-Button Layers", "gInputViewer.LBtn", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
// gInputViewer.RBtn
UIWidgets::EnhancementCheckbox("Show R-Button Layers", "gInputViewer.RBtn", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
// gInputViewer.ZBtn
UIWidgets::EnhancementCheckbox("Show Z-Button Layers", "gInputViewer.ZBtn", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
// gInputViewer.StartBtn
UIWidgets::EnhancementCheckbox("Show Start Button Layers", "gInputViewer.StartBtn", false, "",
UIWidgets::CheckboxGraphics::Checkmark, true);
// gInputViewer.Dpad
UIWidgets::EnhancementCheckbox("Show D-Pad Layers", "gInputViewer.Dpad", false, "",
UIWidgets::CheckboxGraphics::Checkmark, false);
// gInputViewer.ButtonOutlineMode
UIWidgets::PaddedText("Button Outlines/Backgrounds", true, false);
UIWidgets::EnhancementCombobox("gInputViewer.ButtonOutlineMode", buttonOutlineOptions,
BUTTON_OUTLINE_NOT_PRESSED);
UIWidgets::Tooltip(
"Sets the desired visibility behavior for the button outline/background layers. Useful for "
"custom input viewers.");
UIWidgets::PaddedSeparator(true, true);
}
if (ImGui::CollapsingHeader("Analog Stick")) {
// gInputViewer.AnalogStick.VisibilityMode
UIWidgets::PaddedText("Analog Stick Visibility", true, false);
UIWidgets::EnhancementCombobox("gInputViewer.AnalogStick.VisibilityMode", stickModeOptions,
STICK_MODE_ALWAYS_SHOWN);
UIWidgets::Tooltip(
"Determines the conditions under which the moving layer of the analog stick texture is visible.");
// gInputViewer.AnalogStick.OutlineMode
UIWidgets::PaddedText("Analog Stick Outline/Background Visibility", true, false);
UIWidgets::EnhancementCombobox("gInputViewer.AnalogStick.OutlineMode", stickModeOptions,
STICK_MODE_ALWAYS_SHOWN);
UIWidgets::Tooltip(
"Determines the conditions under which the analog stick outline/background texture is visible.");
// gInputViewer.AnalogStick.Movement
UIWidgets::EnhancementSliderInt("Analog Stick Movement: %dpx", "##AnalogMovement",
"gInputViewer.AnalogStick.Movement", 0, 200, "", 12, true);
UIWidgets::Tooltip(
"Sets the distance to move the analog stick in the input viewer. Useful for custom input viewers.");
UIWidgets::PaddedSeparator(true, true);
}
if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) {
// gInputViewer.RightStick.VisibilityMode
UIWidgets::PaddedText("Right Stick Visibility", true, false);
UIWidgets::EnhancementCombobox("gInputViewer.RightStick.VisibilityMode", stickModeOptions,
STICK_MODE_HIDDEN_IN_DEADZONE);
UIWidgets::Tooltip(
"Determines the conditions under which the moving layer of the right stick texture is visible.");
// gInputViewer.RightStick.OutlineMode
UIWidgets::PaddedText("Right Stick Outline/Background Visibility", true, false);
UIWidgets::EnhancementCombobox("gInputViewer.RightStick.OutlineMode", stickModeOptions,
STICK_MODE_HIDDEN_IN_DEADZONE);
UIWidgets::Tooltip(
"Determines the conditions under which the right stick outline/background texture is visible.");
// gInputViewer.RightStick.Movement
UIWidgets::EnhancementSliderInt("Right Stick Movement: %dpx", "##RightMovement",
"gInputViewer.RightStick.Movement", 0, 200, "", 7, true);
UIWidgets::Tooltip(
"Sets the distance to move the right stick in the input viewer. Useful for custom input viewers.");
UIWidgets::PaddedSeparator(true, true);
}
if (ImGui::CollapsingHeader("Analog Angle Values")) {
// gAnalogAngles
UIWidgets::EnhancementCheckbox("Show Analog Stick Angle Values", "gInputViewer.AnalogAngles.Enabled");
UIWidgets::Tooltip("Displays analog stick angle values in the input viewer");
if (CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0)) {
// gInputViewer.AnalogAngles.TextColor
if (ImGui::ColorEdit4("Text Color", (float*)&textColor)) {
CVarSetColor("gInputViewer.AnalogAngles.TextColor", vec2Color(textColor));
}
// gAnalogAngleScale
UIWidgets::EnhancementSliderFloat("Angle Text Scale: %.2f%%", "##AnalogAngleScale",
"gInputViewer.AnalogAngles.Scale", 0.1f, 5.0f, "", 1.0f, true, true);
// gInputViewer.AnalogAngles.Offset
UIWidgets::EnhancementSliderInt("Angle Text Offset: %dpx", "##AnalogAngleOffset",
"gInputViewer.AnalogAngles.Offset", 0, 400, "", 0, true);
UIWidgets::PaddedSeparator(true, true);
// gInputViewer.AnalogAngles.Range1.Enabled
UIWidgets::EnhancementCheckbox("Highlight ESS Position", "gInputViewer.AnalogAngles.Range1.Enabled");
UIWidgets::Tooltip(
"Highlights the angle value text when the analog stick is in ESS position (on flat ground)");
if (CVarGetInteger("gInputViewer.AnalogAngles.Range1.Enabled", 0)) {
// gInputViewer.AnalogAngles.Range1.Color
if (ImGui::ColorEdit4("ESS Color", (float*)&range1Color)) {
CVarSetColor("gInputViewer.AnalogAngles.Range1.Color", vec2Color(range1Color));
}
}
UIWidgets::PaddedSeparator(true, true);
// gInputViewer.AnalogAngles.Range2.Enabled
UIWidgets::EnhancementCheckbox("Highlight Walking Speed Angles",
"gInputViewer.AnalogAngles.Range2.Enabled");
UIWidgets::Tooltip("Highlights the angle value text when the analog stick is at an angle that would "
"produce a walking speed (on flat ground)\n\n"
"Useful for 1.0 Empty Jumpslash Quick Put Away");
if (CVarGetInteger("gInputViewer.AnalogAngles.Range2.Enabled", 0)) {
// gInputViewer.AnalogAngles.Range2.Color
if (ImGui::ColorEdit4("Walking Speed Color", (float*)&range2Color)) {
CVarSetColor("gInputViewer.AnalogAngles.Range2.Color", vec2Color(range2Color));
}
}
}
}
ImGui::End();
}
}

View File

@ -0,0 +1,47 @@
#pragma once
#include <libultraship/libultraship.h>
typedef enum {
BUTTON_OUTLINE_ALWAYS_SHOWN,
BUTTON_OUTLINE_NOT_PRESSED,
BUTTON_OUTLINE_PRESSED,
BUTTON_OUTLINE_ALWAYS_HIDDEN
} ButtonOutlineMode;
typedef enum {
STICK_MODE_ALWAYS_SHOWN,
STICK_MODE_HIDDEN_IN_DEADZONE,
STICK_MODE_ALWAYS_HIDDEN,
} StickMode;
class InputViewer : public LUS::GuiWindow {
public:
using LUS::GuiWindow::GuiWindow;
void InitElement() override {};
void DrawElement() override;
void UpdateElement() override {};
InputViewer();
~InputViewer();
void Draw();
private:
void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode);
};
class InputViewerSettingsWindow : public LUS::GuiWindow {
public:
using LUS::GuiWindow::GuiWindow;
void InitElement() override {};
void DrawElement() override;
void UpdateElement() override {};
InputViewerSettingsWindow();
~InputViewerSettingsWindow();
void Draw();
};

View File

@ -269,35 +269,35 @@ static std::map<std::string, CosmeticOption> cosmeticOptions = {
COSMETIC_OPTION("Hud_NameTagActorText", "Nametag Text", GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false),
COSMETIC_OPTION("Hud_NameTagActorBackground", "Nametag Background", GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true),
COSMETIC_OPTION("Kal_ItemSelA", "Item Select Color A", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false),
COSMETIC_OPTION("Kal_ItemSelB", "Item Select Color B", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, false),
COSMETIC_OPTION("Kal_ItemSelC", "Item Select Color C", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, false),
COSMETIC_OPTION("Kal_ItemSelD", "Item Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false),
COSMETIC_OPTION("Kal_ItemSelA", "Item Select Color", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false),
COSMETIC_OPTION("Kal_ItemSelB", "Item Select Color B", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true),
COSMETIC_OPTION("Kal_ItemSelC", "Item Select Color C", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true),
COSMETIC_OPTION("Kal_ItemSelD", "Item Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true),
COSMETIC_OPTION("Kal_EquipSelA", "Equip Select Color A", GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false),
COSMETIC_OPTION("Kal_EquipSelB", "Equip Select Color B", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_EquipSelC", "Equip Select Color C", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_EquipSelD", "Equip Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false),
COSMETIC_OPTION("Kal_EquipSelA", "Equip Select Color", GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false),
COSMETIC_OPTION("Kal_EquipSelB", "Equip Select Color B", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true),
COSMETIC_OPTION("Kal_EquipSelC", "Equip Select Color C", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true),
COSMETIC_OPTION("Kal_EquipSelD", "Equip Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true),
COSMETIC_OPTION("Kal_MapSelDunA", "Map Dungeon Color A", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelDunB", "Map Dungeon Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelDunC", "Map Dungeon Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelDunD", "Map Dungeon Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelDunA", "Map Dungeon Color", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true),
COSMETIC_OPTION("Kal_MapSelDunB", "Map Dungeon Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true),
COSMETIC_OPTION("Kal_MapSelDunC", "Map Dungeon Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true),
COSMETIC_OPTION("Kal_MapSelDunD", "Map Dungeon Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true),
COSMETIC_OPTION("Kal_QuestStatusA", "Quest StatusColor A", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false),
COSMETIC_OPTION("Kal_QuestStatusB", "Quest StatusColor B", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, false),
COSMETIC_OPTION("Kal_QuestStatusC", "Quest StatusColor C", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, false),
COSMETIC_OPTION("Kal_QuestStatusD", "Quest StatusColor D", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false),
COSMETIC_OPTION("Kal_QuestStatusA", "Quest Status Color", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false),
COSMETIC_OPTION("Kal_QuestStatusB", "Quest Status Color B", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true),
COSMETIC_OPTION("Kal_QuestStatusC", "Quest Status Color C", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true),
COSMETIC_OPTION("Kal_QuestStatusD", "Quest Status Color D", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, true),
COSMETIC_OPTION("Kal_MapSelectA", "Map Color A", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelectB", "Map Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelectC", "Map Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelectD", "Map Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelectA", "Map Color", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false),
COSMETIC_OPTION("Kal_MapSelectB", "Map Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true),
COSMETIC_OPTION("Kal_MapSelectC", "Map Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true),
COSMETIC_OPTION("Kal_MapSelectD", "Map Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true),
COSMETIC_OPTION("Kal_SaveA", "Save A", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false),
COSMETIC_OPTION("Kal_SaveB", "Save B", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, false),
COSMETIC_OPTION("Kal_SaveC", "Save C", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, false),
COSMETIC_OPTION("Kal_SaveD", "Save D", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false),
COSMETIC_OPTION("Kal_SaveA", "Save Color", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false),
COSMETIC_OPTION("Kal_SaveB", "Save Color B", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true),
COSMETIC_OPTION("Kal_SaveC", "Save Color C", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true),
COSMETIC_OPTION("Kal_SaveD", "Save Color D", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, true),
COSMETIC_OPTION("Kal_NamePanel", "Name Panel", GROUP_KALEIDO, ImVec4(90,100,130,255), true, true, false),
@ -1065,12 +1065,16 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) {
if (manualChange || CVarGetInteger(npcGoldenSkulltula.rainbowCvar, 0)) {
static Color_RGBA8 defaultColor = {npcGoldenSkulltula.defaultColor.x, npcGoldenSkulltula.defaultColor.y, npcGoldenSkulltula.defaultColor.z, npcGoldenSkulltula.defaultColor.w};
Color_RGBA8 color = CVarGetColor(npcGoldenSkulltula.cvar, defaultColor);
PATCH_GFX(gGiSkulltulaTokenDL, "NPC_GoldenSkulltula1", npcGoldenSkulltula.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
PATCH_GFX(gGiSkulltulaTokenDL, "NPC_GoldenSkulltula2", npcGoldenSkulltula.changedCvar, 6, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255));
PATCH_GFX(gGiSkulltulaTokenFlameDL, "NPC_GoldenSkulltula3", npcGoldenSkulltula.changedCvar, 32, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
PATCH_GFX(gGiSkulltulaTokenFlameDL, "NPC_GoldenSkulltula4", npcGoldenSkulltula.changedCvar, 33, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255));
PATCH_GFX(object_st_DL_003FB0, "NPC_GoldenSkulltula5", npcGoldenSkulltula.changedCvar, 118, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
PATCH_GFX(object_st_DL_003FB0, "NPC_GoldenSkulltula6", npcGoldenSkulltula.changedCvar, 119, gsDPSetEnvColor(color.r / 4, color.g / 4, color.b / 4, 255));
PATCH_GFX(gSkulltulaTokenDL, "NPC_GoldenSkulltula1", npcGoldenSkulltula.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
PATCH_GFX(gSkulltulaTokenDL, "NPC_GoldenSkulltula2", npcGoldenSkulltula.changedCvar, 6, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255));
PATCH_GFX(gSkulltulaTokenFlameDL, "NPC_GoldenSkulltula3", npcGoldenSkulltula.changedCvar, 32, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
PATCH_GFX(gSkulltulaTokenFlameDL, "NPC_GoldenSkulltula4", npcGoldenSkulltula.changedCvar, 33, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255));
PATCH_GFX(gGiSkulltulaTokenDL, "NPC_GoldenSkulltula5", npcGoldenSkulltula.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
PATCH_GFX(gGiSkulltulaTokenDL, "NPC_GoldenSkulltula6", npcGoldenSkulltula.changedCvar, 6, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255));
PATCH_GFX(gGiSkulltulaTokenFlameDL, "NPC_GoldenSkulltula7", npcGoldenSkulltula.changedCvar, 32, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
PATCH_GFX(gGiSkulltulaTokenFlameDL, "NPC_GoldenSkulltula8", npcGoldenSkulltula.changedCvar, 33, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255));
PATCH_GFX(object_st_DL_003FB0, "NPC_GoldenSkulltula9", npcGoldenSkulltula.changedCvar, 118, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255));
PATCH_GFX(object_st_DL_003FB0, "NPC_GoldenSkulltula10", npcGoldenSkulltula.changedCvar, 119, gsDPSetEnvColor(color.r / 4, color.g / 4, color.b / 4, 255));
}
static CosmeticOption& npcGerudo = cosmeticOptions.at("NPC_Gerudo");
@ -1181,6 +1185,43 @@ void DrawScaleSlider(const std::string CvarName,float DefaultValue){
//Disabled for now. feature not done and several fixes needed to be merged.
//UIWidgets::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true);
}
void Draw_Table_Dropdown(const char* Header_Title, const char* Table_ID, const char* Column_Title, const char* Slider_Title, const char* Slider_ID, int MinY, int MaxY, int MinX, int MaxX, float Default_Value) {
if (ImGui::CollapsingHeader(Header_Title)) {
if (ImGui::BeginTable(Table_ID, 1, FlagsTable)) {
ImGui::TableSetupColumn(Column_Title, FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider(Slider_Title, Slider_ID);
DrawPositionsRadioBoxes(Slider_ID);
DrawPositionSlider(Slider_ID, MinY, MaxY, MinX, MaxX);
DrawScaleSlider(Slider_ID, Default_Value);
ImGui::NewLine();
ImGui::EndTable();
}
}
}
void C_Button_Dropdown(const char* Header_Title, const char* Table_ID, const char* Column_Title, const char* Slider_Title, const char* Slider_ID, const char* Int_Type, float Slider_Scale_Value) {
if (ImGui::CollapsingHeader(Header_Title)) {
if (ImGui::BeginTable(Table_ID, 1, FlagsTable)) {
ImGui::TableSetupColumn(Column_Title, FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider(Slider_Title, Slider_ID);
DrawPositionsRadioBoxes(Slider_ID);
s16 Min_X_CU = 0;
s16 Max_X_CU = ImGui::GetWindowViewport()->Size.x/2;
if(CVarGetInteger(Int_Type,0) == 2){
Max_X_CU = 294;
} else if(CVarGetInteger(Int_Type,0) == 3){
Max_X_CU = ImGui::GetWindowViewport()->Size.x/2;
} else if(CVarGetInteger(Int_Type,0) == 4){
Min_X_CU = (ImGui::GetWindowViewport()->Size.x/2)*-1;
}
DrawPositionSlider(Slider_ID, 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CU, Max_X_CU);
DrawScaleSlider(Slider_ID, Slider_Scale_Value);
ImGui::NewLine();
ImGui::EndTable();
}
}
}
void Draw_Placements(){
if (ImGui::BeginTable("tableMargins", 1, FlagsTable)) {
ImGui::TableSetupColumn("General margins settings", FlagsCell, TablesCellsWidth);
@ -1247,126 +1288,13 @@ void Draw_Placements(){
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("B Button position")) {
if (ImGui::BeginTable("tablebbtn", 1, FlagsTable)) {
ImGui::TableSetupColumn("B Button settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("B Button", "gBBtn");
DrawPositionsRadioBoxes("gBBtn");
DrawPositionSlider("gBBtn", 0, ImGui::GetWindowViewport()->Size.y/4+50, -1, ImGui::GetWindowViewport()->Size.x-50);
DrawScaleSlider("gBBtn",0.95f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("A Button position")) {
if (ImGui::BeginTable("tableabtn", 1, FlagsTable)) {
ImGui::TableSetupColumn("A Button settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("A Button", "gABtn");
DrawPositionsRadioBoxes("gABtn");
DrawPositionSlider("gABtn", -10, ImGui::GetWindowViewport()->Size.y/4+50, -20, ImGui::GetWindowViewport()->Size.x-50);
DrawScaleSlider("gABtn",0.95f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Start Button position")) {
if (ImGui::BeginTable("tablestartbtn", 1, FlagsTable)) {
ImGui::TableSetupColumn("Start Button settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("Start Button", "gStartBtn");
DrawPositionsRadioBoxes("gStartBtn");
DrawPositionSlider("gStartBtn", 0, ImGui::GetWindowViewport()->Size.y/2, 0, ImGui::GetWindowViewport()->Size.x/2+70);
DrawScaleSlider("gStartBtn",0.75f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("C Button Up position")) {
if (ImGui::BeginTable("tablecubtn", 1, FlagsTable)) {
ImGui::TableSetupColumn("C Button Up settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("C Button Up", "gCBtnU");
DrawPositionsRadioBoxes("gCBtnU");
s16 Min_X_CU = 0;
s16 Max_X_CU = ImGui::GetWindowViewport()->Size.x/2;
if(CVarGetInteger("gCBtnUPosType",0) == 2){
Max_X_CU = 294;
} else if(CVarGetInteger("gCBtnUPosType",0) == 3){
Max_X_CU = ImGui::GetWindowViewport()->Size.x/2;
} else if(CVarGetInteger("gCBtnUPosType",0) == 4){
Min_X_CU = (ImGui::GetWindowViewport()->Size.x/2)*-1;
}
DrawPositionSlider("gCBtnU", 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CU, Max_X_CU);
DrawScaleSlider("gCBtnU",0.5f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("C Button Down position")) {
if (ImGui::BeginTable("tablecdbtn", 1, FlagsTable)) {
ImGui::TableSetupColumn("C Button Down settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("C Button Down", "gCBtnD");
DrawPositionsRadioBoxes("gCBtnD");
s16 Min_X_CD = 0;
s16 Max_X_CD = ImGui::GetWindowViewport()->Size.x/2;
if(CVarGetInteger("gCBtnDPosType",0) == 2){
Max_X_CD = 294;
} else if(CVarGetInteger("gCBtnDPosType",0) == 3){
Max_X_CD = ImGui::GetWindowViewport()->Size.x/2;
} else if(CVarGetInteger("gCBtnDPosType",0) == 4){
Min_X_CD = (ImGui::GetWindowViewport()->Size.x/2)*-1;
}
DrawPositionSlider("gCBtnD", 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CD, Max_X_CD);
DrawScaleSlider("gCBtnD",0.87f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("C Button Left position")) {
if (ImGui::BeginTable("tableclbtn", 1, FlagsTable)) {
ImGui::TableSetupColumn("C Button Left settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("C Button Left", "gCBtnL");
DrawPositionsRadioBoxes("gCBtnL");
s16 Min_X_CL = 0;
s16 Max_X_CL = ImGui::GetWindowViewport()->Size.x/2;
if(CVarGetInteger("gCBtnLPosType",0) == 2){
Max_X_CL = 294;
} else if(CVarGetInteger("gCBtnLPosType",0) == 3){
Max_X_CL = ImGui::GetWindowViewport()->Size.x/2;
} else if(CVarGetInteger("gCBtnLPosType",0) == 4){
Min_X_CL = (ImGui::GetWindowViewport()->Size.x/2)*-1;
}
DrawPositionSlider("gCBtnL", 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CL, Max_X_CL);
DrawScaleSlider("gCBtnL",0.87f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("C Button Right position")) {
if (ImGui::BeginTable("tablecrnbtn", 1, FlagsTable)) {
ImGui::TableSetupColumn("C Button Right settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("C Button Right", "gCBtnR");
DrawPositionsRadioBoxes("gCBtnR");
s16 Min_X_CR = 0;
s16 Max_X_CR = ImGui::GetWindowViewport()->Size.x/2;
if(CVarGetInteger("gCBtnRPosType",0) == 2){
Max_X_CR = 294;
} else if(CVarGetInteger("gCBtnRPosType",0) == 3){
Max_X_CR = ImGui::GetWindowViewport()->Size.x/2;
} else if(CVarGetInteger("gCBtnRPosType",0) == 4){
Min_X_CR = (ImGui::GetWindowViewport()->Size.x/2)*-1;
}
DrawPositionSlider("gCBtnR", 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CR, Max_X_CR);
DrawScaleSlider("gCBtnR",0.87f);
ImGui::NewLine();
ImGui::EndTable();
}
}
Draw_Table_Dropdown("B Button position", "tablebbtn", "B Button settings", "B Button", "gBBtn", 0, ImGui::GetWindowViewport()->Size.y/4+50, -1, ImGui::GetWindowViewport()->Size.x-50, 0.95f);
Draw_Table_Dropdown("A Button position", "tableabtn", "A Button settings", "A Button", "gABtn", -10, ImGui::GetWindowViewport()->Size.y/4+50, -20, ImGui::GetWindowViewport()->Size.x-50, 0.95f);
Draw_Table_Dropdown("Start Button position", "tablestartbtn", "Start Button settings", "Start Button", "gStartBtn", 0, ImGui::GetWindowViewport()->Size.y/2, 0, ImGui::GetWindowViewport()->Size.x/2+70, 0.75f);
C_Button_Dropdown("C Button Up position", "tablecubtn", "C Button Up settings", "C Button Up", "gCBtnU", "gCBtnUPosType", 0.5f);
C_Button_Dropdown("C Button Down position", "tablecdbtn", "C Button Down settings", "C Button Down", "gCBtnD", "gCBtnDPosType", 0.87f);
C_Button_Dropdown("C Button Left position", "tableclbtn", "C Button Left settings", "C Button Left", "gCBtnL", "gCBtnLPosType", 0.87f);
C_Button_Dropdown("C Button Right position", "tablecrbtn", "C Button Right settings", "C Button Right", "gCBtnR", "gCBtnRPosType", 0.87f);
if (CVarGetInteger("gDpadEquips",0) && ImGui::CollapsingHeader("DPad items position")) {
if (ImGui::BeginTable("tabledpaditems", 1, FlagsTable)) {
ImGui::TableSetupColumn("DPad items settings", FlagsCell, TablesCellsWidth);
@ -1386,115 +1314,15 @@ void Draw_Placements(){
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Minimaps position")) {
if (ImGui::BeginTable("tableminimapspos", 1, FlagsTable)) {
ImGui::TableSetupColumn("minimaps settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("Minimap", "gMinimap");
DrawPositionsRadioBoxes("gMinimap", false);
DrawPositionSlider("gMinimap", (ImGui::GetWindowViewport()->Size.y/3)*-1, ImGui::GetWindowViewport()->Size.y/3, ImGui::GetWindowViewport()->Size.x*-1, ImGui::GetWindowViewport()->Size.x/2);
DrawScaleSlider("gMinimap",1.0f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Small Keys counter position")) {
if (ImGui::BeginTable("tablesmolekeys", 1, FlagsTable)) {
ImGui::TableSetupColumn("Small Keys counter settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("Small Keys counter", "gSKC");
DrawPositionsRadioBoxes("gSKC");
DrawPositionSlider("gSKC", 0, ImGui::GetWindowViewport()->Size.y/3, -1, ImGui::GetWindowViewport()->Size.x/2);
DrawScaleSlider("gSKC",1.0f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Rupee counter position")) {
if (ImGui::BeginTable("tablerupeecount", 1, FlagsTable)) {
ImGui::TableSetupColumn("Rupee counter settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("Rupee counter", "gRC");
DrawPositionsRadioBoxes("gRC");
DrawPositionSlider("gRC", -2, ImGui::GetWindowViewport()->Size.y/3, -3, ImGui::GetWindowViewport()->Size.x/2);
DrawScaleSlider("gRC",1.0f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Carrots position")) {
if (ImGui::BeginTable("tableCarrots", 1, FlagsTable)) {
ImGui::TableSetupColumn("Carrots settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("Carrots", "gCarrots");
DrawPositionsRadioBoxes("gCarrots");
DrawPositionSlider("gCarrots", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+25);
DrawScaleSlider("gCarrots",1.0f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Timers position")) {
if (ImGui::BeginTable("tabletimers", 1, FlagsTable)) {
ImGui::TableSetupColumn("Timers settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("Timers", "gTimers");
DrawPositionsRadioBoxes("gTimers");
DrawPositionSlider("gTimers", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50);
DrawScaleSlider("gTimers",1.0f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Archery Scores position")) {
if (ImGui::BeginTable("tablearchery", 1, FlagsTable)) {
ImGui::TableSetupColumn("Archery Scores settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("Archery scores", "gAS");
DrawPositionsRadioBoxes("gAS", false);
DrawPositionSlider("gAS", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50);
DrawScaleSlider("gAS",1.0f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Title cards (Maps) position")) {
if (ImGui::BeginTable("tabletcmaps", 1, FlagsTable)) {
ImGui::TableSetupColumn("Titlecard maps settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("Title cards (overworld)", "gTCM");
DrawPositionsRadioBoxes("gTCM");
DrawPositionSlider("gTCM", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10);
DrawScaleSlider("gTCM",1.0f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Title cards (Bosses) position")) {
if (ImGui::BeginTable("tabletcbosses", 1, FlagsTable)) {
ImGui::TableSetupColumn("Title cards (Bosses) settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("Title cards (Bosses)", "gTCB");
DrawPositionsRadioBoxes("gTCB");
DrawPositionSlider("gTCB", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10);
DrawScaleSlider("gTCB",1.0f);
ImGui::NewLine();
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("In-game Gameplay Timer position")) {
if (ImGui::BeginTable("tablegameplaytimer", 1, FlagsTable)) {
ImGui::TableSetupColumn("In-game Gameplay Timer settings", FlagsCell, TablesCellsWidth);
Table_InitHeader(false);
DrawUseMarginsSlider("In-game Gameplay Timer", "gIGT");
DrawPositionsRadioBoxes("gIGT");
DrawPositionSlider("gIGT", 0, ImGui::GetWindowViewport()->Size.y / 2, -50,
ImGui::GetWindowViewport()->Size.x / 2 + 10);
DrawScaleSlider("gIGT", 1.0f);
ImGui::NewLine();
ImGui::EndTable();
}
}
Draw_Table_Dropdown("Minimaps position", "tableminimapspos", "minimaps settings", "Minimap", "gMinimap", (ImGui::GetWindowViewport()->Size.y/3)*-1, ImGui::GetWindowViewport()->Size.y/3, ImGui::GetWindowViewport()->Size.x*-1, ImGui::GetWindowViewport()->Size.x/2, 1.0f);
Draw_Table_Dropdown("Small Keys counter position", "tablesmolekeys", "Small Keys counter settings", "Small Keys counter", "gSKC", 0, ImGui::GetWindowViewport()->Size.y/3, -1, ImGui::GetWindowViewport()->Size.x/2, 1.0f);
Draw_Table_Dropdown("Rupee counter position", "tablerupeecount", "Rupee counter settings", "Rupee counter", "gRC", -2, ImGui::GetWindowViewport()->Size.y/3, -3, ImGui::GetWindowViewport()->Size.x/2, 1.0f);
Draw_Table_Dropdown("Carrots position", "tableCarrots", "Carrots settings", "Carrots", "gCarrots", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+25, 1.0f);
Draw_Table_Dropdown("Timers position", "tabletimers", "Timers settings", "Timers", "gTimers", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f);
Draw_Table_Dropdown("Archery Scores position", "tablearchery", "Archery Scores settings", "Archery scores", "gAS", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f);
Draw_Table_Dropdown("Title cards (Maps) position", "tabletcmaps", "Titlecard maps settings", "Title cards (overworld)", "gTCM", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f);
Draw_Table_Dropdown("Title cards (Bosses) position", "tabletcbosses", "Title cards (Bosses) settings", "Title cards (Bosses)", "gTCB", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f);
Draw_Table_Dropdown("In-game Gameplay Timer position", "tablegameplaytimer", "In-game Gameplay Timer settings", "In-game Gameplay Timer", "gIGT", 0, ImGui::GetWindowViewport()->Size.y / 2, -50, ImGui::GetWindowViewport()->Size.x / 2 + 10, 1.0f);
if (ImGui::CollapsingHeader("Enemy Health Bar position")) {
if (ImGui::BeginTable("enemyhealthbar", 1, FlagsTable)) {
ImGui::TableSetupColumn("Enemy Health Bar settings", FlagsCell, TablesCellsWidth);
@ -1522,7 +1350,21 @@ void Draw_Placements(){
}
}
}
void Reset_Option_Single(const char* Button_Title, const char* name) {
ImGui::SameLine();
if (ImGui::Button(Button_Title)) {
CVarClear(name);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
}
void Reset_Option_Double(const char* Button_Title, const char* name) {
ImGui::SameLine();
if (ImGui::Button(Button_Title)) {
CVarClear((std::string(name) + ".Value").c_str());
CVarClear((std::string(name) + ".Changed").c_str());
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
}
void DrawSillyTab() {
ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0));
if (CVarGetInteger("gLetItSnow", 0)) {
@ -1548,67 +1390,28 @@ void DrawSillyTab() {
if (UIWidgets::EnhancementSliderFloat("Link Head Scale: %.2fx", "##Link_HeadScale", "gCosmetics.Link_HeadScale.Value", 0.4f, 4.0f, "", 1.0f, false)) {
CVarSetInteger("gCosmetics.Link_HeadScale.Changed", 1);
}
ImGui::SameLine();
if (ImGui::Button("Reset##Link_HeadScale")) {
CVarClear("gCosmetics.Link_HeadScale.Value");
CVarClear("gCosmetics.Link_HeadScale.Changed");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
if (UIWidgets::EnhancementSliderFloat("Link Sword Scale: %.3fx", "##Link_SwordScale", "gCosmetics.Link_SwordScale.Value", 1.0f, 2.5f, "", 1.0f, false)) {
Reset_Option_Double("Reset##Link_HeadScale", "gCosmetics.Link_HeadScale");
if (UIWidgets::EnhancementSliderFloat("Link Sword Scale: %f", "##Link_SwordScale", "gCosmetics.Link_SwordScale.Value", 1.0f, 2.5f, "", 1.0f, false)) {
CVarSetInteger("gCosmetics.Link_SwordScale.Changed", 1);
}
ImGui::SameLine();
if (ImGui::Button("Reset##Link_SwordScale")) {
CVarClear("gCosmetics.Link_SwordScale.Value");
CVarClear("gCosmetics.Link_SwordScale.Changed");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
UIWidgets::EnhancementSliderFloat("Bunny Hood Length: %.0f", "##BunnyHood_EarLength", "gCosmetics.BunnyHood_EarLength", -300.0f, 1000.0f, "", 0.0f, false);
ImGui::SameLine();
if (ImGui::Button("Reset##BunnyHood_EarLength")) {
CVarClear("gCosmetics.BunnyHood_EarLength");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
UIWidgets::EnhancementSliderFloat("Bunny Hood Spread: %.0f", "##BunnyHood_EarSpread", "gCosmetics.BunnyHood_EarSpread", -300.0f, 500.0f, "", 0.0f, false);
ImGui::SameLine();
if (ImGui::Button("Reset##BunnyHood_EarSpread")) {
CVarClear("gCosmetics.BunnyHood_EarSpread");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
UIWidgets::EnhancementSliderFloat("Goron Neck Length: %.0f", "##Goron_NeckLength", "gCosmetics.Goron_NeckLength", 0.0f, 5000.0f, "", 0.0f, false);
ImGui::SameLine();
if (ImGui::Button("Reset##Goron_NeckLength")) {
CVarClear("gCosmetics.Goron_NeckLength");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
Reset_Option_Double("Reset##Link_SwordScale", "gCosmetics.Link_SwordScale");
UIWidgets::EnhancementSliderFloat("Bunny Hood Length: %f", "##BunnyHood_EarLength", "gCosmetics.BunnyHood_EarLength", -300.0f, 1000.0f, "", 0.0f, false);
Reset_Option_Single("Reset##BunnyHood_EarLength", "gCosmetics.BunnyHood_EarLength");
UIWidgets::EnhancementSliderFloat("Bunny Hood Spread: %f", "##BunnyHood_EarSpread", "gCosmetics.BunnyHood_EarSpread", -300.0f, 500.0f, "", 0.0f, false);
Reset_Option_Single("Reset##BunnyHood_EarSpread", "gCosmetics.BunnyHood_EarSpread");
UIWidgets::EnhancementSliderFloat("Goron Neck Length: %f", "##Goron_NeckLength", "gCosmetics.Goron_NeckLength", 0.0f, 1000.0f, "", 0.0f, false);
Reset_Option_Single("Reset##Goron_NeckLength", "gCosmetics.Goron_NeckLength");
UIWidgets::EnhancementCheckbox("Unfix Goron Spin", "gUnfixGoronSpin");
UIWidgets::EnhancementSliderFloat("Fairies Size: %.2fx", "##Fairies_Size", "gCosmetics.Fairies_Size", 0.25f, 5.0f, "", 1.0f, false);
ImGui::SameLine();
if (ImGui::Button("Reset##Fairies_Size")) {
CVarClear("gCosmetics.Fairies_Size");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
UIWidgets::EnhancementSliderFloat("N64 Logo Spin Speed: %.2fx", "##N64Logo_SpinSpeed", "gCosmetics.N64Logo_SpinSpeed", 0.25f, 5.0f, "", 1.0f, false);
ImGui::SameLine();
if (ImGui::Button("Reset##N64Logo_SpinSpeed")) {
CVarClear("gCosmetics.N64Logo_SpinSpeed");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
UIWidgets::EnhancementSliderFloat("Moon Size: %.1f %%", "##Moon_Size", "gCosmetics.Moon_Size", 0.5f, 2.0f, "", 1.0f, true);
ImGui::SameLine();
if (ImGui::Button("Reset##Moon_Size")) {
CVarClear("gCosmetics.Moon_Size");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
if (UIWidgets::EnhancementSliderFloat("Kak Windmill Speed: %.0f", "##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed.Value", 100.0f, 6000.0f, "", 100.0f, false)) {
UIWidgets::EnhancementSliderFloat("Fairies Size: %f", "##Fairies_Size", "gCosmetics.Fairies_Size", 0.25f, 5.0f, "", 1.0f, false);
Reset_Option_Single("Reset##Fairies_Size", "gCosmetics.Fairies_Size");
UIWidgets::EnhancementSliderFloat("N64 Logo Spin Speed: %f", "##N64Logo_SpinSpeed", "gCosmetics.N64Logo_SpinSpeed", 0.25f, 5.0f, "", 1.0f, false);
Reset_Option_Single("Reset##N64Logo_SpinSpeed", "gCosmetics.N64Logo_SpinSpeed");
UIWidgets::EnhancementSliderFloat("Moon Size: %f", "##Moon_Size", "gCosmetics.Moon_Size", 0.5f, 2.0f, "", 1.0f, false);
Reset_Option_Single("Reset##Moon_Size", "gCosmetics.Moon_Size");
if (UIWidgets::EnhancementSliderFloat("Kak Windmill Speed: %f", "##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed.Value", 100.0f, 6000.0f, "", 100.0f, false)) {
CVarSetInteger("gCosmetics.Kak_Windmill_Speed.Changed", 1);
}
ImGui::SameLine();
if (ImGui::Button("Reset##Kak_Windmill_Speed")) {
CVarClear("gCosmetics.Kak_Windmill_Speed.Value");
CVarClear("gCosmetics.Kak_Windmill_Speed.Changed");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
Reset_Option_Double("Reset##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed");
ImGui::EndDisabled();
}
@ -1631,25 +1434,20 @@ void CopyMultipliedColor(CosmeticOption& cosmeticOptionSrc, CosmeticOption& cosm
CVarSetInteger((cosmeticOptionTarget.changedCvar), 1);
}
void RandomizeColor(CosmeticOption& cosmeticOption) {
Color_RGBA8 newColor;
newColor.r = Random(0, 255);
newColor.g = Random(0, 255);
newColor.b = Random(0, 255);
newColor.a = 255;
// For alpha supported options, retain the last set alpha instead of overwriting
if (cosmeticOption.supportsAlpha) {
newColor.a = cosmeticOption.currentColor.w * 255;
void ToggleRainbow(CosmeticOption& cosmeticOption, bool state) {
if (state) {
CVarSetInteger(cosmeticOption.rainbowCvar, 1);
CVarSetInteger(cosmeticOption.changedCvar, 1);
} else {
CVarClear(cosmeticOption.rainbowCvar);
CVarClear(cosmeticOption.changedCvar);
}
}
cosmeticOption.currentColor.x = newColor.r / 255.0;
cosmeticOption.currentColor.y = newColor.g / 255.0;
cosmeticOption.currentColor.z = newColor.b / 255.0;
cosmeticOption.currentColor.w = newColor.a / 255.0;
CVarSetColor(cosmeticOption.cvar, newColor);
CVarSetInteger((cosmeticOption.rainbowCvar), 0);
CVarSetInteger((cosmeticOption.changedCvar), 1);
void ApplySideEffects(CosmeticOption& cosmeticOption) {
if (CVarGetInteger("gCosmetics.AdvancedMode", 0)) {
return;
}
// This bit is kind of experimental, not sure how I feel about it yet, but it allows for
// advanced cosmetic options to be changed based on a non-advanced option.
@ -1671,9 +1469,91 @@ void RandomizeColor(CosmeticOption& cosmeticOption) {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack_Level1Primary"), 2.0f);
} else if (cosmeticOption.label == "Level 2 Secondary") {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack_Level2Primary"), 2.0f);
} else if (cosmeticOption.label == "Item Select Color") {
if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
ToggleRainbow(cosmeticOptions.at("Kal_ItemSelB"), true);
ToggleRainbow(cosmeticOptions.at("Kal_ItemSelC"), true);
ToggleRainbow(cosmeticOptions.at("Kal_ItemSelD"), true);
} else {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_ItemSelB"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_ItemSelC"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_ItemSelD"), 1.0f);
}
} else if (cosmeticOption.label == "Equip Select Color") {
if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
ToggleRainbow(cosmeticOptions.at("Kal_EquipSelB"), true);
ToggleRainbow(cosmeticOptions.at("Kal_EquipSelC"), true);
ToggleRainbow(cosmeticOptions.at("Kal_EquipSelD"), true);
} else {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_EquipSelB"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_EquipSelC"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_EquipSelD"), 1.0f);
}
} else if (cosmeticOption.label == "Map Dungeon Color") {
if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
ToggleRainbow(cosmeticOptions.at("Kal_MapSelDunB"), true);
ToggleRainbow(cosmeticOptions.at("Kal_MapSelDunC"), true);
ToggleRainbow(cosmeticOptions.at("Kal_MapSelDunD"), true);
} else {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelDunB"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelDunC"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelDunD"), 1.0f);
}
} else if (cosmeticOption.label == "Quest Status Color") {
if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
ToggleRainbow(cosmeticOptions.at("Kal_QuestStatusB"), true);
ToggleRainbow(cosmeticOptions.at("Kal_QuestStatusC"), true);
ToggleRainbow(cosmeticOptions.at("Kal_QuestStatusD"), true);
} else {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_QuestStatusB"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_QuestStatusC"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_QuestStatusD"), 1.0f);
}
} else if (cosmeticOption.label == "Map Color") {
if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
ToggleRainbow(cosmeticOptions.at("Kal_MapSelectB"), true);
ToggleRainbow(cosmeticOptions.at("Kal_MapSelectC"), true);
ToggleRainbow(cosmeticOptions.at("Kal_MapSelectD"), true);
} else {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelectB"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelectC"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelectD"), 1.0f);
}
} else if (cosmeticOption.label == "Save Color") {
if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
ToggleRainbow(cosmeticOptions.at("Kal_SaveB"), true);
ToggleRainbow(cosmeticOptions.at("Kal_SaveC"), true);
ToggleRainbow(cosmeticOptions.at("Kal_SaveD"), true);
} else {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_SaveB"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_SaveC"), 2.0f);
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_SaveD"), 1.0f);
}
}
}
void RandomizeColor(CosmeticOption& cosmeticOption) {
Color_RGBA8 newColor;
newColor.r = Random(0, 255);
newColor.g = Random(0, 255);
newColor.b = Random(0, 255);
newColor.a = 255;
// For alpha supported options, retain the last set alpha instead of overwriting
if (cosmeticOption.supportsAlpha) {
newColor.a = cosmeticOption.currentColor.w * 255;
}
cosmeticOption.currentColor.x = newColor.r / 255.0;
cosmeticOption.currentColor.y = newColor.g / 255.0;
cosmeticOption.currentColor.z = newColor.b / 255.0;
cosmeticOption.currentColor.w = newColor.a / 255.0;
CVarSetColor(cosmeticOption.cvar, newColor);
CVarSetInteger((cosmeticOption.rainbowCvar), 0);
CVarSetInteger((cosmeticOption.changedCvar), 1);
ApplySideEffects(cosmeticOption);
}
void ResetColor(CosmeticOption& cosmeticOption) {
Color_RGBA8 defaultColor = {cosmeticOption.defaultColor.x, cosmeticOption.defaultColor.y, cosmeticOption.defaultColor.z, cosmeticOption.defaultColor.w};
cosmeticOption.currentColor.x = defaultColor.r / 255.0;
@ -1691,7 +1571,7 @@ void ResetColor(CosmeticOption& cosmeticOption) {
CVarClear((std::string(cosmeticOption.cvar) + ".A").c_str());
CVarClear((std::string(cosmeticOption.cvar) + ".Type").c_str());
// This portion should match 1:1 the multiplied colors in `RandomizeColor()`
// This portion should match 1:1 the multiplied colors in `ApplySideEffect()`
if (cosmeticOption.label == "Bow Body") {
ResetColor(cosmeticOptions.at("Equipment_BowTips"));
ResetColor(cosmeticOptions.at("Equipment_BowHandle"));
@ -1707,6 +1587,30 @@ void ResetColor(CosmeticOption& cosmeticOption) {
ResetColor(cosmeticOptions.at("SpinAttack_Level1Primary"));
} else if (cosmeticOption.label == "Level 2 Secondary") {
ResetColor(cosmeticOptions.at("SpinAttack_Level2Primary"));
} else if (cosmeticOption.label == "Item Select Color") {
ResetColor(cosmeticOptions.at("Kal_ItemSelB"));
ResetColor(cosmeticOptions.at("Kal_ItemSelC"));
ResetColor(cosmeticOptions.at("Kal_ItemSelD"));
} else if (cosmeticOption.label == "Equip Select Color") {
ResetColor(cosmeticOptions.at("Kal_EquipSelB"));
ResetColor(cosmeticOptions.at("Kal_EquipSelC"));
ResetColor(cosmeticOptions.at("Kal_EquipSelD"));
} else if (cosmeticOption.label == "Map Dungeon Color") {
ResetColor(cosmeticOptions.at("Kal_MapSelDunB"));
ResetColor(cosmeticOptions.at("Kal_MapSelDunC"));
ResetColor(cosmeticOptions.at("Kal_MapSelDunD"));
} else if (cosmeticOption.label == "Quest Status Color") {
ResetColor(cosmeticOptions.at("Kal_QuestStatusB"));
ResetColor(cosmeticOptions.at("Kal_QuestStatusC"));
ResetColor(cosmeticOptions.at("Kal_QuestStatusD"));
} else if (cosmeticOption.label == "Map Color") {
ResetColor(cosmeticOptions.at("Kal_MapSelectB"));
ResetColor(cosmeticOptions.at("Kal_MapSelectC"));
ResetColor(cosmeticOptions.at("Kal_MapSelectD"));
} else if (cosmeticOption.label == "Save Color") {
ResetColor(cosmeticOptions.at("Kal_SaveB"));
ResetColor(cosmeticOptions.at("Kal_SaveC"));
ResetColor(cosmeticOptions.at("Kal_SaveD"));
}
}
@ -1727,6 +1631,7 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) {
CVarSetColor(cosmeticOption.cvar, color);
CVarSetInteger((cosmeticOption.rainbowCvar), 0);
CVarSetInteger((cosmeticOption.changedCvar), 1);
ApplySideEffects(cosmeticOption);
ApplyOrResetCustomGfxPatches();
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
@ -1744,6 +1649,7 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) {
if (ImGui::Checkbox(("Rainbow##" + cosmeticOption.label).c_str(), &isRainbow)) {
CVarSetInteger((cosmeticOption.rainbowCvar), isRainbow);
CVarSetInteger((cosmeticOption.changedCvar), 1);
ApplySideEffects(cosmeticOption);
ApplyOrResetCustomGfxPatches();
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
@ -1800,7 +1706,7 @@ static const char* colorSchemes[2] = {
};
void CosmeticsEditorWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(480, 520), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(550, 520), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Cosmetics Editor", &mIsVisible)) {
ImGui::End();
return;

View File

@ -0,0 +1,271 @@
#include "MessageViewer.h"
#include <soh/UIWidgets.hpp>
#include <textures/message_static/message_static.h>
#include "../custom-message/CustomMessageManager.h"
#include "functions.h"
#include "macros.h"
#include "message_data_static.h"
#include "variables.h"
#include "soh/util.h"
extern "C" u8 sMessageHasSetSfx;
void MessageViewer::InitElement() {
CustomMessageManager::Instance->AddCustomMessageTable(TABLE_ID);
mTableIdBuf = static_cast<char*>(calloc(MAX_STRING_SIZE, sizeof(char)));
mTextIdBuf = static_cast<char*>(calloc(MAX_STRING_SIZE, sizeof(char)));
mCustomMessageBuf = static_cast<char*>(calloc(MAX_STRING_SIZE, sizeof(char)));
}
void MessageViewer::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Custom Message Debugger", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
ImGui::Text("Table ID");
ImGui::SameLine();
ImGui::InputText("##TableID", mTableIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum);
UIWidgets::InsertHelpHoverText("Leave blank for vanilla table");
ImGui::Text("Text ID");
ImGui::SameLine();
switch (mTextIdBase) {
case DECIMAL:
ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsDecimal);
UIWidgets::InsertHelpHoverText("Decimal Text ID of the message to load. Decimal digits only (0-9).");
break;
case HEXADECIMAL:
default:
ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsHexadecimal);
UIWidgets::InsertHelpHoverText("Hexadecimal Text ID of the message to load. Hexadecimal digits only (0-9/A-F).");
break;
}
if (ImGui::RadioButton("Hexadecimal", &mTextIdBase, HEXADECIMAL)) {
memset(mTextIdBuf, 0, sizeof(char) * MAX_STRING_SIZE);
}
ImGui::SameLine();
if (ImGui::RadioButton("Decimal", &mTextIdBase, DECIMAL)) {
memset(mTextIdBuf, 0, sizeof(char) * MAX_STRING_SIZE);
}
ImGui::Text("Language");
ImGui::SameLine();
if (ImGui::BeginCombo("##Language", mLanguages[mLanguage])) {
// ReSharper disable CppDFAUnreachableCode
for (size_t i = 0; i < mLanguages.size(); i++) {
if (strlen(mLanguages[i]) > 0) {
if (ImGui::Selectable(mLanguages[i], i == mLanguage)) {
mLanguage = i;
}
}
}
ImGui::EndCombo();
}
UIWidgets::InsertHelpHoverText("Which language to load from the selected text ID");
if (ImGui::Button("Display Message##ExistingMessage")) {
mDisplayExistingMessageClicked = true;
}
ImGui::Text("Custom Message");
UIWidgets::InsertHelpHoverText("Enter a string using Custom Message Syntax to preview it in-game. "
"Any newline (\\n) characters inserted by the Enter key will be stripped "
"from the output.");
ImGui::InputTextMultiline("##CustomMessage", mCustomMessageBuf, MAX_STRING_SIZE);
if (ImGui::Button("Display Message##CustomMessage")) {
mDisplayCustomMessageClicked = true;
}
ImGui::End();
// ReSharper restore CppDFAUnreachableCode
}
void MessageViewer::UpdateElement() {
if (mDisplayExistingMessageClicked) {
mTableId = std::string(mTableIdBuf);
switch (mTextIdBase) {
case DECIMAL:
mTextId = std::stoi(std::string(mTextIdBuf), nullptr, 10);
break;
case HEXADECIMAL:
default:
mTextId = std::stoi(std::string(mTextIdBuf), nullptr, 16);
break;
}
DisplayExistingMessage();
mDisplayExistingMessageClicked = false;
}
if (mDisplayCustomMessageClicked) {
mCustomMessageString = std::string(mCustomMessageBuf);
std::erase(mCustomMessageString, '\n');
DisplayCustomMessage();
mDisplayCustomMessageClicked = false;
}
}
void MessageViewer::DisplayExistingMessage() const {
MessageDebug_StartTextBox(mTableId.c_str(), mTextId, mLanguage);
}
void MessageViewer::DisplayCustomMessage() const {
MessageDebug_DisplayCustomMessage(mCustomMessageString.c_str());
}
extern "C" MessageTableEntry* sNesMessageEntryTablePtr;
extern "C" MessageTableEntry* sGerMessageEntryTablePtr;
extern "C" MessageTableEntry* sFraMessageEntryTablePtr;
extern "C" MessageTableEntry* sStaffMessageEntryTablePtr;
void FindMessage(PlayState* play, const uint16_t textId, const uint8_t language) {
const char* foundSeg;
const char* nextSeg;
MessageTableEntry* messageTableEntry = sNesMessageEntryTablePtr;
Font* font;
u16 bufferId = textId;
// Use the better owl message if better owl is enabled
if (CVarGetInteger("gBetterOwl", 0) != 0 && (bufferId == 0x2066 || bufferId == 0x607B ||
bufferId == 0x10C2 || bufferId == 0x10C6 || bufferId == 0x206A))
{
bufferId = 0x71B3;
}
if (language == LANGUAGE_GER)
messageTableEntry = sGerMessageEntryTablePtr;
else if (language == LANGUAGE_FRA)
messageTableEntry = sFraMessageEntryTablePtr;
// If PAL languages are not present in the OTR file, default to English
if (messageTableEntry == nullptr)
messageTableEntry = sNesMessageEntryTablePtr;
const char* seg = messageTableEntry->segment;
while (messageTableEntry->textId != 0xFFFF) {
font = &play->msgCtx.font;
if (messageTableEntry->textId == bufferId) {
foundSeg = messageTableEntry->segment;
font->charTexBuf[0] = messageTableEntry->typePos;
nextSeg = messageTableEntry->segment;
font->msgOffset = reinterpret_cast<uintptr_t>(messageTableEntry->segment);
font->msgLength = messageTableEntry->msgSize;
return;
}
messageTableEntry++;
}
font = &play->msgCtx.font;
messageTableEntry = sNesMessageEntryTablePtr;
foundSeg = messageTableEntry->segment;
font->charTexBuf[0] = messageTableEntry->typePos;
messageTableEntry++;
nextSeg = messageTableEntry->segment;
font->msgOffset = foundSeg - seg;
font->msgLength = nextSeg - foundSeg;
}
static const char* msgStaticTbl[] =
{
gDefaultMessageBackgroundTex,
gSignMessageBackgroundTex,
gNoteStaffMessageBackgroundTex,
gFadingMessageBackgroundTex,
gMessageContinueTriangleTex,
gMessageEndSquareTex,
gMessageArrowTex
};
void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t language) {
PlayState* play = gPlayState;
static int16_t messageStaticIndices[] = { 0, 1, 3, 2 };
const auto player = GET_PLAYER(gPlayState);
player->actor.flags |= ACTOR_FLAG_PLAYER_TALKED_TO;
MessageContext* msgCtx = &play->msgCtx;
msgCtx->ocarinaAction = 0xFFFF;
Font* font = &msgCtx->font;
sMessageHasSetSfx = 0;
for (u32 i = 0; i < FONT_CHAR_TEX_SIZE * 120; i += FONT_CHAR_TEX_SIZE) {
if (&font->charTexBuf[i] != nullptr) {
gSPInvalidateTexCache(play->state.gfxCtx->polyOpa.p++, reinterpret_cast<uintptr_t>(&font->charTexBuf[i]));
}
}
R_TEXT_CHAR_SCALE = 75;
R_TEXT_LINE_SPACING = 12;
R_TEXT_INIT_XPOS = 65;
char* buffer = font->msgBuf;
msgCtx->textId = textId;
if (strlen(tableId) == 0) {
FindMessage(play, textId, language);
msgCtx->msgLength = static_cast<int32_t>(font->msgLength);
const uintptr_t src = font->msgOffset;
memcpy(font->msgBuf, reinterpret_cast<void const *>(src), font->msgLength);
} else {
constexpr int maxBufferSize = sizeof(font->msgBuf);
const CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(tableId, textId);
font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition();
switch (language) {
case LANGUAGE_FRA:
font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetFrench(), maxBufferSize);
break;
case LANGUAGE_GER:
font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetGerman(), maxBufferSize);
break;
case LANGUAGE_ENG:
default:
font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetEnglish(), maxBufferSize);
break;
}
msgCtx->msgLength = static_cast<int32_t>(font->msgLength);
}
msgCtx->textBoxProperties = font->charTexBuf[0];
msgCtx->textBoxType = msgCtx->textBoxProperties >> 4;
msgCtx->textBoxPos = msgCtx->textBoxProperties & 0xF;
const int16_t textBoxType = msgCtx->textBoxType;
// "Text Box Type"
osSyncPrintf("吹き出し種類=%d\n", msgCtx->textBoxType);
if (textBoxType < TEXTBOX_TYPE_NONE_BOTTOM) {
const char* textureName = msgStaticTbl[messageStaticIndices[textBoxType]];
memcpy(msgCtx->textboxSegment, textureName, strlen(textureName) + 1);
if (textBoxType == TEXTBOX_TYPE_BLACK) {
msgCtx->textboxColorRed = 0;
msgCtx->textboxColorGreen = 0;
msgCtx->textboxColorBlue = 0;
} else if (textBoxType == TEXTBOX_TYPE_WOODEN) {
msgCtx->textboxColorRed = 70;
msgCtx->textboxColorGreen = 50;
msgCtx->textboxColorBlue = 30;
} else if (textBoxType == TEXTBOX_TYPE_BLUE) {
msgCtx->textboxColorRed = 0;
msgCtx->textboxColorGreen = 10;
msgCtx->textboxColorBlue = 50;
} else {
msgCtx->textboxColorRed = 255;
msgCtx->textboxColorGreen = 0;
msgCtx->textboxColorBlue = 0;
}
if (textBoxType == TEXTBOX_TYPE_WOODEN) {
msgCtx->textboxColorAlphaTarget = 230;
} else if (textBoxType == TEXTBOX_TYPE_OCARINA) {
msgCtx->textboxColorAlphaTarget = 180;
} else {
msgCtx->textboxColorAlphaTarget = 170;
}
msgCtx->textboxColorAlphaCurrent = 0;
}
msgCtx->choiceNum = msgCtx->textUnskippable = msgCtx->textboxEndType = 0;
msgCtx->msgBufPos = msgCtx->unk_E3D0 = msgCtx->textDrawPos = 0;
msgCtx->talkActor = &player->actor;
msgCtx->msgMode = MSGMODE_TEXT_START;
msgCtx->stateTimer = 0;
msgCtx->textDelayTimer = 0;
msgCtx->ocarinaMode = OCARINA_MODE_00;
}
void MessageDebug_DisplayCustomMessage(const char* customMessage) {
CustomMessageManager::Instance->ClearMessageTable(MessageViewer::TABLE_ID);
CustomMessageManager::Instance->CreateMessage(MessageViewer::TABLE_ID, 0,
CustomMessage(customMessage, customMessage, customMessage));
MessageDebug_StartTextBox(MessageViewer::TABLE_ID, 0, 0);
}

View File

@ -0,0 +1,62 @@
#ifndef CUSTOMMESSAGEDEBUGGER_H
#define CUSTOMMESSAGEDEBUGGER_H
#include "z64.h"
#ifdef __cplusplus
#include "GuiWindow.h"
#include <array>
extern "C" {
#endif
/**
* \brief Pulls a message from the specified message table and kicks off the process of displaying that message
* in a text box on screen.
* \param tableId the tableId string for the table we want to pull from. Empty string for authentic/vanilla messages
* \param textId The textId corresponding to the message to display. Putting in a textId that doesn't exist will
* probably result in a crash.
* \param language The Language to display on the screen.
*/
void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t language);
/**
* \brief
* \param customMessage A string using Custom Message Syntax.
*/
void MessageDebug_DisplayCustomMessage(const char* customMessage);
#ifdef __cplusplus
}
class MessageViewer : public LUS::GuiWindow {
public:
static inline const char* TABLE_ID = "MessageViewer";
using GuiWindow::GuiWindow;
void InitElement() override;
void DrawElement() override;
void UpdateElement() override;
virtual ~MessageViewer() = default;
private:
void DisplayExistingMessage() const;
void DisplayCustomMessage() const;
static constexpr uint16_t MAX_STRING_SIZE = 1024;
static constexpr std::array<const char*, LANGUAGE_MAX> mLanguages = {"English", "German", "French"};
static constexpr int HEXADECIMAL = 0;
static constexpr int DECIMAL = 1;
char* mTableIdBuf;
std::string mTableId;
char* mTextIdBuf;
uint16_t mTextId;
int mTextIdBase = HEXADECIMAL;
size_t mLanguage = LANGUAGE_ENG;
char* mCustomMessageBuf;
std::string mCustomMessageString;
bool mDisplayExistingMessageClicked = false;
bool mDisplayCustomMessageClicked = false;
};
#endif //__cplusplus
#endif //CUSTOMMESSAGEDEBUGGER_H

View File

@ -9,7 +9,6 @@
#include <bit>
#include <map>
#include <string>
#include <regex>
#include <libultraship/libultraship.h>
#include "dlViewer.h"
@ -68,14 +67,12 @@ std::map<int, std::string> cmdMap = {
void PerformDisplayListSearch() {
auto result = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*" + std::string(searchString) + "*DL*");
std::regex dlSearch(".*((DL)|(DL_.*))$");
displayListSearchResults.clear();
// Filter the file results even further as StormLib can only use wildcard searching
for (size_t i = 0; i < result->size(); i++) {
std::string val = result->at(i);
if (std::regex_search(val.c_str(), dlSearch)) {
if (val.ends_with("DL") || val.find("DL_") != std::string::npos) {
displayListSearchResults.push_back(val);
}
}
@ -99,8 +96,6 @@ void DLViewerWindow::DrawElement() {
return;
}
ImGui::Text("%d", searchDebounceFrames);
// Debounce the search field as listing otr files is expensive
if (ImGui::InputText("Search Display Lists", searchString, ARRAY_COUNT(searchString))) {
doSearch = true;

View File

@ -78,4 +78,10 @@ typedef enum {
DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE,
} DekuStickType;
typedef enum {
SWORD_TOGGLE_NONE,
SWORD_TOGGLE_CHILD,
SWORD_TOGGLE_BOTH_AGES,
} SwordToggleMode;
#endif

View File

@ -37,12 +37,19 @@ GameInteractionEffectQueryResult GameInteractor::RemoveEffect(RemovableGameInter
// MARK: - Helpers
bool GameInteractor::IsSaveLoaded() {
bool GameInteractor::IsSaveLoaded(bool allowDbgSave) {
Player* player;
if (gPlayState != NULL) {
player = GET_PLAYER(gPlayState);
}
return (gPlayState == NULL || player == NULL || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) ? false : true;
// Checking for normal game mode prevents debug saves from reporting true on title screen
if (gPlayState == NULL || player == NULL || gSaveContext.gameMode != GAMEMODE_NORMAL) {
return false;
}
// Valid save file or debug save
return (gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2) || (allowDbgSave && gSaveContext.fileNum == 0xFF);
}
bool GameInteractor::IsGameplayPaused() {

View File

@ -163,11 +163,30 @@ public:
static GameInteractionEffectQueryResult RemoveEffect(RemovableGameInteractionEffect* effect);
// Game Hooks
template <typename H> struct RegisteredGameHooks { inline static std::vector<typename H::fn> functions; };
template <typename H> void RegisterGameHook(typename H::fn h) { RegisteredGameHooks<H>::functions.push_back(h); }
uint32_t nextHookId = 1;
template <typename H> struct RegisteredGameHooks { inline static std::unordered_map<uint32_t, typename H::fn> functions; };
template <typename H> struct HooksToUnregister { inline static std::vector<uint32_t> hooks; };
template <typename H> uint32_t RegisterGameHook(typename H::fn h) {
// Ensure hook id is unique and not 0, which is reserved for invalid hooks
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1;
while (RegisteredGameHooks<H>::functions.find(this->nextHookId) != RegisteredGameHooks<H>::functions.end()) {
this->nextHookId++;
}
RegisteredGameHooks<H>::functions[this->nextHookId] = h;
return this->nextHookId++;
}
template <typename H> void UnregisterGameHook(uint32_t id) {
HooksToUnregister<H>::hooks.push_back(id);
}
template <typename H, typename... Args> void ExecuteHooks(Args&&... args) {
for (auto& fn : RegisteredGameHooks<H>::functions) {
fn(std::forward<Args>(args)...);
for (auto& hookId : HooksToUnregister<H>::hooks) {
RegisteredGameHooks<H>::functions.erase(hookId);
}
HooksToUnregister<H>::hooks.clear();
for (auto& hook : RegisteredGameHooks<H>::functions) {
hook.second(std::forward<Args>(args)...);
}
}
@ -224,7 +243,7 @@ public:
DEFINE_HOOK(OnKaleidoUpdate, void());
// Helpers
static bool IsSaveLoaded();
static bool IsSaveLoaded(bool allowDbgSave = false);
static bool IsGameplayPaused();
static bool CanSpawnActor();
static bool CanAddOrTakeAmmo(int16_t amount, int16_t item);

View File

@ -111,9 +111,9 @@ void GameInteractor::RawAction::FreezePlayer() {
void GameInteractor::RawAction::BurnPlayer() {
Player* player = GET_PLAYER(gPlayState);
for (int i = 0; i < 18; i++) {
player->flameTimers[i] = Rand_S16Offset(0, 200);
player->bodyFlameTimers[i] = Rand_S16Offset(0, 200);
}
player->isBurning = true;
player->bodyIsBurning = true;
func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0);
}

View File

@ -26,6 +26,7 @@
#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_Fishing/z_fishing.h"
#include "src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h"
#include "objects/object_link_boy/object_link_boy.h"
#include "objects/object_link_child/object_link_child.h"
@ -36,6 +37,7 @@ extern "C" {
#include "functions.h"
#include "variables.h"
#include "functions.h"
#include "src/overlays/actors/ovl_En_Door/z_en_door.h"
void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction);
void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName);
@ -66,7 +68,7 @@ void ReloadSceneTogglingLinkAge() {
void RegisterInfiniteMoney() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded(true)) return;
if (CVarGetInteger("gInfiniteMoney", 0) != 0 && (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))) {
if (gSaveContext.rupees < CUR_CAPACITY(UPG_WALLET)) {
gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET);
@ -77,7 +79,7 @@ void RegisterInfiniteMoney() {
void RegisterInfiniteHealth() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded(true)) return;
if (CVarGetInteger("gInfiniteHealth", 0) != 0) {
if (gSaveContext.health < gSaveContext.healthCapacity) {
gSaveContext.health = gSaveContext.healthCapacity;
@ -88,7 +90,7 @@ void RegisterInfiniteHealth() {
void RegisterInfiniteAmmo() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded(true)) return;
if (CVarGetInteger("gInfiniteAmmo", 0) != 0) {
// Deku Sticks
if (AMMO(ITEM_STICK) < CUR_CAPACITY(UPG_STICKS)) {
@ -125,7 +127,7 @@ void RegisterInfiniteAmmo() {
void RegisterInfiniteMagic() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded(true)) return;
if (CVarGetInteger("gInfiniteMagic", 0) != 0) {
if (gSaveContext.isMagicAcquired && gSaveContext.magic != (gSaveContext.isDoubleMagicAcquired + 1) * 0x30) {
gSaveContext.magic = (gSaveContext.isDoubleMagicAcquired + 1) * 0x30;
@ -136,7 +138,7 @@ void RegisterInfiniteMagic() {
void RegisterInfiniteNayrusLove() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded(true)) return;
if (CVarGetInteger("gInfiniteNayru", 0) != 0) {
gSaveContext.nayrusLoveTimer = 0x44B;
}
@ -145,7 +147,7 @@ void RegisterInfiniteNayrusLove() {
void RegisterMoonJumpOnL() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded(true)) return;
if (CVarGetInteger("gMoonJumpOnL", 0) != 0) {
Player* player = GET_PLAYER(gPlayState);
@ -160,7 +162,7 @@ void RegisterMoonJumpOnL() {
void RegisterInfiniteISG() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded(true)) return;
if (CVarGetInteger("gEzISG", 0) != 0) {
Player* player = GET_PLAYER(gPlayState);
@ -172,7 +174,7 @@ void RegisterInfiniteISG() {
//Permanent quick put away (QPA) glitched damage value
void RegisterEzQPA() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded(true)) return;
if (CVarGetInteger("gEzQPA", 0) != 0) {
Player* player = GET_PLAYER(gPlayState);
@ -184,7 +186,7 @@ void RegisterEzQPA() {
void RegisterUnrestrictedItems() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded(true)) return;
if (CVarGetInteger("gNoRestrictItems", 0) != 0) {
u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong;
@ -212,11 +214,14 @@ void RegisterFreezeTime() {
/// Switches Link's age and respawns him at the last entrance he entered.
void RegisterSwitchAge() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded()) {
static bool warped = false;
if (!GameInteractor::IsSaveLoaded(true)) {
CVarClear("gSwitchAge");
warped = false;
return;
}
static bool warped = false;
static Vec3f playerPos;
static int16_t playerYaw;
static RoomContext* roomCtx;
@ -250,7 +255,7 @@ void RegisterSwitchAge() {
void RegisterOcarinaTimeTravel() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnOcarinaSongAction>([]() {
if (!GameInteractor::IsSaveLoaded()) {
if (!GameInteractor::IsSaveLoaded(true)) {
CVarClear("gTimeTravel");
return;
}
@ -521,70 +526,93 @@ void RegisterDaytimeGoldSkultullas() {
});
}
void RegisterHyperBosses() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make bosses move and act twice as fast.
bool IsHyperBossesActive() {
return CVarGetInteger("gHyperBosses", 0) ||
(IS_BOSS_RUSH && gSaveContext.bossRushOptions[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
}
Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor);
void UpdateHyperBossesState() {
static uint32_t actorUpdateHookId = 0;
if (actorUpdateHookId != 0) {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(actorUpdateHookId);
actorUpdateHookId = 0;
}
uint8_t isBossActor =
actor->id == ACTOR_BOSS_GOMA || // Gohma
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath
actor->id == ACTOR_BOSS_VA || // Barinade
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder
actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse
actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying)
actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks
actor->id == ACTOR_BOSS_MO || // Morpha
actor->id == ACTOR_BOSS_SST || // Bongo Bongo
actor->id == ACTOR_BOSS_TW || // Twinrova
actor->id == ACTOR_BOSS_GANON || // Ganondorf
actor->id == ACTOR_BOSS_GANON2; // Ganon
if (IsHyperBossesActive()) {
actorUpdateHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make bosses move and act twice as fast.
uint8_t hyperBossesActive =
CVarGetInteger("gHyperBosses", 0) ||
(IS_BOSS_RUSH &&
gSaveContext.bossRushOptions[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor);
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses.
if (hyperBossesActive && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) {
// Barinade needs to be updated in sequence to avoid unintended behaviour.
if (actor->id == ACTOR_BOSS_VA) {
// params -1 is BOSSVA_BODY
if (actor->params == -1) {
Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head;
while (actorList != NULL) {
GameInteractor::RawAction::UpdateActor(actorList);
actorList = actorList->next;
uint8_t isBossActor =
actor->id == ACTOR_BOSS_GOMA || // Gohma
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath
actor->id == ACTOR_BOSS_VA || // Barinade
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder
actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse
actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying)
actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks
actor->id == ACTOR_BOSS_MO || // Morpha
actor->id == ACTOR_BOSS_SST || // Bongo Bongo
actor->id == ACTOR_BOSS_TW || // Twinrova
actor->id == ACTOR_BOSS_GANON || // Ganondorf
actor->id == ACTOR_BOSS_GANON2; // Ganon
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses.
if (IsHyperBossesActive() && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) {
// Barinade needs to be updated in sequence to avoid unintended behaviour.
if (actor->id == ACTOR_BOSS_VA) {
// params -1 is BOSSVA_BODY
if (actor->params == -1) {
Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head;
while (actorList != NULL) {
GameInteractor::RawAction::UpdateActor(actorList);
actorList = actorList->next;
}
}
} else {
GameInteractor::RawAction::UpdateActor(actor);
}
} else {
GameInteractor::RawAction::UpdateActor(actor);
}
}
});
}
}
void RegisterHyperBosses() {
UpdateHyperBossesState();
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int16_t fileNum) {
UpdateHyperBossesState();
});
}
void RegisterHyperEnemies() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make enemies and minibosses move and act twice as fast.
void UpdateHyperEnemiesState() {
static uint32_t actorUpdateHookId = 0;
if (actorUpdateHookId != 0) {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(actorUpdateHookId);
actorUpdateHookId = 0;
}
Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor);
if (CVarGetInteger("gHyperEnemies", 0)) {
actorUpdateHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make enemies and minibosses move and act twice as fast.
// Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies.
bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2;
bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2;
Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor);
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes.
if (CVarGetInteger("gHyperEnemies", 0) && isEnemy && !isExcludedEnemy &&
!Player_InBlockingCsMode(gPlayState, player)) {
GameInteractor::RawAction::UpdateActor(actor);
}
});
// Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies.
bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2;
bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2;
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes.
if (CVarGetInteger("gHyperEnemies", 0) && isEnemy && !isExcludedEnemy &&
!Player_InBlockingCsMode(gPlayState, player)) {
GameInteractor::RawAction::UpdateActor(actor);
}
});
}
}
void RegisterBonkDamage() {
@ -1283,6 +1311,34 @@ void RegisterRandomizedEnemySizes() {
});
}
void RegisterOpenAllHours() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
Actor* actor = static_cast<Actor*>(refActor);
if (CVarGetInteger("gEnhancements.OpenAllHours", 0) && (actor->id == ACTOR_EN_DOOR)) {
switch (actor->params) {
case 4753: // Night Market Bazaar
case 1678: // Night Potion Shop
case 2689: // Day Bombchu Shop
case 2703: // Night Slingshot Game
case 653: // Day Chest Game
case 6801: // Night Kak Bazaar
case 7822: // Night Kak Potion Shop
case 4751: // Night Kak Archery Game
case 3728: // Night Mask Shop
{
actor->params = (actor->params & 0xFC00) | (DOOR_SCENEEXIT << 7) | 0x3F;
EnDoor* enDoor = static_cast<EnDoor*>(refActor);
EnDoor_SetupType(enDoor, gPlayState);
break;
}
default:
break;
}
}
});
}
void PatchToTMedallions() {
// TODO: Refactor the DemoEffect_UpdateJewelAdult and DemoEffect_UpdateJewelChild from z_demo_effect
// effects to take effect in there
@ -1365,6 +1421,23 @@ void RegisterToTMedallions() {
});
}
void RegisterFloorSwitchesHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
Actor* actor = static_cast<Actor*>(refActor);
if (actor->id != ACTOR_OBJ_SWITCH || !CVarGetInteger("gEnhancements.FixFloorSwitches", 0)) {
return;
}
ObjSwitch* switchActor = reinterpret_cast<ObjSwitch*>(actor);
s32 type = (switchActor->dyna.actor.params & 7);
if (switchActor->dyna.actor.params == 0x1200 || switchActor->dyna.actor.params == 0x3A00) {
switchActor->dyna.actor.world.pos.y -= 1;
}
});
}
void RegisterPauseMenuHooks() {
static bool pauseWarpHooksRegistered = false;
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([&]() {
@ -1654,7 +1727,7 @@ void InitMods() {
RegisterPermanentHeartLoss();
RegisterDeleteFileOnDeath();
RegisterHyperBosses();
RegisterHyperEnemies();
UpdateHyperEnemiesState();
RegisterBonkDamage();
RegisterMenuPathFix();
RegisterMirrorModeHandler();
@ -1666,12 +1739,14 @@ void InitMods() {
RegisterRandomizerSheikSpawn();
RegisterBossSouls();
RegisterRandomizedEnemySizes();
RegisterOpenAllHours();
RegisterToTMedallions();
RegisterNoSwim();
RegisterNoWallet();
RegisterFishsanity();
RegisterRandomizerCompasses();
NameTag_RegisterHooks();
RegisterFloorSwitchesHook();
RegisterPatchHandHandler();
RegisterHurtContainerModeHandler();
RegisterPauseMenuHooks();

View File

@ -13,6 +13,8 @@ void UpdateHurtContainerModeState(bool newState);
void PatchToTMedallions();
void PatchCompasses();
void UpdatePermanentHeartLossState();
void UpdateHyperEnemiesState();
void UpdateHyperBossesState();
void InitMods();
void UpdatePatchHand();

View File

@ -262,6 +262,24 @@ const std::vector<const char*> enhancementsCvars = {
"gAddTraps.Tele",
"gAddTraps.Void",
"gToTMedallionsColors",
"gCuccoStayDurationMultiplier",
"gDeleteFileOnDeath",
"gEnemySizeScalesHealth",
"gEnhancements.BetterAmmoRendering",
"gEnhancements.EquimentAlwaysVisible",
"gEnhancements.FixDaruniaDanceSpeed",
"gEnhancements.OpenAllHours",
"gEnhancements.ResetNaviTimer",
"gEnhancements.ScaleAdultEquimentAsChild",
"gEnhancements.LeeverSpawnRate",
"gEnhancements.SwordToggle",
"gEnhancements.FixFloorSwitches",
"gFixZoraHintDialogue",
"gHurtContainer",
"gPauseWarp",
"gPermanentHeartLoss",
"gRemoveExplosiveLimit",
"gToggleStrength",
};
const std::vector<const char*> cheatCvars = {
@ -314,6 +332,7 @@ const std::vector<const char*> cheatCvars = {
"gSwitchAge",
"gSwitchTimeline",
"gNoRedeadFreeze",
"gNoKeeseGuayTarget",
"gBombTimerMultiplier",
"gNoFishDespawn",
"gNoBugsDespawn",
@ -333,6 +352,7 @@ const std::vector<const char*> cheatCvars = {
"gCosmetics.Link_HeadScale.Value",
"gCosmetics.Link_SwordScale.Changed",
"gCosmetics.Link_SwordScale.Value",
"gEnhancements.RememberMapToggleState",
};
const std::vector<const char*> randomizerCvars = {
@ -532,6 +552,8 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
PRESET_ENTRY_S32("gNaviTextFix", 1),
// Extend Silver Rupee Jingle
PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1),
// Fix some Floor Switches
PRESET_ENTRY_S32("gEnhancements.FixFloorSwitches", 1),
// Red Ganon blood
PRESET_ENTRY_S32("gRedGanonBlood", 1),
@ -603,6 +625,8 @@ const std::vector<PresetEntry> enhancedPresetEntries = {
PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1),
// Fix enemies not spawning on ground over water
PRESET_ENTRY_S32("gEnemySpawnsOverWaterboxes", 1),
// Fix some Floor Switches
PRESET_ENTRY_S32("gEnhancements.FixFloorSwitches", 1),
// Red Ganon blood
PRESET_ENTRY_S32("gRedGanonBlood", 1),
@ -725,6 +749,8 @@ const std::vector<PresetEntry> randomizerPresetEntries = {
PRESET_ENTRY_S32("gNaviTextFix", 1),
// Extend Silver Rupee Jingle
PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1),
// Fix some Floor Switches
PRESET_ENTRY_S32("gEnhancements.FixFloorSwitches", 1),
// Red Ganon blood
PRESET_ENTRY_S32("gRedGanonBlood", 1),

View File

@ -525,6 +525,11 @@ void Randomizer::LoadMerchantMessages() {
CustomMessage(ctx->GetHint(RH_BEAN_SALESMAN)->GetText().GetEnglish(),
ctx->GetHint(RH_BEAN_SALESMAN)->GetText().GetGerman(),
ctx->GetHint(RH_BEAN_SALESMAN)->GetText().GetFrench()));
CustomMessageManager::Instance->CreateMessage(
Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100,
CustomMessage("I never thought I'd say this, but I'm &selling the last %rMagic Bean%w. %r99%w Rupees...\x1B&%gYes&No%w",
"\x1B&%gJa&Nein%w",
"Je te vends mon dernier %rHaricot&magique%w pour %r99 Rubis%w.\x1B&%gAcheter&Ne pas acheter%w"));
//Setup for merchant text boxes
@ -536,7 +541,7 @@ void Randomizer::LoadMerchantMessages() {
ctx->GetHint(RH_MEDIGORON)->GetText().GetGerman(),
ctx->GetHint(RH_MEDIGORON)->GetText().GetFrench()));
//Granny Shopy
//Granny Shop
//RANDOTODO: Implement obscure/ambiguous hints
CustomMessageManager::Instance->CreateMessage(
Randomizer::merchantMessageTableID, TEXT_GRANNYS_SHOP,
@ -2164,7 +2169,11 @@ void RandomizerSettingsWindow::DrawElement() {
excludedLocationString += std::to_string(excludedLocationIt);
excludedLocationString += ",";
}
CVarSetString("gRandomizeExcludedLocations", excludedLocationString.c_str());
if (excludedLocationString == "") {
CVarClear("gRandomizeExcludedLocations");
} else {
CVarSetString("gRandomizeExcludedLocations", excludedLocationString.c_str());
}
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
ImGui::SameLine();
@ -2334,7 +2343,7 @@ void RandomizerSettingsWindow::DrawElement() {
enabledTrickString += std::to_string(enabledTrickIt);
enabledTrickString += ",";
}
CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str());
CVarClear("gRandomizeEnabledTricks");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
ImGui::SameLine();
@ -2506,7 +2515,7 @@ void RandomizerSettingsWindow::DrawElement() {
enabledTrickString += std::to_string(enabledTrickIt);
enabledTrickString += ",";
}
CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str());
CVarClear("gRandomizeEnabledTricks");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
@ -2541,7 +2550,11 @@ void RandomizerSettingsWindow::DrawElement() {
enabledTrickString += std::to_string(enabledTrickIt);
enabledTrickString += ",";
}
CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str());
if (enabledTrickString == "") {
CVarClear("gRandomizeEnabledTricks");
} else {
CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str());
}
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
Rando::Tricks::DrawTagChips(option.GetTags());
@ -2696,7 +2709,7 @@ CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) {
}
CustomMessage Randomizer::GetSariaMessage(u16 originalTextId) {
if (originalTextId == TEXT_SARIA_SFM || (originalTextId == TEXT_SARIAS_SONG_FOREST_SOUNDS && originalTextId == TEXT_SARIAS_SONG_FOREST_TEMPLE)) {
if (originalTextId == TEXT_SARIA_SFM || (originalTextId >= TEXT_SARIAS_SONG_FACE_TO_FACE && originalTextId <= TEXT_SARIAS_SONG_CHANNELING_POWER)) {
CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SARIAS_SONG_FACE_TO_FACE);
CustomMessage messageEntry2 = messageEntry;
std::string code = originalTextId == TEXT_SARIA_SFM ? "" : "\x0B";

View File

@ -781,7 +781,6 @@ void InitTrackerData(bool isDebug) {
}
}
UpdateAllOrdering();
UpdateInventoryChecks();
}
void SaveTrackerData(SaveContext* saveContext, int sectionID, bool gameSave) {

View File

@ -497,8 +497,8 @@ void Entrance_EnableFW(void) {
gPlayState->sceneNum == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR || gPlayState->sceneNum == SCENE_GROTTOS ||
gPlayState->sceneNum == SCENE_FISHING_POND || gPlayState->sceneNum == SCENE_GANON_BOSS ||
gSaveContext.eventInf[0] & 0x1 || // Ingo's Minigame state
player->stateFlags1 & 0x08A02000 || // Swimming, riding horse, Down A, hanging from a ledge
player->stateFlags2 & 0x00040000 // Blank A
player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LADDER | PLAYER_STATE1_ON_HORSE | PLAYER_STATE1_IN_WATER) || // Swimming, riding horse, Down A, hanging from a ledge
player->stateFlags2 & PLAYER_STATE2_CRAWLING // Blank A
// Shielding, spinning and getting skull tokens still disable buttons automatically
) {
return;

View File

@ -30,6 +30,8 @@ void DrawBottle(ItemTrackerItem item);
void DrawQuest(ItemTrackerItem item);
void DrawSong(ItemTrackerItem item);
int itemTrackerSectionId;
bool shouldUpdateVectors = true;
std::vector<ItemTrackerItem> mainWindowItems = {};
@ -330,11 +332,6 @@ void ItemTrackerOnFrame() {
}
}
void SaveNotes(uint32_t fileNum) {
CVarSetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), std::string(std::begin(itemTrackerNotes), std::end(itemTrackerNotes)).c_str());
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
bool IsValidSaveFile() {
bool validSave = gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2;
return validSave;
@ -900,7 +897,7 @@ void DrawNotes(bool resizeable = false) {
}
if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) {
notesNeedSave = false;
SaveNotes(gSaveContext.fileNum);
SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true);
}
ImGui::EndGroup();
}
@ -1165,6 +1162,26 @@ void UpdateVectors() {
shouldUpdateVectors = false;
}
void ItemTrackerInitFile(bool isDebug) {
itemTrackerNotes.clear();
itemTrackerNotes.push_back(0);
}
void ItemTrackerSaveFile(SaveContext* saveContext, int sectionID, bool fullSave) {
SaveManager::Instance->SaveData("personalNotes", std::string(std::begin(itemTrackerNotes), std::end(itemTrackerNotes)).c_str());
}
void ItemTrackerLoadFile() {
std::string initialTrackerNotes = "";
SaveManager::Instance->LoadData("personalNotes", initialTrackerNotes);
itemTrackerNotes.resize(initialTrackerNotes.length() + 1);
if (initialTrackerNotes != "") {
SohUtils::CopyStringToCharArray(itemTrackerNotes.Data, initialTrackerNotes.c_str(), itemTrackerNotes.size());
} else {
itemTrackerNotes.push_back(0);
}
}
void ItemTrackerWindow::DrawElement() {
UpdateVectors();
@ -1465,14 +1482,9 @@ void ItemTrackerWindow::InitElement() {
itemTrackerNotes.push_back(0);
}
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadFile>([](uint32_t fileNum) {
const char* initialTrackerNotes = CVarGetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), "");
itemTrackerNotes.resize(strlen(initialTrackerNotes) + 1);
strcpy(itemTrackerNotes.Data, initialTrackerNotes);
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnDeleteFile>([](uint32_t fileNum) {
CVarSetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), "");
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
});
SaveManager::Instance->AddInitFunction(ItemTrackerInitFile);
itemTrackerSectionId = SaveManager::Instance->AddSaveFunction("itemTrackerData", 1, ItemTrackerSaveFile, true, -1);
SaveManager::Instance->AddLoadFunction("itemTrackerData", 1, ItemTrackerLoadFile);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(ItemTrackerOnFrame);
}

View File

@ -168,7 +168,7 @@ void RegisterOnInterfaceUpdateHook() {
prevTimer = timer;
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded(true)) return;
static int16_t lostHealth = 0;
static int16_t prevHealth = 0;

View File

@ -107,7 +107,8 @@ void Extractor::ShowSizeErrorBox() const {
}
void Extractor::ShowCrcErrorBox() const {
ShowErrorBox("Rom CRC invalid", "Rom CRC did not match the list of known good roms. Please find another.");
ShowErrorBox("Rom CRC invalid", "Rom CRC did not match the list of known compatible roms. Please find another.\n\n"
"Visit https://ship.equipment/ to validate your ROM and see a list of compatible versions");
}
void Extractor::ShowCompressedErrorBox() const {
@ -479,7 +480,8 @@ bool Extractor::Run(std::string searchPath, RomSearchMode searchMode) {
ShowCrcErrorBox();
} else {
ShowErrorBox("Rom CRC invalid",
"Rom CRC did not match the list of known good roms. Trying the next one...");
"Rom CRC did not match the list of known compatible roms. Trying the next one...\n\n"
"Visit https://ship.equipment/ to validate your ROM and see a list of compatible versions");
}
continue;
}

View File

@ -94,6 +94,7 @@ GameInteractorSail* GameInteractorSail::Instance;
#include <libultraship/libultraship.h>
// Resource Types/Factories
#include "soh/resource/type/SohResourceType.h"
#include "soh/resource/type/Animation.h"
#include "soh/resource/type/AudioSample.h"
#include "soh/resource/type/AudioSequence.h"
@ -321,19 +322,24 @@ OTRGlobals::OTRGlobals() {
SPDLOG_INFO("Starting Ship of Harkinian version {}", (char*)gBuildVersion);
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_Animation), std::make_shared<LUS::AnimationFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_PlayerAnimation), std::make_shared<LUS::PlayerAnimationFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_Room), std::make_shared<LUS::SceneFactory>()); // Is room scene? maybe?
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_CollisionHeader), std::make_shared<LUS::CollisionHeaderFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_Skeleton), std::make_shared<LUS::SkeletonFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_SkeletonLimb), std::make_shared<LUS::SkeletonLimbFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_Path), std::make_shared<LUS::PathFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_Cutscene), std::make_shared<LUS::CutsceneFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_Text), std::make_shared<LUS::TextFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_AudioSample), std::make_shared<LUS::AudioSampleFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_AudioSoundFont), std::make_shared<LUS::AudioSoundFontFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_AudioSequence), std::make_shared<LUS::AudioSequenceFactory>());
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast<uint32_t>(LUS::ResourceType::SOH_Background), std::make_shared<LUS::BackgroundFactory>());
auto loader = context->GetResourceManager()->GetResourceLoader();
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAnimationV0>(), RESOURCE_FORMAT_BINARY, "Animation", static_cast<uint32_t>(SOH::ResourceType::SOH_Animation), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryPlayerAnimationV0>(), RESOURCE_FORMAT_BINARY, "PlayerAnimation", static_cast<uint32_t>(SOH::ResourceType::SOH_PlayerAnimation), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinarySceneV0>(), RESOURCE_FORMAT_BINARY, "Room", static_cast<uint32_t>(SOH::ResourceType::SOH_Room), 0); // Is room scene? maybe?
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryCollisionHeaderV0>(), RESOURCE_FORMAT_BINARY, "CollisionHeader", static_cast<uint32_t>(SOH::ResourceType::SOH_CollisionHeader), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryXMLCollisionHeaderV0>(), RESOURCE_FORMAT_XML, "CollisionHeader", static_cast<uint32_t>(SOH::ResourceType::SOH_CollisionHeader), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinarySkeletonV0>(), RESOURCE_FORMAT_BINARY, "Skeleton", static_cast<uint32_t>(SOH::ResourceType::SOH_Skeleton), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryXMLSkeletonV0>(), RESOURCE_FORMAT_XML, "Skeleton", static_cast<uint32_t>(SOH::ResourceType::SOH_Skeleton), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinarySkeletonLimbV0>(), RESOURCE_FORMAT_BINARY, "SkeletonLimb", static_cast<uint32_t>(SOH::ResourceType::SOH_SkeletonLimb), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryXMLSkeletonLimbV0>(), RESOURCE_FORMAT_XML, "SkeletonLimb", static_cast<uint32_t>(SOH::ResourceType::SOH_SkeletonLimb), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryPathV0>(), RESOURCE_FORMAT_BINARY, "Path", static_cast<uint32_t>(SOH::ResourceType::SOH_Path), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryCutsceneV0>(), RESOURCE_FORMAT_BINARY, "Cutscene", static_cast<uint32_t>(SOH::ResourceType::SOH_Cutscene), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryTextV0>(), RESOURCE_FORMAT_BINARY, "Text", static_cast<uint32_t>(SOH::ResourceType::SOH_Text), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryXMLTextV0>(), RESOURCE_FORMAT_XML, "Text", static_cast<uint32_t>(SOH::ResourceType::SOH_Text), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSampleV2>(), RESOURCE_FORMAT_BINARY, "AudioSample", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSample), 2);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSoundFontV2>(), RESOURCE_FORMAT_BINARY, "AudioSoundFont", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSoundFont), 2);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSequenceV2>(), RESOURCE_FORMAT_BINARY, "AudioSequence", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSequence), 2);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryBackgroundV0>(), RESOURCE_FORMAT_BINARY, "Background", static_cast<uint32_t>(SOH::ResourceType::SOH_Background), 0);
gSaveStateMgr = std::make_shared<SaveStateMgr>();
gRandoContext = Rando::Context::CreateInstance();
@ -540,7 +546,7 @@ extern "C" void VanillaItemTable_Init() {
static GetItemEntry getItemTable[] = {
GET_ITEM(ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBS_5),
GET_ITEM(ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_NUTS_5),
GET_ITEM(ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBCHUS_10),
GET_ITEM(ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_BOMBCHUS_10),
GET_ITEM(ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_BOW),
GET_ITEM(ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_SLINGSHOT),
GET_ITEM(ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_BOOMERANG),
@ -643,8 +649,8 @@ extern "C" void VanillaItemTable_Init() {
GET_ITEM(ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBS_20),
GET_ITEM(ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBS_30),
GET_ITEM(ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_SEEDS_30),
GET_ITEM(ITEM_BOMBCHUS_5, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBCHUS_5),
GET_ITEM(ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBCHUS_20),
GET_ITEM(ITEM_BOMBCHUS_5, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_BOMBCHUS_5),
GET_ITEM(ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_BOMBCHUS_20),
GET_ITEM(ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, GI_FISH),
GET_ITEM(ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BUGS),
GET_ITEM(ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BLUE_FIRE),
@ -1396,7 +1402,7 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
// Actually update the CVar now before runing the alt asset update listeners
CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0));
gfx_texture_cache_clear();
LUS::SkeletonPatcher::UpdateSkeletons();
SOH::SkeletonPatcher::UpdateSkeletons();
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnAssetAltChange>();
}
@ -1625,7 +1631,7 @@ extern "C" uint8_t ResourceMgr_TexIsRaw(const char* texPath) {
extern "C" uint8_t ResourceMgr_ResourceIsBackground(char* texPath) {
auto res = GetResourceByNameHandlingMQ(texPath);
return res->GetInitData()->Type == static_cast<uint32_t>(LUS::ResourceType::SOH_Background);
return res->GetInitData()->Type == static_cast<uint32_t>(SOH::ResourceType::SOH_Background);
}
extern "C" char* ResourceMgr_LoadJPEG(char* data, size_t dataSize)
@ -1701,7 +1707,7 @@ extern "C" uint8_t GetSeedIconIndex(uint8_t index) {
}
extern "C" char* ResourceMgr_LoadPlayerAnimByName(const char* animPath) {
auto anim = std::static_pointer_cast<LUS::PlayerAnimation>(GetResourceByNameHandlingMQ(animPath));
auto anim = std::static_pointer_cast<SOH::PlayerAnimation>(GetResourceByNameHandlingMQ(animPath));
return (char*)&anim->limbRotData[0];
}
@ -1965,7 +1971,7 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel
// Therefore we can take this oppurtunity to take note of the Skeleton that is created...
if (skelAnime != nullptr) {
auto stringPath = std::string(path);
LUS::SkeletonPatcher::RegisterSkeleton(stringPath, skelAnime);
SOH::SkeletonPatcher::RegisterSkeleton(stringPath, skelAnime);
}
return skelHeader;
@ -1973,12 +1979,12 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel
extern "C" void ResourceMgr_UnregisterSkeleton(SkelAnime* skelAnime) {
if (skelAnime != nullptr)
LUS::SkeletonPatcher::UnregisterSkeleton(skelAnime);
SOH::SkeletonPatcher::UnregisterSkeleton(skelAnime);
}
extern "C" void ResourceMgr_ClearSkeletons(SkelAnime* skelAnime) {
if (skelAnime != nullptr)
LUS::SkeletonPatcher::ClearSkeletons();
SOH::SkeletonPatcher::ClearSkeletons();
}
extern "C" s32* ResourceMgr_LoadCSByName(const char* path) {
@ -2630,6 +2636,8 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
} else if (Randomizer_GetSettingValue(RSK_SARIA_HINT) &&
(gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && textId == TEXT_SARIA_SFM) || (textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER)) {
messageEntry = OTRGlobals::Instance->gRandomizer->GetSariaMessage(textId);
} else if (textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100);
} else if (Randomizer_GetSettingValue(RSK_BIGGORON_HINT) && (textId == TEXT_BIGGORON_BETTER_AT_SMITHING || textId == TEXT_BIGGORON_WAITING_FOR_YOU || textId == TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS)) {
messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_BIGGORON_BETTER_AT_SMITHING, RC_DMT_TRADE_CLAIM_CHECK);
} else if (Randomizer_GetSettingValue(RSK_BIG_POES_HINT) && (textId == TEXT_GHOST_SHOP_EXPLAINATION || textId == TEXT_GHOST_SHOP_CARD_HAS_POINTS)) {

View File

@ -41,6 +41,7 @@
#include "Enhancements/game-interactor/GameInteractor.h"
#include "Enhancements/cosmetics/authenticGfxPatches.h"
#include "Enhancements/resolution-editor/ResolutionEditor.h"
#include "Enhancements/debugger/MessageViewer.h"
bool ToggleAltAssetsAtEndOfFrame = false;
bool isBetaQuestEnabled = false;
@ -116,12 +117,15 @@ namespace SohGui {
std::shared_ptr<LUS::GuiWindow> mInputEditorWindow;
std::shared_ptr<AudioEditor> mAudioEditorWindow;
std::shared_ptr<InputViewer> mInputViewer;
std::shared_ptr<InputViewerSettingsWindow> mInputViewerSettings;
std::shared_ptr<CosmeticsEditorWindow> mCosmeticsEditorWindow;
std::shared_ptr<ActorViewerWindow> mActorViewerWindow;
std::shared_ptr<ColViewerWindow> mColViewerWindow;
std::shared_ptr<SaveEditorWindow> mSaveEditorWindow;
std::shared_ptr<DLViewerWindow> mDLViewerWindow;
std::shared_ptr<ValueViewerWindow> mValueViewerWindow;
std::shared_ptr<MessageViewer> mMessageViewerWindow;
std::shared_ptr<GameplayStatsWindow> mGameplayStatsWindow;
std::shared_ptr<CheckTracker::CheckTrackerSettingsWindow> mCheckTrackerSettingsWindow;
std::shared_ptr<CheckTracker::CheckTrackerWindow> mCheckTrackerWindow;
@ -163,6 +167,10 @@ namespace SohGui {
mAudioEditorWindow = std::make_shared<AudioEditor>("gAudioEditor.WindowOpen", "Audio Editor");
gui->AddGuiWindow(mAudioEditorWindow);
mInputViewer = std::make_shared<InputViewer>("gOpenWindows.InputViewer", "Input Viewer");
gui->AddGuiWindow(mInputViewer);
mInputViewerSettings = std::make_shared<InputViewerSettingsWindow>("gOpenWindows.InputViewerSettings", "Input Viewer Settings");
gui->AddGuiWindow(mInputViewerSettings);
mCosmeticsEditorWindow = std::make_shared<CosmeticsEditorWindow>("gCosmeticsEditorEnabled", "Cosmetics Editor");
gui->AddGuiWindow(mCosmeticsEditorWindow);
mActorViewerWindow = std::make_shared<ActorViewerWindow>("gActorViewerEnabled", "Actor Viewer");
@ -175,6 +183,8 @@ namespace SohGui {
gui->AddGuiWindow(mDLViewerWindow);
mValueViewerWindow = std::make_shared<ValueViewerWindow>("gValueViewer.WindowOpen", "Value Viewer");
gui->AddGuiWindow(mValueViewerWindow);
mMessageViewerWindow = std::make_shared<MessageViewer>("gMessageViewerEnabled", "Message Viewer");
gui->AddGuiWindow(mMessageViewerWindow);
mGameplayStatsWindow = std::make_shared<GameplayStatsWindow>("gGameplayStatsEnabled", "Gameplay Stats");
gui->AddGuiWindow(mGameplayStatsWindow);
mCheckTrackerWindow = std::make_shared<CheckTracker::CheckTrackerWindow>("gCheckTrackerEnabled", "Check Tracker");
@ -204,6 +214,7 @@ namespace SohGui {
mGameplayStatsWindow = nullptr;
mDLViewerWindow = nullptr;
mValueViewerWindow = nullptr;
mMessageViewerWindow = nullptr;
mSaveEditorWindow = nullptr;
mColViewerWindow = nullptr;
mActorViewerWindow = nullptr;
@ -213,5 +224,7 @@ namespace SohGui {
mStatsWindow = nullptr;
mConsoleWindow = nullptr;
mSohMenuBar = nullptr;
mInputViewer = nullptr;
mInputViewerSettings = nullptr;
}
}

View File

@ -11,6 +11,7 @@
#include <stdio.h>
#include "SohMenuBar.h"
#include "Enhancements/audio/AudioEditor.h"
#include "Enhancements/controls/InputViewer.h"
#include "Enhancements/cosmetics/CosmeticsEditor.h"
#include "Enhancements/debugger/actorViewer.h"
#include "Enhancements/debugger/colViewer.h"

View File

@ -22,6 +22,7 @@
#include "Enhancements/audio/AudioEditor.h"
#include "Enhancements/controls/InputViewer.h"
#include "Enhancements/cosmetics/CosmeticsEditor.h"
#include "Enhancements/debugger/actorViewer.h"
#include "Enhancements/debugger/colViewer.h"
@ -29,6 +30,7 @@
#include "Enhancements/debugger/dlViewer.h"
#include "Enhancements/debugger/valueViewer.h"
#include "Enhancements/gameplaystatswindow.h"
#include "Enhancements/debugger/MessageViewer.h"
#include "Enhancements/randomizer/randomizer_check_tracker.h"
#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
#include "Enhancements/randomizer/randomizer_item_tracker.h"
@ -104,6 +106,7 @@ static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large
"OHKO"
};
static const char* timeTravelOptions[3] = { "Disabled", "Ocarina of Time", "Any Ocarina" };
static const char* swordToggleModes[3] = { "Disabled", "Child Toggle", "Both Ages (May lead to unintended behaviour)"};
extern "C" SaveContext gSaveContext;
@ -180,6 +183,8 @@ void DrawShipMenu() {
}
extern std::shared_ptr<LUS::GuiWindow> mInputEditorWindow;
extern std::shared_ptr<InputViewer> mInputViewer;
extern std::shared_ptr<InputViewerSettingsWindow> mInputViewerSettings;
extern std::shared_ptr<AdvancedResolutionSettings::AdvancedResolutionSettingsWindow> mAdvancedResolutionSettingsWindow;
void DrawSettingsMenu() {
@ -245,11 +250,25 @@ void DrawSettingsMenu() {
#ifndef __SWITCH__
UIWidgets::EnhancementCheckbox("Menubar Controller Navigation", "gControlNav");
UIWidgets::Tooltip("Allows controller navigation of the SOH menu bar (Settings, Enhancements,...)\nCAUTION: This will disable game inputs while the menubar is visible.\n\nD-pad to move between items, A to select, and X to grab focus on the menu bar");
UIWidgets::PaddedSeparator();
#endif
UIWidgets::PaddedEnhancementCheckbox("Show Inputs", "gInputEnabled", true, false);
UIWidgets::Tooltip("Shows currently pressed inputs on the bottom right of the screen");
UIWidgets::PaddedEnhancementSliderFloat("Input Scale: %.2f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false, true, true, false);
UIWidgets::Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting");
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2 (12.0f, 6.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f));
if (mInputViewer) {
if (ImGui::Button(GetWindowButtonText("Input Viewer", CVarGetInteger("gOpenWindows.InputViewer", 0)).c_str(), ImVec2 (-1.0f, 0.0f))) {
mInputViewer->ToggleVisibility();
}
}
if (mInputViewerSettings) {
if (ImGui::Button(GetWindowButtonText("Input Viewer Settings", CVarGetInteger("gOpenWindows.InputViewerSettings", 0)).c_str(), ImVec2 (-1.0f, 0.0f))) {
mInputViewerSettings->ToggleVisibility();
}
}
ImGui::PopStyleColor(1);
ImGui::PopStyleVar(3);
UIWidgets::PaddedEnhancementSliderInt("Simulated Input Lag: %d frames", "##SimulatedInputLag", "gSimulatedInputLag", 0, 6, "", 0, true, true, false);
UIWidgets::Tooltip("Buffers your inputs to be executed a specified amount of frames later");
@ -631,6 +650,8 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("The default response to Kaepora Gaebora is always that you understood what he said");
UIWidgets::PaddedEnhancementCheckbox("Exit Market at Night", "gMarketSneak", true, false);
UIWidgets::Tooltip("Allows exiting Hyrule Castle Market Town to Hyrule Field at night by speaking to the guard next to the gate.");
UIWidgets::PaddedEnhancementCheckbox("Shops and Games Always Open", "gEnhancements.OpenAllHours", true, false);
UIWidgets::Tooltip("Shops and minigames are open both day and night. Requires scene reload to take effect.");
UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false);
UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name");
UIWidgets::PaddedEnhancementCheckbox("Quit Fishing At Door", "gQuitFishingAtDoor", true, false);
@ -944,9 +965,13 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("Bonking into trees will have a chance to drop up to 3 sticks. Must already have obtained sticks.");
UIWidgets::PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false);
UIWidgets::Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series");
UIWidgets::PaddedEnhancementCheckbox("Hyper Bosses", "gHyperBosses", true, false);
if (UIWidgets::PaddedEnhancementCheckbox("Hyper Bosses", "gHyperBosses", true, false)) {
UpdateHyperBossesState();
}
UIWidgets::Tooltip("All major bosses move and act twice as fast.");
UIWidgets::PaddedEnhancementCheckbox("Hyper Enemies", "gHyperEnemies", true, false);
if (UIWidgets::PaddedEnhancementCheckbox("Hyper Enemies", "gHyperEnemies", true, false)) {
UpdateHyperEnemiesState();
}
UIWidgets::Tooltip("All regular enemies and mini-bosses move and act twice as fast.");
UIWidgets::PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false);
UIWidgets::Tooltip("Always get the heart piece/purple rupee from the spinning Goron pot");
@ -957,6 +982,8 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("All dogs can be traded in and will count as Richard.");
UIWidgets::PaddedEnhancementSliderInt("Cuccos Stay Put Multiplier: %dx", "##CuccoStayDurationMultiplier", "gCuccoStayDurationMultiplier", 1, 5, "", 1, true, true, false);
UIWidgets::Tooltip("Cuccos will stay in place longer after putting them down, by a multiple of the value of the slider.");
UIWidgets::PaddedEnhancementSliderInt("Leever Spawn Rate: %d seconds", "##LeeverSpawnRate", "gEnhancements.LeeverSpawnRate", 0, 10, "", 0, true, true, false);
UIWidgets::Tooltip("The time between leever groups spawning.");
ImGui::EndMenu();
}
@ -973,6 +1000,8 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("Disables the voice audio when Navi calls you");
UIWidgets::PaddedEnhancementCheckbox("Disable Hot/Underwater Warning Text", "gDisableTunicWarningText", true, false);
UIWidgets::Tooltip("Disables warning text when you don't have on the Goron/Zora Tunic in Hot/Underwater conditions.");
UIWidgets::PaddedEnhancementCheckbox("Remember Minimap State Between Areas", "gEnhancements.RememberMapToggleState");
UIWidgets::Tooltip("Preserves the minimap visibility state when going between areas rather than defaulting it to \"on\" when going through loading zones.");
ImGui::EndMenu();
}
@ -985,6 +1014,17 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("Allows equipping the tunic and boots to c-buttons");
UIWidgets::PaddedEnhancementCheckbox("Equipment Toggle", "gEquipmentCanBeRemoved", true, false);
UIWidgets::Tooltip("Allows equipment to be removed by toggling it off on\nthe equipment subscreen.");
if (CVarGetInteger("gEquipmentCanBeRemoved", 0)) {
UIWidgets::PaddedText("Sword Toggle Options", true, false);
UIWidgets::EnhancementCombobox("gEnhancements.SwordToggle", swordToggleModes, SWORD_TOGGLE_NONE);
UIWidgets::Tooltip(
"Introduces Options for unequipping Link's sword\n\n"
"None: Only Biggoron's Sword/Giant's Knife can be toggled. Doing so will equip the Master Sword.\n\n"
"Child Toggle: This will allow for completely unequipping any sword as child link.\n\n"
"Both Ages: Any sword can be unequipped as either age. This may lead to swordless glitches as Adult.\n"
);
}
UIWidgets::PaddedEnhancementCheckbox("Link's Cow in Both Time Periods", "gCowOfTime", true, false);
UIWidgets::Tooltip("Allows the Lon Lon Ranch obstacle course reward to be shared across time periods");
UIWidgets::PaddedEnhancementCheckbox("Enable visible guard vision", "gGuardVision", true, false);
@ -1151,6 +1191,8 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("Space between text characters (useful for HD font textures)");
UIWidgets::PaddedEnhancementCheckbox("More info in file select", "gFileSelectMoreInfo", true, false);
UIWidgets::Tooltip("Shows what items you have collected in the file select screen, like in N64 randomizer");
UIWidgets::PaddedEnhancementCheckbox("Better ammo rendering in pause menu", "gEnhancements.BetterAmmoRendering", true, false);
UIWidgets::Tooltip("Ammo counts in the pause menu will work correctly regardless of the position of items in the inventory");
ImGui::EndMenu();
}
@ -1217,6 +1259,11 @@ void DrawEnhancementsMenu() {
UIWidgets::PaddedEnhancementCheckbox("Fix Darunia dancing too fast", "gEnhancements.FixDaruniaDanceSpeed",
true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true);
UIWidgets::Tooltip("Fixes Darunia's dancing speed so he dances to the beat of Saria's Song, like in vanilla.");
UIWidgets::PaddedEnhancementCheckbox("Fix raised Floor Switches", "gEnhancements.FixFloorSwitches", true, false);
UIWidgets::Tooltip("Fixes the two raised floor switches, the one in Forest Temple Basement and the one at the top of Fire Temple. \n"
"This will lower them, making activating them easier");
UIWidgets::PaddedEnhancementCheckbox("Fix Zora hint dialogue", "gFixZoraHintDialogue", true, false);
UIWidgets::Tooltip("Fixes one Zora's dialogue giving a hint about bringing Ruto's Letter to King Zora to properly occur before moving King Zora rather than after");
ImGui::EndMenu();
}
@ -1508,6 +1555,8 @@ void DrawCheatsMenu() {
UIWidgets::Tooltip("This syncs the ingame time with the real world time");
UIWidgets::PaddedEnhancementCheckbox("No ReDead/Gibdo Freeze", "gNoRedeadFreeze", true, false);
UIWidgets::Tooltip("Prevents ReDeads and Gibdos from being able to freeze you with their scream");
UIWidgets::PaddedEnhancementCheckbox("Keese/Guay don't target you", "gNoKeeseGuayTarget", true, false);
UIWidgets::Tooltip("Keese and Guay no longer target you and simply ignore you as if you were wearing the skull mask");
{
static int32_t betaQuestEnabled = CVarGetInteger("gEnableBetaQuest", 0);
static int32_t lastBetaQuestEnabled = betaQuestEnabled;
@ -1584,6 +1633,7 @@ extern std::shared_ptr<ColViewerWindow> mColViewerWindow;
extern std::shared_ptr<ActorViewerWindow> mActorViewerWindow;
extern std::shared_ptr<DLViewerWindow> mDLViewerWindow;
extern std::shared_ptr<ValueViewerWindow> mValueViewerWindow;
extern std::shared_ptr<MessageViewer> mMessageViewerWindow;
void DrawDeveloperToolsMenu() {
if (ImGui::BeginMenu("Developer Tools")) {
@ -1683,6 +1733,12 @@ void DrawDeveloperToolsMenu() {
mValueViewerWindow->ToggleVisibility();
}
}
UIWidgets::Spacer(0);
if (mMessageViewerWindow) {
if (ImGui::Button(GetWindowButtonText("Message Viewer", CVarGetInteger("gMessageViewerEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) {
mMessageViewerWindow->ToggleVisibility();
}
}
ImGui::PopStyleVar(3);
ImGui::PopStyleColor(1);
@ -1997,4 +2053,4 @@ void SohMenuBar::DrawElement() {
ImGui::EndMenuBar();
}
}
} // namespace SohGui
} // namespace SohGui

View File

@ -449,7 +449,7 @@ namespace UIWidgets {
if (changed && !(abs(oldVal - val) < 0.000001f)) {
std::stringstream ss;
ss << std::setprecision(ticks + 1) << val;
ss << std::setprecision(ticks + 1) << std::setiosflags(std::ios_base::fixed) << val;
val = std::stof(ss.str());
CVarSetFloat(cvarName, val);
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();

View File

@ -2,32 +2,14 @@
#include "soh/resource/type/Animation.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
AnimationFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Animation>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<AnimationFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Animation with version {}", resource->GetInitData()->ResourceVersion);
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryAnimationV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::AnimationFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<Animation> animation = std::static_pointer_cast<Animation>(resource);
ResourceVersionFactory::ParseFileBinary(reader, animation);
auto animation = std::make_shared<Animation>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
AnimationType animType = (AnimationType)reader->ReadUInt32();
animation->type = animType;
@ -100,5 +82,7 @@ void LUS::AnimationFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> read
} else if (animType == AnimationType::Legacy) {
SPDLOG_DEBUG("BEYTAH ANIMATION?!");
}
return animation;
}
} // namespace LUS
} // namespace SOH

View File

@ -1,17 +1,11 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
namespace LUS {
class AnimationFactory : public ResourceFactory {
namespace SOH {
class ResourceFactoryBinaryAnimationV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class AnimationFactoryV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,33 +2,14 @@
#include "soh/resource/type/AudioSample.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
AudioSampleFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<AudioSample>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 2:
factory = std::make_shared<AudioSampleFactoryV0>();
break;
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryAudioSampleV2::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load AudioSample with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::AudioSampleFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<AudioSample> audioSample = std::static_pointer_cast<AudioSample>(resource);
ResourceVersionFactory::ParseFileBinary(reader, audioSample);
auto audioSample = std::make_shared<AudioSample>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
audioSample->sample.codec = reader->ReadUByte();
audioSample->sample.medium = reader->ReadUByte();
@ -65,9 +46,10 @@ void LUS::AudioSampleFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> re
}
audioSample->book.book = audioSample->bookData.data();
audioSample->sample.book = &audioSample->book;
}
} // namespace LUS
return audioSample;
}
} // namespace SOH
/*
in ResourceMgr_LoadAudioSample we used to have

View File

@ -1,19 +1,11 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
namespace LUS {
class AudioSampleFactory : public ResourceFactory
{
namespace SOH {
class ResourceFactoryBinaryAudioSampleV2 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class AudioSampleFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,33 +2,14 @@
#include "soh/resource/type/AudioSequence.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
AudioSequenceFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<AudioSequence>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 2:
factory = std::make_shared<AudioSequenceFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load AudioSequence with version {}", resource->GetInitData()->ResourceVersion);
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::AudioSequenceFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<AudioSequence> audioSequence = std::static_pointer_cast<AudioSequence>(resource);
ResourceVersionFactory::ParseFileBinary(reader, audioSequence);
auto audioSequence = std::make_shared<AudioSequence>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
audioSequence->sequence.seqDataSize = reader->ReadInt32();
audioSequence->sequenceData.reserve(audioSequence->sequence.seqDataSize);
@ -48,5 +29,7 @@ void LUS::AudioSequenceFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader>
for (uint32_t i = 0; i < audioSequence->sequence.numFonts; i++) {
audioSequence->sequence.fonts[i] = reader->ReadUByte();
}
return audioSequence;
}
} // namespace LUS
} // namespace SOH

View File

@ -1,19 +1,11 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
namespace LUS {
class AudioSequenceFactory : public ResourceFactory
{
namespace SOH {
class ResourceFactoryBinaryAudioSequenceV2 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class AudioSequenceFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -3,33 +3,14 @@
#include "spdlog/spdlog.h"
#include "libultraship/libultraship.h"
namespace LUS {
std::shared_ptr<IResource>
AudioSoundFontFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<AudioSoundFont>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 2:
factory = std::make_shared<AudioSoundFontFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load AudioSoundFont with version {}", resource->GetInitData()->ResourceVersion);
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryAudioSoundFontV2::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::AudioSoundFontFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<AudioSoundFont> audioSoundFont = std::static_pointer_cast<AudioSoundFont>(resource);
ResourceVersionFactory::ParseFileBinary(reader, audioSoundFont);
auto audioSoundFont = std::make_shared<AudioSoundFont>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
audioSoundFont->soundFont.fntIndex = reader->ReadInt32();
audioSoundFont->medium = reader->ReadInt8();
@ -186,5 +167,7 @@ void LUS::AudioSoundFontFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader>
audioSoundFont->soundEffects.push_back(soundEffect);
}
audioSoundFont->soundFont.soundEffects = audioSoundFont->soundEffects.data();
return audioSoundFont;
}
} // namespace LUS
} // namespace SOH

View File

@ -1,19 +1,11 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
namespace LUS {
class AudioSoundFontFactory : public ResourceFactory
{
namespace SOH {
class ResourceFactoryBinaryAudioSoundFontV2 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class AudioSoundFontFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,31 +2,14 @@
#include "soh/resource/type/Background.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
BackgroundFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Background>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<BackgroundFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Background with version {}", resource->GetInitData()->ResourceVersion);
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryBackgroundV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void BackgroundFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<Background> background = std::static_pointer_cast<Background>(resource);
ResourceVersionFactory::ParseFileBinary(reader, background);
auto background = std::make_shared<Background>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
uint32_t dataSize = reader->ReadUInt32();
@ -35,5 +18,7 @@ void BackgroundFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
for (uint32_t i = 0; i < dataSize; i++) {
background->Data.push_back(reader->ReadUByte());
}
return background;
}
} // namespace LUS
} // namespace SOH

View File

@ -1,17 +1,11 @@
#pragma once
#include "resource/Resource.h"
#include "resource/ResourceFactory.h"
#include "resource/ResourceFactoryBinary.h"
namespace LUS {
class BackgroundFactory : public ResourceFactory {
namespace SOH {
class ResourceFactoryBinaryBackgroundV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class BackgroundFactoryV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,54 +2,14 @@
#include "soh/resource/type/CollisionHeader.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
CollisionHeaderFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<CollisionHeader>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<CollisionHeaderFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Collision Header with version {}", resource->GetInitData()->ResourceVersion);
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryCollisionHeaderV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
std::shared_ptr<IResource>
CollisionHeaderFactory::ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) {
auto resource = std::make_shared<CollisionHeader>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<CollisionHeaderFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Collision Header with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileXML(reader, resource);
return resource;
}
void LUS::CollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<CollisionHeader> collisionHeader = std::static_pointer_cast<CollisionHeader>(resource);
ResourceVersionFactory::ParseFileBinary(reader, collisionHeader);
auto collisionHeader = std::make_shared<CollisionHeader>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
collisionHeader->collisionHeaderData.minBounds.x = reader->ReadInt16();
collisionHeader->collisionHeaderData.minBounds.y = reader->ReadInt16();
@ -159,10 +119,19 @@ void LUS::CollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader
collisionHeader->waterBoxes.push_back(waterBox);
}
collisionHeader->collisionHeaderData.waterBoxes = collisionHeader->waterBoxes.data();
return collisionHeader;
}
void LUS::CollisionHeaderFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<CollisionHeader> collisionHeader = std::static_pointer_cast<CollisionHeader>(resource);
std::shared_ptr<LUS::IResource> ResourceFactoryXMLCollisionHeaderV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
auto collisionHeader = std::make_shared<CollisionHeader>(file->InitData);
auto reader = std::get<std::shared_ptr<tinyxml2::XMLDocument>>(file->Reader)->FirstChildElement();
auto child = reader->FirstChildElement();
collisionHeader->collisionHeaderData.minBounds.x = reader->IntAttribute("MinBoundsX");
collisionHeader->collisionHeaderData.minBounds.y = reader->IntAttribute("MinBoundsY");
@ -178,8 +147,6 @@ void LUS::CollisionHeaderFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, s
zero.z = 0;
collisionHeader->camPosDataZero = zero;
auto child = reader->FirstChildElement();
while (child != nullptr) {
std::string childName = child->Name();
if (childName == "Vertex") {
@ -274,5 +241,7 @@ void LUS::CollisionHeaderFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, s
collisionHeader->collisionHeaderData.cameraDataList = collisionHeader->camData.data();
collisionHeader->collisionHeaderData.cameraDataListLen = collisionHeader->camDataCount;
collisionHeader->collisionHeaderData.waterBoxes = collisionHeader->waterBoxes.data();
return collisionHeader;
}
}
} // namespace SOH

View File

@ -1,20 +1,17 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
#include "ResourceFactoryXML.h"
namespace LUS {
class CollisionHeaderFactory : public ResourceFactory {
namespace SOH {
class ResourceFactoryBinaryCollisionHeaderV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<IResource>
ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class CollisionHeaderFactoryV0 : public ResourceVersionFactory {
class ResourceFactoryXMLCollisionHeaderV0 : public LUS::ResourceFactoryXML {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,36 +2,14 @@
#include "soh/resource/type/Cutscene.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
CutsceneFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Cutscene>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<CutsceneFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Cutscene with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
static inline uint32_t read_CMD_BBBB(std::shared_ptr<BinaryReader> reader) {
static inline uint32_t read_CMD_BBBB(std::shared_ptr<LUS::BinaryReader> reader) {
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
return v;
}
static inline uint32_t read_CMD_BBH(std::shared_ptr<BinaryReader> reader) {
static inline uint32_t read_CMD_BBH(std::shared_ptr<LUS::BinaryReader> reader) {
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
@ -46,7 +24,7 @@ static inline uint32_t read_CMD_BBH(std::shared_ptr<BinaryReader> reader) {
return v;
}
static inline uint32_t read_CMD_HBB(std::shared_ptr<BinaryReader> reader) {
static inline uint32_t read_CMD_HBB(std::shared_ptr<LUS::BinaryReader> reader) {
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
@ -61,7 +39,7 @@ static inline uint32_t read_CMD_HBB(std::shared_ptr<BinaryReader> reader) {
return v;
}
static inline uint32_t read_CMD_HH(std::shared_ptr<BinaryReader> reader) {
static inline uint32_t read_CMD_HH(std::shared_ptr<LUS::BinaryReader> reader) {
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
@ -79,11 +57,14 @@ static inline uint32_t read_CMD_HH(std::shared_ptr<BinaryReader> reader) {
return v;
}
void LUS::CutsceneFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<Cutscene> cutscene = std::static_pointer_cast<Cutscene>(resource);
ResourceVersionFactory::ParseFileBinary(reader, cutscene);
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryCutsceneV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
auto cutscene = std::make_shared<Cutscene>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
uint32_t numEntries = reader->ReadUInt32();
cutscene->commands.reserve(numEntries);
@ -459,7 +440,7 @@ void LUS::CutsceneFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reade
case 0xFFFFFFFF: // CS_END
{
cutscene->commands.push_back(reader->ReadUInt32());
return;
return cutscene;
}
default:
SPDLOG_TRACE("CutsceneV0: Unknown command {}\n", commandId);
@ -467,5 +448,7 @@ void LUS::CutsceneFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reade
break;
}
}
return cutscene;
}
} // namespace LUS
} // namespace SOH

View File

@ -1,19 +1,11 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
namespace LUS {
class CutsceneFactory : public ResourceFactory
{
namespace SOH {
class ResourceFactoryBinaryCutsceneV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class CutsceneFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,32 +2,14 @@
#include "soh/resource/type/Path.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
PathFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Path>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<PathFactoryV0>();
break;
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryPathV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Path with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::PathFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<Path> path = std::static_pointer_cast<Path>(resource);
ResourceVersionFactory::ParseFileBinary(reader, path);
auto path = std::make_shared<Path>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
path->numPaths = reader->ReadUInt32();
path->paths.reserve(path->numPaths);
@ -52,5 +34,7 @@ void LUS::PathFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
path->pathData.push_back(pathDataEntry);
}
return path;
}
} // namespace LUS
} // namespace SOH

View File

@ -1,19 +1,11 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
namespace LUS {
class PathFactory : public ResourceFactory
{
namespace SOH {
class ResourceFactoryBinaryPathV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class PathFactoryV0 : public ResourceVersionFactory
{
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,34 +2,14 @@
#include "soh/resource/type/PlayerAnimation.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
PlayerAnimationFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<PlayerAnimation>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<PlayerAnimationFactoryV0>();
break;
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryPlayerAnimationV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load PlayerAnimation with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::PlayerAnimationFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<PlayerAnimation> playerAnimation = std::static_pointer_cast<PlayerAnimation>(resource);
ResourceVersionFactory::ParseFileBinary(reader, playerAnimation);
auto playerAnimation = std::make_shared<PlayerAnimation>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
uint32_t numEntries = reader->ReadUInt32();
playerAnimation->limbRotData.reserve(numEntries);
@ -37,5 +17,7 @@ void LUS::PlayerAnimationFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader
for (uint32_t i = 0; i < numEntries; i++) {
playerAnimation->limbRotData.push_back(reader->ReadInt16());
}
}
} // namespace LUS
return playerAnimation;
};
} // namespace SOH

View File

@ -1,17 +1,11 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
namespace LUS {
class PlayerAnimationFactory : public ResourceFactory {
namespace SOH {
class ResourceFactoryBinaryPlayerAnimationV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class PlayerAnimationFactoryV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -1,4 +1,5 @@
#include "spdlog/spdlog.h"
#include "soh/resource/type/SohResourceType.h"
#include "soh/resource/importer/SceneFactory.h"
#include "soh/resource/type/Scene.h"
#include "soh/resource/type/scenecommand/SceneCommand.h"
@ -28,67 +29,36 @@
#include "soh/resource/importer/scenecommand/SetLightListFactory.h"
#include "soh/resource/importer/scenecommand/SetMeshFactory.h"
namespace LUS {
std::shared_ptr<IResource>
SceneFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
if (SceneFactory::sceneCommandFactories.empty()) {
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetLightingSettings] = std::make_shared<SetLightingSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetWind] = std::make_shared<SetWindSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetExitList] = std::make_shared<SetExitListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetTimeSettings] = std::make_shared<SetTimeSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSkyboxModifier] = std::make_shared<SetSkyboxModifierFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetEchoSettings] = std::make_shared<SetEchoSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSoundSettings] = std::make_shared<SetSoundSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSkyboxSettings] = std::make_shared<SetSkyboxSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetRoomBehavior] = std::make_shared<SetRoomBehaviorFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCsCamera] = std::make_shared<SetCsCameraFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCameraSettings] = std::make_shared<SetCameraSettingsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetRoomList] = std::make_shared<SetRoomListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCollisionHeader] = std::make_shared<SetCollisionHeaderFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetEntranceList] = std::make_shared<SetEntranceListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSpecialObjects] = std::make_shared<SetSpecialObjectsFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetObjectList] = std::make_shared<SetObjectListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetStartPositionList] = std::make_shared<SetStartPositionListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetActorList] = std::make_shared<SetActorListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetTransitionActorList] = std::make_shared<SetTransitionActorListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::EndMarker] = std::make_shared<EndMarkerFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetAlternateHeaders] = std::make_shared<SetAlternateHeadersFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetPathways] = std::make_shared<SetPathwaysFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCutscenes] = std::make_shared<SetCutscenesFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetLightList] = std::make_shared<SetLightListFactory>();
SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetMesh] = std::make_shared<SetMeshFactory>();
}
auto resource = std::make_shared<Scene>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SceneFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Scene with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
namespace SOH {
ResourceFactoryBinarySceneV0::ResourceFactoryBinarySceneV0() {
sceneCommandFactories[SceneCommandID::SetLightingSettings] = std::make_shared<SetLightingSettingsFactory>();
sceneCommandFactories[SceneCommandID::SetWind] = std::make_shared<SetWindSettingsFactory>();
sceneCommandFactories[SceneCommandID::SetExitList] = std::make_shared<SetExitListFactory>();
sceneCommandFactories[SceneCommandID::SetTimeSettings] = std::make_shared<SetTimeSettingsFactory>();
sceneCommandFactories[SceneCommandID::SetSkyboxModifier] = std::make_shared<SetSkyboxModifierFactory>();
sceneCommandFactories[SceneCommandID::SetEchoSettings] = std::make_shared<SetEchoSettingsFactory>();
sceneCommandFactories[SceneCommandID::SetSoundSettings] = std::make_shared<SetSoundSettingsFactory>();
sceneCommandFactories[SceneCommandID::SetSkyboxSettings] = std::make_shared<SetSkyboxSettingsFactory>();
sceneCommandFactories[SceneCommandID::SetRoomBehavior] = std::make_shared<SetRoomBehaviorFactory>();
sceneCommandFactories[SceneCommandID::SetCsCamera] = std::make_shared<SetCsCameraFactory>();
sceneCommandFactories[SceneCommandID::SetCameraSettings] = std::make_shared<SetCameraSettingsFactory>();
sceneCommandFactories[SceneCommandID::SetRoomList] = std::make_shared<SetRoomListFactory>();
sceneCommandFactories[SceneCommandID::SetCollisionHeader] = std::make_shared<SetCollisionHeaderFactory>();
sceneCommandFactories[SceneCommandID::SetEntranceList] = std::make_shared<SetEntranceListFactory>();
sceneCommandFactories[SceneCommandID::SetSpecialObjects] = std::make_shared<SetSpecialObjectsFactory>();
sceneCommandFactories[SceneCommandID::SetObjectList] = std::make_shared<SetObjectListFactory>();
sceneCommandFactories[SceneCommandID::SetStartPositionList] = std::make_shared<SetStartPositionListFactory>();
sceneCommandFactories[SceneCommandID::SetActorList] = std::make_shared<SetActorListFactory>();
sceneCommandFactories[SceneCommandID::SetTransitionActorList] = std::make_shared<SetTransitionActorListFactory>();
sceneCommandFactories[SceneCommandID::EndMarker] = std::make_shared<EndMarkerFactory>();
sceneCommandFactories[SceneCommandID::SetAlternateHeaders] = std::make_shared<SetAlternateHeadersFactory>();
sceneCommandFactories[SceneCommandID::SetPathways] = std::make_shared<SetPathwaysFactory>();
sceneCommandFactories[SceneCommandID::SetCutscenes] = std::make_shared<SetCutscenesFactory>();
sceneCommandFactories[SceneCommandID::SetLightList] = std::make_shared<SetLightListFactory>();
sceneCommandFactories[SceneCommandID::SetMesh] = std::make_shared<SetMeshFactory>();
}
void SceneFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<Scene> scene = std::static_pointer_cast<Scene>(resource);
ResourceVersionFactory::ParseFileBinary(reader, scene);
ParseSceneCommands(scene, reader);
}
void SceneFactoryV0::ParseSceneCommands(std::shared_ptr<Scene> scene, std::shared_ptr<BinaryReader> reader) {
void ResourceFactoryBinarySceneV0::ParseSceneCommands(std::shared_ptr<Scene> scene, std::shared_ptr<LUS::BinaryReader> reader) {
uint32_t commandCount = reader->ReadUInt32();
scene->commands.reserve(commandCount);
@ -97,19 +67,19 @@ void SceneFactoryV0::ParseSceneCommands(std::shared_ptr<Scene> scene, std::share
}
}
std::shared_ptr<ISceneCommand> SceneFactoryV0::ParseSceneCommand(std::shared_ptr<Scene> scene,
std::shared_ptr<BinaryReader> reader, uint32_t index) {
std::shared_ptr<ISceneCommand> ResourceFactoryBinarySceneV0::ParseSceneCommand(std::shared_ptr<Scene> scene,
std::shared_ptr<LUS::BinaryReader> reader, uint32_t index) {
SceneCommandID cmdID = (SceneCommandID)reader->ReadInt32();
reader->Seek(-sizeof(int32_t), SeekOffsetType::Current);
reader->Seek(-sizeof(int32_t), LUS::SeekOffsetType::Current);
std::shared_ptr<ISceneCommand> result = nullptr;
std::shared_ptr<SceneCommandFactory> commandFactory = SceneFactory::sceneCommandFactories[cmdID];
auto commandFactory = ResourceFactoryBinarySceneV0::sceneCommandFactories[cmdID];
if (commandFactory != nullptr) {
auto initData = std::make_shared<ResourceInitData>();
auto initData = std::make_shared<LUS::ResourceInitData>();
initData->Id = scene->GetInitData()->Id;
initData->Type = static_cast<uint32_t>(ResourceType::SOH_SceneCommand);
initData->Type = static_cast<uint32_t>(SOH::ResourceType::SOH_SceneCommand);
initData->Path = scene->GetInitData()->Path + "/SceneCommand" + std::to_string(index);
initData->ResourceVersion = scene->GetInitData()->ResourceVersion;
result = std::static_pointer_cast<ISceneCommand>(commandFactory->ReadResource(initData, reader));
@ -123,4 +93,16 @@ std::shared_ptr<ISceneCommand> SceneFactoryV0::ParseSceneCommand(std::shared_ptr
return result;
}
} // namespace LUS
std::shared_ptr<LUS::IResource> ResourceFactoryBinarySceneV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
auto scene = std::make_shared<Scene>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
ParseSceneCommands(scene, reader);
return scene;
};
} // namespace SOH

View File

@ -4,26 +4,22 @@
#include "soh/resource/type/scenecommand/SceneCommand.h"
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
namespace LUS {
class SceneFactory : public ResourceFactory {
namespace SOH {
class ResourceFactoryBinarySceneV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
ResourceFactoryBinarySceneV0();
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
void ParseSceneCommands(std::shared_ptr<Scene> scene, std::shared_ptr<LUS::BinaryReader> reader);
// Doing something very similar to what we do on the ResourceLoader.
// Eventually, scene commands should be moved up to the ResourceLoader as well.
// They can not right now because the exporter does not give them a proper resource type enum value,
// and the exporter does not export the commands with a proper OTR header.
static inline std::unordered_map<SceneCommandID, std::shared_ptr<SceneCommandFactory>> sceneCommandFactories;
};
class SceneFactoryV0 : public ResourceVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseSceneCommands(std::shared_ptr<Scene> scene, std::shared_ptr<BinaryReader> reader);
static inline std::unordered_map<SceneCommandID, std::shared_ptr<SceneCommandFactoryBinaryV0>> sceneCommandFactories;
protected:
std::shared_ptr<ISceneCommand> ParseSceneCommand(std::shared_ptr<Scene> scene, std::shared_ptr<BinaryReader> reader, uint32_t index);
std::shared_ptr<ISceneCommand> ParseSceneCommand(std::shared_ptr<Scene> scene, std::shared_ptr<LUS::BinaryReader> reader, uint32_t index);
};
}; // namespace LUS
} // namespace SOH

View File

@ -3,54 +3,14 @@
#include <spdlog/spdlog.h>
#include <libultraship/libultraship.h>
namespace LUS {
std::shared_ptr<IResource>
SkeletonFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Skeleton>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SkeletonFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Skeleton with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
std::shared_ptr<IResource>
SkeletonFactory::ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) {
auto resource = std::make_shared<Skeleton>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SkeletonFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Skeleton with version {}", resource->GetInitData()->ResourceVersion);
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinarySkeletonV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
factory->ParseFileXML(reader, resource);
return resource;
}
void SkeletonFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<Skeleton> skeleton = std::static_pointer_cast<Skeleton>(resource);
ResourceVersionFactory::ParseFileBinary(reader, skeleton);
auto skeleton = std::make_shared<Skeleton>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
skeleton->type = (SkeletonType)reader->ReadInt8();
skeleton->limbType = (LimbType)reader->ReadInt8();
@ -66,17 +26,17 @@ void SkeletonFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
skeleton->limbTable.push_back(limbPath);
}
if (skeleton->type == LUS::SkeletonType::Curve) {
if (skeleton->type == SkeletonType::Curve) {
skeleton->skeletonData.skelCurveLimbList.limbCount = skeleton->limbCount;
skeleton->curveLimbArray.reserve(skeleton->skeletonData.skelCurveLimbList.limbCount);
} else if (skeleton->type == LUS::SkeletonType::Flex) {
} else if (skeleton->type == SkeletonType::Flex) {
skeleton->skeletonData.flexSkeletonHeader.dListCount = skeleton->dListCount;
}
if (skeleton->type == LUS::SkeletonType::Normal) {
if (skeleton->type == SkeletonType::Normal) {
skeleton->skeletonData.skeletonHeader.limbCount = skeleton->limbCount;
skeleton->standardLimbArray.reserve(skeleton->skeletonData.skeletonHeader.limbCount);
} else if (skeleton->type == LUS::SkeletonType::Flex) {
} else if (skeleton->type == SkeletonType::Flex) {
skeleton->skeletonData.flexSkeletonHeader.sh.limbCount = skeleton->limbCount;
skeleton->standardLimbArray.reserve(skeleton->skeletonData.flexSkeletonHeader.sh.limbCount);
}
@ -87,21 +47,29 @@ void SkeletonFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
skeleton->skeletonHeaderSegments.push_back(limb ? limb->GetRawPointer() : nullptr);
}
if (skeleton->type == LUS::SkeletonType::Normal) {
if (skeleton->type == SkeletonType::Normal) {
skeleton->skeletonData.skeletonHeader.segment = (void**)skeleton->skeletonHeaderSegments.data();
} else if (skeleton->type == LUS::SkeletonType::Flex) {
} else if (skeleton->type == SkeletonType::Flex) {
skeleton->skeletonData.flexSkeletonHeader.sh.segment = (void**)skeleton->skeletonHeaderSegments.data();
} else if (skeleton->type == LUS::SkeletonType::Curve) {
} else if (skeleton->type == SkeletonType::Curve) {
skeleton->skeletonData.skelCurveLimbList.limbs = (SkelCurveLimb**)skeleton->skeletonHeaderSegments.data();
} else {
SPDLOG_ERROR("unknown skeleton type {}", (uint32_t)skeleton->type);
}
skeleton->skeletonData.skeletonHeader.skeletonType = (uint8_t)skeleton->type;
return skeleton;
}
void SkeletonFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource)
{
std::shared_ptr<Skeleton> skel = std::static_pointer_cast<Skeleton>(resource);
std::shared_ptr<LUS::IResource> ResourceFactoryXMLSkeletonV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
auto skel = std::make_shared<Skeleton>(file->InitData);
auto reader = std::get<std::shared_ptr<tinyxml2::XMLDocument>>(file->Reader)->FirstChildElement();
auto child = reader->FirstChildElement();
skel->type = SkeletonType::Flex; // Default to Flex for legacy reasons
if (reader->FindAttribute("Type")) {
@ -137,8 +105,6 @@ void SkeletonFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_p
skel->limbCount = reader->IntAttribute("LimbCount");
skel->dListCount = reader->IntAttribute("DisplayListCount");
auto child = reader->FirstChildElement();
while (child != nullptr) {
std::string childName = child->Name();
@ -157,6 +123,7 @@ void SkeletonFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_p
skel->skeletonData.flexSkeletonHeader.sh.segment = (void**)skel->skeletonHeaderSegments.data();
skel->skeletonData.flexSkeletonHeader.dListCount = skel->dListCount;
skel->skeletonData.skeletonHeader.skeletonType = (uint8_t)skel->type;
}
} // namespace LUS
return skel;
}
} // namespace SOH

View File

@ -1,23 +1,17 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
#include "ResourceFactoryXML.h"
namespace LUS {
class SkeletonFactory : public ResourceFactory
{
namespace SOH {
class ResourceFactoryBinarySkeletonV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<IResource>
ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class SkeletonFactoryV0 : public ResourceVersionFactory
{
class ResourceFactoryXMLSkeletonV0 : public LUS::ResourceFactoryXML {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -3,54 +3,14 @@
#include "spdlog/spdlog.h"
#include "libultraship/libultraship.h"
namespace LUS {
std::shared_ptr<IResource>
SkeletonLimbFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SkeletonLimb>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SkeletonLimbFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Skeleton Limb with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
std::shared_ptr<IResource>
SkeletonLimbFactory::ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) {
auto resource = std::make_shared<SkeletonLimb>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SkeletonLimbFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Skeleton Limb with version {}", resource->GetInitData()->ResourceVersion);
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinarySkeletonLimbV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
factory->ParseFileXML(reader, resource);
return resource;
}
void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SkeletonLimb> skeletonLimb = std::static_pointer_cast<SkeletonLimb>(resource);
ResourceVersionFactory::ParseFileBinary(reader, skeletonLimb);
auto skeletonLimb = std::make_shared<SkeletonLimb>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
skeletonLimb->limbType = (LimbType)reader->ReadInt8();
skeletonLimb->skinSegmentType = (ZLimbSkinType)reader->ReadInt8();
@ -124,7 +84,7 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> r
skeletonLimb->childIndex = reader->ReadUByte();
skeletonLimb->siblingIndex = reader->ReadUByte();
if (skeletonLimb->limbType == LUS::LimbType::LOD) {
if (skeletonLimb->limbType == LimbType::LOD) {
skeletonLimb->limbData.lodLimb.jointPos.x = skeletonLimb->transX;
skeletonLimb->limbData.lodLimb.jointPos.y = skeletonLimb->transY;
skeletonLimb->limbData.lodLimb.jointPos.z = skeletonLimb->transZ;
@ -144,7 +104,7 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> r
} else {
skeletonLimb->limbData.lodLimb.dLists[1] = nullptr;
}
} else if (skeletonLimb->limbType == LUS::LimbType::Standard) {
} else if (skeletonLimb->limbType == LimbType::Standard) {
skeletonLimb->limbData.standardLimb.jointPos.x = skeletonLimb->transX;
skeletonLimb->limbData.standardLimb.jointPos.y = skeletonLimb->transY;
skeletonLimb->limbData.standardLimb.jointPos.z = skeletonLimb->transZ;
@ -156,7 +116,7 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> r
skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr;
skeletonLimb->limbData.standardLimb.dList = (Gfx*)skeletonLimb->dListPtr.c_str();
}
} else if (skeletonLimb->limbType == LUS::LimbType::Curve) {
} else if (skeletonLimb->limbType == LimbType::Curve) {
skeletonLimb->limbData.skelCurveLimb.firstChildIdx = skeletonLimb->childIndex;
skeletonLimb->limbData.skelCurveLimb.nextLimbIdx = skeletonLimb->siblingIndex;
skeletonLimb->limbData.skelCurveLimb.dList[0] = nullptr;
@ -171,31 +131,31 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> r
skeletonLimb->dList2Ptr = "__OTR__" + skeletonLimb->dList2Ptr;
skeletonLimb->limbData.skelCurveLimb.dList[1] = (Gfx*)skeletonLimb->dList2Ptr.c_str();
}
} else if (skeletonLimb->limbType == LUS::LimbType::Skin) {
} else if (skeletonLimb->limbType == LimbType::Skin) {
skeletonLimb->limbData.skinLimb.jointPos.x = skeletonLimb->transX;
skeletonLimb->limbData.skinLimb.jointPos.y = skeletonLimb->transY;
skeletonLimb->limbData.skinLimb.jointPos.z = skeletonLimb->transZ;
skeletonLimb->limbData.skinLimb.child = skeletonLimb->childIndex;
skeletonLimb->limbData.skinLimb.sibling = skeletonLimb->siblingIndex;
if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_DList) {
if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_DList) {
skeletonLimb->limbData.skinLimb.segmentType = static_cast<int32_t>(skeletonLimb->skinSegmentType);
} else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_4) {
} else if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_4) {
skeletonLimb->limbData.skinLimb.segmentType = 4;
} else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_5) {
} else if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_5) {
skeletonLimb->limbData.skinLimb.segmentType = 5;
} else {
skeletonLimb->limbData.skinLimb.segmentType = 0;
}
if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_DList) {
if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_DList) {
if (skeletonLimb->skinDList != "") {
skeletonLimb->skinDList = "__OTR__" + skeletonLimb->skinDList;
skeletonLimb->limbData.skinLimb.segment = (Gfx*)skeletonLimb->skinDList.c_str();
} else {
skeletonLimb->limbData.skinLimb.segment = nullptr;
}
} else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_4) {
} else if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_4) {
skeletonLimb->skinAnimLimbData.totalVtxCount = skeletonLimb->skinVtxCnt;
skeletonLimb->skinAnimLimbData.limbModifCount = skeletonLimb->skinLimbModifCount;
skeletonLimb->skinAnimLimbData.limbModifications = skeletonLimb->skinLimbModifArray.data();
@ -220,10 +180,17 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> r
skeletonLimb->limbData.skinLimb.segment = &skeletonLimb->skinAnimLimbData;
}
}
return skeletonLimb;
}
void SkeletonLimbFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource)
{
std::shared_ptr<SkeletonLimb> skelLimb = std::static_pointer_cast<SkeletonLimb>(resource);
std::shared_ptr<LUS::IResource> ResourceFactoryXMLSkeletonLimbV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
auto skelLimb = std::make_shared<SkeletonLimb>(file->InitData);
auto reader = std::get<std::shared_ptr<tinyxml2::XMLDocument>>(file->Reader)->FirstChildElement();
std::string limbType = reader->Attribute("Type");
@ -275,6 +242,7 @@ void SkeletonLimbFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shar
limbData.lodLimb.sibling = skelLimb->siblingIndex;
// skelLimb->dList2Ptr = reader->Attribute("DisplayList2");
}
} // namespace LUS
return skelLimb;
}
} // namespace SOH

View File

@ -1,23 +1,17 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
#include "ResourceFactoryXML.h"
namespace LUS {
class SkeletonLimbFactory : public ResourceFactory
{
namespace SOH {
class ResourceFactoryBinarySkeletonLimbV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<IResource>
ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class SkeletonLimbFactoryV0 : public ResourceVersionFactory
{
class ResourceFactoryXMLSkeletonLimbV0 : public LUS::ResourceFactoryXML {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,74 +2,38 @@
#include "soh/resource/type/Text.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
TextFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<Text>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<TextFactoryV0>();
break;
default:
// VERSION NOT SUPPORTED
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Text with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
std::shared_ptr<IResource>
TextFactory::ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) {
auto resource = std::make_shared<Text>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<TextFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Text with version {}", resource->GetInitData()->ResourceVersion);
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryTextV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
factory->ParseFileXML(reader, resource);
return resource;
}
void LUS::TextFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<Text> text = std::static_pointer_cast<Text>(resource);
ResourceVersionFactory::ParseFileBinary(reader, text);
auto text = std::make_shared<Text>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
uint32_t msgCount = reader->ReadUInt32();
text->messages.reserve(msgCount);
for (uint32_t i = 0; i < msgCount; i++) {
MessageEntry entry;
entry.id = reader->ReadUInt16();
entry.textboxType = reader->ReadUByte();
entry.textboxYPos = reader->ReadUByte();
entry.msg = reader->ReadString();
MessageEntry entry;
entry.id = reader->ReadUInt16();
entry.textboxType = reader->ReadUByte();
entry.textboxYPos = reader->ReadUByte();
entry.msg = reader->ReadString();
text->messages.push_back(entry);
text->messages.push_back(entry);
}
}
void TextFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<Text> txt = std::static_pointer_cast<Text>(resource);
auto child = reader->FirstChildElement();
return text;
}
std::shared_ptr<LUS::IResource> ResourceFactoryXMLTextV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
auto txt = std::make_shared<Text>(file->InitData);
auto child = std::get<std::shared_ptr<tinyxml2::XMLDocument>>(file->Reader)->FirstChildElement()->FirstChildElement();
while (child != nullptr) {
std::string childName = child->Name();
@ -88,6 +52,7 @@ void TextFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<I
child = child->NextSiblingElement();
}
}
} // namespace LUS
return txt;
}
} // namespace SOH

View File

@ -1,23 +1,17 @@
#pragma once
#include "Resource.h"
#include "ResourceFactory.h"
#include "ResourceFactoryBinary.h"
#include "ResourceFactoryXML.h"
namespace LUS {
class TextFactory : public ResourceFactory
{
namespace SOH {
class ResourceFactoryBinaryTextV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<IResource>
ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
class TextFactoryV0 : public ResourceVersionFactory
{
class ResourceFactoryXMLTextV0 : public LUS::ResourceFactoryXML {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,37 +2,13 @@
#include "soh/resource/type/scenecommand/EndMarker.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
EndMarkerFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<EndMarker>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<EndMarkerFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load EndMarker with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::EndMarkerFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<EndMarker> endMarker = std::static_pointer_cast<EndMarker>(resource);
ResourceVersionFactory::ParseFileBinary(reader, endMarker);
namespace SOH {
std::shared_ptr<LUS::IResource>
EndMarkerFactory::ReadResource(std::shared_ptr<LUS::ResourceInitData> initData, std::shared_ptr<LUS::BinaryReader> reader) {
auto endMarker = std::make_shared<EndMarker>(initData);
ReadCommandId(endMarker, reader);
// This has no data.
}
} // namespace LUS
return endMarker;
}
} // namespace SOH

View File

@ -2,15 +2,9 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class EndMarkerFactory : public SceneCommandFactory {
namespace SOH {
class EndMarkerFactory : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::ResourceInitData> initData, std::shared_ptr<LUS::BinaryReader> reader) override;
};
class EndMarkerFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,9 +2,8 @@
#include "soh/resource/type/scenecommand/SceneCommand.h"
#include "spdlog/spdlog.h"
namespace LUS {
void SceneCommandVersionFactory::ReadCommandId(std::shared_ptr<ISceneCommand> command, std::shared_ptr<BinaryReader> reader) {
namespace SOH {
void SceneCommandFactoryBinaryV0::ReadCommandId(std::shared_ptr<ISceneCommand> command, std::shared_ptr<LUS::BinaryReader> reader) {
command->cmdId = (SceneCommandID)reader->ReadInt32();
}
}
} // namespace SOH

View File

@ -5,11 +5,12 @@
#include "ResourceFactory.h"
#include "soh/resource/type/scenecommand/SceneCommand.h"
namespace LUS {
class SceneCommandFactory : public ResourceFactory {};
namespace SOH {
class SceneCommandFactoryBinaryV0 {
public:
virtual std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::ResourceInitData> initData, std::shared_ptr<LUS::BinaryReader> reader) = 0;
class SceneCommandVersionFactory : public ResourceVersionFactory {
protected:
void ReadCommandId(std::shared_ptr<ISceneCommand> command, std::shared_ptr<BinaryReader> reader);
protected:
void ReadCommandId(std::shared_ptr<ISceneCommand> command, std::shared_ptr<LUS::BinaryReader> reader);
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,52 +2,30 @@
#include "soh/resource/type/scenecommand/SetActorList.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource>
SetActorListFactory::ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetActorList>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetActorListFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load SetActorList with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetActorListFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) {
std::shared_ptr<SetActorList> setActorList = std::static_pointer_cast<SetActorList>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setActorList);
namespace SOH {
std::shared_ptr<LUS::IResource>
SetActorListFactory::ReadResource(std::shared_ptr<LUS::ResourceInitData> initData, std::shared_ptr<LUS::BinaryReader> reader) {
auto setActorList = std::make_shared<SetActorList>(initData);
ReadCommandId(setActorList, reader);
setActorList->numActors = reader->ReadUInt32();
setActorList->actorList.reserve(setActorList->numActors);
for (uint32_t i = 0; i < setActorList->numActors; i++) {
ActorEntry entry;
ActorEntry entry;
entry.id = reader->ReadUInt16();
entry.pos.x = reader->ReadInt16();
entry.pos.y = reader->ReadInt16();
entry.pos.z = reader->ReadInt16();
entry.rot.x = reader->ReadInt16();
entry.rot.y = reader->ReadInt16();
entry.rot.z = reader->ReadInt16();
entry.params = reader->ReadUInt16();
entry.id = reader->ReadUInt16();
entry.pos.x = reader->ReadInt16();
entry.pos.y = reader->ReadInt16();
entry.pos.z = reader->ReadInt16();
entry.rot.x = reader->ReadInt16();
entry.rot.y = reader->ReadInt16();
entry.rot.z = reader->ReadInt16();
entry.params = reader->ReadUInt16();
setActorList->actorList.push_back(entry);
}
}
} // namespace LUS
return setActorList;
}
} // namespace SOH

View File

@ -2,15 +2,10 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetActorListFactory : public SceneCommandFactory {
namespace SOH {
class SetActorListFactory : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource>
ReadResource(std::shared_ptr<LUS::ResourceInitData> initData, std::shared_ptr<LUS::BinaryReader> reader) override;
};
class SetActorListFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -3,47 +3,24 @@
#include "spdlog/spdlog.h"
#include "libultraship/libultraship.h"
namespace LUS {
std::shared_ptr<IResource> SetAlternateHeadersFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetAlternateHeaders>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetAlternateHeadersFactoryV0>();
break;
}
if (factory == nullptr)
{
SPDLOG_ERROR("Failed to load SetAlternateHeaders with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetAlternateHeadersFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SetAlternateHeaders> setAlternateHeaders = std::static_pointer_cast<SetAlternateHeaders>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setAlternateHeaders);
namespace SOH {
std::shared_ptr<LUS::IResource> SetAlternateHeadersFactory::ReadResource(std::shared_ptr<LUS::ResourceInitData> initData,
std::shared_ptr<LUS::BinaryReader> reader) {
auto setAlternateHeaders = std::make_shared<SetAlternateHeaders>(initData);
ReadCommandId(setAlternateHeaders, reader);
setAlternateHeaders->numHeaders = reader->ReadUInt32();
setAlternateHeaders->headers.reserve(setAlternateHeaders->numHeaders);
for (uint32_t i = 0; i < setAlternateHeaders->numHeaders; i++) {
auto headerName = reader->ReadString();
if (!headerName.empty()) {
setAlternateHeaders->headers.push_back(std::static_pointer_cast<LUS::Scene>(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str())));
} else {
setAlternateHeaders->headers.push_back(nullptr);
}
auto headerName = reader->ReadString();
if (!headerName.empty()) {
setAlternateHeaders->headers.push_back(std::static_pointer_cast<Scene>(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str())));
} else {
setAlternateHeaders->headers.push_back(nullptr);
}
}
}
} // namespace LUS
return setAlternateHeaders;
}
} // namespace SOH

View File

@ -2,15 +2,10 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetAlternateHeadersFactory : public SceneCommandFactory {
namespace SOH {
class SetAlternateHeadersFactory : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource>
ReadResource(std::shared_ptr<LUS::ResourceInitData> initData, std::shared_ptr<LUS::BinaryReader> reader) override;
};
class SetAlternateHeadersFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

View File

@ -2,38 +2,16 @@
#include "soh/resource/type/scenecommand/SetCameraSettings.h"
#include "spdlog/spdlog.h"
namespace LUS {
std::shared_ptr<IResource> SetCameraSettingsFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) {
auto resource = std::make_shared<SetCameraSettings>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<SetCameraSettingsFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load SetCameraSettings with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileBinary(reader, resource);
return resource;
}
void LUS::SetCameraSettingsFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource)
{
std::shared_ptr<SetCameraSettings> setCameraSettings = std::static_pointer_cast<SetCameraSettings>(resource);
ResourceVersionFactory::ParseFileBinary(reader, setCameraSettings);
namespace SOH {
std::shared_ptr<LUS::IResource> SetCameraSettingsFactory::ReadResource(std::shared_ptr<LUS::ResourceInitData> initData,
std::shared_ptr<LUS::BinaryReader> reader) {
auto setCameraSettings = std::make_shared<SetCameraSettings>(initData);
ReadCommandId(setCameraSettings, reader);
setCameraSettings->settings.cameraMovement = reader->ReadInt8();
setCameraSettings->settings.worldMapArea = reader->ReadInt32();
}
} // namespace LUS
return setCameraSettings;
}
} // namespace SOH

View File

@ -2,15 +2,10 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace LUS {
class SetCameraSettingsFactory : public SceneCommandFactory {
namespace SOH {
class SetCameraSettingsFactory : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<LUS::IResource>
ReadResource(std::shared_ptr<LUS::ResourceInitData> initData, std::shared_ptr<LUS::BinaryReader> reader) override;
};
class SetCameraSettingsFactoryV0 : public SceneCommandVersionFactory {
public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
};
}; // namespace LUS
} // namespace SOH

Some files were not shown because too many files have changed in this diff Show More