diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bdaf1de9..cc3adb1f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,7 @@ math(EXPR PATCH_INDEX "${PROJECT_VERSION_PATCH}") # Use the patch number to select the correct word list(GET NATO_PHONETIC_ALPHABET ${PATCH_INDEX} PROJECT_PATCH_WORD) -set(PROJECT_BUILD_NAME "MacReady ${PROJECT_PATCH_WORD}" CACHE STRING "" FORCE) +set(PROJECT_BUILD_NAME "Holiday 2024" CACHE STRING "" FORCE) set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "" FORCE) execute_process( diff --git a/soh/assets/custom/objects/custom_snowball/LightNoise.rgba32 b/soh/assets/custom/objects/custom_snowball/LightNoise.rgba32 new file mode 100644 index 000000000..73bcf2a59 Binary files /dev/null and b/soh/assets/custom/objects/custom_snowball/LightNoise.rgba32 differ diff --git a/soh/assets/custom/objects/custom_snowball/mat_snowball_snow b/soh/assets/custom/objects/custom_snowball/mat_snowball_snow new file mode 100644 index 000000000..49b24d2b5 --- /dev/null +++ b/soh/assets/custom/objects/custom_snowball/mat_snowball_snow @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/custom_snowball/model.xml b/soh/assets/custom/objects/custom_snowball/model.xml new file mode 100644 index 000000000..8e2e4aa6e --- /dev/null +++ b/soh/assets/custom/objects/custom_snowball/model.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/custom_snowball/snowball b/soh/assets/custom/objects/custom_snowball/snowball new file mode 100644 index 000000000..ca9fb8e40 --- /dev/null +++ b/soh/assets/custom/objects/custom_snowball/snowball @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/custom_snowball/snowball_tri_0 b/soh/assets/custom/objects/custom_snowball/snowball_tri_0 new file mode 100644 index 000000000..7c4fb871d --- /dev/null +++ b/soh/assets/custom/objects/custom_snowball/snowball_tri_0 @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/custom_snowball/snowball_vtx_0 b/soh/assets/custom/objects/custom_snowball/snowball_vtx_0 new file mode 100644 index 000000000..69080c089 --- /dev/null +++ b/soh/assets/custom/objects/custom_snowball/snowball_vtx_0 @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/custom_snowball/snowball_vtx_cull b/soh/assets/custom/objects/custom_snowball/snowball_vtx_cull new file mode 100644 index 000000000..8e2e4aa6e --- /dev/null +++ b/soh/assets/custom/objects/custom_snowball/snowball_vtx_cull @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/antlers_64 b/soh/assets/custom/objects/object_festivehats/antlers_64 new file mode 100644 index 000000000..74fe9e819 Binary files /dev/null and b/soh/assets/custom/objects/object_festivehats/antlers_64 differ diff --git a/soh/assets/custom/objects/object_festivehats/gCuccoLadyHatDL b/soh/assets/custom/objects/object_festivehats/gCuccoLadyHatDL new file mode 100644 index 000000000..ab8fdf45f --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gCuccoLadyHatDL @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gCuccoLadyHatDL_tri_0 b/soh/assets/custom/objects/object_festivehats/gCuccoLadyHatDL_tri_0 new file mode 100644 index 000000000..980452845 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gCuccoLadyHatDL_tri_0 @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gCuccoLadyHatDL_vtx_0 b/soh/assets/custom/objects/object_festivehats/gCuccoLadyHatDL_vtx_0 new file mode 100644 index 000000000..8a64cdf18 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gCuccoLadyHatDL_vtx_0 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL b/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL new file mode 100644 index 000000000..6d059179f --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_tri_0 b/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_tri_0 new file mode 100644 index 000000000..3e0ab2ad8 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_tri_0 @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_tri_1 b/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_tri_1 new file mode 100644 index 000000000..99f0a799d --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_tri_1 @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_vtx_0 b/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_vtx_0 new file mode 100644 index 000000000..ebb2b0eea --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_vtx_0 @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_vtx_1 b/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_vtx_1 new file mode 100644 index 000000000..d7263bc94 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gEponaRudolphHatDL_vtx_1 @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gHorseAntlersDL b/soh/assets/custom/objects/object_festivehats/gHorseAntlersDL new file mode 100644 index 000000000..2b2ee6c3e --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gHorseAntlersDL @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gHorseAntlersDL_tri_0 b/soh/assets/custom/objects/object_festivehats/gHorseAntlersDL_tri_0 new file mode 100644 index 000000000..543e90c1f --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gHorseAntlersDL_tri_0 @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gHorseAntlersDL_vtx_0 b/soh/assets/custom/objects/object_festivehats/gHorseAntlersDL_vtx_0 new file mode 100644 index 000000000..d7263bc94 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gHorseAntlersDL_vtx_0 @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkAdultHatTrimDL b/soh/assets/custom/objects/object_festivehats/gLinkAdultHatTrimDL new file mode 100644 index 000000000..27bdd9211 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkAdultHatTrimDL @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkAdultHatTrimDL_tri_0 b/soh/assets/custom/objects/object_festivehats/gLinkAdultHatTrimDL_tri_0 new file mode 100644 index 000000000..313f489de --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkAdultHatTrimDL_tri_0 @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkAdultHatTrimDL_vtx_0 b/soh/assets/custom/objects/object_festivehats/gLinkAdultHatTrimDL_vtx_0 new file mode 100644 index 000000000..eb7d042ff --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkAdultHatTrimDL_vtx_0 @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkAdultPompomDL b/soh/assets/custom/objects/object_festivehats/gLinkAdultPompomDL new file mode 100644 index 000000000..6f7262451 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkAdultPompomDL @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkAdultPompomDL_tri_0 b/soh/assets/custom/objects/object_festivehats/gLinkAdultPompomDL_tri_0 new file mode 100644 index 000000000..83cf6d929 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkAdultPompomDL_tri_0 @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkAdultPompomDL_vtx_0 b/soh/assets/custom/objects/object_festivehats/gLinkAdultPompomDL_vtx_0 new file mode 100644 index 000000000..b937dad3e --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkAdultPompomDL_vtx_0 @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkChildHatTrimDL b/soh/assets/custom/objects/object_festivehats/gLinkChildHatTrimDL new file mode 100644 index 000000000..769a41928 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkChildHatTrimDL @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkChildHatTrimDL_tri_0 b/soh/assets/custom/objects/object_festivehats/gLinkChildHatTrimDL_tri_0 new file mode 100644 index 000000000..776fb4da9 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkChildHatTrimDL_tri_0 @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkChildHatTrimDL_vtx_0 b/soh/assets/custom/objects/object_festivehats/gLinkChildHatTrimDL_vtx_0 new file mode 100644 index 000000000..847f1ae81 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkChildHatTrimDL_vtx_0 @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkChildPompomDL b/soh/assets/custom/objects/object_festivehats/gLinkChildPompomDL new file mode 100644 index 000000000..4093e1aa3 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkChildPompomDL @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkChildPompomDL_tri_0 b/soh/assets/custom/objects/object_festivehats/gLinkChildPompomDL_tri_0 new file mode 100644 index 000000000..4f18af8bf --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkChildPompomDL_tri_0 @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gLinkChildPompomDL_vtx_0 b/soh/assets/custom/objects/object_festivehats/gLinkChildPompomDL_vtx_0 new file mode 100644 index 000000000..b0c371f13 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gLinkChildPompomDL_vtx_0 @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gPaperCrownGenericDL b/soh/assets/custom/objects/object_festivehats/gPaperCrownGenericDL new file mode 100644 index 000000000..ec6ccada7 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gPaperCrownGenericDL @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gPaperCrownGenericDL_tri_0 b/soh/assets/custom/objects/object_festivehats/gPaperCrownGenericDL_tri_0 new file mode 100644 index 000000000..672602bc1 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gPaperCrownGenericDL_tri_0 @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gPaperCrownGenericDL_vtx_0 b/soh/assets/custom/objects/object_festivehats/gPaperCrownGenericDL_vtx_0 new file mode 100644 index 000000000..c7a513a67 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gPaperCrownGenericDL_vtx_0 @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL b/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL new file mode 100644 index 000000000..0f4573976 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_tri_0 b/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_tri_0 new file mode 100644 index 000000000..5396ff4d8 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_tri_0 @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_tri_1 b/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_tri_1 new file mode 100644 index 000000000..bdf895c49 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_tri_1 @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_vtx_0 b/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_vtx_0 new file mode 100644 index 000000000..145ca70f4 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_vtx_0 @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_vtx_1 b/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_vtx_1 new file mode 100644 index 000000000..7f90daac7 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/gSantaHatGenericDL_vtx_1 @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/hilite_nose b/soh/assets/custom/objects/object_festivehats/hilite_nose new file mode 100644 index 000000000..b2d4623c9 Binary files /dev/null and b/soh/assets/custom/objects/object_festivehats/hilite_nose differ diff --git a/soh/assets/custom/objects/object_festivehats/mat_gCuccoLadyHatDL_f3dlite_hatcolour b/soh/assets/custom/objects/object_festivehats/mat_gCuccoLadyHatDL_f3dlite_hatcolour new file mode 100644 index 000000000..d1d036f89 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/mat_gCuccoLadyHatDL_f3dlite_hatcolour @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/mat_gEponaRudolphHatDL_f3dlite_antlers b/soh/assets/custom/objects/object_festivehats/mat_gEponaRudolphHatDL_f3dlite_antlers new file mode 100644 index 000000000..3717c72b2 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/mat_gEponaRudolphHatDL_f3dlite_antlers @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_f3dlite_shard_edge b/soh/assets/custom/objects/object_festivehats/mat_gEponaRudolphHatDL_f3dlite_rednose similarity index 75% rename from soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_f3dlite_shard_edge rename to soh/assets/custom/objects/object_festivehats/mat_gEponaRudolphHatDL_f3dlite_rednose index b9e61293d..758d8698b 100644 --- a/soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_f3dlite_shard_edge +++ b/soh/assets/custom/objects/object_festivehats/mat_gEponaRudolphHatDL_f3dlite_rednose @@ -1,21 +1,21 @@ - - - + + + - + - + - + diff --git a/soh/assets/custom/objects/object_festivehats/mat_gHorseAntlersDL_f3dlite_antlers b/soh/assets/custom/objects/object_festivehats/mat_gHorseAntlersDL_f3dlite_antlers new file mode 100644 index 000000000..3717c72b2 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/mat_gHorseAntlersDL_f3dlite_antlers @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/mat_gLinkAdultHatTrimDL_f3dlite_santahat_white b/soh/assets/custom/objects/object_festivehats/mat_gLinkAdultHatTrimDL_f3dlite_santahat_white new file mode 100644 index 000000000..2f72783f7 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/mat_gLinkAdultHatTrimDL_f3dlite_santahat_white @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/mat_gLinkAdultPompomDL_f3dlite_santahat_white b/soh/assets/custom/objects/object_festivehats/mat_gLinkAdultPompomDL_f3dlite_santahat_white new file mode 100644 index 000000000..2f72783f7 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/mat_gLinkAdultPompomDL_f3dlite_santahat_white @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/mat_gLinkChildHatTrimDL_f3dlite_santahat_white b/soh/assets/custom/objects/object_festivehats/mat_gLinkChildHatTrimDL_f3dlite_santahat_white new file mode 100644 index 000000000..2f72783f7 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/mat_gLinkChildHatTrimDL_f3dlite_santahat_white @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/mat_gLinkChildPompomDL_f3dlite_santahat_white b/soh/assets/custom/objects/object_festivehats/mat_gLinkChildPompomDL_f3dlite_santahat_white new file mode 100644 index 000000000..2f72783f7 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/mat_gLinkChildPompomDL_f3dlite_santahat_white @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/mat_gPaperCrownGenericDL_f3dlite_crown b/soh/assets/custom/objects/object_festivehats/mat_gPaperCrownGenericDL_f3dlite_crown new file mode 100644 index 000000000..4fb4e2029 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/mat_gPaperCrownGenericDL_f3dlite_crown @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/mat_gSantaHatGenericDL_f3dlite_santahatred b/soh/assets/custom/objects/object_festivehats/mat_gSantaHatGenericDL_f3dlite_santahatred new file mode 100644 index 000000000..b42644ae8 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/mat_gSantaHatGenericDL_f3dlite_santahatred @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_festivehats/mat_gSantaHatGenericDL_f3dlite_santahatwhite b/soh/assets/custom/objects/object_festivehats/mat_gSantaHatGenericDL_f3dlite_santahatwhite new file mode 100644 index 000000000..2f72783f7 --- /dev/null +++ b/soh/assets/custom/objects/object_festivehats/mat_gSantaHatGenericDL_f3dlite_santahatwhite @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/CuccoBedding_32 b/soh/assets/custom/objects/object_kakariko_decor/CuccoBedding_32 new file mode 100644 index 000000000..68187fbf5 Binary files /dev/null and b/soh/assets/custom/objects/object_kakariko_decor/CuccoBedding_32 differ diff --git a/soh/assets/custom/objects/object_kakariko_decor/SnowBlanket_32 b/soh/assets/custom/objects/object_kakariko_decor/SnowBlanket_32 new file mode 100644 index 000000000..733b30757 Binary files /dev/null and b/soh/assets/custom/objects/object_kakariko_decor/SnowBlanket_32 differ diff --git a/soh/assets/custom/objects/object_kakariko_decor/SnowBuildup_32 b/soh/assets/custom/objects/object_kakariko_decor/SnowBuildup_32 new file mode 100644 index 000000000..4653f07d1 Binary files /dev/null and b/soh/assets/custom/objects/object_kakariko_decor/SnowBuildup_32 differ diff --git a/soh/assets/custom/objects/object_kakariko_decor/SnowDissolve_32 b/soh/assets/custom/objects/object_kakariko_decor/SnowDissolve_32 new file mode 100644 index 000000000..e7c7aa142 Binary files /dev/null and b/soh/assets/custom/objects/object_kakariko_decor/SnowDissolve_32 differ diff --git a/soh/assets/custom/objects/object_kakariko_decor/String_BYBY_32 b/soh/assets/custom/objects/object_kakariko_decor/String_BYBY_32 new file mode 100644 index 000000000..62efcb10a Binary files /dev/null and b/soh/assets/custom/objects/object_kakariko_decor/String_BYBY_32 differ diff --git a/soh/assets/custom/objects/object_kakariko_decor/String_GRGR_32 b/soh/assets/custom/objects/object_kakariko_decor/String_GRGR_32 new file mode 100644 index 000000000..b905f21a9 Binary files /dev/null and b/soh/assets/custom/objects/object_kakariko_decor/String_GRGR_32 differ diff --git a/soh/assets/custom/objects/object_kakariko_decor/UsagiLeaf_8 b/soh/assets/custom/objects/object_kakariko_decor/UsagiLeaf_8 new file mode 100644 index 000000000..fc4d3ff5b Binary files /dev/null and b/soh/assets/custom/objects/object_kakariko_decor/UsagiLeaf_8 differ diff --git a/soh/assets/custom/objects/object_kakariko_decor/YukiUsagi_16 b/soh/assets/custom/objects/object_kakariko_decor/YukiUsagi_16 new file mode 100644 index 000000000..2034627ff Binary files /dev/null and b/soh/assets/custom/objects/object_kakariko_decor/YukiUsagi_16 differ diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL new file mode 100644 index 000000000..13d9447f7 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_tri_0 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_tri_0 new file mode 100644 index 000000000..1263127aa --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_tri_0 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_tri_1 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_tri_1 new file mode 100644 index 000000000..2aff9496e --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_tri_1 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_vtx_0 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_vtx_0 new file mode 100644 index 000000000..9f3683fed --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_vtx_0 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_vtx_1 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_vtx_1 new file mode 100644 index 000000000..e438e71cf --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_vtx_1 @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_vtx_cull b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_vtx_cull new file mode 100644 index 000000000..c3ecddb8a --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoAdultDecorDL_vtx_cull @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL new file mode 100644 index 000000000..a3972ce7a --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_tri_0 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_tri_0 new file mode 100644 index 000000000..eb7e92fdf --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_tri_0 @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_tri_1 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_tri_1 new file mode 100644 index 000000000..77468a738 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_tri_1 @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_tri_2 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_tri_2 new file mode 100644 index 000000000..97634bb7b --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_tri_2 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_0 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_0 new file mode 100644 index 000000000..24e3e3d6e --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_0 @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_1 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_1 new file mode 100644 index 000000000..0b12310ec --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_1 @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_2 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_2 new file mode 100644 index 000000000..f2a81069d --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_2 @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_cull b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_cull new file mode 100644 index 000000000..b2e233783 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoChildDecorDL_vtx_cull @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL new file mode 100644 index 000000000..f0363d242 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_0 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_0 new file mode 100644 index 000000000..5ee2633e5 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_0 @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_1 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_1 new file mode 100644 index 000000000..2b52e5ef3 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_1 @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_2 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_2 new file mode 100644 index 000000000..d6f5dbafe --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_2 @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_3 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_3 new file mode 100644 index 000000000..f66ba5914 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_3 @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_4 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_4 new file mode 100644 index 000000000..e0d376897 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_4 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_5 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_5 new file mode 100644 index 000000000..ca52719c9 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_5 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_6 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_6 new file mode 100644 index 000000000..75be056f5 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_6 @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_7 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_7 new file mode 100644 index 000000000..eeedcf1ee --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_tri_7 @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_0 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_0 new file mode 100644 index 000000000..c0a07802c --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_0 @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_1 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_1 new file mode 100644 index 000000000..c7615dd3b --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_1 @@ -0,0 +1,770 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_2 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_2 new file mode 100644 index 000000000..3ff9d2e43 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_2 @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_3 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_3 new file mode 100644 index 000000000..b0e49797a --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_3 @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_4 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_4 new file mode 100644 index 000000000..043452939 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_4 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_5 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_5 new file mode 100644 index 000000000..46c6ac9a1 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_5 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_6 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_6 new file mode 100644 index 000000000..0e5970505 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_6 @@ -0,0 +1,497 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_7 b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_7 new file mode 100644 index 000000000..1929d460e --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_7 @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_cull b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_cull new file mode 100644 index 000000000..a183da293 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/gKakarikoDecorDL_vtx_cull @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoAdultDecorDL_f3dlite_StringGRGR b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoAdultDecorDL_f3dlite_StringGRGR new file mode 100644 index 000000000..b8478fa90 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoAdultDecorDL_f3dlite_StringGRGR @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_f3dlite_triforce_edges b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoAdultDecorDL_f3dlite_snowlayer similarity index 52% rename from soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_f3dlite_triforce_edges rename to soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoAdultDecorDL_f3dlite_snowlayer index 9355e7094..5456b3893 100644 --- a/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_f3dlite_triforce_edges +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoAdultDecorDL_f3dlite_snowlayer @@ -1,21 +1,21 @@ - - - + + + - + - - + + - + - + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoChildDecorDL_f3dlite_SnowBuildup b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoChildDecorDL_f3dlite_SnowBuildup new file mode 100644 index 000000000..a79cca54f --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoChildDecorDL_f3dlite_SnowBuildup @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoChildDecorDL_f3dlite_UsagiLeaf b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoChildDecorDL_f3dlite_UsagiLeaf new file mode 100644 index 000000000..be29498ef --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoChildDecorDL_f3dlite_UsagiLeaf @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoChildDecorDL_f3dlite_YukiUsagiBody b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoChildDecorDL_f3dlite_YukiUsagiBody new file mode 100644 index 000000000..3a2d2c889 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoChildDecorDL_f3dlite_YukiUsagiBody @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_CuccoBedding b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_CuccoBedding new file mode 100644 index 000000000..520258210 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_CuccoBedding @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_SnowBuildup b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_SnowBuildup new file mode 100644 index 000000000..a79cca54f --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_SnowBuildup @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_StringBYBY b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_StringBYBY new file mode 100644 index 000000000..5c85eb88f --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_StringBYBY @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_StringGRGR b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_StringGRGR new file mode 100644 index 000000000..b8478fa90 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_StringGRGR @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_UsagiLeaf b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_UsagiLeaf new file mode 100644 index 000000000..be29498ef --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_UsagiLeaf @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_YukiUsagiBody b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_YukiUsagiBody new file mode 100644 index 000000000..3a2d2c889 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_YukiUsagiBody @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_snowdissolve b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_snowdissolve new file mode 100644 index 000000000..e86142f29 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_snowdissolve @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_snowlayer b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_snowlayer new file mode 100644 index 000000000..5456b3893 --- /dev/null +++ b/soh/assets/custom/objects/object_kakariko_decor/mat_gKakarikoDecorDL_f3dlite_snowlayer @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/mat_object_penguin_DL_beak b/soh/assets/custom/objects/object_penguin/mat_object_penguin_DL_beak new file mode 100644 index 000000000..f83feec12 --- /dev/null +++ b/soh/assets/custom/objects/object_penguin/mat_object_penguin_DL_beak @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/mat_object_penguin_DL_eye b/soh/assets/custom/objects/object_penguin/mat_object_penguin_DL_eye new file mode 100644 index 000000000..c24abe2ab --- /dev/null +++ b/soh/assets/custom/objects/object_penguin/mat_object_penguin_DL_eye @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/mat_object_penguin_DL_skin b/soh/assets/custom/objects/object_penguin/mat_object_penguin_DL_skin new file mode 100644 index 000000000..6c57863e3 --- /dev/null +++ b/soh/assets/custom/objects/object_penguin/mat_object_penguin_DL_skin @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/object_penguin_DL b/soh/assets/custom/objects/object_penguin/object_penguin_DL new file mode 100644 index 000000000..393bbc438 --- /dev/null +++ b/soh/assets/custom/objects/object_penguin/object_penguin_DL @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/object_penguin_DL_tri_0 b/soh/assets/custom/objects/object_penguin/object_penguin_DL_tri_0 new file mode 100644 index 000000000..9039650d4 --- /dev/null +++ b/soh/assets/custom/objects/object_penguin/object_penguin_DL_tri_0 @@ -0,0 +1,862 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/object_penguin_DL_tri_1 b/soh/assets/custom/objects/object_penguin/object_penguin_DL_tri_1 new file mode 100644 index 000000000..efb326ace --- /dev/null +++ b/soh/assets/custom/objects/object_penguin/object_penguin_DL_tri_1 @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/object_penguin_DL_tri_2 b/soh/assets/custom/objects/object_penguin/object_penguin_DL_tri_2 new file mode 100644 index 000000000..96c7933ec --- /dev/null +++ b/soh/assets/custom/objects/object_penguin/object_penguin_DL_tri_2 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/object_penguin_DL_vtx_0 b/soh/assets/custom/objects/object_penguin/object_penguin_DL_vtx_0 new file mode 100644 index 000000000..f1a650d47 --- /dev/null +++ b/soh/assets/custom/objects/object_penguin/object_penguin_DL_vtx_0 @@ -0,0 +1,922 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/object_penguin_DL_vtx_1 b/soh/assets/custom/objects/object_penguin/object_penguin_DL_vtx_1 new file mode 100644 index 000000000..5cd519f95 --- /dev/null +++ b/soh/assets/custom/objects/object_penguin/object_penguin_DL_vtx_1 @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/object_penguin_DL_vtx_2 b/soh/assets/custom/objects/object_penguin/object_penguin_DL_vtx_2 new file mode 100644 index 000000000..97f03bf0f --- /dev/null +++ b/soh/assets/custom/objects/object_penguin/object_penguin_DL_vtx_2 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_penguin/ping_eye b/soh/assets/custom/objects/object_penguin/ping_eye new file mode 100644 index 000000000..32eb2e7e1 Binary files /dev/null and b/soh/assets/custom/objects/object_penguin/ping_eye differ diff --git a/soh/assets/custom/objects/object_penguin/ping_tex b/soh/assets/custom/objects/object_penguin/ping_tex new file mode 100644 index 000000000..9913decc7 Binary files /dev/null and b/soh/assets/custom/objects/object_penguin/ping_tex differ diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/SnowBlanket_32 b/soh/assets/custom/objects/object_temple_of_time_decor/SnowBlanket_32 new file mode 100644 index 000000000..733b30757 Binary files /dev/null and b/soh/assets/custom/objects/object_temple_of_time_decor/SnowBlanket_32 differ diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/SnowBuildup_32 b/soh/assets/custom/objects/object_temple_of_time_decor/SnowBuildup_32 new file mode 100644 index 000000000..4653f07d1 Binary files /dev/null and b/soh/assets/custom/objects/object_temple_of_time_decor/SnowBuildup_32 differ diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/String_BYBY_32 b/soh/assets/custom/objects/object_temple_of_time_decor/String_BYBY_32 new file mode 100644 index 000000000..62efcb10a Binary files /dev/null and b/soh/assets/custom/objects/object_temple_of_time_decor/String_BYBY_32 differ diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/String_GRGR_32 b/soh/assets/custom/objects/object_temple_of_time_decor/String_GRGR_32 new file mode 100644 index 000000000..b905f21a9 Binary files /dev/null and b/soh/assets/custom/objects/object_temple_of_time_decor/String_GRGR_32 differ diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL new file mode 100644 index 000000000..491663279 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_0 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_0 new file mode 100644 index 000000000..75fc6598b --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_0 @@ -0,0 +1,2222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_1 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_1 new file mode 100644 index 000000000..bf36e26c4 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_1 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_2 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_2 new file mode 100644 index 000000000..4020ff3d1 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_2 @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_3 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_3 new file mode 100644 index 000000000..eb072a5ef --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_3 @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_4 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_4 new file mode 100644 index 000000000..34fbdd806 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_4 @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_5 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_5 new file mode 100644 index 000000000..e360d5739 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_5 @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_6 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_6 new file mode 100644 index 000000000..8dcd07878 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_6 @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_7 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_7 new file mode 100644 index 000000000..a276056ed --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_7 @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_8 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_8 new file mode 100644 index 000000000..b7f90b048 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_tri_8 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_0 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_0 new file mode 100644 index 000000000..772a7955d --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_0 @@ -0,0 +1,4468 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_1 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_1 new file mode 100644 index 000000000..f62970ec9 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_1 @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_2 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_2 new file mode 100644 index 000000000..30da04c9f --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_2 @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_3 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_3 new file mode 100644 index 000000000..834efd769 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_3 @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_4 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_4 new file mode 100644 index 000000000..acfe49fc6 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_4 @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_5 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_5 new file mode 100644 index 000000000..13fd6d48a --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_5 @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_6 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_6 new file mode 100644 index 000000000..e8e4e4a52 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_6 @@ -0,0 +1,278 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_7 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_7 new file mode 100644 index 000000000..359d48716 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_7 @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_8 b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_8 new file mode 100644 index 000000000..2cb6bf701 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_8 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_cull b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_cull new file mode 100644 index 000000000..6dd5d78cb --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/gTempleOfTimeDecorDL_vtx_cull @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/ice b/soh/assets/custom/objects/object_temple_of_time_decor/ice new file mode 100644 index 000000000..ff27a0246 Binary files /dev/null and b/soh/assets/custom/objects/object_temple_of_time_decor/ice differ diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_SnowBuildup b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_SnowBuildup new file mode 100644 index 000000000..46d52d40d --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_SnowBuildup @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_f3dlite_shard_edge b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_StringBYBY similarity index 52% rename from soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_f3dlite_shard_edge rename to soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_StringBYBY index c222fe68d..16c505a28 100644 --- a/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_f3dlite_shard_edge +++ b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_StringBYBY @@ -1,21 +1,21 @@ - - - + + + - + - - + + - + - + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_StringGRGR b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_StringGRGR new file mode 100644 index 000000000..5663994ee --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_StringGRGR @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_blue_material b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_blue_material new file mode 100644 index 000000000..c0c1a4ac9 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_blue_material @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_green_material b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_green_material new file mode 100644 index 000000000..6fcf6e1d8 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_green_material @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_red_material b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_red_material new file mode 100644 index 000000000..a73985478 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_red_material @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_yellow_material b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_yellow_material new file mode 100644 index 000000000..9f11354bd --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_gift_col_yellow_material @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_f3dlite_triforce_surface b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_ice_material similarity index 65% rename from soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_f3dlite_triforce_surface rename to soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_ice_material index e863b31c5..2a71c2cc9 100644 --- a/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_f3dlite_triforce_surface +++ b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_ice_material @@ -1,21 +1,21 @@ - - - + + + - + - + - + diff --git a/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_snowlayer b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_snowlayer new file mode 100644 index 000000000..e15d18af1 --- /dev/null +++ b/soh/assets/custom/objects/object_temple_of_time_decor/mat_gTempleOfTimeDecorDL_f3dlite_snowlayer @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_completed/GlowAlpha_64 b/soh/assets/custom/objects/object_triforce_completed/GlowAlpha_64 new file mode 100644 index 000000000..1682d9e6f Binary files /dev/null and b/soh/assets/custom/objects/object_triforce_completed/GlowAlpha_64 differ diff --git a/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL b/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL index 966bef206..b7c7d8af0 100644 --- a/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL +++ b/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL @@ -1,7 +1,7 @@ - + - + diff --git a/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_tri_0 b/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_tri_0 index dea47708c..f9d6420cc 100644 --- a/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_tri_0 +++ b/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_tri_0 @@ -1,56 +1,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_tri_1 b/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_tri_1 index 36be4333f..b67adf06e 100644 --- a/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_tri_1 +++ b/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_tri_1 @@ -1,7 +1,390 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_vtx_0 b/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_vtx_0 index 6ca96db30..ca11ab1b3 100644 --- a/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_vtx_0 +++ b/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_vtx_0 @@ -1,54 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_vtx_1 b/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_vtx_1 index 3a653966d..cc747f74a 100644 --- a/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_vtx_1 +++ b/soh/assets/custom/objects/object_triforce_completed/gTriforcePieceCompletedDL_vtx_1 @@ -1,8 +1,347 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_completed/hilite_melon b/soh/assets/custom/objects/object_triforce_completed/hilite_melon new file mode 100644 index 000000000..df1d605b3 Binary files /dev/null and b/soh/assets/custom/objects/object_triforce_completed/hilite_melon differ diff --git a/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_Glow b/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_Glow new file mode 100644 index 000000000..6bed4d274 --- /dev/null +++ b/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_Glow @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_f3dlite_triforce_surface b/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_OrnamentGold similarity index 75% rename from soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_f3dlite_triforce_surface rename to soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_OrnamentGold index 5f8dc51f9..65dfd4f56 100644 --- a/soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_f3dlite_triforce_surface +++ b/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_OrnamentGold @@ -1,6 +1,6 @@ - + @@ -8,14 +8,14 @@ - + - + diff --git a/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_triforce_edges b/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_triforce_edges deleted file mode 100644 index 52591dfc8..000000000 --- a/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_triforce_edges +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_triforce_surface b/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_triforce_surface deleted file mode 100644 index 06193ae61..000000000 --- a/soh/assets/custom/objects/object_triforce_completed/mat_gTriforcePieceCompletedDL_f3dlite_triforce_surface +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/soh/assets/custom/objects/object_triforce_completed/noise_tex b/soh/assets/custom/objects/object_triforce_completed/noise_tex deleted file mode 100644 index a6d6cf945..000000000 Binary files a/soh/assets/custom/objects/object_triforce_completed/noise_tex and /dev/null differ diff --git a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL index 70d08c31d..0beb02144 100644 --- a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL +++ b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL @@ -1,10 +1,8 @@ - + - + - - diff --git a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_0 b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_0 index 09e44f1b7..286a54384 100644 --- a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_0 +++ b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_0 @@ -1,17 +1,67 @@ - - - + + + - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_1 b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_1 index 48001e3c3..a3c013e4a 100644 --- a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_1 +++ b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_1 @@ -1,18 +1,91 @@ - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_2 b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_2 deleted file mode 100644 index e35e34492..000000000 --- a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_tri_2 +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_0 b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_0 index a86fa98bf..4f60b10fe 100644 --- a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_0 +++ b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_0 @@ -1,18 +1,72 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_1 b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_1 index 230fbb7f8..80931181f 100644 --- a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_1 +++ b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_1 @@ -1,22 +1,107 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_2 b/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_2 deleted file mode 100644 index 86d123825..000000000 --- a/soh/assets/custom/objects/object_triforce_piece_0/gTriforcePiece0DL_vtx_2 +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/soh/assets/custom/objects/object_triforce_piece_0/image b/soh/assets/custom/objects/object_triforce_piece_0/image new file mode 100644 index 000000000..2a8a62348 Binary files /dev/null and b/soh/assets/custom/objects/object_triforce_piece_0/image differ diff --git a/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_ball b/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_ball new file mode 100644 index 000000000..214ad3df6 --- /dev/null +++ b/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_ball @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_f3dlite_shard_edge b/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_f3dlite_shard_edge deleted file mode 100644 index f62631793..000000000 --- a/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_f3dlite_shard_edge +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_silver b/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_silver new file mode 100644 index 000000000..d56781ad2 --- /dev/null +++ b/soh/assets/custom/objects/object_triforce_piece_0/mat_gTriforcePiece0DL_silver @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_0/noise_tex b/soh/assets/custom/objects/object_triforce_piece_0/noise_tex deleted file mode 100644 index a6d6cf945..000000000 Binary files a/soh/assets/custom/objects/object_triforce_piece_0/noise_tex and /dev/null differ diff --git a/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL b/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL index 50a9264c6..4ffea5cf8 100644 --- a/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL +++ b/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL @@ -1,7 +1,7 @@ - + - + diff --git a/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_tri_0 b/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_tri_0 index 5f33f7347..c9e63a8d9 100644 --- a/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_tri_0 +++ b/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_tri_0 @@ -1,20 +1,67 @@ - - - - - - + + + + + + + + - - - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_tri_1 b/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_tri_1 index 43df6492b..67f0ba8eb 100644 --- a/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_tri_1 +++ b/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_tri_1 @@ -1,25 +1,88 @@ - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_vtx_0 b/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_vtx_0 index e078b8246..366463fd9 100644 --- a/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_vtx_0 +++ b/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_vtx_0 @@ -1,23 +1,72 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_vtx_1 b/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_vtx_1 index e0460194d..8085ae95a 100644 --- a/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_vtx_1 +++ b/soh/assets/custom/objects/object_triforce_piece_1/gTriforcePiece1DL_vtx_1 @@ -1,34 +1,96 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_1/image b/soh/assets/custom/objects/object_triforce_piece_1/image new file mode 100644 index 000000000..2a8a62348 Binary files /dev/null and b/soh/assets/custom/objects/object_triforce_piece_1/image differ diff --git a/soh/assets/custom/objects/object_triforce_piece_1/image_copy b/soh/assets/custom/objects/object_triforce_piece_1/image_copy new file mode 100644 index 000000000..2a8a62348 Binary files /dev/null and b/soh/assets/custom/objects/object_triforce_piece_1/image_copy differ diff --git a/soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_blue_mat b/soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_blue_mat new file mode 100644 index 000000000..6ba4d88f9 --- /dev/null +++ b/soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_blue_mat @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_silver_002 b/soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_silver_002 new file mode 100644 index 000000000..26f9a0b70 --- /dev/null +++ b/soh/assets/custom/objects/object_triforce_piece_1/mat_gTriforcePiece1DL_silver_002 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_1/noise_tex b/soh/assets/custom/objects/object_triforce_piece_1/noise_tex deleted file mode 100644 index a6d6cf945..000000000 Binary files a/soh/assets/custom/objects/object_triforce_piece_1/noise_tex and /dev/null differ diff --git a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL index 5213cd53c..7318e9b1c 100644 --- a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL +++ b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL @@ -1,10 +1,8 @@ - + - + - - diff --git a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_0 b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_0 index b54e182d5..59d81883f 100644 --- a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_0 +++ b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_0 @@ -1,29 +1,67 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_1 b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_1 index 00a32bfd8..a15c641d7 100644 --- a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_1 +++ b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_1 @@ -1,11 +1,378 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_2 b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_2 deleted file mode 100644 index 0993c1c1e..000000000 --- a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_tri_2 +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_0 b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_0 index bf7dfcac6..90dc38784 100644 --- a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_0 +++ b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_0 @@ -1,36 +1,72 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_1 b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_1 index e3237ab21..ef4ea40e4 100644 --- a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_1 +++ b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_1 @@ -1,12 +1,410 @@ - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_2 b/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_2 deleted file mode 100644 index ec4e73700..000000000 --- a/soh/assets/custom/objects/object_triforce_piece_2/gTriforcePiece2DL_vtx_2 +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/soh/assets/custom/objects/object_triforce_piece_2/image b/soh/assets/custom/objects/object_triforce_piece_2/image new file mode 100644 index 000000000..2a8a62348 Binary files /dev/null and b/soh/assets/custom/objects/object_triforce_piece_2/image differ diff --git a/soh/assets/custom/objects/object_triforce_piece_2/image_copy b/soh/assets/custom/objects/object_triforce_piece_2/image_copy new file mode 100644 index 000000000..2a8a62348 Binary files /dev/null and b/soh/assets/custom/objects/object_triforce_piece_2/image_copy differ diff --git a/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_Green_mat b/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_Green_mat new file mode 100644 index 000000000..94418f24f --- /dev/null +++ b/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_Green_mat @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_f3dlite_triforce_surface b/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_f3dlite_triforce_surface deleted file mode 100644 index d903f00bb..000000000 --- a/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_f3dlite_triforce_surface +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_silver_001 b/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_silver_001 new file mode 100644 index 000000000..6a9be7bec --- /dev/null +++ b/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_silver_001 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_2/noise_tex b/soh/assets/custom/objects/object_triforce_piece_2/noise_tex deleted file mode 100644 index a6d6cf945..000000000 Binary files a/soh/assets/custom/objects/object_triforce_piece_2/noise_tex and /dev/null differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Bark_64 b/soh/assets/custom/objects/object_xmas_tree/Bark_64 new file mode 100644 index 000000000..8f1b837cd Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Bark_64 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Bauble1Tex_B_32 b/soh/assets/custom/objects/object_xmas_tree/Bauble1Tex_B_32 new file mode 100644 index 000000000..5e28d8e82 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Bauble1Tex_B_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Bauble1Tex_G_32 b/soh/assets/custom/objects/object_xmas_tree/Bauble1Tex_G_32 new file mode 100644 index 000000000..a40393dbd Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Bauble1Tex_G_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Bauble1Tex_R_32 b/soh/assets/custom/objects/object_xmas_tree/Bauble1Tex_R_32 new file mode 100644 index 000000000..c2d49ae42 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Bauble1Tex_R_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Bauble2Tex_B_32 b/soh/assets/custom/objects/object_xmas_tree/Bauble2Tex_B_32 new file mode 100644 index 000000000..2596d8264 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Bauble2Tex_B_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Bauble2Tex_G_32 b/soh/assets/custom/objects/object_xmas_tree/Bauble2Tex_G_32 new file mode 100644 index 000000000..e6889fee4 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Bauble2Tex_G_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Bauble2Tex_R_32 b/soh/assets/custom/objects/object_xmas_tree/Bauble2Tex_R_32 new file mode 100644 index 000000000..aef353a27 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Bauble2Tex_R_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Bauble3Tex_B_32 b/soh/assets/custom/objects/object_xmas_tree/Bauble3Tex_B_32 new file mode 100644 index 000000000..8f9c96cb1 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Bauble3Tex_B_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Bauble3Tex_G_32 b/soh/assets/custom/objects/object_xmas_tree/Bauble3Tex_G_32 new file mode 100644 index 000000000..b8ce81e43 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Bauble3Tex_G_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Bauble3Tex_R_32 b/soh/assets/custom/objects/object_xmas_tree/Bauble3Tex_R_32 new file mode 100644 index 000000000..40394698f Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Bauble3Tex_R_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/GlowAlpha_64 b/soh/assets/custom/objects/object_xmas_tree/GlowAlpha_64 new file mode 100644 index 000000000..1682d9e6f Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/GlowAlpha_64 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/LeavesAlpha_64 b/soh/assets/custom/objects/object_xmas_tree/LeavesAlpha_64 new file mode 100644 index 000000000..e33491d5a Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/LeavesAlpha_64 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/LeavesAlpha_shaded_64 b/soh/assets/custom/objects/object_xmas_tree/LeavesAlpha_shaded_64 new file mode 100644 index 000000000..dca2158b4 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/LeavesAlpha_shaded_64 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Wrapping_B_32 b/soh/assets/custom/objects/object_xmas_tree/Wrapping_B_32 new file mode 100644 index 000000000..9d70aa720 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Wrapping_B_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Wrapping_B_64 b/soh/assets/custom/objects/object_xmas_tree/Wrapping_B_64 new file mode 100644 index 000000000..071e01a2d Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Wrapping_B_64 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Wrapping_G_32 b/soh/assets/custom/objects/object_xmas_tree/Wrapping_G_32 new file mode 100644 index 000000000..8fac0c1c4 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Wrapping_G_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Wrapping_G_64 b/soh/assets/custom/objects/object_xmas_tree/Wrapping_G_64 new file mode 100644 index 000000000..6c128dbee Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Wrapping_G_64 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Wrapping_R_32 b/soh/assets/custom/objects/object_xmas_tree/Wrapping_R_32 new file mode 100644 index 000000000..a61f3d386 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Wrapping_R_32 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/Wrapping_R_64 b/soh/assets/custom/objects/object_xmas_tree/Wrapping_R_64 new file mode 100644 index 000000000..d884c2ca6 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/Wrapping_R_64 differ diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL new file mode 100644 index 000000000..c354defda --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_0 new file mode 100644 index 000000000..bc1589a65 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_0 @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_1 new file mode 100644 index 000000000..ff14442dc --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_1 @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_2 new file mode 100644 index 000000000..ea5e79a96 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_2 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_3 new file mode 100644 index 000000000..4280e17a5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_tri_3 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_0 new file mode 100644 index 000000000..2d2b533a4 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_0 @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_1 new file mode 100644 index 000000000..2199d0779 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_1 @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_2 new file mode 100644 index 000000000..e0403545a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_2 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_3 new file mode 100644 index 000000000..ae1fba294 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor100DL_vtx_3 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL new file mode 100644 index 000000000..80f8fc81b --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_0 new file mode 100644 index 000000000..2a2601403 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_0 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_1 new file mode 100644 index 000000000..87dc5c7ca --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_1 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_2 new file mode 100644 index 000000000..d9d225ee1 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_2 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_3 new file mode 100644 index 000000000..010dfe669 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_3 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_4 new file mode 100644 index 000000000..34de1a10f --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_4 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_5 new file mode 100644 index 000000000..dbaef4a37 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_5 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_6 new file mode 100644 index 000000000..4b4aaa742 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_6 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_7 new file mode 100644 index 000000000..a3aa6c672 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_tri_7 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_0 new file mode 100644 index 000000000..189a72f78 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_0 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_1 new file mode 100644 index 000000000..491afaa21 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_1 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_2 new file mode 100644 index 000000000..1c86dfb20 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_2 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_3 new file mode 100644 index 000000000..fef6070e2 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_3 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_4 new file mode 100644 index 000000000..74ff37e83 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_4 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_5 new file mode 100644 index 000000000..e5347a692 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_5 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_6 new file mode 100644 index 000000000..57b0c83f5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_6 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_7 new file mode 100644 index 000000000..4eea9d31d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor10DL_vtx_7 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL new file mode 100644 index 000000000..cd83c25f8 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_0 new file mode 100644 index 000000000..7410becef --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_0 @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_1 new file mode 100644 index 000000000..782f5f9e1 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_1 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_2 new file mode 100644 index 000000000..46d90cfee --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_2 @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_3 new file mode 100644 index 000000000..fcae1cb60 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_3 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_4 new file mode 100644 index 000000000..cea2d4b01 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_4 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_5 new file mode 100644 index 000000000..8e6c88ddf --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_5 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_6 new file mode 100644 index 000000000..0c0928683 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_6 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_7 new file mode 100644 index 000000000..f56472810 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_7 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_8 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_8 new file mode 100644 index 000000000..8464121eb --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_8 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_9 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_9 new file mode 100644 index 000000000..a22341bdf --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_tri_9 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_0 new file mode 100644 index 000000000..c8a3028f5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_0 @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_1 new file mode 100644 index 000000000..d7bf03045 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_1 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_2 new file mode 100644 index 000000000..768baea65 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_2 @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_3 new file mode 100644 index 000000000..87d0b1315 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_3 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_4 new file mode 100644 index 000000000..8fb018224 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_4 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_5 new file mode 100644 index 000000000..76d9b788a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_5 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_6 new file mode 100644 index 000000000..60cef595c --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_6 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_7 new file mode 100644 index 000000000..e590fd848 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_7 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_8 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_8 new file mode 100644 index 000000000..505f171b0 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_8 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_9 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_9 new file mode 100644 index 000000000..50c131f9c --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor20DL_vtx_9 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL new file mode 100644 index 000000000..4e4fd95aa --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_0 new file mode 100644 index 000000000..1ee54492c --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_0 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_1 new file mode 100644 index 000000000..0efacf68a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_1 @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_2 new file mode 100644 index 000000000..e05cc11fb --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_2 @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_3 new file mode 100644 index 000000000..19917bd2e --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_3 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_4 new file mode 100644 index 000000000..f5f256b23 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_4 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_5 new file mode 100644 index 000000000..536d06f7a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_5 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_6 new file mode 100644 index 000000000..45568173a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_tri_6 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_0 new file mode 100644 index 000000000..509ed6529 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_0 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_1 new file mode 100644 index 000000000..49c0a080a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_1 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_2 new file mode 100644 index 000000000..c109c19f5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_2 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_3 new file mode 100644 index 000000000..c7c1e10a6 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_3 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_4 new file mode 100644 index 000000000..a26e55df1 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_4 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_5 new file mode 100644 index 000000000..d1177d633 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_5 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_6 new file mode 100644 index 000000000..d947223ad --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor30DL_vtx_6 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL new file mode 100644 index 000000000..9da99431f --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_0 new file mode 100644 index 000000000..f94c732e4 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_0 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_1 new file mode 100644 index 000000000..348919286 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_1 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_10 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_10 new file mode 100644 index 000000000..959b692d4 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_10 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_11 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_11 new file mode 100644 index 000000000..41fb8d2b9 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_11 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_12 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_12 new file mode 100644 index 000000000..8062b5a56 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_12 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_2 new file mode 100644 index 000000000..7c52dae86 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_2 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_3 new file mode 100644 index 000000000..af7892786 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_3 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_4 new file mode 100644 index 000000000..e662f6ed6 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_4 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_5 new file mode 100644 index 000000000..22b809b3f --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_5 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_6 new file mode 100644 index 000000000..1d845ad8a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_6 @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_7 new file mode 100644 index 000000000..12c90c209 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_7 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_8 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_8 new file mode 100644 index 000000000..bbd9078ce --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_8 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_9 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_9 new file mode 100644 index 000000000..11e6780ea --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_tri_9 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_0 new file mode 100644 index 000000000..8579d6fee --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_0 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_1 new file mode 100644 index 000000000..b0dcceeec --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_1 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_10 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_10 new file mode 100644 index 000000000..7d59969b3 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_10 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_11 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_11 new file mode 100644 index 000000000..ab7d95f64 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_11 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_12 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_12 new file mode 100644 index 000000000..514f00f38 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_12 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_2 new file mode 100644 index 000000000..7135901b7 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_2 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_3 new file mode 100644 index 000000000..874e86e45 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_3 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_4 new file mode 100644 index 000000000..8dcece79b --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_4 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_5 new file mode 100644 index 000000000..030415bf5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_5 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_6 new file mode 100644 index 000000000..5758decfe --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_6 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_7 new file mode 100644 index 000000000..7e171bd29 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_7 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_8 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_8 new file mode 100644 index 000000000..26f056a5f --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_8 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_9 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_9 new file mode 100644 index 000000000..878f90b20 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor40DL_vtx_9 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL new file mode 100644 index 000000000..537d98d5f --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_0 new file mode 100644 index 000000000..41e8cb3c9 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_0 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_1 new file mode 100644 index 000000000..0beb4cd5f --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_1 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_2 new file mode 100644 index 000000000..a33dc9689 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_2 @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_3 new file mode 100644 index 000000000..8cd67cdeb --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_3 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_4 new file mode 100644 index 000000000..f3cb40c18 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_4 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_5 new file mode 100644 index 000000000..28c1fa004 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_tri_5 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_0 new file mode 100644 index 000000000..4bbea8de4 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_0 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_1 new file mode 100644 index 000000000..c331cabed --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_1 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_2 new file mode 100644 index 000000000..62bb3dc53 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_2 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_3 new file mode 100644 index 000000000..135764c05 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_3 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_4 new file mode 100644 index 000000000..1066194fb --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_4 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_5 new file mode 100644 index 000000000..afec2ee78 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor50DL_vtx_5 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL new file mode 100644 index 000000000..fe51b9f6b --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_0 new file mode 100644 index 000000000..1d746dde9 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_0 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_1 new file mode 100644 index 000000000..095e5d8f1 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_1 @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_2 new file mode 100644 index 000000000..b1f3c81fc --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_2 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_3 new file mode 100644 index 000000000..e88a5cffe --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_3 @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_4 new file mode 100644 index 000000000..cbc9ce14a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_4 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_5 new file mode 100644 index 000000000..6646786c1 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_5 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_6 new file mode 100644 index 000000000..a2a881763 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_6 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_7 new file mode 100644 index 000000000..2a5440b86 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_7 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_8 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_8 new file mode 100644 index 000000000..245daae2b --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_8 @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_9 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_9 new file mode 100644 index 000000000..34a3d0b55 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_tri_9 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_0 new file mode 100644 index 000000000..b33405eec --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_0 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_1 new file mode 100644 index 000000000..ff671566d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_1 @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_2 new file mode 100644 index 000000000..21358026e --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_2 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_3 new file mode 100644 index 000000000..831547972 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_3 @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_4 new file mode 100644 index 000000000..c591133b8 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_4 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_5 new file mode 100644 index 000000000..d111addad --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_5 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_6 new file mode 100644 index 000000000..2684a5759 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_6 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_7 new file mode 100644 index 000000000..a2ab6b20a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_7 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_8 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_8 new file mode 100644 index 000000000..fed438e57 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_8 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_9 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_9 new file mode 100644 index 000000000..9f8e178ed --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor60DL_vtx_9 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL new file mode 100644 index 000000000..9d7a0b749 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_0 new file mode 100644 index 000000000..540a5e3e3 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_0 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_1 new file mode 100644 index 000000000..3b27e35d2 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_1 @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_2 new file mode 100644 index 000000000..29326efac --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_2 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_3 new file mode 100644 index 000000000..83850278e --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_3 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_4 new file mode 100644 index 000000000..38401ac4f --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_4 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_5 new file mode 100644 index 000000000..ef0b4397d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_5 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_6 new file mode 100644 index 000000000..0df608625 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_tri_6 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_0 new file mode 100644 index 000000000..6e115c0bb --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_0 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_1 new file mode 100644 index 000000000..ce6941dc9 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_1 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_2 new file mode 100644 index 000000000..56624ffb0 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_2 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_3 new file mode 100644 index 000000000..ec758ec91 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_3 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_4 new file mode 100644 index 000000000..3e9cc0ff4 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_4 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_5 new file mode 100644 index 000000000..ac28e8fb0 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_5 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_6 new file mode 100644 index 000000000..0cf3101e0 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor70DL_vtx_6 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL new file mode 100644 index 000000000..ba14f553d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_0 new file mode 100644 index 000000000..233c5e5b7 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_0 @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_1 new file mode 100644 index 000000000..160f85e33 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_1 @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_2 new file mode 100644 index 000000000..712db2ead --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_2 @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_3 new file mode 100644 index 000000000..567f9bbfa --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_3 @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_4 new file mode 100644 index 000000000..ed60abbb9 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_4 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_5 new file mode 100644 index 000000000..9d0125976 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_5 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_6 new file mode 100644 index 000000000..011391daa --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_6 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_7 new file mode 100644 index 000000000..ae4be6ebd --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_7 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_8 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_8 new file mode 100644 index 000000000..b7a34eb1d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_tri_8 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_0 new file mode 100644 index 000000000..4e538463f --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_0 @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_1 new file mode 100644 index 000000000..1c7a6b49c --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_1 @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_2 new file mode 100644 index 000000000..2717d84f0 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_2 @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_3 new file mode 100644 index 000000000..e5f479fc4 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_3 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_4 new file mode 100644 index 000000000..5e1500678 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_4 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_5 new file mode 100644 index 000000000..e00362088 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_5 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_6 new file mode 100644 index 000000000..e67313e14 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_6 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_7 new file mode 100644 index 000000000..7acc51f2a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_7 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_8 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_8 new file mode 100644 index 000000000..c3ac2ef36 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor80DL_vtx_8 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL new file mode 100644 index 000000000..f96deccc4 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_0 new file mode 100644 index 000000000..aaf575f3e --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_0 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_1 new file mode 100644 index 000000000..17e2bbb14 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_1 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_2 new file mode 100644 index 000000000..45f70fca8 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_2 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_3 new file mode 100644 index 000000000..501540e99 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_3 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_4 new file mode 100644 index 000000000..6aa20edeb --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_4 @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_5 new file mode 100644 index 000000000..9f5515c3b --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_5 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_6 new file mode 100644 index 000000000..e8b2ebe15 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_6 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_7 new file mode 100644 index 000000000..e8686cfeb --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_tri_7 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_0 new file mode 100644 index 000000000..4bf94f75a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_0 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_1 new file mode 100644 index 000000000..a3e163984 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_1 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_2 new file mode 100644 index 000000000..5075a9732 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_2 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_3 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_3 new file mode 100644 index 000000000..7b0fce1b2 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_3 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_4 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_4 new file mode 100644 index 000000000..240d7afe2 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_4 @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_5 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_5 new file mode 100644 index 000000000..adf5dfa9b --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_5 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_6 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_6 new file mode 100644 index 000000000..5e02e04d8 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_6 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_7 b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_7 new file mode 100644 index 000000000..f92e3d98d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasDecor90DL_vtx_7 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL b/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL new file mode 100644 index 000000000..2bad08d2d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_tri_0 new file mode 100644 index 000000000..79b9903f8 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_tri_0 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_tri_1 new file mode 100644 index 000000000..0f82cf893 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_tri_1 @@ -0,0 +1,390 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_vtx_0 new file mode 100644 index 000000000..a990fc5af --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_vtx_0 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_vtx_1 new file mode 100644 index 000000000..746770594 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasStarDL_vtx_1 @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL new file mode 100644 index 000000000..c343cfe2a --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_tri_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_tri_0 new file mode 100644 index 000000000..38cdbe014 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_tri_0 @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_tri_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_tri_1 new file mode 100644 index 000000000..ff4e066a5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_tri_1 @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_tri_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_tri_2 new file mode 100644 index 000000000..561d3ac5e --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_tri_2 @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_vtx_0 b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_vtx_0 new file mode 100644 index 000000000..94e5e1fef --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_vtx_0 @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_vtx_1 b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_vtx_1 new file mode 100644 index 000000000..01ed88a14 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_vtx_1 @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_vtx_2 b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_vtx_2 new file mode 100644 index 000000000..fd03778f8 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/gXmasTreeDL_vtx_2 @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/hilite_melon b/soh/assets/custom/objects/object_xmas_tree/hilite_melon new file mode 100644 index 000000000..df1d605b3 Binary files /dev/null and b/soh/assets/custom/objects/object_xmas_tree/hilite_melon differ diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_B_64 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_B_64 new file mode 100644 index 000000000..e2cb1c6af --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_B_64 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_G_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_G_32 new file mode 100644 index 000000000..5f67d4de1 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_G_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_R_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_R_32 new file mode 100644 index 000000000..f330997c2 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_R_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_R_64 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_R_64 new file mode 100644 index 000000000..ddba85e48 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor100DL_f3dlite_Wrapping_R_64 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble1_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble1_B new file mode 100644 index 000000000..0562ad514 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble1_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble1_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble1_G new file mode 100644 index 000000000..424720964 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble1_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble1_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble1_R new file mode 100644 index 000000000..ed8997bac --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble1_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble2_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble2_B new file mode 100644 index 000000000..a2fb86662 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble2_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble2_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble2_G new file mode 100644 index 000000000..a3ebffce5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble2_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble2_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble2_R new file mode 100644 index 000000000..780bee1c5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble2_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble3_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble3_G new file mode 100644 index 000000000..5ec29067d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble3_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble3_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble3_R new file mode 100644 index 000000000..6bfad5f53 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor10DL_f3dlite_Bauble3_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble1_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble1_B new file mode 100644 index 000000000..0562ad514 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble1_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble1_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble1_R new file mode 100644 index 000000000..ed8997bac --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble1_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble2_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble2_B new file mode 100644 index 000000000..a2fb86662 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble2_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble2_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble2_G new file mode 100644 index 000000000..a3ebffce5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble2_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble2_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble2_R new file mode 100644 index 000000000..780bee1c5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble2_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble3_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble3_B new file mode 100644 index 000000000..7af3c0fdf --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble3_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble3_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble3_G new file mode 100644 index 000000000..5ec29067d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Bauble3_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Wrapping_B_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Wrapping_B_32 new file mode 100644 index 000000000..1425245e0 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Wrapping_B_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Wrapping_G_64 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Wrapping_G_64 new file mode 100644 index 000000000..c3a973f39 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Wrapping_G_64 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Wrapping_R_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Wrapping_R_32 new file mode 100644 index 000000000..f330997c2 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor20DL_f3dlite_Wrapping_R_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble1_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble1_B new file mode 100644 index 000000000..0562ad514 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble1_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble1_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble1_G new file mode 100644 index 000000000..424720964 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble1_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble1_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble1_R new file mode 100644 index 000000000..ed8997bac --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble1_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble2_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble2_B new file mode 100644 index 000000000..a2fb86662 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble2_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble2_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble2_G new file mode 100644 index 000000000..a3ebffce5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble2_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble3_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble3_B new file mode 100644 index 000000000..7af3c0fdf --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble3_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble3_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble3_R new file mode 100644 index 000000000..6bfad5f53 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor30DL_f3dlite_Bauble3_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble1_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble1_B new file mode 100644 index 000000000..0562ad514 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble1_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble1_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble1_R new file mode 100644 index 000000000..ed8997bac --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble1_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble2_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble2_B new file mode 100644 index 000000000..a2fb86662 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble2_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble2_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble2_G new file mode 100644 index 000000000..a3ebffce5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble2_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble2_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble2_R new file mode 100644 index 000000000..780bee1c5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble2_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble3_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble3_B new file mode 100644 index 000000000..7af3c0fdf --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble3_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble3_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble3_G new file mode 100644 index 000000000..5ec29067d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble3_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble3_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble3_R new file mode 100644 index 000000000..6bfad5f53 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Bauble3_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_B_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_B_32 new file mode 100644 index 000000000..1425245e0 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_B_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_G_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_G_32 new file mode 100644 index 000000000..5f67d4de1 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_G_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_G_64 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_G_64 new file mode 100644 index 000000000..c3a973f39 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_G_64 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_R_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_R_32 new file mode 100644 index 000000000..f330997c2 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_R_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_R_64 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_R_64 new file mode 100644 index 000000000..ddba85e48 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor40DL_f3dlite_Wrapping_R_64 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble1_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble1_B new file mode 100644 index 000000000..0562ad514 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble1_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble1_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble1_G new file mode 100644 index 000000000..424720964 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble1_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble2_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble2_G new file mode 100644 index 000000000..a3ebffce5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble2_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble2_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble2_R new file mode 100644 index 000000000..780bee1c5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble2_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble3_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble3_B new file mode 100644 index 000000000..7af3c0fdf --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble3_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble3_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble3_R new file mode 100644 index 000000000..6bfad5f53 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor50DL_f3dlite_Bauble3_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble1_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble1_B new file mode 100644 index 000000000..0562ad514 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble1_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble1_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble1_G new file mode 100644 index 000000000..424720964 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble1_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble1_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble1_R new file mode 100644 index 000000000..ed8997bac --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble1_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble2_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble2_G new file mode 100644 index 000000000..a3ebffce5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble2_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble2_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble2_R new file mode 100644 index 000000000..780bee1c5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble2_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble3_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble3_G new file mode 100644 index 000000000..5ec29067d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Bauble3_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_B_64 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_B_64 new file mode 100644 index 000000000..e2cb1c6af --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_B_64 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_G_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_G_32 new file mode 100644 index 000000000..5f67d4de1 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_G_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_R_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_R_32 new file mode 100644 index 000000000..f330997c2 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_R_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_R_64 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_R_64 new file mode 100644 index 000000000..ddba85e48 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor60DL_f3dlite_Wrapping_R_64 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble1_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble1_G new file mode 100644 index 000000000..424720964 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble1_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble1_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble1_R new file mode 100644 index 000000000..ed8997bac --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble1_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble2_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble2_G new file mode 100644 index 000000000..a3ebffce5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble2_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble2_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble2_R new file mode 100644 index 000000000..780bee1c5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble2_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble3_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble3_B new file mode 100644 index 000000000..7af3c0fdf --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble3_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble3_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble3_G new file mode 100644 index 000000000..5ec29067d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble3_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble3_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble3_R new file mode 100644 index 000000000..6bfad5f53 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor70DL_f3dlite_Bauble3_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble1_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble1_B new file mode 100644 index 000000000..0562ad514 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble1_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble1_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble1_R new file mode 100644 index 000000000..ed8997bac --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble1_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble2_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble2_G new file mode 100644 index 000000000..a3ebffce5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble2_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble3_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble3_B new file mode 100644 index 000000000..7af3c0fdf --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble3_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble3_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble3_G new file mode 100644 index 000000000..5ec29067d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble3_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble3_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble3_R new file mode 100644 index 000000000..6bfad5f53 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Bauble3_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Wrapping_B_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Wrapping_B_32 new file mode 100644 index 000000000..1425245e0 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Wrapping_B_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Wrapping_G_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Wrapping_G_32 new file mode 100644 index 000000000..5f67d4de1 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Wrapping_G_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Wrapping_R_32 b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Wrapping_R_32 new file mode 100644 index 000000000..f330997c2 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor80DL_f3dlite_Wrapping_R_32 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble1_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble1_B new file mode 100644 index 000000000..0562ad514 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble1_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble1_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble1_G new file mode 100644 index 000000000..424720964 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble1_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble1_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble1_R new file mode 100644 index 000000000..ed8997bac --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble1_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble2_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble2_B new file mode 100644 index 000000000..a2fb86662 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble2_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble2_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble2_R new file mode 100644 index 000000000..780bee1c5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble2_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble3_B b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble3_B new file mode 100644 index 000000000..7af3c0fdf --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble3_B @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble3_G b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble3_G new file mode 100644 index 000000000..5ec29067d --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble3_G @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble3_R b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble3_R new file mode 100644 index 000000000..6bfad5f53 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasDecor90DL_f3dlite_Bauble3_R @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasStarDL_f3dlite_Glow b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasStarDL_f3dlite_Glow new file mode 100644 index 000000000..381668c5c --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasStarDL_f3dlite_Glow @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_f3dlite_triforce_edges b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasStarDL_f3dlite_OrnamentGold similarity index 72% rename from soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_f3dlite_triforce_edges rename to soh/assets/custom/objects/object_xmas_tree/mat_gXmasStarDL_f3dlite_OrnamentGold index 5968068f5..b657da8a7 100644 --- a/soh/assets/custom/objects/object_triforce_piece_2/mat_gTriforcePiece2DL_f3dlite_triforce_edges +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasStarDL_f3dlite_OrnamentGold @@ -1,21 +1,21 @@ - + - + - + - + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasTreeDL_f3dlite_TreeBrown b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasTreeDL_f3dlite_TreeBrown new file mode 100644 index 000000000..37fdb10d2 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasTreeDL_f3dlite_TreeBrown @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasTreeDL_f3dlite_TreeGreen b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasTreeDL_f3dlite_TreeGreen new file mode 100644 index 000000000..119341c70 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasTreeDL_f3dlite_TreeGreen @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_xmas_tree/mat_gXmasTreeDL_f3dlite_TreeTip b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasTreeDL_f3dlite_TreeTip new file mode 100644 index 000000000..9baaadbf5 --- /dev/null +++ b/soh/assets/custom/objects/object_xmas_tree/mat_gXmasTreeDL_f3dlite_TreeTip @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/textures/parameter_static/gTriforcePiece.rgba32.png b/soh/assets/custom/textures/parameter_static/gTriforcePiece.rgba32.png index cc67b6a13..eace659af 100644 Binary files a/soh/assets/custom/textures/parameter_static/gTriforcePiece.rgba32.png and b/soh/assets/custom/textures/parameter_static/gTriforcePiece.rgba32.png differ diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h index 3d3cfab2e..40761fbc5 100644 --- a/soh/assets/soh_assets.h +++ b/soh/assets/soh_assets.h @@ -8,6 +8,27 @@ // On Mac, not using aligned resource names was causing crashes in release builds // objects +#define dgLinkAdultHatTrimDL "__OTR__objects/object_festivehats/gLinkAdultHatTrimDL" +static const ALIGN_ASSET(2) char gLinkAdultHatTrimDL[] = dgLinkAdultHatTrimDL; + +#define dgLinkAdultPompomDL "__OTR__objects/object_festivehats/gLinkAdultPompomDL" +static const ALIGN_ASSET(2) char gLinkAdultPompomDL[] = dgLinkAdultPompomDL; + +#define dgLinkChildHatTrimDL "__OTR__objects/object_festivehats/gLinkChildHatTrimDL" +static const ALIGN_ASSET(2) char gLinkChildHatTrimDL[] = dgLinkChildHatTrimDL; + +#define dgPaperCrownGenericDL "__OTR__objects/object_festivehats/gPaperCrownGenericDL" +static const ALIGN_ASSET(2) char gPaperCrownGenericDL[] = dgPaperCrownGenericDL; + +#define dgSantaHatGenericDL "__OTR__objects/object_festivehats/gSantaHatGenericDL" +static const ALIGN_ASSET(2) char gSantaHatGenericDL[] = dgSantaHatGenericDL; + +#define dgHorseAntlersDL "__OTR__objects/object_festivehats/gHorseAntlersDL" +static const ALIGN_ASSET(2) char gHorseAntlersDL[] = dgHorseAntlersDL; + +#define dgEponaRudolphHatDL "__OTR__objects/object_festivehats/gEponaRudolphHatDL" +static const ALIGN_ASSET(2) char gEponaRudolphHatDL[] = dgEponaRudolphHatDL; + #define dgChristmasGreenTreasureChestFrontTex "__OTR__objects/object_box/gChristmasGreenTreasureChestFrontTex" static const ALIGN_ASSET(2) char gChristmasGreenTreasureChestFrontTex[] = dgChristmasGreenTreasureChestFrontTex; @@ -38,6 +59,9 @@ static const ALIGN_ASSET(2) char gSkullTreasureChestFrontTex[] = dgSkullTreasure #define dgSkullTreasureChestSideAndTopTex "__OTR__objects/object_box/gSkullTreasureChestSideAndTopTex" static const ALIGN_ASSET(2) char gSkullTreasureChestSideAndTopTex[] = dgSkullTreasureChestSideAndTopTex; +#define dgSnowballDL "__OTR__objects/custom_snowball/snowball" +static const ALIGN_ASSET(2) char gSnowballDL[] = dgSnowballDL; + #define dgTitleRandomizerSubtitleTex "__OTR__objects/object_mag/gTitleRandomizerSubtitleTex" static const ALIGN_ASSET(2) char gTitleRandomizerSubtitleTex[] = dgTitleRandomizerSubtitleTex; @@ -83,6 +107,57 @@ static const ALIGN_ASSET(2) char gFishingPoleGiDL[] = dgFishingPoleGiDL; #define dgMysteryItemDL "__OTR__objects/object_mystery_item/gMysteryItemDL" static const ALIGN_ASSET(2) char gMysteryItemDL[] = dgMysteryItemDL; +#define dgXmasTreeDL "__OTR__objects/object_xmas_tree/gXmasTreeDL" +static const ALIGN_ASSET(2) char gXmasTreeDL[] = dgXmasTreeDL; + +#define dgXmasDecor10DL "__OTR__objects/object_xmas_tree/gXmasDecor10DL" +static const ALIGN_ASSET(2) char gXmasDecor10DL[] = dgXmasDecor10DL; + +#define dgXmasDecor20DL "__OTR__objects/object_xmas_tree/gXmasDecor20DL" +static const ALIGN_ASSET(2) char gXmasDecor20DL[] = dgXmasDecor20DL; + +#define dgXmasDecor30DL "__OTR__objects/object_xmas_tree/gXmasDecor30DL" +static const ALIGN_ASSET(2) char gXmasDecor30DL[] = dgXmasDecor30DL; + +#define dgXmasDecor40DL "__OTR__objects/object_xmas_tree/gXmasDecor40DL" +static const ALIGN_ASSET(2) char gXmasDecor40DL[] = dgXmasDecor40DL; + +#define dgXmasDecor50DL "__OTR__objects/object_xmas_tree/gXmasDecor50DL" +static const ALIGN_ASSET(2) char gXmasDecor50DL[] = dgXmasDecor50DL; + +#define dgXmasDecor60DL "__OTR__objects/object_xmas_tree/gXmasDecor60DL" +static const ALIGN_ASSET(2) char gXmasDecor60DL[] = dgXmasDecor60DL; + +#define dgXmasDecor70DL "__OTR__objects/object_xmas_tree/gXmasDecor70DL" +static const ALIGN_ASSET(2) char gXmasDecor70DL[] = dgXmasDecor70DL; + +#define dgXmasDecor80DL "__OTR__objects/object_xmas_tree/gXmasDecor80DL" +static const ALIGN_ASSET(2) char gXmasDecor80DL[] = dgXmasDecor80DL; + +#define dgXmasDecor90DL "__OTR__objects/object_xmas_tree/gXmasDecor90DL" +static const ALIGN_ASSET(2) char gXmasDecor90DL[] = dgXmasDecor90DL; + +#define dgXmasDecor100DL "__OTR__objects/object_xmas_tree/gXmasDecor100DL" +static const ALIGN_ASSET(2) char gXmasDecor100DL[] = dgXmasDecor100DL; + +#define dgXmasStarDL "__OTR__objects/object_xmas_tree/gXmasStarDL" +static const ALIGN_ASSET(2) char gXmasStarDL[] = dgXmasStarDL; + +#define dgPenguinDL "__OTR__objects/object_penguin/object_penguin_DL" +static const ALIGN_ASSET(2) char gPenguinDL[] = dgPenguinDL; + +#define dgKakarikoDecorDL "__OTR__objects/object_kakariko_decor/gKakarikoDecorDL" +static const ALIGN_ASSET(2) char gKakarikoDecorDL[] = dgKakarikoDecorDL; + +#define dgTempleOfTimeDecorDL "__OTR__objects/object_temple_of_time_decor/gTempleOfTimeDecorDL" +static const ALIGN_ASSET(2) char gTempleOfTimeDecorDL[] = dgTempleOfTimeDecorDL; + +#define dgKakarikoChildDecorDL "__OTR__objects/object_kakariko_decor/gKakarikoChildDecorDL" +static const ALIGN_ASSET(2) char gKakarikoChildDecorDL[] = dgKakarikoChildDecorDL; + +#define dgKakarikoAdultDecorDL "__OTR__objects/object_kakariko_decor/gKakarikoAdultDecorDL" +static const ALIGN_ASSET(2) char gKakarikoAdultDecorDL[] = dgKakarikoAdultDecorDL; + // overlays #define dgOptionsDividerChangeLangVtx "__OTR__overlays/ovl_file_choose/gOptionsDividerChangeLangVtx" static const ALIGN_ASSET(2) char gOptionsDividerChangeLangVtx[] = dgOptionsDividerChangeLangVtx; diff --git a/soh/assets/sources/TempleOfTime_DL.blend b/soh/assets/sources/TempleOfTime_DL.blend new file mode 100644 index 000000000..38500e0d7 Binary files /dev/null and b/soh/assets/sources/TempleOfTime_DL.blend differ diff --git a/soh/include/functions.h b/soh/include/functions.h index d4b47b60c..80de37858 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -2461,6 +2461,9 @@ s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projected void PauseWarp_HandleSelection(); void PauseWarp_Execute(); +// Exposing for Roc's Feather +void func_80838940(Player* this, LinkAnimationHeader* anim, f32 arg2, PlayState* play, u16 sfxId); + // #endregion #ifdef __cplusplus diff --git a/soh/include/z64actor.h b/soh/include/z64actor.h index 156f1d679..08ca0032f 100644 --- a/soh/include/z64actor.h +++ b/soh/include/z64actor.h @@ -182,6 +182,7 @@ typedef struct Actor { /* 0x13C */ char dbgPad[0x10]; // Padding that only exists in the debug rom // #region SOH [General] /* */ u8 maximumHealth; // Max health value for use with health bars, set on actor init + /* */ u8 isShiny; // #endregion } Actor; // size = 0x14C diff --git a/soh/include/z64item.h b/soh/include/z64item.h index 214d82711..1731800aa 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -306,6 +306,7 @@ typedef enum { /* 0x99 */ ITEM_STICK_UPGRADE_30, /* 0x9A */ ITEM_NUT_UPGRADE_30, /* 0x9B */ ITEM_NUT_UPGRADE_40, + /* 0x9C */ ITEM_SHIP, // SOH [Enhancement] Added to enable custom item gives /* 0xFC */ ITEM_LAST_USED = 0xFC, /* 0xFE */ ITEM_NONE_FE = 0xFE, /* 0xFF */ ITEM_NONE = 0xFF @@ -455,9 +456,10 @@ typedef enum { /* 0x79 */ GI_NUT_UPGRADE_30, /* 0x7A */ GI_NUT_UPGRADE_40, /* 0x7B */ GI_BULLET_BAG_50, - /* 0x7C */ GI_ICE_TRAP, // freezes link when opened from a chest - /* 0x7D */ GI_TEXT_0, // no model appears over Link, shows text id 0 (pocket egg) - /* 0x84 */ GI_MAX + /* 0x7C */ GI_SHIP, // SOH [Enhancement] Added to enable custom item gives + /* 0x7D */ GI_ICE_TRAP, // freezes link when opened from a chest + /* 0x7E */ GI_TEXT_0, // no model appears over Link, shows text id 0 (pocket egg) + /* 0x7F */ GI_MAX } GetItemID; typedef enum { diff --git a/soh/soh/ActorDB.cpp b/soh/soh/ActorDB.cpp index de2538888..4a629c53d 100644 --- a/soh/soh/ActorDB.cpp +++ b/soh/soh/ActorDB.cpp @@ -609,8 +609,59 @@ static ActorDBInit EnPartnerInit = { }; extern "C" s16 gEnPartnerId; +#include "src/overlays/actors/ovl_En_Snowball/z_en_snowball.h" +static ActorDBInit EnSnowballInit = { + "En_Snowball", + "Snowball", + ACTORCAT_ITEMACTION, + (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_DRAGGED_BY_HOOKSHOT | ACTOR_FLAG_CAN_PRESS_SWITCH), + OBJECT_GAMEPLAY_KEEP, + sizeof(EnSnowball), + (ActorFunc)EnSnowball_Init, + (ActorFunc)EnSnowball_Destroy, + (ActorFunc)EnSnowball_Update, + (ActorFunc)EnSnowball_Draw, + nullptr, +}; +extern "C" s16 gEnSnowballId; + +#include "src/overlays/actors/ovl_En_ChristmasTree/z_en_christmastree.h" +static ActorDBInit EnChristmasTreeInit = { + "En_ChristmasTree", + "Christmas Tree", + ACTORCAT_PROP, + (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED), + OBJECT_GAMEPLAY_KEEP, + sizeof(EnChristmasTree), + (ActorFunc)EnChristmasTree_Init, + (ActorFunc)EnChristmasTree_Destroy, + (ActorFunc)EnChristmasTree_Update, + (ActorFunc)EnChristmasTree_Draw, + nullptr, +}; +extern "C" s16 gEnChristmasTreeId; + +#include "src/overlays/actors/ovl_En_ChristmasDeco/z_en_christmasdeco.h" +static ActorDBInit EnChristmasDecoInit = { + "En_ChristmasDeco", + "Christmas Decos", + ACTORCAT_PROP, + (ACTOR_FLAG_DRAW_WHILE_CULLED), + OBJECT_GAMEPLAY_KEEP, + sizeof(EnChristmasDeco), + (ActorFunc)EnChristmasDeco_Init, + (ActorFunc)EnChristmasDeco_Destroy, + (ActorFunc)EnChristmasDeco_Update, + (ActorFunc)EnChristmasDeco_Draw, + nullptr, +}; +extern "C" s16 gEnChristmasDecoId; + void ActorDB::AddBuiltInCustomActors() { gEnPartnerId = ActorDB::Instance->AddEntry(EnPartnerInit).entry.id; + gEnSnowballId = ActorDB::Instance->AddEntry(EnSnowballInit).entry.id; + gEnChristmasTreeId = ActorDB::Instance->AddEntry(EnChristmasTreeInit).entry.id; + gEnChristmasDecoId = ActorDB::Instance->AddEntry(EnChristmasDecoInit).entry.id; } extern "C" ActorDBEntry* ActorDB_Retrieve(const int id) { diff --git a/soh/soh/Enhancements/Holiday/AGreenSpoon.cpp b/soh/soh/Enhancements/Holiday/AGreenSpoon.cpp new file mode 100644 index 000000000..6885aa345 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/AGreenSpoon.cpp @@ -0,0 +1,82 @@ +#include "Holiday.hpp" +#include "soh/Enhancements/randomizer/3drando/random.hpp" +#include "soh/frame_interpolation.h" +#include "soh_assets.h" +#include "overlays/actors/ovl_En_Gs/z_en_gs.h" +#include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +extern PlayState* gPlayState; +} + +#define AUTHOR "AGreenSpoon" +#define CVAR(v) "gHoliday." AUTHOR "." v + +void EnGs_Evil(EnGs* enGs, PlayState* play) { + Player* player = GET_PLAYER(gPlayState); + if (!(player->stateFlags1 & PLAYER_STATE1_TALKING)) { + Math_ApproachS(&enGs->actor.shape.rot.y, enGs->actor.yawTowardsPlayer, 5, 0xBB8); + + if (enGs->unk_200 <= 0) { + float offsetDistance = 10.0f; + float offsetX = sinf(enGs->actor.shape.rot.y * (M_PI / 0x8000)) * offsetDistance; + float offsetZ = cosf(enGs->actor.shape.rot.y * (M_PI / 0x8000)) * offsetDistance; + + float dx = player->actor.world.pos.x - (enGs->actor.world.pos.x + offsetX); + float dy = player->actor.world.pos.y - 10.0f - enGs->actor.world.pos.y; + float dz = player->actor.world.pos.z - (enGs->actor.world.pos.z + offsetZ); + + s16 rotX = atan2f(dy, sqrtf(dx * dx + dz * dz)) * (0x8000 / M_PI); + s16 rotY = enGs->actor.shape.rot.y; + s16 rotZ = atan2f(dx, dz) * (0x8000 / M_PI); + + Actor* actor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, + enGs->actor.world.pos.x + offsetX, + enGs->actor.world.pos.y + 40.0f, + enGs->actor.world.pos.z + offsetZ, + rotX, rotY, rotZ, + 100, false); + + EnClearTag* clearTag = (EnClearTag*)actor; + + enGs->unk_200 = 5; + } + + enGs->unk_200--; + } +} + +static void OnConfigurationChanged() { + COND_ID_HOOK(OnOpenText, 0x2053, CVarGetInteger(CVAR("EvilGossipStone"), 0), [](u16 * textId, bool* loadFromMessageTable) { + Actor* actor = Actor_FindNearby(gPlayState, &GET_PLAYER(gPlayState)->actor, ACTOR_EN_GS, ACTORCAT_PROP, 100.0f); + + if (actor == NULL) { + return; + } + + EnGs* gs = (EnGs*)actor; + gs->actionFunc = EnGs_Evil; + }); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + if (UIWidgets::EnhancementCheckbox("Evil Gossip Stone", CVAR("EvilGossipStone"))) { + OnConfigurationChanged(); + } + UIWidgets::Tooltip("Don't you dare talk to them."); +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + OnConfigurationChanged(); + // #endregion + + // TODO: Anything you want to run once on startup +} + +// TODO: Uncomment this line to enable the mod +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/Archez.cpp b/soh/soh/Enhancements/Holiday/Archez.cpp new file mode 100644 index 000000000..0665c9d29 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Archez.cpp @@ -0,0 +1,123 @@ +#include "Holiday.hpp" +#include "Archez.h" +#include +#include "soh/UIWidgets.hpp" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +#include "objects/object_goroiwa/object_goroiwa.h" + +extern PlayState* gPlayState; +} + +#define AUTHOR "Archez" +#define CVAR(v) "gHoliday." AUTHOR "." v + +static bool sSkipNextLimb = false; +static bool sSkipNextSkeleton = false; + +extern "C" void SkipOverrideNextLimb() { + sSkipNextLimb = true; +} + +extern "C" void SkipOverrideNextSkeleton() { + sSkipNextSkeleton = true; +} + +extern "C" void ClearOverrideSkips() { + sSkipNextLimb = false; + sSkipNextSkeleton = false; +} + +static void ConfigurationChanged() { + COND_VB_SHOULD(VB_DRAW_SKEL_LIMB, CVarGetInteger(CVAR("SnowGolems"), 0), { + if (!*should) { + return; + } + + if (sSkipNextLimb) { + sSkipNextLimb = false; + return; + } + + if (sSkipNextSkeleton) { + return; + } + + Gfx** gfxP = va_arg(args, Gfx**); + void* dList = va_arg(args, void*); + + *should = false; + + Gfx* gfx = *gfxP; + + Matrix_Push(); + + Matrix_Scale(0.55f, 0.55f, 0.55f, MTXMODE_APPLY); + gSPMatrix(gfx++, Matrix_NewMtx(gPlayState->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_LOAD); + gSPDisplayList(gfx++, (Gfx*)gSnowballDL); + + Matrix_Pop(); + + gSPMatrix(gfx++, Matrix_NewMtx(gPlayState->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_LOAD); + + *gfxP = gfx; + }); + + COND_VB_SHOULD(VB_DRAW_SKEL_FLEX_LIMB, CVarGetInteger(CVAR("SnowGolems"), 0), { + if (!*should) { + return; + } + + if (sSkipNextLimb) { + sSkipNextLimb = false; + } + + if (sSkipNextSkeleton) { + return; + } + + Gfx** gfxP = va_arg(args, Gfx**); + void* dList = va_arg(args, void*); + Mtx* mtx = va_arg(args, Mtx*); + + *should = false; + + Gfx* gfx = *gfxP; + MtxF mtxF; + + Matrix_Push(); + Matrix_MtxToMtxF(mtx, &mtxF); + Matrix_Put(&mtxF); + + Matrix_Scale(0.55f, 0.55f, 0.55f, MTXMODE_APPLY); + gSPMatrix(gfx++, Matrix_NewMtx(gPlayState->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_LOAD); + gSPDisplayList(gfx++, (Gfx*)gSnowballDL); + + Matrix_Pop(); + + gSPMatrix(gfx++, mtx, G_MTX_LOAD); + + *gfxP = gfx; + }); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + + if (UIWidgets::EnhancementCheckbox("Snow Golems", CVAR("SnowGolems"))) { + ConfigurationChanged(); + } + UIWidgets::Tooltip("Overrides most charactor skeletons with snow balls to make them look like Snow Golems"); +} + +static void RegisterMod() { + ConfigurationChanged(); +} + +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/Archez.h b/soh/soh/Enhancements/Holiday/Archez.h new file mode 100644 index 000000000..93bd27457 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Archez.h @@ -0,0 +1,17 @@ +#ifndef ARCHEZ_H +#define ARCHEZ_H + + +#ifdef __cplusplus +extern "C" { +#endif + +void SkipOverrideNextLimb(); +void SkipOverrideNextSkeleton(); +void ClearOverrideSkips(); + +#ifdef __cplusplus +} +#endif + +#endif // ARCHEZ_H diff --git a/soh/soh/Enhancements/Holiday/Caladius.cpp b/soh/soh/Enhancements/Holiday/Caladius.cpp new file mode 100644 index 000000000..5eb632a5d --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Caladius.cpp @@ -0,0 +1,319 @@ +#include "Caladius.h" +#include "Holiday.hpp" +#include "soh/Notification/Notification.h" +#include "soh/Enhancements/gameplaystats.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/custom-message/CustomMessageManager.h" +#include "soh/Enhancements/randomizer/randomizer.h" +#include "soh/frame_interpolation.h" +#include "soh_assets.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +extern PlayState* gPlayState; +uint64_t GetUnixTimestamp(); +} + +#define AUTHOR "Caladius" +#define CVAR(v) "gHoliday." AUTHOR "." v + +bool isFeverDisabled = false; +bool isExchangeDisabled = false; +static float fontScale = 1.0f; + +extern GetItemEntry vanillaQueuedItemEntry; + +std::vector boulderList = { ACTOR_OBJ_BOMBIWA, ACTOR_BG_ICE_SHELTER, ACTOR_EN_ISHI, ACTOR_OBJ_HAMISHI }; + +std::string formatTimestampIceTrapFever(uint32_t value) { + uint32_t sec = value / 10; + uint32_t hh = sec / 3600; + uint32_t mm = (sec - hh * 3600) / 60; + uint32_t ss = sec - hh * 3600 - mm * 60; + return fmt::format("{}:{:0>2}:{:0>2}", hh, mm, ss); +} + +void OnTimeOver() { + gSaveContext.health = 0; +} + +int32_t calculateRemainingTime() { + int32_t timeRemaining = + ((gSaveContext.sohStats.count[COUNT_ICE_TRAPS] * (CVarGetInteger(CVAR("ExtendTimer"), 0) * 600)) + + (CVarGetInteger(CVAR("StartTimer"), 0) * 600) - GAMEPLAYSTAT_TOTAL_TIME); + if (timeRemaining <= 0) { + OnTimeOver(); + timeRemaining = 0; + } + return timeRemaining; +} + +s32 ActorSnapToFloor(Actor* refActor, PlayState* play, f32 arg2) { + CollisionPoly* poly; + Vec3f pos; + s32 bgId; + f32 floorY; + + pos.x = refActor->world.pos.x; + pos.y = refActor->world.pos.y + 30.0f; + pos.z = refActor->world.pos.z; + floorY = BgCheck_EntityRaycastFloor4(&play->colCtx, &poly, &bgId, refActor, &pos); + if (floorY > BGCHECK_Y_MIN) { + refActor->world.pos.y = floorY + arg2; + Math_Vec3f_Copy(&refActor->home.pos, &refActor->world.pos); + } + return refActor->world.pos.y; +} + +void RandomizeBoulder(Actor* refActor) { + Actor* actor = (Actor*) refActor; + int16_t param = actor->params; + int32_t yAdj = 0; + uint32_t roll = rand() % boulderList.size(); + if (boulderList[roll] == ACTOR_EN_ISHI) { + param = 3; + } + yAdj = ActorSnapToFloor(actor, gPlayState, 0.0f); + + Actor_Spawn(&gPlayState->actorCtx, gPlayState, boulderList[roll], actor->world.pos.x, ActorSnapToFloor(actor, gPlayState, 0.0f), + actor->world.pos.z, 0, 0, 0, param, false); + Actor_Kill(actor); +} + +bool spawningPresents = false; + +struct Present { +}; + +std::unordered_map presents; + +void Present_Init(Actor* actor, PlayState* play) { + Present present; + presents[actor] = present; + + actor->gravity = -1; + Actor_MoveXZGravity(actor); + actor->shape.rot.y = Random(0, 0xFFFF); + + Actor_UpdateBgCheckInfo(play, actor, 10.0f, 10.0f, 0.0f, 0xFF); +} + +void Present_Update(Actor* actor, PlayState* play) { + Present* present = &presents[actor]; + + if (actor->xzDistToPlayer < 50.0f && actor->yDistToPlayer < 50.0f) { + uint32_t giftsCollected = CVarGetInteger(CVAR("GiftsCollected"), 0); + giftsCollected++; + CVarSetInteger(CVAR("GiftsCollected"), giftsCollected); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + std::string msg = std::to_string(giftsCollected).c_str(); + msg += " Gifts in Inventory."; + Notification::Emit({ + .itemIcon = "RG_TRIFORCE_PIECE", + .message = msg, + .messageColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f), + }); + Actor_Kill(actor); + } +} + +void Present_Draw(Actor* actor, PlayState* play) { + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + Matrix_Scale(30.0f, 30.0f, 30.0f, MTXMODE_APPLY); + Matrix_Translate(49.20f, 0.0f, -106.60f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor100DL); + + CLOSE_DISPS(play->state.gfxCtx); +} + +void Present_Destroy(Actor* actor, PlayState* play) { + presents.erase(actor); +} + +static void OnPresentChange() { + isExchangeDisabled = !CVarGetInteger(CVAR("OrnExch.Enabled"), 0); + COND_ID_HOOK(OnOpenText, 0x204A, CVarGetInteger(CVAR("OrnExch.Enabled"), 0), [](u16 * textId, bool* loadFromMessageTable) { + auto messageEntry = CustomMessage(""); + bool reduceGifts = false; + uint32_t giftsCollected = CVarGetInteger(CVAR("GiftsCollected"), 0); + uint32_t giftsRequired = CVarGetInteger(CVAR("OrnExch.Amount"), 15); + if (giftsCollected < giftsRequired) { + std::string msg = "You only have %r " + std::to_string(giftsCollected) + "%w If you bring me %g" + + std::to_string(giftsRequired) + "%w I'll give you a reward!"; + messageEntry = CustomMessage(msg); + } else { + std::string msg = "A present? And %g" + std::to_string(giftsRequired) + + "%w to boot? Here's your reward, bring me more if you find any!"; + messageEntry = CustomMessage(msg); + reduceGifts = true; + } + messageEntry.AutoFormat(); + messageEntry.LoadIntoFont(); + *loadFromMessageTable = false; + + if (reduceGifts) { + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_TRIFORCE_PIECE).GetGIEntry_Copy(); + giftsCollected -= giftsRequired; + CVarSetInteger(CVAR("GiftsCollected"), giftsCollected); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + + std::string msg = std::to_string(giftsCollected).c_str(); + msg += " Gifts in Inventory."; + Notification::Emit({ + .itemIcon = "RG_TRIFORCE_PIECE", + .message = msg + }); + } + }); + + COND_HOOK(OnSceneSpawnActors, CVarGetInteger(CVAR("OrnExch.Enabled"), 0), []() { + presents.clear(); + Vec3f pos; + static CollisionPoly presentPoly; + static f32 raycastResult; + pos.y = 9999.0f; + int spawnAttempts = 0; + while (spawnAttempts < 20) { + if (GET_PLAYER(gPlayState) != nullptr) { + pos.x = GET_PLAYER(gPlayState)->actor.world.pos.x; + pos.z = GET_PLAYER(gPlayState)->actor.world.pos.z; + } else { + pos.x = 0; + pos.z = 0; + } + // X/Z anywhere from -1000.0 to +1000.0 from player + pos.x += (float)(Random(0, 20000)) - 10000.0f; + pos.z += (float)(Random(0, 20000)) - 10000.0f; + + raycastResult = BgCheck_AnyRaycastFloor1(&gPlayState->colCtx, &presentPoly, &pos); + + if (raycastResult > BGCHECK_Y_MIN) { + spawningPresents = true; + Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_OE2, pos.x, raycastResult, pos.z, 0, 0, 0, 0, false); + spawningPresents = false; + // break; + } + + spawnAttempts++; + } + }); + + COND_ID_HOOK(ShouldActorInit, ACTOR_EN_OE2, CVarGetInteger(CVAR("OrnExch.Enabled"), 0), [](void* actorRef, bool* should) { + Actor* actor = (Actor*)actorRef; + if (spawningPresents) { + actor->init = Present_Init; + actor->update = Present_Update; + actor->draw = Present_Draw; + actor->destroy = Present_Destroy; + } + }); +} + +static void OnBlitzChange() { + COND_HOOK(OnSceneSpawnActors, CVarGetInteger(CVAR("Blitz.Enabled"), 0), []() { + if (!gPlayState) { + return; + } + ActorListEntry boulders = gPlayState->actorCtx.actorLists[ACTORCAT_PROP]; + Actor* currentActor = boulders.head; + if (currentActor != nullptr) { + while (currentActor != nullptr) { + for (auto& boulderActor : boulderList) { + if (currentActor->id == boulderActor) { + RandomizeBoulder(currentActor); + } + } + currentActor = currentActor->next; + } + } + }); +} + +static void OnFeverConfigurationChanged() { + isFeverDisabled = !CVarGetInteger(CVAR("Fever.Enabled"), 0); + fontScale = CVarGetFloat(CVAR("FontScale"), 1.0f); + if (fontScale < 1.0f) { + fontScale = 1.0f; + } + if (CVarGetInteger(CVAR("ExtendTimer"), 0) < 1) { + CVarSetInteger(CVAR("ExtendTimer"), 1); + } + if (CVarGetInteger(CVAR("StartTimer"), 0) < 1) { + CVarSetInteger(CVAR("StartTimer"), 1); + } +} + +void CaladiusWindow::Draw() { + if (!CVarGetInteger(CVAR("Fever.Enabled"), 0)) { + return; + } + + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f); + ImGui::Begin("TimerDisplay", nullptr, ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoNav | + ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoDocking | + ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoScrollWithMouse | + ImGuiWindowFlags_NoScrollbar); + ImGui::SetWindowFontScale(fontScale); + ImGui::Text(formatTimestampIceTrapFever(calculateRemainingTime()).c_str()); + ImGui::End(); + + ImGui::PopStyleColor(2); + ImGui::PopStyleVar(1); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + if (UIWidgets::EnhancementCheckbox("Holiday Fever", CVAR("Fever.Enabled"))) { + OnFeverConfigurationChanged(); + } + UIWidgets::Tooltip("Can you beat your objective before the Fever sets in?/n" + "- Obtaining Ice Traps extends your timer."); + if (CVarGetInteger(CVAR("Fever.Enabled"), 0)) { + if (UIWidgets::EnhancementSliderFloat("", "##FontScale", CVAR("FontScale"), + 1.0f, 5.0f, "Font: %.1fx", 1.0f, false, false, isFeverDisabled)) { + OnFeverConfigurationChanged(); + } + UIWidgets::PaddedEnhancementSliderInt("Starting Timer: %d minutes", "##StartTime", CVAR("StartTimer"), + 5, 30, "", 15, true, true, false, isFeverDisabled); + UIWidgets::PaddedEnhancementSliderInt("Time Extensions: %d minutes", "##ExtendTime", CVAR("ExtendTimer"), + 1, 10, "", 5, true, true, false, isFeverDisabled); + } + UIWidgets::PaddedSeparator(); + + if (UIWidgets::EnhancementCheckbox("Boulder Blitz", CVAR("Blitz.Enabled"))) { + OnBlitzChange(); + } + UIWidgets::Tooltip("Boulders will randomly be replaced with other boulder types."); + UIWidgets::PaddedSeparator(); + + if (UIWidgets::EnhancementCheckbox("Ornament Exchange", CVAR("OrnExch.Enabled"))) { + OnPresentChange(); + } + UIWidgets::Tooltip("See Malon as Young Link in Lon Lon Ranch to exchange Gifts for Ornaments!"); + if (CVarGetInteger(CVAR("OrnExch.Enabled"), 0)) { + UIWidgets::PaddedEnhancementSliderInt("Gifts Required: %d Gifts", "##GiftsReq", CVAR("OrnExch.Amount"), + 5, 30, "", 15, true, true, false, isExchangeDisabled); + } +} + + +static void RegisterMod() { + OnFeverConfigurationChanged(); + OnBlitzChange(); + OnPresentChange(); +} + +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/Caladius.h b/soh/soh/Enhancements/Holiday/Caladius.h new file mode 100644 index 000000000..4bbd1ad8e --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Caladius.h @@ -0,0 +1,11 @@ +#include + +class CaladiusWindow : public Ship::GuiWindow { + public: + using GuiWindow::GuiWindow; + + void InitElement() override {}; + void DrawElement() override {}; + void Draw() override; + void UpdateElement() override {}; +}; \ No newline at end of file diff --git a/soh/soh/Enhancements/Holiday/Example.cpp b/soh/soh/Enhancements/Holiday/Example.cpp new file mode 100644 index 000000000..235738811 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Example.cpp @@ -0,0 +1,45 @@ +#include "Holiday.hpp" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +extern PlayState* gPlayState; + +// TODO: Include anything you need here from C land +} + +// TODO: Change this to YourName +#define AUTHOR "Example" +#define CVAR(v) "gHoliday." AUTHOR "." v + +static void OnConfigurationChanged() { + // TODO: Register any hooks or things that need to run on startup and when the main CVar is toggled + // Note: Hooks should be registered/unregistered depending on the CVar state (Use COND_HOOK or COND_ID_HOOK) + + // COND_HOOK(OnSceneSpawnActors, CVarGetInteger(CVAR("Enabled"), 0), []() { + // // Spawn your own actors? + // }); + + // COND_ID_HOOK(OnActorInit, ACTOR_OBJ_TSUBO, CVarGetInteger(CVAR("DoSomethingWithPots"), 0), [](void* actorRef) { + // // Do something with pots? + // }); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + if (UIWidgets::EnhancementCheckbox("DoSomethingWithPots", CVAR("DoSomethingWithPots"))) { + OnConfigurationChanged(); + } +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + OnConfigurationChanged(); + // #endregion + + // TODO: Anything you want to run once on startup +} + +// TODO: Uncomment this line to enable the mod +// static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/Fredomato.cpp b/soh/soh/Enhancements/Holiday/Fredomato.cpp new file mode 100644 index 000000000..df33ccfe8 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Fredomato.cpp @@ -0,0 +1,492 @@ +#include "Holiday.hpp" +#include +#include "soh/UIWidgets.hpp" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "objects/object_dog/object_dog.h" +#include "soh/frame_interpolation.h" +#include "soh/Enhancements/randomizer/3drando/random.hpp" +#include "soh/Enhancements/randomizer/3drando/location_access.hpp" +#include "soh/Enhancements/randomizer/entrance.h" +#include "soh/Enhancements/custom-collectible/CustomCollectible.h" +#include "soh/Notification/Notification.h" +#include "soh/Enhancements/nametag.h" + +#include "objects/gameplay_field_keep/gameplay_field_keep.h" +#include "objects/gameplay_keep/gameplay_keep.h" +#include "objects/object_md/object_md.h" +#include "objects/object_trap/object_trap.h" +#include "objects/object_toryo/object_toryo.h" +#include "src/overlays/actors/ovl_Door_Ana/z_door_ana.h" +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" + +extern PlayState* gPlayState; +void DoorAna_SetupAction(DoorAna* doorAna, DoorAnaActionFunc actionFunc); +void DoorAna_GrabPlayer(DoorAna* doorAna, PlayState* play); +} +extern GetItemEntry vanillaQueuedItemEntry; + +#define AUTHOR "Fredomato" +#define CVAR(v) "gHoliday." AUTHOR "." v + +static CollisionPoly snowballPoly; +static f32 raycastResult; + +const s16 entrances[] = { + 0x0000, 0x0209, 0x0004, 0x0242, 0x0028, 0x0221, 0x0169, 0x0215, 0x0165, 0x024A, 0x0010, 0x021D, 0x0082, 0x01E1, 0x0037, 0x0205, + 0x0098, 0x02A6, 0x0088, 0x03D4, 0x0008, 0x03A8, 0x0467, 0x023D, 0x0433, 0x0443, 0x0437, 0x0447, 0x009C, 0x033C, 0x00C9, 0x026A, + 0x00C1, 0x0266, 0x0043, 0x03CC, 0x045F, 0x0309, 0x03A0, 0x03D0, 0x007E, 0x026E, 0x0530, 0x01D1, 0x0507, 0x03BC, 0x0388, 0x02A2, + 0x0063, 0x01D5, 0x0528, 0x03C0, 0x043B, 0x0067, 0x02FD, 0x0349, 0x0550, 0x04EE, 0x039C, 0x0345, 0x05C8, 0x05DC, 0x0072, 0x034D, + 0x030D, 0x0355, 0x037C, 0x03FC, 0x0380, 0x03C4, 0x004F, 0x0378, 0x02F9, 0x042F, 0x05D0, 0x05D4, 0x052C, 0x03B8, 0x016D, 0x01CD, + 0x00B7, 0x0201, 0x003B, 0x0463, 0x0588, 0x057C, 0x0578, 0x0340, 0x04C2, 0x03E8, 0x04BE, 0x0482, 0x0315, 0x045B, 0x0371, 0x0394, + 0x0272, 0x0211, 0x0053, 0x0472, 0x0453, 0x0351, 0x0384, 0x044B, 0x03EC, 0x04FF, 0x0700, 0x0800, 0x0701, 0x0801, 0x0702, 0x0802, + 0x0703, 0x0803, 0x0704, 0x0804, 0x0705, 0x0805, 0x0706, 0x0806, 0x0707, 0x0807, 0x0708, 0x0808, 0x0709, 0x0809, 0x070A, 0x080A, + 0x070B, 0x080B, 0x080C, 0x070D, 0x080D, 0x070E, 0x080E, 0x070F, 0x080F, 0x0710, 0x0711, 0x0811, 0x0712, 0x0812, + 0x0713, 0x0813, 0x0714, 0x0814, 0x0715, 0x0815, 0x0716, 0x0816, 0x0717, 0x0817, 0x0718, 0x0818, 0x0719, 0x0819, 0x081A, + 0x071B, 0x081B, 0x071C, 0x081C, 0x071D, 0x081D, 0x071E, 0x081E, 0x071F, 0x081F, 0x0720, 0x0820, 0x004B, 0x035D, 0x031C, 0x0361, + 0x002D, 0x050B, 0x044F, 0x0359, 0x05E0, 0x020D, 0x011E, 0x0286, 0x04E2, 0x04D6, 0x01DD, 0x04DA, 0x00FC, 0x01A9, 0x0185, 0x04DE, + 0x0102, 0x0189, 0x0117, 0x018D, 0x0276, 0x01FD, 0x00DB, 0x017D, 0x00EA, 0x0181, 0x0157, 0x01F9, 0x0328, 0x0560, 0x0129, 0x022D, + 0x0130, 0x03AC, 0x0123, 0x0365, 0x00B1, 0x0033, 0x0138, 0x025A, 0x0171, 0x025E, 0x00E4, 0x0195, 0x013D, 0x0191, 0x014D, 0x01B9, + 0x0246, 0x01C1, 0x0147, 0x01BD, 0x0108, 0x019D, 0x0225, 0x01A1, 0x0219, 0x027E, 0x0554, 0x00BB, 0x0282, 0x0600, 0x04F6, 0x0604, + 0x01F1, 0x0568, 0x05F4, 0x040F, 0x0252, 0x040B, 0x00C5, 0x0301, 0x0407, 0x000C, 0x024E, 0x0305, 0x0175, 0x0417, 0x0423, 0x008D, + 0x02F5, 0x0413, 0x02B2, 0x0457, 0x047A, 0x010E, 0x0608, 0x0564, 0x060C, 0x0610, 0x0580 +}; + +static bool midoGrottoInit = false; +static SkelAnime midoSkelAnime; +static Vec3s midoJointTable[17]; +static Vec3s midoMorphTable[17]; +int FredsQuestWoodCollected = 0; +int FredsQuestWoodOnHand = 0; +static int lastDisplayedCount = -1; +static bool FredsQuestComplete = false; +static SkelAnime collectionPointSkelAnime; +static Vec3s collectionPointJointTable[17]; +static Vec3s collectionPointMorphTable[17]; +static std::string collectionPointNametag; + + +static void RandomGrotto_WaitOpen(DoorAna* doorAna, PlayState* play) { + if (!midoGrottoInit) { + midoGrottoInit = true; + SkelAnime_InitFlex(play, &midoSkelAnime, (FlexSkeletonHeader*)&gMidoSkel, (AnimationHeader*)&gMidoWalkingAnim, midoJointTable, midoMorphTable, 17); + } + SkelAnime_Update(&midoSkelAnime); + + Actor* actor = &doorAna->actor; + Player* player = GET_PLAYER(play); + if (!Player_InCsMode(play)) { + Math_SmoothStepToF(&actor->world.pos.x, player->actor.world.pos.x, 0.1f, 10.0f, 0.0f); + Math_SmoothStepToF(&actor->world.pos.z, player->actor.world.pos.z, 0.1f, 10.0f, 0.0f); + Math_SmoothStepToF(&actor->world.pos.y, player->actor.world.pos.y, 0.1f, 10.0f, 0.0f); + } + + Math_ApproachS(&doorAna->actor.shape.rot.y, doorAna->actor.yawTowardsPlayer, 5, 0xBB8); + + if (Math_StepToF(&actor->scale.x, 0.01f, 0.001f)) { + if ((actor->targetMode != 0) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (player->stateFlags1 & PLAYER_STATE1_FLOOR_DISABLED) && (player->av1.actionVar1 == 0)) { + play->nextEntranceIndex = RandomElement(entrances); + DoorAna_SetupAction((DoorAna*)actor, DoorAna_GrabPlayer); + } else { + if (!Player_InCsMode(play) && !(player->stateFlags1 & (PLAYER_STATE1_ON_HORSE | PLAYER_STATE1_IN_WATER)) && + actor->xzDistToPlayer <= 15.0f && -50.0f <= actor->yDistToPlayer && + actor->yDistToPlayer <= 15.0f) { + player->stateFlags1 |= PLAYER_STATE1_FLOOR_DISABLED; + actor->targetMode = 1; + } else { + actor->targetMode = 0; + } + } + } + Actor_SetScale(actor, actor->scale.x); +} + +static void RandomGrotto_Draw(Actor* actor, PlayState* play) { + if (!midoGrottoInit) { + return; + } + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGrottoDL); + + Matrix_Translate(0.0f, -2700.0f, 0.0f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + gSPSegment(POLY_OPA_DISP++, 0x08, (uintptr_t)gMidoEyeOpenTex); + func_80034BA0(play, &midoSkelAnime, NULL, NULL, actor, 255); + + CLOSE_DISPS(play->state.gfxCtx); +} + +static Vec3f FindValidPos(f32 distance) { + Vec3f pos; + pos.y = 9999.0f; + while (true) { + if (GET_PLAYER(gPlayState) != nullptr) { + pos.x = GET_PLAYER(gPlayState)->actor.world.pos.x; + pos.z = GET_PLAYER(gPlayState)->actor.world.pos.z; + } else { + pos.x = 0; + pos.z = 0; + } + pos.x += (float)(Random(0, distance)) - distance / 2; + pos.z += (float)(Random(0, distance)) - distance / 2; + + raycastResult = BgCheck_AnyRaycastFloor1(&gPlayState->colCtx, &snowballPoly, &pos); + + if (raycastResult > BGCHECK_Y_MIN) { + pos.y = raycastResult; + return pos; + } + } +} + +// TODO: If in hyrule field and treeChopper is on, teleport somewhere else in hyrule field +static void SpawnRandomGrotto() { + if ( + gPlayState->sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY || + gPlayState->sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT || + gPlayState->sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS + ) { + return; + } + + Vec3f pos = FindValidPos(2000.0f); + Actor* grotto = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_ANA, pos.x, pos.y, pos.z, 0, 0, 0, 0, false); + midoGrottoInit = false; + DoorAna_SetupAction((DoorAna*)grotto, RandomGrotto_WaitOpen); + grotto->draw = RandomGrotto_Draw; +} + +void SpawnStick(Vec3f pos) { + CustomCollectible::Spawn(pos.x, pos.y + 150.0f, pos.z, 0, CustomCollectible::KILL_ON_TOUCH | CustomCollectible::TOSS_ON_SPAWN, 0, [](Actor* actor, PlayState* play) { + FredsQuestWoodOnHand++; + Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + }, [](Actor* actor, PlayState* play) { + Matrix_Scale(40.0f, 40.0f, 40.0f, MTXMODE_APPLY); + for (int i = 4; i < 7; i++) { + Matrix_RotateZYX(800 * i, 0, 800 * i, MTXMODE_APPLY); + GetItem_Draw(play, GID_STICK); + } + }); +} + +Actor* specialTree = nullptr; + +void ChooseSpecialTree() { + Actor* actor = gPlayState->actorCtx.actorLists[ACTORCAT_PROP].head; + std::vector trees; + + specialTree = nullptr; + + while (actor != NULL) { + if (ACTOR_EN_WOOD02 == actor->id && actor->params < 10) { + trees.push_back(actor); + } + actor = actor->next; + } + + if (trees.size() <= 1) { + return; + } + + specialTree = trees[Random(0, trees.size() - 1)]; +} + +extern "C" bool HandleTreeBonk(Actor* actor) { + if (!CVarGetInteger(CVAR("FredsQuest.Enabled"), 0)) { + return false; + } + + int damage = 2; + // random chance of doing a crit + if (Random(0, 100) < 30) { + damage = 4; + } + + if (actor->colChkInfo.health - damage <= 0) { + if (specialTree == actor) { + ChooseSpecialTree(); + + for (int i = 0; i < CVarGetInteger(CVAR("FredsQuest.SpecialBreakDropRate"), 10); i++) { + SpawnStick(actor->world.pos); + } + } else { + for (int i = 0; i < CVarGetInteger(CVAR("FredsQuest.TreeBreakDropRate"), 3); i++) { + SpawnStick(actor->world.pos); + } + } + + // Move tree (instead of killing and spawning another) + actor->colChkInfo.health = 8; + Vec3f pos = FindValidPos(5000.0f); + actor->world.pos.x = pos.x; + actor->world.pos.y = pos.y; + actor->world.pos.z = pos.z; + } else { + actor->colChkInfo.health -= damage; + for (int i = 0; i < CVarGetInteger(CVAR("FredsQuest.TreeBonkDropRate"), 1); i++) { + SpawnStick(actor->world.pos); + } + } + + return true; +} + +void DrawCrazyTaxiArrow(Actor* actor, PlayState* play) { + if (specialTree == nullptr || !CVarGetInteger(CVAR("FredsQuest.CrazyTaxiArrow"), 0)) { + return; + } + + s16 yaw = Actor_WorldYawTowardActor(actor, specialTree); + Math_ApproachS(&actor->shape.rot.y, yaw, 5, 10000); + + OPEN_DISPS(gPlayState->state.gfxCtx); + + Gfx_SetupDL_4Xlu(gPlayState->state.gfxCtx); + + Matrix_Scale(50.0f, 50.0f, 50.0f, MTXMODE_APPLY); + Matrix_Translate(0.0f, 70.0f, 0.0f, MTXMODE_APPLY); + Matrix_RotateY(5.86f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, 255, 0, 255); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 255, 0, 255); + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gDebugArrowDL); + + CLOSE_DISPS(gPlayState->state.gfxCtx); +} + +void SpawnCrazyTaxiArrow() { + EnItem00* arrow = CustomCollectible::Spawn(0, 0, 0, 0, CustomCollectible::KEEP_ON_PLAYER, 0, NULL, NULL); + arrow->actor.draw = DrawCrazyTaxiArrow; +} + +void CollectionPoint_Update(Actor* actor, PlayState* play) { + EnItem00* enItem00 = (EnItem00*)actor; + + SkelAnime_Update(&collectionPointSkelAnime); + + if (FredsQuestComplete) { + return; + } + + if (lastDisplayedCount != FredsQuestWoodCollected) { + lastDisplayedCount = FredsQuestWoodCollected; + collectionPointNametag = "Bring me wood!"; + if (FredsQuestWoodCollected > 0) { + collectionPointNametag += std::string(" (") + std::to_string(FredsQuestWoodCollected) + "/" + std::to_string(CVarGetInteger(CVAR("FredsQuest.WoodNeeded"), 300)) + ")"; + } + NameTag_RemoveAllForActor(actor); + NameTag_RegisterForActorWithOptions(actor, collectionPointNametag.c_str(), { .yOffset = 100 }); + } + + if ((actor->xzDistToPlayer <= 200.0f) && (fabsf(actor->yDistToPlayer) <= fabsf(50.0f))) { + if (FredsQuestWoodOnHand) { + FredsQuestWoodCollected++; + FredsQuestWoodOnHand--; + Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + + if (FredsQuestWoodCollected >= CVarGetInteger(CVAR("FredsQuest.WoodNeeded"), 300)) { + FredsQuestComplete = true; + collectionPointNametag = "You're a hero!"; + NameTag_RemoveAllForActor(actor); + NameTag_RegisterForActorWithOptions(actor, collectionPointNametag.c_str(), { .yOffset = 100 }); + + if (IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_TRIFORCE_HUNT)) { + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_TRIFORCE_PIECE).GetGIEntry_Copy(); + } else { + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_HEART_CONTAINER).GetGIEntry_Copy(); + } + + } + } + } +} + +void CollectionPoint_Draw(Actor* actor, PlayState* play) { + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + SkelAnime_DrawSkeletonOpa(play, &collectionPointSkelAnime, NULL, NULL, actor); + + // For every 2% of the goal, draw a stick at a different angle, building a tree + Matrix_Scale(40.0f, 40.0f, 40.0f, MTXMODE_APPLY); + Matrix_Translate(0, 0, -300.0f, MTXMODE_APPLY); + for (int i = 0; i < FredsQuestWoodCollected / (CVarGetInteger(CVAR("FredsQuest.WoodNeeded"), 300) / 50); i++) { + float angle = 10 * i; + float radius = (50 - i) * 0.5f; // Radius decreases as it goes up + float height = 10.0f; // Incremental height + + Matrix_Translate(radius * cosf(angle), height, radius * sinf(angle), MTXMODE_APPLY); + Matrix_RotateY(angle, MTXMODE_APPLY); + GetItem_Draw(play, GID_STICK); + } + + CLOSE_DISPS(play->state.gfxCtx); +} + +void SpawnCollectionPoint() { + EnItem00* collectionPoint = CustomCollectible::Spawn(859.0f, 347.0f, 5185.0f, 0xB000, 0, 0, NULL, NULL); + collectionPoint->actor.update = CollectionPoint_Update; + collectionPoint->actor.draw = CollectionPoint_Draw; + collectionPoint->actor.flags |= ACTOR_FLAG_DRAW_WHILE_CULLED; + SkelAnime_InitFlex(gPlayState, &collectionPointSkelAnime, (FlexSkeletonHeader*)&object_toryo_Skel_007150, + (AnimationHeader*)&object_toryo_Anim_000E50, collectionPointJointTable, collectionPointMorphTable, 17); +} + +void RandomTrap_Update(Actor* actor, PlayState* play) { + EnItem00* enItem00 = (EnItem00*)actor; + + enItem00->unk_158--; + if (enItem00->unk_158 == 0) { + Actor_Kill(actor); + return; + } + + Math_ApproachS(&actor->world.rot.y, actor->yawTowardsPlayer, 5, 0xBB8); + actor->speedXZ = 3.0f; + + // TODO: CVar for speed + // Multiply speed by distance + actor->speedXZ += actor->xzDistToPlayer * 0.01f; + if (actor->xzDistToPlayer > 1000.0f && actor->velocity.y < -3.0f) { + actor->velocity.y += ABS(actor->yDistToPlayer) * 0.01f; + } + + actor->shape.rot.y += 0x1000; + + if ((actor->xzDistToPlayer <= 50.0f) && (fabsf(actor->yDistToPlayer) <= fabsf(20.0f))) { + // TODO: Random crowd control effect + GameInteractor::RawAction::KnockbackPlayer(5.0f); + Actor_Kill(actor); + } + + if (actor->gravity != 0.0f) { + Actor_MoveXZGravity(actor); + Actor_UpdateBgCheckInfo(play, actor, 20.0f, 15.0f, 15.0f, 0x1D); + } + + if (actor->bgCheckFlags & 0x0003) { + actor->speedXZ = 0.0f; + } +} + +void RandomTrap_Draw(Actor* actor, PlayState* play) { + OPEN_DISPS(play->state.gfxCtx); + + Matrix_Scale(4.0f, 4.0f, 4.0f, MTXMODE_APPLY); + Matrix_Translate(0, -200.0f, 0, MTXMODE_APPLY); + func_8002EBCC(actor, play, 1); + Gfx_DrawDListOpa(play, (Gfx*)gSlidingBladeTrapDL); + + CLOSE_DISPS(play->state.gfxCtx); +} + +void SpawnRandomTrap() { + Vec3f pos = FindValidPos(2000.0f); + EnItem00* randomTrap = CustomCollectible::Spawn(pos.x, pos.y, pos.z, 0, CustomCollectible::TOSS_ON_SPAWN, 0, NULL, NULL); + SoundSource_PlaySfxAtFixedWorldPos(gPlayState, &randomTrap->actor.world.pos, 20, NA_SE_EV_LIGHTNING); + randomTrap->actor.update = RandomTrap_Update; + randomTrap->actor.draw = RandomTrap_Draw; + randomTrap->unk_158 = 20 * CVarGetInteger(CVAR("RandomTraps.Lifetime"), 30); +} + +void OnSceneInit() { + // Reset wood collected + FredsQuestWoodCollected = 0; + FredsQuestWoodOnHand = 0; + lastDisplayedCount = -1; + FredsQuestComplete = false; + + if (gPlayState->sceneNum != SCENE_HYRULE_FIELD) { + return; + } + + ChooseSpecialTree(); + SpawnCrazyTaxiArrow(); + SpawnCollectionPoint(); +} + +static void ConfigurationChanged() { + COND_HOOK(OnSceneSpawnActors, CVarGetInteger(CVAR("FredsQuest.Enabled"), 0), OnSceneInit); + + COND_HOOK(OnPlayerUpdate, CVarGetInteger(CVAR("RandomTraps.Enabled"), 0), []() { + if (rand() % CVarGetInteger(CVAR("RandomTraps.SpawnChance"), 400) == 0) { + SpawnRandomTrap(); + } + }); + + COND_HOOK(OnPlayerUpdate, CVarGetInteger(CVAR("FredsQuest.Enabled"), 0), []() { + if (CVarGetInteger(CVAR("FredsQuest.EncumberedThreshold"), 60) == 0 || FredsQuestWoodOnHand <= CVarGetInteger(CVAR("FredsQuest.EncumberedThreshold"), 60)) { + GameInteractor::State::RunSpeedModifier = 0; + } else { + GameInteractor::State::RunSpeedModifier = -2; + } + }); + + COND_VB_SHOULD(VB_PLAYER_ROLL, CVarGetInteger(CVAR("FredsQuest.Enabled"), 0), { + if (FredsQuestWoodOnHand > CVarGetInteger(CVAR("FredsQuest.EncumberedThreshold"), 0)) { + *should = false; + } + }); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + + // UIWidgets::EnhancementSliderFloat("Xfloat", "Xfloat", CVAR("tmpxf"), 0.0f, 10.0f, "%.2f", 1.0f, false); + // UIWidgets::EnhancementSliderFloat("Yfloat", "Yfloat", CVAR("tmpyf"), 0.0f, 10.0f, "%.2f", 1.0f, false); + // UIWidgets::EnhancementSliderFloat("Zfloat", "Zfloat", CVAR("tmpzf"), 0.0f, 10.0f, "%.2f", 1.0f, false); + // UIWidgets::EnhancementSliderInt("Xs", "Xs", CVAR("tmpxs"), 0, UINT16_MAX, "%d", 1, false); + // UIWidgets::EnhancementSliderInt("Ys", "Ys", CVAR("tmpys"), 0, UINT16_MAX, "%d", 1, false); + // UIWidgets::EnhancementSliderInt("Zs", "Zs", CVAR("tmpzs"), 0, UINT16_MAX, "%d", 1, false); + if (UIWidgets::EnhancementCheckbox("Fred's Quest", CVAR("FredsQuest.Enabled"))) { + ConfigurationChanged(); + } + UIWidgets::Tooltip("Collect wood and bring it to the collection point in Hyrule Field for a small reward."); + if (CVarGetInteger(CVAR("FredsQuest.Enabled"), 0)) { + if (UIWidgets::EnhancementCheckbox("Crazy Taxi Arrow", CVAR("FredsQuest.CrazyTaxiArrow"))) { + ConfigurationChanged(); + } + if (UIWidgets::EnhancementSliderInt("Wood Needed", "##FredsQuest.WoodNeeded", CVAR("FredsQuest.WoodNeeded"), 0, 1000, "%d", 300, false)) { + ConfigurationChanged(); + } + if (UIWidgets::EnhancementSliderInt("Tree Bonk Drop Rate", "##FredsQuest.TreeBonkDropRate", CVAR("FredsQuest.TreeBonkDropRate"), 0, 10, "%d", 1, false)) { + ConfigurationChanged(); + } + if (UIWidgets::EnhancementSliderInt("Tree Break Drop Rate", "##FredsQuest.TreeBreakDropRate", CVAR("FredsQuest.TreeBreakDropRate"), 0, 50, "%d", 3, false)) { + ConfigurationChanged(); + } + if (UIWidgets::EnhancementSliderInt("Special Break Drop Rate", "##FredsQuest.SpecialBreakDropRate", CVAR("FredsQuest.SpecialBreakDropRate"), 0, 50, "%d", 10, false)) { + ConfigurationChanged(); + } + if (UIWidgets::EnhancementSliderInt("Encumbered Threshold", "##FredsQuest.EncumberedThreshold", CVAR("FredsQuest.EncumberedThreshold"), 0, 200, "%d", 60, false)) { + ConfigurationChanged(); + } + UIWidgets::Tooltip("If you have more than this many sticks, you will be encumbered and run slower. 0 for disabled"); + } + if (UIWidgets::EnhancementCheckbox("Random Traps", CVAR("RandomTraps.Enabled"))) { + ConfigurationChanged(); + } + UIWidgets::Tooltip("Random traps will spawn around you at a configurable rate. (Currently only knockback)"); + if (CVarGetInteger(CVAR("RandomTraps.Enabled"), 0)) { + if (UIWidgets::EnhancementSliderInt("Trap Lifetime (Seconds)", "##RandomTraps.Lifetime", CVAR("RandomTraps.Lifetime"), 0, 60, "%d", 30, false)) { + ConfigurationChanged(); + } + if (UIWidgets::EnhancementSliderInt("Spawn Chance", "##RandomTraps.SpawnChance", CVAR("RandomTraps.SpawnChance"), 40, 2000, "%d", 1000, false)) { + ConfigurationChanged(); + } + } +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + ConfigurationChanged(); + // #endregion +} + +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/Fredomato.h b/soh/soh/Enhancements/Holiday/Fredomato.h new file mode 100644 index 000000000..3479b3f1e --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Fredomato.h @@ -0,0 +1,18 @@ +#ifndef FRED_H +#define FRED_H + +#ifdef __cplusplus +extern int FredsQuestWoodCollected; +extern int FredsQuestWoodOnHand; + +extern "C" { +#include "z64actor.h" +#endif + +bool HandleTreeBonk(Actor* actor); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/soh/soh/Enhancements/Holiday/Grimey.cpp b/soh/soh/Enhancements/Holiday/Grimey.cpp new file mode 100644 index 000000000..094a355c2 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Grimey.cpp @@ -0,0 +1,230 @@ +#include "Holiday.hpp" +#include "soh/Enhancements/randomizer/3drando/random.hpp" +#include "soh/frame_interpolation.h" +#include "soh_assets.h" +#include "overlays/actors/ovl_En_Nutsball/z_en_nutsball.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" + +#include "objects/gameplay_field_keep/gameplay_field_keep.h" +extern PlayState* gPlayState; +void func_80ABBBA8(EnNutsball* nut, PlayState* play); +void EnNutsball_Draw(Actor* nut, PlayState* play); +} + +#define AUTHOR "Grimey" +#define CVAR(v) "gHoliday." AUTHOR "." v + +static bool spawningPenguins = false; + +typedef enum { + PENGUIN_STATE_IDLE, + PENGUIN_STATE_WALK, +} PenguinState; + +struct Penguin { + PenguinState state; + s16 timer; + s16 targetRot; +}; + +std::unordered_map penguins; + +void Penguin_Init(Actor* actor, PlayState* play) { + Penguin penguin; + penguin.state = PENGUIN_STATE_IDLE; + penguin.timer = 0; + actor->world.rot.y = penguin.targetRot = rand() % 0x10000; + penguins[actor] = penguin; + actor->gravity = -1.0f; + actor->flags &= ~ACTOR_FLAG_TARGETABLE; +} + +void Penguin_Update(Actor* actor, PlayState* play) { + Penguin* penguin = &penguins[actor]; + + if (penguin->timer <= 0) { + if (penguin->state == PENGUIN_STATE_IDLE) { + penguin->state = (PenguinState)(rand() % 3); + penguin->timer = rand() % (20 * 10) + (20 * 3); + } else { + penguin->state = PENGUIN_STATE_IDLE; + penguin->timer = rand() % (20 * 10) + (20 * 3); + } + } else { + penguin->timer--; + } + + if (rand() % 100 == 0) { + penguin->targetRot = rand() % 0x10000; + } + + switch (penguin->state) { + case PENGUIN_STATE_IDLE: + break; + case PENGUIN_STATE_WALK: + actor->speedXZ = 0.5f; + break; + } + + Math_SmoothStepToS(&actor->world.rot.y, penguin->targetRot, 1, 200, 0); + actor->shape.rot.y = actor->world.rot.y; + + if (actor->speedXZ < 0.0f) { + actor->speedXZ = 0.0f; + } + + Actor_MoveXZGravity(actor); + + Actor_UpdateBgCheckInfo(play, actor, 10.0f, 10.0f, 0.0f, 0xFF); +} + +void Penguin_Draw(Actor* actor, PlayState* play) { + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + Matrix_Scale(0.8f, 0.8f, 0.8f, MTXMODE_APPLY); + Matrix_Translate(0, 2000.0f, 0, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gPenguinDL); + + CLOSE_DISPS(play->state.gfxCtx); +} + +void Penguin_Destroy(Actor* actor, PlayState* play) { + penguins.erase(actor); +} + +static void OnConfigurationChanged() { + COND_HOOK(OnPlayerUpdate, CVarGetInteger(CVAR("Hailstorm"), 0), []() { + // Every frame has a 1/500 chance of spawning close hail + if (rand() % 500 == 0) { + int spawned = 0; + while (spawned < 1) { + Vec3f pos = GET_PLAYER(gPlayState)->actor.world.pos; + pos.x += (float)Random(0, 50) - 25.0f; + pos.z += (float)Random(0, 50) - 25.0f; + pos.y += 200.0f; + + Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_NUTSBALL, pos.x, pos.y, pos.z, 0, 0, 0, 0, false); + EnNutsball* nut = (EnNutsball*)actor; + nut->actor.draw = EnNutsball_Draw; + nut->actor.shape.rot.y = 0; + nut->timer = 0; + nut->actionFunc = func_80ABBBA8; + nut->actor.speedXZ = 0.0f; + nut->actor.gravity = -2.0f; + spawned++; + } + } + // Every frame has a 1/50 chance of spawning far hail + if (rand() % 50 == 0) { + int spawned = 0; + while (spawned < 1) { + Vec3f pos = GET_PLAYER(gPlayState)->actor.world.pos; + pos.x += (float)Random(0, 500) - 250.0f; + pos.z += (float)Random(0, 500) - 250.0f; + pos.y += 200.0f; + + Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_NUTSBALL, pos.x, pos.y, pos.z, 0, 0, 0, 0, false); + EnNutsball* nut = (EnNutsball*)actor; + nut->actor.draw = EnNutsball_Draw; + nut->actor.shape.rot.y = 0; + nut->timer = 0; + nut->actionFunc = func_80ABBBA8; + nut->actor.speedXZ = 0.0f; + nut->actor.gravity = -2.0f; + spawned++; + } + } + }); + + COND_HOOK(OnSceneSpawnActors, CVarGetInteger(CVAR("Penguins"), 0), []() { + penguins.clear(); + + if (gPlayState->sceneNum != SCENE_HYRULE_FIELD) { + return; + } + + static Vec3f huddlePos; + static Vec3f spawnPos; + static f32 raycastResult; + static CollisionPoly poly; + + spawningPenguins = true; + + int huddlesSpawned = 0; + while (huddlesSpawned < 10) { + huddlePos.x = (float)(Random( + (gPlayState->sceneNum == SCENE_HYRULE_FIELD ? -10000 : -2700) + 10000, + (gPlayState->sceneNum == SCENE_HYRULE_FIELD ? 5000 : 2000) + 10000 + ) - (float)10000.0f); + huddlePos.y = 5000; + huddlePos.z = (float)(Random( + (gPlayState->sceneNum == SCENE_HYRULE_FIELD ? -1000 : -2000) + 10000, + (gPlayState->sceneNum == SCENE_HYRULE_FIELD ? 15000 : 2000) + 10000 + ) - (float)10000.0f); + + if (BgCheck_AnyRaycastFloor1(&gPlayState->colCtx, &poly, &huddlePos) <= BGCHECK_Y_MIN) { + continue; + } + + // 5-10 + int huddleSize = rand() % 6 + 5; + int penguinsSpawned = 0; + while (penguinsSpawned < huddleSize) { + spawnPos.x = huddlePos.x + rand() % 100 - 50; + spawnPos.y = huddlePos.y; + spawnPos.z = huddlePos.z + rand() % 100 - 50; + + raycastResult = BgCheck_AnyRaycastFloor1(&gPlayState->colCtx, &poly, &spawnPos); + + if (raycastResult > BGCHECK_Y_MIN) { + Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_OE2, spawnPos.x, raycastResult, spawnPos.z, 0, 0, 0, 0, false); + penguinsSpawned++; + } + } + huddlesSpawned++; + } + + spawningPenguins = false; + }); + + COND_ID_HOOK(ShouldActorInit, ACTOR_EN_OE2, CVarGetInteger(CVAR("Penguins"), 0), [](void* actorRef, bool* should) { + Actor* actor = (Actor*)actorRef; + if (spawningPenguins) { + actor->init = Penguin_Init; + actor->update = Penguin_Update; + actor->draw = Penguin_Draw; + actor->destroy = Penguin_Destroy; + } + }); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + if (UIWidgets::EnhancementCheckbox("Penguins", CVAR("Penguins"))) { + OnConfigurationChanged(); + } + UIWidgets::Tooltip("Penguins will spawn in huddles throughout hyrule"); + if (UIWidgets::EnhancementCheckbox("Hailstorm", CVAR("Hailstorm"))) { + OnConfigurationChanged(); + } + UIWidgets::Tooltip("Ever persistent hailstorm throughout hyrule"); +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + OnConfigurationChanged(); + // #endregion + + // TODO: Anything you want to run once on startup +} + +// TODO: Uncomment this line to enable the mod +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/Holiday.hpp b/soh/soh/Enhancements/Holiday/Holiday.hpp new file mode 100644 index 000000000..9a6717060 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Holiday.hpp @@ -0,0 +1,38 @@ +#ifndef HOLIDAY_HPP +#define HOLIDAY_HPP + +#include +#include +#include +#include "soh/UIWidgets.hpp" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/cosmetics/CosmeticsEditor.h" + +inline std::vector> holidayDrawFuncs = {}; +inline std::vector> holidayRegisterFuncs = {}; + +inline void DrawHolidayMenu() { + if (ImGui::BeginMenu("Holiday")) { + for (auto& drawFunc : holidayDrawFuncs) { + ImGui::PushID(&drawFunc); + drawFunc(); + ImGui::PopID(); + } + ImGui::EndMenu(); + } +} + +inline void RegisterHoliday() { + for (auto& regFunc : holidayRegisterFuncs) { + regFunc(); + } +} + +struct Holiday { + Holiday(std::function drawFunc, std::function registerFunc) { + holidayDrawFuncs.push_back(drawFunc); + holidayRegisterFuncs.push_back(registerFunc); + } +}; + +#endif //HOLIDAY_HPP diff --git a/soh/soh/Enhancements/Holiday/LL.cpp b/soh/soh/Enhancements/Holiday/LL.cpp new file mode 100644 index 000000000..344d8043e --- /dev/null +++ b/soh/soh/Enhancements/Holiday/LL.cpp @@ -0,0 +1,129 @@ +#include "Holiday.hpp" +#include "LL.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +extern PlayState* gPlayState; + +// TODO: Include anything you need here from C land +} + +// TODO: Change this to YourName +#define AUTHOR "LL" +#define CVAR(v) "gHoliday." AUTHOR "." v + +static ImVec4 customColorZero = RAINBOW_PRESETS[0][0]; +static ImVec4 customColorOne = RAINBOW_PRESETS[0][1]; +static ImVec4 customColorMinusZero = RAINBOW_PRESETS[0][2]; +static ImVec4 customColorMinusOne = RAINBOW_PRESETS[0][3]; + +ImVec4 Color_LUSToImGui(Color_RGBA8 color) { + ImVec4 result; + + result.x = color.r / 255.0f; + result.y = color.g / 255.0f; + result.z = color.b / 255.0f; + result.w = color.a / 255.0f; + + return result; +} + +Color_RGBA8 Color_ImGuiToLUS(ImVec4 color) { + Color_RGBA8 result; + + result.r = static_cast(color.x * 255); + result.g = static_cast(color.y * 255); + result.b = static_cast(color.z * 255); + result.a = static_cast(color.w * 255); + + return result; +} + +static void OnConfigurationChanged() { + Color_RGBA8 c1 = CVarGetColor(CVAR("lCustomRainbow1"), Color_ImGuiToLUS(RAINBOW_PRESETS[0][0])); + Color_RGBA8 c2 = CVarGetColor(CVAR("lCustomRainbow2"), Color_ImGuiToLUS(RAINBOW_PRESETS[0][1])); + Color_RGBA8 c3 = CVarGetColor(CVAR("lCustomRainbow3"), Color_ImGuiToLUS(RAINBOW_PRESETS[0][2])); + Color_RGBA8 c4 = CVarGetColor(CVAR("lCustomRainbow4"), Color_ImGuiToLUS(RAINBOW_PRESETS[0][3])); + + customColorZero = Color_LUSToImGui((Color_RGBA8)c1); + customColorOne = Color_LUSToImGui((Color_RGBA8)c2); + customColorMinusZero = Color_LUSToImGui((Color_RGBA8)c3); + customColorMinusOne = Color_LUSToImGui((Color_RGBA8)c4); + + // TODO: Register any hooks or things that need to run on startup and when the main CVar is toggled + // Note: Hooks should be registered/unregistered depending on the CVar state (Use COND_HOOK or COND_ID_HOOK) + + // COND_HOOK(OnSceneSpawnActors, CVarGetInteger(CVAR("Enabled"), 0), []() { + // // Spawn your own actors? + // }); + + // COND_ID_HOOK(OnActorInit, ACTOR_OBJ_TSUBO, CVarGetInteger(CVAR("DoSomethingWithPots"), 0), [](void* actorRef) { + // // Do something with pots? + // }); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + if (ImGui::BeginMenu("Customize Rainbows")) { + UIWidgets::EnhancementCheckbox("Enable", CVAR("lEnableCustomRainbows")); + if (CVarGetInteger(CVAR("lEnableCustomRainbows"), 0)) { + ImGui::ColorEdit3("Color 1", (float*)&customColorZero, ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit3("Color 2", (float*)&customColorOne, ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit3("Color 3", (float*)&customColorMinusZero, ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit3("Color 4", (float*)&customColorMinusOne, ImGuiColorEditFlags_NoInputs); + + UIWidgets::PaddedText("Presets", true, false); + size_t rainbowPresetIdx = 0; + if (UIWidgets::EnhancementCombobox(CVAR("lCustomRainbowPreset"), RAINBOW_PRESET_NAMES, 0) && + (rainbowPresetIdx = CVarGetInteger(CVAR("lCustomRainbowPreset"), 0)) <= RAINBOW_PRESET_LEN) { //paranoia + customColorZero = RAINBOW_PRESETS[rainbowPresetIdx][0]; + customColorOne = RAINBOW_PRESETS[rainbowPresetIdx][1]; + customColorMinusZero = RAINBOW_PRESETS[rainbowPresetIdx][2]; + customColorMinusOne = RAINBOW_PRESETS[rainbowPresetIdx][3]; + } + + Color_RGBA8 color1, color2, color3, color4; + color1.r = static_cast(customColorZero.x * 255.0f); + color1.g = static_cast(customColorZero.y * 255.0f); + color1.b = static_cast(customColorZero.z * 255.0f); + + color2.r = static_cast(customColorOne.x * 255.0f); + color2.g = static_cast(customColorOne.y * 255.0f); + color2.b = static_cast(customColorOne.z * 255.0f); + + color3.r = static_cast(customColorMinusZero.x * 255.0f); + color3.g = static_cast(customColorMinusZero.y * 255.0f); + color3.b = static_cast(customColorMinusZero.z * 255.0f); + + color4.r = static_cast(customColorMinusOne.x * 255.0f); + color4.g = static_cast(customColorMinusOne.y * 255.0f); + color4.b = static_cast(customColorMinusOne.z * 255.0f); + + CVarSetColor(CVAR("lCustomRainbow1"), color1); + CVarSetColor(CVAR("lCustomRainbow2"), color2); + CVarSetColor(CVAR("lCustomRainbow3"), color3); + CVarSetColor(CVAR("lCustomRainbow4"), color4); + + OnConfigurationChanged(); + } + + ImGui::EndMenu(); + + } + //if (UIWidgets::EnhancementCheckbox("DoSomethingWithPots", CVAR("DoSomethingWithPots"))) { + // OnConfigurationChanged(); + //} +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + OnConfigurationChanged(); + // #endregion + + // TODO: Anything you want to run once on startup +} + +// TODO: Uncomment this line to enable the mod +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/LL.h b/soh/soh/Enhancements/Holiday/LL.h new file mode 100644 index 000000000..ba936b6c3 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/LL.h @@ -0,0 +1,86 @@ +#ifndef LL_H +#define LL_H + +#include "soh/Enhancements/cosmetics/CosmeticsEditor.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" + +const size_t RAINBOW_PRESET_LEN = 9; + +static const char* RAINBOW_PRESET_NAMES[RAINBOW_PRESET_LEN] = { + "Christmas", + "Transgender", + "Nonbinary", + "Bisexual", + "Lesbian", + "Gay (MLM)", + "Asexual", + "Brazil", + "Italy" +}; + +static const ImVec4 RAINBOW_PRESETS[RAINBOW_PRESET_LEN][4] = { + { //christmas + {0.0/255.0, 140.0/255.0, 69.0/255.0, 0}, + {205.0/255.0, 33.0/255.0, 42.0/255.0, 0}, + {0.0/255.0, 140.0/255.0, 69.0/255.0, 0}, + {205.0/255.0, 33.0/255.0, 42.0/255.0, 0} + }, + { //trans + {255.0/255.0, 255.0/255.0, 255.0/255.0, 0}, + {255.0/255.0, 159.0/255.0, 186.0/255.0, 0}, + {255.0/255.0, 255.0/255.0, 255.0/255.0, 0}, + {71.0/255.0, 186.0/255.0, 230.0/255.0, 0} + }, + + { //enby + {252.0/255.0, 244.0/255.0, 52.0/255.0, 0}, + {255.0/255.0, 255.0/255.0, 255.0/255.0, 0}, + {156.0/255.0, 89.0/255.0, 209.0/255.0, 0}, + {0.0/255.0, 0.0/255.0, 0.0/255.0, 0} + }, + + { //bi + {155.0/255.0, 79.0/255.0, 150.0/255.0, 0}, + {0.0/255.0, 56.0/255.0, 168.0/255.0, 0}, + {155.0/255.0, 79.0/255.0, 150.0/255.0, 0}, + {214.0/255.0, 2.0/255.0, 112.0/255.0, 0} + }, + + { //lesbian + {255.0/255.0, 255.0/255.0, 255.0/255.0, 0}, + {213.0/255.0, 45.0/255.0, 0.0/255.0, 0}, + {255.0/255.0, 255.0/255.0, 255.0/255.0, 0}, + {163.0/255.0, 2.0/255.0, 98.0/255.0, 0} + }, + + { //gay + {7.0/255.0, 141.0/255.0, 112.0/255.0, 0}, + {255.0/255.0, 255.0/255.0, 255.0/255.0, 0}, + {123.0/255.0, 173.0/255.0, 226.0/255.0, 0}, + {61.0/255.0, 26.0/255.0, 120.0/255.0, 0} + }, + + { //ace + {0.0/255.0, 0.0/255.0, 0.0/255.0, 0}, + {163.0/255.0, 163.0/255.0, 163.0/255.0, 0}, + {255.0/255.0, 255.0/255.0, 255.0/255.0, 0}, + {128.0/255.0, 0.0/255.0, 128.0/255.0, 0} + }, + + { //br + {0.0/255.0, 151.0/255.0, 57.0/255.0, 0}, + {254.0/255.0, 221.0/255.0, 0.0/255.0, 0}, + {255.0/255.0, 255.0/255.0, 255.0/255.0, 0}, + {1.0/255.0, 33.0/255.0, 105.0/255.0, 0} + }, + + { //it + {255.0/255.0, 255.0/255.0, 255.0/255.0, 0}, + {0.0/255.0, 140.0/255.0, 69.0/255.0, 0}, + {255.0/255.0, 255.0/255.0, 255.0/255.0, 0}, + {205.0/255.0, 33.0/255.0, 42.0/255.0, 0} + } + +}; + +#endif diff --git a/soh/soh/Enhancements/Holiday/NotProxySaw.cpp b/soh/soh/Enhancements/Holiday/NotProxySaw.cpp new file mode 100644 index 000000000..fe0995467 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/NotProxySaw.cpp @@ -0,0 +1,147 @@ +#include "Holiday.hpp" +#include +#include "soh/UIWidgets.hpp" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/custom-message/CustomMessageManager.h" +#include "include/message_data_fmt.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +extern PlayState* gPlayState; +} + +#define AUTHOR "NotProxySaw" +#define CVAR(v) "gHoliday." AUTHOR "." v + +int dialogIndex = 0; +int affection = 0; +int TARGET_AFFECTION = 10; +struct DialogOption { + std::string text; + int affectionChange; + int nextDialogIndex; +}; +struct Dialog { + std::string ganonText; + std::vector options; +}; + +const std::vector dialogs = { + { // 0 + "Think you can defeat me? Foolish!", + { + {"You're lonely. You don't have to be.", 3, 1}, + {"I'm here to end this... peacefully.", 1, 2}, + {"I respect a man with ambition.", -1, 3}, + } + }, + { // 1 + "Lonely? Power's my only ally.", + { + {"There's more to you than that.", 3, 4}, + {"I get it more than you think.", 5, 4}, + {"Why not let someone in?", 2, 4}, + } + }, + { // 2 + "Peace? It's meaningless here.", + { + {"Maybe you've forgotten peace.", 2, 4}, + {"Power isn't everything.", 4, 4}, + {"Ally, not enemy.. that's my goal.", 1, 4}, + } + }, + { // 3 + "Respect? From you?", + { + {"We're not so different.", 3, 4}, + {"Maybe I admire your strength.", 5, 4}, + {"True power must be earned.", -1, 4}, + } + }, + { // 4 + "You're... different than I thought.", + { + {"Together, we'd be unstoppable.", 5, 5}, + {"Power won't bring fulfillment.", 3, 5}, + {"Let's change the world.", 4, 5}, + } + }, + { // 5 + "What if I trusted you with power?", + { + {"I'll protect it. And you.", 10, -1}, + {"Together, we're unstoppable.", 5, -1}, + {"Our way. Our history.", -3, -1}, + } + } +}; + +static void ConfigurationChanged() { + COND_ID_HOOK(OnActorInit, ACTOR_BOSS_GANON, CVarGetInteger(CVAR("GanonDatingSim"), 0), [](void* actorRef) { + dialogIndex = 0; + affection = 0; + }); + + COND_VB_SHOULD(VB_GANONDORF_DECIDE_TO_FIGHT, CVarGetInteger(CVAR("GanonDatingSim"), 0), { + MessageContext* msgCtx = &gPlayState->msgCtx; + + if (dialogIndex == -1) { + if (affection >= TARGET_AFFECTION) { + gPlayState->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; + gSaveContext.nextCutsceneIndex = 0xFFF2; + gPlayState->transitionTrigger = TRANS_TRIGGER_START; + gPlayState->transitionType = TRANS_TYPE_FADE_WHITE; + GameInteractor::State::TriforceHuntCreditsWarpActive = 0; + *should = false; + return; + } + return; + } + + affection += dialogs[dialogIndex].options[msgCtx->choiceIndex].affectionChange; + dialogIndex = dialogs[dialogIndex].options[msgCtx->choiceIndex].nextDialogIndex; + + *should = false; + Message_StartTextbox(gPlayState, 0x70CB, NULL); + }); + + COND_ID_HOOK(OnOpenText, 0x70CB, CVarGetInteger(CVAR("GanonDatingSim"), 0), [](u16 * textId, bool* loadFromMessageTable) { + std::string message; + if (dialogIndex == -1) { + if (affection >= TARGET_AFFECTION) { + message = "I've never felt this way before...\x01Take my power, Link. I trust you."; + } else { + message = "Liar! You're just like the rest of\x01them! Now I must destroy you!"; + } + } else { + message = dialogs[dialogIndex].ganonText + "\x01\x1C" + + dialogs[dialogIndex].options[0].text + "\x01" + + dialogs[dialogIndex].options[1].text + "\x01" + + dialogs[dialogIndex].options[2].text; + } + + auto messageEntry = CustomMessage(message); + messageEntry.Format(); + messageEntry.LoadIntoFont(); + *loadFromMessageTable = false; + }); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + if (UIWidgets::EnhancementCheckbox("Ganon Dating Sim", CVAR("GanonDatingSim"))) { + ConfigurationChanged(); + } + UIWidgets::Tooltip("Prior to fighting him at the top of his Castle, you make an attempt to convince Ganon to join you instead."); +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + ConfigurationChanged(); + // #endregion +} + +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/Pablo.cpp b/soh/soh/Enhancements/Holiday/Pablo.cpp new file mode 100644 index 000000000..0299964d7 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Pablo.cpp @@ -0,0 +1,201 @@ +#include "Holiday.hpp" +#include "z64.h" +#include "macros.h" +#include "functions.h" +#include "src/overlays/effects/ovl_Effect_Ss_En_Ice/z_eff_ss_en_ice.h" + +extern "C" { + extern PlayState* gPlayState; +} + +#define AUTHOR "Pablo" +#define CVAR(v) "gHoliday." AUTHOR "." v + +#pragma region Shiny + +static Vec3f shineSpots[12] = { + { 20.0f, 20.0f, 0.0f }, { 10.0f, 40.0f, 10.0f }, { -10.0f, 40.0f, 10.0f }, { -20.0f, 20.0f, 0.0f }, + { 10.0f, 40.0f, -10.0f }, { -10.0f, 40.0f, -10.0f }, { 0.0f, 20.0f, -20.0f }, { 10.0f, 0.0f, 10.0f }, + { 10.0f, 0.0f, -10.0f }, { 0.0f, 20.0f, 20.0f }, { -10.0f, 0.0f, 10.0f }, { -10.0f, 0.0f, -10.0f }, +}; + +static u8 shinyableActorIds[51] = { + ACTOR_EN_WALLMAS, + ACTOR_EN_ZF, + ACTOR_EN_YUKABYUN, + ACTOR_EN_WF, + ACTOR_EN_WEIYER, + ACTOR_EN_VM, + ACTOR_EN_TUBO_TRAP, + ACTOR_EN_VALI, + ACTOR_EN_TP, + ACTOR_EN_TORCH2, + ACTOR_EN_TITE, + ACTOR_EN_TEST, + ACTOR_EN_SW, + ACTOR_EN_ST, + ACTOR_EN_SKB, + ACTOR_EN_SKJ, + ACTOR_EN_PEEHAT, + ACTOR_EN_SB, + ACTOR_EN_RR, + ACTOR_EN_REEBA, + ACTOR_EN_RD, + ACTOR_EN_PO_SISTERS, + ACTOR_EN_PO_FIELD, + ACTOR_EN_POH, + ACTOR_EN_KAREBABA, + ACTOR_EN_OKUTA, + ACTOR_EN_NY, + ACTOR_EN_MB, + ACTOR_EN_IK, + ACTOR_EN_GOMA, + ACTOR_EN_GELDB, + ACTOR_EN_FZ, + ACTOR_EN_FLOORMAS, + ACTOR_EN_FIREFLY, + ACTOR_EN_FD, + ACTOR_EN_EIYER, + ACTOR_EN_DODONGO, + ACTOR_EN_DODOJR, + ACTOR_EN_DH, + ACTOR_EN_DEKUBABA, + ACTOR_EN_CROW, + ACTOR_EN_CLEAR_TAG, + ACTOR_EN_BW, + ACTOR_EN_BUBBLE, + ACTOR_EN_AM, + ACTOR_EN_BILI, + ACTOR_EN_BIGOKUTA, + ACTOR_EN_BB, + ACTOR_EN_BA, + ACTOR_EN_ANUBICE, + ACTOR_DOOR_KILLER +}; + +u8 CanBeShiny(Actor* actor) { + for (u8 i = 0; i < ARRAY_COUNT(shinyableActorIds); i += 1) { + if (shinyableActorIds[i] == actor->id) { + return true; + } + } + return false; +} + +void ApplyShinyness(Actor* actor) { + if (!CanBeShiny(actor)) { + assert(false); + return; + } + + actor->isShiny = true; + actor->colChkInfo.health *= 4; + actor->maximumHealth *= 4; + actor->scale.x *= 1.25f; + actor->scale.y *= 1.25f; + actor->scale.z *= 1.25f; +} + +void RenderShines(Actor* actor) { + if (!CanBeShiny(actor) || !actor->isShiny) { + assert(false); + return; + } + + if (gSaveContext.gameMode != GAMEMODE_NORMAL || gPlayState->pauseCtx.state != 0) { + return; + } + + if (Rand_ZeroOne() < 0.1f) { + Vec3f shinePos; + s32 i = (s32)(Rand_ZeroOne() * ARRAY_COUNT(shineSpots)); + + shinePos.x = actor->world.pos.x + shineSpots[i].x; + shinePos.y = actor->world.pos.y + shineSpots[i].y; + shinePos.z = actor->world.pos.z + shineSpots[i].z; + + EffectSsEnIceInitParams initParams; + + initParams.actor = actor; + initParams.pos = shinePos; + initParams.type = 0; + + // 50/50 chance of red or green + if (Rand_Next() % 2 == 0) { + initParams.primColor.r = 255; + initParams.primColor.g = 0; + initParams.envColor.r = 255; + initParams.envColor.g = 0; + } else { + initParams.primColor.r = 0; + initParams.primColor.g = 255; + initParams.envColor.r = 0; + initParams.envColor.g = 255; + } + + initParams.primColor.b = 0; + initParams.primColor.a = 250; + initParams.envColor.b = 0; + initParams.scale = 0.5f; + + EffectSs_Spawn(gPlayState, EFFECT_SS_EN_ICE, 80, &initParams); + } +} + +void SpawnShinyReward(Actor* actor) { + if (!CanBeShiny(actor)) { + assert(false); + return; + } + + for (u8 i = 0; i < 10; i += 1) { + Item_DropCollectible(gPlayState, &actor->world.pos, ITEM00_RUPEE_RED); + Item_DropCollectible(gPlayState, &actor->world.pos, ITEM00_RUPEE_GREEN); + } +} + +void RegisterShiny() { + GameInteractor::Instance->RegisterGameHook([](void* refActor) { + Actor* actor = static_cast(refActor); + if (CVarGetInteger(CVAR("Shiny.Enabled"), 0) && CanBeShiny(actor) && Rand_ZeroOne() < (1.0f / (s32)CVarGetInteger(CVAR("Shiny.Chance"), 8192))) { + ApplyShinyness(actor); + } + }); + + GameInteractor::Instance->RegisterGameHook([](void* refActor) { + Actor* actor = static_cast(refActor); + if (CVarGetInteger(CVAR("Shiny.Enabled"), 0) && actor->isShiny) { + SpawnShinyReward(actor); + } + }); + + GameInteractor::Instance->RegisterGameHook([](void* refActor) { + Actor* actor = static_cast(refActor); + if (CVarGetInteger(CVAR("Shiny.Enabled"), 0) && actor->isShiny) { + RenderShines(actor); + } + }); +} + +void ShinyDrawImGui() { + UIWidgets::PaddedEnhancementCheckbox("Enable Shiny Enemies", CVAR("Shiny.Enabled"), true, false); + UIWidgets::Tooltip("Allows enemies to be shiny.\nShiny enemies are 25% bigger and have 4 times the health but drop the equivalent of a gold rupee upon death"); + + if (CVarGetInteger(CVAR("Shiny.Enabled"), 0)) { + UIWidgets::PaddedEnhancementSliderInt("Shiny Chance: %d", "##ShinyChance", CVAR("Shiny.Chance"), 1, 8192, "", 8192, true, true, false, false, ""); + UIWidgets::Tooltip("The chance for an enemy to be shiny is 1 / Shiny Chance"); + } +} + +#pragma endregion + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + ShinyDrawImGui(); +} + +static void RegisterMod() { + RegisterShiny(); +} + +static Holiday holiday(DrawMenu, RegisterMod); \ No newline at end of file diff --git a/soh/soh/Enhancements/Holiday/ProxySaw.cpp b/soh/soh/Enhancements/Holiday/ProxySaw.cpp new file mode 100644 index 000000000..a4c9fe122 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/ProxySaw.cpp @@ -0,0 +1,242 @@ +#include "Holiday.hpp" +#include +#include "soh/UIWidgets.hpp" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "objects/object_dog/object_dog.h" +#include "soh/frame_interpolation.h" +#include "soh/Enhancements/randomizer/3drando/random.hpp" +#include "soh/Enhancements/randomizer/3drando/location_access.hpp" +#include "soh/Enhancements/randomizer/entrance.h" + +#include "objects/gameplay_field_keep/gameplay_field_keep.h" +#include "objects/object_md/object_md.h" +#include "src/overlays/actors/ovl_Door_Ana/z_door_ana.h" +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" + +extern PlayState* gPlayState; +extern "C" s16 gEnSnowballId; +void DoorAna_SetupAction(DoorAna* doorAna, DoorAnaActionFunc actionFunc); +void DoorAna_GrabPlayer(DoorAna* doorAna, PlayState* play); +} + +#define AUTHOR "ProxySaw" +#define CVAR(v) "gHoliday." AUTHOR "." v + +static CollisionPoly snowballPoly; +static Vec3f snowballPos; +static f32 raycastResult; + +static u32 iceBlockParams[] = { + 0x214, + 0x1, + 0x11, + 0x10, + 0x20, +}; + +static void SpawnSnowballs() { + if (gPlayState->sceneNum != SCENE_HYRULE_FIELD && gPlayState->sceneNum != SCENE_KAKARIKO_VILLAGE) { + return; + } + + int actorsSpawned = 0; + + while (actorsSpawned < 30) { + snowballPos.x = (float)(Random( + (gPlayState->sceneNum == SCENE_HYRULE_FIELD ? -10000 : -2700) + 10000, + (gPlayState->sceneNum == SCENE_HYRULE_FIELD ? 5000 : 2000) + 10000 + ) - (float)10000.0f); + snowballPos.y = 5000; + snowballPos.z = (float)(Random( + (gPlayState->sceneNum == SCENE_HYRULE_FIELD ? -1000 : -2000) + 10000, + (gPlayState->sceneNum == SCENE_HYRULE_FIELD ? 15000 : 2000) + 10000 + ) - (float)10000.0f); + + raycastResult = BgCheck_AnyRaycastFloor1(&gPlayState->colCtx, &snowballPoly, &snowballPos); + + if (raycastResult > BGCHECK_Y_MIN) { + Actor_Spawn(&gPlayState->actorCtx, gPlayState, gEnSnowballId, snowballPos.x, raycastResult, + snowballPos.z, 0, 0, 0, gPlayState->sceneNum == SCENE_HYRULE_FIELD, 0); + actorsSpawned++; + } + } +} + +static void SpawnIcebergs() { + if (gPlayState->sceneNum != SCENE_LAKE_HYLIA) { + return; + } + + int actorsSpawned = 0; + + Vec3f spawnedIceBlockPos[15]; + + while (actorsSpawned < 15) { + Vec3f iceBlockPos; + iceBlockPos.x = (float)(Random( + (-4200) + 10000, + (3000) + 10000 + ) - (float)10000.0f); + iceBlockPos.y = -1713.0f; + iceBlockPos.z = (float)(Random( + (2600) + 10000, + (9000) + 10000 + ) - (float)10000.0f); + + raycastResult = BgCheck_AnyRaycastFloor1(&gPlayState->colCtx, &snowballPoly, &iceBlockPos); + + if (raycastResult > BGCHECK_Y_MIN) { + + bool overlaps = false; + for (int i = 0; i < actorsSpawned; i++) { + if (Math_Vec3f_DistXZ(&spawnedIceBlockPos[i], &iceBlockPos) < 500.0f) { + overlaps = true; + break; + } + } + + if (overlaps) { + continue; + } + + if (LINK_IS_ADULT && !Flags_GetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER)) { + iceBlockPos.y = raycastResult; + } else { + iceBlockPos.y = -1310.0f; + } + + Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_BG_SPOT08_ICEBLOCK, iceBlockPos.x, iceBlockPos.y, + iceBlockPos.z, 0, (s16)Random(0, 0xFFFF), 0, RandomElement(iceBlockParams), 0); + spawnedIceBlockPos[actorsSpawned] = iceBlockPos; + actorsSpawned++; + } + } +} + +const s16 entrances[] = { + 0x0000, 0x0209, 0x0004, 0x0242, 0x0028, 0x0221, 0x0169, 0x0215, 0x0165, 0x024A, 0x0010, 0x021D, 0x0082, 0x01E1, 0x0037, 0x0205, + 0x0098, 0x02A6, 0x0088, 0x03D4, 0x0008, 0x03A8, 0x0467, 0x023D, 0x0433, 0x0443, 0x0437, 0x0447, 0x009C, 0x033C, 0x00C9, 0x026A, + 0x00C1, 0x0266, 0x0043, 0x03CC, 0x045F, 0x0309, 0x03A0, 0x03D0, 0x007E, 0x026E, 0x0530, 0x01D1, 0x0507, 0x03BC, 0x0388, 0x02A2, + 0x0063, 0x01D5, 0x0528, 0x03C0, 0x043B, 0x0067, 0x02FD, 0x0349, 0x0550, 0x04EE, 0x039C, 0x0345, 0x05C8, 0x05DC, 0x0072, 0x034D, + 0x030D, 0x0355, 0x037C, 0x03FC, 0x0380, 0x03C4, 0x004F, 0x0378, 0x02F9, 0x042F, 0x05D0, 0x05D4, 0x052C, 0x03B8, 0x016D, 0x01CD, + 0x00B7, 0x0201, 0x003B, 0x0463, 0x0588, 0x057C, 0x0578, 0x0340, 0x04C2, 0x03E8, 0x04BE, 0x0482, 0x0315, 0x045B, 0x0371, 0x0394, + 0x0272, 0x0211, 0x0053, 0x0472, 0x0453, 0x0351, 0x0384, 0x044B, 0x03EC, 0x04FF, 0x0700, 0x0800, 0x0701, 0x0801, 0x0702, 0x0802, + 0x0703, 0x0803, 0x0704, 0x0804, 0x0705, 0x0805, 0x0706, 0x0806, 0x0707, 0x0807, 0x0708, 0x0808, 0x0709, 0x0809, 0x070A, 0x080A, + 0x070B, 0x080B, 0x080C, 0x070D, 0x080D, 0x070E, 0x080E, 0x070F, 0x080F, 0x0710, 0x0711, 0x0811, 0x0712, 0x0812, + 0x0713, 0x0813, 0x0714, 0x0814, 0x0715, 0x0815, 0x0716, 0x0816, 0x0717, 0x0817, 0x0718, 0x0818, 0x0719, 0x0819, 0x081A, + 0x071B, 0x081B, 0x071C, 0x081C, 0x071D, 0x081D, 0x071E, 0x081E, 0x071F, 0x081F, 0x0720, 0x0820, 0x004B, 0x035D, 0x031C, 0x0361, + 0x002D, 0x050B, 0x044F, 0x0359, 0x05E0, 0x020D, 0x011E, 0x0286, 0x04E2, 0x04D6, 0x01DD, 0x04DA, 0x00FC, 0x01A9, 0x0185, 0x04DE, + 0x0102, 0x0189, 0x0117, 0x018D, 0x0276, 0x01FD, 0x00DB, 0x017D, 0x00EA, 0x0181, 0x0157, 0x01F9, 0x0328, 0x0560, 0x0129, 0x022D, + 0x0130, 0x03AC, 0x0123, 0x0365, 0x00B1, 0x0033, 0x0138, 0x025A, 0x0171, 0x025E, 0x00E4, 0x0195, 0x013D, 0x0191, 0x014D, 0x01B9, + 0x0246, 0x01C1, 0x0147, 0x01BD, 0x0108, 0x019D, 0x0225, 0x01A1, 0x0219, 0x027E, 0x0554, 0x00BB, 0x0282, 0x0600, 0x04F6, 0x0604, + 0x01F1, 0x0568, 0x05F4, 0x040F, 0x0252, 0x040B, 0x00C5, 0x0301, 0x0407, 0x000C, 0x024E, 0x0305, 0x0175, 0x0417, 0x0423, 0x008D, + 0x02F5, 0x0413, 0x02B2, 0x0457, 0x047A, 0x010E, 0x0608, 0x0564, 0x060C, 0x0610, 0x0580 +}; + +static void RandomGrotto_WaitOpen(DoorAna* doorAna, PlayState* play) { + Actor* actor = &doorAna->actor; + Player* player = GET_PLAYER(play); + if (Math_StepToF(&actor->scale.x, 0.01f, 0.001f)) { + if ((actor->targetMode != 0) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (player->stateFlags1 & PLAYER_STATE1_FLOOR_DISABLED) && (player->av1.actionVar1 == 0)) { + play->nextEntranceIndex = RandomElement(entrances); + DoorAna_SetupAction((DoorAna*)actor, DoorAna_GrabPlayer); + } else { + if (!Player_InCsMode(play) && !(player->stateFlags1 & (PLAYER_STATE1_ON_HORSE | PLAYER_STATE1_IN_WATER)) && + actor->xzDistToPlayer <= 15.0f && -50.0f <= actor->yDistToPlayer && + actor->yDistToPlayer <= 15.0f) { + player->stateFlags1 |= PLAYER_STATE1_FLOOR_DISABLED; + actor->targetMode = 1; + } else { + actor->targetMode = 0; + } + } + } + Actor_SetScale(actor, actor->scale.x); +} + +static void SpawnRandomGrotto() { + if ( + gPlayState->sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY || + gPlayState->sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT || + gPlayState->sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS + ) { + return; + } + + Vec3f pos; + pos.y = 9999.0f; + int spawnAttempts = 0; + while (spawnAttempts < 50) { + if (GET_PLAYER(gPlayState) != nullptr) { + pos.x = GET_PLAYER(gPlayState)->actor.world.pos.x; + pos.z = GET_PLAYER(gPlayState)->actor.world.pos.z; + } else { + pos.x = 0; + pos.z = 0; + } + // X/Z anywhere from -1000.0 to +1000.0 from player + pos.x += (float)(Random(0, 5000)) - 2500.0f; + pos.z += (float)(Random(0, 5000)) - 2500.0f; + + raycastResult = BgCheck_AnyRaycastFloor1(&gPlayState->colCtx, &snowballPoly, &pos); + + if (raycastResult > BGCHECK_Y_MIN) { + Actor* grotto = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_ANA, pos.x, raycastResult, pos.z, 0, 0, 0, 0, false); + DoorAna_SetupAction((DoorAna*)grotto, RandomGrotto_WaitOpen); + break; + } + + spawnAttempts++; + } + +} + +static void ConfigurationChanged() { + COND_HOOK(OnSceneSpawnActors, CVarGetInteger(CVAR("Snowballs"), 0), SpawnSnowballs); + COND_HOOK(OnPlayerUpdate, CVarGetInteger(CVAR("SuperBonk"), 0), []() { + Player* player = GET_PLAYER(gPlayState); + if (player->actor.bgCheckFlags & 0x08 && ABS(player->linearVelocity) > 15.0f) { + player->yaw = ((player->actor.wallYaw - player->yaw) + player->actor.wallYaw) - 0x8000; + Player_PlaySfx(&player->actor, NA_SE_PL_BODY_HIT); + } + }); + + COND_HOOK(OnPlayerBonk, CVarGetInteger(CVAR("SuperBonk"), 0), []() { + Player* player = GET_PLAYER(gPlayState); + + player->linearVelocity = -100.0f; + }); + COND_HOOK(OnSceneSpawnActors, CVarGetInteger(CVAR("Icebergs"), 0), SpawnIcebergs); + COND_HOOK(OnSceneSpawnActors, CVarGetInteger(CVAR("DownTheRabbitHole"), 0), SpawnRandomGrotto); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + + if (UIWidgets::EnhancementCheckbox("Snowballs", CVAR("Snowballs"))) { + ConfigurationChanged(); + } + UIWidgets::Tooltip("Rogue snowballs will spawn in Hyrule Field and Kakariko Village."); + if (UIWidgets::EnhancementCheckbox("Lake Hylia Icebergs", CVAR("Icebergs"))) { + ConfigurationChanged(); + } + UIWidgets::Tooltip("Icebergs will spawn in Lake Hylia."); + if (UIWidgets::EnhancementCheckbox("Down the Rabbit Hole", CVAR("DownTheRabbitHole"))) { + ConfigurationChanged(); + } + UIWidgets::Tooltip("Random grottos will spawn throughout Hyrule. Who knows where they will take you?"); + if (UIWidgets::EnhancementCheckbox("Super Bonk", CVAR("SuperBonk"))) { + ConfigurationChanged(); + } +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + ConfigurationChanged(); + // #endregion +} + +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/Rando.cpp b/soh/soh/Enhancements/Holiday/Rando.cpp new file mode 100644 index 000000000..e5466dccf --- /dev/null +++ b/soh/soh/Enhancements/Holiday/Rando.cpp @@ -0,0 +1,49 @@ +#include "Holiday.hpp" +#include +#include "soh/UIWidgets.hpp" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/custom-message/CustomMessageManager.h" +#include "include/message_data_fmt.h" +#include "soh/OTRGlobals.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +extern PlayState* gPlayState; +} + +static void ConfigurationChanged() { + COND_ID_HOOK(OnOpenText, 0x406B, IS_RANDO, [](u16 * textId, bool* loadFromMessageTable) { + if (gPlayState->sceneNum != SCENE_KAKARIKO_VILLAGE) { + return; + } + + std::string message; + uint8_t current = gSaveContext.triforcePiecesCollected; + uint8_t required = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED); + + if (current < required) { + message = "The %yChristmas tree%w seems to be&missing some of %gits magic%w... Find all&ornaments to save %rChristmas%w!"; + } else { + message = "The tree's magic has been fully&restored. %gMerry %rChristmas%w!"; + } + + auto messageEntry = CustomMessage(message); + messageEntry.Format(); + messageEntry.LoadIntoFont(); + *loadFromMessageTable = false; + }); +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + ConfigurationChanged(); + // #endregion + + GameInteractor::Instance->RegisterGameHook([](int16_t fileNum) { + ConfigurationChanged(); + }); +} + +static Holiday holiday([]() {}, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/aMannus.cpp b/soh/soh/Enhancements/Holiday/aMannus.cpp new file mode 100644 index 000000000..8cf854b1d --- /dev/null +++ b/soh/soh/Enhancements/Holiday/aMannus.cpp @@ -0,0 +1,76 @@ +#include "Holiday.hpp" + +#define AUTHOR "aMannus" +#define CVAR(v) "gHoliday." AUTHOR "." v + +extern "C" { +#include ; +#include "functions.h"; +#include "variables.h"; +#include "macros.h"; +#include "objects/gameplay_keep/gameplay_keep.h" +extern PlayState* gPlayState; +} + +uint8_t rocsUseCount = 0; + +static void ConfigurationChanged() { + + COND_HOOK(OnPlayerUpdate, CVarGetInteger(CVAR("RocsFeather"), 0), []() { + Player* player = GET_PLAYER(gPlayState); + // Reset Rocs count when touching the ground + if (player->actor.bgCheckFlags & 1) { + rocsUseCount = 0; + } + }); + + COND_VB_SHOULD(VB_USE_ITEM, CVarGetInteger(CVAR("RocsFeather"), 0), { + int32_t* usedItem = va_arg(args, int32_t*); + Player* player = GET_PLAYER(gPlayState); + + // Roc's Feather behaviour + if (*usedItem == ITEM_NAYRUS_LOVE) { + *should = false; + + if (!rocsUseCount) { + rocsUseCount++; + player->linearVelocity = 5.0f; + player->actor.velocity.y = 8.0f; + player->actor.world.rot.y = player->yaw = player->actor.shape.rot.y; + + func_80838940(player, (LinkAnimationHeader*)&gPlayerAnim_link_fighter_backturn_jump, + !(2 & 1) ? 5.8f : 3.5f, gPlayState, 0); + + Vec3f effectsPos = player->actor.home.pos; + effectsPos.y += 3; + f32 effectsScale = 1; + if (!gSaveContext.linkAge) { + effectsScale = 1.5f; + } + EffectSsGRipple_Spawn(gPlayState, &effectsPos, 200 * effectsScale, 300 * effectsScale, 1); + EffectSsGSplash_Spawn(gPlayState, &effectsPos, NULL, NULL, 0, 150 * effectsScale); + + player->stateFlags2 &= ~(PLAYER_STATE2_HOPPING); + + Player_PlaySfx(&player->actor, NA_SE_PL_SKIP); + } + } + }); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + + if (UIWidgets::EnhancementCheckbox("Roc's Feather", CVAR("RocsFeather"))) { + ConfigurationChanged(); + } + UIWidgets::Tooltip("Using Nayru's Love will now act as Roc's Feather instead! No magic required."); +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + ConfigurationChanged(); + // #endregion +} + +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/Holiday/lilDavid.cpp b/soh/soh/Enhancements/Holiday/lilDavid.cpp new file mode 100644 index 000000000..33d8b2847 --- /dev/null +++ b/soh/soh/Enhancements/Holiday/lilDavid.cpp @@ -0,0 +1,137 @@ +#include "Holiday.hpp" + +#include "utils/StringHelper.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +extern PlayState* gPlayState; +} + +#include "src/overlays/actors/ovl_En_Arrow/z_en_arrow.h" +#include "src/overlays/actors/ovl_En_Bom/z_en_bom.h" + +extern "C" { + void func_809B45E0(EnArrow*, PlayState*); + void func_809B4640(EnArrow*, PlayState*); +} + +#define AUTHOR "lilDavid" +#define CVAR(v) "gHoliday." AUTHOR "." v + +static void OnConfigurationChanged() { + if (!CVarGetInteger(CVAR("BombArrows.Enabled"), 0)) + CVarSetInteger(CVAR("BombArrows.Active"), 0); + + COND_HOOK(OnSaveFile, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](int32_t file, int sectionID) { + std::string cvar = StringHelper::Sprintf("%s%d", CVAR("BombArrows.Save"), file); + CVarSetInteger(cvar.c_str(), CVarGetInteger(CVAR("BombArrows.Active"), 0)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + }); + + COND_HOOK(OnLoadFile, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](int32_t file) { + std::string cvar = StringHelper::Sprintf("%s%d", CVAR("BombArrows.Save"), file); + CVarSetInteger(CVAR("BombArrows.Active"), CVarGetInteger(cvar.c_str(), 0)); + }); + + COND_HOOK(OnCopyFile, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](int32_t from, int32_t to) { + std::string cvarFrom = StringHelper::Sprintf("%s%d", CVAR("BombArrows.Save"), from); + std::string cvarTo = StringHelper::Sprintf("%s%d", CVAR("BombArrows.Save"), to); + CVarSetInteger(cvarTo.c_str(), CVarGetInteger(cvarFrom.c_str(), 0)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + }); + + COND_HOOK(OnDeleteFile, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](int32_t file) { + std::string cvar = StringHelper::Sprintf("%s%d", CVAR("BombArrows.Save"), file); + CVarSetInteger(cvar.c_str(), 0); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + }); + + COND_ID_HOOK(OnActorInit, ACTOR_EN_ARROW, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](void* actorRef) { + EnArrow* arrow = (EnArrow*) actorRef; + if (!CVarGetInteger(CVAR("BombArrows.Active"), 0) || + arrow->actor.params != ARROW_NORMAL || AMMO(ITEM_BOMB) == 0 || + gSaveContext.minigameState == 1 || gPlayState->shootingGalleryStatus > 1) + return; + + EnBom* bomb = (EnBom*) Actor_SpawnAsChild(&gPlayState->actorCtx, &arrow->actor, gPlayState, ACTOR_EN_BOM, + arrow->actor.world.pos.x, arrow->actor.world.pos.y, arrow->actor.world.pos.z, + 0, 0, 0, BOMB_BODY); + if (bomb == nullptr) + return; + + Actor_SetScale(&bomb->actor, 0.003f); + bomb->timer = 65; + }); + + COND_ID_HOOK(OnActorUpdate, ACTOR_EN_ARROW, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](void* actorRef) { + EnArrow* arrow = (EnArrow*) actorRef; + if (!arrow->actor.child || arrow->actor.child->id != ACTOR_EN_BOM) + return; + + EnBom* bomb = (EnBom*) arrow->actor.child; + bomb->actor.world.pos = arrow->actor.world.pos; + f32 r = 8.0f; + f32 xrot = arrow->actor.world.rot.x; + f32 yrot = arrow->actor.world.rot.y; + bomb->actor.world.pos.x += r * Math_CosS(xrot) * Math_SinS(yrot); + bomb->actor.world.pos.y -= r * Math_SinS(xrot) + 2.0f; + bomb->actor.world.pos.z += r * Math_CosS(xrot) * Math_CosS(yrot); + + if (arrow->actor.parent == nullptr) { + if (bomb->timer > 60) { + Inventory_ChangeAmmo(ITEM_BOMB, -1); + } + bomb->timer = 52; + } else { + bomb->timer = 62; + } + + if (arrow->actionFunc == func_809B45E0 || + arrow->actionFunc == func_809B4640 || + arrow->actor.params == ARROW_NORMAL_LIT) + { + arrow->actor.child = nullptr; + bomb->actor.parent = nullptr; + bomb->timer = 2; + Actor_Kill(&arrow->actor); + } + }); + + COND_ID_HOOK(OnActorKill, ACTOR_EN_ARROW, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](void* actorRef) { + EnArrow* arrow = (EnArrow*) actorRef; + if (!arrow->actor.child || arrow->actor.child->id != ACTOR_EN_BOM) + return; + Actor_Kill(arrow->actor.child); + }); + + COND_ID_HOOK(OnActorUpdate, ACTOR_EN_BOM, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](void* actorRef) { + EnBom* bomb = (EnBom*) actorRef; + if (!bomb->actor.parent || bomb->actor.parent->id != ACTOR_EN_ARROW) + return; + + if (bomb->timer > 55 && bomb->timer < 60) + bomb->timer += 4; + if (bomb->timer > 45 && bomb->timer < 50) + bomb->timer += 4; + }); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + if (UIWidgets::EnhancementCheckbox("Bomb Arrows", CVAR("BombArrows.Enabled"))) { + OnConfigurationChanged(); + } + UIWidgets::Tooltip("Equip bombs over an already equipped Bow to shoot bomb arrows"); +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + OnConfigurationChanged(); + // #endregion + + CVarSetInteger(CVAR("BombArrows.Active"), 0); +} + +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp index cb9dfbb46..0247e98dd 100644 --- a/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp +++ b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp @@ -1,5 +1,6 @@ #include "TimeDisplay.h" #include "soh/Enhancements/gameplaystats.h" +#include "soh/Enhancements/Holiday/Fredomato.h" #include #include "assets/textures/parameter_static/parameter_static.h" @@ -40,7 +41,8 @@ const std::vector timeDisplayList = { { DISPLAY_IN_GAME_TIMER, "Display Gameplay Timer", CVAR_ENHANCEMENT("TimeDisplay.Timers.InGameTimer") }, { DISPLAY_TIME_OF_DAY, "Display Time of Day", CVAR_ENHANCEMENT("TimeDisplay.Timers.TimeofDay") }, { DISPLAY_CONDITIONAL_TIMER, "Display Conditional Timer", CVAR_ENHANCEMENT("TimeDisplay.Timers.HotWater") }, - { DISPLAY_NAVI_TIMER, "Display Navi Timer", CVAR_ENHANCEMENT("TimeDisplay.Timers.NaviTimer") } + { DISPLAY_NAVI_TIMER, "Display Navi Timer", CVAR_ENHANCEMENT("TimeDisplay.Timers.NaviTimer") }, + { DISPLAY_FRED_QUEST, "Display Fred's Quest", CVAR_ENHANCEMENT("TimeDisplay.Timers.FredsQuest") } }; static std::vector activeTimers; @@ -134,6 +136,10 @@ static void TimeDisplayGetTimer(uint32_t timeID) { } textureDisplay = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("NAVI_TIMER"); break; + case DISPLAY_FRED_QUEST: + timeDisplayTime = std::to_string(FredsQuestWoodOnHand) + "/" + std::to_string(FredsQuestWoodCollected) + "/" + + std::to_string(CVarGetInteger("gHoliday.Fredomato.FredsQuest.WoodNeeded", 300)); + textureDisplay = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("ITEM_STICK"); default: break; } @@ -189,6 +195,12 @@ void TimeDisplayWindow::Draw() { ImGui::Image(textureDisplay, ImVec2(16.0f * fontScale, 16.0f * fontScale)); ImGui::TableNextColumn(); + if (timers.timeID == DISPLAY_FRED_QUEST) { + ImGui::Text("%s", timeDisplayTime.c_str()); + ImGui::PopID(); + continue; + } + if (timeDisplayTime != "-:--") { char* textToDecode = new char[timeDisplayTime.size() + 1]; textToDecode = std::strcpy(textToDecode, timeDisplayTime.c_str()); diff --git a/soh/soh/Enhancements/TimeDisplay/TimeDisplay.h b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.h index 090ac2901..3002ac8a4 100644 --- a/soh/soh/Enhancements/TimeDisplay/TimeDisplay.h +++ b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.h @@ -17,7 +17,8 @@ typedef enum { DISPLAY_IN_GAME_TIMER, DISPLAY_TIME_OF_DAY, DISPLAY_CONDITIONAL_TIMER, - DISPLAY_NAVI_TIMER + DISPLAY_NAVI_TIMER, + DISPLAY_FRED_QUEST, }; typedef enum { diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 47d98488b..426101fdd 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -47,6 +47,13 @@ extern "C" { #include "objects/object_gjyo_objects/object_gjyo_objects.h" #include "textures/nintendo_rogo_static/nintendo_rogo_static.h" #include "objects/object_gi_rabit_mask/object_gi_rabit_mask.h" +#include "objects/object_wood02/object_wood02.h" +#include "scenes/overworld/spot00/spot00_room_0.h" +#include "scenes/overworld/spot04/spot04_room_0.h" +#include "scenes/overworld/spot04/spot04_room_1.h" +#include "scenes/overworld/spot20/spot20_room_0.h" +#include "scenes/overworld/spot03/spot03_room_0.h" +#include "scenes/overworld/spot15/spot15_room_0.h" #include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h" #include "overlays/ovl_Magic_Wind/ovl_Magic_Wind.h" #include "textures/nintendo_rogo_static/nintendo_rogo_static.h" @@ -189,9 +196,9 @@ Color_RGBA8 ColorRGBA8(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { colors were darker than the gDPSetPrimColor. You will see many more examples of this below in the `ApplyOrResetCustomGfxPatches` method */ static std::map cosmeticOptions = { - COSMETIC_OPTION("Link.KokiriTunic", "Kokiri Tunic", COSMETICS_GROUP_LINK, ColorRGBA8( 30, 105, 27, 255), false, true, false), - COSMETIC_OPTION("Link.GoronTunic", "Goron Tunic", COSMETICS_GROUP_LINK, ColorRGBA8(100, 20, 0, 255), false, true, false), - COSMETIC_OPTION("Link.ZoraTunic", "Zora Tunic", COSMETICS_GROUP_LINK, ColorRGBA8( 0, 60, 100, 255), false, true, false), + COSMETIC_OPTION("Link.KokiriTunic", "Kokiri Tunic", COSMETICS_GROUP_LINK, ColorRGBA8(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("Link.GoronTunic", "Goron Tunic", COSMETICS_GROUP_LINK, ColorRGBA8(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("Link.ZoraTunic", "Zora Tunic", COSMETICS_GROUP_LINK, ColorRGBA8(255, 0, 0, 255), false, true, false), COSMETIC_OPTION("Link.Hair", "Hair", COSMETICS_GROUP_LINK, ColorRGBA8(255, 173, 27, 255), false, true, true), COSMETIC_OPTION("Link.Linen", "Linen", COSMETICS_GROUP_LINK, ColorRGBA8(255, 255, 255, 255), false, true, true), COSMETIC_OPTION("Link.Boots", "Boots", COSMETICS_GROUP_LINK, ColorRGBA8( 93, 44, 18, 255), false, true, true), @@ -394,7 +401,7 @@ static std::map cosmeticOptions = { COSMETIC_OPTION("NPC.Dog1", "Dog 1", COSMETICS_GROUP_NPC, ColorRGBA8(255, 255, 200, 255), false, true, true), COSMETIC_OPTION("NPC.Dog2", "Dog 2", COSMETICS_GROUP_NPC, ColorRGBA8(150, 100, 50, 255), false, true, true), COSMETIC_OPTION("NPC.GoldenSkulltula", "Golden Skulltula", COSMETICS_GROUP_NPC, ColorRGBA8(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC.Kokiri", "Kokiri", COSMETICS_GROUP_NPC, ColorRGBA8( 0, 130, 70, 255), false, true, false), + COSMETIC_OPTION("NPC.Kokiri", "Kokiri", COSMETICS_GROUP_NPC, ColorRGBA8(255, 0, 0, 255), false, true, false), COSMETIC_OPTION("NPC.Gerudo", "Gerudo", COSMETICS_GROUP_NPC, ColorRGBA8( 90, 0, 140, 255), false, true, false), COSMETIC_OPTION("NPC.MetalTrap", "Metal Trap", COSMETICS_GROUP_NPC, ColorRGBA8(255, 255, 255, 255), false, true, true), COSMETIC_OPTION("NPC.IronKnuckles", "Iron Knuckles", COSMETICS_GROUP_NPC, ColorRGBA8(245, 255, 205, 255), false, true, false), @@ -486,6 +493,8 @@ void ResetPositionAll() { int hue = 0; +#define CVAR_LL(v) "gHoliday." "LL" "." v + // Runs every frame to update rainbow hue, a potential future optimization is to only run this a once or twice a second and increase the speed of the rainbow hue rotation. void CosmeticsUpdateTick() { int index = 0; @@ -494,10 +503,44 @@ void CosmeticsUpdateTick() { if (cosmeticOption.supportsRainbow && CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { double frequency = 2 * M_PI / (360 * rainbowSpeed); Color_RGBA8 newColor; - newColor.r = static_cast(sin(frequency * (hue + index) + 0) * 127) + 128; - newColor.g = static_cast(sin(frequency * (hue + index) + (2 * M_PI / 3)) * 127) + 128; - newColor.b = static_cast(sin(frequency * (hue + index) + (4 * M_PI / 3)) * 127) + 128; + newColor.a = 255; + + if (!CVarGetInteger(CVAR_LL("lEnableCustomRainbows"), 0)) { + newColor.r = static_cast(sin(frequency * (hue + index) + 0) * 127) + 128; + newColor.g = static_cast(sin(frequency * (hue + index) + (2 * M_PI / 3)) * 127) + 128; + newColor.b = static_cast(sin(frequency * (hue + index) + (4 * M_PI / 3)) * 127) + 128; + } + else { + Color_RGBA8 customColorZero = CVarGetColor(CVAR_LL("lCustomRainbow1"), {}); + Color_RGBA8 customColorOne = CVarGetColor(CVAR_LL("lCustomRainbow2"), {}); + Color_RGBA8 customColorMinusZero = CVarGetColor(CVAR_LL("lCustomRainbow3"), {}); + Color_RGBA8 customColorMinusOne = CVarGetColor(CVAR_LL("lCustomRainbow4"), {}); + float sinangle = sin(frequency * (hue + index)); + bool quadrant1 = hue <= (360 * rainbowSpeed) / 4; + bool quadrant2 = hue >= (360 * rainbowSpeed) / 4 && hue <= (360 * rainbowSpeed) / 2; + bool quadrant3 = hue >= (360 * rainbowSpeed) / 2 && hue <= (360 * rainbowSpeed) * 3 / 4; + bool quadrant4 = hue >= (360 * rainbowSpeed) * 3 / 4; + + if (quadrant1) { //zero to one + newColor.r = sinangle * (customColorOne.r - customColorZero.r) + customColorZero.r; + newColor.g = sinangle * (customColorOne.g - customColorZero.g) + customColorZero.g; + newColor.b = sinangle * (customColorOne.b - customColorZero.b) + customColorZero.b; + } else if (quadrant2) { //one to zero + newColor.r = sinangle * (customColorOne.r - customColorMinusZero.r) + customColorMinusZero.r; + newColor.g = sinangle * (customColorOne.g - customColorMinusZero.g) + customColorMinusZero.g; + newColor.b = sinangle * (customColorOne.b - customColorMinusZero.b) + customColorMinusZero.b; + } else if (quadrant3) { //zero to minus one + newColor.r = -sinangle * (customColorMinusOne.r - customColorMinusZero.r) + customColorMinusZero.r; + newColor.g = -sinangle * (customColorMinusOne.g - customColorMinusZero.g) + customColorMinusZero.g; + newColor.b = -sinangle * (customColorMinusOne.b - customColorMinusZero.b) + customColorMinusZero.b; + } else if (quadrant4) { //minus one to zero + newColor.r = -sinangle * (customColorMinusOne.r - customColorZero.r) + customColorZero.r; + newColor.g = -sinangle * (customColorMinusOne.g - customColorZero.g) + customColorZero.g; + newColor.b = -sinangle * (customColorMinusOne.b - customColorZero.b) + customColorZero.b; + } + } + // For alpha supported options, retain the last set alpha instead of overwriting if (cosmeticOption.supportsAlpha) { newColor.a = static_cast(cosmeticOption.currentColor.w * 255.0f); @@ -534,6 +577,24 @@ void CosmeticsUpdateTick() { 5. GFX Command: The GFX command you want to insert */ void ApplyOrResetCustomGfxPatches(bool manualChange) { + if (manualChange) { + PATCH_GFX(object_wood02_DL_007968, "Tree1", "gLetItSnow", 17, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(object_wood02_DL_000090, "Tree2", "gLetItSnow", 17, gsDPSetPrimColor(0, 0, 200, 255, 255, 255)); + PATCH_GFX(object_wood02_DL_000340, "Tree3", "gLetItSnow", 17, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(object_wood02_DL_000340, "Tree4", "gLetItSnow", 24, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(spot00_room_0DL_0139A8, "Path1", "gLetItSnow", 23, gsDPSetPrimColor(0, 0, 100, 150, 255, 60)); + PATCH_GFX(spot00_room_0DL_013250, "Path2", "gLetItSnow", 23, gsDPSetPrimColor(0, 0, 100, 150, 255, 60)); + PATCH_GFX(spot00_room_0DL_0143C8, "Path3", "gLetItSnow", 23, gsDPSetPrimColor(0, 0, 100, 150, 255, 60)); + PATCH_GFX(spot04_room_0DL_018048, "Path4", "gLetItSnow", 24, gsDPSetPrimColor(0, 0, 100, 150, 255, 60)); + PATCH_GFX(spot04_room_1DL_007810, "Path5", "gLetItSnow", 24, gsDPSetPrimColor(0, 0, 100, 150, 255, 60)); + PATCH_GFX(spot20_room_0DL_0062D0, "Path6", "gLetItSnow", 23, gsDPSetPrimColor(0, 0, 200, 230, 255, 30)); + PATCH_GFX(spot20_room_0DL_004460, "Path8", "gLetItSnow", 31, gsDPSetPrimColor(0, 0, 200, 230, 255, 30)); + PATCH_GFX(spot20_room_0DL_004460, "Path9", "gLetItSnow", 118, gsDPSetPrimColor(0, 0, 200, 230, 255, 30)); + PATCH_GFX(spot20_room_0DL_0065E8, "Path10", "gLetItSnow", 24, gsDPSetPrimColor(0, 0, 200, 230, 255, 30)); + PATCH_GFX(spot03_room_0DL_00C4B0, "Path11", "gLetItSnow", 23, gsDPSetPrimColor(0, 0, 200, 230, 255, 30)); + PATCH_GFX(spot15_room_0DL_00C748, "Path12", "gLetItSnow", 23, gsDPSetPrimColor(0, 0, 200, 230, 255, 30)); + } + static CosmeticOption& magicFaroresPrimary = cosmeticOptions.at("Magic.FaroresPrimary"); if (manualChange || CVarGetInteger(magicFaroresPrimary.rainbowCvar, 0)) { Color_RGBA8 color = CVarGetColor(magicFaroresPrimary.cvar, magicFaroresPrimary.defaultColor); @@ -1445,8 +1506,8 @@ void Reset_Option_Double(const char* Button_Title, const char* name) { void DrawSillyTab() { ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); - if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { - if (UIWidgets::EnhancementCheckbox("Let It Snow", CVAR_GENERAL("LetItSnow"))) { + if (CVarGetInteger("gLetItSnow", 0)) { + if (UIWidgets::EnhancementCheckbox("Let It Snow", "gLetItSnow")) { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); } } diff --git a/soh/soh/Enhancements/custom-collectible/CustomCollectible.cpp b/soh/soh/Enhancements/custom-collectible/CustomCollectible.cpp new file mode 100644 index 000000000..63ef5f9b3 --- /dev/null +++ b/soh/soh/Enhancements/custom-collectible/CustomCollectible.cpp @@ -0,0 +1,209 @@ +#include "CustomCollectible.h" +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/randomizer/3drando/random.hpp" +#include "soh/frame_interpolation.h" +#include "soh/Enhancements/custom-message/CustomMessageManager.h" + +extern "C" { +#include "z64actor.h" +#include "functions.h" +#include "variables.h" +#include "macros.h" +#include "objects/object_md/object_md.h" +extern PlayState* gPlayState; +} + +EnItem00* CustomCollectible::Spawn(f32 posX, f32 posY, f32 posZ, s16 rot, s16 flags, s16 params, ActorFunc actionFunc, + ActorFunc drawFunc) { + if (!gPlayState) { + return nullptr; + } + + Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_ITEM00, posX, posY, posZ, flags, rot, params, ITEM00_NONE, 0); + EnItem00* enItem00 = (EnItem00*)actor; + + if (actionFunc != NULL) { + enItem00->actionFunc = (EnItem00ActionFunc)actionFunc; + } + + if (drawFunc != NULL) { + actor->draw = drawFunc; + } + + return enItem00; +} + +void CustomCollectible_Init(Actor* actor, PlayState* play) { + EnItem00* enItem00 = (EnItem00*)actor; + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::STOP_BOBBING) { + actor->shape.yOffset = 1250.0f; + } else { + actor->shape.yOffset = (Math_SinS(actor->shape.rot.y) * 150.0f) + 1250.0f; + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::HIDE_TILL_OVERHEAD) { + Actor_SetScale(actor, 0.0f); + } else { + Actor_SetScale(actor, 0.015f); + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::KEEP_ON_PLAYER) { + Math_Vec3f_Copy(&actor->world.pos, &GET_PLAYER(play)->actor.world.pos); + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::TOSS_ON_SPAWN) { + actor->velocity.y = 8.0f; + actor->speedXZ = 2.0f; + actor->gravity = -1.4f; + actor->world.rot.y = Rand_ZeroOne() * 40000.0f; + } + + enItem00->unk_15A = -1; +} + +// By default this will just assume the GID was passed in as the rot z, if you want different functionality you should +// override the draw +void CustomCollectible_Draw(Actor* actor, PlayState* play) { + Matrix_Scale(30.0f, 30.0f, 30.0f, MTXMODE_APPLY); + GetItem_Draw(play, CUSTOM_ITEM_PARAM); +} + +void CustomCollectible_Update(Actor* actor, PlayState* play) { + EnItem00* enItem00 = (EnItem00*)actor; + Player* player = GET_PLAYER(play); + + if (!(CUSTOM_ITEM_FLAGS & CustomCollectible::STOP_SPINNING)) { + actor->shape.rot.y += 960; + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::STOP_BOBBING) { + actor->shape.yOffset = 1250.0f; + } else { + actor->shape.yOffset = (Math_SinS(actor->shape.rot.y) * 150.0f) + 1250.0f; + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::HIDE_TILL_OVERHEAD) { + Actor_SetScale(actor, 0.0f); + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::KEEP_ON_PLAYER) { + actor->gravity = 0.0f; + Math_Vec3f_Copy(&actor->world.pos, &GET_PLAYER(play)->actor.world.pos); + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::KILL_ON_TOUCH) { + // Pretty self explanatory, if the player is within range, kill the actor and call the action function + if ((actor->xzDistToPlayer <= 50.0f) && (fabsf(actor->yDistToPlayer) <= fabsf(20.0f))) { + if (enItem00->actionFunc != NULL) { + enItem00->actionFunc(enItem00, play); + CUSTOM_ITEM_FLAGS |= CustomCollectible::CALLED_ACTION; + } + Actor_Kill(actor); + } + } else if (CUSTOM_ITEM_FLAGS & CustomCollectible::GIVE_OVERHEAD) { + // If the item hasn't been picked up (unk_15A == -1) and the player is within range + if (enItem00->unk_15A == -1 && (actor->xzDistToPlayer <= 50.0f) && + (fabsf(actor->yDistToPlayer) <= fabsf(20.0f))) { + // Fire the action function + if (enItem00->actionFunc != NULL) { + enItem00->actionFunc(enItem00, play); + CUSTOM_ITEM_FLAGS |= CustomCollectible::CALLED_ACTION; + } + Sfx_PlaySfxCentered(NA_SE_SY_GET_ITEM); + // Set the unk_15A to 15, this indicates the item has been picked up and will start the overhead animation + enItem00->unk_15A = 15; + CUSTOM_ITEM_FLAGS |= CustomCollectible::STOP_BOBBING; + CUSTOM_ITEM_FLAGS |= CustomCollectible::KEEP_ON_PLAYER; + } + + // If the item has been picked up + if (enItem00->unk_15A > 0) { + // Reduce the size a bit, but also makes it visible for HIDE_TILL_OVERHEAD + Actor_SetScale(actor, 0.010f); + + // Decrement the unk_15A, which will be used to bob the item up and down + enItem00->unk_15A--; + + // Account for the different heights of the player forms + f32 height = 45.0f; + // TODO: Check for adult? + + // Bob the item up and down + actor->world.pos.y += (height + (Math_SinS(enItem00->unk_15A * 15000) * (enItem00->unk_15A * 0.3f))); + } + + // Finally, once the bobbing animation is done, kill the actor + if (enItem00->unk_15A == 0) { + Actor_Kill(actor); + } + } else if (CUSTOM_ITEM_FLAGS & CustomCollectible::GIVE_ITEM_CUTSCENE) { + // If the item hasn't been picked up and the player is within range + if (!Actor_HasParent(actor, play) && enItem00->unk_15A == -1) { + Actor_OfferGetItem(actor, play, GI_SHIP, 50.0f, 20.0f); + } else { + if (enItem00->unk_15A == -1) { + CUSTOM_ITEM_FLAGS |= CustomCollectible::STOP_BOBBING; + CUSTOM_ITEM_FLAGS |= CustomCollectible::KEEP_ON_PLAYER; + CUSTOM_ITEM_FLAGS |= CustomCollectible::HIDE_TILL_OVERHEAD; + } + + // Begin incrementing the unk_15A, indicating the item has been picked up + enItem00->unk_15A++; + + // For the first 20 frames, wait while the player's animation plays + if (enItem00->unk_15A >= 20) { + // After the first 20 frames, show the item and call the action function + if (enItem00->unk_15A == 20 && enItem00->actionFunc != NULL) { + enItem00->actionFunc(enItem00, play); + CUSTOM_ITEM_FLAGS |= CustomCollectible::CALLED_ACTION; + } + // Override the bobbing animation to be a fixed height + actor->shape.yOffset = 900.0f; + Actor_SetScale(actor, 0.007f); + + f32 height = 45.0f; + // TODO: Check for adult? + + actor->world.pos.y += height; + } + + // Once the player is no longer in the "Give Item" state, kill the actor + if (!(player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM)) { + Actor_Kill(actor); + } + } + } + + if (actor->gravity != 0.0f) { + Actor_MoveXZGravity(actor); + Actor_UpdateBgCheckInfo(play, actor, 20.0f, 15.0f, 15.0f, 0x1D); + } + + if (actor->bgCheckFlags & 0x0003) { + actor->speedXZ = 0.0f; + } + + Collider_UpdateCylinder(actor, &enItem00->collider); + CollisionCheck_SetAC(play, &play->colChkCtx, &enItem00->collider.base); +} + +void CustomCollectible::RegisterHooks() { + GameInteractor::Instance->RegisterGameHookForID( + ACTOR_EN_ITEM00, [](void* actorRef, bool* should) { + Actor* actor = (Actor*)actorRef; + if (actor->params != ITEM00_NONE) { + return; + } + + actor->init = CustomCollectible_Init; + actor->update = CustomCollectible_Update; + actor->draw = CustomCollectible_Draw; + actor->destroy = NULL; + + // Set the rotX/rotZ back to 0, the original values can be accessed from actor->home + actor->world.rot.x = 0; + actor->world.rot.z = 0; + }); +} diff --git a/soh/soh/Enhancements/custom-collectible/CustomCollectible.h b/soh/soh/Enhancements/custom-collectible/CustomCollectible.h new file mode 100644 index 000000000..ff2549b0f --- /dev/null +++ b/soh/soh/Enhancements/custom-collectible/CustomCollectible.h @@ -0,0 +1,24 @@ +extern "C" { +#include "z64actor.h" +} + +#define CUSTOM_ITEM_FLAGS (actor->home.rot.x) +#define CUSTOM_ITEM_PARAM (actor->home.rot.z) + +namespace CustomCollectible { + +enum CustomCollectibleFlags : int16_t { + KILL_ON_TOUCH = 1 << 0, // 0000 0000 0000 0001 + GIVE_OVERHEAD = 1 << 1, // 0000 0000 0000 0010 + GIVE_ITEM_CUTSCENE = 1 << 2, // 0000 0000 0000 0100 + HIDE_TILL_OVERHEAD = 1 << 3, // 0000 0000 0000 1000 + KEEP_ON_PLAYER = 1 << 4, // 0000 0000 0001 0000 + STOP_BOBBING = 1 << 5, // 0000 0000 0010 0000 + STOP_SPINNING = 1 << 6, // 0000 0000 0100 0000 + CALLED_ACTION = 1 << 7, // 0000 0000 1000 0000 + TOSS_ON_SPAWN = 1 << 8, // 0000 0001 0000 0000 +}; +void RegisterHooks(); +EnItem00* Spawn(f32 posX, f32 posY, f32 posZ, s16 rot, s16 flags, s16 params, ActorFunc actionFunc = NULL, + ActorFunc drawFunc = NULL); +}; // namespace CustomCollectible diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 4d4d27b3f..05b566b16 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -7,6 +7,12 @@ #include #include +#include "soh/util.h" + +extern "C" { +extern PlayState* gPlayState; +} + using namespace std::literals::string_literals; static const std::unordered_map textBoxSpecialCharacters = { @@ -183,6 +189,15 @@ const TextBoxPosition& CustomMessage::GetTextBoxPosition() const { return position; } +void CustomMessage::LoadIntoFont() { + MessageContext* msgCtx = &gPlayState->msgCtx; + Font* font = &msgCtx->font; + char* buffer = font->msgBuf; + const int maxBufferSize = sizeof(font->msgBuf); + font->charTexBuf[0] = (type << 4) | position; + msgCtx->msgLength = font->msgLength = SohUtils::CopyStringToCharBuffer(GetEnglish(MF_RAW), buffer, maxBufferSize); +} + CustomMessage CustomMessage::operator+(const CustomMessage& right) const { std::vector newColors = colors; std::vector rColors = right.GetColors(); diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index e8a969064..0c5880c4d 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -70,6 +70,9 @@ class CustomMessage { void SetTextBoxType(TextBoxType boxType); const TextBoxPosition& GetTextBoxPosition() const; + // To only be used with OnOpenText hook + void LoadIntoFont(); + CustomMessage operator+(const CustomMessage& right) const; CustomMessage operator+(const std::string& right) const; void operator+=(const std::string& right); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 844e91c37..333f6cc89 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -357,6 +357,8 @@ typedef enum { VB_GIVE_RANDO_FISHING_PRIZE, VB_PLAY_THROW_ANIMATION, VB_INFLICT_VOID_DAMAGE, + VB_GANONDORF_DECIDE_TO_FIGHT, + VB_USE_ITEM, // Vanilla condition: Close enough & various cutscene checks // Opt: *EnRu1 VB_PLAY_CHILD_RUTO_INTRO, @@ -369,6 +371,7 @@ typedef enum { // Vanilla condition: !Flags_GetInfTable(INFTABLE_145) // Opt: *EnRu1 VB_RUTO_BE_CONSIDERED_NOT_KIDNAPPED, + VB_PLAYER_ROLL, /*** Give Items ***/ @@ -509,12 +512,16 @@ typedef enum { // Vanilla condition: Actor is ACTOR_EN_ELF, ACTOR_EN_FISH, ACTOR_EN_ICE_HONO, or ACTOR_EN_INSECT // Opt: *Actor VB_BOTTLE_ACTOR, + + VB_DRAW_SKEL_LIMB, + VB_DRAW_SKEL_FLEX_LIMB, } GIVanillaBehavior; #ifdef __cplusplus extern "C" { #endif uint8_t GameInteractor_NoUIActive(); +void GameInteractor_SetNoUIActive(uint8_t state); GILinkSize GameInteractor_GetLinkSize(); void GameInteractor_SetLinkSize(GILinkSize size); uint8_t GameInteractor_InvisibleLinkActive(); @@ -599,6 +606,33 @@ struct HookInfo { body; \ va_end(args); \ }) +#define COND_HOOK(hookType, condition, body) \ + { \ + static HOOK_ID hookId = 0; \ + GameInteractor::Instance->UnregisterGameHook(hookId); \ + hookId = 0; \ + if (condition) { \ + hookId = GameInteractor::Instance->RegisterGameHook(body); \ + } \ + } +#define COND_ID_HOOK(hookType, id, condition, body) \ + { \ + static HOOK_ID hookId = 0; \ + GameInteractor::Instance->UnregisterGameHookForID(hookId); \ + hookId = 0; \ + if (condition) { \ + hookId = GameInteractor::Instance->RegisterGameHookForID(id, body); \ + } \ + } +#define COND_VB_SHOULD(id, condition, body) \ + { \ + static HOOK_ID hookId = 0; \ + GameInteractor::Instance->UnregisterGameHookForID(hookId); \ + hookId = 0; \ + if (condition) { \ + hookId = REGISTER_VB_SHOULD(id, body); \ + } \ + } class GameInteractor { public: diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h index a2d5c56ec..5754df7f3 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h @@ -18,22 +18,29 @@ DEFINE_HOOK(OnFlagSet, (int16_t flagType, int16_t flag)); DEFINE_HOOK(OnFlagUnset, (int16_t flagType, int16_t flag)); DEFINE_HOOK(OnSceneSpawnActors, ()); DEFINE_HOOK(OnPlayerUpdate, ()); +DEFINE_HOOK(OnPlayerSfx, (u16 sfxId)); DEFINE_HOOK(OnOcarinaSongAction, ()); DEFINE_HOOK(OnShopSlotChange, (uint8_t cursorIndex, int16_t price)); +DEFINE_HOOK(OnDungeonKeyUsed, (uint16_t mapIndex)); +DEFINE_HOOK(ShouldActorInit, (void* actor, bool* result)); DEFINE_HOOK(OnActorInit, (void* actor)); DEFINE_HOOK(OnActorUpdate, (void* actor)); +DEFINE_HOOK(OnActorDraw, (void* actor)); DEFINE_HOOK(OnActorKill, (void* actor)); DEFINE_HOOK(OnEnemyDefeat, (void* actor)); DEFINE_HOOK(OnBossDefeat, (void* actor)); DEFINE_HOOK(OnTimestamp, (u8 item)); DEFINE_HOOK(OnPlayerBonk, ()); +DEFINE_HOOK(OnPlayerRoll, ()); DEFINE_HOOK(OnPlayerHealthChange, (int16_t amount)); DEFINE_HOOK(OnPlayerBottleUpdate, (int16_t contents)); DEFINE_HOOK(OnPlayDestroy, ()); DEFINE_HOOK(OnPlayDrawEnd, ()); +DEFINE_HOOK(OnOpenText, (u16 * textId, bool* loadFromMessageTable)); DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list originalArgs)); -DEFINE_HOOK(OnSaveFile, (int32_t fileNum)); +DEFINE_HOOK(OnSaveFile, (int32_t fileNum, int32_t sectionID)); DEFINE_HOOK(OnLoadFile, (int32_t fileNum)); +DEFINE_HOOK(OnCopyFile, (int32_t sourceFileNum, uint32_t destFileNum)); DEFINE_HOOK(OnDeleteFile, (int32_t fileNum)); DEFINE_HOOK(OnDialogMessage, ()); @@ -59,3 +66,7 @@ DEFINE_HOOK(OnSetGameLanguage, ()); DEFINE_HOOK(OnFileDropped, (std::string filePath)); DEFINE_HOOK(OnAssetAltChange, ()); DEFINE_HOOK(OnKaleidoUpdate, ()); + +DEFINE_HOOK(OnRandoSetCheckStatus, (RandomizerCheck rc, RandomizerCheckStatus status)); +DEFINE_HOOK(OnRandoSetIsSkipped, (RandomizerCheck rc, bool isSkipped)); +DEFINE_HOOK(OnRandoEntranceDiscovered, (u16 entranceIndex, u8 isReversedEntrance)); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index 39fc298a8..2ea19806c 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -64,6 +64,10 @@ void GameInteractor_ExecuteOnPlayerUpdate() { GameInteractor::Instance->ExecuteHooks(); } +void GameInteractor_ExecuteOnPlayerSfx(u16 sfxId) { + GameInteractor::Instance->ExecuteHooks(sfxId); +} + void GameInteractor_ExecuteOnOcarinaSongAction() { GameInteractor::Instance->ExecuteHooks(); } @@ -72,6 +76,10 @@ void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t pr GameInteractor::Instance->ExecuteHooks(cursorIndex, price); } +void GameInteractor_ExecuteOnDungeonKeyUsedHooks(uint16_t mapIndex) { + GameInteractor::Instance->ExecuteHooks(mapIndex); +} + void GameInteractor_ExecuteOnActorInit(void* actor) { GameInteractor::Instance->ExecuteHooks(actor); GameInteractor::Instance->ExecuteHooksForID(((Actor*)actor)->id, actor); @@ -79,6 +87,15 @@ void GameInteractor_ExecuteOnActorInit(void* actor) { GameInteractor::Instance->ExecuteHooksForFilter(actor); } +bool GameInteractor_ShouldActorInit(void* actor) { + bool result = true; + GameInteractor::Instance->ExecuteHooks(actor, &result); + GameInteractor::Instance->ExecuteHooksForID(((Actor*)actor)->id, actor, &result); + GameInteractor::Instance->ExecuteHooksForPtr((uintptr_t)actor, actor, &result); + GameInteractor::Instance->ExecuteHooksForFilter(actor, &result); + return result; +} + void GameInteractor_ExecuteOnActorUpdate(void* actor) { GameInteractor::Instance->ExecuteHooks(actor); GameInteractor::Instance->ExecuteHooksForID(((Actor*)actor)->id, actor); @@ -86,6 +103,13 @@ void GameInteractor_ExecuteOnActorUpdate(void* actor) { GameInteractor::Instance->ExecuteHooksForFilter(actor); } +void GameInteractor_ExecuteOnActorDraw(void* actor) { + GameInteractor::Instance->ExecuteHooks(actor); + GameInteractor::Instance->ExecuteHooksForID(((Actor*)actor)->id, actor); + GameInteractor::Instance->ExecuteHooksForPtr((uintptr_t)actor, actor); + GameInteractor::Instance->ExecuteHooksForFilter(actor); +} + void GameInteractor_ExecuteOnActorKill(void* actor) { GameInteractor::Instance->ExecuteHooks(actor); GameInteractor::Instance->ExecuteHooksForID(((Actor*)actor)->id, actor); @@ -115,6 +139,10 @@ void GameInteractor_ExecuteOnPlayerBonk() { GameInteractor::Instance->ExecuteHooks(); } +void GameInteractor_ExecuteOnPlayerRoll() { + GameInteractor::Instance->ExecuteHooks(); +} + void GameInteractor_ExecuteOnPlayerHealthChange(int16_t amount) { GameInteractor::Instance->ExecuteHooks(amount); } @@ -131,6 +159,12 @@ void GameInteractor_ExecuteOnPlayDrawEnd() { GameInteractor::Instance->ExecuteHooks(); } +void GameInteractor_ExecuteOnOpenText(u16* textId, bool* loadFromMessageTable) { + GameInteractor::Instance->ExecuteHooks(textId, loadFromMessageTable); + GameInteractor::Instance->ExecuteHooksForID(*textId, textId, loadFromMessageTable); + GameInteractor::Instance->ExecuteHooksForFilter(textId, loadFromMessageTable); +} + bool GameInteractor_Should(GIVanillaBehavior flag, u32 result, ...) { // Only the external function can use the Variadic Function syntax // To pass the va args to the next caller must be done using va_list and reading the args into it @@ -154,14 +188,18 @@ bool GameInteractor_Should(GIVanillaBehavior flag, u32 result, ...) { // MARK: - Save Files -void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) { - GameInteractor::Instance->ExecuteHooks(fileNum); +void GameInteractor_ExecuteOnSaveFile(int32_t fileNum, int32_t sectionID) { + GameInteractor::Instance->ExecuteHooks(fileNum, sectionID); } void GameInteractor_ExecuteOnLoadFile(int32_t fileNum) { GameInteractor::Instance->ExecuteHooks(fileNum); } +void GameInteractor_ExecuteOnCopyFile(int32_t sourceFileNum, int32_t destFileNum) { + GameInteractor::Instance->ExecuteHooks(sourceFileNum, destFileNum); +} + void GameInteractor_ExecuteOnDeleteFile(int32_t fileNum) { GameInteractor::Instance->ExecuteHooks(fileNum); } @@ -255,3 +293,8 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)) { void GameInteractor_ExecuteOnKaleidoUpdate() { GameInteractor::Instance->ExecuteHooks(); } + +// MARK: - Rando +void GameInteractor_ExecuteOnRandoEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance) { + GameInteractor::Instance->ExecuteHooks(entranceIndex, isReversedEntrance); +} diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index 3438d269d..9a2703f81 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -18,25 +18,32 @@ void GameInteractor_ExecuteOnFlagSet(int16_t flagType, int16_t flag); void GameInteractor_ExecuteOnFlagUnset(int16_t flagType, int16_t flag); void GameInteractor_ExecuteOnSceneSpawnActors(); void GameInteractor_ExecuteOnPlayerUpdate(); +void GameInteractor_ExecuteOnPlayerSfx(u16 sfxId); void GameInteractor_ExecuteOnOcarinaSongAction(); +bool GameInteractor_ShouldActorInit(void* actor); void GameInteractor_ExecuteOnActorInit(void* actor); void GameInteractor_ExecuteOnActorUpdate(void* actor); +void GameInteractor_ExecuteOnActorDraw(void* actor); void GameInteractor_ExecuteOnActorKill(void* actor); void GameInteractor_ExecuteOnEnemyDefeat(void* actor); void GameInteractor_ExecuteOnBossDefeat(void* actor); void GameInteractor_ExecuteOnTimestamp (u8 item); void GameInteractor_ExecuteOnPlayerBonk(); +void GameInteractor_ExecuteOnPlayerRoll(); void GameInteractor_ExecuteOnPlayerHealthChange(int16_t amount); void GameInteractor_ExecuteOnPlayerBottleUpdate(int16_t contents); void GameInteractor_ExecuteOnOcarinaSongAction(); void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price); +void GameInteractor_ExecuteOnDungeonKeyUsedHooks(uint16_t mapIndex); void GameInteractor_ExecuteOnPlayDestroy(); void GameInteractor_ExecuteOnPlayDrawEnd(); +void GameInteractor_ExecuteOnOpenText(u16* textId, bool* loadFromMessageTable); bool GameInteractor_Should(GIVanillaBehavior flag, uint32_t result, ...); // MARK: - Save Files -void GameInteractor_ExecuteOnSaveFile(int32_t fileNum); +void GameInteractor_ExecuteOnSaveFile(int32_t fileNum, int32_t sectionID); void GameInteractor_ExecuteOnLoadFile(int32_t fileNum); +void GameInteractor_ExecuteOnCopyFile(int32_t sourceFileNum, int32_t destFileNum); void GameInteractor_ExecuteOnDeleteFile(int32_t fileNum); // MARK: - Dialog @@ -69,6 +76,9 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)); //Mark: - Pause Menu void GameInteractor_ExecuteOnKaleidoUpdate(); +// MARK: - Rando +void GameInteractor_ExecuteOnRandoEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance); + #ifdef __cplusplus } #endif diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp index 21642dded..38d125786 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp @@ -36,6 +36,10 @@ uint8_t GameInteractor_NoUIActive() { return GameInteractor::State::NoUIActive; } +void GameInteractor_SetNoUIActive(uint8_t state) { + GameInteractor::State::NoUIActive = state; +} + // MARK: - GameInteractor::State::LinkSize GILinkSize GameInteractor_GetLinkSize() { return GameInteractor::State::LinkSize; diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 0c11c79b2..35c967d5c 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -16,6 +16,7 @@ #include "soh/Enhancements/TimeSavers/TimeSavers.h" #include "soh/Enhancements/cheat_hook_handlers.h" #include "soh/Enhancements/randomizer/hook_handlers.h" +#include "soh/Enhancements/Holiday/Holiday.hpp" #include "objects/object_gi_compass/object_gi_compass.h" #include "src/overlays/actors/ovl_En_Bb/z_en_bb.h" @@ -52,6 +53,7 @@ extern "C" { extern SaveContext gSaveContext; extern PlayState* gPlayState; +extern "C" s16 gEnSnowballId; extern void Overlay_DisplayText(float duration, const char* text); } @@ -1442,4 +1444,5 @@ void InitMods() { RegisterHurtContainerModeHandler(); RegisterPauseMenuHooks(); RandoKaleido_RegisterHooks(); + RegisterHoliday(); } diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 0bdd2b0cc..6a6ac103d 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -995,12 +995,12 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l if (item00->itemEntry.modIndex == MOD_NONE) { Notification::Emit({ .itemIcon = GetTextureForItemId(item00->itemEntry.itemId), - .message = "You found ", + .message = "You found", .suffix = SohUtils::GetItemName(item00->itemEntry.itemId), }); } else if (item00->itemEntry.modIndex == MOD_RANDOMIZER) { Notification::Emit({ - .message = "You found ", + .message = "You found", .suffix = Rando::StaticData::RetrieveItem((RandomizerGet)item00->itemEntry.getItemId).GetName().english, }); } diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 458144411..f4ce76f8b 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -335,7 +335,7 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DEKU_STICK_CAPACITY_30] = Item(RG_DEKU_STICK_CAPACITY_30, Text{ "Deku Stick Capacity (30)", "Capacité de Bâtons Mojo (30)", "Deku-Stab-Kapazität (30)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_30, ITEM_STICK_UPGRADE_30, OBJECT_GI_STICK, GID_STICK, 0x91, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbessertes Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce-Fragment" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Christmas Ornament", "Christmas Ornament", "Christmas Ornament" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); // Init itemNameToEnum for (auto& item : itemTable) { diff --git a/soh/soh/Enhancements/randomizer/item_location.cpp b/soh/soh/Enhancements/randomizer/item_location.cpp index 9f0f84509..1a11c087c 100644 --- a/soh/soh/Enhancements/randomizer/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/item_location.cpp @@ -130,6 +130,7 @@ bool ItemLocation::HasObtained() const { void ItemLocation::SetCheckStatus(RandomizerCheckStatus status_) { status = status_; + GameInteractor::Instance->ExecuteHooks(rc, status); } RandomizerCheckStatus ItemLocation::GetCheckStatus() { @@ -138,6 +139,7 @@ RandomizerCheckStatus ItemLocation::GetCheckStatus() { void ItemLocation::SetIsSkipped(bool isSkipped_) { isSkipped = isSkipped_; + GameInteractor::Instance->ExecuteHooks(rc, isSkipped); } bool ItemLocation::GetIsSkipped() { diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 534cb451e..5d8d99688 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -116,14 +116,14 @@ void Settings::CreateOptionDescriptions() { "set to either MQ or Random here, you will have fewer MQ Dungeons than the number you " "set."; mOptionDescriptions[RSK_TRIFORCE_HUNT] = - "Pieces of the Triforce of Courage have been scattered across the world. Find them all to finish the game!\n\n" - "When the required amount of pieces have been found, the game is saved and Ganon's Boss key is given " + "Ornaments have been scattered across the world. Find them all to finish the game!\n\n" + "When the required amount of ornaments have been found, the game is saved and Ganon's Boss key is given " "to you when you load back into the game if you desire to beat Ganon afterwards.\n\n" "Keep in mind Ganon might not be logically beatable when \"All Locations Reachable\" is turned off."; mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL] = - "The amount of Triforce pieces that will be placed in the world. " - "Keep in mind seed generation can fail if more pieces are placed than there are junk items in the item pool."; - mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = "The amount of Triforce pieces required to win the game."; + "The amount of Ornaments that will be placed in the world. " + "Keep in mind seed generation can fail if more ornaments are placed than there are junk items in the item pool."; + mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = "The amount of Ornaments required to win the game."; mOptionDescriptions[RSK_SHUFFLE_DUNGEON_ENTRANCES] = "Shuffle the pool of dungeon entrances, including Bottom of the Well, Ice Cavern and Gerudo Training Ground.\n" "\n" diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index e0883d664..5faa33736 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2762,27 +2762,27 @@ CustomMessage Randomizer::GetRupeeMessage(u16 rupeeTextId) { void CreateTriforcePieceMessages() { CustomMessage TriforcePieceMessages[NUM_TRIFORCE_PIECE_MESSAGES] = { - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. It's a start!", + { "You found a %yChristmas Ornament%w!&%g[[current]]%w down, %c[[remaining]]%w to go. It's a start!", "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es ist ein&Anfang!", "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est un début!" }, - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Progress!", + { "You found a %yChristmas Ornament%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Progress!", "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es geht voran!", "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Ça avance!" }, - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Over half-way&there!", + { "You found a %yChristmas Ornament%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Over half-way&there!", "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Schon&über die Hälfte!", "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Il en reste un&peu moins que la moitié!" }, - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!", + { "You found a %yChristmas Ornament%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!", "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Fast&geschafft!", "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est presque&terminé!" }, - { "You completed the %yTriforce of&Courage%w! %gGG%w!", + { "You found all of the %yChristmas&Ornaments%w! Visit the %gChristmas&tree%w in Kakariko Village!", "Das %yTriforce des Mutes%w! Du hast&alle Splitter gefunden. %gGut gemacht%w!", "Vous avez complété la %yTriforce&du Courage%w! %gFélicitations%w!" }, - { "You found a spare %yTriforce Piece%w!&You only needed %c[[required]]%w, but you have %g[[current]]%w!", + { "You found a spare %yChristmas Ornament%w!&You only needed %c[[required]]%w, but you have %g[[current]]%w!", "Ein übriger %yTriforce-Splitter%w! Du&hast nun %g[[current]]%w von %c[[required]]%w nötigen gefunden.", "Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c[[required]]%w, mais vous en avez %g[[current]]%w en&tout!" }, }; @@ -3163,7 +3163,7 @@ CustomMessage Randomizer::GetIceTrapMessage() { CustomMessage msg; - if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { + if (CVarGetInteger("gLetItSnow", 0)) { msg = CustomMessage( /*english*/ "This year for Christmas, all you get is #COAL#!", /*german*/ "This year for Christmas, all you get is #COAL#!", diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index 7a492fe9c..cb770c54f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -15,6 +15,7 @@ #include "global.h" #include "entrance.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" extern PlayState* gPlayState; @@ -778,6 +779,8 @@ void Entrance_SetEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance) { return; } + GameInteractor_ExecuteOnRandoEntranceDiscovered(entranceIndex, isReversedEntrance); + u16 bitsPerIndex = sizeof(u32) * 8; u32 idx = entranceIndex / bitsPerIndex; if (idx < SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT) { diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 7f80edfeb..793077d12 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -685,7 +685,7 @@ void DrawItem(ItemTrackerItem item) { case RG_TRIFORCE_PIECE: actualItemId = item.id; hasItem = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT); - itemName = "Triforce Piece"; + itemName = "Christmas Ornament"; break; case RG_GOHMA_SOUL: actualItemId = item.id; @@ -1428,7 +1428,7 @@ void ItemTrackerSettingsWindow::DrawElement() { UIWidgets::Spacer(0); - ImGui::Text("Triforce Piece Count Tracking"); + ImGui::Text("Christmas ornament Count Tracking"); UIWidgets::EnhancementCombobox(CVAR_TRACKER_ITEM("TriforcePieceCounts"), itemTrackerTriforcePieceTrackOptions, TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX); UIWidgets::InsertHelpHoverText("Customize what numbers are shown for triforce piece tracking."); @@ -1471,7 +1471,7 @@ void ItemTrackerSettingsWindow::DrawElement() { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Triforce Pieces", CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), displayTypes, SECTION_DISPLAY_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Christmas Ornaments", CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; } diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 27999292a..a6d2f4db5 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -145,9 +145,9 @@ void Settings::CreateOptions() { mOptions[RSK_BOMBCHUS_IN_LOGIC] = Option::Bool("Bombchus in Logic", CVAR_RANDOMIZER_SETTING("BombchusInLogic"), mOptionDescriptions[RSK_BOMBCHUS_IN_LOGIC]); mOptions[RSK_ENABLE_BOMBCHU_DROPS] = Option::U8("Bombchu Drops", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS], WidgetType::Combobox, RO_AMMO_DROPS_ON); // TODO: AmmoDrops and/or HeartDropRefill, combine with/separate Ammo Drops from Bombchu Drops? - mOptions[RSK_TRIFORCE_HUNT] = Option::Bool("Triforce Hunt", CVAR_RANDOMIZER_SETTING("TriforceHunt"), mOptionDescriptions[RSK_TRIFORCE_HUNT], IMFLAG_NONE); - mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL] = Option::U8("Triforce Hunt Total Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL], WidgetType::Slider, 29, false, IMFLAG_NONE); - mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = Option::U8("Triforce Hunt Required Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntRequiredPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED], WidgetType::Slider, 19); + mOptions[RSK_TRIFORCE_HUNT] = Option::Bool("Ornament Hunt", CVAR_RANDOMIZER_SETTING("TriforceHunt"), mOptionDescriptions[RSK_TRIFORCE_HUNT], IMFLAG_NONE); + mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL] = Option::U8("Ornament Hunt Total Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL], WidgetType::Slider, 29, false, IMFLAG_NONE); + mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = Option::U8("Ornament Hunt Required Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntRequiredPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED], WidgetType::Slider, 19); mOptions[RSK_MQ_DUNGEON_RANDOM] = Option::U8("MQ Dungeon Setting", {"None", "Set Number", "Random", "Selection Only"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeons"), mOptionDescriptions[RSK_MQ_DUNGEON_RANDOM], WidgetType::Combobox, RO_MQ_DUNGEONS_NONE, true, IMFLAG_NONE); mOptions[RSK_MQ_DUNGEON_COUNT] = Option::U8("MQ Dungeon Count", {NumOpts(0, 12)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonCount"), "", WidgetType::Slider, 12, true, IMFLAG_NONE); mOptions[RSK_MQ_DUNGEON_SET] = Option::Bool("Set Dungeon Quests", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsSelection"), mOptionDescriptions[RSK_MQ_DUNGEON_SET], WidgetType::Checkbox, false, false, IMFLAG_NONE); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index dbfca709c..31818dee1 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -999,7 +999,7 @@ void TimeSaverOnSceneInitHandler(int16_t sceneNum) { } } -static GetItemEntry vanillaQueuedItemEntry = GET_ITEM_NONE; +GetItemEntry vanillaQueuedItemEntry = GET_ITEM_NONE; void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { @@ -1192,11 +1192,11 @@ void TimeSaverRegisterHooks() { onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnVanillaBehaviorHandler); onActorInitHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnActorInitHandler); onGameFrameUpdate = GameInteractor::Instance->RegisterGameHook(TimeSaverOnGameFrameUpdateHandler); + onPlayerUpdateHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnPlayerUpdateHandler); + onItemReceiveHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnItemReceiveHandler); if (IS_RANDO) return; onFlagSetHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnFlagSetHandler); - onPlayerUpdateHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnPlayerUpdateHandler); - onItemReceiveHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnItemReceiveHandler); }); } diff --git a/soh/soh/Network/Anchor/Anchor.cpp b/soh/soh/Network/Anchor/Anchor.cpp new file mode 100644 index 000000000..bc40f13b5 --- /dev/null +++ b/soh/soh/Network/Anchor/Anchor.cpp @@ -0,0 +1,403 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" +#include "soh/Enhancements/nametag.h" + +extern "C" { +#include "variables.h" +#include "functions.h" +extern PlayState* gPlayState; +} + +// MARK: - Overrides + +void Anchor::Enable() { + Network::Enable(CVarGetString(CVAR_REMOTE_ANCHOR("Host"), "anchor.proxysaw.dev"), CVarGetInteger(CVAR_REMOTE_ANCHOR("Port"), 43383)); + ownClientId = CVarGetInteger(CVAR_REMOTE_ANCHOR("LastClientId"), 0); + roomState.ownerClientId = 0; +} + +void Anchor::Disable() { + Network::Disable(); + + clients.clear(); + RefreshClientActors(); +} + +void Anchor::OnConnected() { + SendPacket_Handshake(); + RegisterHooks(); + + if (IsSaveLoaded()) { + SendPacket_RequestTeamState(); + } +} + +void Anchor::OnDisconnected() { + RegisterHooks(); +} + +void Anchor::SendJsonToRemote(nlohmann::json payload) { + if (!isConnected) { + return; + } + + payload["clientId"] = ownClientId; + if (!payload.contains("quiet")) { + SPDLOG_INFO("[Anchor] Sending payload:\n{}", payload.dump()); + } + Network::SendJsonToRemote(payload); +} + +void Anchor::OnIncomingJson(nlohmann::json payload) { + // If it doesn't contain a type, it's not a valid payload + if (!payload.contains("type")) { + return; + } + + // If it's not a quiet payload, log it + if (!payload.contains("quiet")) { + SPDLOG_INFO("[Anchor] Received payload:\n{}", payload.dump()); + } + + std::string packetType = payload["type"].get(); + + // Ignore packets from mismatched clients, except for ALL_CLIENT_STATE or UPDATE_CLIENT_STATE + if (packetType != ALL_CLIENT_STATE && packetType != UPDATE_CLIENT_STATE) { + if (payload.contains("clientId")) { + uint32_t clientId = payload["clientId"].get(); + if (clients.contains(clientId) && clients[clientId].clientVersion != clientVersion) { + return; + } + } + } + + // packetType here is a string so we can't use a switch statement + if (packetType == ALL_CLIENT_STATE) HandlePacket_AllClientState(payload); + else if (packetType == CONSUME_ADULT_TRADE_ITEM) HandlePacket_ConsumeAdultTradeItem(payload); + else if (packetType == DAMAGE_PLAYER) HandlePacket_DamagePlayer(payload); + else if (packetType == DISABLE_ANCHOR) HandlePacket_DisableAnchor(payload); + else if (packetType == ENTRANCE_DISCOVERED) HandlePacket_EntranceDiscovered(payload); + else if (packetType == GAME_COMPLETE) HandlePacket_GameComplete(payload); + else if (packetType == GIVE_ITEM) HandlePacket_GiveItem(payload); + else if (packetType == PLAYER_SFX) HandlePacket_PlayerSfx(payload); + else if (packetType == PLAYER_UPDATE) HandlePacket_PlayerUpdate(payload); + else if (packetType == UPDATE_TEAM_STATE) HandlePacket_UpdateTeamState(payload); + else if (packetType == REQUEST_TEAM_STATE) HandlePacket_RequestTeamState(payload); + else if (packetType == REQUEST_TELEPORT) HandlePacket_RequestTeleport(payload); + else if (packetType == SERVER_MESSAGE) HandlePacket_ServerMessage(payload); + else if (packetType == SET_CHECK_STATUS) HandlePacket_SetCheckStatus(payload); + else if (packetType == SET_FLAG) HandlePacket_SetFlag(payload); + else if (packetType == TELEPORT_TO) HandlePacket_TeleportTo(payload); + else if (packetType == UNSET_FLAG) HandlePacket_UnsetFlag(payload); + else if (packetType == UPDATE_BEANS_COUNT) HandlePacket_UpdateBeansCount(payload); + else if (packetType == UPDATE_CLIENT_STATE) HandlePacket_UpdateClientState(payload); + else if (packetType == UPDATE_ROOM_STATE) HandlePacket_UpdateRoomState(payload); + else if (packetType == UPDATE_DUNGEON_ITEMS) HandlePacket_UpdateDungeonItems(payload); +} + +// Macros to let us easily register and unregister functions when the anchor is enabled/disabled +#define HOOK(hook, condition, body) \ + static HOOK_ID hook = 0; \ + GameInteractor::Instance->UnregisterGameHook(hook); \ + hook = 0; \ + if (condition) { \ + hook = GameInteractor::Instance->RegisterGameHook(body); \ + } + +#define HOOK_FOR_ID(hook, condition, id, body) \ + static HOOK_ID hook = 0; \ + GameInteractor::Instance->UnregisterGameHookForID(hook); \ + hook = 0; \ + if (condition) { \ + hook = GameInteractor::Instance->RegisterGameHookForID(id, body); \ + } + +void Anchor::RegisterHooks() { + HOOK(OnSceneSpawnActors, isConnected, [&]() { + SendPacket_UpdateClientState(); + + if (IsSaveLoaded()) { + RefreshClientActors(); + } + }); + + HOOK(OnPresentFileSelect, isConnected, [&]() { + SendPacket_UpdateClientState(); + }); + + HOOK_FOR_ID(ShouldActorInit, isConnected, ACTOR_PLAYER, [&](void* actorRef, bool* should) { + Actor* actor = (Actor*)actorRef; + + if (refreshingActors) { + // By the time we get here, the actor was already added to the ACTORCAT_PLAYER list, so we need to move it + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC); + actor->id = ACTOR_EN_OE2; + actor->category = ACTORCAT_NPC; + actor->init = DummyPlayer_Init; + actor->update = DummyPlayer_Update; + actor->draw = DummyPlayer_Draw; + actor->destroy = DummyPlayer_Destroy; + } + }); + + HOOK(OnPlayerUpdate, isConnected, [&]() { + if (justLoadedSave) { + justLoadedSave = false; + SendPacket_RequestTeamState(); + } + SendPacket_PlayerUpdate(); + }); + + HOOK(OnPlayerSfx, isConnected, [&](u16 sfxId) { + SendPacket_PlayerSfx(sfxId); + }); + + HOOK(OnLoadGame, isConnected, [&](s16 fileNum) { + justLoadedSave = true; + }); + + HOOK(OnSaveFile, isConnected, [&](s16 fileNum, int sectionID) { + if (sectionID == 0) { + SendPacket_UpdateTeamState(); + } + }); + + HOOK(OnFlagSet, isConnected, [&](s16 flagType, s16 flag) { + SendPacket_SetFlag(SCENE_ID_MAX, flagType, flag); + }); + + HOOK(OnFlagUnset, isConnected, [&](s16 flagType, s16 flag) { + SendPacket_UnsetFlag(SCENE_ID_MAX, flagType, flag); + }); + + HOOK(OnSceneFlagSet, isConnected, [&](s16 sceneNum, s16 flagType, s16 flag) { + SendPacket_SetFlag(sceneNum, flagType, flag); + }); + + HOOK(OnSceneFlagUnset, isConnected, [&](s16 sceneNum, s16 flagType, s16 flag) { + SendPacket_UnsetFlag(sceneNum, flagType, flag); + }); + + HOOK(OnRandoSetCheckStatus, isConnected, [&](RandomizerCheck rc, RandomizerCheckStatus status) { + if (!isHandlingUpdateTeamState) { + SendPacket_SetCheckStatus(rc); + } + }); + + HOOK(OnRandoSetIsSkipped, isConnected, [&](RandomizerCheck rc, bool isSkipped) { + if (!isHandlingUpdateTeamState) { + SendPacket_SetCheckStatus(rc); + } + }); + + HOOK(OnRandoEntranceDiscovered, isConnected, [&](u16 entranceIndex, u8 isReversedEntrance) { + SendPacket_EntranceDiscovered(entranceIndex); + }); + + HOOK_FOR_ID(OnBossDefeat, isConnected, ACTOR_BOSS_GANON2, [&](void* refActor) { + SendPacket_GameComplete(); + }); + + HOOK(OnItemReceive, isConnected, [&](GetItemEntry itemEntry) { + // Handle vanilla dungeon items a bit differently + if (itemEntry.modIndex == MOD_NONE && (itemEntry.itemId >= ITEM_KEY_BOSS && itemEntry.itemId <= ITEM_KEY_SMALL)) { + SendPacket_UpdateDungeonItems(); + return; + } + + SendPacket_GiveItem(itemEntry.tableId, itemEntry.getItemId); + }); + + HOOK(OnDungeonKeyUsed, isConnected, [&](uint16_t mapIndex) { + // Handle vanilla dungeon items a bit differently + SendPacket_UpdateDungeonItems(); + }); +} + +// MARK: - Misc/Helpers + +// Kills all existing anchor actors and respawns them with the new client data +void Anchor::RefreshClientActors() { + if (!IsSaveLoaded()) { + return; + } + + Actor* actor = gPlayState->actorCtx.actorLists[ACTORCAT_NPC].head; + + while (actor != NULL) { + if (actor->id == ACTOR_EN_OE2 && actor->update == DummyPlayer_Update) { + NameTag_RemoveAllForActor(actor); + Actor_Kill(actor); + } + actor = actor->next; + } + + actorIndexToClientId.clear(); + refreshingActors = true; + for (auto& [clientId, client] : clients) { + if (!client.online || client.self) { + continue; + } + + actorIndexToClientId.push_back(clientId); + // We are using a hook `ShouldActorInit` to override the init/update/draw/destroy functions of the Player we spawn + // We quickly store a mapping of "index" to clientId, then within the init function we use this to get the clientId + // and store it on player->zTargetActiveTimer (unused s32 for the dummy) for convenience + auto dummy = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_PLAYER, client.posRot.pos.x, + client.posRot.pos.y, client.posRot.pos.z, client.posRot.rot.x, client.posRot.rot.y, + client.posRot.rot.z, actorIndexToClientId.size() - 1, false); + client.player = (Player*)dummy; + } + refreshingActors = false; +} + +bool Anchor::IsSaveLoaded() { + if (gPlayState == nullptr) { + return false; + } + + if (GET_PLAYER(gPlayState) == nullptr) { + return false; + } + + if (gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) { + return false; + } + + if (gSaveContext.gameMode != GAMEMODE_NORMAL) { + return false; + } + + return true; +} + +// MARK: - UI + +void Anchor::DrawMenu() { + ImGui::PushID("Anchor"); + + std::string host = CVarGetString(CVAR_REMOTE_ANCHOR("Host"), "anchor.proxysaw.dev"); + uint16_t port = CVarGetInteger(CVAR_REMOTE_ANCHOR("Port"), 43383); + std::string anchorTeamId = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + std::string anchorRoomId = CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), ""); + std::string anchorName = CVarGetString(CVAR_REMOTE_ANCHOR("Name"), ""); + bool isFormValid = !SohUtils::IsStringEmpty(host) && port > 1024 && port < 65535 && + !SohUtils::IsStringEmpty(anchorRoomId) && !SohUtils::IsStringEmpty(anchorName); + + ImGui::SeparatorText("Anchor"); + // UIWidgets::Tooltip("Anchor Stuff"); + if (ImGui::IsItemClicked()) { + // ImGui::SetClipboardText("https://github.com/garrettjoecox/anchor"); + } + + ImGui::BeginDisabled(isEnabled); + ImGui::Text("Host & Port"); + if (UIWidgets::InputString("##Host", &host)) { + CVarSetString(CVAR_REMOTE_ANCHOR("Host"), host.c_str()); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + } + + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 5); + if (ImGui::InputScalar("##Port", ImGuiDataType_U16, &port)) { + CVarSetInteger(CVAR_REMOTE_ANCHOR("Port"), port); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + } + + ImGui::Text("Tunic Color & Name"); + static Color_RGBA8 color = CVarGetColor(CVAR_REMOTE_ANCHOR("Color"), { 100, 255, 100, 255 }); + static ImVec4 colorVec = ImVec4(color.r / 255.0, color.g / 255.0, color.b / 255.0, 1); + if (ImGui::ColorEdit3("##Color", (float*)&colorVec, + ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) { + color.r = colorVec.x * 255.0; + color.g = colorVec.y * 255.0; + color.b = colorVec.z * 255.0; + + CVarSetColor(CVAR_REMOTE_ANCHOR("Color"), color); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + } + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (UIWidgets::InputString("##Name", &anchorName)) { + CVarSetString(CVAR_REMOTE_ANCHOR("Name"), anchorName.c_str()); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + } + ImGui::Text("Room ID"); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (UIWidgets::InputString("##RoomId", &anchorRoomId, isEnabled ? ImGuiInputTextFlags_Password : 0)) { + CVarSetString(CVAR_REMOTE_ANCHOR("RoomId"), anchorRoomId.c_str()); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + } + ImGui::Text("Team ID (Items & Flags Shared)"); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (UIWidgets::InputString("##TeamId", &anchorTeamId)) { + CVarSetString(CVAR_REMOTE_ANCHOR("TeamId"), anchorTeamId.c_str()); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + } + ImGui::EndDisabled(); + + ImGui::Spacing(); + + ImGui::BeginDisabled(!isFormValid); + const char* buttonLabel = isEnabled ? "Disable" : "Enable"; + if (ImGui::Button(buttonLabel, ImVec2(-1.0f, 0.0f))) { + if (isEnabled) { + CVarClear(CVAR_REMOTE_ANCHOR("Enabled")); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + Disable(); + } else { + CVarSetInteger(CVAR_REMOTE_ANCHOR("Enabled"), 1); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + Enable(); + } + } + ImGui::EndDisabled(); + + if (isEnabled) { + ImGui::Spacing(); + if (isConnected) { + ImGui::Text("Connected"); + + if (roomState.ownerClientId == ownClientId) { + if (ImGui::BeginMenu("Room Settings")) { + ImGui::Text("PvP Mode:"); + static const char* pvpModes[3] = { "Off", "On", "On + Friendly Fire" }; + if (UIWidgets::EnhancementCombobox(CVAR_REMOTE_ANCHOR("RoomSettings.PvpMode"), pvpModes, 1)) { + SendPacket_UpdateRoomState(); + } + ImGui::Text("Show Locations For:"); + static const char* showLocationsModes[3] = { "None", "Team Only", "All" }; + if (UIWidgets::EnhancementCombobox(CVAR_REMOTE_ANCHOR("RoomSettings.ShowLocationsMode"), showLocationsModes, 1)) { + SendPacket_UpdateRoomState(); + } + ImGui::Text("Allow Teleporting To:"); + static const char* teleportModes[3] = { "None", "Team Only", "All" }; + if (UIWidgets::EnhancementCombobox(CVAR_REMOTE_ANCHOR("RoomSettings.TeleportMode"), teleportModes, 1)) { + SendPacket_UpdateRoomState(); + } + ImGui::EndMenu(); + } + } + + if (ImGui::Button("Request Team State", ImVec2(ImGui::GetContentRegionAvail().x - 25.0f, 0.0f))) { + SendPacket_RequestTeamState(); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_TRASH)) { + SendPacket_ClearTeamState(); + } + UIWidgets::Tooltip("Clear Team State"); + } else { + ImGui::Text("Connecting..."); + } + } + + ImGui::PopID(); +} + +#endif diff --git a/soh/soh/Network/Anchor/Anchor.h b/soh/soh/Network/Anchor/Anchor.h new file mode 100644 index 000000000..16e3dd142 --- /dev/null +++ b/soh/soh/Network/Anchor/Anchor.h @@ -0,0 +1,177 @@ +#ifdef ENABLE_REMOTE_CONTROL +#ifndef NETWORK_ANCHOR_H +#define NETWORK_ANCHOR_H +#ifdef __cplusplus + +#include "soh/Network/Network.h" +#include + +extern "C" { +#include "variables.h" +#include "z64.h" +} + +void DummyPlayer_Init(Actor* actor, PlayState* play); +void DummyPlayer_Update(Actor* actor, PlayState* play); +void DummyPlayer_Draw(Actor* actor, PlayState* play); +void DummyPlayer_Destroy(Actor* actor, PlayState* play); + +typedef struct { + uint32_t clientId; + std::string name; + Color_RGB8 color; + std::string clientVersion; + std::string teamId; + bool online; + bool self; + uint32_t seed; + bool isSaveLoaded; + bool isGameComplete; + s16 sceneNum; + s32 entranceIndex; + + // Only available in PLAYER_UPDATE packets + s32 linkAge; + PosRot posRot; + Vec3s jointTable[24]; + Vec3s upperLimbRot; + s8 currentBoots; + s8 currentShield; + s8 currentTunic; + u32 stateFlags1; + u32 stateFlags2; + u8 buttonItem0; + s8 itemAction; + s8 heldItemAction; + u8 modelGroup; + s8 invincibilityTimer; + s16 unk_862; + s8 actionVar1; + + // Ptr to the dummy player + Player* player; +} AnchorClient; + +typedef struct { + uint32_t ownerClientId; + u8 pvpMode; // 0 = off, 1 = on, 2 = on with friendly fire + u8 showLocationsMode; // 0 = none, 1 = team, 2 = all + u8 teleportMode; // 0 = off, 1 = team, 2 = all +} RoomState; + +class Anchor : public Network { + private: + bool refreshingActors = false; + bool justLoadedSave = false; + bool isHandlingUpdateTeamState = false; + uint32_t ownClientId; + + nlohmann::json PrepClientState(); + nlohmann::json PrepRoomState(); + void RegisterHooks(); + void RefreshClientActors(); + void HandlePacket_AllClientState(nlohmann::json payload); + void HandlePacket_ConsumeAdultTradeItem(nlohmann::json payload); + void HandlePacket_DamagePlayer(nlohmann::json payload); + void HandlePacket_DisableAnchor(nlohmann::json payload); + void HandlePacket_EntranceDiscovered(nlohmann::json payload); + void HandlePacket_GameComplete(nlohmann::json payload); + void HandlePacket_GiveItem(nlohmann::json payload); + void HandlePacket_PlayerSfx(nlohmann::json payload); + void HandlePacket_PlayerUpdate(nlohmann::json payload); + void HandlePacket_RequestTeamState(nlohmann::json payload); + void HandlePacket_RequestTeleport(nlohmann::json payload); + void HandlePacket_ServerMessage(nlohmann::json payload); + void HandlePacket_SetCheckStatus(nlohmann::json payload); + void HandlePacket_SetFlag(nlohmann::json payload); + void HandlePacket_TeleportTo(nlohmann::json payload); + void HandlePacket_UnsetFlag(nlohmann::json payload); + void HandlePacket_UpdateBeansCount(nlohmann::json payload); + void HandlePacket_UpdateClientState(nlohmann::json payload); + void HandlePacket_UpdateDungeonItems(nlohmann::json payload); + void HandlePacket_UpdateRoomState(nlohmann::json payload); + void HandlePacket_UpdateTeamState(nlohmann::json payload); + + public: + inline static const std::string clientVersion = (char*)gBuildVersion; + + // Packet types // + inline static const std::string ALL_CLIENT_STATE = "ALL_CLIENT_STATE"; + inline static const std::string CONSUME_ADULT_TRADE_ITEM = "CONSUME_ADULT_TRADE_ITEM"; + inline static const std::string DAMAGE_PLAYER = "DAMAGE_PLAYER"; + inline static const std::string DISABLE_ANCHOR = "DISABLE_ANCHOR"; + inline static const std::string ENTRANCE_DISCOVERED = "ENTRANCE_DISCOVERED"; + inline static const std::string GAME_COMPLETE = "GAME_COMPLETE"; + inline static const std::string GIVE_ITEM = "GIVE_ITEM"; + inline static const std::string HANDSHAKE = "HANDSHAKE"; + inline static const std::string PLAYER_SFX = "PLAYER_SFX"; + inline static const std::string PLAYER_UPDATE = "PLAYER_UPDATE"; + inline static const std::string REQUEST_TEAM_STATE = "REQUEST_TEAM_STATE"; + inline static const std::string REQUEST_TELEPORT = "REQUEST_TELEPORT"; + inline static const std::string SERVER_MESSAGE = "SERVER_MESSAGE"; + inline static const std::string SET_CHECK_STATUS = "SET_CHECK_STATUS"; + inline static const std::string SET_FLAG = "SET_FLAG"; + inline static const std::string TELEPORT_TO = "TELEPORT_TO"; + inline static const std::string UNSET_FLAG = "UNSET_FLAG"; + inline static const std::string UPDATE_BEANS_COUNT = "UPDATE_BEANS_COUNT"; + inline static const std::string UPDATE_CLIENT_STATE = "UPDATE_CLIENT_STATE"; + inline static const std::string UPDATE_DUNGEON_ITEMS = "UPDATE_DUNGEON_ITEMS"; + inline static const std::string UPDATE_ROOM_STATE = "UPDATE_ROOM_STATE"; + inline static const std::string UPDATE_TEAM_STATE = "UPDATE_TEAM_STATE"; + + static Anchor* Instance; + std::map clients; + std::vector actorIndexToClientId; + RoomState roomState; + + void Enable(); + void Disable(); + void OnIncomingJson(nlohmann::json payload); + void OnConnected(); + void OnDisconnected(); + void DrawMenu(); + void SendJsonToRemote(nlohmann::json packet); + bool IsSaveLoaded(); + + void SendPacket_ClearTeamState(); + void SendPacket_ConsumeAdultTradeItem(u8 itemId); + void SendPacket_DamagePlayer(u32 clientId, u8 damageEffect, u8 damage); + void SendPacket_EntranceDiscovered(u16 entranceIndex); + void SendPacket_GameComplete(); + void SendPacket_GiveItem(u16 modId, s16 getItemId); + void SendPacket_Handshake(); + void SendPacket_PlayerSfx(u16 sfxId); + void SendPacket_PlayerUpdate(); + void SendPacket_RequestTeamState(); + void SendPacket_RequestTeleport(u32 clientId); + void SendPacket_SetCheckStatus(RandomizerCheck rc); + void SendPacket_SetFlag(s16 sceneNum, s16 flagType, s16 flag); + void SendPacket_TeleportTo(u32 clientId); + void SendPacket_UnsetFlag(s16 sceneNum, s16 flagType, s16 flag); + void SendPacket_UpdateBeansCount(); + void SendPacket_UpdateClientState(); + void SendPacket_UpdateDungeonItems(); + void SendPacket_UpdateRoomState(); + void SendPacket_UpdateTeamState(); +}; + +typedef enum { + // Starting at 5 to continue from the last value in the PlayerDamageResponseType enum + DUMMY_PLAYER_HIT_RESPONSE_STUN = 5, + DUMMY_PLAYER_HIT_RESPONSE_FIRE, + DUMMY_PLAYER_HIT_RESPONSE_NORMAL, +} DummyPlayerDamageResponseType; + +class AnchorRoomWindow : public Ship::GuiWindow { + public: + using GuiWindow::GuiWindow; + + void InitElement() override {}; + void DrawElement() override {}; + void Draw() override; + void UpdateElement() override {}; +}; + +#endif // __cplusplus +#endif // NETWORK_ANCHOR_H +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/AnchorRoomWindow.cpp b/soh/soh/Network/Anchor/AnchorRoomWindow.cpp new file mode 100644 index 000000000..4e20713ad --- /dev/null +++ b/soh/soh/Network/Anchor/AnchorRoomWindow.cpp @@ -0,0 +1,122 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "Anchor.h" +#include "soh/OTRGlobals.h" + +extern "C" { +#include "variables.h" +#include "functions.h" +extern PlayState* gPlayState; +} + +void AnchorRoomWindow::Draw() { + if (!Anchor::Instance->isConnected) { + return; + } + + + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, CVarGetFloat(CVAR_SETTING("Notifications.BgOpacity"), 0.5f))); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f); + + auto vp = ImGui::GetMainViewport(); + ImGui::SetNextWindowViewport(vp->ID); + + ImGui::Begin("Anchor Room", nullptr, + ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoNav | + ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoDocking | + ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoScrollWithMouse | + ImGuiWindowFlags_NoScrollbar + ); + + // First build a list of teams + std::set teams; + for (auto& [clientId, client] : Anchor::Instance->clients) { + teams.insert(client.teamId); + } + + for (auto& team : teams) { + if (teams.size() > 1) { + ImGui::SeparatorText(team.c_str()); + } + bool isOwnTeam = team == CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + for (auto& [clientId, client] : Anchor::Instance->clients) { + if (client.teamId != team) { + continue; + } + + ImGui::PushID(clientId); + + if (client.clientId == Anchor::Instance->roomState.ownerClientId) { + ImGui::TextColored(ImVec4(1, 1, 0, 1), "%s", ICON_FA_GAVEL); + ImGui::SameLine(); + } + + if (client.self) { + ImGui::TextColored(ImVec4(0.8f, 1.0f, 0.8f, 1.0f), "%s", CVarGetString(CVAR_REMOTE_ANCHOR("Name"), "")); + } else if (!client.online) { + ImGui::TextColored(ImVec4(1, 1, 1, 0.3f), "%s - offline", client.name.c_str()); + ImGui::PopID(); + continue; + } else { + ImGui::Text("%s", client.name.c_str()); + } + + if (Anchor::Instance->roomState.showLocationsMode == 2 || (Anchor::Instance->roomState.showLocationsMode == 1 && isOwnTeam)) { + if ((client.self ? Anchor::Instance->IsSaveLoaded() : client.isSaveLoaded)) { + ImGui::SameLine(); + ImGui::TextColored(ImVec4(1, 1, 1, 0.5f), "- %s", SohUtils::GetSceneName(client.self ? gPlayState->sceneNum : client.sceneNum).c_str()); + } + } + + if ( + Anchor::Instance->IsSaveLoaded() && !client.self && client.isSaveLoaded && + (Anchor::Instance->roomState.teleportMode == 2 || (Anchor::Instance->roomState.teleportMode == 1 && isOwnTeam)) + ) { + ImGui::SameLine(); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); + if (ImGui::Button(ICON_FA_LOCATION_ARROW, ImVec2(15.0f, 15.0f))) { + Anchor::Instance->SendPacket_RequestTeleport(client.clientId); + } + ImGui::PopStyleVar(); + } + + if (client.clientVersion != Anchor::clientVersion) { + ImGui::SameLine(); + ImGui::TextColored(ImVec4(1, 0, 0, 1), ICON_FA_EXCLAMATION_TRIANGLE); + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::Text("Incompatible version! Will not work together!"); + ImGui::Text("Yours: %s", Anchor::clientVersion.c_str()); + ImGui::Text("Theirs: %s", client.clientVersion.c_str()); + ImGui::EndTooltip(); + } + } + uint32_t seed = IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed() : 0; + if (client.isSaveLoaded && Anchor::Instance->IsSaveLoaded() && client.seed != seed && client.online) { + ImGui::SameLine(); + ImGui::TextColored(ImVec4(1, 0, 0, 1), ICON_FA_EXCLAMATION_TRIANGLE); + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::Text("Seed mismatch! Continuing will break things!"); + ImGui::Text("Yours: %u", seed); + ImGui::Text("Theirs: %u", client.seed); + ImGui::EndTooltip(); + } + } + ImGui::PopID(); + } + } + + + ImGui::End(); + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(2); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/DummyPlayer.cpp b/soh/soh/Network/Anchor/DummyPlayer.cpp new file mode 100644 index 000000000..63c6daf03 --- /dev/null +++ b/soh/soh/Network/Anchor/DummyPlayer.cpp @@ -0,0 +1,216 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "Anchor.h" +#include "soh/Enhancements/nametag.h" +#include "soh/frame_interpolation.h" + +extern "C" { +#include "macros.h" +#include "variables.h" +#include "functions.h" +extern PlayState* gPlayState; + +void Player_UseItem(PlayState* play, Player* player, s32 item); +void Player_Draw(Actor* actor, PlayState* play); +} + +// Hijacking player->zTargetActiveTimer (unused s32 for the dummy) to store the clientId for convenience +#define DUMMY_CLIENT_ID player->zTargetActiveTimer + +static DamageTable DummyPlayerDamageTable = { + /* Deku nut */ DMG_ENTRY(0, DUMMY_PLAYER_HIT_RESPONSE_STUN), + /* Deku stick */ DMG_ENTRY(2, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Slingshot */ DMG_ENTRY(1, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Explosive */ DMG_ENTRY(2, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Boomerang */ DMG_ENTRY(0, DUMMY_PLAYER_HIT_RESPONSE_STUN), + /* Normal arrow */ DMG_ENTRY(2, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Hammer swing */ DMG_ENTRY(2, PLAYER_HIT_RESPONSE_KNOCKBACK_LARGE), + /* Hookshot */ DMG_ENTRY(0, DUMMY_PLAYER_HIT_RESPONSE_STUN), + /* Kokiri sword */ DMG_ENTRY(1, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Master sword */ DMG_ENTRY(2, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Giant's Knife */ DMG_ENTRY(4, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Fire arrow */ DMG_ENTRY(2, DUMMY_PLAYER_HIT_RESPONSE_FIRE), + /* Ice arrow */ DMG_ENTRY(4, PLAYER_HIT_RESPONSE_ICE_TRAP), + /* Light arrow */ DMG_ENTRY(2, PLAYER_HIT_RESPONSE_ELECTRIC_SHOCK), + /* Unk arrow 1 */ DMG_ENTRY(2, PLAYER_HIT_RESPONSE_NONE), + /* Unk arrow 2 */ DMG_ENTRY(2, PLAYER_HIT_RESPONSE_NONE), + /* Unk arrow 3 */ DMG_ENTRY(2, PLAYER_HIT_RESPONSE_NONE), + /* Fire magic */ DMG_ENTRY(0, DUMMY_PLAYER_HIT_RESPONSE_FIRE), + /* Ice magic */ DMG_ENTRY(3, PLAYER_HIT_RESPONSE_ICE_TRAP), + /* Light magic */ DMG_ENTRY(0, PLAYER_HIT_RESPONSE_ELECTRIC_SHOCK), + /* Shield */ DMG_ENTRY(0, PLAYER_HIT_RESPONSE_NONE), + /* Mirror Ray */ DMG_ENTRY(0, PLAYER_HIT_RESPONSE_NONE), + /* Kokiri spin */ DMG_ENTRY(1, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Giant spin */ DMG_ENTRY(4, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Master spin */ DMG_ENTRY(2, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Kokiri jump */ DMG_ENTRY(2, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Giant jump */ DMG_ENTRY(8, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Master jump */ DMG_ENTRY(4, DUMMY_PLAYER_HIT_RESPONSE_NORMAL), + /* Unknown 1 */ DMG_ENTRY(0, PLAYER_HIT_RESPONSE_NONE), + /* Unblockable */ DMG_ENTRY(0, PLAYER_HIT_RESPONSE_NONE), + /* Hammer jump */ DMG_ENTRY(4, PLAYER_HIT_RESPONSE_KNOCKBACK_LARGE), + /* Unknown 2 */ DMG_ENTRY(0, PLAYER_HIT_RESPONSE_NONE), +}; + +void DummyPlayer_Init(Actor* actor, PlayState* play) { + Player* player = (Player*)actor; + + uint32_t clientId = Anchor::Instance->actorIndexToClientId[actor->params]; + DUMMY_CLIENT_ID = clientId; + + if (!Anchor::Instance->clients.contains(DUMMY_CLIENT_ID)) { + Actor_Kill(actor); + return; + } + + AnchorClient& client = Anchor::Instance->clients[DUMMY_CLIENT_ID]; + + // Hack to account for usage of gSaveContext in Player_Init + s32 originalAge = gSaveContext.linkAge; + gSaveContext.linkAge = client.linkAge; + + // #region modeled after EnTorch2_Init and Player_Init + actor->room = -1; + player->itemAction = player->heldItemAction = -1; + player->heldItemId = ITEM_NONE; + Player_UseItem(play, player, ITEM_NONE); + Player_SetModelGroup(player, Player_ActionToModelGroup(player, player->heldItemAction)); + play->playerInit(player, play, gPlayerSkelHeaders[client.linkAge]); + + play->func_11D54(player, play); + // #endregion + + player->cylinder.base.acFlags = AC_ON | AC_TYPE_PLAYER; + player->cylinder.base.ocFlags2 = OC2_TYPE_1; + player->cylinder.info.bumperFlags = BUMP_ON | BUMP_HOOKABLE | BUMP_NO_HITMARK; + player->actor.flags |= ACTOR_FLAG_DRAGGED_BY_HOOKSHOT; + player->cylinder.dim.radius = 30; + player->actor.colChkInfo.damageTable = &DummyPlayerDamageTable; + + gSaveContext.linkAge = originalAge; + + NameTag_RegisterForActorWithOptions(actor, client.name.c_str(), { .yOffset = 30 }); +} + +void Math_Vec3s_Copy(Vec3s* dest, Vec3s* src) { + dest->x = src->x; + dest->y = src->y; + dest->z = src->z; +} + +// Update the actor with new data from the client +void DummyPlayer_Update(Actor* actor, PlayState* play) { + Player* player = (Player*)actor; + + if (!Anchor::Instance->clients.contains(DUMMY_CLIENT_ID)) { + Actor_Kill(actor); + return; + } + + AnchorClient& client = Anchor::Instance->clients[DUMMY_CLIENT_ID]; + + if (client.sceneNum != gPlayState->sceneNum || !client.online || !client.isSaveLoaded) { + actor->world.pos.x = -9999.0f; + actor->world.pos.y = -9999.0f; + actor->world.pos.z = -9999.0f; + actor->shape.shadowAlpha = 0; + return; + } + + actor->shape.shadowAlpha = 255; + Math_Vec3s_Copy(&player->upperLimbRot, &client.upperLimbRot); + Math_Vec3s_Copy(&actor->shape.rot, &client.posRot.rot); + Math_Vec3f_Copy(&actor->world.pos, &client.posRot.pos); + player->skelAnime.jointTable = client.jointTable; + player->currentBoots = client.currentBoots; + player->currentShield = client.currentShield; + player->currentTunic = client.currentTunic; + player->stateFlags1 = client.stateFlags1; + player->stateFlags2 = client.stateFlags2; + player->itemAction = client.itemAction; + player->heldItemAction = client.heldItemAction; + player->invincibilityTimer = client.invincibilityTimer; + player->unk_862 = client.unk_862; + player->av1.actionVar1 = client.actionVar1; + + if (player->modelGroup != client.modelGroup) { + // Hack to account for usage of gSaveContext + s32 originalAge = gSaveContext.linkAge; + gSaveContext.linkAge = client.linkAge; + u8 originalButtonItem0 = gSaveContext.equips.buttonItems[0]; + gSaveContext.equips.buttonItems[0] = client.buttonItem0; + Player_SetModelGroup(player, client.modelGroup); + gSaveContext.linkAge = originalAge; + gSaveContext.equips.buttonItems[0] = originalButtonItem0; + } + + if ( + Anchor::Instance->roomState.pvpMode == 0 || + (Anchor::Instance->roomState.pvpMode == 1 && client.teamId == CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default")) + ) { + return; + } + + if (player->cylinder.base.acFlags & AC_HIT && player->invincibilityTimer == 0) { + Anchor::Instance->SendPacket_DamagePlayer(client.clientId, player->actor.colChkInfo.damageEffect, player->actor.colChkInfo.damage); + if (player->actor.colChkInfo.damageEffect == DUMMY_PLAYER_HIT_RESPONSE_STUN) { + Actor_SetColorFilter(&player->actor, 0, 0xFF, 0, 24); + } else { + player->invincibilityTimer = 20; + } + } + + Collider_UpdateCylinder(&player->actor, &player->cylinder); + + if (!(player->stateFlags2 & PLAYER_STATE2_FROZEN)) { + if (!(player->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_ON_HORSE))) { + CollisionCheck_SetOC(play, &play->colChkCtx, &player->cylinder.base); + } + + if (!(player->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_DAMAGED)) && (player->invincibilityTimer <= 0)) { + CollisionCheck_SetAC(play, &play->colChkCtx, &player->cylinder.base); + + if (player->invincibilityTimer < 0) { + CollisionCheck_SetAT(play, &play->colChkCtx, &player->cylinder.base); + } + } + } + + if (player->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE)) { + player->actor.colChkInfo.mass = MASS_IMMOVABLE; + } else { + player->actor.colChkInfo.mass = 50; + } + + Collider_ResetCylinderAC(play, &player->cylinder.base); +} + +void DummyPlayer_Draw(Actor* actor, PlayState* play) { + Player* player = (Player*)actor; + + if (!Anchor::Instance->clients.contains(DUMMY_CLIENT_ID)) { + Actor_Kill(actor); + return; + } + + AnchorClient& client = Anchor::Instance->clients[DUMMY_CLIENT_ID]; + + if (client.sceneNum != gPlayState->sceneNum || !client.online || !client.isSaveLoaded) { + return; + } + + // Hack to account for usage of gSaveContext in Player_Draw + s32 originalAge = gSaveContext.linkAge; + gSaveContext.linkAge = client.linkAge; + u8 originalButtonItem0 = gSaveContext.equips.buttonItems[0]; + gSaveContext.equips.buttonItems[0] = client.buttonItem0; + + Player_Draw((Actor*)player, play); + gSaveContext.linkAge = originalAge; + gSaveContext.equips.buttonItems[0] = originalButtonItem0; +} + +void DummyPlayer_Destroy(Actor* actor, PlayState* play) { +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/JsonConversions.hpp b/soh/soh/Network/Anchor/JsonConversions.hpp new file mode 100644 index 000000000..3ec04f043 --- /dev/null +++ b/soh/soh/Network/Anchor/JsonConversions.hpp @@ -0,0 +1,186 @@ +#ifdef ENABLE_REMOTE_CONTROL +#ifndef NETWORK_ANCHOR_JSON_CONVERSIONS_H +#define NETWORK_ANCHOR_JSON_CONVERSIONS_H +#ifdef __cplusplus + +#include +#include +#include "Anchor.h" + +extern "C" { +#include "z64.h" +} + +using json = nlohmann::json; + +inline void from_json(const json& j, Color_RGB8& color) { + j.at("r").get_to(color.r); + j.at("g").get_to(color.g); + j.at("b").get_to(color.b); +} + +inline void to_json(json& j, const Color_RGB8& color) { + j = json{ + {"r", color.r}, + {"g", color.g}, + {"b", color.b} + }; +} + +inline void to_json(json& j, const Vec3f& vec) { + j = json{ + {"x", vec.x}, + {"y", vec.y}, + {"z", vec.z} + }; +} + +inline void to_json(json& j, const Vec3s& vec) { + j = json{ + {"x", vec.x}, + {"y", vec.y}, + {"z", vec.z} + }; +} + +inline void from_json(const json& j, Vec3f& vec) { + j.at("x").get_to(vec.x); + j.at("y").get_to(vec.y); + j.at("z").get_to(vec.z); +} + +inline void from_json(const json& j, Vec3s& vec) { + j.at("x").get_to(vec.x); + j.at("y").get_to(vec.y); + j.at("z").get_to(vec.z); +} + +inline void to_json(json& j, const PosRot& posRot) { + j = json{ + {"pos", posRot.pos}, + {"rot", posRot.rot} + }; +} + +inline void from_json(const json& j, PosRot& posRot) { + j.at("pos").get_to(posRot.pos); + j.at("rot").get_to(posRot.rot); +} + +inline void from_json(const json& j, AnchorClient& client) { + j.contains("clientId") ? j.at("clientId").get_to(client.clientId) : client.clientId = 0; + j.contains("name") ? j.at("name").get_to(client.name) : client.name = "???"; + j.contains("color") ? j.at("color").get_to(client.color) : client.color = { 255, 255, 255 }; + j.contains("clientVersion") ? j.at("clientVersion").get_to(client.clientVersion) : client.clientVersion = "???"; + j.contains("teamId") ? j.at("teamId").get_to(client.teamId) : client.teamId = "default"; + j.contains("online") ? j.at("online").get_to(client.online) : client.online = false; + j.contains("seed") ? j.at("seed").get_to(client.seed) : client.seed = 0; + j.contains("isSaveLoaded") ? j.at("isSaveLoaded").get_to(client.isSaveLoaded) : client.isSaveLoaded = false; + j.contains("isGameComplete") ? j.at("isGameComplete").get_to(client.isGameComplete) : client.isGameComplete = false; + j.contains("sceneNum") ? j.at("sceneNum").get_to(client.sceneNum) : client.sceneNum = SCENE_ID_MAX; + j.contains("entranceIndex") ? j.at("entranceIndex").get_to(client.entranceIndex) : client.entranceIndex = 0; + j.contains("self") ? j.at("self").get_to(client.self) : client.self = false; +} + +inline void to_json(json& j, const Inventory& inventory) { + j = json{ + {"items", inventory.items}, + {"ammo", inventory.ammo}, + {"equipment", inventory.equipment}, + {"upgrades", inventory.upgrades}, + {"questItems", inventory.questItems}, + {"dungeonItems", inventory.dungeonItems}, + {"dungeonKeys", inventory.dungeonKeys}, + {"defenseHearts", inventory.defenseHearts}, + {"gsTokens", inventory.gsTokens} + }; +} + +inline void from_json(const json& j, Inventory& inventory) { + j.at("items").get_to(inventory.items); + j.at("ammo").get_to(inventory.ammo); + j.at("equipment").get_to(inventory.equipment); + j.at("upgrades").get_to(inventory.upgrades); + j.at("questItems").get_to(inventory.questItems); + j.at("dungeonItems").get_to(inventory.dungeonItems); + j.at("dungeonKeys").get_to(inventory.dungeonKeys); + j.at("defenseHearts").get_to(inventory.defenseHearts); + j.at("gsTokens").get_to(inventory.gsTokens); +} + +inline void to_json(json& j, const SohStats& sohStats) { + j = json{ + {"entrancesDiscovered", sohStats.entrancesDiscovered}, + {"fileCreatedAt", sohStats.fileCreatedAt}, + }; +} + +inline void from_json(const json& j, SohStats& sohStats) { + j.at("entrancesDiscovered").get_to(sohStats.entrancesDiscovered); + j.at("fileCreatedAt").get_to(sohStats.fileCreatedAt); +} + +inline void to_json(json& j, const SaveContext& saveContext) { + std::vector sceneFlagsArray; + for (const auto& sceneFlags : saveContext.sceneFlags) { + sceneFlagsArray.push_back(sceneFlags.chest); + sceneFlagsArray.push_back(sceneFlags.swch); + sceneFlagsArray.push_back(sceneFlags.clear); + sceneFlagsArray.push_back(sceneFlags.collect); + } + + j = json{ + {"healthCapacity", saveContext.healthCapacity}, + {"magicLevel", saveContext.magicLevel}, + {"magicCapacity", saveContext.magicCapacity}, + {"isMagicAcquired", saveContext.isMagicAcquired}, + {"isDoubleMagicAcquired", saveContext.isDoubleMagicAcquired}, + {"isDoubleDefenseAcquired", saveContext.isDoubleDefenseAcquired}, + {"bgsFlag", saveContext.bgsFlag}, + {"swordHealth", saveContext.swordHealth}, + {"sceneFlags", sceneFlagsArray}, + {"eventChkInf", saveContext.eventChkInf}, + {"itemGetInf", saveContext.itemGetInf}, + {"infTable", saveContext.infTable}, + {"randomizerInf", saveContext.randomizerInf}, + {"gsFlags", saveContext.gsFlags}, + {"inventory", saveContext.inventory}, + {"sohStats", saveContext.sohStats}, + {"adultTradeItems", saveContext.adultTradeItems}, + {"triforcePiecesCollected", saveContext.triforcePiecesCollected}, + {"questId", saveContext.questId}, + }; +} + +inline void from_json(const json& j, SaveContext& saveContext) { + j.at("healthCapacity").get_to(saveContext.healthCapacity); + j.at("magicLevel").get_to(saveContext.magicLevel); + j.at("magicCapacity").get_to(saveContext.magicCapacity); + j.at("isMagicAcquired").get_to(saveContext.isMagicAcquired); + j.at("isDoubleMagicAcquired").get_to(saveContext.isDoubleMagicAcquired); + j.at("isDoubleDefenseAcquired").get_to(saveContext.isDoubleDefenseAcquired); + j.at("bgsFlag").get_to(saveContext.bgsFlag); + j.at("swordHealth").get_to(saveContext.swordHealth); + std::vector sceneFlagsArray; + j.at("sceneFlags").get_to(sceneFlagsArray); + for (int i = 0; i < 124; i++) { + saveContext.sceneFlags[i].chest = sceneFlagsArray[i * 4]; + saveContext.sceneFlags[i].swch = sceneFlagsArray[i * 4 + 1]; + saveContext.sceneFlags[i].clear = sceneFlagsArray[i * 4 + 2]; + saveContext.sceneFlags[i].collect = sceneFlagsArray[i * 4 + 3]; + } + j.at("eventChkInf").get_to(saveContext.eventChkInf); + j.at("itemGetInf").get_to(saveContext.itemGetInf); + j.at("infTable").get_to(saveContext.infTable); + j.at("randomizerInf").get_to(saveContext.randomizerInf); + j.at("gsFlags").get_to(saveContext.gsFlags); + j.at("inventory").get_to(saveContext.inventory); + j.at("sohStats").get_to(saveContext.sohStats); + j.at("adultTradeItems").get_to(saveContext.adultTradeItems); + j.at("triforcePiecesCollected").get_to(saveContext.triforcePiecesCollected); + j.at("questId").get_to(saveContext.questId); +} + +#endif // __cplusplus +#endif // NETWORK_ANCHOR_JSON_CONVERSIONS_H +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/AllClientState.cpp b/soh/soh/Network/Anchor/Packets/AllClientState.cpp new file mode 100644 index 000000000..d9d455535 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/AllClientState.cpp @@ -0,0 +1,74 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include "soh/Network/Anchor/JsonConversions.hpp" +#include +#include +#include "soh/OTRGlobals.h" +#include "soh/Notification/Notification.h" + +/** + * ALL_CLIENT_STATE + * + * Contains a list of all clients and their CLIENT_STATE currently connected to the server + * + * The server itself sends this packet to all clients when a client connects or disconnects + */ + +void Anchor::HandlePacket_AllClientState(nlohmann::json payload) { + std::vector newClients = payload["state"].get>(); + + // add new clients + for (auto& client : newClients) { + if (client.self) { + ownClientId = client.clientId; + CVarSetInteger(CVAR_REMOTE_ANCHOR("LastClientId"), ownClientId); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); + clients[client.clientId].self = true; + } else { + clients[client.clientId].self = false; + if (clients.contains(client.clientId)) { + if (clients[client.clientId].online != client.online) { + Notification::Emit({ + .prefix = client.name, + .message = client.online ? "Connected" : "Disconnected", + }); + } + } else if (client.online) { + Notification::Emit({ + .prefix = client.name, + .message = "Connected", + }); + } + } + + clients[client.clientId].clientId = client.clientId; + clients[client.clientId].name = client.name; + clients[client.clientId].color = client.color; + clients[client.clientId].clientVersion = client.clientVersion; + clients[client.clientId].teamId = client.teamId; + clients[client.clientId].online = client.online; + clients[client.clientId].seed = client.seed; + clients[client.clientId].isSaveLoaded = client.isSaveLoaded; + clients[client.clientId].isGameComplete = client.isGameComplete; + clients[client.clientId].sceneNum = client.sceneNum; + clients[client.clientId].entranceIndex = client.entranceIndex; + } + + // remove clients that are no longer in the list + std::vector clientsToRemove; + for (auto& [clientId, client] : clients) { + if (std::find_if(newClients.begin(), newClients.end(), + [clientId](AnchorClient& c) { return c.clientId == clientId; }) == newClients.end()) { + clientsToRemove.push_back(clientId); + } + } + // (seperate loop to avoid iterator invalidation) + for (auto& clientId : clientsToRemove) { + clients.erase(clientId); + } + + RefreshClientActors(); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/ConsumeAdultTradeItem.cpp b/soh/soh/Network/Anchor/Packets/ConsumeAdultTradeItem.cpp new file mode 100644 index 000000000..645916f6d --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/ConsumeAdultTradeItem.cpp @@ -0,0 +1,46 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" + +extern "C" { +#include "functions.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +extern PlayState* gPlayState; +} + +/** + * CONSUME_ADULT_TRADE_ITEM + * + * This is primarily to just get rid of used adult trade items to prevent confusion for other players. + * Whatever flags/items are given from adult trade checks are synced by other packets. + */ + +void Anchor::SendPacket_ConsumeAdultTradeItem(u8 itemId) { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + payload["type"] = CONSUME_ADULT_TRADE_ITEM; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["itemId"] = itemId; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_ConsumeAdultTradeItem(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + uint8_t itemId = payload["itemId"].get(); + gSaveContext.adultTradeItems &= ~ADULT_TRADE_FLAG(itemId); + Inventory_ReplaceItem(gPlayState, itemId, Randomizer_GetNextAdultTradeItem()); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp b/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp new file mode 100644 index 000000000..e2da27eef --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp @@ -0,0 +1,62 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +extern PlayState* gPlayState; +void func_80838280(Player* player); +} + +/** + * DAMAGE_PLAYER + */ + +void Anchor::SendPacket_DamagePlayer(u32 clientId, u8 damageEffect, u8 damage) { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + payload["type"] = DAMAGE_PLAYER; + payload["targetClientId"] = clientId; + payload["damageEffect"] = damageEffect; + payload["damage"] = damage; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_DamagePlayer(nlohmann::json payload) { + uint32_t clientId = payload["clientId"].get(); + if (!clients.contains(clientId) || clients[clientId].player == nullptr) { + return; + } + + AnchorClient& anchorClient = clients[clientId]; + Player* otherPlayer = anchorClient.player; + Player* self = GET_PLAYER(gPlayState); + + u8 damageEffect = payload["damageEffect"].get(); + u8 damage = payload["damage"].get(); + + self->actor.colChkInfo.damage = damage * 8; // Arbitrary number currently, need to fine tune + + if (damageEffect == DUMMY_PLAYER_HIT_RESPONSE_FIRE) { + for (int i = 0; i < ARRAY_COUNT(self->bodyFlameTimers); i++) { + self->bodyFlameTimers[i] = Rand_S16Offset(0, 200); + } + self->bodyIsBurning = true; + } else if (damageEffect == DUMMY_PLAYER_HIT_RESPONSE_STUN) { + self->actor.freezeTimer = 20; + Actor_SetColorFilter(&self->actor, 0, 0xFF, 0, 24); + return; + } + + func_80837C0C(gPlayState, self, damageEffect, 4.0f, 5.0f, Actor_WorldYawTowardActor(&otherPlayer->actor, &self->actor), 20); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/DisableAnchor.cpp b/soh/soh/Network/Anchor/Packets/DisableAnchor.cpp new file mode 100644 index 000000000..6f01ddef6 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/DisableAnchor.cpp @@ -0,0 +1,18 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" + +/** + * DISABLE_ANCHOR + * + * No current use, potentially will be used for a future feature. + */ + +void Anchor::HandlePacket_DisableAnchor(nlohmann::json payload) { + Disable(); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/EntranceDiscovered.cpp b/soh/soh/Network/Anchor/Packets/EntranceDiscovered.cpp new file mode 100644 index 000000000..71773dcfd --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/EntranceDiscovered.cpp @@ -0,0 +1,41 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/randomizer/randomizer_entrance.h" +#include "soh/OTRGlobals.h" + +static bool isResultOfHandling = false; + +/** + * ENTRANCE_DISCOVERED + */ + +void Anchor::SendPacket_EntranceDiscovered(u16 entranceIndex) { + if (!IsSaveLoaded() || isResultOfHandling) { + return; + } + + nlohmann::json payload; + payload["type"] = ENTRANCE_DISCOVERED; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["entranceIndex"] = entranceIndex; + payload["quiet"] = true; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_EntranceDiscovered(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + isResultOfHandling = true; + u16 entranceIndex = payload["entranceIndex"].get(); + Entrance_SetEntranceDiscovered(entranceIndex, 1); + isResultOfHandling = false; +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/GameComplete.cpp b/soh/soh/Network/Anchor/Packets/GameComplete.cpp new file mode 100644 index 000000000..cd7d72d5b --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/GameComplete.cpp @@ -0,0 +1,48 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Notification/Notification.h" +#include "soh/Enhancements/randomizer/3drando/random.hpp" + +const std::string gameCompleteMessages[] = { + "killed Ganon", + "saved Zelda", + "proved their Courage", + "collected the Triforce", + "is the Hero of Time", + "proved Mido wrong", +}; + +/** + * GAME_COMPLETE + */ + +void Anchor::SendPacket_GameComplete() { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + payload["type"] = GAME_COMPLETE; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_GameComplete(nlohmann::json payload) { + uint32_t clientId = payload["clientId"].get(); + if (!clients.contains(clientId)) { + return; + } + + AnchorClient& anchorClient = clients[clientId]; + anchorClient.isGameComplete = true; + Notification::Emit({ + .prefix = anchorClient.name, + .message = RandomElement(gameCompleteMessages), + }); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/GiveItem.cpp b/soh/soh/Network/Anchor/Packets/GiveItem.cpp new file mode 100644 index 000000000..f6a6e05d2 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/GiveItem.cpp @@ -0,0 +1,104 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Notification/Notification.h" +#include "soh/Enhancements/randomizer/randomizer.h" +#include "soh/ImGuiUtils.h" +#include "soh/Enhancements/item-tables/ItemTableManager.h" +#include "soh/OTRGlobals.h" + +extern "C" { +#include "functions.h" +extern PlayState* gPlayState; +} + +/** + * GIVE_ITEM + */ + +static bool gettingItem; +static uint8_t incomingIceTraps; + +void Anchor::SendPacket_GiveItem(u16 modId, s16 getItemId) { + if (!IsSaveLoaded() || gettingItem) { + return; + } + + if (modId == MOD_RANDOMIZER && getItemId == RG_ICE_TRAP && incomingIceTraps > 0) { + incomingIceTraps = MAX(incomingIceTraps - 1, 0); + return; + } + + nlohmann::json payload; + payload["type"] = GIVE_ITEM; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["modId"] = modId; + payload["getItemId"] = getItemId; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_GiveItem(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + uint32_t clientId = payload["clientId"].get(); + AnchorClient& client = clients[clientId]; + + GetItemEntry getItemEntry; + if (payload["modId"].get() == MOD_NONE) { + getItemEntry = ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, payload["getItemId"].get()); + } else { + getItemEntry = Rando::StaticData::RetrieveItem(payload["getItemId"].get()).GetGIEntry_Copy(); + } + + gettingItem = true; + if (getItemEntry.modIndex == MOD_NONE) { + if (getItemEntry.getItemId == GI_SWORD_BGS) { + gSaveContext.bgsFlag = true; + } + Item_Give(gPlayState, getItemEntry.itemId); + } else if (getItemEntry.modIndex == MOD_RANDOMIZER) { + if (getItemEntry.getItemId == RG_ICE_TRAP) { + gSaveContext.pendingIceTrapCount++; + incomingIceTraps++; + } else { + Randomizer_Item_Give(gPlayState, getItemEntry); + } + } + + // Handle if the player gets a 4th heart piece (usually handled in z_message) + s32 heartPieces = (s32)(gSaveContext.inventory.questItems & 0xF0000000) >> (QUEST_HEART_PIECE + 4); + if (heartPieces >= 4) { + gSaveContext.inventory.questItems &= ~0xF0000000; + gSaveContext.inventory.questItems += (heartPieces % 4) << (QUEST_HEART_PIECE + 4); + gSaveContext.healthCapacity += 0x10 * (heartPieces / 4); + gSaveContext.health += 0x10 * (heartPieces / 4); + gSaveContext.healthAccumulator = 0x140; + } + gettingItem = false; + + if (getItemEntry.getItemCategory != ITEM_CATEGORY_JUNK) { + if (getItemEntry.modIndex == MOD_NONE) { + Notification::Emit({ + .itemIcon = GetTextureForItemId(getItemEntry.itemId), + .prefix = client.name, + .message = "found", + .suffix = SohUtils::GetItemName(getItemEntry.itemId), + }); + } else if (getItemEntry.modIndex == MOD_RANDOMIZER) { + Notification::Emit({ + .prefix = client.name, + .message = "found", + .suffix = Rando::StaticData::RetrieveItem((RandomizerGet)getItemEntry.getItemId).GetName().english, + }); + } + } +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/Handshake.cpp b/soh/soh/Network/Anchor/Packets/Handshake.cpp new file mode 100644 index 000000000..592da4932 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/Handshake.cpp @@ -0,0 +1,26 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" + +/** + * HANDSHAKE + * + * Sent by the client to the server when it first connects to the server, sends over both the local room settings + * in case the room needs to be created, along with the current client state + */ + +void Anchor::SendPacket_Handshake() { + nlohmann::json payload; + payload["type"] = HANDSHAKE; + payload["roomId"] = CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), ""); + payload["roomState"] = PrepRoomState(); + payload["clientState"] = PrepClientState(); + + SendJsonToRemote(payload); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/PlayerSfx.cpp b/soh/soh/Network/Anchor/Packets/PlayerSfx.cpp new file mode 100644 index 000000000..dc2741d9a --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/PlayerSfx.cpp @@ -0,0 +1,51 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include "soh/Network/Anchor/JsonConversions.hpp" +#include +#include + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +extern PlayState* gPlayState; +} + +/** + * PLAYER_SFX + * + * Sound effects, only sent to other clients in the same scene as the player + */ + +void Anchor::SendPacket_PlayerSfx(u16 sfxId) { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + + payload["type"] = PLAYER_SFX; + payload["sfxId"] = sfxId; + payload["quiet"] = true; + + for (auto& [clientId, client] : clients) { + if (client.sceneNum == gPlayState->sceneNum && client.online && client.isSaveLoaded) { + payload["targetClientId"] = clientId; + SendJsonToRemote(payload); + } + } +} + +void Anchor::HandlePacket_PlayerSfx(nlohmann::json payload) { + uint32_t clientId = payload["clientId"].get(); + u16 sfxId = payload["sfxId"].get(); + + if (!clients.contains(clientId) || !clients[clientId].player) { + return; + } + + Player_PlaySfx((Actor*)clients[clientId].player, sfxId); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/PlayerUpdate.cpp b/soh/soh/Network/Anchor/Packets/PlayerUpdate.cpp new file mode 100644 index 000000000..7a604d802 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/PlayerUpdate.cpp @@ -0,0 +1,120 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include "soh/Network/Anchor/JsonConversions.hpp" +#include +#include + +extern "C" { +#include "macros.h" +#include "variables.h" +extern PlayState* gPlayState; +} + +/** + * PLAYER_UPDATE + * + * Contains real-time data necessary to update other clients in the same scene as the player + * + * Sent every frame to other clients within the same scene + * + * Note: This packet is sent _a lot_, so please do not include any unnecessary data in it + */ + +void Anchor::SendPacket_PlayerUpdate() { + if (!IsSaveLoaded()) { + return; + } + + uint32_t currentPlayerCount = 0; + for (auto& [clientId, client] : clients) { + if (client.sceneNum == gPlayState->sceneNum && client.online && client.isSaveLoaded) { + currentPlayerCount++; + } + } + if (currentPlayerCount == 0) { + return; + } + + Player* player = GET_PLAYER(gPlayState); + nlohmann::json payload; + + payload["type"] = PLAYER_UPDATE; + payload["sceneNum"] = gPlayState->sceneNum; + payload["entranceIndex"] = gSaveContext.entranceIndex; + payload["linkAge"] = gSaveContext.linkAge; + payload["posRot"]["pos"] = player->actor.world.pos; + payload["posRot"]["rot"] = player->actor.shape.rot; + std::vector jointArray; + for (const auto& joint : player->jointTable) { + jointArray.push_back(joint.x); + jointArray.push_back(joint.y); + jointArray.push_back(joint.z); + } + payload["jointTable"] = jointArray; + payload["upperLimbRot"] = player->upperLimbRot; + payload["currentBoots"] = player->currentBoots; + payload["currentShield"] = player->currentShield; + payload["currentTunic"] = player->currentTunic; + payload["stateFlags1"] = player->stateFlags1; + payload["stateFlags2"] = player->stateFlags2; + payload["buttonItem0"] = gSaveContext.equips.buttonItems[0]; + payload["itemAction"] = player->itemAction; + payload["heldItemAction"] = player->heldItemAction; + payload["modelGroup"] = player->modelGroup; + payload["invincibilityTimer"] = player->invincibilityTimer; + payload["unk_862"] = player->unk_862; + payload["actionVar1"] = player->av1.actionVar1; + payload["quiet"] = true; + + for (auto& [clientId, client] : clients) { + if (client.sceneNum == gPlayState->sceneNum && client.online && client.isSaveLoaded) { + payload["targetClientId"] = clientId; + SendJsonToRemote(payload); + } + } +} + +void Anchor::HandlePacket_PlayerUpdate(nlohmann::json payload) { + uint32_t clientId = payload["clientId"].get(); + + bool shouldRefreshActors = false; + + if (clients.contains(clientId)) { + auto& client = clients[clientId]; + + if (client.linkAge != payload["linkAge"].get()) { + shouldRefreshActors = true; + } + + client.sceneNum = payload["sceneNum"].get(); + client.entranceIndex = payload["entranceIndex"].get(); + client.linkAge = payload["linkAge"].get(); + client.posRot = payload["posRot"].get(); + std::vector jointArray = payload["jointTable"]; + for (int i = 0; i < 24; i++) { + client.jointTable[i].x = jointArray[i * 3]; + client.jointTable[i].y = jointArray[i * 3 + 1]; + client.jointTable[i].z = jointArray[i * 3 + 2]; + } + client.upperLimbRot = payload["upperLimbRot"].get(); + client.currentBoots = payload["currentBoots"].get(); + client.currentShield = payload["currentShield"].get(); + client.currentTunic = payload["currentTunic"].get(); + client.stateFlags1 = payload["stateFlags1"].get(); + client.stateFlags2 = payload["stateFlags2"].get(); + client.buttonItem0 = payload["buttonItem0"].get(); + client.itemAction = payload["itemAction"].get(); + client.heldItemAction = payload["heldItemAction"].get(); + client.modelGroup = payload["modelGroup"].get(); + client.invincibilityTimer = payload["invincibilityTimer"].get(); + client.unk_862 = payload["unk_862"].get(); + client.actionVar1 = payload["actionVar1"].get(); + } + + if (shouldRefreshActors) { + RefreshClientActors(); + } +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/RequestTeamState.cpp b/soh/soh/Network/Anchor/Packets/RequestTeamState.cpp new file mode 100644 index 000000000..88638b082 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/RequestTeamState.cpp @@ -0,0 +1,41 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/OTRGlobals.h" + +/** + * REQUEST_TEAM_STATE + * + * Requests team state from the server, which will pass on the request to any connected teammates, or send the last known + * state if no teammates are connected. + * + * This fires when loading into a file while Anchor is connected, or when Anchor is connected while a file is already + * loaded + * + * Note: This can additionally be fired with a button in the menus to fix any desyncs that may have occurred in the save + * state + */ + +void Anchor::SendPacket_RequestTeamState() { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + payload["type"] = REQUEST_TEAM_STATE; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_RequestTeamState(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + SendPacket_UpdateTeamState(); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/RequestTeleport.cpp b/soh/soh/Network/Anchor/Packets/RequestTeleport.cpp new file mode 100644 index 000000000..fdd79e536 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/RequestTeleport.cpp @@ -0,0 +1,36 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" + +/** + * REQUEST_TELEPORT + * + * Because we don't have all the necessary information to directly teleport to a player, we emit a request, + * in which they will respond with a TELEPORT_TO packet, with the necessary information. + */ + +void Anchor::SendPacket_RequestTeleport(uint32_t clientId) { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + payload["type"] = REQUEST_TELEPORT; + payload["targetClientId"] = clientId; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_RequestTeleport(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + uint32_t clientId = payload["clientId"].get(); + SendPacket_TeleportTo(clientId); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/ServerMessage.cpp b/soh/soh/Network/Anchor/Packets/ServerMessage.cpp new file mode 100644 index 000000000..3af07c8b8 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/ServerMessage.cpp @@ -0,0 +1,21 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Notification/Notification.h" + +/** + * SERVER_MESSAGE + */ + +void Anchor::HandlePacket_ServerMessage(nlohmann::json payload) { + Notification::Emit({ + .prefix = "Server:", + .prefixColor = ImVec4(1.0f, 0.5f, 0.5f, 1.0f), + .message = payload["message"].get(), + }); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/SetCheckStatus.cpp b/soh/soh/Network/Anchor/Packets/SetCheckStatus.cpp new file mode 100644 index 000000000..802b33a69 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/SetCheckStatus.cpp @@ -0,0 +1,59 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" + +static bool isResultOfHandling = false; + +/** + * SET_CHECK_STATUS + * + * Fired when a check status is updated or skipped + */ + +void Anchor::SendPacket_SetCheckStatus(RandomizerCheck rc) { + if (!IsSaveLoaded() || isResultOfHandling) { + return; + } + + auto randoContext = Rando::Context::GetInstance(); + + nlohmann::json payload; + payload["type"] = SET_CHECK_STATUS; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["rc"] = rc; + payload["status"] = randoContext->GetItemLocation(rc)->GetCheckStatus(); + payload["skipped"] = randoContext->GetItemLocation(rc)->GetIsSkipped(); + payload["quiet"] = true; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_SetCheckStatus(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + auto randoContext = Rando::Context::GetInstance(); + + RandomizerCheck rc = payload["rc"].get(); + RandomizerCheckStatus status = payload["status"].get(); + bool skipped = payload["skipped"].get(); + + isResultOfHandling = true; + + if (randoContext->GetItemLocation(rc)->GetCheckStatus() != status) { + randoContext->GetItemLocation(rc)->SetCheckStatus(status); + } + if (randoContext->GetItemLocation(rc)->GetIsSkipped() != skipped) { + randoContext->GetItemLocation(rc)->SetIsSkipped(skipped); + } + + isResultOfHandling = false; +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/SetFlag.cpp b/soh/soh/Network/Anchor/Packets/SetFlag.cpp new file mode 100644 index 000000000..693c75350 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/SetFlag.cpp @@ -0,0 +1,54 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" + +/** + * SET_FLAG + * + * Fired when a flag is set in the save context + */ + +void Anchor::SendPacket_SetFlag(s16 sceneNum, s16 flagType, s16 flag) { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + payload["type"] = SET_FLAG; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["sceneNum"] = sceneNum; + payload["flagType"] = flagType; + payload["flag"] = flag; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_SetFlag(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + s16 sceneNum = payload["sceneNum"].get(); + s16 flagType = payload["flagType"].get(); + s16 flag = payload["flag"].get(); + + if (sceneNum == SCENE_ID_MAX) { + auto effect = new GameInteractionEffect::SetFlag(); + effect->parameters[0] = payload["flagType"].get(); + effect->parameters[1] = payload["flag"].get(); + effect->Apply(); + } else { + auto effect = new GameInteractionEffect::SetSceneFlag(); + effect->parameters[0] = payload["sceneNum"].get(); + effect->parameters[1] = payload["flagType"].get(); + effect->parameters[2] = payload["flag"].get(); + effect->Apply(); + } +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/TeleportTo.cpp b/soh/soh/Network/Anchor/Packets/TeleportTo.cpp new file mode 100644 index 000000000..05e3cbb83 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/TeleportTo.cpp @@ -0,0 +1,63 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Network/Anchor/JsonConversions.hpp" + +extern "C" { +#include "macros.h" +extern PlayState* gPlayState; +} + +/** + * TELEPORT_TO + * + * See REQUEST_TELEPORT for more information, this is the second part of the process. + */ + +void Anchor::SendPacket_TeleportTo(uint32_t clientId) { + if (!IsSaveLoaded()) { + return; + } + + Player* player = GET_PLAYER(gPlayState); + + nlohmann::json payload; + payload["type"] = TELEPORT_TO; + payload["targetClientId"] = clientId; + payload["entranceIndex"] = gSaveContext.entranceIndex; + payload["roomIndex"] = gPlayState->roomCtx.curRoom.num; + payload["posRot"] = player->actor.world; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_TeleportTo(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + s32 entranceIndex = payload["entranceIndex"].get(); + s8 roomIndex = payload["roomIndex"].get(); + PosRot posRot = payload["posRot"].get(); + + gPlayState->nextEntranceIndex = entranceIndex; + gPlayState->transitionTrigger = TRANS_TRIGGER_START; + gPlayState->transitionType = TRANS_TYPE_INSTANT; + gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = entranceIndex; + gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex = roomIndex; + gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = posRot.pos; + gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = posRot.rot.y; + gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0xDFF; + gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST; + gSaveContext.respawnFlag = 1; + static HOOK_ID hookId = 0; + hookId = REGISTER_VB_SHOULD(VB_INFLICT_VOID_DAMAGE, { + *should = false; + GameInteractor::Instance->UnregisterGameHookForID(hookId); + }); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/UnsetFlag.cpp b/soh/soh/Network/Anchor/Packets/UnsetFlag.cpp new file mode 100644 index 000000000..5de78595a --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/UnsetFlag.cpp @@ -0,0 +1,55 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" + +/** + * UNSET_FLAG + * + * Fired when a flag is unset in the save context + */ + +void Anchor::SendPacket_UnsetFlag(s16 sceneNum, s16 flagType, s16 flag) { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + payload["type"] = UNSET_FLAG; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["sceneNum"] = sceneNum; + payload["flagType"] = flagType; + payload["flag"] = flag; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_UnsetFlag(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + s16 sceneNum = payload["sceneNum"].get(); + s16 flagType = payload["flagType"].get(); + s16 flag = payload["flag"].get(); + + if (sceneNum == SCENE_ID_MAX) { + auto effect = new GameInteractionEffect::UnsetFlag(); + effect->parameters[0] = payload["flagType"].get(); + effect->parameters[1] = payload["flag"].get(); + effect->Apply(); + } else { + auto effect = new GameInteractionEffect::UnsetSceneFlag(); + effect->parameters[0] = payload["sceneNum"].get(); + effect->parameters[1] = payload["flagType"].get(); + effect->parameters[2] = payload["flag"].get(); + effect->Apply(); + } + +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/UpdateBeansCount.cpp b/soh/soh/Network/Anchor/Packets/UpdateBeansCount.cpp new file mode 100644 index 000000000..89e1d6443 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/UpdateBeansCount.cpp @@ -0,0 +1,43 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" + +extern "C" { +#include "macros.h" +} + +/** + * UPDATE_BEANS_COUNT + * + * Keeps the client's bean count in sync as they buy/use them + */ + +void Anchor::SendPacket_UpdateBeansCount() { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + payload["type"] = UPDATE_BEANS_COUNT; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["amount"] = AMMO(ITEM_BEAN); + payload["amountBought"] = BEANS_BOUGHT; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_UpdateBeansCount(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + AMMO(ITEM_BEAN) = payload["amount"].get(); + BEANS_BOUGHT = payload["amountBought"].get(); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/UpdateClientState.cpp b/soh/soh/Network/Anchor/Packets/UpdateClientState.cpp new file mode 100644 index 000000000..237f1baa0 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/UpdateClientState.cpp @@ -0,0 +1,77 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include "soh/Network/Anchor/JsonConversions.hpp" +#include +#include +#include "soh/OTRGlobals.h" + +extern "C" { +#include "variables.h" +extern PlayState* gPlayState; +} + +/** + * UPDATE_CLIENT_STATE + * + * Contains a small subset of data that is cached on the server and important for the client to know for various reasons + * + * Sent on various events, such as changing scenes, soft resetting, finishing the game, opening file select, etc. + * + * Note: This packet should be cross version compatible, so if you add anything here don't assume all clients will be + * providing it, consider doing a `contains` check before accessing any version specific data + */ + +nlohmann::json Anchor::PrepClientState() { + nlohmann::json payload; + payload["name"] = CVarGetString(CVAR_REMOTE_ANCHOR("Name"), ""); + payload["color"] = CVarGetColor24(CVAR_REMOTE_ANCHOR("Color"), { 100, 255, 100 }); + payload["clientVersion"] = clientVersion; + payload["teamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["online"] = true; + + if (IsSaveLoaded()) { + payload["seed"] = IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed() : 0; + payload["isSaveLoaded"] = true; + payload["isGameComplete"] = gSaveContext.sohStats.gameComplete; + payload["sceneNum"] = gPlayState->sceneNum; + payload["entranceIndex"] = gSaveContext.entranceIndex; + } else { + payload["seed"] = 0; + payload["isSaveLoaded"] = false; + payload["isGameComplete"] = false; + payload["sceneNum"] = SCENE_ID_MAX; + payload["entranceIndex"] = 0x00; + } + + return payload; +} + +void Anchor::SendPacket_UpdateClientState() { + nlohmann::json payload; + payload["type"] = UPDATE_CLIENT_STATE; + payload["state"] = PrepClientState(); + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_UpdateClientState(nlohmann::json payload) { + uint32_t clientId = payload["clientId"].get(); + + if (clients.contains(clientId)) { + AnchorClient client = payload["state"].get(); + clients[clientId].clientId = clientId; + clients[clientId].name = client.name; + clients[clientId].color = client.color; + clients[clientId].clientVersion = client.clientVersion; + clients[clientId].teamId = client.teamId; + clients[clientId].online = client.online; + clients[clientId].seed = client.seed; + clients[clientId].isSaveLoaded = client.isSaveLoaded; + clients[clientId].isGameComplete = client.isGameComplete; + clients[clientId].sceneNum = client.sceneNum; + clients[clientId].entranceIndex = client.entranceIndex; + } +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/UpdateDungeonItems.cpp b/soh/soh/Network/Anchor/Packets/UpdateDungeonItems.cpp new file mode 100644 index 000000000..c7beaa6b8 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/UpdateDungeonItems.cpp @@ -0,0 +1,42 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" + +/** + * UPDATE_DUNGEON_ITEMS + * + * This is for 2 things, first is updating the dungeon items in vanilla saves, and second is + * for ensuring the amount of keys used is synced as players are using them. + */ + +void Anchor::SendPacket_UpdateDungeonItems() { + if (!IsSaveLoaded()) { + return; + } + + nlohmann::json payload; + payload["type"] = UPDATE_DUNGEON_ITEMS; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + payload["addToQueue"] = true; + payload["mapIndex"] = gSaveContext.mapIndex; + payload["dungeonItems"] = gSaveContext.inventory.dungeonItems[gSaveContext.mapIndex]; + payload["dungeonKeys"] = gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]; + + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_UpdateDungeonItems(nlohmann::json payload) { + if (!IsSaveLoaded()) { + return; + } + + u16 mapIndex = payload["mapIndex"].get(); + gSaveContext.inventory.dungeonItems[mapIndex] = payload["dungeonItems"].get(); + gSaveContext.inventory.dungeonKeys[mapIndex] = payload["dungeonKeys"].get(); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/UpdateRoomState.cpp b/soh/soh/Network/Anchor/Packets/UpdateRoomState.cpp new file mode 100644 index 000000000..ce08f3640 --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/UpdateRoomState.cpp @@ -0,0 +1,47 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include "soh/Network/Anchor/JsonConversions.hpp" +#include +#include +#include "soh/OTRGlobals.h" + +extern "C" { +#include "variables.h" +extern PlayState* gPlayState; +} + +/** + * UPDATE_ROOM_STATE + */ + +nlohmann::json Anchor::PrepRoomState() { + nlohmann::json payload; + payload["ownerClientId"] = ownClientId; + payload["pvpMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.PvpMode"), 1); + payload["showLocationsMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.ShowLocationsMode"), 1); + payload["teleportMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.TeleportMode"), 1); + + return payload; +} + +void Anchor::SendPacket_UpdateRoomState() { + nlohmann::json payload; + payload["type"] = UPDATE_ROOM_STATE; + payload["state"] = PrepRoomState(); + + Network::SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_UpdateRoomState(nlohmann::json payload) { + if (!payload.contains("state")) { + return; + } + + roomState.ownerClientId = payload["state"]["ownerClientId"].get(); + roomState.pvpMode = payload["state"]["pvpMode"].get(); + roomState.showLocationsMode = payload["state"]["showLocationsMode"].get(); + roomState.teleportMode = payload["state"]["teleportMode"].get(); +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp b/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp new file mode 100644 index 000000000..d17981f4f --- /dev/null +++ b/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp @@ -0,0 +1,273 @@ +#ifdef ENABLE_REMOTE_CONTROL + +#include "soh/Network/Anchor/Anchor.h" +#include "soh/Network/Anchor/JsonConversions.hpp" +#include +#include +#include "soh/Enhancements/randomizer/entrance.h" +#include "soh/Enhancements/randomizer/dungeon.h" +#include "soh/OTRGlobals.h" +#include "soh/Notification/Notification.h" + +extern "C" { +#include "variables.h" +extern PlayState* gPlayState; +} + +/** + * UPDATE_TEAM_STATE + * + * Pushes the current save state to the server for other teammates to use. + * + * Fires when the server passes on a REQUEST_TEAM_STATE packet, or when this client saves the game + * + * When sending this packet we will assume that the team queue has been emptied for this client, so the queue + * stored in the server will be cleared. + * + * When receiving this packet, if there is items in the team queue, we will play them back in order. + */ + +void Anchor::SendPacket_UpdateTeamState() { + if (!IsSaveLoaded()) { + return; + } + + json payload; + payload["type"] = UPDATE_TEAM_STATE; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + + // Assume the team queue has been emptied, so clear it + payload["queue"] = json::array(); + + payload["state"] = gSaveContext; + // manually update current scene flags + payload["state"]["sceneFlags"][gPlayState->sceneNum * 4] = gPlayState->actorCtx.flags.chest; + payload["state"]["sceneFlags"][gPlayState->sceneNum * 4 + 1] = gPlayState->actorCtx.flags.swch; + payload["state"]["sceneFlags"][gPlayState->sceneNum * 4 + 2] = gPlayState->actorCtx.flags.clear; + payload["state"]["sceneFlags"][gPlayState->sceneNum * 4 + 3] = gPlayState->actorCtx.flags.collect; + + // The commented out code below is an attempt at sending the entire randomizer seed over, in hopes that a player doesn't have to generate the seed themselves + // Currently it doesn't work :) + if (IS_RANDO) { + auto randoContext = Rando::Context::GetInstance(); + + payload["state"]["rando"] = json::object(); + payload["state"]["rando"]["itemLocations"] = json::array(); + for (int i = 0; i < RC_MAX; i++) { + payload["state"]["rando"]["itemLocations"][i] = json::array(); + // payload["state"]["rando"]["itemLocations"][i]["rgID"] = randoContext->GetItemLocation(i)->GetPlacedRandomizerGet(); + payload["state"]["rando"]["itemLocations"][i][0] = randoContext->GetItemLocation(i)->GetCheckStatus(); + payload["state"]["rando"]["itemLocations"][i][1] = (u8)randoContext->GetItemLocation(i)->GetIsSkipped(); + + // if (randoContext->GetItemLocation(i)->GetPlacedRandomizerGet() == RG_ICE_TRAP) { + // payload["state"]["rando"]["itemLocations"][i]["fakeRgID"] = randoContext->GetItemOverride(i).LooksLike(); + // payload["state"]["rando"]["itemLocations"][i]["trickName"] = json::object(); + // payload["state"]["rando"]["itemLocations"][i]["trickName"]["english"] = randoContext->GetItemOverride(i).GetTrickName().GetEnglish(); + // payload["state"]["rando"]["itemLocations"][i]["trickName"]["french"] = randoContext->GetItemOverride(i).GetTrickName().GetFrench(); + // } + // if (randoContext->GetItemLocation(i)->HasCustomPrice()) { + // payload["state"]["rando"]["itemLocations"][i]["price"] = randoContext->GetItemLocation(i)->GetPrice(); + // } + } + + // auto entranceCtx = randoContext->GetEntranceShuffler(); + // for (int i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) { + // payload["state"]["rando"]["entrances"][i] = json::object(); + // payload["state"]["rando"]["entrances"][i]["type"] = entranceCtx->entranceOverrides[i].type; + // payload["state"]["rando"]["entrances"][i]["index"] = entranceCtx->entranceOverrides[i].index; + // payload["state"]["rando"]["entrances"][i]["destination"] = entranceCtx->entranceOverrides[i].destination; + // payload["state"]["rando"]["entrances"][i]["override"] = entranceCtx->entranceOverrides[i].override; + // payload["state"]["rando"]["entrances"][i]["overrideDestination"] = entranceCtx->entranceOverrides[i].overrideDestination; + // } + + // payload["state"]["rando"]["seed"] = json::array(); + // for (int i = 0; i < randoContext->hashIconIndexes.size(); i++) { + // payload["state"]["rando"]["seed"][i] = randoContext->hashIconIndexes[i]; + // } + // payload["state"]["rando"]["inputSeed"] = randoContext->GetSettings()->GetSeedString(); + // payload["state"]["rando"]["finalSeed"] = randoContext->GetSettings()->GetSeed(); + + // payload["state"]["rando"]["randoSettings"] = json::array(); + // for (int i = 0; i < RSK_MAX; i++) { + // payload["state"]["rando"]["randoSettings"][i] = randoContext->GetOption((RandomizerSettingKey(i))).GetSelectedOptionIndex(); + // } + + // payload["state"]["rando"]["masterQuestDungeonCount"] = randoContext->GetDungeons()->CountMQ(); + // payload["state"]["rando"]["masterQuestDungeons"] = json::array(); + // for (int i = 0; i < randoContext->GetDungeons()->GetDungeonListSize(); i++) { + // payload["state"]["rando"]["masterQuestDungeons"][i] = randoContext->GetDungeon(i)->IsMQ(); + // } + // for (int i = 0; i < randoContext->GetTrials()->GetTrialListSize(); i++) { + // payload["state"]["rando"]["requiredTrials"][i] = randoContext->GetTrial(i)->IsRequired(); + // } + } + + SendJsonToRemote(payload); +} + +void Anchor::SendPacket_ClearTeamState() { + if (!IsSaveLoaded()) { + return; + } + + json payload; + payload["type"] = UPDATE_TEAM_STATE; + payload["targetTeamId"] = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default"); + + payload["queue"] = json::array(); + payload["state"] = json::object(); + SendJsonToRemote(payload); +} + +void Anchor::HandlePacket_UpdateTeamState(nlohmann::json payload) { + isHandlingUpdateTeamState = true; + // This can happen in between file select and the game starting, so we cant use this check, but we need to ensure we + // be careful to wrap PlayState usage in this check + // if (!IsSaveLoaded()) { + // return; + // } + + if (payload.contains("state")) { + SaveContext loadedData = payload["state"].get(); + + gSaveContext.questId = loadedData.questId; + gSaveContext.healthCapacity = loadedData.healthCapacity; + gSaveContext.magicLevel = loadedData.magicLevel; + gSaveContext.magicCapacity = gSaveContext.magic = loadedData.magicCapacity; + gSaveContext.isMagicAcquired = loadedData.isMagicAcquired; + gSaveContext.isDoubleMagicAcquired = loadedData.isDoubleMagicAcquired; + gSaveContext.isDoubleDefenseAcquired = loadedData.isDoubleDefenseAcquired; + gSaveContext.bgsFlag = loadedData.bgsFlag; + gSaveContext.swordHealth = loadedData.swordHealth; + gSaveContext.adultTradeItems = loadedData.adultTradeItems; + gSaveContext.triforcePiecesCollected = loadedData.triforcePiecesCollected; + + for (int i = 0; i < 124; i++) { + gSaveContext.sceneFlags[i] = loadedData.sceneFlags[i]; + if (IsSaveLoaded() && gPlayState->sceneNum == i) { + gPlayState->actorCtx.flags.chest = loadedData.sceneFlags[i].chest; + gPlayState->actorCtx.flags.swch = loadedData.sceneFlags[i].swch; + gPlayState->actorCtx.flags.clear = loadedData.sceneFlags[i].clear; + gPlayState->actorCtx.flags.collect = loadedData.sceneFlags[i].collect; + } + } + + for (int i = 0; i < 14; i++) { + gSaveContext.eventChkInf[i] = loadedData.eventChkInf[i]; + } + + for (int i = 0; i < 4; i++) { + gSaveContext.itemGetInf[i] = loadedData.itemGetInf[i]; + } + + // Skip last row of infTable, don't want to sync swordless flag + for (int i = 0; i < 29; i++) { + gSaveContext.infTable[i] = loadedData.infTable[i]; + } + + for (int i = 0; i < 52; i++) { + gSaveContext.randomizerInf[i] = loadedData.randomizerInf[i]; + } + + for (int i = 0; i < 6; i++) { + gSaveContext.gsFlags[i] = loadedData.gsFlags[i]; + } + + gSaveContext.sohStats.fileCreatedAt = loadedData.sohStats.fileCreatedAt; + + // Restore master sword state + u8 hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, 1); + if (hasMasterSword) { + loadedData.inventory.equipment |= 0x2; + } else { + loadedData.inventory.equipment &= ~0x2; + } + + // Restore bottle contents (unless it's ruto's letter) + for (int i = 0; i < 4; i++) { + if (gSaveContext.inventory.items[SLOT_BOTTLE_1 + i] != ITEM_NONE && gSaveContext.inventory.items[SLOT_BOTTLE_1 + i] != ITEM_LETTER_RUTO) { + loadedData.inventory.items[SLOT_BOTTLE_1 + i] = gSaveContext.inventory.items[SLOT_BOTTLE_1 + i]; + } + } + + // Restore ammo if it's non-zero, unless it's beans + for (int i = 0; i < ARRAY_COUNT(gSaveContext.inventory.ammo); i++) { + if (gSaveContext.inventory.ammo[i] != 0 && i != SLOT(ITEM_BEAN) && i != SLOT(ITEM_BEAN + 1)) { + loadedData.inventory.ammo[i] = gSaveContext.inventory.ammo[i]; + } + } + + gSaveContext.inventory = loadedData.inventory; + + // The commented out code below is an attempt at sending the entire randomizer seed over, in hopes that a player doesn't have to generate the seed themselves + // Currently it doesn't work :) + if (IS_RANDO && payload["state"].contains("rando")) { + auto randoContext = Rando::Context::GetInstance(); + + for (int i = 0; i < RC_MAX; i++) { + // randoContext->GetItemLocation(i)->RefPlacedItem() = payload["state"]["rando"]["itemLocations"][i]["rgID"].get(); + OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetCheckStatus(payload["state"]["rando"]["itemLocations"][i][0].get()); + OTRGlobals::Instance->gRandoContext->GetItemLocation(i)->SetIsSkipped(payload["state"]["rando"]["itemLocations"][i][0].get()); + + // if (payload["state"]["rando"]["itemLocations"][i].contains("fakeRgID")) { + // randoContext->overrides.emplace(static_cast(i), Rando::ItemOverride(static_cast(i), payload["state"]["rando"]["itemLocations"][i]["fakeRgID"].get())); + // randoContext->GetItemOverride(i).GetTrickName().english = payload["state"]["rando"]["itemLocations"][i]["trickName"]["english"].get(); + // randoContext->GetItemOverride(i).GetTrickName().french = payload["state"]["rando"]["itemLocations"][i]["trickName"]["french"].get(); + // } + // if (payload["state"]["rando"]["itemLocations"][i].contains("price")) { + // u16 price = payload["state"]["rando"]["itemLocations"][i]["price"].get(); + // if (price > 0) { + // randoContext->GetItemLocation(i)->SetCustomPrice(price); + // } + // } + } + + // auto entranceCtx = randoContext->GetEntranceShuffler(); + // for (int i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) { + // entranceCtx->entranceOverrides[i].type = payload["state"]["rando"]["entrances"][i]["type"].get(); + // entranceCtx->entranceOverrides[i].index = payload["state"]["rando"]["entrances"][i]["index"].get(); + // entranceCtx->entranceOverrides[i].destination = payload["state"]["rando"]["entrances"][i]["destination"].get(); + // entranceCtx->entranceOverrides[i].override = payload["state"]["rando"]["entrances"][i]["override"].get(); + // entranceCtx->entranceOverrides[i].overrideDestination = payload["state"]["rando"]["entrances"][i]["overrideDestination"].get(); + // } + + // for (int i = 0; i < randoContext->hashIconIndexes.size(); i++) { + // randoContext->hashIconIndexes[i] = payload["state"]["rando"]["seed"][i].get(); + // } + // randoContext->GetSettings()->SetSeedString(payload["state"]["rando"]["inputSeed"].get()); + // randoContext->GetSettings()->SetSeed(payload["state"]["rando"]["finalSeed"].get()); + + // for (int i = 0; i < RSK_MAX; i++) { + // randoContext->GetOption(RandomizerSettingKey(i)).SetSelectedIndex(payload["state"]["rando"]["randoSettings"][i].get()); + // } + + // randoContext->GetDungeons()->ClearAllMQ(); + // for (int i = 0; i < randoContext->GetDungeons()->GetDungeonListSize(); i++) { + // if (payload["state"]["rando"]["masterQuestDungeons"][i].get()) { + // randoContext->GetDungeon(i)->SetMQ(); + // } + // } + + // randoContext->GetTrials()->SkipAll(); + // for (int i = 0; i < randoContext->GetTrials()->GetTrialListSize(); i++) { + // if (payload["state"]["rando"]["requiredTrials"][i].get()) { + // randoContext->GetTrial(i)->SetAsRequired(); + // } + // } + } + + Notification::Emit({ + .message = "Save updated from team", + }); + } + + if (payload.contains("queue")) { + for (auto& item : payload["queue"]) { + nlohmann::json itemPayload = nlohmann::json::parse(item.get()); + Anchor::Instance->OnIncomingJson(itemPayload); + } + } + isHandlingUpdateTeamState = false; +} + +#endif // ENABLE_REMOTE_CONTROL diff --git a/soh/soh/Notification/Notification.cpp b/soh/soh/Notification/Notification.cpp index ebc4e168b..5bc0e8974 100644 --- a/soh/soh/Notification/Notification.cpp +++ b/soh/soh/Notification/Notification.cpp @@ -20,7 +20,7 @@ void Window::Draw() { const float margin = 30.0f; const float padding = 10.0f; - int position = CVarGetInteger(CVAR_SETTING("Notifications.Position"), 0); + int position = CVarGetInteger(CVAR_SETTING("Notifications.Position"), 3); // Top Left ImVec2 basePosition; diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index b5627db36..bb312c39a 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -77,13 +77,16 @@ #ifdef ENABLE_REMOTE_CONTROL #include "soh/Network/CrowdControl/CrowdControl.h" #include "soh/Network/Sail/Sail.h" +#include "soh/Network/Anchor/Anchor.h" CrowdControl* CrowdControl::Instance; Sail* Sail::Instance; +Anchor* Anchor::Instance; #endif #include "Enhancements/mods.h" #include "Enhancements/game-interactor/GameInteractor.h" #include "Enhancements/randomizer/draw.h" +#include "Enhancements/custom-collectible/CustomCollectible.h" #include // Resource Types/Factories @@ -703,6 +706,7 @@ extern "C" void VanillaItemTable_Init() { GET_ITEM(ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, GI_NUT_UPGRADE_30), GET_ITEM(ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, GI_NUT_UPGRADE_40), GET_ITEM(ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG_50, 0x6C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, GI_BULLET_BAG_50), + GET_ITEM(ITEM_SHIP, OBJECT_UNSET_16E, GID_MAXIMUM, 0x00, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, GI_SHIP), GET_ITEM_NONE, GET_ITEM_NONE, GET_ITEM_NONE // GI_MAX - if you need to add to this table insert it before this entry. @@ -1164,6 +1168,7 @@ extern "C" void InitOTR() { #ifdef ENABLE_REMOTE_CONTROL CrowdControl::Instance = new CrowdControl(); Sail::Instance = new Sail(); + Anchor::Instance = new Anchor(); #endif OTRMessage_Init(); @@ -1173,6 +1178,7 @@ extern "C" void InitOTR() { DebugConsole_Init(); InitMods(); + CustomCollectible::RegisterHooks(); ActorDB::AddBuiltInCustomActors(); // #region SOH [Randomizer] TODO: Remove these and refactor spoiler file handling for randomizer CVarClear(CVAR_GENERAL("RandomizerNewFileDropped")); @@ -1184,11 +1190,24 @@ extern "C" void InitOTR() { time_t now = time(NULL); tm *tm_now = localtime(&now); - if (tm_now->tm_mon == 11 && tm_now->tm_mday >= 24 && tm_now->tm_mday <= 25) { - CVarRegisterInteger(CVAR_GENERAL("LetItSnow"), 1); - } else { - CVarClear(CVAR_GENERAL("LetItSnow")); - } + // if (tm_now->tm_mon == 11 && tm_now->tm_mday >= 24 && tm_now->tm_mday <= 25) { + // CVarRegisterInteger("gLetItSnow", 1); + // } else { + // CVarClear("gLetItSnow"); + // } + + CVarRegisterInteger("gLetItSnow", 1); + CVarRegisterInteger("gAltAssets", 1); + CVarRegisterInteger("gCosmetics.Hud_AButton.Changed", 1); + CVarRegisterColor("gCosmetics.Hud_AButton.Value", Color_RGBA8{ 255, 255, 255, 255 }); + CVarRegisterInteger("gCosmetics.Hud_BButton.Changed", 1); + CVarRegisterColor("gCosmetics.Hud_BButton.Value", Color_RGBA8{ 255, 255, 255, 255 }); + CVarRegisterInteger("gCosmetics.Hud_CButtons.Changed", 1); + CVarRegisterColor("gCosmetics.Hud_CButtons.Value", Color_RGBA8{ 255, 255, 255, 255 }); + CVarRegisterInteger("gCosmetics.Consumable_Hearts.Changed", 1); + CVarRegisterColor("gCosmetics.Consumable_Hearts.Value", Color_RGBA8{ 255, 158, 0, 255 }); + CVarRegisterInteger("gCosmetics.Consumable_Magic.Changed", 1); + CVarRegisterColor("gCosmetics.Consumable_Magic.Value", Color_RGBA8{ 255, 0, 0, 255 }); srand(now); #ifdef ENABLE_REMOTE_CONTROL @@ -1199,6 +1218,9 @@ extern "C" void InitOTR() { if (CVarGetInteger(CVAR_REMOTE_SAIL("Enabled"), 0)) { Sail::Instance->Enable(); } + if (CVarGetInteger(CVAR_REMOTE_ANCHOR("Enabled"), 0)) { + Anchor::Instance->Enable(); + } #endif } @@ -1216,6 +1238,9 @@ extern "C" void DeinitOTR() { if (CVarGetInteger(CVAR_REMOTE_SAIL("Enabled"), 0)) { Sail::Instance->Disable(); } + if (CVarGetInteger(CVAR_REMOTE_ANCHOR("Enabled"), 0)) { + Anchor::Instance->Disable(); + } SDLNet_Quit(); #endif diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 1edec3025..5e8962b9d 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -1223,7 +1223,7 @@ void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, int se delete saveContext; InitMeta(fileNum); - GameInteractor::Instance->ExecuteHooks(fileNum); + GameInteractor::Instance->ExecuteHooks(fileNum, sectionID); SPDLOG_INFO("Save File Finish - fileNum: {}", fileNum); saveMtx.unlock(); } @@ -2459,6 +2459,7 @@ void SaveManager::CopyZeldaFile(int from, int to) { fileMetaInfo[to].buildVersionPatch = fileMetaInfo[from].buildVersionPatch; SohUtils::CopyStringToCharArray(fileMetaInfo[to].buildVersion, fileMetaInfo[from].buildVersion, ARRAY_COUNT(fileMetaInfo[to].buildVersion)); + GameInteractor::Instance->ExecuteHooks(from, to); } void SaveManager::DeleteZeldaFile(int fileNum) { diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 2dbf62a99..b49cdb13f 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -38,7 +38,11 @@ #include "Enhancements/resolution-editor/ResolutionEditor.h" #include "Enhancements/debugger/MessageViewer.h" #include "soh/Notification/Notification.h" +#include "soh/Enhancements/Holiday/Caladius.h" #include "soh/Enhancements/TimeDisplay/TimeDisplay.h" +#ifdef ENABLE_REMOTE_CONTROL +#include "soh/Network/Anchor/Anchor.h" +#endif bool isBetaQuestEnabled = false; @@ -137,7 +141,11 @@ namespace SohGui { std::shared_ptr mAdvancedResolutionSettingsWindow; std::shared_ptr mModalWindow; std::shared_ptr mNotificationWindow; + std::shared_ptr mCaladiusWindow; std::shared_ptr mTimeDisplayWindow; +#ifdef ENABLE_REMOTE_CONTROL + std::shared_ptr mAnchorRoomWindow; +#endif void SetupGuiElements() { auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); @@ -223,8 +231,15 @@ namespace SohGui { mNotificationWindow = std::make_shared(CVAR_WINDOW("Notifications"), "Notifications Window"); gui->AddGuiWindow(mNotificationWindow); mNotificationWindow->Show(); + mCaladiusWindow = std::make_shared(CVAR_WINDOW("Holiday Cal"), "Holiday Cal"); + gui->AddGuiWindow(mCaladiusWindow); + mCaladiusWindow->Show(); mTimeDisplayWindow = std::make_shared(CVAR_WINDOW("TimeDisplayEnabled"), "Additional Timers"); gui->AddGuiWindow(mTimeDisplayWindow); +#ifdef ENABLE_REMOTE_CONTROL + mAnchorRoomWindow = std::make_shared(CVAR_WINDOW("AnchorRoom"), "Anchor Room"); + gui->AddGuiWindow(mAnchorRoomWindow); +#endif } void Destroy() { @@ -259,8 +274,12 @@ namespace SohGui { mInputViewer = nullptr; mInputViewerSettings = nullptr; mTimeSplitWindow = nullptr; + mCaladiusWindow = nullptr; mPlandomizerWindow = nullptr; mTimeDisplayWindow = nullptr; +#ifdef ENABLE_REMOTE_CONTROL + mAnchorRoomWindow = nullptr; +#endif } void RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, std::function button1callback, std::function button2callback) { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index ba9e683bf..8e36abe6c 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -22,6 +22,7 @@ #ifdef ENABLE_REMOTE_CONTROL #include "soh/Network/CrowdControl/CrowdControl.h" #include "soh/Network/Sail/Sail.h" +#include "soh/Network/Anchor/Anchor.h" #endif @@ -43,6 +44,7 @@ #include "Enhancements/resolution-editor/ResolutionEditor.h" #include "Enhancements/enemyrandomizer.h" #include "Enhancements/timesplits/TimeSplits.h" +#include "Enhancements/Holiday/Holiday.hpp" #include "Enhancements/randomizer/Plandomizer.h" #include "Enhancements/TimeDisplay/TimeDisplay.h" @@ -584,7 +586,7 @@ void DrawSettingsMenu() { }; ImGui::Text("Position"); - UIWidgets::EnhancementCombobox(CVAR_SETTING("Notifications.Position"), notificationPosition, 0); + UIWidgets::EnhancementCombobox(CVAR_SETTING("Notifications.Position"), notificationPosition, 3); UIWidgets::EnhancementSliderFloat("Duration: %.1f seconds", "##NotificationDuration", CVAR_SETTING("Notifications.Duration"), 3.0f, 30.0f, "", 10.0f, false, true, false); UIWidgets::EnhancementSliderFloat("BG Opacity: %.1f %%", "##NotificaitonBgOpacity", CVAR_SETTING("Notifications.BgOpacity"), 0.0f, 1.0f, "", 0.5f, true, true, false); UIWidgets::EnhancementSliderFloat("Size: %.1f", "##NotificaitonSize", CVAR_SETTING("Notifications.Size"), 1.0f, 20.0f, "", 1.8f, false, true, false); @@ -2102,6 +2104,7 @@ void DrawRemoteControlMenu() { if (ImGui::BeginMenu("Network")) { Sail::Instance->DrawMenu(); CrowdControl::Instance->DrawMenu(); + Anchor::Instance->DrawMenu(); ImGui::EndMenu(); } } @@ -2333,6 +2336,10 @@ void SohMenuBar::DrawElement() { DrawRandomizerMenu(); + ImGui::SetCursorPosY(0.0f); + + DrawHolidayMenu(); + ImGui::PopStyleVar(1); ImGui::EndMenuBar(); } diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index 23af9f613..958685eac 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -825,7 +825,7 @@ namespace UIWidgets { return 0; } - bool InputString(const char* label, std::string* value) { - return ImGui::InputText(label, (char*)value->c_str(), value->capacity() + 1, ImGuiInputTextFlags_CallbackResize, InputTextResizeCallback, value); + bool InputString(const char* label, std::string* value, ImGuiInputTextFlags flags) { + return ImGui::InputText(label, (char*)value->c_str(), value->capacity() + 1, ImGuiInputTextFlags_CallbackResize | flags, InputTextResizeCallback, value); } } diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp index 5903220d2..0ad2a4703 100644 --- a/soh/soh/UIWidgets.hpp +++ b/soh/soh/UIWidgets.hpp @@ -102,7 +102,7 @@ namespace UIWidgets { void DrawFlagArray16(const std::string& name, uint16_t& flags); void DrawFlagArray8(const std::string& name, uint8_t& flags); bool StateButton(const char* str_id, const char* label); - bool InputString(const char* label, std::string* value); + bool InputString(const char* label, std::string* value, ImGuiInputTextFlags flags = 0); } #endif /* UIWidgets_hpp */ diff --git a/soh/soh/cvar_prefixes.h b/soh/soh/cvar_prefixes.h index 6ddde97bd..cee81167e 100644 --- a/soh/soh/cvar_prefixes.h +++ b/soh/soh/cvar_prefixes.h @@ -14,4 +14,5 @@ #define CVAR_GENERAL(var) CVAR_PREFIX_GENERAL "." var #define CVAR_REMOTE(var) CVAR_PREFIX_REMOTE "." var #define CVAR_REMOTE_CROWD_CONTROL(var) CVAR_REMOTE(".CrowdControl." var) -#define CVAR_REMOTE_SAIL(var) CVAR_REMOTE(".Sail." var) \ No newline at end of file +#define CVAR_REMOTE_SAIL(var) CVAR_REMOTE(".Sail." var) +#define CVAR_REMOTE_ANCHOR(var) CVAR_REMOTE(".Anchor." var) diff --git a/soh/soh/util.cpp b/soh/soh/util.cpp index faa171231..8d675c17c 100644 --- a/soh/soh/util.cpp +++ b/soh/soh/util.cpp @@ -117,6 +117,7 @@ std::vector sceneNames = { "Castle Hedge Maze (Early)", "Sasa Test", "Treasure Chest Room", + "Unknown", }; std::vector itemNames = { @@ -391,6 +392,19 @@ size_t SohUtils::CopyStringToCharBuffer(char* buffer, const std::string& source, return 0; } +int SohUtils::CopyStringToCharBuffer(const std::string& inputStr, char* buffer, const int maxBufferSize) { + if (!inputStr.empty()) { + // Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents negatives. + memset(buffer, 0, std::max(0, maxBufferSize)); + // Gaurentee that this value will be greater than 0, regardless of passed variables. + const int copiedCharLen = std::min(std::max(0, maxBufferSize - 1), inputStr.length()); + memcpy(buffer, inputStr.c_str(), copiedCharLen); + return copiedCharLen; + } + + return 0; +} + bool SohUtils::IsStringEmpty(std::string str) { // Remove spaces at the beginning of the string std::string::size_type start = str.find_first_not_of(' '); diff --git a/soh/soh/util.h b/soh/soh/util.h index a37279a18..a566a5382 100644 --- a/soh/soh/util.h +++ b/soh/soh/util.h @@ -20,6 +20,7 @@ namespace SohUtils { // Copies a string into a char buffer up to maxBufferSize characters. This does NOT insert a null terminator // on the end, as this is used for in-game messages which are not null-terminated. size_t CopyStringToCharBuffer(char* buffer, const std::string& source, size_t maxBufferSize); + int CopyStringToCharBuffer(const std::string& inputStr, char* buffer, const int maxBufferSize); bool IsStringEmpty(std::string str); } // namespace SohUtils diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 70c7a3233..8d08d2112 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1231,14 +1231,19 @@ void Actor_Init(Actor* actor, PlayState* play) { ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f); if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) { Actor_SetObjectDependency(play, actor); - actor->init(actor, play); - actor->init = NULL; + if (GameInteractor_ShouldActorInit(actor)) { + actor->init(actor, play); + actor->init = NULL; - GameInteractor_ExecuteOnActorInit(actor); + GameInteractor_ExecuteOnActorInit(actor); - // For enemy health bar we need to know the max health during init - if (actor->category == ACTORCAT_ENEMY) { - actor->maximumHealth = actor->colChkInfo.health; + // For enemy health bar we need to know the max health during init + if (actor->category == ACTORCAT_ENEMY) { + actor->maximumHealth = actor->colChkInfo.health; + } + } else { + actor->init = NULL; + Actor_Kill(actor); } } } @@ -2210,6 +2215,10 @@ void Player_PlaySfx(Actor* actor, u16 sfxId) { // Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &D_801333E0 , &D_801333E0, &D_801333E8); Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &freqMultiplier, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } + + if (actor->id == ACTOR_PLAYER) { + GameInteractor_ExecuteOnPlayerSfx(sfxId); + } } void Audio_PlayActorSound2(Actor* actor, u16 sfxId) { @@ -2589,14 +2598,19 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) { Actor_SetObjectDependency(play, actor); - actor->init(actor, play); - actor->init = NULL; + if (GameInteractor_ShouldActorInit(actor)) { + actor->init(actor, play); + actor->init = NULL; - GameInteractor_ExecuteOnActorInit(actor); + GameInteractor_ExecuteOnActorInit(actor); - // For enemy health bar we need to know the max health during init - if (actor->category == ACTORCAT_ENEMY) { - actor->maximumHealth = actor->colChkInfo.health; + // For enemy health bar we need to know the max health during init + if (actor->category == ACTORCAT_ENEMY) { + actor->maximumHealth = actor->colChkInfo.health; + } + } else { + actor->init = NULL; + Actor_Kill(actor); } } actor = actor->next; @@ -2746,6 +2760,7 @@ void Actor_Draw(PlayState* play, Actor* actor) { } actor->draw(actor, play); + GameInteractor_ExecuteOnActorDraw(actor); if (actor->colorFilterTimer != 0) { if (actor->colorFilterParams & 0x2000) { @@ -3299,7 +3314,7 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos objBankIndex = Object_GetIndex(&gPlayState->objectCtx, dbEntry->objectId); - if (objBankIndex < 0 && (!gMapLoading || CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0))) { + if (objBankIndex < 0 && (!gMapLoading || CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gHoliday.Caladius.Blitz.Enabled", 0))) { objBankIndex = 0; } diff --git a/soh/src/code/z_draw.c b/soh/src/code/z_draw.c index e27f230b1..caf31a234 100644 --- a/soh/src/code/z_draw.c +++ b/soh/src/code/z_draw.c @@ -399,6 +399,9 @@ DrawItemTableEntry sDrawItemTable[] = { * Calls the corresponding draw function for the given draw ID */ void GetItem_Draw(PlayState* play, s16 drawId) { + if (drawId < 0 || drawId >= GID_MAXIMUM) { + return; + } sDrawItemTable[drawId].drawFunc(play, drawId); } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 1bd859718..b71a19feb 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -775,6 +775,13 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { EnItem00* this = (EnItem00*)thisx; s32 pad; + // #region SOH [Co-op] + if (Flags_GetCollectible(play, this->collectibleFlag)) { + Actor_Kill(&this->actor); + return; + } + // #endregion + // Rotate some drops when 3D drops are on, otherwise reset rotation back to 0 for billboard effect if ( (this->actor.params == ITEM00_HEART && this->unk_15A >= 0) || diff --git a/soh/src/code/z_kankyo.c b/soh/src/code/z_kankyo.c index 6e3736b77..ad4883a77 100644 --- a/soh/src/code/z_kankyo.c +++ b/soh/src/code/z_kankyo.c @@ -2291,17 +2291,17 @@ void Environment_FillScreen(GraphicsContext* gfxCtx, u8 red, u8 green, u8 blue, } Color_RGB8 sSandstormPrimColors[] = { - { 210, 156, 85 }, - { 255, 200, 100 }, - { 225, 160, 50 }, - { 105, 90, 40 }, + { 210, 210, 210 }, + { 255, 255, 255 }, + { 225, 225, 225 }, + { 105, 105, 105 }, }; Color_RGB8 sSandstormEnvColors[] = { - { 155, 106, 35 }, - { 200, 150, 50 }, - { 170, 110, 0 }, - { 50, 40, 0 }, + { 155, 155, 155 }, + { 200, 200, 200 }, + { 170, 170, 170 }, + { 50, 50, 50 }, }; u16 previousPatchedSandstormScreenSize = 0; diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index e6b944a73..501e49195 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1672,6 +1672,9 @@ void Message_OpenText(PlayState* play, u16 textId) { Font* font = &msgCtx->font; s16 textBoxType; + bool loadFromMessageTable = true; + GameInteractor_ExecuteOnOpenText(&textId, &loadFromMessageTable); + if (msgCtx->msgMode == MSGMODE_NONE) { gSaveContext.unk_13EE = gSaveContext.unk_13EA; } @@ -1730,7 +1733,9 @@ void Message_OpenText(PlayState* play, u16 textId) { } // RANDOTODO: Use this for ice trap messages - if (CustomMessage_RetrieveIfExists(play)) { + if (!loadFromMessageTable) { + // no-op + } else if (CustomMessage_RetrieveIfExists(play)) { osSyncPrintf("Found custom message"); } else if (sTextIsCredits) { Message_FindCreditsMessage(play, textId); diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index d2c3e1a26..71bc672ac 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1891,6 +1891,12 @@ u8 Return_Item(u8 itemID, ModIndex modId, ItemID returnItem) { * @return u8 */ u8 Item_Give(PlayState* play, u8 item) { + // TODO: Add ShouldItemGive + // if (!GameInteractor_ShouldItemGive(item) || item == ITEM_SHIP) { + if (item == ITEM_SHIP) { + return ITEM_NONE; + } + //prevents getting sticks without the bag in case something got missed if ( IS_RANDO && @@ -2486,6 +2492,11 @@ u8 Item_CheckObtainability(u8 item) { s16 slot = SLOT(item); s32 temp; + // SOH [Enhancements] Added to enable custom item gives + if (item == ITEM_SHIP) { + return ITEM_NONE; + } + if (item >= ITEM_STICKS_5) { slot = SLOT(sExtraItemBases[item - ITEM_STICKS_5]); } @@ -4730,6 +4741,11 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { } ammo = AMMO(i); + if (CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0) && + gSaveContext.equips.buttonItems[button] == ITEM_BOW && + AMMO(ITEM_BOMB) != 0 && AMMO(ITEM_BOMB) < AMMO(ITEM_BOW)) { + ammo = AMMO(ITEM_BOMB); + } gDPPipeSync(OVERLAY_DISP++); @@ -4742,6 +4758,11 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { if (ammo < 0) { ammo = 0; } + } else if (gSaveContext.equips.buttonItems[button] == ITEM_BOW && + CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) { + if (AMMO(ITEM_BOMB) != 0 && ammo == MIN(CUR_CAPACITY(UPG_QUIVER), CUR_CAPACITY(UPG_BOMB_BAG))) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 120, 255, 0, alpha); + } } else if (((i == ITEM_BOW) && (AMMO(i) == CUR_CAPACITY(UPG_QUIVER))) || ((i == ITEM_BOMB) && (AMMO(i) == CUR_CAPACITY(UPG_BOMB_BAG))) || ((i == ITEM_SLINGSHOT) && (AMMO(i) == CUR_CAPACITY(UPG_BULLET_BAG))) || @@ -5319,6 +5340,9 @@ void Interface_Draw(PlayState* play) { if (gSaveContext.equips.buttonItems[1] < 0xF0) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->cLeftAlpha); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); + if (gSaveContext.equips.buttonItems[1] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) { + Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 1); + } Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[1]], 1); gDPPipeSync(OVERLAY_DISP++); gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, @@ -5332,6 +5356,9 @@ void Interface_Draw(PlayState* play) { if (gSaveContext.equips.buttonItems[2] < 0xF0) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->cDownAlpha); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); + if (gSaveContext.equips.buttonItems[2] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) { + Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 2); + } Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[2]], 2); gDPPipeSync(OVERLAY_DISP++); gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, @@ -5345,6 +5372,9 @@ void Interface_Draw(PlayState* play) { if (gSaveContext.equips.buttonItems[3] < 0xF0) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->cRightAlpha); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); + if (gSaveContext.equips.buttonItems[3] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) { + Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 3); + } Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[3]], 3); gDPPipeSync(OVERLAY_DISP++); gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, @@ -5404,6 +5434,9 @@ void Interface_Draw(PlayState* play) { if (gSaveContext.equips.buttonItems[4] < 0xF0) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadUpAlpha); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); + if (gSaveContext.equips.buttonItems[4] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) { + Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 4); + } Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[4]], 4); gDPPipeSync(OVERLAY_DISP++); gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, @@ -5415,6 +5448,9 @@ void Interface_Draw(PlayState* play) { if (gSaveContext.equips.buttonItems[5] < 0xF0) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadDownAlpha); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); + if (gSaveContext.equips.buttonItems[5] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) { + Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 5); + } Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[5]], 5); gDPPipeSync(OVERLAY_DISP++); gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, @@ -5426,6 +5462,9 @@ void Interface_Draw(PlayState* play) { if (gSaveContext.equips.buttonItems[6] < 0xF0) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadLeftAlpha); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); + if (gSaveContext.equips.buttonItems[6] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) { + Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 6); + } Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[6]], 6); gDPPipeSync(OVERLAY_DISP++); gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, @@ -5437,6 +5476,9 @@ void Interface_Draw(PlayState* play) { if (gSaveContext.equips.buttonItems[7] < 0xF0) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadRightAlpha); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); + if (gSaveContext.equips.buttonItems[7] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) { + Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 7); + } Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[7]], 7); gDPPipeSync(OVERLAY_DISP++); gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index df1314e71..77f513b0a 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -38,6 +38,9 @@ Input* D_8012D1F8 = NULL; PlayState* gPlayState; s16 firstInit = 0; s16 gEnPartnerId; +s16 gEnSnowballId; +s16 gEnChristmasTreeId; +s16 gEnChristmasDecoId; void Play_SpawnScene(PlayState* play, s32 sceneId, s32 spawn); @@ -692,6 +695,12 @@ void Play_Init(GameState* thisx) { GET_PLAYER(play)->actor.world.pos.y + Player_GetHeight(GET_PLAYER(play)) + 5.0f, GET_PLAYER(play)->actor.world.pos.z, 0, 0, 0, 1, true); } + + if (play->sceneNum == SCENE_KAKARIKO_VILLAGE) { + Actor_Spawn(&play->actorCtx, play, gEnChristmasTreeId, -734, 0, 420, 0, 0, 0, 0, true); + } + + Actor_Spawn(&play->actorCtx, play, gEnChristmasDecoId, 0, 0, 0, 0, 0, 0, 0, true); } void Play_Update(PlayState* play) { @@ -1673,7 +1682,7 @@ void Play_Main(GameState* thisx) { CVarSetInteger(CVAR_GENERAL("CheatEasyPauseBufferTimer"), CVarGetInteger(CVAR_GENERAL("CheatEasyPauseBufferTimer"), 0) - 1); } - if (play->envCtx.unk_EE[2] == 0 && CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { + if (play->envCtx.unk_EE[2] == 0 && CVarGetInteger("gLetItSnow", 0)) { play->envCtx.unk_EE[3] = 64; Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_OBJECT_KANKYO, 0, 0, 0, 0, 0, 0, 3, 0); } diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 3207abaf6..e662f8c46 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -8,9 +8,12 @@ #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/randomizer/draw.h" +#include "soh/Enhancements/Holiday/Fredomato.h" #include "soh/ResourceManagerHelpers.h" #include +#include +#include "soh/Enhancements/Holiday/Archez.h" typedef struct { /* 0x00 */ u8 flag; @@ -1055,10 +1058,18 @@ void* sMouthTextures[] = { }; #endif +// Original colors +//Color_RGB8 sTunicColors[] = { +// { 30, 105, 27 }, +// { 100, 20, 0 }, +// { 0, 60, 100 }, +//}; + +// Overwrite to red tunic as default for Holidays in Hyrule build Color_RGB8 sTunicColors[] = { - { 30, 105, 27 }, - { 100, 20, 0 }, - { 0, 60, 100 }, + { 255, 0, 0 }, + { 255, 0, 0 }, + { 255, 0, 0 }, }; Color_RGB8 sGauntletColors[] = { @@ -1413,6 +1424,10 @@ s32 Player_OverrideLimbDrawGameplayDefault(PlayState* play, s32 limbIndex, Gfx** sLeftHandType = PLAYER_MODELTYPE_LH_CLOSED; } + if (sLeftHandType != PLAYER_MODELTYPE_LH_OPEN && sLeftHandType != PLAYER_MODELTYPE_LH_CLOSED) { + SkipOverrideNextLimb(); + } + *dList = ResourceMgr_LoadGfxByName(dLists[sDListsLodOffset]); } else if (limbIndex == PLAYER_LIMB_R_HAND) { Gfx** dLists = this->rightHandDLists; @@ -1424,8 +1439,13 @@ s32 Player_OverrideLimbDrawGameplayDefault(PlayState* play, s32 limbIndex, Gfx** sRightHandType = PLAYER_MODELTYPE_RH_CLOSED; } + if (sRightHandType != PLAYER_MODELTYPE_RH_OPEN && sRightHandType != PLAYER_MODELTYPE_RH_CLOSED) { + SkipOverrideNextLimb(); + } + *dList = ResourceMgr_LoadGfxByName(dLists[sDListsLodOffset]); } else if (limbIndex == PLAYER_LIMB_SHEATH) { + SkipOverrideNextLimb(); Gfx** dLists = this->sheathDLists; if ((this->sheathType == PLAYER_MODELTYPE_SHEATH_18) || (this->sheathType == PLAYER_MODELTYPE_SHEATH_19)) { @@ -1482,10 +1502,13 @@ s32 Player_OverrideLimbDrawGameplayFirstPerson(PlayState* play, s32 limbIndex, G } *dList = sFirstPersonLeftHandDLs[handOutDlIndex]; } else if (limbIndex == PLAYER_LIMB_R_SHOULDER) { + SkipOverrideNextLimb(); *dList = sFirstPersonRightShoulderDLs[gSaveContext.linkAge]; } else if (limbIndex == PLAYER_LIMB_R_FOREARM) { + SkipOverrideNextLimb(); *dList = sFirstPersonForearmDLs[gSaveContext.linkAge]; } else if (limbIndex == PLAYER_LIMB_R_HAND) { + SkipOverrideNextLimb(); s32 firstPersonWeaponIndex = gSaveContext.linkAge; if (CVarGetInteger(CVAR_ENHANCEMENT("BowSlingshotAmmoFix"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) { if (Player_HoldsBow(this)) { @@ -1597,7 +1620,7 @@ void func_800906D4(PlayState* play, Player* this, Vec3f* newTipPos) { void Player_DrawGetItemIceTrap(PlayState* play, Player* this, Vec3f* refPos, s32 drawIdPlusOne, f32 height) { OPEN_DISPS(play->state.gfxCtx); - if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { + if (CVarGetInteger("gLetItSnow", 0)) { Gfx_SetupDL_25Opa(play->state.gfxCtx); Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY); @@ -1806,6 +1829,52 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve Matrix_MultVec3f(&sZeroVec, D_80160000); } + if (CVarGetInteger("gLetItSnow", 0) && !(this->stateFlags1 & PLAYER_STATE1_FIRST_PERSON) && !(this->stateFlags2 & PLAYER_STATE2_CRAWLING)) { + if (limbIndex == PLAYER_LIMB_HEAD) { + OPEN_DISPS(play->state.gfxCtx); + + Matrix_Push(); + if (LINK_IS_ADULT) { + Matrix_RotateZYX(24000, -16000, -7000, MTXMODE_APPLY); + Matrix_Translate(32.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gLinkAdultHatTrimDL); + } else { + Matrix_RotateZYX(24000, -16000, -7000, MTXMODE_APPLY); + Matrix_Translate(32.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gLinkChildHatTrimDL); + } + + Matrix_Pop(); + + CLOSE_DISPS(play->state.gfxCtx); + } + + if (limbIndex == PLAYER_LIMB_HAT) { + OPEN_DISPS(play->state.gfxCtx); + + Matrix_Push(); + if (LINK_IS_ADULT) { + Matrix_RotateZYX(0, 0, 17500, MTXMODE_APPLY); + Matrix_Translate(-195.0f, 1500.0f, -95.0f, MTXMODE_APPLY); + Matrix_Scale(2.0f, 2.0f, 2.0f, MTXMODE_APPLY); + } else { + Matrix_RotateZYX(0, 0, 27000, MTXMODE_APPLY); + Matrix_Translate(-950.0f, 2600.0f, -75.0f, MTXMODE_APPLY); + Matrix_Scale(2.0f, 2.0f, 2.0f, MTXMODE_APPLY); + } + + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gLinkAdultPompomDL); + Matrix_Pop(); + + CLOSE_DISPS(play->state.gfxCtx); + } + } + if (limbIndex == PLAYER_LIMB_L_HAND) { MtxF sp14C; Actor* hookedActor; diff --git a/soh/src/code/z_skelanime.c b/soh/src/code/z_skelanime.c index e91de847b..d513973fb 100644 --- a/soh/src/code/z_skelanime.c +++ b/soh/src/code/z_skelanime.c @@ -5,6 +5,9 @@ #include #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/Holiday/Archez.h" #define ANIM_INTERP 1 @@ -45,7 +48,7 @@ void SkelAnime_DrawLimbLod(PlayState* play, s32 limbIndex, void** skeleton, Vec3 if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &dList, &pos, &rot, arg)) { Matrix_TranslateRotateZYX(&pos, &rot); - if (dList != NULL) { + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, dList != NULL, &POLY_OPA_DISP, dList)) { gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_LOAD); gSPDisplayList(POLY_OPA_DISP++, dList); } @@ -105,7 +108,7 @@ void SkelAnime_DrawLod(PlayState* play, void** skeleton, Vec3s* jointTable, if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, 1, &dList, &pos, &rot, arg)) { Matrix_TranslateRotateZYX(&pos, &rot); - if (dList != NULL) { + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, dList != NULL, &POLY_OPA_DISP, dList)) { gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_LOAD); gSPDisplayList(POLY_OPA_DISP++, dList); } @@ -122,6 +125,8 @@ void SkelAnime_DrawLod(PlayState* play, void** skeleton, Vec3s* jointTable, Matrix_Pop(); CLOSE_DISPS(play->state.gfxCtx); + + ClearOverrideSkips(); } /** @@ -158,8 +163,10 @@ void SkelAnime_DrawFlexLimbLod(PlayState* play, s32 limbIndex, void** skeleton, MATRIX_TOMTX(*mtx); { OPEN_DISPS(play->state.gfxCtx); - gSPMatrix(POLY_OPA_DISP++, *mtx, G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, newDList); + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, true, &POLY_OPA_DISP, newDList, *mtx)) { + gSPMatrix(POLY_OPA_DISP++, *mtx, G_MTX_LOAD); + gSPDisplayList(POLY_OPA_DISP++, newDList); + } CLOSE_DISPS(play->state.gfxCtx); } (*mtx)++; @@ -231,8 +238,10 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable, if (newDList != NULL) { MATRIX_TOMTX(mtx); gDPNoOpString(POLY_OPA_DISP++, "T5ST", 0); - gSPMatrix(POLY_OPA_DISP++, mtx, G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, newDList); + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, true, &POLY_OPA_DISP, newDList, *mtx)) { + gSPMatrix(POLY_OPA_DISP++, mtx, G_MTX_LOAD); + gSPDisplayList(POLY_OPA_DISP++, newDList); + } mtx++; } else if (limbDList != NULL) { MATRIX_TOMTX(mtx); @@ -251,6 +260,8 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable, Matrix_Pop(); CLOSE_DISPS(play->state.gfxCtx); + + ClearOverrideSkips(); } /** @@ -276,7 +287,7 @@ void SkelAnime_DrawLimbOpa(PlayState* play, s32 limbIndex, void** skeleton, Vec3 if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &dList, &pos, &rot, arg)) { Matrix_TranslateRotateZYX(&pos, &rot); - if (dList != NULL) { + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, dList != NULL, &POLY_OPA_DISP, dList)) { gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_LOAD); gSPDisplayList(POLY_OPA_DISP++, dList); } @@ -358,7 +369,7 @@ void SkelAnime_DrawOpa(PlayState* play, void** skeleton, Vec3s* jointTable, if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, 1, &dList, &pos, &rot, arg)) { Matrix_TranslateRotateZYX(&pos, &rot); - if (dList != NULL) { + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, dList != NULL, &POLY_OPA_DISP, dList)) { gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_LOAD); gSPDisplayList(POLY_OPA_DISP++, dList); } @@ -375,6 +386,8 @@ void SkelAnime_DrawOpa(PlayState* play, void** skeleton, Vec3s* jointTable, Matrix_Pop(); CLOSE_DISPS(play->state.gfxCtx); + + ClearOverrideSkips(); } /** @@ -409,8 +422,10 @@ void SkelAnime_DrawFlexLimbOpa(PlayState* play, s32 limbIndex, void** skeleton, Matrix_TranslateRotateZYX(&pos, &rot); if (newDList != NULL) { MATRIX_TOMTX(*limbMatricies); - gSPMatrix(POLY_OPA_DISP++, *limbMatricies, G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, newDList); + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, true, &POLY_OPA_DISP, newDList, *limbMatricies)) { + gSPMatrix(POLY_OPA_DISP++, *limbMatricies, G_MTX_LOAD); + gSPDisplayList(POLY_OPA_DISP++, newDList); + } (*limbMatricies)++; } else if (limbDList != NULL) { MATRIX_TOMTX(*limbMatricies); @@ -478,8 +493,10 @@ void SkelAnime_DrawFlexOpa(PlayState* play, void** skeleton, Vec3s* jointTable, Matrix_TranslateRotateZYX(&pos, &rot); if (newDList != NULL) { MATRIX_TOMTX(mtx); - gSPMatrix(POLY_OPA_DISP++, mtx, G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, newDList); + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, true, &POLY_OPA_DISP, newDList, *mtx)) { + gSPMatrix(POLY_OPA_DISP++, mtx, G_MTX_LOAD); + gSPDisplayList(POLY_OPA_DISP++, newDList); + } mtx++; } else if (limbDList != NULL) { MATRIX_TOMTX(mtx); @@ -498,6 +515,8 @@ void SkelAnime_DrawFlexOpa(PlayState* play, void** skeleton, Vec3s* jointTable, Matrix_Pop(); CLOSE_DISPS(play->state.gfxCtx); + + ClearOverrideSkips(); } /** @@ -576,7 +595,7 @@ Gfx* SkelAnime_DrawLimb(PlayState* play, s32 limbIndex, void** skeleton, Vec3s* if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &dList, &pos, &rot, arg, &gfx)) { Matrix_TranslateRotateZYX(&pos, &rot); - if (dList != NULL) { + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, dList != NULL, &gfx, dList)) { gSPMatrix(gfx++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_LOAD); gSPDisplayList(gfx++, dList); } @@ -634,7 +653,7 @@ Gfx* SkelAnime_Draw(PlayState* play, void** skeleton, Vec3s* jointTable, Overrid if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, 1, &dList, &pos, &rot, arg, &gfx)) { Matrix_TranslateRotateZYX(&pos, &rot); - if (dList != NULL) { + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, dList != NULL, &gfx, dList)) { gSPMatrix(gfx++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_LOAD); gSPDisplayList(gfx++, dList); } @@ -651,6 +670,8 @@ Gfx* SkelAnime_Draw(PlayState* play, void** skeleton, Vec3s* jointTable, Overrid Matrix_Pop(); + ClearOverrideSkips(); + return gfx; } @@ -681,8 +702,10 @@ Gfx* SkelAnime_DrawFlexLimb(PlayState* play, s32 limbIndex, void** skeleton, Vec Matrix_TranslateRotateZYX(&pos, &rot); if (newDList != NULL) { MATRIX_TOMTX(*mtx); - gSPMatrix(gfx++, *mtx, G_MTX_LOAD); - gSPDisplayList(gfx++, newDList); + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, true, &gfx, newDList, *mtx)) { + gSPMatrix(gfx++, *mtx, G_MTX_LOAD); + gSPDisplayList(gfx++, newDList); + } (*mtx)++; } else if (limbDList != NULL) { MATRIX_TOMTX(*mtx); @@ -746,8 +769,10 @@ Gfx* SkelAnime_DrawFlex(PlayState* play, void** skeleton, Vec3s* jointTable, s32 Matrix_TranslateRotateZYX(&pos, &rot); if (newDList != NULL) { MATRIX_TOMTX(mtx); - gSPMatrix(gfx++, mtx, G_MTX_LOAD); - gSPDisplayList(gfx++, newDList); + if (GameInteractor_Should(VB_DRAW_SKEL_LIMB, true, &gfx, newDList, *mtx)) { + gSPMatrix(gfx++, mtx, G_MTX_LOAD); + gSPDisplayList(gfx++, newDList); + } mtx++; } else if (limbDList != NULL) { MATRIX_TOMTX(mtx); @@ -764,6 +789,8 @@ Gfx* SkelAnime_DrawFlex(PlayState* play, void** skeleton, Vec3s* jointTable, s32 Matrix_Pop(); + ClearOverrideSkips(); + return gfx; } diff --git a/soh/src/overlays/actors/ovl_Bg_Bombwall/z_bg_bombwall.c b/soh/src/overlays/actors/ovl_Bg_Bombwall/z_bg_bombwall.c index 160dc15f9..cf57bdc55 100644 --- a/soh/src/overlays/actors/ovl_Bg_Bombwall/z_bg_bombwall.c +++ b/soh/src/overlays/actors/ovl_Bg_Bombwall/z_bg_bombwall.c @@ -211,7 +211,9 @@ void func_8086ED50(BgBombwall* this, PlayState* play) { } void func_8086ED70(BgBombwall* this, PlayState* play) { - if (this->collider.base.acFlags & AC_HIT) { + // #region SOH [Co-op] + if ((this->collider.base.acFlags & AC_HIT) || Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { + // #endregion this->collider.base.acFlags &= ~AC_HIT; func_8086EDFC(this, play); Flags_SetSwitch(play, this->dyna.actor.params & 0x3F); diff --git a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c index 9f89e7980..bee6b1155 100644 --- a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c +++ b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c @@ -277,7 +277,9 @@ void BgBreakwall_Wait(BgBreakwall* this, PlayState* play) { } } - if (GameInteractor_Should(VB_BG_BREAKWALL_BREAK, this->collider.base.acFlags & 2 || blueFireArrowHit)) { + // #region SOH [Co-op] + if (GameInteractor_Should(VB_BG_BREAKWALL_BREAK, this->collider.base.acFlags & 2 || blueFireArrowHit) || Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { + // #endregion Vec3f effectPos; s32 wallType = ((this->dyna.actor.params >> 13) & 3) & 0xFF; diff --git a/soh/src/overlays/actors/ovl_Bg_Haka_Zou/z_bg_haka_zou.c b/soh/src/overlays/actors/ovl_Bg_Haka_Zou/z_bg_haka_zou.c index f41964603..4d3ed967f 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka_Zou/z_bg_haka_zou.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka_Zou/z_bg_haka_zou.c @@ -268,7 +268,9 @@ void func_80882E54(BgHakaZou* this, PlayState* play) { } void func_80883000(BgHakaZou* this, PlayState* play) { - if (this->collider.base.acFlags & AC_HIT) { + // #region SOH [Co-op] + if ((this->collider.base.acFlags & AC_HIT) || Flags_GetSwitch(play, this->switchFlag)) { + // #endregion Flags_SetSwitch(play, this->switchFlag); if (this->dyna.actor.params == STA_GIANT_BIRD_STATUE) { diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c index c1d402188..6ce78615c 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c @@ -126,8 +126,10 @@ void BgHidanDalm_Destroy(Actor* thisx, PlayState* play) { void BgHidanDalm_Wait(BgHidanDalm* this, PlayState* play) { Player* player = GET_PLAYER(play); - if ((this->collider.base.acFlags & AC_HIT) && !Player_InCsMode(play) && - (player->meleeWeaponAnimation == 22 || player->meleeWeaponAnimation == 23)) { + // #region SOH [Co-op] + if (((this->collider.base.acFlags & AC_HIT) && !Player_InCsMode(play) && + (player->meleeWeaponAnimation == 22 || player->meleeWeaponAnimation == 23)) || Flags_GetSwitch(play, this->switchFlag)) { + // #endregion this->collider.base.acFlags &= ~AC_HIT; if ((this->collider.elements[0].info.bumperFlags & BUMP_HIT) || (this->collider.elements[1].info.bumperFlags & BUMP_HIT)) { diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Hamstep/z_bg_hidan_hamstep.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Hamstep/z_bg_hidan_hamstep.c index 818533571..e49f33a9a 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Hamstep/z_bg_hidan_hamstep.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Hamstep/z_bg_hidan_hamstep.c @@ -278,7 +278,9 @@ void func_80888734(BgHidanHamstep* this) { } void func_808887C4(BgHidanHamstep* this, PlayState* play) { - if (this->collider.base.acFlags & AC_HIT) { + // #region SOH [Co-op] + if ((this->collider.base.acFlags & AC_HIT) || Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0xFF)) { + // #endregion OnePointCutscene_Init(play, 3310, 100, &this->dyna.actor, MAIN_CAM); Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_HAMMER_SWITCH); this->collider.base.acFlags = AC_NONE; diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Hrock/z_bg_hidan_hrock.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Hrock/z_bg_hidan_hrock.c index ea49fbd4f..5079c200e 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Hrock/z_bg_hidan_hrock.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Hrock/z_bg_hidan_hrock.c @@ -201,7 +201,9 @@ void func_8088960C(BgHidanHrock* this, PlayState* play) { } void func_808896B8(BgHidanHrock* this, PlayState* play) { - if (this->collider.base.acFlags & 2) { + // #region SOH [Co-op] + if ((this->collider.base.acFlags & 2) || Flags_GetSwitch(play, this->unk_16A)) { + // #endregion this->collider.base.acFlags &= ~2; this->actionFunc = func_808894B0; this->dyna.actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Kowarerukabe/z_bg_hidan_kowarerukabe.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Kowarerukabe/z_bg_hidan_kowarerukabe.c index c9cbb039f..71f586f45 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Kowarerukabe/z_bg_hidan_kowarerukabe.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Kowarerukabe/z_bg_hidan_kowarerukabe.c @@ -303,7 +303,9 @@ void BgHidanKowarerukabe_Update(Actor* thisx, PlayState* play) { BgHidanKowarerukabe* this = (BgHidanKowarerukabe*)thisx; s32 pad; - if (Actor_GetCollidedExplosive(play, &this->collider.base) != NULL) { + // #region SOH [Co-op] + if ((Actor_GetCollidedExplosive(play, &this->collider.base) != NULL) || Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) { + // #endregion BgHidanKowarerukabe_Break(this, play); Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); diff --git a/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c b/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c index 9810f2749..d09980978 100644 --- a/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c +++ b/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c @@ -333,10 +333,12 @@ void func_8089107C(BgIceShelter* this, PlayState* play) { MeltOnIceArrowHit(this, this->cylinder2, type, play); } // Default blue fire check - if (this->cylinder1.base.acFlags & AC_HIT) { + // #region SOH [Co-op] + if ((this->cylinder1.base.acFlags & AC_HIT) || Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { this->cylinder1.base.acFlags &= ~AC_HIT; - if ((this->cylinder1.base.ac != NULL) && (this->cylinder1.base.ac->id == ACTOR_EN_ICE_HONO)) { + if (((this->cylinder1.base.ac != NULL) && (this->cylinder1.base.ac->id == ACTOR_EN_ICE_HONO)) || Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { + // #endregion if (type == 4) { if (this->dyna.actor.parent != NULL) { this->dyna.actor.parent->freezeTimer = 50; diff --git a/soh/src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.c b/soh/src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.c index cb36b743d..bb7333c52 100644 --- a/soh/src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.c +++ b/soh/src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.c @@ -142,7 +142,9 @@ void BgJyaBombchuiwa_SetupWaitForExplosion(BgJyaBombchuiwa* this, PlayState* pla } void BgJyaBombchuiwa_WaitForExplosion(BgJyaBombchuiwa* this, PlayState* play) { - if ((this->collider.base.acFlags & AC_HIT) || (this->timer > 0)) { + // #region SOH [Co-op] + if (((this->collider.base.acFlags & AC_HIT) || (this->timer > 0)) || Flags_GetSwitch(play, this->actor.params & 0x3F)) { + // #endregion if (this->timer == 0) { OnePointCutscene_Init(play, 3410, -99, &this->actor, MAIN_CAM); } diff --git a/soh/src/overlays/actors/ovl_Bg_Jya_Bombiwa/z_bg_jya_bombiwa.c b/soh/src/overlays/actors/ovl_Bg_Jya_Bombiwa/z_bg_jya_bombiwa.c index d0e4b9471..9edb9edc6 100644 --- a/soh/src/overlays/actors/ovl_Bg_Jya_Bombiwa/z_bg_jya_bombiwa.c +++ b/soh/src/overlays/actors/ovl_Bg_Jya_Bombiwa/z_bg_jya_bombiwa.c @@ -163,7 +163,9 @@ void BgJyaBombiwa_Break(BgJyaBombiwa* this, PlayState* play) { void BgJyaBombiwa_Update(Actor* thisx, PlayState* play) { BgJyaBombiwa* this = (BgJyaBombiwa*)thisx; - if (this->collider.base.acFlags & AC_HIT) { + // #region SOH [Co-op] + if ((this->collider.base.acFlags & AC_HIT) || Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { + // #endregion BgJyaBombiwa_Break(this, play); Flags_SetSwitch(play, this->dyna.actor.params & 0x3F); SoundSource_PlaySfxAtFixedWorldPos(play, &this->dyna.actor.world.pos, 40, NA_SE_EV_WALL_BROKEN); diff --git a/soh/src/overlays/actors/ovl_Bg_Mizu_Bwall/z_bg_mizu_bwall.c b/soh/src/overlays/actors/ovl_Bg_Mizu_Bwall/z_bg_mizu_bwall.c index 89db58c0e..8eaa8ff10 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mizu_Bwall/z_bg_mizu_bwall.c +++ b/soh/src/overlays/actors/ovl_Bg_Mizu_Bwall/z_bg_mizu_bwall.c @@ -467,7 +467,9 @@ void BgMizuBwall_SpawnDebris(BgMizuBwall* this, PlayState* play) { void BgMizuBwall_Idle(BgMizuBwall* this, PlayState* play) { BgMizuBwall_SetAlpha(this, play); - if (this->collider.base.acFlags & AC_HIT) { + // #region SOH [Co-op] + if ((this->collider.base.acFlags & AC_HIT) || Flags_GetSwitch(play, ((u16)this->dyna.actor.params >> 8) & 0x3F)) { + // #endregion this->collider.base.acFlags &= ~AC_HIT; Flags_SetSwitch(play, ((u16)this->dyna.actor.params >> 8) & 0x3F); this->breakTimer = 1; diff --git a/soh/src/overlays/actors/ovl_Bg_Spot08_Bakudankabe/z_bg_spot08_bakudankabe.c b/soh/src/overlays/actors/ovl_Bg_Spot08_Bakudankabe/z_bg_spot08_bakudankabe.c index e40302b66..5269510fe 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot08_Bakudankabe/z_bg_spot08_bakudankabe.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot08_Bakudankabe/z_bg_spot08_bakudankabe.c @@ -183,7 +183,9 @@ void BgSpot08Bakudankabe_Destroy(Actor* thisx, PlayState* play) { void BgSpot08Bakudankabe_Update(Actor* thisx, PlayState* play) { BgSpot08Bakudankabe* this = (BgSpot08Bakudankabe*)thisx; - if (this->collider.base.acFlags & AC_HIT) { + // #region SOH [Co-op] + if ((this->collider.base.acFlags & AC_HIT) || Flags_GetSwitch(play, (this->dyna.actor.params & 0x3F))) { + // #endregion func_808B0324(this, play); Flags_SetSwitch(play, (this->dyna.actor.params & 0x3F)); SoundSource_PlaySfxAtFixedWorldPos(play, &this->dyna.actor.world.pos, 40, NA_SE_EV_WALL_BROKEN); diff --git a/soh/src/overlays/actors/ovl_Bg_Spot08_Iceblock/z_bg_spot08_iceblock.c b/soh/src/overlays/actors/ovl_Bg_Spot08_Iceblock/z_bg_spot08_iceblock.c index d7b45c9b6..545dbdac1 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot08_Iceblock/z_bg_spot08_iceblock.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot08_Iceblock/z_bg_spot08_iceblock.c @@ -308,7 +308,7 @@ void BgSpot08Iceblock_Init(Actor* thisx, PlayState* play) { break; } - if (LINK_AGE_IN_YEARS == YEARS_CHILD) { + if (LINK_AGE_IN_YEARS == YEARS_CHILD && play->sceneNum == SCENE_ZORAS_FOUNTAIN) { Actor_Kill(&this->dyna.actor); return; } @@ -332,6 +332,11 @@ void BgSpot08Iceblock_Init(Actor* thisx, PlayState* play) { this->surfaceNormal.y = 1.0f; this->rotationAxis.x = 1.0f; + if (LINK_IS_ADULT && !Flags_GetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER) && play->sceneNum == SCENE_LAKE_HYLIA) { + BgSpot08Iceblock_SetupNoAction(this); + return; + } + switch (this->dyna.actor.params & 0xF) { case 0: case 1: diff --git a/soh/src/overlays/actors/ovl_Bg_Spot11_Bakudankabe/z_bg_spot11_bakudankabe.c b/soh/src/overlays/actors/ovl_Bg_Spot11_Bakudankabe/z_bg_spot11_bakudankabe.c index 3b7f7c7e4..81fe0a06b 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot11_Bakudankabe/z_bg_spot11_bakudankabe.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot11_Bakudankabe/z_bg_spot11_bakudankabe.c @@ -135,7 +135,9 @@ void BgSpot11Bakudankabe_Destroy(Actor* thisx, PlayState* play) { void BgSpot11Bakudankabe_Update(Actor* thisx, PlayState* play) { BgSpot11Bakudankabe* this = (BgSpot11Bakudankabe*)thisx; - if (this->collider.base.acFlags & AC_HIT) { + // #region SOH [Co-op] + if ((this->collider.base.acFlags & AC_HIT) || Flags_GetSwitch(play, (this->dyna.actor.params & 0x3F))) { + // #endregion func_808B2218(this, play); Flags_SetSwitch(play, (this->dyna.actor.params & 0x3F)); SoundSource_PlaySfxAtFixedWorldPos(play, &D_808B2738, 40, NA_SE_EV_WALL_BROKEN); diff --git a/soh/src/overlays/actors/ovl_Bg_Spot17_Bakudankabe/z_bg_spot17_bakudankabe.c b/soh/src/overlays/actors/ovl_Bg_Spot17_Bakudankabe/z_bg_spot17_bakudankabe.c index 6537a1690..fe934bd2d 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot17_Bakudankabe/z_bg_spot17_bakudankabe.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot17_Bakudankabe/z_bg_spot17_bakudankabe.c @@ -114,7 +114,9 @@ void BgSpot17Bakudankabe_Destroy(Actor* thisx, PlayState* play) { void BgSpot17Bakudankabe_Update(Actor* thisx, PlayState* play) { BgSpot17Bakudankabe* this = (BgSpot17Bakudankabe*)thisx; - if (this->dyna.actor.xzDistToPlayer < 650.0f && func_80033684(play, &this->dyna.actor) != NULL) { + // #region SOH [Co-op] + if ((this->dyna.actor.xzDistToPlayer < 650.0f && func_80033684(play, &this->dyna.actor) != NULL) || Flags_GetSwitch(play, (this->dyna.actor.params & 0x3F))) { + // #endregion func_808B6BC0(this, play); Flags_SetSwitch(play, (this->dyna.actor.params & 0x3F)); SoundSource_PlaySfxAtFixedWorldPos(play, &this->dyna.actor.world.pos, 40, NA_SE_EV_WALL_BROKEN); diff --git a/soh/src/overlays/actors/ovl_Bg_Ydan_Maruta/z_bg_ydan_maruta.c b/soh/src/overlays/actors/ovl_Bg_Ydan_Maruta/z_bg_ydan_maruta.c index 23d7fac96..f2556541b 100644 --- a/soh/src/overlays/actors/ovl_Bg_Ydan_Maruta/z_bg_ydan_maruta.c +++ b/soh/src/overlays/actors/ovl_Bg_Ydan_Maruta/z_bg_ydan_maruta.c @@ -146,7 +146,9 @@ void func_808BEFF4(BgYdanMaruta* this, PlayState* play) { } void func_808BF078(BgYdanMaruta* this, PlayState* play) { - if (this->collider.base.acFlags & AC_HIT) { + // #region SOH [Co-op] + if ((this->collider.base.acFlags & AC_HIT) || Flags_GetSwitch(play, this->switchFlag)) { + // #endregion this->unk_16A = 20; Flags_SetSwitch(play, this->switchFlag); Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME); diff --git a/soh/src/overlays/actors/ovl_Bg_Ydan_Sp/z_bg_ydan_sp.c b/soh/src/overlays/actors/ovl_Bg_Ydan_Sp/z_bg_ydan_sp.c index 59402d658..f448d55a0 100644 --- a/soh/src/overlays/actors/ovl_Bg_Ydan_Sp/z_bg_ydan_sp.c +++ b/soh/src/overlays/actors/ovl_Bg_Ydan_Sp/z_bg_ydan_sp.c @@ -282,6 +282,12 @@ void BgYdanSp_FloorWebIdle(BgYdanSp* this, PlayState* play) { webPos.x = this->dyna.actor.world.pos.x; webPos.y = this->dyna.actor.world.pos.y - 50.0f; webPos.z = this->dyna.actor.world.pos.z; + // #region SOH [Co-op] + if (Flags_GetSwitch(play, this->isDestroyedSwitchFlag)) { + BgYdanSp_BurnWeb(this, play); + return; + } + // #endregion if (Player_IsBurningStickInRange(play, &webPos, 70.0f, 50.0f) != 0) { this->dyna.actor.home.pos.x = player->meleeWeaponInfo[0].tip.x; this->dyna.actor.home.pos.z = player->meleeWeaponInfo[0].tip.z; @@ -411,6 +417,11 @@ void BgYdanSp_WallWebIdle(BgYdanSp* this, PlayState* play) { BgYdanSp_BurnWeb(this, play); } } + // #region SOH [Co-op] + if (Flags_GetSwitch(play, this->isDestroyedSwitchFlag)) { + BgYdanSp_BurnWeb(this, play); + } + // #endregion CollisionCheck_SetAC(play, &play->colChkCtx, &this->trisCollider.base); } diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c index 4702d8376..87c50c978 100644 --- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c +++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c @@ -4,6 +4,7 @@ #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "scenes/dungeons/ddan_boss/ddan_boss_room_1.h" #include "soh/frame_interpolation.h" +#include "soh_assets.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" @@ -1355,6 +1356,21 @@ void BossDodongo_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s Matrix_MultVec3f(&D_808CA48C, &this->unk_404); } Collider_UpdateSpheres(limbIndex, &this->collider); + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 7) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-6643, 1771, -14834, MTXMODE_APPLY); + Matrix_Translate(2000.0f, 5000.0f, 4000.0f, MTXMODE_APPLY); + Matrix_Scale(6.114f, 6.114f, 6.114f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void BossDodongo_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c index a418ced3a..c26b80437 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c @@ -9,6 +9,7 @@ #include "assets/objects/object_ganon_anime1/object_ganon_anime1.h" #include "assets/objects/object_ganon_anime2/object_ganon_anime2.h" #include "assets/scenes/dungeons/ganon_boss/ganon_boss_scene.h" +#include "soh_assets.h" #include "soh/frame_interpolation.h" #include "soh/OTRGlobals.h" @@ -571,7 +572,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE); this->csCamFov = 60.0f; - if (Flags_GetEventChkInf(EVENTCHKINF_BEGAN_GANONDORF_BATTLE) || IS_RANDO || IS_BOSS_RUSH) { + if (Flags_GetEventChkInf(EVENTCHKINF_BEGAN_GANONDORF_BATTLE) || IS_RANDO || IS_BOSS_RUSH || CVarGetInteger("gHoliday.NotProxySaw.GanonDatingSim", 0)) { // watched cutscene already, skip most of it this->csState = 17; this->csTimer = 0; @@ -926,6 +927,9 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { if ((this->csTimer <= 50) || (Message_GetState(&play->msgCtx) != TEXT_STATE_NONE)) { break; } + if (!GameInteractor_Should(VB_GANONDORF_DECIDE_TO_FIGHT, true)) { + break; + } this->csState = 19; this->csTimer = 0; @@ -3382,6 +3386,21 @@ void BossGanon_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* Matrix_MultVec3f(&sp1C, &this->unk_214); } + + if (limbIndex == 14) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(7749, 0, -11956, MTXMODE_APPLY); + Matrix_Translate(675.676f, -229.730f, 148.649f, MTXMODE_APPLY); + Matrix_Scale(1.014f, 1.014f, 1.014f, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + Color_RGBA8 color = { 255, 0, 0, 255 }; + gDPSetEnvColor(POLY_OPA_DISP++, color.r, color.g, color.b, color.a); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } } void BossGanon_InitRand(s32 seedInit0, s32 seedInit1, s32 seedInit2) { diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c index 5270402fe..f5251a55a 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c @@ -10,6 +10,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include @@ -2658,6 +2659,18 @@ void BossGanon2_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* } } + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 16) { + Matrix_Push(); + Matrix_RotateZYX(5977, 4649, 18154, MTXMODE_APPLY); + Matrix_Translate(364.865f, 67.568f, 378.378f, MTXMODE_APPLY); + Matrix_Scale(4.595f, 4.595f, 4.595f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + } + } + CLOSE_DISPS(play->state.gfxCtx); } @@ -2782,6 +2795,21 @@ void BossGanon2_PostLimbDraw2(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s } else if (limbIndex == 10) { Matrix_MultVec3f(&D_80907164, &this->unk_1B8); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 11) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, -15056, MTXMODE_APPLY); + Matrix_Translate(824.324f, 472.973f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.845f, 0.845f, 0.845f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 100, 100, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void func_80905674(BossGanon2* this, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c index 1ac0d2c90..4e6a0f860 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c @@ -13,6 +13,9 @@ #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" + +#include "soh/Enhancements/Holiday/Archez.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -1350,6 +1353,8 @@ s32 BossGanondrof_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, case 15: if ((this->actionFunc == BossGanondrof_Intro) && this->work[GND_MASK_OFF]) { *dList = gPhantomGanonFaceDL; + } else { + SkipOverrideNextLimb(); } rot->y += this->rideRotY[limbIndex]; rot->z += this->rideRotZ[limbIndex]; @@ -1409,6 +1414,10 @@ s32 BossGanondrof_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, break; } + if (limbIndex == 12) { + SkipOverrideNextLimb(); + } + return 0; } @@ -1427,6 +1436,20 @@ void BossGanondrof_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec if (((this->flyMode != GND_FLY_PAINTING) || (this->actionFunc == BossGanondrof_Intro)) && (limbIndex <= 25)) { Matrix_MultVec3f(&zeroVec, &this->bodyPartsPos[limbIndex - 1]); } + if (CVarGetInteger("gLetItSnow", 0) && this->deathState == NOT_DEAD) { + if (limbIndex == 15) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(11955, 0, -15499, MTXMODE_APPLY); + Matrix_Translate(459.460f, 256.757f, -567.568f, MTXMODE_APPLY); + Matrix_Scale(0.877f, 0.877f, 0.877f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 100, 100, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } Gfx* BossGanondrof_GetClearPixelDList(GraphicsContext* gfxCtx) { diff --git a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c index fdc16fd1e..c9e46f5ae 100644 --- a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c +++ b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c @@ -8,6 +8,8 @@ #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) // IRIS_FOLLOW: gohma looks towards the player (iris rotation) @@ -1980,6 +1982,7 @@ s32 BossGoma_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f switch (limbIndex) { case BOSSGOMA_LIMB_EYE: + SkipOverrideNextLimb(); if (this->eyeState == EYESTATE_IRIS_FOLLOW_BONUS_IFRAMES && this->eyeLidBottomRotX < -0xA8C) { *dList = NULL; } else if (this->invincibilityFrames != 0) { @@ -1992,10 +1995,12 @@ s32 BossGoma_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f break; case BOSSGOMA_LIMB_EYE_LID_BOTTOM_ROOT2: + SkipOverrideNextLimb(); rot->x += this->eyeLidBottomRotX; break; case BOSSGOMA_LIMB_EYE_LID_TOP_ROOT2: + SkipOverrideNextLimb(); rot->x += this->eyeLidTopRotX; break; diff --git a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c index edd5c032f..1ccaf1689 100644 --- a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c +++ b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c @@ -15,6 +15,8 @@ #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_DRAGGED_BY_HOOKSHOT) #define vParity actionVar @@ -2862,6 +2864,11 @@ s32 BossSst_OverrideHeadDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* rot->z -= 0x200; } } + + if (limbIndex == 7) { + SkipOverrideNextLimb(); + } + return false; } diff --git a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c index a0df96d42..737ea7225 100644 --- a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c +++ b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c @@ -8,6 +8,7 @@ #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include +#include "soh/Enhancements/Holiday/Archez.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -3191,6 +3192,10 @@ s32 BossTw_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* } } + if (limbIndex == 14) { + SkipOverrideNextLimb(); + } + return false; } @@ -3621,6 +3626,10 @@ s32 BossTw_TwinrovaOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, *dList = NULL; } + if (limbIndex == 34 || limbIndex == 40) { + SkipOverrideNextLimb(); + } + CLOSE_DISPS(play->state.gfxCtx); return false; diff --git a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c index 18bc927d5..5d969b011 100644 --- a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c +++ b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c @@ -19,6 +19,8 @@ #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) #define GET_BODY(this) ((BossVa*)(this)->actor.parent) @@ -3265,6 +3267,7 @@ void BossVa_Draw(Actor* thisx, PlayState* play) { break; default: if (!this->isDead) { + SkipOverrideNextSkeleton(); SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, BossVa_BariOverrideLimbDraw, BossVa_BariPostLimbDraw, this); Collider_UpdateSpheres(0, &this->colliderSph); diff --git a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c index d4d3d8b60..786da7768 100644 --- a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c +++ b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c @@ -180,7 +180,7 @@ void DoorAna_Update(Actor* thisx, PlayState* play) { this->actionFunc(this, play); // Changes the grottos facing angle based on camera angle - if (!CVarGetInteger(CVAR_ENHANCEMENT("DisableGrottoRotation"), 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("DisableGrottoRotation"), 0) && thisx->draw == DoorAna_Draw) { this->actor.shape.rot.y = Camera_GetCamDirYaw(GET_ACTIVE_CAM(play)) + 0x8000; } } diff --git a/soh/src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.c b/soh/src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.c index 99dd5e43f..3db8803a6 100644 --- a/soh/src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.c +++ b/soh/src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.c @@ -6,6 +6,7 @@ #include "z_door_gerudo.h" #include "objects/object_door_gerudo/object_door_gerudo.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -103,6 +104,7 @@ void func_8099485C(DoorGerudo* this, PlayState* play) { gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] -= 1; Flags_SetSwitch(play, this->dyna.actor.params & 0x3F); Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_CHAIN_KEY_UNLOCK); + GameInteractor_ExecuteOnDungeonKeyUsedHooks(gSaveContext.mapIndex); } else { s32 direction = func_80994750(this, play); diff --git a/soh/src/overlays/actors/ovl_Door_Killer/z_door_killer.c b/soh/src/overlays/actors/ovl_Door_Killer/z_door_killer.c index f29b23450..9f3b5241a 100644 --- a/soh/src/overlays/actors/ovl_Door_Killer/z_door_killer.c +++ b/soh/src/overlays/actors/ovl_Door_Killer/z_door_killer.c @@ -13,6 +13,8 @@ #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED typedef enum { @@ -533,6 +535,7 @@ void DoorKiller_DrawDoor(Actor* thisx, PlayState* play) { Gfx_SetupDL_37Opa(play->state.gfxCtx); DoorKiller_SetTexture(&this->actor, play); + SkipOverrideNextSkeleton(); SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, NULL, NULL); } diff --git a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c index c842571e7..14cff8380 100644 --- a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c +++ b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c @@ -379,6 +379,7 @@ void func_80996B0C(DoorShutter* this, PlayState* play) { if (this->doorType != SHUTTER_BOSS) { gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]--; Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_CHAIN_KEY_UNLOCK); + GameInteractor_ExecuteOnDungeonKeyUsedHooks(gSaveContext.mapIndex); } else { Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_CHAIN_KEY_UNLOCK_B); } @@ -645,6 +646,11 @@ void DoorShutter_Update(Actor* thisx, PlayState* play) { if (!(player->stateFlags1 & (PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_IN_ITEM_CS)) || (this->actionFunc == DoorShutter_SetupType)) { this->actionFunc(this, play); } + // #region SOH [Co-op] + if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { + DECR(this->unk_16E); + } + // #endregion } Gfx* func_80997838(PlayState* play, DoorShutter* this, Gfx* p) { diff --git a/soh/src/overlays/actors/ovl_En_Am/z_en_am.c b/soh/src/overlays/actors/ovl_En_Am/z_en_am.c index 70a6ae5da..94be217bf 100644 --- a/soh/src/overlays/actors/ovl_En_Am/z_en_am.c +++ b/soh/src/overlays/actors/ovl_En_Am/z_en_am.c @@ -8,8 +8,11 @@ #include "objects/object_am/object_am.h" #include "overlays/actors/ovl_En_Bom/z_en_bom.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_CAN_PRESS_SWITCH) void EnAm_Init(Actor* thisx, PlayState* play); @@ -945,6 +948,21 @@ void EnAm_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, if ((limbIndex == 1) && (this->unk_264 != 0)) { EnAm_TransformSwordHitbox(&this->dyna.actor, play); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 4) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, -2657, MTXMODE_APPLY); + Matrix_Translate(4000.0f, 1148.649f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.655f, 1.655f, 1.655f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } static Vec3f sIcePosOffsets[] = { @@ -962,6 +980,7 @@ void EnAm_Draw(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, this->textureBlend); + SkipOverrideNextSkeleton(); SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, EnAm_PostLimbDraw, this); diff --git a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c index 8126a1425..209529938 100644 --- a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c +++ b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c @@ -9,6 +9,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -318,6 +319,21 @@ void EnAni_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, if (limbIndex == 15) { Matrix_MultVec3f(&sMultVec, &this->actor.focus.pos); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(1992, 0, 2656, MTXMODE_APPLY); + Matrix_Translate(972.973f, 40.541f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.965f, 0.965f, 0.965f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnAni_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c index 0669d43d6..097ea3470 100644 --- a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c +++ b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c @@ -8,6 +8,8 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_gi_nuts/object_gi_nuts.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) void EnArrow_Init(Actor* thisx, PlayState* play); @@ -501,6 +503,7 @@ void EnArrow_Draw(Actor* thisx, PlayState* play) { if (this->actor.params <= ARROW_0E) { Gfx_SetupDL_25Opa(play->state.gfxCtx); + SkipOverrideNextSkeleton(); SkelAnime_DrawLod(play, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, NULL, this, (this->actor.projectedPos.z < MREG(95)) ? 0 : 1); } else if (this->actor.speedXZ != 0.0f) { diff --git a/soh/src/overlays/actors/ovl_En_Bb/z_en_bb.c b/soh/src/overlays/actors/ovl_En_Bb/z_en_bb.c index b03b6490a..7c215672e 100644 --- a/soh/src/overlays/actors/ovl_En_Bb/z_en_bb.c +++ b/soh/src/overlays/actors/ovl_En_Bb/z_en_bb.c @@ -8,6 +8,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_Bb/object_Bb.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_PLAY_HIT_SFX) @@ -1270,6 +1271,20 @@ void EnBb_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, EnBb* this = (EnBb*)thisx; BodyBreak_SetInfo(&this->bodyBreak, limbIndex, 4, 15, 15, dList, BODYBREAK_OBJECT_DEFAULT); + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-13063, 0, -27454, MTXMODE_APPLY); + Matrix_Translate(418.919f, -81.081f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.757f, 1.757f, 1.757f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } static Vec3f sFireIceOffsets[] = { diff --git a/soh/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.c b/soh/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.c index aa53182c5..db1cff7ea 100644 --- a/soh/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.c +++ b/soh/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.c @@ -3,6 +3,8 @@ #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) void EnBigokuta_Init(Actor* thisx, PlayState* play); @@ -868,6 +870,11 @@ s32 EnBigokuta_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec Matrix_Scale(1.0f, 1.25f - temp_f0, 1.25f - temp_f0, MTXMODE_APPLY); } } + + if (limbIndex == 15 || limbIndex == 16 || limbIndex == CVarGetInteger("gMyThing", 0)) { + SkipOverrideNextLimb(); + } + return false; } diff --git a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c index e5c9c2a99..bd479eaf6 100644 --- a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c +++ b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c @@ -287,7 +287,12 @@ void EnBom_Update(Actor* thisx, PlayState* play2) { // spawn spark effect on even frames effPos = thisx->world.pos; - effPos.y += 17.0f; + if (CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0) && + thisx->parent && thisx->parent->id == ACTOR_EN_ARROW) { + effPos.y += 5.0f; + } else { + effPos.y += 17.0f; + } if ((play->gameplayFrames % 2) == 0) { EffectSsGSpk_SpawnFuse(play, thisx, &effPos, &effVelocity, &effAccel); } diff --git a/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c b/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c index df74e5317..3589a6fae 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c @@ -1,6 +1,7 @@ #include "z_en_bom_chu.h" #include "overlays/actors/ovl_En_Bom/z_en_bom.h" #include "objects/gameplay_keep/gameplay_keep.h" +#include "soh_assets.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -529,5 +530,15 @@ void EnBomChu_Draw(Actor* thisx, PlayState* play) { G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_OPA_DISP++, gBombchuDL); + if (CVarGetInteger("gLetItSnow", 0)) { + Matrix_Push(); + Matrix_RotateZYX(0, -3100, 17047, MTXMODE_APPLY); + Matrix_Translate(445.946f, -27.027f, 608.108f, MTXMODE_APPLY); + Matrix_Scale(0.541f, 0.541f, 0.541f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + } + CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index bcf8a9413..580c146c2 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -670,7 +670,7 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) { } } - if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0) && hasChristmasChestTexturesAvailable && hasCreatedRandoChestTextures && !hasCustomChestDLs) { + if (CVarGetInteger("gLetItSnow", 0) && hasChristmasChestTexturesAvailable && hasCreatedRandoChestTextures && !hasCustomChestDLs) { if (this->dyna.actor.scale.x == 0.01f) { this->boxBodyDL = gChristmasRedTreasureChestChestFrontDL; this->boxLidDL = gChristmasRedTreasureChestChestSideAndLidDL; diff --git a/soh/src/overlays/actors/ovl_En_ChristmasDeco/z_en_christmasdeco.c b/soh/src/overlays/actors/ovl_En_ChristmasDeco/z_en_christmasdeco.c new file mode 100644 index 000000000..2a4e02be9 --- /dev/null +++ b/soh/src/overlays/actors/ovl_En_ChristmasDeco/z_en_christmasdeco.c @@ -0,0 +1,61 @@ +/* + * File: z_en_christmasdeco.c + * Overlay: ovl_En_ChristmasDeco + * Description: Custom Christmas Decorations + */ + +#include "z_en_christmasdeco.h" +#include "soh_assets.h" + +void EnChristmasDeco_Init(Actor* thisx, PlayState* play); +void EnChristmasDeco_Destroy(Actor* thisx, PlayState* play); +void EnChristmasDeco_Update(Actor* thisx, PlayState* play); +void EnChristmasDeco_Draw(Actor* thisx, PlayState* play); + +void EnChristmasDeco_Init(Actor* thisx, PlayState* play) { + if (play->sceneNum == SCENE_TEMPLE_OF_TIME) { + EnChristmasDeco* this = (EnChristmasDeco*)thisx; + this->actor.room = -1; + } +} + +void EnChristmasDeco_Destroy(Actor* thisx, PlayState* play) { + +} + +void EnChristmasDeco_Update(Actor* thisx, PlayState* play) { + +} + +void EnChristmasDeco_Draw(Actor* thisx, PlayState* play) { + float decoSize = 10.0f; + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + Matrix_Scale(decoSize, decoSize, decoSize, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + + // Assertion Halt in Debug mode, switch to Release when testing. + if (play->sceneNum == SCENE_KAKARIKO_VILLAGE) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gKakarikoDecorDL); + if (LINK_IS_CHILD) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gKakarikoChildDecorDL); + } else { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gKakarikoAdultDecorDL); + } + } + + if (play->sceneNum == SCENE_TEMPLE_OF_TIME) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gTempleOfTimeDecorDL); + if (LINK_IS_CHILD) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gTempleOfTimeDecorDL); + } else { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gTempleOfTimeDecorDL); + } + } + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/soh/src/overlays/actors/ovl_En_ChristmasDeco/z_en_christmasdeco.h b/soh/src/overlays/actors/ovl_En_ChristmasDeco/z_en_christmasdeco.h new file mode 100644 index 000000000..f2a317648 --- /dev/null +++ b/soh/src/overlays/actors/ovl_En_ChristmasDeco/z_en_christmasdeco.h @@ -0,0 +1,27 @@ +#ifndef Z_EN_CHRISTMASDECO_H +#define Z_EN_CHRISTMASDECO_H + +#include +#include "global.h" + +struct EnChristmasDeco; + +typedef void (*EnChristmasDecoActionFunc)(struct EnChristmasDeco*, PlayState*); + +typedef struct EnChristmasDeco { + Actor actor; + EnChristmasDecoActionFunc actionFunc; +} EnChristmasDeco; + +#ifdef __cplusplus +extern "C" { +#endif +void EnChristmasDeco_Init(Actor* thisx, PlayState* play); +void EnChristmasDeco_Destroy(Actor* thisx, PlayState* play); +void EnChristmasDeco_Update(Actor* thisx, PlayState* play); +void EnChristmasDeco_Draw(Actor* thisx, PlayState* play); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/soh/src/overlays/actors/ovl_En_ChristmasTree/z_en_christmastree.c b/soh/src/overlays/actors/ovl_En_ChristmasTree/z_en_christmastree.c new file mode 100644 index 000000000..467bc6d31 --- /dev/null +++ b/soh/src/overlays/actors/ovl_En_ChristmasTree/z_en_christmastree.c @@ -0,0 +1,213 @@ +/* + * File: z_en_christmastree.c + * Overlay: ovl_En_ChristmasTree + * Description: Custom Christmas Tree for Ornament Hunt + */ + +#include "z_en_christmastree.h" +#include "soh_assets.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" + +void EnChristmasTree_Init(Actor* thisx, PlayState* play); +void EnChristmasTree_Destroy(Actor* thisx, PlayState* play); +void EnChristmasTree_Update(Actor* thisx, PlayState* play); +void EnChristmasTree_Draw(Actor* thisx, PlayState* play); + +void EnChristmasTree_Wait(EnChristmasTree* this, PlayState* play); +void EnChristmasTree_Talk(EnChristmasTree* this, PlayState* play); +void EnChristmasTree_SetupEndTitle(EnChristmasTree* this, PlayState* play); +void EnChristmasTree_HandleEndTitle(EnChristmasTree* this, PlayState* play); + +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_NONE, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_2, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x00000000, 0x00, 0x00 }, + TOUCH_NONE, + BUMP_NONE, + OCELEM_ON, + }, + { 100, 330, 0, { 0, 0, 0 } }, +}; + +static CollisionCheckInfoInit2 sColChkInfoInit = { 0, 0, 0, 0, MASS_IMMOVABLE }; + +void EnChristmasTree_Init(Actor* thisx, PlayState* play) { + EnChristmasTree* this = (EnChristmasTree*)thisx; + + ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 160.0f); + Collider_InitCylinder(play, &this->collider); + Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); + CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit); + Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, 4); + + this->actor.targetMode = 1; + this->actor.textId = 0x406B; // Hijacking bean seller text ID so I'm sure it doesn't clash + + this->actor.shape.rot.y = -14784; + + this->actionFunc = EnChristmasTree_Wait; +} + +void EnChristmasTree_Destroy(Actor* thisx, PlayState* play) { + EnChristmasTree* this = (EnChristmasTree*)thisx; + + Collider_DestroyCylinder(play, &this->collider); +} + +void EnChristmasTree_Wait(EnChristmasTree* this, PlayState* play) { + if (Actor_ProcessTalkRequest(&this->actor, play)) { // if talk is initiated + this->actionFunc = EnChristmasTree_Talk; + } else if ((this->actor.xzDistToPlayer < 170.0f) && Randomizer_GetSettingValue(RSK_TRIFORCE_HUNT)) { // talk range + func_8002F2CC(&this->actor, play, 170.0f); + } +} + +void EnChristmasTree_Talk(EnChristmasTree* this, PlayState* play) { + u8 dialogState = Message_GetState(&play->msgCtx); + if (dialogState != TEXT_STATE_CHOICE) { + if ((dialogState == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { // advanced final textbox + // Teleport to credits when goal is reached. + if (gSaveContext.triforcePiecesCollected >= Randomizer_GetSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED)) { + gSaveContext.sohStats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED] = GAMEPLAYSTAT_TOTAL_TIME; + gSaveContext.sohStats.gameComplete = 1; + Play_PerformSave(play); + GameInteractor_SetTriforceHuntCreditsWarpActive(true); + this->actionFunc = EnChristmasTree_SetupEndTitle; + } else { + this->actionFunc = EnChristmasTree_Wait; + } + } + } +} + +void EnChristmasTree_SetupEndTitle(EnChristmasTree* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + Actor_Spawn(&play->actorCtx, play, ACTOR_END_TITLE, 0, 0, 0, 0, 0, 0, 2, false); + + player->stateFlags1 = PLAYER_STATE1_INPUT_DISABLED; + + Flags_SetRandomizerInf(RAND_INF_GRANT_GANONS_BOSSKEY); + + Play_PerformSave(play); + + this->actionFunc = EnChristmasTree_HandleEndTitle; +} + +void EnChristmasTree_HandleEndTitle(EnChristmasTree* this, PlayState* play) { + Camera* camera = Play_GetCamera(play, play->mainCamera.thisIdx); + Player* player = GET_PLAYER(play); + Vec3f camAt; + Vec3f camEye; + + // Not forcing camera mode makes the camera jitter for a bit after setting position. + // Also forces letterbox bars. + Camera_ChangeMode(camera, CAM_MODE_STILL); + + // Christmas Tree's position + camAt.x = -734.0f; + camAt.y = 130.0f; + camAt.z = 420.0f; + + // Camera's position + camEye.x = -1237.0f; + camEye.y = 218.0f; + camEye.z = 408.0f; + + // Not setting fov manually makes camera zoom in after setting the above for a little bit. + camera->fov = 60.0f; + + // Set camera + Play_CameraSetAtEye(play, play->mainCamera.thisIdx, &camAt, &camEye); + + // Hide player so he's not visible in the final screen. Also move him so target arrow on tree dissapears. + player->actor.scale.x = player->actor.scale.y = player->actor.scale.z = 0.00001f; + player->actor.world.pos.z = 500.0f; + + // Hide HUD + Interface_ChangeAlpha(1); +} + +void EnChristmasTree_Update(Actor* thisx, PlayState* play) { + EnChristmasTree* this = (EnChristmasTree*)thisx; + ColliderCylinder* collider = &this->collider; + + Collider_UpdateCylinder(thisx, collider); + CollisionCheck_SetOC(play, &play->colChkCtx, (Collider*)collider); + + Actor_SetFocus(&this->actor, 80.0f); + + uint8_t triforceHuntActive = Randomizer_GetSettingValue(RSK_TRIFORCE_HUNT); + float percentageCompleted = (float)gSaveContext.triforcePiecesCollected / + (float)Randomizer_GetSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED); + + if ((percentageCompleted >= 1.0f || !triforceHuntActive) && !this->spawnedRupee) { + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_WONDER_ITEM, this->actor.world.pos.x, this->actor.world.pos.y + 280, + this->actor.world.pos.z, 0, 0, LINK_IS_ADULT ? 1 : 4, 0x1ABF, false); + this->spawnedRupee = 1; + } + + this->actionFunc(this, play); +} + +void EnChristmasTree_Draw(Actor* thisx, PlayState* play) { + EnChristmasTree* this = (EnChristmasTree*)thisx; + + float treeSize = 55.0f; + uint8_t triforceHuntActive = Randomizer_GetSettingValue(RSK_TRIFORCE_HUNT); + float percentageCompleted = (float)gSaveContext.triforcePiecesCollected / + (float)Randomizer_GetSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED); + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + Matrix_Scale(treeSize, treeSize, treeSize, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasTreeDL); + + if (percentageCompleted >= 0.1f || !triforceHuntActive) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor10DL); + } + if (percentageCompleted >= 0.2f || !triforceHuntActive) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor20DL); + } + if (percentageCompleted >= 0.3f || !triforceHuntActive) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor30DL); + } + if (percentageCompleted >= 0.4f || !triforceHuntActive) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor40DL); + } + if (percentageCompleted >= 0.5f || !triforceHuntActive) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor50DL); + } + if (percentageCompleted >= 0.6f || !triforceHuntActive) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor60DL); + } + if (percentageCompleted >= 0.7f || !triforceHuntActive) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor70DL); + } + if (percentageCompleted >= 0.8f || !triforceHuntActive) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor80DL); + } + if (percentageCompleted >= 0.9f || !triforceHuntActive) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor90DL); + } + if (percentageCompleted >= 1.0f || !triforceHuntActive) { + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasDecor100DL); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gXmasStarDL); + } + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/soh/src/overlays/actors/ovl_En_ChristmasTree/z_en_christmastree.h b/soh/src/overlays/actors/ovl_En_ChristmasTree/z_en_christmastree.h new file mode 100644 index 000000000..fd580ac71 --- /dev/null +++ b/soh/src/overlays/actors/ovl_En_ChristmasTree/z_en_christmastree.h @@ -0,0 +1,29 @@ +#ifndef Z_EN_CHRISTMASTREE_H +#define Z_EN_CHRISTMASTREE_H + +#include +#include "global.h" + +struct EnChristmasTree; + +typedef void (*EnChristmasTreeActionFunc)(struct EnChristmasTree*, PlayState*); + +typedef struct EnChristmasTree { + Actor actor; + ColliderCylinder collider; + EnChristmasTreeActionFunc actionFunc; + u8 spawnedRupee; +} EnChristmasTree; + +#ifdef __cplusplus +extern "C" { +#endif +void EnChristmasTree_Init(Actor* thisx, PlayState* play); +void EnChristmasTree_Destroy(Actor* thisx, PlayState* play); +void EnChristmasTree_Update(Actor* thisx, PlayState* play); +void EnChristmasTree_Draw(Actor* thisx, PlayState* play); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c b/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c index 753c3d537..187cc9b78 100644 --- a/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c +++ b/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c @@ -244,15 +244,22 @@ void EnClearTag_Init(Actor* thisx, PlayState* play) { if (this->actor.params == CLEAR_TAG_LASER) { this->state = CLEAR_TAG_STATE_LASER; this->timers[CLEAR_TAG_TIMER_LASER_DEATH] = 70; - this->actor.speedXZ = 35.0f; - Actor_UpdateVelocityXYZ(&this->actor); - for (j = 0; j <= 0; j++) { - Actor_UpdatePos(&this->actor); + if (CVarGetInteger("gHoliday.AGreenSpoon.EvilGossipStone", 0)) { + this->actor.scale.x = 0.4f; + this->actor.scale.y = 0.4f; + this->actor.scale.z = 2.0f; + this->actor.speedXZ = MAX(10.0f, Actor_WorldDistXZToActor(thisx, &GET_PLAYER(gPlayState)->actor) * 0.33f); + } else { + this->actor.speedXZ = 35.0f; + Actor_UpdateVelocityXYZ(&this->actor); + for (j = 0; j <= 0; j++) { + Actor_UpdatePos(&this->actor); + } + this->actor.scale.x = 0.4f; + this->actor.scale.y = 0.4f; + this->actor.scale.z = 2.0f; + this->actor.speedXZ = 70.0f; } - this->actor.scale.x = 0.4f; - this->actor.scale.y = 0.4f; - this->actor.scale.z = 2.0f; - this->actor.speedXZ = 70.0f; this->actor.shape.rot.x = -this->actor.shape.rot.x; Actor_UpdateVelocityXYZ(&this->actor); @@ -570,12 +577,21 @@ void EnClearTag_Update(Actor* thisx, PlayState* play2) { } // Set laser collider properties. - this->collider.dim.radius = 23; - this->collider.dim.height = 25; - this->collider.dim.yShift = -10; - Collider_UpdateCylinder(&this->actor, &this->collider); - CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); - Actor_UpdateBgCheckInfo(play, &this->actor, 50.0f, 80.0f, 100.0f, 5); + if (CVarGetInteger("gHoliday.AGreenSpoon.EvilGossipStone", 0)) { + this->collider.dim.radius = 10; + this->collider.dim.height = 25; + this->collider.dim.yShift = -10; + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); + Actor_UpdateBgCheckInfo(play, &this->actor, 10.0f, 10.0f, 10.0f, 5); + } else { + this->collider.dim.radius = 23; + this->collider.dim.height = 25; + this->collider.dim.yShift = -10; + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); + Actor_UpdateBgCheckInfo(play, &this->actor, 50.0f, 80.0f, 100.0f, 5); + } // Check if the laser has hit a target, timed out, or hit the ground. if (this->actor.bgCheckFlags & 9 || hasAtHit || this->timers[CLEAR_TAG_TIMER_LASER_DEATH] == 0) { diff --git a/soh/src/overlays/actors/ovl_En_Cs/z_en_cs.c b/soh/src/overlays/actors/ovl_En_Cs/z_en_cs.c index 78d4350c6..2bcd37c11 100644 --- a/soh/src/overlays/actors/ovl_En_Cs/z_en_cs.c +++ b/soh/src/overlays/actors/ovl_En_Cs/z_en_cs.c @@ -1,6 +1,7 @@ #include "z_en_cs.h" #include "objects/object_cs/object_cs.h" #include "objects/object_link_child/object_link_child.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -522,4 +523,19 @@ void EnCs_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Matrix_RotateZ(5.0 * M_PI / 9.0, MTXMODE_APPLY); Matrix_Get(&this->spookyMaskMtx); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(8191, -5757, -24133, MTXMODE_APPLY); + Matrix_Translate(270.27f, 297.297f, -513.514f, MTXMODE_APPLY); + Matrix_Scale(1.135f, 1.135f, 1.135f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } diff --git a/soh/src/overlays/actors/ovl_En_Daiku_Kakariko/z_en_daiku_kakariko.c b/soh/src/overlays/actors/ovl_En_Daiku_Kakariko/z_en_daiku_kakariko.c index 77e8bda81..c53c2c0af 100644 --- a/soh/src/overlays/actors/ovl_En_Daiku_Kakariko/z_en_daiku_kakariko.c +++ b/soh/src/overlays/actors/ovl_En_Daiku_Kakariko/z_en_daiku_kakariko.c @@ -6,6 +6,7 @@ #include "z_en_daiku_kakariko.h" #include "objects/object_daiku/object_daiku.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -540,6 +541,51 @@ void EnDaikuKakariko_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, V gSPDisplayList(POLY_OPA_DISP++, carpenterHeadDLists[this->actor.params & 3]); } + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + Matrix_Push(); + switch(this->actor.params) { + case 259: { + Matrix_RotateZYX(4649, 0, -3543, MTXMODE_APPLY); + Matrix_Translate(824.324f, 324.324f, -175.676f, MTXMODE_APPLY); + Matrix_Scale(0.966f, 0.966f, 0.966f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + break; + } + case 513: { + Matrix_RotateZYX(0, 0, -6200, MTXMODE_APPLY); + Matrix_Translate(770.27f, 567.568f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.899f, 0.899f, 0.899f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 255, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + break; + } + case 2: { + Matrix_RotateZYX(0, 0, 7970, MTXMODE_APPLY); + Matrix_Translate(1270.27f, -878.378f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 255, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + break; + } + case -256: + default: { + Matrix_RotateZYX(0, 0, -8635, MTXMODE_APPLY); + Matrix_Translate(675.676f, 716.216f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.899f, 0.899f, 0.899f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + } + } + Matrix_Pop(); + } + } + CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.c b/soh/src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.c index 735cb025d..d15ba09a4 100644 --- a/soh/src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.c +++ b/soh/src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.c @@ -3,6 +3,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE) @@ -1280,6 +1281,20 @@ void EnDekubaba_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* if (limbIndex == 1) { Collider_UpdateSpheres(limbIndex, &this->collider); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 4) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(16485, -1425, -20964, MTXMODE_APPLY); + Matrix_Translate(-149.0f, 92.0f, -587.0f, MTXMODE_APPLY); + Matrix_Scale(1.534f, 1.534f, 1.534f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnDekubaba_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c index fb665f74d..7087fee14 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c @@ -8,6 +8,7 @@ #include "objects/object_shopnuts/object_shopnuts.h" #include "vt.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" @@ -505,9 +506,27 @@ void EnDns_Update(Actor* thisx, PlayState* play) { } } +void EnDns_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + EnDns* this = (EnDns*)thisx; + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 17) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, 17490, MTXMODE_APPLY); + Matrix_Translate(4200.0f, -472.973f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(4.932f, 4.932f, 4.932f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } +} + void EnDns_Draw(Actor* thisx, PlayState* play) { EnDns* this = (EnDns*)thisx; Gfx_SetupDL_25Opa(play->state.gfxCtx); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, NULL, &this->actor); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, EnDns_PostLimbDraw, &this->actor); } diff --git a/soh/src/overlays/actors/ovl_En_Dodongo/z_en_dodongo.c b/soh/src/overlays/actors/ovl_En_Dodongo/z_en_dodongo.c index d714093ac..60ff72ad1 100644 --- a/soh/src/overlays/actors/ovl_En_Dodongo/z_en_dodongo.c +++ b/soh/src/overlays/actors/ovl_En_Dodongo/z_en_dodongo.c @@ -3,6 +3,7 @@ #include "overlays/actors/ovl_En_Bombf/z_en_bombf.h" #include "objects/object_dodongo/object_dodongo.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -916,6 +917,21 @@ void EnDodongo_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* Matrix_MultVec3f(&baseOffset, &this->icePos[i]); } } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 7) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, -13063, MTXMODE_APPLY); + Matrix_Translate(864.865f, 756.757f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.662f, 0.662f, 0.662f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnDodongo_Draw(Actor* thisx, PlayState* play2) { diff --git a/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c b/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c index 27619c492..113a27a5b 100644 --- a/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c +++ b/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c @@ -6,6 +6,7 @@ #include "z_en_dog.h" #include "objects/object_dog/object_dog.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS 0 @@ -495,6 +496,19 @@ s32 EnDog_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p } void EnDog_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 4) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(20811, -32768, 3985, MTXMODE_APPLY); + Matrix_Translate(0.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.25f, 1.25f, 1.25f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnDog_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c index 92670921d..7890e099b 100644 --- a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c +++ b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c @@ -11,6 +11,9 @@ #include "objects/object_mizu_objects/object_mizu_objects.h" #include "objects/object_haka_door/object_haka_door.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" + +#include "soh/Enhancements/Holiday/Archez.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -204,6 +207,7 @@ void EnDoor_Idle(EnDoor* this, PlayState* play) { gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]--; Flags_SetSwitch(play, this->actor.params & 0x3F); Audio_PlayActorSound2(&this->actor, NA_SE_EV_CHAIN_KEY_UNLOCK); + GameInteractor_ExecuteOnDungeonKeyUsedHooks(gSaveContext.mapIndex); } } else if (!Player_InCsMode(play)) { if (fabsf(playerPosRelToDoor.y) < 20.0f && fabsf(playerPosRelToDoor.x) < 20.0f && @@ -231,6 +235,11 @@ void EnDoor_Idle(EnDoor* this, PlayState* play) { this->actionFunc = EnDoor_AjarOpen; } } + // #region SOH [Co-op] + if (Flags_GetSwitch(play, this->actor.params & 0x3F)) { + DECR(this->lockTimer); + } + // #endregion } void EnDoor_WaitForCheck(EnDoor* this, PlayState* play) { @@ -339,6 +348,7 @@ void EnDoor_Draw(Actor* thisx, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); Gfx_SetupDL_25Opa(play->state.gfxCtx); + SkipOverrideNextSkeleton(); SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnDoor_OverrideLimbDraw, NULL, &this->actor); diff --git a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c index 497ba9388..0899a4683 100644 --- a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c +++ b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c @@ -10,6 +10,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -288,6 +289,21 @@ void EnDs_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, if (limbIndex == 5) { Matrix_MultVec3f(&sMultVec, &this->actor.focus.pos); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 5) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-1329, -3100, 0, MTXMODE_APPLY); + Matrix_Translate(1270.27f, 351.351f, -310.811f, MTXMODE_APPLY); + Matrix_Scale(0.797f, 0.797f, 0.797f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnDs_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c index 04d979127..f088a2b0e 100644 --- a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c +++ b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c @@ -3,6 +3,7 @@ #include "scenes/overworld/spot18/spot18_scene.h" #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -654,6 +655,20 @@ void EnDu_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, if (limbIndex == 16) { Matrix_MultVec3f(&D_809FF40C, &this->actor.focus.pos); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 17) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(13062, -1329, -15499, MTXMODE_APPLY); + Matrix_Translate(945.946f, -297.297f, 608.108f, MTXMODE_APPLY); + Matrix_Scale(1.217f, 1.217f, 1.217f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnDu_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index d1cc30952..8398aedfd 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -7,6 +7,7 @@ #include "z_en_elf.h" #include "objects/gameplay_keep/gameplay_keep.h" #include +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -1505,6 +1506,26 @@ s32 EnElf_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p return false; } +s32 EnElf_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + EnElf* this = (EnElf*)thisx; + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 2) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, 17047, MTXMODE_APPLY); + Matrix_Translate(202.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.595f, 0.595f, 0.595f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } + + return false; +} + void EnElf_Draw(Actor* thisx, PlayState* play) { s32 pad; f32 alphaScale; @@ -1542,7 +1563,7 @@ void EnElf_Draw(Actor* thisx, PlayState* play) { gDPSetEnvColor(POLY_XLU_DISP++, (u8)this->outerColor.r, (u8)this->outerColor.g, (u8)this->outerColor.b, (u8)(envAlpha * alphaScale)); POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, - EnElf_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); + EnElf_OverrideLimbDraw, EnElf_PostLimbDraw, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c index 38553196c..4ab331e0d 100644 --- a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c +++ b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c @@ -7,6 +7,7 @@ #include "z_en_fu.h" #include "objects/object_fu/object_fu.h" #include "scenes/indoors/hakasitarelay/hakasitarelay_scene.h" +#include "soh_assets.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" @@ -303,6 +304,20 @@ void EnFu_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, if (limbIndex == FU_LIMB_HEAD) { Matrix_MultVec3f(&sMtxSrc, &this->actor.focus.pos); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 14) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-27454, 0, 1992, MTXMODE_APPLY); + Matrix_Translate(878.378f, -108.108f, 67.568f, MTXMODE_APPLY); + Matrix_Scale(1.135f, 1.135f, 1.135f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnFu_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index 4718cac79..e5b9887eb 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -6,6 +6,8 @@ #include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #include "soh/OTRGlobals.h" +#include "soh_assets.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) void EnGo_Init(Actor* thisx, PlayState* play); @@ -1055,10 +1057,15 @@ void EnGo_DrawCurledUp(EnGo* this, PlayState* play) { Matrix_Push(); Gfx_SetupDL_25Opa(play->state.gfxCtx); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - - gSPDisplayList(POLY_OPA_DISP++, gGoronDL_00BD80); + if (CVarGetInteger("gHoliday.Archez.SnowGolems", 0)) { + Matrix_Translate(0.0f, 10.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.75f, 1.75f, 1.75f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSnowballDL); + } else { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gGoronDL_00BD80); + } Matrix_MultVec3f(&D_80A41BB4, &this->actor.focus.pos); Matrix_Pop(); @@ -1075,9 +1082,15 @@ void EnGo_DrawRolling(EnGo* this, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); Matrix_RotateZYX((s16)(play->state.frames * ((s16)this->actor.speedXZ * 1400)), 0, this->actor.shape.rot.z, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, gGoronDL_00C140); + if (CVarGetInteger("gHoliday.Archez.SnowGolems", 0)) { + Matrix_Translate(0.0f, -10.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.75f, 1.75f, 1.75f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSnowballDL); + } else { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gGoronDL_00C140); + } Matrix_MultVec3f(&D_80A41BC0, &this->actor.focus.pos); Matrix_Pop(); diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index 547524eda..4d2b6b9fc 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -8,6 +8,8 @@ #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) /* @@ -2016,9 +2018,15 @@ s32 EnGo2_DrawCurledUp(EnGo2* this, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); Gfx_SetupDL_25Opa(play->state.gfxCtx); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, gGoronDL_00BD80); + if (CVarGetInteger("gHoliday.Archez.SnowGolems", 0)) { + Matrix_Translate(0.0f, 10.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.75f, 1.75f, 1.75f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSnowballDL); + } else { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gGoronDL_00BD80); + } CLOSE_DISPS(play->state.gfxCtx); Matrix_MultVec3f(&D_80A48554, &this->actor.focus.pos); @@ -2034,9 +2042,17 @@ s32 EnGo2_DrawRolling(EnGo2* this, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); speedXZ = this->actionFunc == EnGo2_ReverseRolling ? 0.0f : this->actor.speedXZ; Matrix_RotateZYX((play->state.frames * ((s16)speedXZ * 1400)), 0, this->actor.shape.rot.z, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, gGoronDL_00C140); + if (CVarGetInteger("gHoliday.Archez.SnowGolems", 0)) { + Matrix_Translate(0.0f, -10.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.75f, 1.75f, 1.75f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSnowballDL); + } else { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gGoronDL_00C140); + } CLOSE_DISPS(play->state.gfxCtx); Matrix_MultVec3f(&D_80A48560, &this->actor.focus.pos); return 1; diff --git a/soh/src/overlays/actors/ovl_En_Hata/z_en_hata.c b/soh/src/overlays/actors/ovl_En_Hata/z_en_hata.c index 6e36e2027..4a5917733 100644 --- a/soh/src/overlays/actors/ovl_En_Hata/z_en_hata.c +++ b/soh/src/overlays/actors/ovl_En_Hata/z_en_hata.c @@ -7,6 +7,8 @@ #include "z_en_hata.h" #include "objects/object_hata/object_hata.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS 0 void EnHata_Init(Actor* thisx, PlayState* play); @@ -130,6 +132,11 @@ s32 EnHata_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* rot->y += limbs[limbIndex].y; rot->z += limbs[limbIndex].z; } + + if (limbIndex == FLAGPOLE_LIMB_POLE_BASE || limbIndex == FLAGPOLE_LIMB_POLE) { + SkipOverrideNextLimb(); + } + return false; } diff --git a/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c b/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c index 90d47b098..a0dc814ad 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c +++ b/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c @@ -9,6 +9,8 @@ #include "vt.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED void EnHeishi1_Init(Actor* thisx, PlayState* play); @@ -498,6 +500,10 @@ s32 EnHeishi1_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3 rot->x += (s16)this->headAngle; } + if (limbIndex == 15) { + SkipOverrideNextLimb(); + } + return false; } diff --git a/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c b/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c index 89fd574d0..d00834ad4 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c +++ b/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c @@ -13,6 +13,8 @@ #include "overlays/actors/ovl_Bg_Spot15_Saku/z_bg_spot15_saku.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) void EnHeishi2_Init(Actor* thisx, PlayState* play); @@ -817,6 +819,10 @@ s32 EnHeishi2_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3 } } + if (limbIndex == 15) { + SkipOverrideNextLimb(); + } + return false; } diff --git a/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c b/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c index 372075806..9690f8913 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c +++ b/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c @@ -9,6 +9,8 @@ #include "vt.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS 0 void EnHeishi3_Init(Actor* thisx, PlayState* play); @@ -245,6 +247,10 @@ s32 EnHeishi3_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3 rot->z += this->unk_264; } + if (limbIndex == 15) { + SkipOverrideNextLimb(); + } + return false; } diff --git a/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c b/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c index f118a55ec..e69b73b1a 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c +++ b/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c @@ -1,9 +1,12 @@ #include "z_en_heishi4.h" #include "objects/object_sd/object_sd.h" #include "vt.h" +#include "soh_assets.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) void EnHeishi4_Init(Actor* thisx, PlayState* play); @@ -413,6 +416,31 @@ s32 EnHeishi_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f rot->x += this->unk_260.y; rot->z += this->unk_260.z; } + + if (limbIndex == 15) { + SkipOverrideNextLimb(); + } + + return false; +} + +s32 EnHeishi4_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + EnHeishi4* this = (EnHeishi4*)thisx; + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 16) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, 442, MTXMODE_APPLY); + Matrix_Translate(256.757f, 121.621f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.337f, 1.337f, 1.337f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } + return false; } @@ -420,5 +448,5 @@ void EnHeishi4_Draw(Actor* thisx, PlayState* play) { EnHeishi4* this = (EnHeishi4*)thisx; Gfx_SetupDL_25Opa(play->state.gfxCtx); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnHeishi_OverrideLimbDraw, NULL, this); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnHeishi_OverrideLimbDraw, EnHeishi4_PostLimbDraw, this); } diff --git a/soh/src/overlays/actors/ovl_En_Hs2/z_en_hs2.c b/soh/src/overlays/actors/ovl_En_Hs2/z_en_hs2.c index 6801247ec..adde48a01 100644 --- a/soh/src/overlays/actors/ovl_En_Hs2/z_en_hs2.c +++ b/soh/src/overlays/actors/ovl_En_Hs2/z_en_hs2.c @@ -7,6 +7,7 @@ #include "z_en_hs2.h" #include "vt.h" #include "objects/object_hs/object_hs.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -66,6 +67,14 @@ void EnHs2_Init(Actor* thisx, PlayState* play) { this->actionFunc = func_80A6F1A4; this->unk_2A8 = 0; this->actor.targetMode = 6; + + if (play->sceneNum == SCENE_KAKARIKO_VILLAGE) { + this->actor.world.pos.x = 756.0; + this->actor.world.pos.y = 80.0; + this->actor.world.pos.z = 1378.0; + this->actor.shape.rot.y = 32534; + } + } void EnHs2_Destroy(Actor* thisx, PlayState* play) { @@ -161,6 +170,21 @@ void EnHs2_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, if (limbIndex == 9) { Matrix_MultVec3f(&D_80A6F4CC, &this->actor.focus.pos); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 9) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, -6421, MTXMODE_APPLY); + Matrix_Translate(621.622f, 378.378f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.763f, 0.763f, 0.763f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 255, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnHs2_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c index 961106225..084fbdf5c 100644 --- a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c +++ b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c @@ -17,6 +17,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -542,7 +543,9 @@ u16 func_80A6F810(PlayState* play, Actor* thisx) { return 0x5058; } case ENHY_TYPE_BOB_18: - if (!LINK_IS_ADULT) { + if (CVarGetInteger("gHoliday.Fredomato.TreeChopper", 0)) { + return 0x505e; + } else if (!LINK_IS_ADULT) { return (Flags_GetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE)) ? 0x505F : ((Flags_GetInfTable(INFTABLE_163)) ? 0x505E : 0x505D); } else { return (this->unk_330 & 0x800) ? 0x5062 : ((Flags_GetInfTable(INFTABLE_164)) ? 0x5061 : 0x5060); @@ -892,6 +895,21 @@ void EnHy_Init(Actor* thisx, PlayState* play) { Actor_Kill(&this->actor); } + if (play->sceneNum == SCENE_KAKARIKO_VILLAGE) { + if (this->actor.params == 1929) { + this->actor.world.pos.x = 261.826; + this->actor.world.pos.y = 240.0; + this->actor.world.pos.z = 1669.660; + this->actor.shape.rot.y = 23784; + } + if (this->actor.params == 1930) { + this->actor.world.pos.x = 262.224; + this->actor.world.pos.y = 240.0; + this->actor.world.pos.z = 1594.390; + this->actor.shape.rot.y = 7728; + } + } + this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->actionFunc = EnHy_InitImpl; } @@ -1173,6 +1191,101 @@ void EnHy_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Matrix_MultVec3f(&sp3C, &this->actor.focus.pos); } + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + Matrix_Push(); + switch(this->actor.params) { + case 1938: { + Matrix_RotateZYX(5313, 0, -1550, MTXMODE_APPLY); + Matrix_Translate(1108.108f, 54.054f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + break; + } + case 135: + case 7: { + Matrix_RotateZYX(1328, 0, 885, MTXMODE_APPLY); + Matrix_Translate(864.865f, 229.73f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.25f, 1.25f, 1.25f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + break; + } + case 1922: { + Matrix_RotateZYX(4206, 221, -3543, MTXMODE_APPLY); + Matrix_Translate(662.162f, 162.162f, -27.027f, MTXMODE_APPLY); + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + break; + } + case 1925: { + Matrix_RotateZYX(-9521, 442, -5536, MTXMODE_APPLY); + Matrix_Translate(351.351f, 256.757f, 283.784f, MTXMODE_APPLY); + Matrix_Scale(1.217f, 1.217f, 1.217f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + break; + } + case 1920: { + Matrix_RotateZYX(0, 0, 3321, MTXMODE_APPLY); + Matrix_Translate(1148.649f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.73f, 0.73f, 0.73f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + break; + } + case 1930: { + Matrix_RotateZYX(3542, 0, 0, MTXMODE_APPLY); + Matrix_Translate(972.973f, -13.514f, 54.054f, MTXMODE_APPLY); + Matrix_Scale(0.831f, 0.831f, 0.831f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + break; + } + case 1929: { + Matrix_RotateZYX(3542, 0, 0, MTXMODE_APPLY); + Matrix_Translate(972.973f, -13.514f, 54.054f, MTXMODE_APPLY); + Matrix_Scale(0.831f, 0.831f, 0.831f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + break; + } + case 1921: { + Matrix_RotateZYX(0, 0, 664, MTXMODE_APPLY); + Matrix_Translate(1256.757f, -297.297f, -40.541f, MTXMODE_APPLY); + Matrix_Scale(1.135f, 1.135f, 1.135f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 255, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + break; + } + case 1939: { + Matrix_RotateZYX(2656, 1328, 1992, MTXMODE_APPLY); + Matrix_Translate(1094.594f, 94.594f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.351f, 1.351f, 1.351f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + break; + } + default: { + Matrix_RotateZYX(0, 0, 664, MTXMODE_APPLY); + Matrix_Translate(783.784f, 94.594f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.662f, 0.662f, 0.662f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + break; + } + } + Matrix_Pop(); + } + } + CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c index ea09efa20..ed1edd41f 100644 --- a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c +++ b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c @@ -9,8 +9,11 @@ #include "objects/object_ik/object_ik.h" #include "vt.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED typedef void (*EnIkDrawFunc)(struct EnIk*, PlayState*); @@ -845,6 +848,11 @@ s32 EnIk_OverrideLimbDraw3(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p *dList = NULL; } } + + if (limbIndex == 17) { + SkipOverrideNextLimb(); + } + return false; } @@ -945,6 +953,19 @@ void EnIk_PostLimbDraw3(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, break; } + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 11) { + Matrix_Push(); + Matrix_RotateZYX(0, 0, -15056, MTXMODE_APPLY); + Matrix_Translate(824.324f, 472.973f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.845f, 0.845f, 0.845f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 100, 100, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + } + } + CLOSE_DISPS(play->state.gfxCtx); } @@ -1179,6 +1200,10 @@ s32 EnIk_OverrideLimbDraw2(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p } } + if (limbIndex == 17) { + SkipOverrideNextLimb(); + } + return 0; } @@ -1226,6 +1251,20 @@ void EnIk_PostLimbDraw2(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, } } break; } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 11) { + Matrix_Push(); + Matrix_RotateZYX(0, 0, -15056, MTXMODE_APPLY); + Matrix_Translate(824.324f, 472.973f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.845f, 0.845f, 0.845f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 100, 100, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + } + } + CLOSE_DISPS(gfxCtx); } @@ -1331,6 +1370,7 @@ s32 EnIk_OverrideLimbDraw1(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p if (curFrame < 120.0f) { *dList = NULL; } else { + SkipOverrideNextLimb(); func_80A76E2C(this, play, pos); } break; @@ -1376,6 +1416,19 @@ void EnIk_PostLimbDraw1(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, break; } + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 11) { + Matrix_Push(); + Matrix_RotateZYX(0, 0, -15056, MTXMODE_APPLY); + Matrix_Translate(824.324f, 472.973f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.845f, 0.845f, 0.845f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 100, 100, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + } + } + CLOSE_DISPS(gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_In/z_en_in.c b/soh/src/overlays/actors/ovl_En_In/z_en_in.c index 7bfc68dbe..17df55638 100644 --- a/soh/src/overlays/actors/ovl_En_In/z_en_in.c +++ b/soh/src/overlays/actors/ovl_En_In/z_en_in.c @@ -1,6 +1,7 @@ #include "z_en_in.h" #include "overlays/actors/ovl_En_Horse/z_en_horse.h" #include "objects/object_in/object_in.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -988,6 +989,18 @@ void EnIn_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, gSPDisplayList(POLY_OPA_DISP++, gIngoChildEraPitchForkDL); } + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 16) { + Matrix_Push(); + Matrix_RotateZYX(-8192, -222, -11513, MTXMODE_APPLY); + Matrix_Translate(770.0f, 837.0f, 878.0f, MTXMODE_APPLY); + Matrix_Scale(1.068f, 1.068f, 1.068f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + } + } + CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Jj/z_en_jj.c b/soh/src/overlays/actors/ovl_En_Jj/z_en_jj.c index 12863e4c6..7e1b72518 100644 --- a/soh/src/overlays/actors/ovl_En_Jj/z_en_jj.c +++ b/soh/src/overlays/actors/ovl_En_Jj/z_en_jj.c @@ -7,8 +7,11 @@ #include "z_en_jj.h" #include "objects/object_jj/object_jj.h" #include "overlays/actors/ovl_Eff_Dust/z_eff_dust.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) typedef enum { @@ -308,6 +311,26 @@ void EnJj_Update(Actor* thisx, PlayState* play) { this->skelAnime.jointTable[10].z = this->mouthOpenAngle; } +s32 EnJj_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + EnJj* this = (EnJj*)thisx; + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 13) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(4649, -8635, 15276, MTXMODE_APPLY); + Matrix_Translate(27.027f, 135.135f, -81.081f, MTXMODE_APPLY); + Matrix_Scale(0.304f, 0.304f, 0.304f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } + + return false; +} + void EnJj_Draw(Actor* thisx, PlayState* play2) { static void* eyeTextures[] = { gJabuJabuEyeOpenTex, gJabuJabuEyeHalfTex, gJabuJabuEyeClosedTex }; PlayState* play = play2; @@ -319,7 +342,8 @@ void EnJj_Draw(Actor* thisx, PlayState* play2) { Matrix_Translate(0.0f, (cosf(this->skelAnime.curFrame * (M_PI / 41.0f)) * 10.0f) - 10.0f, 0.0f, MTXMODE_APPLY); Matrix_Scale(10.0f, 10.0f, 10.0f, MTXMODE_APPLY); gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(eyeTextures[this->eyeIndex])); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, NULL, this); + SkipOverrideNextSkeleton(); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, EnJj_PostLimbDraw, this); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c index dc069b7a8..60112d892 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c @@ -1354,6 +1354,12 @@ Gfx* EnKo_SetEnvColor(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b, u8 a) { void EnKo_Draw(Actor* thisx, PlayState* play) { EnKo* this = (EnKo*)thisx; Color_RGBA8 tunicColor = sModelInfo[ENKO_TYPE].tunicColor; + + // Overwrite to red tunic as default for Holidays in Hyrule build + tunicColor.r = 255; + tunicColor.g = 0; + tunicColor.b = 0; + Color_RGBA8 bootsColor = sModelInfo[ENKO_TYPE].bootsColor; if (CVarGetInteger(CVAR_COSMETIC("NPC.Kokiri.Changed"), 0)) { diff --git a/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c b/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c index 7389db34b..8a48687ca 100644 --- a/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c +++ b/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c @@ -266,6 +266,12 @@ void EnKusa_Init(Actor* thisx, PlayState* play) { return; } + if (gPlayState->sceneNum == SCENE_KAKARIKO_VILLAGE && this->actor.world.pos.z < 600.0) { + this->actor.world.pos.x += 1620.672; + this->actor.world.pos.y += 80; + this->actor.world.pos.z += 900.884; + } + EnKusa_SetupWaitObject(this); } diff --git a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c index e4ceacfb2..4176b5d1f 100644 --- a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c +++ b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c @@ -8,6 +8,7 @@ #include "objects/object_ma1/object_ma1.h" #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -457,6 +458,21 @@ void EnMa1_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, if (limbIndex == 15) { Matrix_MultVec3f(&vec, &this->actor.focus.pos); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, 0, MTXMODE_APPLY); + Matrix_Translate(756.757f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.73f, 0.73f, 0.73f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnMa1_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c b/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c index 96bcac036..cc9ae7fa2 100644 --- a/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c +++ b/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c @@ -9,6 +9,8 @@ #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + /* * This actor can have three behaviors: * - "Spear Guard" (variable -1): uses a spear, walks around home point, charges player if too close @@ -1551,6 +1553,22 @@ void EnMb_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, } } +s32 EnMb_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { + EnMb* this = (EnMb*)thisx; + + if (this->actor.params == ENMB_TYPE_CLUB) { + if (limbIndex == ENMB_LIMB_LHAND) { + SkipOverrideNextLimb(); + } + } else { + if (limbIndex == ENMB_LIMB_RHAND) { + SkipOverrideNextLimb(); + } + } + + return 0; +} + void EnMb_Draw(Actor* thisx, PlayState* play) { static Vec3f frontShieldingTriModel0[] = { { 4000.0f, 7000.0f, 3500.0f }, @@ -1570,7 +1588,7 @@ void EnMb_Draw(Actor* thisx, PlayState* play) { EnMb* this = (EnMb*)thisx; Gfx_SetupDL_25Opa(play->state.gfxCtx); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, EnMb_PostLimbDraw, thisx); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnMb_OverrideLimbDraw, EnMb_PostLimbDraw, thisx); if (thisx->params != ENMB_TYPE_CLUB) { if (this->attack > ENMB_ATTACK_NONE) { diff --git a/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c b/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c index 203a7af59..4200ca00b 100644 --- a/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c +++ b/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c @@ -9,6 +9,7 @@ #include "overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.h" #include "vt.h" #include "soh/frame_interpolation.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_ALWAYS_THROWN) @@ -1133,13 +1134,33 @@ s32 EnNiw_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p return false; } +s32 EnNiw_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + EnNiw* this = (EnNiw*)thisx; + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, -19705, MTXMODE_APPLY); + Matrix_Translate(297.297f, -81.082f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } + + return false; +} + void EnNiw_Draw(Actor* thisx, PlayState* play) { EnNiw* this = (EnNiw*)thisx; Vec3f scale = { 0.15f, 0.15f, 0.15f }; GraphicsContext* gfxCtx = play->state.gfxCtx; Gfx_SetupDL_25Opa(play->state.gfxCtx); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnNiw_OverrideLimbDraw, NULL, this); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnNiw_OverrideLimbDraw, EnNiw_PostLimbDraw, this); if (this->actionFunc == func_80AB6450) { func_80033C30(&this->actor.world.pos, &scale, 255, play); diff --git a/soh/src/overlays/actors/ovl_En_Niw_Girl/z_en_niw_girl.c b/soh/src/overlays/actors/ovl_En_Niw_Girl/z_en_niw_girl.c index ffb752c6c..b3fbaee1d 100644 --- a/soh/src/overlays/actors/ovl_En_Niw_Girl/z_en_niw_girl.c +++ b/soh/src/overlays/actors/ovl_En_Niw_Girl/z_en_niw_girl.c @@ -7,6 +7,7 @@ #include "z_en_niw_girl.h" #include "objects/object_gr/object_gr.h" #include "vt.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -249,6 +250,27 @@ s32 EnNiwGirlOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f static Vec3f sConstVec3f = { 0.2f, 0.2f, 0.2f }; +s32 EnNiwGirl_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + EnNiwGirl* this = (EnNiwGirl*)thisx; + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 4) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, 0, MTXMODE_APPLY); + Matrix_Translate(945.945f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.676f, 0.676f, 0.676f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } + + return false; +} + void EnNiwGirl_Draw(Actor* thisx, PlayState* play) { static void* eyeTextures[] = { gNiwGirlEyeOpenTex, gNiwGirlEyeHalfTex, gNiwGirlEyeClosedTex }; EnNiwGirl* this = (EnNiwGirl*)thisx; @@ -259,7 +281,7 @@ void EnNiwGirl_Draw(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(eyeTextures[this->eyeIndex])); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnNiwGirlOverrideLimbDraw, NULL, this); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnNiwGirlOverrideLimbDraw, EnNiwGirl_PostLimbDraw, this); func_80033C30(&this->actor.world.pos, &sp4C, 255, play); CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c index 63d4104de..76fb5ebb2 100644 --- a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c +++ b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c @@ -7,6 +7,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -602,6 +603,27 @@ s32 EnNiwLady_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3 return false; } +s32 EnNiwLady_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + EnNiwLady* this = (EnNiwLady*)thisx; + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-886, -3322, -5093, MTXMODE_APPLY); + Matrix_Translate(824.324f, 283.782f, -202.703f, MTXMODE_APPLY); + Matrix_Scale(0.762f, 0.762f, 0.762f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } + + return false; +} + void EnNiwLady_Draw(Actor* thisx, PlayState* play) { static void* sEyeTextures[] = { gCuccoLadyEyeOpenTex, gCuccoLadyEyeHalfTex, gCuccoLadyEyeClosedTex }; EnNiwLady* this = (EnNiwLady*)thisx; @@ -613,7 +635,7 @@ void EnNiwLady_Draw(Actor* thisx, PlayState* play) { gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sEyeTextures[this->faceState])); gSPSegment(POLY_OPA_DISP++, 0x0C, func_80ABB0A0(play->state.gfxCtx)); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnNiwLady_OverrideLimbDraw, NULL, this); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnNiwLady_OverrideLimbDraw, EnNiwLady_PostLimbDraw, this); } CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c b/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c index 34afa674f..70c8e1ac8 100644 --- a/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c +++ b/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c @@ -10,6 +10,7 @@ #include "objects/object_dekunuts/object_dekunuts.h" #include "objects/object_hintnuts/object_hintnuts.h" #include "objects/object_shopnuts/object_shopnuts.h" +#include "assets/objects/gameplay_keep/gameplay_keep.h" #include "objects/object_dns/object_dns.h" #include "objects/object_dnk/object_dnk.h" @@ -47,7 +48,7 @@ static ColliderCylinderInit sCylinderInit = { }, { ELEMTYPE_UNK0, - { 0xFFCFFFFF, 0x00, 0x08 }, + { 0xFFCFFFFF, 0x02, 0x08 }, { 0xFFCFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_WOOD, BUMP_ON, @@ -72,10 +73,12 @@ void EnNutsball_Init(Actor* thisx, PlayState* play) { EnNutsball* this = (EnNutsball*)thisx; s32 pad; + this->collider.info.toucher.effect = 2; + ActorShape_Init(&this->actor.shape, 400.0f, ActorShadow_DrawCircle, 13.0f); Collider_InitCylinder(play, &this->collider); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); - if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gLetItSnow", 0)) { this->objBankIndex = 0; } else { this->objBankIndex = Object_GetIndex(&play->objectCtx, sObjectIDs[this->actor.params]); @@ -141,8 +144,8 @@ void func_80ABBBA8(EnNutsball* this, PlayState* play) { sp40.y = this->actor.world.pos.y + 4; sp40.z = this->actor.world.pos.z; - EffectSsHahen_SpawnBurst(play, &sp40, 6.0f, 0, 7, 3, 15, HAHEN_OBJECT_DEFAULT, 10, NULL); - SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, NA_SE_EN_OCTAROCK_ROCK); + EffectSsIcePiece_SpawnBurst(play, &this->actor.world.pos, this->actor.scale.x / 10); + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, NA_SE_PL_ICE_BROKEN); Actor_Kill(&this->actor); } else { if (this->timer == -300) { @@ -176,17 +179,19 @@ void EnNutsball_Draw(Actor* thisx, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); - if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) != 0) { + if ((CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) != 0) || CVarGetInteger("gLetItSnow", 0)) { Gfx_SetupDL_25Opa(play->state.gfxCtx); - gSPSegment(POLY_OPA_DISP++, 0x08, - Gfx_TwoTexScroll(play->state.gfxCtx, 0, 1 * (play->state.frames * 6), - 1 * (play->state.frames * 6), 32, 32, 1, 1 * (play->state.frames * 6), - 1 * (play->state.frames * 6), 32, 32)); - Matrix_Scale(25.0f,25.0f,25.0f,MTXMODE_APPLY); + f32 scale = 12.0f; + + gSPSegment(POLY_OPA_DISP++, 0x08, Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1, 0, (1 * -2) % 128, 32, 32)); + Matrix_RotateX(thisx->home.rot.z * 9.58738e-05f, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, sDListsNew[thisx->params]); + Matrix_Translate(0.0f, -445.946f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 50, 100, 255); + gSPDisplayList(POLY_OPA_DISP++, gEffIceFragment3DL); } else { Gfx_SetupDL_25Opa(play->state.gfxCtx); Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY); diff --git a/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c b/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c index 60a3452a0..65ea20c68 100644 --- a/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c +++ b/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c @@ -2,6 +2,7 @@ #include "objects/object_okuta/object_okuta.h" #include "objects/gameplay_field_keep/gameplay_field_keep.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "assets/objects/gameplay_keep/gameplay_keep.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE) @@ -46,7 +47,7 @@ static ColliderCylinderInit sProjectileColliderInit = { }, { ELEMTYPE_UNK0, - { 0xFFCFFFFF, 0x00, 0x08 }, + { 0xFFCFFFFF, 0x02, 0x08 }, { 0xFFCFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_HARD, BUMP_ON, @@ -520,38 +521,12 @@ void EnOkuta_ProjectileFly(EnOkuta* this, PlayState* play) { f32 temp_f20; f32 temp_f22; s32 i; - for (s16 i = 0; i < ARRAY_COUNT(sEffectScales); i++) { - phi_s0 += 10000; - - temp_f20 = Rand_ZeroOne() * 5.0f; - pos.x = (Math_SinS(phi_s0) * temp_f20) + this->actor.world.pos.x; - pos.y = (Rand_ZeroOne() * 40.0f) + this->actor.world.pos.y + 5.0f; - pos.z = (Math_CosS(phi_s0) * temp_f20) + this->actor.world.pos.z; - - temp_f20 = (Rand_ZeroOne() * 5.0f) + 2.0f; - velocity.x = Math_SinS(phi_s0) * temp_f20; - temp_f22 = Rand_ZeroOne(); - velocity.y = (Rand_ZeroOne() * i * 2.5f) + (temp_f22 * 5.0f); - velocity.z = Math_CosS(phi_s0) * temp_f20; - - if (i == 0) { - phi_v0 = 41; - gravity = -450; - } else if (i < 4) { - phi_v0 = 37; - gravity = -380; - } else { - phi_v0 = 69; - gravity = -320; - } - EffectSsKakera_Spawn(play, &pos, &velocity, &this->actor.world.pos, gravity, phi_v0, 30, 5, 0, - sEffectScales[i]/5, 3, 0, 70, 1, OBJECT_GAMEPLAY_FIELD_KEEP, gSilverRockFragmentsDL); - } + EffectSsIcePiece_SpawnBurst(play, &this->actor.world.pos, this->actor.scale.x / 10); } else { EffectSsHahen_SpawnBurst(play, &pos, 6.0f, 0, 1, 2, 15, 7, 10, gOctorokProjectileDL); } - SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, NA_SE_EN_OCTAROCK_ROCK); + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, NA_SE_PL_ICE_BROKEN); Actor_Kill(&this->actor); } } else if (this->timer == -300) { @@ -764,17 +739,19 @@ void EnOkuta_Draw(Actor* thisx, PlayState* play) { } else { OPEN_DISPS(play->state.gfxCtx); - if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) != 0) { + if ((CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) != 0) || CVarGetInteger("gLetItSnow", 0)) { Gfx_SetupDL_25Opa(play->state.gfxCtx); - gSPSegment(POLY_OPA_DISP++, 0x08, - Gfx_TwoTexScroll(play->state.gfxCtx, 0, 1 * (play->state.frames * 6), - 1 * (play->state.frames * 6), 32, 32, 1, 1 * (play->state.frames * 6), - 1 * (play->state.frames * 6), 32, 32)); - Matrix_Scale(7.0f,7.0f,7.0f,MTXMODE_APPLY); - Matrix_RotateX(thisx->home.rot.z * (M_PI / 0x8000), MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, gSilverRockDL); + f32 scale = 12.0f; + + gSPSegment(POLY_OPA_DISP++, 0x08, Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1, 0, (1 * -2) % 128, 32, 32)); + + Matrix_RotateX(thisx->home.rot.z * 9.58738e-05f, MTXMODE_APPLY); + Matrix_Translate(0.0f, -445.946f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 50, 100, 255); + gSPDisplayList(POLY_OPA_DISP++, gEffIceFragment3DL); } else { Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY); Matrix_RotateZ(this->actor.home.rot.z * (M_PI / 0x8000), MTXMODE_APPLY); diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index 3eaa944b0..354010279 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -16,6 +16,7 @@ #include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include #include "soh/OTRGlobals.h" @@ -2416,6 +2417,69 @@ void EnOssan_DrawStickDirectionPrompts(PlayState* play, EnOssan* this) { CLOSE_DISPS(play->state.gfxCtx); } +s32 EnOssan_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + EnOssan* this = (EnOssan*)thisx; + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 8) { + switch(this->actor.params) { + case 4: { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-11071, -443, -3986, MTXMODE_APPLY); + Matrix_Translate(878.378f, 351.351f, 540.541f, MTXMODE_APPLY); + Matrix_Scale(1.352f, 1.352f, 1.352f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + break; + } + case 1: + case 3: { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-6643, 1992, -1772, MTXMODE_APPLY); + Matrix_Translate(918.919f, 121.622f, 256.757f, MTXMODE_APPLY); + Matrix_Scale(0.73f, 0.73f, 0.73f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 255, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + break; + } + case 2: { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-16163, 0, 2878, MTXMODE_APPLY); + Matrix_Translate(905.406f, 0.0f, -27.027f, MTXMODE_APPLY); + Matrix_Scale(1.318f, 1.318f, 1.318f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + break; + } + default: { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-11071, -443, -3986, MTXMODE_APPLY); + Matrix_Translate(878.378f, 351.351f, 540.541f, MTXMODE_APPLY); + Matrix_Scale(1.352f, 1.352f, 1.352f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + break; + } + } + } + } + + return false; +} + void EnOssan_DrawBazaarShopkeeper(Actor* thisx, PlayState* play) { static void* sBazaarShopkeeperEyeTextures[] = { gOssanEyeOpenTex, gOssanEyeHalfTex, gOssanEyeClosedTex }; EnOssan* this = (EnOssan*)thisx; @@ -2425,7 +2489,7 @@ void EnOssan_DrawBazaarShopkeeper(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sBazaarShopkeeperEyeTextures[this->eyeTextureIdx])); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnOssan_OverrideLimbDrawDefaultShopkeeper, NULL, this); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnOssan_OverrideLimbDrawDefaultShopkeeper, EnOssan_PostLimbDraw, this); EnOssan_DrawCursor(play, this, this->cursorX, this->cursorY, this->cursorZ, this->drawCursor); EnOssan_DrawStickDirectionPrompts(play, this); @@ -2451,6 +2515,16 @@ s32 EnOssan_OverrideLimbDrawKokiriShopkeeper(PlayState* play, s32 limbIndex, Gfx gSPSegment(POLY_OPA_DISP++, 0x0A, SEGMENTED_TO_VIRTUAL(sKokiriShopkeeperEyeTextures[this->eyeTextureIdx])); } + if (limbIndex == 15) { + Matrix_Push(); + Matrix_RotateZYX(14169, -2215, 0, MTXMODE_APPLY); + Matrix_Translate(1810.811f, -351.351f, -94.595f, MTXMODE_APPLY); + Matrix_Scale(1.068f, 1.068f, 1.068f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + } + CLOSE_DISPS(play->state.gfxCtx); return 0; @@ -2479,8 +2553,8 @@ void EnOssan_DrawKokiriShopkeeper(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); - gSPSegment(POLY_OPA_DISP++, 0x08, EnOssan_SetEnvColor(play->state.gfxCtx, 0, 130, 70, 255)); - gSPSegment(POLY_OPA_DISP++, 0x09, EnOssan_SetEnvColor(play->state.gfxCtx, 110, 170, 20, 255)); + gSPSegment(POLY_OPA_DISP++, 0x08, EnOssan_SetEnvColor(play->state.gfxCtx, 255, 0, 0, 255)); + gSPSegment(POLY_OPA_DISP++, 0x09, EnOssan_SetEnvColor(play->state.gfxCtx, 255, 0, 0, 255)); gSPSegment(POLY_OPA_DISP++, 0x0C, EnOssan_EndDList(play->state.gfxCtx)); SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnOssan_OverrideLimbDrawKokiriShopkeeper, NULL, this); @@ -2555,7 +2629,7 @@ void EnOssan_DrawPotionShopkeeper(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sPotionShopkeeperEyeTextures[this->eyeTextureIdx])); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, NULL, this); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, EnOssan_PostLimbDraw, this); EnOssan_DrawCursor(play, this, this->cursorX, this->cursorY, this->cursorZ, this->drawCursor); EnOssan_DrawStickDirectionPrompts(play, this); @@ -2591,7 +2665,7 @@ void EnOssan_DrawBombchuShopkeeper(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sBombchuShopkeeperEyeTextures[this->eyeTextureIdx])); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, NULL, this); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, EnOssan_PostLimbDraw, this); EnOssan_DrawCursor(play, this, this->cursorX, this->cursorY, this->cursorZ, this->drawCursor); EnOssan_DrawStickDirectionPrompts(play, this); diff --git a/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c b/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c index 7ce6cc8df..6969084bb 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c +++ b/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c @@ -7,6 +7,7 @@ #include "z_en_po_relay.h" #include "overlays/actors/ovl_En_Honotrap/z_en_honotrap.h" #include "objects/object_tk/object_tk.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_IGNORE_QUAKE | ACTOR_FLAG_WILL_TALK) @@ -426,6 +427,20 @@ void EnPoRelay_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* gSPDisplayList(POLY_OPA_DISP++, gDampeHaloDL); CLOSE_DISPS(play->state.gfxCtx); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 16) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(10627, 3321, -13727, MTXMODE_APPLY); + Matrix_Translate(418.919f, 40.54f, -256.757f, MTXMODE_APPLY); + Matrix_Scale(1.068f, 1.068f, 1.068f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnPoRelay_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c b/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c index e099480b5..90e8724ad 100644 --- a/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c +++ b/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c @@ -3,6 +3,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE) @@ -304,6 +305,20 @@ void EnShopnuts_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* gSPDisplayList(POLY_OPA_DISP++, gBusinessScrubNoseDL); CLOSE_DISPS(play->state.gfxCtx); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 17) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, 17490, MTXMODE_APPLY); + Matrix_Translate(4200.0f, -472.973f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(4.932f, 4.932f, 4.932f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnShopnuts_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 338dfaf12..8f64213cb 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -149,6 +149,13 @@ void func_80AFB950(EnSi* this, PlayState* play) { void EnSi_Update(Actor* thisx, PlayState* play) { EnSi* this = (EnSi*)thisx; + // #region SOH [Co-op] + if (GET_GS_FLAGS((thisx->params & 0x1F00) >> 8) & (thisx->params & 0xFF)) { + Actor_Kill(&this->actor); + return; + } + // #endregion + Actor_MoveXZGravity(&this->actor); Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, 4); this->actionFunc(this, play); diff --git a/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c b/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c index 1fcb2708a..8f294d739 100644 --- a/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c +++ b/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c @@ -2,6 +2,7 @@ #include "overlays/actors/ovl_En_Encount1/z_en_encount1.h" #include "objects/object_skb/object_skb.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -552,6 +553,21 @@ void EnSkb_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, } else if ((this->unk_283 ^ (this->unk_283 | 4)) == 0) { BodyBreak_SetInfo(&this->bodyBreak, limbIndex, 0, 18, 18, dList, BODYBREAK_OBJECT_DEFAULT); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 11) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, -2215, MTXMODE_APPLY); + Matrix_Translate(1324.324f, 662.162f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnSkb_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Snowball/z_en_snowball.c b/soh/src/overlays/actors/ovl_En_Snowball/z_en_snowball.c new file mode 100644 index 000000000..1a2b9841e --- /dev/null +++ b/soh/src/overlays/actors/ovl_En_Snowball/z_en_snowball.c @@ -0,0 +1,229 @@ +/* + * File: z_en_snowball.c + * Overlay: ovl_En_Snowball + * Description: Rollable Snowball + */ + +#include "z_en_snowball.h" +#include "objects/gameplay_keep/gameplay_keep.h" +#include "objects/object_goroiwa/object_goroiwa.h" +#include "soh_assets.h" + +#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED + +void EnSnowball_Init(Actor* thisx, PlayState* play); +void EnSnowball_Destroy(Actor* thisx, PlayState* play); +void EnSnowball_Update(Actor* thisx, PlayState* play); +void EnSnowball_Draw(Actor* thisx, PlayState* play); + +static ColliderJntSphElementInit sJntSphElementsInit[] = { + { + { + ELEMTYPE_UNK0, + { 0x20000000, 0x00, 0x04 }, + { 0x00000000, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, + { 0, { { 0, 0, 0 }, 14 }, 100 }, + }, +}; + +static ColliderJntSphInit sJntSphInit = { + { + COLTYPE_NONE, + AT_ON | AT_TYPE_ENEMY, + AC_NONE, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_2, + COLSHAPE_JNTSPH, + }, + 1, + sJntSphElementsInit, +}; + +static CollisionCheckInfoInit sColChkInfoInit = { 0, 3, 15, MASS_HEAVY }; + +void EnSnowball_UpdateCollider(EnSnowball* this) { + Sphere16* worldSphere = &this->collider.elements[0].dim.worldSphere; + + worldSphere->center.x = this->actor.world.pos.x; + worldSphere->center.y = this->actor.world.pos.y + (this->actor.scale.x * 500.0f); + worldSphere->center.z = this->actor.world.pos.z; + worldSphere->radius = (this->actor.scale.x * 500.0f); +} + +void EnSnowball_InitCollider(EnSnowball* this, PlayState* play) { + Collider_InitJntSph(play, &this->collider); + Collider_SetJntSph(play, &this->collider, &this->actor, &sJntSphInit, this->colliderItems); + EnSnowball_UpdateCollider(this); + this->collider.elements[0].dim.worldSphere.radius = (this->actor.scale.x * 500.0f); +} + +static InitChainEntry sInitChain[] = { + ICHAIN_F32_DIV1000(gravity, -860, ICHAIN_CONTINUE), ICHAIN_F32_DIV1000(minVelocityY, -15000, ICHAIN_CONTINUE), + ICHAIN_VEC3F_DIV1000(scale, 5, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneForward, 1500, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneScale, 150, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 1500, ICHAIN_STOP), +}; + +void EnSnowball_Init(Actor* thisx, PlayState* play) { + EnSnowball* this = (EnSnowball*)thisx; + + Actor_ProcessInitChain(&this->actor, sInitChain); + EnSnowball_InitCollider(this, play); + CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit); + ActorShape_Init(&this->actor.shape, 595.0f, ActorShadow_DrawCircle, 9.4f); + this->actor.shape.shadowAlpha = 200; + + if (thisx->params == 1) { + this->actor.speedXZ += 5.0f; + this->actor.world.rot.y = Rand_ZeroFloat(65536.0f); + } +} + +void EnSnowball_Destroy(Actor* thisx, PlayState* play) { + EnSnowball* this = (EnSnowball*)thisx; + + Collider_DestroyJntSph(play, &this->collider); +} + +void EnSnowball_Update(Actor* thisx, PlayState* play) { + EnSnowball* this = (EnSnowball*)thisx; + Actor* player = GET_PLAYER(play); + + // Kill the actor if it falls too far + if (thisx->world.pos.y < -10000.0f) { + Actor_Kill(thisx); + return; + } + + u8 meanBoulder = thisx->params == 1 && this->actor.scale.x > 0.1f; + + // Check if the player is close enough to start rolling + if (this->actor.xzDistToPlayer < MAX(20.0f, this->actor.scale.x * 600.0f) && !meanBoulder) { + /// Flip the actor's rotation away from the player + thisx->world.rot.y = thisx->yawTowardsPlayer + 0x8000; + this->actor.speedXZ = MAX(5.0f, this->actor.speedXZ); + } + + if (this->collider.base.atFlags & AT_HIT) { + this->collider.base.atFlags &= ~AT_HIT; + // Flip the actor's rotation away from the player + thisx->world.rot.y = thisx->yawTowardsPlayer + 0x8000; + + func_8002F6D4(play, &this->actor, 2.0f, this->actor.yawTowardsPlayer, 0.0f, 0); + Player_PlaySfx(&GET_PLAYER(play)->actor, NA_SE_PL_BODY_HIT); + } + + // Slow down the actor and increase it's scale + if (this->actor.speedXZ > 0.0f) { + CollisionPoly snowballPoly; + u8 goingUp = this->actor.world.pos.y - this->prevY > 0.001f; + u8 goingDown = this->actor.world.pos.y - this->prevY < -0.001f; + + // friction + if (thisx->params != 1) { + this->actor.speedXZ -= 0.1f; + } + + if (goingDown) { + // Increase the speed if going down hill + f32 speed = (this->prevY - this->actor.world.pos.y) * 0.15f; + this->actor.speedXZ += MIN(speed, 0.5f); + } else if (goingUp) { + // Reduce the speed if going up hill + this->actor.speedXZ -= (this->actor.world.pos.y - this->prevY) * 0.1f; + } + + if (goingUp || goingDown) { + // Check if going straight, one degree right, or one degree left will result in steeper slope + // Check straight + Vec3f snowballPos = this->actor.world.pos; + snowballPos.y += 100.0f; + snowballPos.x += Math_SinS(this->actor.world.rot.y) * 1.0f; + snowballPos.z += Math_CosS(this->actor.world.rot.y) * 1.0f; + float straightSlope = BgCheck_AnyRaycastFloor1(&gPlayState->colCtx, &snowballPoly, &snowballPos); + + // Check one degree right + snowballPos = this->actor.world.pos; + snowballPos.y += 100.0f; + snowballPos.x += Math_SinS(this->actor.world.rot.y + 0x100) * 1.0f; + snowballPos.z += Math_CosS(this->actor.world.rot.y + 0x100) * 1.0f; + float rightSlope = BgCheck_AnyRaycastFloor1(&gPlayState->colCtx, &snowballPoly, &snowballPos); + + // Check one degree left + snowballPos = this->actor.world.pos; + snowballPos.y += 100.0f; + snowballPos.x += Math_SinS(this->actor.world.rot.y - 0x100) * 1.0f; + snowballPos.z += Math_CosS(this->actor.world.rot.y - 0x100) * 1.0f; + float leftSlope = BgCheck_AnyRaycastFloor1(&gPlayState->colCtx, &snowballPoly, &snowballPos); + + if (straightSlope > rightSlope || straightSlope > leftSlope) { + if (rightSlope < leftSlope) { + this->actor.world.rot.y += 0x100; + } else { + this->actor.world.rot.y -= 0x100; + } + } + } + + // Check if the actor is colliding with a wall and bounce off + if (thisx->bgCheckFlags & 8) { + if (ABS((s16)(thisx->wallYaw - thisx->world.rot.y)) > 0x4000) { + thisx->world.rot.y = ((thisx->wallYaw - thisx->world.rot.y) + thisx->wallYaw) - 0x8000; + } + if (thisx->params != 1) { + thisx->speedXZ *= 0.7f; + } + thisx->bgCheckFlags &= ~8; + if (this->actor.speedXZ > 5.0f) { + Audio_PlayActorSound2(thisx, NA_SE_EV_BOMB_BOUND); + } + } + + Actor_SetScale(&this->actor, MIN(0.15f, this->actor.scale.x + (this->actor.speedXZ * 0.00001f))); + } + + if (this->actor.speedXZ < 0.0f) { + this->actor.speedXZ = 0.0f; + } + + // Based on speed and scale, rotate the snowball + // The larger the snowball, the slower it rotates + this->sRot += (this->actor.speedXZ * 15.0f) / this->actor.scale.x; + + // record the actor's position + this->prevY = this->actor.world.pos.y; + + // Process movement (moves foward based on speed and rotation) + Actor_MoveXZGravity(thisx); + + // Prevent actor from going through the ground or walls + Actor_UpdateBgCheckInfo(play, &this->actor, MAX(10.0f, this->actor.scale.x * 250.0f), MAX(10.0f, this->actor.scale.x * 500.0f), 0.0f, 0xFF); + + EnSnowball_UpdateCollider(this); + // Add collision checks if the actor is a mean boulder + if (meanBoulder) { + CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); + CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); + } +} + +void EnSnowball_Draw(Actor* thisx, PlayState* play) { + EnSnowball* this = (EnSnowball*)thisx; + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + Matrix_RotateZYX(this->sRot, thisx->world.rot.y, 0, MTXMODE_APPLY); + + Matrix_Translate(0.0f, 5.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.5f, 0.5f, 0.5f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(POLY_OPA_DISP++, gSnowballDL); + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/soh/src/overlays/actors/ovl_En_Snowball/z_en_snowball.h b/soh/src/overlays/actors/ovl_En_Snowball/z_en_snowball.h new file mode 100644 index 000000000..fa8c0779c --- /dev/null +++ b/soh/src/overlays/actors/ovl_En_Snowball/z_en_snowball.h @@ -0,0 +1,31 @@ +#ifndef Z_EN_SNOWBALL_H +#define Z_EN_SNOWBALL_H + +#include +#include "global.h" + +struct EnSnowball; + +typedef void (*EnSnowballActionFunc)(struct EnSnowball*, PlayState*); + +typedef struct EnSnowball { + Actor actor; + + ColliderJntSph collider; + ColliderJntSphElement colliderItems[1]; + s16 sRot; + f32 prevY; +} EnSnowball; + +#ifdef __cplusplus +extern "C" { +#endif +void EnSnowball_Init(Actor* thisx, PlayState* play); +void EnSnowball_Destroy(Actor* thisx, PlayState* play); +void EnSnowball_Update(Actor* thisx, PlayState* play); +void EnSnowball_Draw(Actor* thisx, PlayState* play); +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c index cc3dd3eb0..b040db901 100644 --- a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c +++ b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c @@ -10,6 +10,7 @@ #include "objects/object_boj/object_boj.h" #include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" @@ -401,6 +402,21 @@ void EnSth_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, CLOSE_DISPS(play->state.gfxCtx); } } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-4207, -665, -4650, MTXMODE_APPLY); + Matrix_Translate(932.432f, 162.163f, 81.082f, MTXMODE_APPLY); + Matrix_Scale(0.73f, 0.73f, 0.73f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } Gfx* EnSth_AllocColorDList(GraphicsContext* play, u8 envR, u8 envG, u8 envB, u8 envA) { diff --git a/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c b/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c index 93dd9c9d3..98da453f3 100644 --- a/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c +++ b/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c @@ -916,6 +916,13 @@ void func_80B0E9BC(EnSw* this, PlayState* play) { void EnSw_Update(Actor* thisx, PlayState* play) { EnSw* this = (EnSw*)thisx; + // #region SOH [Co-op] + if (GET_GS_FLAGS((thisx->params & 0x1F00) >> 8) & (thisx->params & 0xFF)) { + Actor_Kill(&this->actor); + return; + } + // #endregion + SkelAnime_Update(&this->skelAnime); func_80B0C9F0(this, play); this->actionFunc(this, play); diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index 60955727b..39c251ac3 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -7,6 +7,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_LOCKON) @@ -514,12 +515,33 @@ s32 EnSyatekiMan_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, V return 0; } +s32 EnSyatekiMan_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + EnSyatekiMan* this = (EnSyatekiMan*)thisx; + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 8) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(2214, 3985, -7750, MTXMODE_APPLY); + Matrix_Translate(1094.594f, 1162.162f, -40.541f, MTXMODE_APPLY); + Matrix_Scale(0.864f, 0.864f, 0.864f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 255, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } + + return false; +} + void EnSyatekiMan_Draw(Actor* thisx, PlayState* play) { s32 pad; EnSyatekiMan* this = (EnSyatekiMan*)thisx; Gfx_SetupDL_25Opa(play->state.gfxCtx); - SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnSyatekiMan_OverrideLimbDraw, NULL, this); + SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnSyatekiMan_OverrideLimbDraw, EnSyatekiMan_PostLimbDraw, this); } void EnSyatekiMan_SetBgm(void) { diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index 1e923335b..66e04437c 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -10,6 +10,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -1215,6 +1216,20 @@ void EnTa_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, if (limbIndex == 15) { Matrix_MultVec3f(&D_80B16E7C, &this->actor.focus.pos); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(11955, -1993, 221, MTXMODE_APPLY); + Matrix_Translate(1081.081f, -108.108f, -270.270f, MTXMODE_APPLY); + Matrix_Scale(1.554f, 1.554f, 1.554f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnTa_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Test/z_en_test.c b/soh/src/overlays/actors/ovl_En_Test/z_en_test.c index 5accba57a..3574f3d00 100644 --- a/soh/src/overlays/actors/ovl_En_Test/z_en_test.c +++ b/soh/src/overlays/actors/ovl_En_Test/z_en_test.c @@ -7,8 +7,11 @@ #include "z_en_test.h" #include "objects/object_sk2/object_sk2.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED) void EnTest_Init(Actor* thisx, PlayState* play); @@ -1844,6 +1847,10 @@ s32 EnTest_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* *dList = NULL; } + if (limbIndex == STALFOS_LIMB_SWORD || limbIndex == STALFOS_LIMB_SHIELD) { + SkipOverrideNextLimb(); + } + return false; } @@ -1950,6 +1957,20 @@ void EnTest_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot this->bodyPartsPos[bodyPart].z = sp50.z; } } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 11) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-10849, 0, -5314, MTXMODE_APPLY); + Matrix_Translate(513.514f, 283.784f, 554.054f, MTXMODE_APPLY); + Matrix_Scale(1.203f, 1.203f, 1.203f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnTest_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Tg/z_en_tg.c b/soh/src/overlays/actors/ovl_En_Tg/z_en_tg.c index 247db92f3..12f7fa189 100644 --- a/soh/src/overlays/actors/ovl_En_Tg/z_en_tg.c +++ b/soh/src/overlays/actors/ovl_En_Tg/z_en_tg.c @@ -6,6 +6,7 @@ #include "z_en_tg.h" #include "objects/object_mu/object_mu.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -168,6 +169,34 @@ void EnTg_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, // Place the target point at the guy's head instead of the center of the actor Matrix_MultVec3f(&targetOffset, &this->actor.focus.pos); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 20) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-2657, -1550, 1549, MTXMODE_APPLY); + Matrix_Translate(594.594f, -135.135f, -54.054f, MTXMODE_APPLY); + Matrix_Scale(0.966f, 0.966f, 0.966f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + + if (limbIndex == 9) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-3100, 1992, 2435, MTXMODE_APPLY); + Matrix_Translate(864.865f, -121.622f, 175.676f, MTXMODE_APPLY); + Matrix_Scale(0.865f, 0.865f, 0.865f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 255, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } Gfx* EnTg_SetColor(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b, u8 a) { diff --git a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c index e9535c3b5..850cc2bcb 100644 --- a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c +++ b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c @@ -10,6 +10,7 @@ #include "soh/frame_interpolation.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -723,6 +724,20 @@ void EnTk_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Matrix_MultVec3f(&sp28, &this->v3f_304); func_80B1D200(play); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 16) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(10627, 3321, -13727, MTXMODE_APPLY); + Matrix_Translate(418.919f, 40.54f, -256.757f, MTXMODE_APPLY); + Matrix_Scale(1.068f, 1.068f, 1.068f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnTk_Draw(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c b/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c index 28bc936c5..4186534c1 100644 --- a/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c +++ b/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c @@ -8,6 +8,8 @@ #include "objects/object_torch2/object_torch2.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) typedef enum { @@ -772,6 +774,10 @@ s32 EnTorch2_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f Gfx** gfx) { Player* this = (Player*)thisx; + if (limbIndex == PLAYER_LIMB_L_HAND || limbIndex == PLAYER_LIMB_R_HAND) { + SkipOverrideNextLimb(); + } + return Player_OverrideLimbDrawGameplayCommon(play, limbIndex, dList, pos, rot, &this->actor); } diff --git a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c index f0abb973f..356eb4462 100644 --- a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c +++ b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c @@ -10,6 +10,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -108,6 +109,11 @@ void EnToryo_Init(Actor* thisx, PlayState* play) { break; case SCENE_KAKARIKO_VILLAGE: if ((LINK_AGE_IN_YEARS == YEARS_CHILD) && IS_DAY) { + this->actor.world.pos.x = 756.0; + this->actor.world.pos.y = 80.0; + this->actor.world.pos.z = 1378.0; + this->actor.shape.rot.y = 32534; + this->stateFlags |= 2; } break; @@ -418,4 +424,18 @@ void EnToryo_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* ro Matrix_MultVec3f(&sMultVec, &this->actor.focus.pos); break; } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 15) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(-23691, 664, -2879, MTXMODE_APPLY); + Matrix_Translate(810.811f, -243.243f, 270.27f, MTXMODE_APPLY); + Matrix_Scale(1.216f, 1.216f, 1.216f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } diff --git a/soh/src/overlays/actors/ovl_En_Vm/z_en_vm.c b/soh/src/overlays/actors/ovl_En_Vm/z_en_vm.c index 2f6241ef8..dd05c5b7e 100644 --- a/soh/src/overlays/actors/ovl_En_Vm/z_en_vm.c +++ b/soh/src/overlays/actors/ovl_En_Vm/z_en_vm.c @@ -9,8 +9,11 @@ #include "overlays/actors/ovl_En_Bom/z_en_bom.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED) void EnVm_Init(Actor* thisx, PlayState* play); @@ -518,6 +521,20 @@ void EnVm_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, &this->colliderQuad2.dim.quad[1], &this->colliderQuad2.dim.quad[2], &this->colliderQuad2.dim.quad[3]); } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 6) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(19704, -1329, 11734, MTXMODE_APPLY); + Matrix_Translate(310.811f, -108.108f, -81.081f, MTXMODE_APPLY); + Matrix_Scale(2.297f, 2.297f, 2.297f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSantaHatGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } void EnVm_Draw(Actor* thisx, PlayState* play2) { @@ -529,6 +546,7 @@ void EnVm_Draw(Actor* thisx, PlayState* play2) { Gfx_SetupDL_25Opa(play->state.gfxCtx); Gfx_SetupDL_25Xlu(play->state.gfxCtx); + SkipOverrideNextSkeleton(); SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnVm_OverrideLimbDraw, EnVm_PostLimbDraw, this); actorPos = this->actor.world.pos; diff --git a/soh/src/overlays/actors/ovl_En_Weather_Tag/z_en_weather_tag.c b/soh/src/overlays/actors/ovl_En_Weather_Tag/z_en_weather_tag.c index f8b1cfd10..d57a1833b 100644 --- a/soh/src/overlays/actors/ovl_En_Weather_Tag/z_en_weather_tag.c +++ b/soh/src/overlays/actors/ovl_En_Weather_Tag/z_en_weather_tag.c @@ -134,6 +134,10 @@ u8 WeatherTag_CheckEnableWeatherEffect(EnWeatherTag* this, PlayState* play, u8 a u8 ret = false; Player* player = GET_PLAYER(play); + if (LINK_IS_ADULT && gPlayState != NULL && gPlayState->sceneNum == SCENE_KAKARIKO_VILLAGE) { + return ret; + } + if (Actor_WorldDistXZToActor(&player->actor, &this->actor) < WEATHER_TAG_RANGE100(this->actor.params)) { if ((play->envCtx.indoors != 0) || !gSkyboxBlendingEnabled || (play->skyboxId != SKYBOX_NORMAL_SKY && play->envCtx.unk_1F == play->envCtx.unk_20)) { diff --git a/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c b/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c index 91a23dc79..48ba93452 100644 --- a/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c +++ b/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c @@ -9,6 +9,7 @@ #include "overlays/actors/ovl_En_Encount1/z_en_encount1.h" #include "objects/object_wf/object_wf.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -1427,6 +1428,21 @@ void EnWf_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, this->bodyPartsPos[bodyPartIndex].z = bodyPartPos.z; } } + + if (CVarGetInteger("gLetItSnow", 0)) { + if (limbIndex == 17) { + OPEN_DISPS(play->state.gfxCtx); + Matrix_Push(); + Matrix_RotateZYX(0, 0, -18377, MTXMODE_APPLY); + Matrix_Translate(729.73f, 1243.243f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(0.743f, 0.743f, 0.743f, MTXMODE_APPLY); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 0, 0, 255); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gPaperCrownGenericDL); + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); + } + } } static void* sWolfosNormalEyeTextures[] = { gWolfosNormalEyeOpenTex, gWolfosNormalEyeHalfTex, gWolfosNormalEyeNarrowTex, diff --git a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c index 0988f0a66..a185540ab 100644 --- a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c +++ b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c @@ -6,6 +6,7 @@ #include "z_en_wood02.h" #include "objects/object_wood02/object_wood02.h" +#include "soh/Enhancements/Holiday/Fredomato.h" #define FLAGS 0 @@ -179,6 +180,16 @@ void EnWood02_Init(Actor* thisx, PlayState* play2) { f32 floorY; s16 extraRot; + if (gPlayState->sceneNum == SCENE_KAKARIKO_VILLAGE && this->actor.params <= WOOD_TREE_KAKARIKO_ADULT) { + Actor_Kill(this); + } + + if (gPlayState->sceneNum == SCENE_KAKARIKO_VILLAGE && this->actor.params >= 0) { + this->actor.world.pos.x = 754.051; + this->actor.world.pos.y = 80.0; + this->actor.world.pos.z = 1429.908; + } + // The tree in Kakariko's day scene does not have the same params to spawn the GS // as the night scene, For the always spawn GS enhancement we apply the needed // params to have the GS drop when bonking @@ -358,7 +369,9 @@ void EnWood02_Update(Actor* thisx, PlayState* play2) { dropsSpawnPt = this->actor.world.pos; dropsSpawnPt.y += 200.0f; - if ((this->unk_14C >= 0) && (this->unk_14C < 0x64) && (CVarGetInteger(CVAR_ENHANCEMENT("TreesDropSticks"), 0)) && !(INV_CONTENT(ITEM_STICK) == ITEM_NONE)) { + if (HandleTreeBonk(&this->actor)) { + // no-op + } else if ((this->unk_14C >= 0) && (this->unk_14C < 0x64) && (CVarGetInteger(CVAR_ENHANCEMENT("TreesDropSticks"), 0)) && !(INV_CONTENT(ITEM_STICK) == ITEM_NONE)) { (numDrops = (Rand_ZeroOne() * 4)); for (i = 0; i < numDrops; ++i) { Item_DropCollectible(play, &dropsSpawnPt, ITEM00_STICK); @@ -452,14 +465,14 @@ void EnWood02_Draw(Actor* thisx, PlayState* play) { if ((type == WOOD_TREE_OVAL_GREEN_SPAWNER) || (type == WOOD_TREE_OVAL_GREEN_SPAWNED) || (type == WOOD_TREE_OVAL_GREEN) || (type == WOOD_LEAF_GREEN)) { - red = 50; - green = 170; - blue = 70; + red = 255; + green = 255; + blue = 255; } else if ((type == WOOD_TREE_OVAL_YELLOW_SPAWNER) || (type == WOOD_TREE_OVAL_YELLOW_SPAWNED) || (type == WOOD_LEAF_YELLOW)) { - red = 180; - green = 155; - blue = 0; + red = 255; + green = 255; + blue = 255; } else { red = green = blue = 255; } diff --git a/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c b/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c index 85a878cc6..d09142c68 100644 --- a/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c +++ b/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c @@ -7,8 +7,11 @@ #include "z_en_zf.h" #include "objects/object_zf/object_zf.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh_assets.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/Holiday/Archez.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED) void EnZf_Init(Actor* thisx, PlayState* play); @@ -2131,11 +2134,13 @@ s32 EnZf_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* po rot->y -= this->headRot; break; case ENZF_LIMB_SWORD: + SkipOverrideNextLimb(); if (this->swordSheathed) { *dList = gZfEmptyHandDL; } break; case ENZF_LIMB_SCABBARD: + SkipOverrideNextLimb(); if (this->swordSheathed) { *dList = gZfSheathedSwordDL; } @@ -2433,4 +2438,4 @@ s32 EnZf_DodgeRangedWaiting(PlayState* play, EnZf* this) { void EnZf_Reset(void) { D_80B4A1B0 = 0; D_80B4A1B4 = 1; -} \ No newline at end of file +} diff --git a/soh/src/overlays/actors/ovl_End_Title/z_end_title.c b/soh/src/overlays/actors/ovl_End_Title/z_end_title.c index 3e83e5ae3..e644bdba4 100644 --- a/soh/src/overlays/actors/ovl_End_Title/z_end_title.c +++ b/soh/src/overlays/actors/ovl_End_Title/z_end_title.c @@ -72,42 +72,78 @@ void EndTitle_DrawFull(Actor* thisx, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); + uint8_t isKak = play->sceneNum == SCENE_KAKARIKO_VILLAGE; + // Draw title cards on the screen - if ((frameCount > 890) && (this->endAlpha < 200)) { + if ((frameCount > 890 || isKak) && (this->endAlpha < 200)) { this->endAlpha += 7; } - if ((frameCount > 810) && (this->tlozAlpha < 200)) { + if ((frameCount > 810 || isKak) && (this->tlozAlpha < 200)) { this->tlozAlpha += 15; } - if ((frameCount > 850) && (this->ootAlpha < 200)) { + if ((frameCount > 850 || isKak) && (this->ootAlpha < 200)) { this->ootAlpha += 15; } - + OVERLAY_DISP = Gfx_SetupDL_64(OVERLAY_DISP); - gDPSetTextureLUT(OVERLAY_DISP++, G_TT_NONE); - gDPSetEnvColor(OVERLAY_DISP++, 255, 120, 30, 0); - gDPSetRenderMode(OVERLAY_DISP++, G_RM_PASS, G_RM_XLU_SURF2); - gSPClearGeometryMode(OVERLAY_DISP++, - G_TEXTURE_ENABLE | G_CULL_BACK | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR); - gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, - COMBINED, 0, 0, 0, COMBINED); - gDPSetPrimColor(OVERLAY_DISP++, 0x00, 0x80, 0, 0, 0, this->endAlpha); - gDPLoadTextureTile(OVERLAY_DISP++, sTheEndTex, G_IM_FMT_IA, G_IM_SIZ_8b, 80, 24, 0, 0, 80 - 1, 24 - 1, 0, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 0, 0, 0, 0); - gSPTextureRectangle(OVERLAY_DISP++, 120 << 2, 90 << 2, 200 << 2, 113 << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); - gDPPipeSync(OVERLAY_DISP++); - gDPSetPrimColor(OVERLAY_DISP++, 0x00, 0x80, 0, 0, 0, this->tlozAlpha); - gDPLoadTextureTile(OVERLAY_DISP++, sTheLegendOfZeldaTex, G_IM_FMT_IA, G_IM_SIZ_8b, 120, 24, 0, 0, 120 - 1, 24 - 1, 0, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 0, 0, 0, 0); - gSPTextureRectangle(OVERLAY_DISP++, 100 << 2, 160 << 2, 220 << 2, 183 << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, - 1 << 10); - gDPPipeSync(OVERLAY_DISP++); - gDPSetPrimColor(OVERLAY_DISP++, 0x00, 0x80, 0, 0, 0, this->ootAlpha); - gDPLoadTextureTile(OVERLAY_DISP++, sOcarinaOfTimeTex, G_IM_FMT_IA, G_IM_SIZ_8b, 112, 16, 0, - 0, 112 - 1, 16 - 1, 0, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 0, 0, 0, 0); - gSPTextureRectangle(OVERLAY_DISP++, 104 << 2, 177 << 2, 216 << 2, 192 << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, - 1 << 10); + + if (this->actor.params == 2) { + gSPGrayscale(OVERLAY_DISP++, false); + gDPSetTextureLUT(OVERLAY_DISP++, G_TT_NONE); + gDPSetEnvColor(OVERLAY_DISP++, 0, 255, 0, 0); + gDPSetRenderMode(OVERLAY_DISP++, G_RM_PASS, G_RM_XLU_SURF2); + gSPClearGeometryMode(OVERLAY_DISP++, G_TEXTURE_ENABLE | G_CULL_BACK | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR); + gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, COMBINED, 0, 0, 0, COMBINED); + gDPSetPrimColor(OVERLAY_DISP++, 0x00, 0x80, 0, 0, 0, this->endAlpha); + gDPLoadTextureTile(OVERLAY_DISP++, sTheEndTex, G_IM_FMT_IA, G_IM_SIZ_8b, 80, 24, 0, 0, 80 - 1, 24 - 1, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 0, 0, 0, 0); + gSPTextureRectangle(OVERLAY_DISP++, 120 << 2, 90 << 2, 200 << 2, 113 << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + gDPPipeSync(OVERLAY_DISP++); + gDPSetPrimColor(OVERLAY_DISP++, 0x00, 0x80, 0, 0, 0, this->tlozAlpha); + gDPLoadTextureTile(OVERLAY_DISP++, sTheLegendOfZeldaTex, G_IM_FMT_IA, G_IM_SIZ_8b, 120, 24, 0, 0, 120 - 1, 24 - 1, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 0, 0, 0, 0); + gSPTextureRectangle(OVERLAY_DISP++, 100 << 2, 160 << 2, 220 << 2, 183 << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + gDPPipeSync(OVERLAY_DISP++); + gDPSetPrimColor(OVERLAY_DISP++, 0x00, 0x80, 0, 0, 0, this->ootAlpha); + gDPLoadTextureTile(OVERLAY_DISP++, sOcarinaOfTimeTex, G_IM_FMT_IA, G_IM_SIZ_8b, 112, 16, 0, 0, 112 - 1, 16 - 1, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 0, 0, 0, 0); + gSPTextureRectangle(OVERLAY_DISP++, 104 << 2, 177 << 2, 216 << 2, 192 << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + + gVisMonoColor.a = 0; + //gVisMonoColor.r = 205; + //gVisMonoColor.g = 168; + //gVisMonoColor.b = 130; + + //gSPGrayscale(OVERLAY_DISP++, true); + } else { + if (gVisMonoColor.a > 0) + + gSPGrayscale(OVERLAY_DISP++, false); + gDPSetTextureLUT(OVERLAY_DISP++, G_TT_NONE); + gDPSetEnvColor(OVERLAY_DISP++, 255, 120, 30, 0); + gDPSetRenderMode(OVERLAY_DISP++, G_RM_PASS, G_RM_XLU_SURF2); + gSPClearGeometryMode(OVERLAY_DISP++, G_TEXTURE_ENABLE | G_CULL_BACK | G_FOG | G_LIGHTING | G_TEXTURE_GEN | + G_TEXTURE_GEN_LINEAR); + gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, + COMBINED, 0, 0, 0, COMBINED); + gDPSetPrimColor(OVERLAY_DISP++, 0x00, 0x80, 0, 0, 0, this->endAlpha); + gDPLoadTextureTile(OVERLAY_DISP++, sTheEndTex, G_IM_FMT_IA, G_IM_SIZ_8b, 80, 24, 0, 0, 80 - 1, 24 - 1, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 0, 0, 0, 0); + gSPTextureRectangle(OVERLAY_DISP++, 120 << 2, 90 << 2, 200 << 2, 113 << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, + 1 << 10); + gDPPipeSync(OVERLAY_DISP++); + gDPSetPrimColor(OVERLAY_DISP++, 0x00, 0x80, 0, 0, 0, this->tlozAlpha); + gDPLoadTextureTile(OVERLAY_DISP++, sTheLegendOfZeldaTex, G_IM_FMT_IA, G_IM_SIZ_8b, 120, 24, 0, 0, 120 - 1, + 24 - 1, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 0, 0, 0, 0); + gSPTextureRectangle(OVERLAY_DISP++, 100 << 2, 160 << 2, 220 << 2, 183 << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, + 1 << 10); + gDPPipeSync(OVERLAY_DISP++); + gDPSetPrimColor(OVERLAY_DISP++, 0x00, 0x80, 0, 0, 0, this->ootAlpha); + gDPLoadTextureTile(OVERLAY_DISP++, sOcarinaOfTimeTex, G_IM_FMT_IA, G_IM_SIZ_8b, 112, 16, 0, 0, 112 - 1, 16 - 1, + 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 0, 0, 0, 0); + gSPTextureRectangle(OVERLAY_DISP++, 104 << 2, 177 << 2, 216 << 2, 192 << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, + 1 << 10); + if (gVisMonoColor.a > 0) + gSPGrayscale(OVERLAY_DISP++, true); + } + CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index 9d3c9c240..a47b63cf3 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -55,6 +55,13 @@ void ItemBHeart_Destroy(Actor* thisx, PlayState* play) { void ItemBHeart_Update(Actor* thisx, PlayState* play) { ItemBHeart* this = (ItemBHeart*)thisx; + // #region SOH [Co-op] + if (Flags_GetCollectible(play, 0x1F)) { + Actor_Kill(&this->actor); + return; + } + // #endregion + func_80B85264(this, play); Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, 4); if (Actor_HasParent(&this->actor, play)) { diff --git a/soh/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c b/soh/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c index 602236816..9ec4f10bf 100644 --- a/soh/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c +++ b/soh/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c @@ -125,8 +125,10 @@ void ObjBombiwa_Update(Actor* thisx, PlayState* play) { ObjBombiwa* this = (ObjBombiwa*)thisx; s32 pad; + // #region SOH [Co-op] if ((func_80033684(play, &this->actor) != NULL) || - ((this->collider.base.acFlags & AC_HIT) && (this->collider.info.acHitInfo->toucher.dmgFlags & 0x40000040))) { + ((this->collider.base.acFlags & AC_HIT) && (this->collider.info.acHitInfo->toucher.dmgFlags & 0x40000040)) || Flags_GetSwitch(play, this->actor.params & 0x3F)) { + // #endregion ObjBombiwa_Break(this, play); Flags_SetSwitch(play, this->actor.params & 0x3F); SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 80, NA_SE_EV_WALL_BROKEN); diff --git a/soh/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c b/soh/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c index e17cf0d80..2611f25ce 100644 --- a/soh/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c +++ b/soh/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c @@ -171,10 +171,12 @@ void ObjHamishi_Update(Actor* thisx, PlayState* play) { ObjHamishi_Shake(this); - if ((this->collider.base.acFlags & AC_HIT) && (this->collider.info.acHitInfo->toucher.dmgFlags & 0x40000040)) { + // #region SOH [Co-op] + if (((this->collider.base.acFlags & AC_HIT) && (this->collider.info.acHitInfo->toucher.dmgFlags & 0x40000040)) || Flags_GetSwitch(play, this->actor.params & 0x3F)) { this->collider.base.acFlags &= ~AC_HIT; this->hitCount++; - if (this->hitCount < 2) { + if (this->hitCount < 2 && !Flags_GetSwitch(play, this->actor.params & 0x3F)) { + // #endregion this->shakeFrames = 15; this->shakePosSize = 2.0f; this->shakeRotSize = 400.0f; diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 02f422ca0..a5a68b455 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2573,8 +2573,10 @@ void Player_ProcessItemButtons(Player* this, PlayState* play) { sHeldItemButtonIsHeldDown = true; } } else { - this->heldItemButton = i; - Player_UseItem(play, this, item); + if (GameInteractor_Should(VB_USE_ITEM, true, &item)) { + this->heldItemButton = i; + Player_UseItem(play, this, item); + } } } } @@ -6263,11 +6265,16 @@ s32 func_8083BBA0(Player* this, PlayState* play) { } void Player_SetupRoll(Player* this, PlayState* play) { + if (!GameInteractor_Should(VB_PLAYER_ROLL, true)) { + return; + } + Player_SetupAction(play, this, Player_Action_Roll, 0); LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_landing_roll, this->modelAnimType), 1.25f * sWaterSpeedFactor); gSaveContext.sohStats.count[COUNT_ROLLS]++; + GameInteractor_ExecuteOnPlayerRoll(); } s32 Player_TryRoll(Player* this, PlayState* play) { @@ -7310,6 +7317,7 @@ s32 Player_ActionHandler_2(Player* this, PlayState* play) { interactedActor->id == ACTOR_EN_ITEM00 && interactedActor->params != ITEM00_HEART_PIECE && interactedActor->params != ITEM00_SMALL_KEY && + interactedActor->params != ITEM00_NONE && interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY && interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY_GI ) || @@ -8551,6 +8559,16 @@ void Player_Action_808414F8(Player* this, PlayState* play) { } Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play); + + int32_t giSpeedModifier = GameInteractor_RunSpeedModifier(); + if (giSpeedModifier != 0) { + if (giSpeedModifier > 0) { + speedTarget *= giSpeedModifier; + } else { + speedTarget /= abs(giSpeedModifier); + } + } + sp2C = func_8083FD78(this, &speedTarget, &yawTarget, play); if (sp2C >= 0) { diff --git a/soh/src/overlays/effects/ovl_Effect_Ss_Bomb2/z_eff_ss_bomb2.c b/soh/src/overlays/effects/ovl_Effect_Ss_Bomb2/z_eff_ss_bomb2.c index 12d5c38cc..cceafe7ed 100644 --- a/soh/src/overlays/effects/ovl_Effect_Ss_Bomb2/z_eff_ss_bomb2.c +++ b/soh/src/overlays/effects/ovl_Effect_Ss_Bomb2/z_eff_ss_bomb2.c @@ -178,19 +178,19 @@ void EffectSsBomb2_Update(PlayState* play, u32 index, EffectSs* this) { divisor = this->life - 13; this->rPrimColorR = func_80027DD4(this->rPrimColorR, 255, divisor); this->rPrimColorG = func_80027DD4(this->rPrimColorG, 255, divisor); - this->rPrimColorB = func_80027DD4(this->rPrimColorB, 150, divisor); + this->rPrimColorB = func_80027DD4(this->rPrimColorB, 255, divisor); this->rPrimColorA = func_80027DD4(this->rPrimColorA, 255, divisor); - this->rEnvColorR = func_80027DD4(this->rEnvColorR, 150, divisor); - this->rEnvColorG = func_80027DD4(this->rEnvColorG, 0, divisor); - this->rEnvColorB = func_80027DD4(this->rEnvColorB, 0, divisor); + this->rEnvColorR = func_80027DD4(this->rEnvColorR, 255, divisor); + this->rEnvColorG = func_80027DD4(this->rEnvColorG, 255, divisor); + this->rEnvColorB = func_80027DD4(this->rEnvColorB, 255, divisor); } else if ((this->life < 14) && (this->life > -1)) { divisor = this->life + 1; - this->rPrimColorR = func_80027DD4(this->rPrimColorR, 50, divisor); - this->rPrimColorG = func_80027DD4(this->rPrimColorG, 50, divisor); - this->rPrimColorB = func_80027DD4(this->rPrimColorB, 50, divisor); - this->rPrimColorA = func_80027DD4(this->rPrimColorA, 150, divisor); - this->rEnvColorR = func_80027DD4(this->rEnvColorR, 10, divisor); - this->rEnvColorG = func_80027DD4(this->rEnvColorG, 10, divisor); - this->rEnvColorB = func_80027DD4(this->rEnvColorB, 10, divisor); + this->rPrimColorR = func_80027DD4(this->rPrimColorR, 255, divisor); + this->rPrimColorG = func_80027DD4(this->rPrimColorG, 255, divisor); + this->rPrimColorB = func_80027DD4(this->rPrimColorB, 255, divisor); + this->rPrimColorA = func_80027DD4(this->rPrimColorA, 255, divisor); + this->rEnvColorR = func_80027DD4(this->rEnvColorR, 255, divisor); + this->rEnvColorG = func_80027DD4(this->rEnvColorG, 255, divisor); + this->rEnvColorB = func_80027DD4(this->rEnvColorB, 255, divisor); } } diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index 23243a84c..b40291bd0 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -222,7 +222,7 @@ void Title_Draw(TitleContext* this) { } // Draw ice cube around N64 logo. - if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { + if (CVarGetInteger("gLetItSnow", 0)) { f32 scale = 0.4f; gSPSegment(POLY_OPA_DISP++, 0x08, diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 91051f5f3..3bbb81e0c 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -1137,6 +1137,21 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { } } + if (CVarGetInteger("gHoliday.lilDavid.BombArrows.Enabled", 0)) { + if (pauseCtx->equipTargetSlot == SLOT_BOW) { + CVarSetInteger("gHoliday.lilDavid.BombArrows.Active", 0); + } + u8 equipped_slot = gSaveContext.equips.cButtonSlots[pauseCtx->equipTargetCBtn]; + if (!CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0) && + pauseCtx->equipTargetItem == ITEM_BOMB && equipped_slot == SLOT_BOW) + { + CVarSetInteger("gHoliday.lilDavid.BombArrows.Active", 1); + pauseCtx->equipTargetItem = ITEM_BOW; + pauseCtx->equipTargetSlot = SLOT_BOW; + Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + } + // If the item is on another button already, swap the two uint16_t targetButtonIndex = pauseCtx->equipTargetCBtn + 1; for (uint16_t otherSlotIndex = 0; otherSlotIndex < ARRAY_COUNT(gSaveContext.equips.cButtonSlots);