mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-05-10 02:41:42 +00:00
Merge remote-tracking branch 'origin/dev'
This commit is contained in:
commit
2f72b24033
887 changed files with 37119 additions and 4821 deletions
57
.github/workflows/build-coop.yaml
vendored
57
.github/workflows/build-coop.yaml
vendored
|
|
@ -26,7 +26,7 @@ jobs:
|
|||
cd tools
|
||||
g++ -std=c++17 -o hash_file hash_file.cpp
|
||||
echo "::notice ::$(./hash_file ../build/us_pc/sm64coopdx)"
|
||||
|
||||
|
||||
- name: Zip the game
|
||||
run: |
|
||||
cd ./build/us_pc
|
||||
|
|
@ -37,7 +37,7 @@ jobs:
|
|||
with:
|
||||
name: sm64coopdx-linux
|
||||
path: ./build/us_pc/sm64coopdx_Linux.zip
|
||||
|
||||
|
||||
build-steamos:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || contains(github.event.head_commit.message, '[build]') }}
|
||||
runs-on: ubuntu-22.04
|
||||
|
|
@ -58,7 +58,7 @@ jobs:
|
|||
cd tools
|
||||
g++ -std=c++17 -o hash_file hash_file.cpp
|
||||
echo "::notice ::$(./hash_file ../build/us_pc/sm64coopdx)"
|
||||
|
||||
|
||||
- name: Zip the game
|
||||
run: |
|
||||
cd ./build/us_pc
|
||||
|
|
@ -108,7 +108,7 @@ jobs:
|
|||
cd tools
|
||||
g++ -std=c++17 -o hash_file.exe hash_file.cpp
|
||||
echo "::notice ::$(./hash_file.exe ../build/us_pc/sm64coopdx.exe)"
|
||||
|
||||
|
||||
- name: Zip the game
|
||||
run: |
|
||||
cd ./build/us_pc
|
||||
|
|
@ -158,7 +158,7 @@ jobs:
|
|||
cd tools
|
||||
g++ -std=c++17 -o hash_file.exe hash_file.cpp
|
||||
echo "::notice ::$(./hash_file.exe ../build/us_pc/sm64coopdx.exe)"
|
||||
|
||||
|
||||
- name: Zip the game
|
||||
run: |
|
||||
cd ./build/us_pc
|
||||
|
|
@ -172,17 +172,36 @@ jobs:
|
|||
|
||||
build-macos-arm:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || contains(github.event.head_commit.message, '[build]') }}
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-26
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install make mingw-w64 sdl2 pkg-config glew glfw3 coreutils
|
||||
brew install make mingw-w64 pkg-config glfw3 coreutils
|
||||
|
||||
- name: Compile glew
|
||||
run: |
|
||||
export MACOSX_DEPLOYMENT_TARGET=11
|
||||
curl -L -o glew.tar.gz https://github.com/nigels-com/glew/releases/download/glew-2.2.0/glew-2.2.0.tgz
|
||||
tar -xzf glew.tar.gz
|
||||
cd glew-2.2.0
|
||||
make SYSTEM=darwin CC="clang -arch arm64 -mmacosx-version-min=11" GLEW_PREFIX=/opt/homebrew GLEW_DEST=/opt/homebrew
|
||||
make install GLEW_PREFIX=/opt/homebrew GLEW_DEST=/opt/homebrew
|
||||
|
||||
- name: Compile SDL2
|
||||
run: |
|
||||
curl -L -o SDL2.tar.gz https://github.com/libsdl-org/SDL/releases/download/release-2.30.9/SDL2-2.30.9.tar.gz
|
||||
tar -xzf SDL2.tar.gz
|
||||
cd SDL2-2.30.9
|
||||
./configure --prefix=/opt/homebrew CC="clang -arch arm64 -mmacosx-version-min=11"
|
||||
make -j$(sysctl -n hw.ncpu)
|
||||
make install
|
||||
|
||||
- name: Build the game
|
||||
run: |
|
||||
export PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
gmake OSX_BUILD=1 -j$(sysctl -n hw.ncpu)
|
||||
|
||||
- name: Code sign the app (Ad-Hoc)
|
||||
|
|
@ -199,7 +218,7 @@ jobs:
|
|||
run: |
|
||||
cd ./build/us_pc
|
||||
zip -r sm64coopdx_macOS_ARM.zip sm64coopdx.app
|
||||
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
|
@ -215,7 +234,25 @@ jobs:
|
|||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install make mingw-w64 gcc@9 sdl2 pkg-config glew glfw3 coreutils
|
||||
brew install make mingw-w64 gcc@9 pkg-config glfw3 coreutils
|
||||
|
||||
- name: Compile glew
|
||||
run: |
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.15
|
||||
curl -L -o glew.tar.gz https://github.com/nigels-com/glew/releases/download/glew-2.2.0/glew-2.2.0.tgz
|
||||
tar -xzf glew.tar.gz
|
||||
cd glew-2.2.0
|
||||
make SYSTEM=darwin CC="clang -arch x86_64 -mmacosx-version-min=10.15"
|
||||
make install
|
||||
|
||||
- name: Compile SDL2
|
||||
run: |
|
||||
curl -L -o SDL2.tar.gz https://github.com/libsdl-org/SDL/releases/download/release-2.30.9/SDL2-2.30.9.tar.gz
|
||||
tar -xzf SDL2.tar.gz
|
||||
cd SDL2-2.30.9
|
||||
./configure --prefix=/usr/local CC="clang -arch x86_64 -mmacosx-version-min=10.15"
|
||||
make -j$(sysctl -n hw.ncpu)
|
||||
make install
|
||||
|
||||
- name: Build the game
|
||||
run: |
|
||||
|
|
@ -235,7 +272,7 @@ jobs:
|
|||
run: |
|
||||
cd ./build/us_pc
|
||||
zip -r sm64coopdx_macOS_Intel.zip sm64coopdx.app
|
||||
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
|
|
|||
31
Makefile
31
Makefile
|
|
@ -64,12 +64,7 @@ ICON ?= 1
|
|||
# Use .app (for macOS)
|
||||
USE_APP ?= 1
|
||||
# Minimum macOS Version
|
||||
# If our arch is arm, set to macOS 14
|
||||
ifeq ($(shell arch),arm64)
|
||||
MIN_MACOS_VERSION ?= 14
|
||||
else
|
||||
MIN_MACOS_VERSION ?= 10.15
|
||||
endif
|
||||
MIN_MACOS_VERSION ?= 11
|
||||
# Make some small adjustments for handheld devices
|
||||
HANDHELD ?= 0
|
||||
|
||||
|
|
@ -1575,15 +1570,15 @@ endif
|
|||
# with no prerequisites, .SECONDARY causes no intermediate target to be removed
|
||||
.SECONDARY:
|
||||
|
||||
# Handle end of macOS compilation
|
||||
APP_DIR = ./sm64coopdx.app
|
||||
APP_CONTENTS_DIR = $(APP_DIR)/Contents
|
||||
APP_MACOS_DIR = $(APP_CONTENTS_DIR)/MacOS
|
||||
APP_RESOURCES_DIR = $(APP_CONTENTS_DIR)/Resources
|
||||
|
||||
|
||||
ifeq ($(OSX_BUILD),1)
|
||||
GLEW_LIB := $(shell find $(BREW_PREFIX)/Cellar/glew | grep libGLEW.2.2.0 | sort -n | uniq)
|
||||
SDL2_LIB := $(shell find $(BREW_PREFIX)/Cellar/sdl2 | grep libSDL2- | sort -n | uniq)
|
||||
GLEW_LIB := $(shell find $(BREW_PREFIX)/lib/ | grep libGLEW.2.2.0 | sort -n | uniq)
|
||||
SDL2_LIB := $(shell find $(BREW_PREFIX)/lib/ | grep libSDL2- | sort -n | uniq)
|
||||
endif
|
||||
|
||||
all:
|
||||
|
|
@ -1605,14 +1600,20 @@ all:
|
|||
cp build/us_pc/libcoopnet.dylib $(APP_MACOS_DIR); \
|
||||
cp build/us_pc/libjuice.1.6.2.dylib $(APP_MACOS_DIR); \
|
||||
cp $(SDL2_LIB) $(APP_MACOS_DIR)/libSDL2.dylib; \
|
||||
install_name_tool -change $(BREW_PREFIX)/opt/sdl2/lib/libSDL2-2.0.0.dylib @executable_path/libSDL2.dylib $(APP_MACOS_DIR)/sm64coopdx; > /dev/null 2>&1 \
|
||||
install_name_tool -id @executable_path/libSDL2.dylib $(APP_MACOS_DIR)/libSDL2.dylib; > /dev/null 2>&1 \
|
||||
install_name_tool -change $(BREW_PREFIX)/lib/libSDL2-2.0.0.dylib @executable_path/libSDL2.dylib $(APP_MACOS_DIR)/sm64coopdx > /dev/null 2>&1; \
|
||||
install_name_tool -change $(BREW_PREFIX)/opt/sdl2/lib/libSDL2-2.0.0.dylib @executable_path/libSDL2.dylib $(APP_MACOS_DIR)/sm64coopdx > /dev/null 2>&1; \
|
||||
install_name_tool -id @executable_path/libSDL2.dylib $(APP_MACOS_DIR)/libSDL2.dylib > /dev/null 2>&1; \
|
||||
codesign --force --deep --sign - $(APP_MACOS_DIR)/libSDL2.dylib; \
|
||||
cp $(GLEW_LIB) $(APP_MACOS_DIR)/libGLEW.dylib; \
|
||||
install_name_tool -change $(BREW_PREFIX)/opt/glew/lib/libGLEW.2.2.dylib @executable_path/libGLEW.dylib $(APP_MACOS_DIR)/sm64coopdx; > /dev/null 2>&1 \
|
||||
install_name_tool -id @executable_path/libGLEW.dylib $(APP_MACOS_DIR)/libGLEW.dylib; > /dev/null 2>&1 \
|
||||
install_name_tool -change $(BREW_PREFIX)/lib/libGLEW.2.2.0.dylib @executable_path/libGLEW.dylib $(APP_MACOS_DIR)/sm64coopdx > /dev/null 2>&1; \
|
||||
install_name_tool -change $(BREW_PREFIX)/opt/glew/lib/libGLEW.2.2.0.dylib @executable_path/libGLEW.dylib $(APP_MACOS_DIR)/sm64coopdx > /dev/null 2>&1; \
|
||||
install_name_tool -id @executable_path/libGLEW.dylib $(APP_MACOS_DIR)/libGLEW.dylib > /dev/null 2>&1; \
|
||||
codesign --force --deep --sign - $(APP_MACOS_DIR)/libGLEW.dylib; \
|
||||
cp res/icon.icns $(APP_RESOURCES_DIR)/icon.icns; \
|
||||
mkdir res/build; \
|
||||
xcrun actool res/icon.icon --compile res/build --app-icon icon --output-partial-info-plist res/build/Info.plist --minimum-deployment-target $(MIN_MACOS_VERSION) --platform macosx > /dev/null 2>&1; \
|
||||
mv res/build/Assets.car $(APP_RESOURCES_DIR)/; \
|
||||
cp res/icon.icns $(APP_RESOURCES_DIR)/; \
|
||||
rm -rf res/build; \
|
||||
echo "APPL????" > $(APP_CONTENTS_DIR)/PkgInfo; \
|
||||
echo '<?xml version="1.0" encoding="UTF-8"?>' > $(APP_CONTENTS_DIR)/Info.plist; \
|
||||
echo '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' >> $(APP_CONTENTS_DIR)/Info.plist; \
|
||||
|
|
@ -1623,7 +1624,7 @@ all:
|
|||
echo ' <key>CFBundleIconFile</key>' >> $(APP_CONTENTS_DIR)/Info.plist; \
|
||||
echo ' <string>icon</string>' >> $(APP_CONTENTS_DIR)/Info.plist; \
|
||||
echo ' <key>CFBundleIconName</key>' >> $(APP_CONTENTS_DIR)/Info.plist; \
|
||||
echo ' <string>AppIcon</string>' >> $(APP_CONTENTS_DIR)/Info.plist; \
|
||||
echo ' <string>icon</string>' >> $(APP_CONTENTS_DIR)/Info.plist; \
|
||||
echo ' <key>CFBundleDisplayName</key>' >> $(APP_CONTENTS_DIR)/Info.plist; \
|
||||
echo ' <string>sm64coopdx</string>' >> $(APP_CONTENTS_DIR)/Info.plist; \
|
||||
echo ' <!-- Add other keys and values here -->' >> $(APP_CONTENTS_DIR)/Info.plist; \
|
||||
|
|
|
|||
|
|
@ -535,6 +535,8 @@ def def_constant(fname, processed_constant, skip_constant):
|
|||
continue
|
||||
if '"' in c[1]:
|
||||
s += '\n--- @type string\n'
|
||||
elif "." in c[1]:
|
||||
s += '\n--- @type number\n'
|
||||
else:
|
||||
s += '\n--- @type integer\n'
|
||||
s += '%s = %s\n' % (c[0], c[1])
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ in_files = [
|
|||
"src/audio/seqplayer.h",
|
||||
"src/engine/lighting_engine.h",
|
||||
"src/pc/network/sync_object.h",
|
||||
"src/audio/load.h",
|
||||
]
|
||||
|
||||
override_allowed_functions = {
|
||||
|
|
@ -99,6 +100,7 @@ override_allowed_functions = {
|
|||
"src/game/ingame_menu.h": [ "set_min_dialog_width", "set_dialog_override_pos", "reset_dialog_override_pos", "set_dialog_override_color", "reset_dialog_override_color", "set_menu_mode", "create_dialog_box", "create_dialog_box_with_var", "create_dialog_inverted_box", "create_dialog_box_with_response", "reset_dialog_render_state", "set_dialog_box_state", "handle_special_dialog_text" ],
|
||||
"src/audio/seqplayer.h": [ "sequence_player_set_tempo", "sequence_player_set_tempo_acc", "sequence_player_set_transposition", "sequence_player_get_tempo", "sequence_player_get_tempo_acc", "sequence_player_get_transposition", "sequence_player_get_volume", "sequence_player_get_fade_volume", "sequence_player_get_mute_volume_scale" ],
|
||||
"src/pc/network/sync_object.h": [ "sync_object_is_initialized", "sync_object_is_owned_locally", "sync_object_get_object" ],
|
||||
"src/audio/load.h": [ "set_sound_bank_override" ],
|
||||
}
|
||||
|
||||
override_disallowed_functions = {
|
||||
|
|
@ -120,14 +122,14 @@ override_disallowed_functions = {
|
|||
"src/game/sound_init.h": [ "_loop_", "thread4_", "set_sound_mode" ],
|
||||
"src/pc/network/network_utils.h": [ "network_get_player_text_color[^_]" ],
|
||||
"src/pc/network/network_player.h": [ "_init", "_connected[^_]", "_shutdown", "_disconnected", "_update", "construct_player_popup", "network_player_name_valid" ],
|
||||
"src/game/object_helpers.c": [ "spawn_obj", "^bhv_", "abs[fi]", "^bit_shift", "_debug$", "^stub_", "_set_model", "cur_obj_set_direction_table", "cur_obj_progress_direction_table" ],
|
||||
"src/game/obj_behaviors.c": [ "debug_", "turn_obj_away_from_surface" ],
|
||||
"src/game/object_helpers.c": [ "spawn_obj", "^bhv_", "geo_", "abs[fi]", "^bit_shift", "_debug$", "^stub_", "_set_model", "cur_obj_set_direction_table", "cur_obj_progress_direction_table" ],
|
||||
"src/game/obj_behaviors.c": [ "debug_", "geo_", "turn_obj_away_from_surface"],
|
||||
"src/game/obj_behaviors_2.c": [ "wiggler_jumped_on_attack_handler", "huge_goomba_weakly_attacked" ],
|
||||
"src/game/spawn_sound.h": [ "exec_anim_sound_state" ],
|
||||
"src/game/level_info.h": [ "_name_table", "convert_string_" ],
|
||||
"src/pc/lua/utils/smlua_obj_utils.h": [ "spawn_object_remember_field" ],
|
||||
"src/game/camera.h": [ "update_camera", "init_camera", "stub_camera", "^reset_camera", "move_point_along_spline", "romhack_camera_init_settings", "romhack_camera_reset_settings" ],
|
||||
"src/game/behavior_actions.h": [ "bhv_dust_smoke_loop", "bhv_init_room" ],
|
||||
"src/game/camera.h": [ "geo_", "update_camera", "init_camera", "stub_camera", "^reset_camera", "move_point_along_spline", "romhack_camera_init_settings", "romhack_camera_reset_settings" ],
|
||||
"src/game/behavior_actions.h": [ "bhv_dust_smoke_loop", "bhv_init_room", "geo_" ],
|
||||
"src/pc/lua/utils/smlua_audio_utils.h": [ "smlua_audio_utils_override", "audio_custom_shutdown", "smlua_audio_custom_deinit", "audio_sample_destroy_pending_copies", "audio_custom_update_volume" ],
|
||||
"src/pc/lua/utils/smlua_level_utils.h": [ "smlua_level_util_reset" ],
|
||||
"src/pc/lua/utils/smlua_text_utils.h": [ "smlua_text_utils_init", "smlua_text_utils_shutdown", "smlua_text_utils_dialog_get_unmodified"],
|
||||
|
|
@ -825,7 +827,7 @@ def build_param(fid, param, i):
|
|||
lot = translate_type_to_lot(ptype)
|
||||
s = ' %s %s = (%s)smlua_to_cobject(L, %d, %s);' % (ptype, pid, ptype, i, lot)
|
||||
|
||||
if '???' in lot or "GRAPHNODE" in lot:
|
||||
if '???' in lot:
|
||||
s = '//' + s + ' <--- UNIMPLEMENTED'
|
||||
else:
|
||||
s = ' ' + s
|
||||
|
|
@ -949,7 +951,7 @@ def build_function(function, do_extern):
|
|||
sparam = build_param(fid, param, i)
|
||||
param_var, param_value = sparam.split('=')
|
||||
param_type = param_var.replace(pid, '').strip()
|
||||
s += ' %s = (%s) NULL;\n' % (param_var.strip(), param_type)
|
||||
s += ' %s = (%s) %s;\n' % (param_var.strip(), param_type, "NULL" if '*' in param_type else "0")
|
||||
s += ' if (top >= %d) {\n' % (i)
|
||||
s += ' %s = %s\n' % (pid, param_value.strip())
|
||||
s += ' if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %%u for function \'%%s\'", %d, "%s"); return 0; }\n' % (i, fid)
|
||||
|
|
@ -1340,7 +1342,7 @@ def doc_function(fname, function):
|
|||
s += '- None\n'
|
||||
|
||||
s += '\n### Returns\n'
|
||||
if rtype != None:
|
||||
if len(rvalues) > 0:
|
||||
for _, ptype, plink in rvalues:
|
||||
if plink:
|
||||
s += '- [%s](%s)\n' % (ptype, plink)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ SMLUA_CALL_EVENT_HOOKS_SET_HOOK_RESULT = """
|
|||
SMLUA_CALL_EVENT_HOOKS_CALLBACK = """
|
||||
// call the callback
|
||||
if (0 != smlua_call_hook(L, {n_inputs}, {n_outputs}, 0, hook->mod[i], hook->modFile[i])) {{
|
||||
LOG_LUA("Failed to call the callback for hook %s", sLuaHookedEventTypeName[{hook_type}]);
|
||||
LOG_LUA("Failed to call the callback for hook %s - '%s/%s'", sLuaHookedEventTypeName[{hook_type}], hook->mod[i]->relativePath, hook->modFile[i]->relativePath);
|
||||
continue;
|
||||
}}{set_hook_result}
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -306,6 +306,49 @@ IN_OUT_BOUNCE = function (x) return x < 0.5 and (1 - OUT_BOUNCE(1 - 2 * x)) / 2
|
|||
---@return number
|
||||
OUT_IN_BOUNCE = function (x) return x < 0.5 and 0.5 * OUT_BOUNCE(x * 2) or 0.5 + 0.5 * IN_BOUNCE(2 * x - 1) end
|
||||
|
||||
--- @alias EasingFunction
|
||||
--- | `IN_SINE`
|
||||
--- | `OUT_SINE`
|
||||
--- | `IN_OUT_SINE`
|
||||
--- | `OUT_IN_SINE`
|
||||
--- | `IN_QUAD`
|
||||
--- | `OUT_QUAD`
|
||||
--- | `IN_OUT_QUAD`
|
||||
--- | `OUT_IN_QUAD`
|
||||
--- | `IN_CUBIC`
|
||||
--- | `OUT_CUBIC`
|
||||
--- | `IN_OUT_CUBIC`
|
||||
--- | `OUT_IN_CUBIC`
|
||||
--- | `IN_QUART`
|
||||
--- | `OUT_QUART`
|
||||
--- | `IN_OUT_QUART`
|
||||
--- | `OUT_IN_QUART`
|
||||
--- | `IN_QUINT`
|
||||
--- | `OUT_QUINT`
|
||||
--- | `IN_OUT_QUINT`
|
||||
--- | `OUT_IN_QUINT`
|
||||
--- | `IN_EXPO`
|
||||
--- | `OUT_EXPO`
|
||||
--- | `IN_OUT_EXPO`
|
||||
--- | `OUT_IN_EXPO`
|
||||
--- | `IN_CIRC`
|
||||
--- | `OUT_CIRC`
|
||||
--- | `IN_OUT_CIRC`
|
||||
--- | `OUT_IN_CIRC`
|
||||
--- | `IN_BACK`
|
||||
--- | `OUT_BACK`
|
||||
--- | `IN_OUT_BACK`
|
||||
--- | `OUT_IN_BACK`
|
||||
--- | `IN_ELASTIC`
|
||||
--- | `OUT_ELASTIC`
|
||||
--- | `IN_OUT_ELASTIC`
|
||||
--- | `OUT_IN_ELASTIC`
|
||||
--- | `IN_BOUNCE`
|
||||
--- | `OUT_BOUNCE`
|
||||
--- | `IN_OUT_BOUNCE`
|
||||
--- | `OUT_IN_BOUNCE`
|
||||
--- | fun(x: number): number
|
||||
|
||||
--------------------
|
||||
-- math functions --
|
||||
--------------------
|
||||
|
|
@ -385,7 +428,7 @@ function math.round(x)
|
|||
return x > 0 and __math_floor(x + 0.5) or __math_ceil(x - 0.5)
|
||||
end
|
||||
|
||||
--- @param t function | number
|
||||
--- @param t EasingFunction | number
|
||||
--- @param a number
|
||||
--- @param b number
|
||||
--- @param x number
|
||||
|
|
|
|||
|
|
@ -308,6 +308,49 @@ IN_OUT_BOUNCE = function (x) return x < 0.5 and (1 - OUT_BOUNCE(1 - 2 * x)) / 2
|
|||
---@return number
|
||||
OUT_IN_BOUNCE = function (x) return x < 0.5 and 0.5 * OUT_BOUNCE(x * 2) or 0.5 + 0.5 * IN_BOUNCE(2 * x - 1) end
|
||||
|
||||
--- @alias EasingFunction
|
||||
--- | `IN_SINE`
|
||||
--- | `OUT_SINE`
|
||||
--- | `IN_OUT_SINE`
|
||||
--- | `OUT_IN_SINE`
|
||||
--- | `IN_QUAD`
|
||||
--- | `OUT_QUAD`
|
||||
--- | `IN_OUT_QUAD`
|
||||
--- | `OUT_IN_QUAD`
|
||||
--- | `IN_CUBIC`
|
||||
--- | `OUT_CUBIC`
|
||||
--- | `IN_OUT_CUBIC`
|
||||
--- | `OUT_IN_CUBIC`
|
||||
--- | `IN_QUART`
|
||||
--- | `OUT_QUART`
|
||||
--- | `IN_OUT_QUART`
|
||||
--- | `OUT_IN_QUART`
|
||||
--- | `IN_QUINT`
|
||||
--- | `OUT_QUINT`
|
||||
--- | `IN_OUT_QUINT`
|
||||
--- | `OUT_IN_QUINT`
|
||||
--- | `IN_EXPO`
|
||||
--- | `OUT_EXPO`
|
||||
--- | `IN_OUT_EXPO`
|
||||
--- | `OUT_IN_EXPO`
|
||||
--- | `IN_CIRC`
|
||||
--- | `OUT_CIRC`
|
||||
--- | `IN_OUT_CIRC`
|
||||
--- | `OUT_IN_CIRC`
|
||||
--- | `IN_BACK`
|
||||
--- | `OUT_BACK`
|
||||
--- | `IN_OUT_BACK`
|
||||
--- | `OUT_IN_BACK`
|
||||
--- | `IN_ELASTIC`
|
||||
--- | `OUT_ELASTIC`
|
||||
--- | `IN_OUT_ELASTIC`
|
||||
--- | `OUT_IN_ELASTIC`
|
||||
--- | `IN_BOUNCE`
|
||||
--- | `OUT_BOUNCE`
|
||||
--- | `IN_OUT_BOUNCE`
|
||||
--- | `OUT_IN_BOUNCE`
|
||||
--- | fun(x: number): number
|
||||
|
||||
--------------------
|
||||
-- math functions --
|
||||
--------------------
|
||||
|
|
@ -387,7 +430,7 @@ function math.round(x)
|
|||
return x > 0 and __math_floor(x + 0.5) or __math_ceil(x - 0.5)
|
||||
end
|
||||
|
||||
--- @param t function | number
|
||||
--- @param t EasingFunction | number
|
||||
--- @param a number
|
||||
--- @param b number
|
||||
--- @param x number
|
||||
|
|
@ -2717,6 +2760,42 @@ CONSOLE_MESSAGE_ERROR = 2 --- @type ConsoleMessageLevel
|
|||
--- | `CONSOLE_MESSAGE_WARNING`
|
||||
--- | `CONSOLE_MESSAGE_ERROR`
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_X_LEFT = 0.0
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_X_CENTER = 0.5
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_X_RIGHT = 1.0
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_Y_TOP = 0.0
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_Y_CENTER = 0.5
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_Y_BOTTOM = 1.0
|
||||
|
||||
--- @type number
|
||||
TEXT_HALIGN_LEFT = 0.0
|
||||
|
||||
--- @type number
|
||||
TEXT_HALIGN_CENTER = 0.5
|
||||
|
||||
--- @type number
|
||||
TEXT_HALIGN_RIGHT = 1.0
|
||||
|
||||
--- @type number
|
||||
TEXT_VALIGN_TOP = 0.0
|
||||
|
||||
--- @type number
|
||||
TEXT_VALIGN_CENTER = 0.5
|
||||
|
||||
--- @type number
|
||||
TEXT_VALIGN_BOTTOM = 1.0
|
||||
|
||||
RESOLUTION_DJUI = 0 --- @type HudUtilsResolution
|
||||
RESOLUTION_N64 = 1 --- @type HudUtilsResolution
|
||||
RESOLUTION_COUNT = 2 --- @type HudUtilsResolution
|
||||
|
|
@ -2735,16 +2814,18 @@ FILTER_COUNT = 2 --- @type HudUtilsFilter
|
|||
--- | `FILTER_LINEAR`
|
||||
--- | `FILTER_COUNT`
|
||||
|
||||
FONT_NORMAL = 0 --- @type DjuiFontType
|
||||
FONT_MENU = 1 --- @type DjuiFontType
|
||||
FONT_HUD = 2 --- @type DjuiFontType
|
||||
FONT_ALIASED = 3 --- @type DjuiFontType
|
||||
FONT_CUSTOM_HUD = 4 --- @type DjuiFontType
|
||||
FONT_RECOLOR_HUD = 5 --- @type DjuiFontType
|
||||
FONT_SPECIAL = 6 --- @type DjuiFontType
|
||||
FONT_COUNT = 7 --- @type DjuiFontType
|
||||
FONT_LEGACY = -1 --- @type DjuiFontType
|
||||
FONT_NORMAL = 0 --- @type DjuiFontType
|
||||
FONT_MENU = 1 --- @type DjuiFontType
|
||||
FONT_HUD = 2 --- @type DjuiFontType
|
||||
FONT_ALIASED = 3 --- @type DjuiFontType
|
||||
FONT_CUSTOM_HUD = 4 --- @type DjuiFontType
|
||||
FONT_RECOLOR_HUD = 5 --- @type DjuiFontType
|
||||
FONT_SPECIAL = 6 --- @type DjuiFontType
|
||||
FONT_COUNT = 7 --- @type DjuiFontType
|
||||
|
||||
--- @alias DjuiFontType
|
||||
--- | `FONT_LEGACY`
|
||||
--- | `FONT_NORMAL`
|
||||
--- | `FONT_MENU`
|
||||
--- | `FONT_HUD`
|
||||
|
|
@ -3276,7 +3357,7 @@ PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT = 10
|
|||
PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE = -5
|
||||
|
||||
--- @type integer
|
||||
PVP_ATTACK_OVERRIDE_VANILLA_INVINCIBILITY = 0x0000FFFF
|
||||
PVP_ATTACK_KNOCKBACK_ACTION_ARG = 0x10000
|
||||
|
||||
--- @type integer
|
||||
INT_STATUS_ATTACK_MASK = 0x000000FF
|
||||
|
|
@ -3635,7 +3716,7 @@ HUD_DISPLAY_DEFAULT = HUD_DISPLAY_FLAG_LIVES | HUD_DISPLAY_FLAG_CO
|
|||
--- | `HUD_DISPLAY_DEFAULT`
|
||||
|
||||
--- @type integer
|
||||
LE_MAX_LIGHTS = 512
|
||||
LE_MAX_LIGHTS = 1024
|
||||
|
||||
LE_MODE_AFFECT_ALL_SHADED_AND_COLORED = 0 --- @type LEMode
|
||||
LE_MODE_AFFECT_ALL_SHADED = 1 --- @type LEMode
|
||||
|
|
@ -8191,6 +8272,9 @@ HOOK_MAX = 60 --- @type LuaHookedEventType
|
|||
--- | `HOOK_ON_PACKET_BYTESTRING_RECEIVE`
|
||||
--- | `HOOK_MAX`
|
||||
|
||||
--- @type integer
|
||||
MAX_HOOKED_BEHAVIORS = 1024
|
||||
|
||||
HUD_DISPLAY_LIVES = 0 --- @type HudDisplayValue
|
||||
HUD_DISPLAY_COINS = 1 --- @type HudDisplayValue
|
||||
HUD_DISPLAY_STARS = 2 --- @type HudDisplayValue
|
||||
|
|
|
|||
|
|
@ -3030,7 +3030,7 @@ end
|
|||
|
||||
--- @param name string
|
||||
--- @return BehaviorId
|
||||
--- gets a behavior ID from a behavior name
|
||||
--- Gets a behavior ID from a behavior name
|
||||
function get_id_from_behavior_name(name)
|
||||
-- ...
|
||||
end
|
||||
|
|
@ -3856,7 +3856,9 @@ function djui_hud_reset_color()
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @return HudUtilsRotation
|
||||
--- @return integer rotation
|
||||
--- @return number pivotX
|
||||
--- @return number pivotY
|
||||
--- Gets the current DJUI HUD rotation
|
||||
function djui_hud_get_rotation()
|
||||
-- ...
|
||||
|
|
@ -3881,6 +3883,29 @@ function djui_hud_set_rotation_interpolated(prevRotation, prevPivotX, prevPivotY
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @return number textHAlign
|
||||
--- @return number textVAlign
|
||||
--- Gets the current DJUI HUD text alignment
|
||||
function djui_hud_get_text_alignment()
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param textHAlign number
|
||||
--- @param textVAlign number
|
||||
--- Sets the current DJUI HUD text alignment
|
||||
function djui_hud_set_text_alignment(textHAlign, textVAlign)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param prevTextHAlign number
|
||||
--- @param prevTextVAlign number
|
||||
--- @param textHAlign number
|
||||
--- @param textVAlign number
|
||||
--- Sets the current DJUI HUD text alignment interpolated
|
||||
function djui_hud_set_text_alignment_interpolated(prevTextHAlign, prevTextVAlign, textHAlign, textVAlign)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @return integer
|
||||
--- Gets the screen width in the current DJUI HUD resolution
|
||||
function djui_hud_get_screen_width()
|
||||
|
|
@ -5103,6 +5128,12 @@ function le_set_ambient_color(r, g, b)
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @param count integer
|
||||
--- Sets the max amount of lights that can affect a vertex
|
||||
function le_set_max_lights_per_vertex(count)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param pos Vec3f
|
||||
--- @param out Color
|
||||
--- @param lightIntensityScalar number
|
||||
|
|
@ -5234,6 +5265,12 @@ function le_set_light_use_surface_normals(id, useSurfaceNormals)
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @param bank integer
|
||||
--- Overrides the soundbank, set to -1 to reset
|
||||
function set_sound_bank_override(bank)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param m MarioState
|
||||
--- @return integer
|
||||
--- Checks if Mario's current animation has reached its final frame (i.e., the last valid frame in the animation). Useful for deciding when to transition out of an animation-driven action
|
||||
|
|
@ -11516,6 +11553,12 @@ function get_dialog_response()
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @return integer
|
||||
--- Gets the active time stop flags, used to freeze specific objects during cutscenes
|
||||
function get_time_stop_flags()
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @return string
|
||||
--- Gets the local discord ID if it isn't disabled, otherwise "0" is returned
|
||||
function get_local_discord_id()
|
||||
|
|
@ -11622,35 +11665,42 @@ function get_os_name()
|
|||
end
|
||||
|
||||
--- @return GraphNodeRoot
|
||||
--- Gets the current GraphNodeRoot
|
||||
--- Gets the current root node being processed
|
||||
function geo_get_current_root()
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @return GraphNodeMasterList
|
||||
--- Gets the current GraphNodeMasterList
|
||||
--- Gets the current master list node being processed
|
||||
function geo_get_current_master_list()
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @return GraphNodePerspective
|
||||
--- Gets the current GraphNodePerspective
|
||||
--- Gets the current perspective node being processed
|
||||
function geo_get_current_perspective()
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @return GraphNodeCamera
|
||||
--- Gets the current GraphNodeCamera
|
||||
--- Gets the current camera node being processed
|
||||
function geo_get_current_camera()
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @return GraphNodeHeldObject
|
||||
--- Gets the current GraphNodeHeldObject
|
||||
--- Gets the current held object node being processed
|
||||
function geo_get_current_held_object()
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param node GraphNode
|
||||
--- @param obj GraphNodeObject
|
||||
--- Skips graph node interpolation for a frame
|
||||
function geo_skip_interpolation(node, obj)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param tex Pointer_Texture
|
||||
--- @return table
|
||||
--- Converts a texture's pixels to a Lua table. Returns nil if failed. Otherwise, returns a 1-indexed table of RGBA pixels
|
||||
|
|
@ -12062,6 +12112,18 @@ function set_whirlpools(x, y, z, strength, area, index)
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @param o Object
|
||||
--- Skips object interpolation for a frame
|
||||
function obj_skip_interpolation(o)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param o Object
|
||||
--- Skips animation interpolation for a frame
|
||||
function obj_anim_skip_interpolation(o)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- Resets every modified dialog back to vanilla
|
||||
function smlua_text_utils_reset_all()
|
||||
-- ...
|
||||
|
|
|
|||
|
|
@ -97,11 +97,6 @@ gServerSettings = {}
|
|||
--- Struct containing the settings for Nametags
|
||||
gNametagsSettings = {}
|
||||
|
||||
--- @type Camera
|
||||
--- Struct contaning camera fields
|
||||
--- - This camera is the same as `gMarioStates[i].area.camera` or `gCurrentArea.camera`
|
||||
gCamera = {}
|
||||
|
||||
-----------
|
||||
-- hooks --
|
||||
-----------
|
||||
|
|
|
|||
|
|
@ -955,14 +955,6 @@
|
|||
--- @field public translation Vec3s
|
||||
--- @field public rotation Vec3s
|
||||
|
||||
--- @class HudUtilsRotation
|
||||
--- @field public rotation number
|
||||
--- @field public rotationDiff number
|
||||
--- @field public prevPivotX number
|
||||
--- @field public prevPivotY number
|
||||
--- @field public pivotX number
|
||||
--- @field public pivotY number
|
||||
|
||||
--- @class InstantWarp
|
||||
--- @field public id integer
|
||||
--- @field public area integer
|
||||
|
|
|
|||
|
|
@ -597,5 +597,11 @@ enum BehaviorId get_id_from_behavior_name(const char* name) {
|
|||
return i;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < gHookedBehaviorsCount; i++) {
|
||||
struct LuaHookedBehavior *hooked = &gHookedBehaviors[i];
|
||||
if (hooked->bhvName && !strcmp(name, hooked->bhvName)) {
|
||||
return hooked->overrideId;
|
||||
}
|
||||
}
|
||||
return id_bhv_max_count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2449,6 +2449,48 @@ static void ParseBehaviorScriptSymbol(GfxData *aGfxData, DataNode<BehaviorScript
|
|||
PrintDataError(" ERROR: Unknown behavior symbol: %s", _Symbol.begin());
|
||||
}
|
||||
|
||||
static bool DynOS_Bhv_CheckCommands(const BehaviorScript *aBhv, const Array<BehaviorScript> &aCommands) {
|
||||
u8 bhvCommand = (*aBhv >> 24) & 0xFF;
|
||||
for (const auto &commandToCheck : aCommands) {
|
||||
if (bhvCommand == ((commandToCheck >> 24) & 0xFF)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool DynOS_Bhv_Validate(GfxData *aGfxData, const DataNode<BehaviorScript> *aNode) {
|
||||
|
||||
// 1st command must be BEGIN
|
||||
if (!DynOS_Bhv_CheckCommands(aNode->mData + 0, { BEGIN(0) })) {
|
||||
PrintDataError(" ERROR: Validation failed for behavior %s: First command of the script must be BEGIN.", aNode->mName.begin());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2nd command must be ID
|
||||
if (!DynOS_Bhv_CheckCommands(aNode->mData + 1, { ID(0) })) {
|
||||
PrintDataError(" ERROR: Validation failed for behavior %s: Second command of the script must be ID.", aNode->mName.begin());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Last command must be a terminating command
|
||||
if (!DynOS_Bhv_CheckCommands(aNode->mData + aNode->mSize - 1, {
|
||||
CALL(0),
|
||||
RETURN(),
|
||||
GOTO(0),
|
||||
END_LOOP(),
|
||||
BREAK(),
|
||||
DEACTIVATE(),
|
||||
CALL_EXT(0),
|
||||
GOTO_EXT(0),
|
||||
})) {
|
||||
PrintDataError(" ERROR: Validation failed for behavior %s: Last command of the script must be one of:\n CALL, RETURN, GOTO, END_LOOP, BREAK, DEACTIVATE", aNode->mName.begin());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DataNode<BehaviorScript> *DynOS_Bhv_Parse(GfxData *aGfxData, DataNode<BehaviorScript> *aNode, bool aDisplayPercent) {
|
||||
if (aNode->mData) return aNode;
|
||||
|
||||
|
|
@ -2460,9 +2502,13 @@ DataNode<BehaviorScript> *DynOS_Bhv_Parse(GfxData *aGfxData, DataNode<BehaviorSc
|
|||
ParseBehaviorScriptSymbol(aGfxData, aNode, _Head, _TokenIndex, _SwitchNodes);
|
||||
if (aDisplayPercent && aGfxData->mErrorCount == 0) { PrintNoNewLine("%3d%%\b\b\b\b", (s32) (_TokenIndex * 100) / aNode->mTokens.Count()); }
|
||||
}
|
||||
if (aDisplayPercent && aGfxData->mErrorCount == 0) { Print("100%%"); }
|
||||
aNode->mSize = (u32)(_Head - aNode->mData);
|
||||
aNode->mLoadIndex = aGfxData->mLoadIndex++;
|
||||
|
||||
// Validate behavior script
|
||||
DynOS_Bhv_Validate(aGfxData, aNode);
|
||||
|
||||
if (aDisplayPercent && aGfxData->mErrorCount == 0) { Print("100%%"); }
|
||||
return aNode;
|
||||
}
|
||||
|
||||
|
|
@ -2592,6 +2638,12 @@ static DataNode<BehaviorScript> *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat
|
|||
}
|
||||
}
|
||||
|
||||
// Validate it
|
||||
if (!DynOS_Bhv_Validate(aGfxData, _Node)) {
|
||||
Delete(_Node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add it
|
||||
if (aGfxData != NULL) {
|
||||
aGfxData->mBehaviorScripts.Add(_Node);
|
||||
|
|
|
|||
|
|
@ -1149,6 +1149,18 @@
|
|||
<br />
|
||||
|
||||
## [djui_hud_utils.h](#djui_hud_utils.h)
|
||||
- ROTATION_PIVOT_X_LEFT
|
||||
- ROTATION_PIVOT_X_CENTER
|
||||
- ROTATION_PIVOT_X_RIGHT
|
||||
- ROTATION_PIVOT_Y_TOP
|
||||
- ROTATION_PIVOT_Y_CENTER
|
||||
- ROTATION_PIVOT_Y_BOTTOM
|
||||
- TEXT_HALIGN_LEFT
|
||||
- TEXT_HALIGN_CENTER
|
||||
- TEXT_HALIGN_RIGHT
|
||||
- TEXT_VALIGN_TOP
|
||||
- TEXT_VALIGN_CENTER
|
||||
- TEXT_VALIGN_BOTTOM
|
||||
|
||||
### [enum HudUtilsResolution](#HudUtilsResolution)
|
||||
| Identifier | Value |
|
||||
|
|
@ -1167,6 +1179,7 @@
|
|||
### [enum DjuiFontType](#DjuiFontType)
|
||||
| Identifier | Value |
|
||||
| :--------- | :---- |
|
||||
| FONT_LEGACY | -1 |
|
||||
| FONT_NORMAL | 0 |
|
||||
| FONT_MENU | 1 |
|
||||
| FONT_HUD | 2 |
|
||||
|
|
@ -1459,7 +1472,7 @@
|
|||
- ATTACK_FROM_BELOW
|
||||
- PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT
|
||||
- PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE
|
||||
- PVP_ATTACK_OVERRIDE_VANILLA_INVINCIBILITY
|
||||
- PVP_ATTACK_KNOCKBACK_ACTION_ARG
|
||||
- INT_STATUS_ATTACK_MASK
|
||||
- INT_STATUS_HOOT_GRABBED_BY_MARIO
|
||||
- INT_STATUS_MARIO_UNK1
|
||||
|
|
@ -3525,6 +3538,7 @@
|
|||
| HOOK_ON_CLEAR_AREAS | 58 |
|
||||
| HOOK_ON_PACKET_BYTESTRING_RECEIVE | 59 |
|
||||
| HOOK_MAX | 60 |
|
||||
- MAX_HOOKED_BEHAVIORS
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ Gets a behavior name from a behavior ID (bhvMyGreatMODCustom004)
|
|||
## [get_id_from_behavior_name](#get_id_from_behavior_name)
|
||||
|
||||
### Description
|
||||
gets a behavior ID from a behavior name
|
||||
Gets a behavior ID from a behavior name
|
||||
|
||||
### Lua Example
|
||||
`local enumValue = get_id_from_behavior_name(name)`
|
||||
|
|
@ -1312,7 +1312,8 @@ Calculates and returns the pitch and yaw angles from one 3D position (`from`) to
|
|||
| to | [Vec3f](structs.md#Vec3f) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `integer`
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`void calculate_angles(Vec3f from, Vec3f to, RET s16 *pitch, RET s16 *yaw);`
|
||||
|
|
@ -1585,7 +1586,7 @@ Applies a roll-based shake effect to the camera. Simulates rotational disturbanc
|
|||
| roll | `integer` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`void shake_camera_roll(INOUT s16 *roll);`
|
||||
|
|
@ -2825,7 +2826,7 @@ Gets the current DJUI HUD font
|
|||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`u8 djui_hud_get_font(void);`
|
||||
`s8 djui_hud_get_font(void);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
|
|
@ -2928,16 +2929,18 @@ Resets the current DJUI HUD color
|
|||
Gets the current DJUI HUD rotation
|
||||
|
||||
### Lua Example
|
||||
`local hudUtilsRotationValue = djui_hud_get_rotation()`
|
||||
`local rotation, pivotX, pivotY = djui_hud_get_rotation()`
|
||||
|
||||
### Parameters
|
||||
- None
|
||||
|
||||
### Returns
|
||||
- [HudUtilsRotation](structs.md#HudUtilsRotation)
|
||||
- `integer`
|
||||
- `number`
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`struct HudUtilsRotation* djui_hud_get_rotation(void);`
|
||||
`void djui_hud_get_rotation(RET s16 *rotation, RET f32 *pivotX, RET f32 *pivotY);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
|
|
@ -2990,7 +2993,79 @@ Sets the current DJUI HUD rotation interpolated
|
|||
- None
|
||||
|
||||
### C Prototype
|
||||
`void djui_hud_set_rotation_interpolated(s32 prevRotation, f32 prevPivotX, f32 prevPivotY, s32 rotation, f32 pivotX, f32 pivotY);`
|
||||
`void djui_hud_set_rotation_interpolated(s16 prevRotation, f32 prevPivotX, f32 prevPivotY, s16 rotation, f32 pivotX, f32 pivotY);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [djui_hud_get_text_alignment](#djui_hud_get_text_alignment)
|
||||
|
||||
### Description
|
||||
Gets the current DJUI HUD text alignment
|
||||
|
||||
### Lua Example
|
||||
`local textHAlign, textVAlign = djui_hud_get_text_alignment()`
|
||||
|
||||
### Parameters
|
||||
- None
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`void djui_hud_get_text_alignment(RET f32 *textHAlign, RET f32 *textVAlign);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [djui_hud_set_text_alignment](#djui_hud_set_text_alignment)
|
||||
|
||||
### Description
|
||||
Sets the current DJUI HUD text alignment
|
||||
|
||||
### Lua Example
|
||||
`djui_hud_set_text_alignment(textHAlign, textVAlign)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| textHAlign | `number` |
|
||||
| textVAlign | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void djui_hud_set_text_alignment(f32 textHAlign, f32 textVAlign);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [djui_hud_set_text_alignment_interpolated](#djui_hud_set_text_alignment_interpolated)
|
||||
|
||||
### Description
|
||||
Sets the current DJUI HUD text alignment interpolated
|
||||
|
||||
### Lua Example
|
||||
`djui_hud_set_text_alignment_interpolated(prevTextHAlign, prevTextVAlign, textHAlign, textVAlign)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| prevTextHAlign | `number` |
|
||||
| prevTextVAlign | `number` |
|
||||
| textHAlign | `number` |
|
||||
| textVAlign | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void djui_hud_set_text_alignment_interpolated(f32 prevTextHAlign, f32 prevTextVAlign, f32 textHAlign, f32 textVAlign);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
|
|
|
|||
|
|
@ -147,6 +147,29 @@ Sets the lighting engine ambient color
|
|||
|
||||
<br />
|
||||
|
||||
## [le_set_max_lights_per_vertex](#le_set_max_lights_per_vertex)
|
||||
|
||||
### Description
|
||||
Sets the max amount of lights that can affect a vertex
|
||||
|
||||
### Lua Example
|
||||
`le_set_max_lights_per_vertex(count)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| count | `integer` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void le_set_max_lights_per_vertex(u8 count);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [le_calculate_lighting_color](#le_calculate_lighting_color)
|
||||
|
||||
### Description
|
||||
|
|
@ -560,6 +583,35 @@ Sets whether a lighting engine point light will use a surface's normals to deter
|
|||
|
||||
<br />
|
||||
|
||||
---
|
||||
# functions from load.h
|
||||
|
||||
<br />
|
||||
|
||||
|
||||
## [set_sound_bank_override](#set_sound_bank_override)
|
||||
|
||||
### Description
|
||||
Overrides the soundbank, set to -1 to reset
|
||||
|
||||
### Lua Example
|
||||
`set_sound_bank_override(bank)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| bank | `integer` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void set_sound_bank_override(s32 bank);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
---
|
||||
# functions from mario.h
|
||||
|
||||
|
|
@ -5082,7 +5134,9 @@ Calculates the distance between two points in 3D space (`from` and `to`), as wel
|
|||
| to | [Vec3f](structs.md#Vec3f) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `number`
|
||||
- `integer`
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`void vec3f_get_dist_and_angle(Vec3f from, Vec3f to, RET f32 *dist, RET s16 *pitch, RET s16 *yaw);`
|
||||
|
|
|
|||
|
|
@ -2945,7 +2945,7 @@ Determines an object's forward speed multiplier.
|
|||
| floor_nY | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`void calc_obj_friction(RET f32 *objFriction, f32 floor_nY);`
|
||||
|
|
@ -4419,7 +4419,7 @@ Begin by increasing the current object's scale by `scaleVel`, and slowly decreas
|
|||
| blinkLength | `integer` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`void obj_update_blinking(INOUT s32 *blinkTimer, s16 baseCycleLength, s16 cycleLengthRange, s16 blinkLength);`
|
||||
|
|
@ -4743,7 +4743,8 @@ Treats far home as Mario. Returns the distance and angle to the nearest player
|
|||
| threshold | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `integer`
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`void treat_far_home_as_mario(f32 threshold, RET s32* distanceToPlayer, RET s32* angleToPlayer);`
|
||||
|
|
|
|||
|
|
@ -1963,7 +1963,7 @@ Marks an object to be unloaded at the end of the frame
|
|||
| dragStrength | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`void apply_drag_to_value(INOUT f32 *value, f32 dragStrength);`
|
||||
|
|
|
|||
|
|
@ -1775,6 +1775,27 @@ Gets the choice selected inside of a dialog box (0-1)
|
|||
|
||||
<br />
|
||||
|
||||
## [get_time_stop_flags](#get_time_stop_flags)
|
||||
|
||||
### Description
|
||||
Gets the active time stop flags, used to freeze specific objects during cutscenes
|
||||
|
||||
### Lua Example
|
||||
`local integerValue = get_time_stop_flags()`
|
||||
|
||||
### Parameters
|
||||
- None
|
||||
|
||||
### Returns
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`u32 get_time_stop_flags(void);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [get_local_discord_id](#get_local_discord_id)
|
||||
|
||||
### Description
|
||||
|
|
@ -2154,7 +2175,7 @@ Gets the name of the operating system the game is running on
|
|||
## [geo_get_current_root](#geo_get_current_root)
|
||||
|
||||
### Description
|
||||
Gets the current GraphNodeRoot
|
||||
Gets the current root node being processed
|
||||
|
||||
### Lua Example
|
||||
`local graphNodeRootValue = geo_get_current_root()`
|
||||
|
|
@ -2175,7 +2196,7 @@ Gets the current GraphNodeRoot
|
|||
## [geo_get_current_master_list](#geo_get_current_master_list)
|
||||
|
||||
### Description
|
||||
Gets the current GraphNodeMasterList
|
||||
Gets the current master list node being processed
|
||||
|
||||
### Lua Example
|
||||
`local graphNodeMasterListValue = geo_get_current_master_list()`
|
||||
|
|
@ -2196,7 +2217,7 @@ Gets the current GraphNodeMasterList
|
|||
## [geo_get_current_perspective](#geo_get_current_perspective)
|
||||
|
||||
### Description
|
||||
Gets the current GraphNodePerspective
|
||||
Gets the current perspective node being processed
|
||||
|
||||
### Lua Example
|
||||
`local graphNodePerspectiveValue = geo_get_current_perspective()`
|
||||
|
|
@ -2217,7 +2238,7 @@ Gets the current GraphNodePerspective
|
|||
## [geo_get_current_camera](#geo_get_current_camera)
|
||||
|
||||
### Description
|
||||
Gets the current GraphNodeCamera
|
||||
Gets the current camera node being processed
|
||||
|
||||
### Lua Example
|
||||
`local graphNodeCameraValue = geo_get_current_camera()`
|
||||
|
|
@ -2238,7 +2259,7 @@ Gets the current GraphNodeCamera
|
|||
## [geo_get_current_held_object](#geo_get_current_held_object)
|
||||
|
||||
### Description
|
||||
Gets the current GraphNodeHeldObject
|
||||
Gets the current held object node being processed
|
||||
|
||||
### Lua Example
|
||||
`local graphNodeHeldObjectValue = geo_get_current_held_object()`
|
||||
|
|
@ -2256,6 +2277,30 @@ Gets the current GraphNodeHeldObject
|
|||
|
||||
<br />
|
||||
|
||||
## [geo_skip_interpolation](#geo_skip_interpolation)
|
||||
|
||||
### Description
|
||||
Skips graph node interpolation for a frame
|
||||
|
||||
### Lua Example
|
||||
`geo_skip_interpolation(node, obj)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| node | [GraphNode](structs.md#GraphNode) |
|
||||
| obj | [GraphNodeObject](structs.md#GraphNodeObject) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void geo_skip_interpolation(struct GraphNode *node, struct GraphNodeObject *obj);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [texture_to_lua_table](#texture_to_lua_table)
|
||||
|
||||
### Description
|
||||
|
|
@ -3531,6 +3576,52 @@ Sets the parameters of one of the two whirlpools (0-indexed) in an area
|
|||
|
||||
<br />
|
||||
|
||||
## [obj_skip_interpolation](#obj_skip_interpolation)
|
||||
|
||||
### Description
|
||||
Skips object interpolation for a frame
|
||||
|
||||
### Lua Example
|
||||
`obj_skip_interpolation(o)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| o | [Object](structs.md#Object) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void obj_skip_interpolation(struct Object *o);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [obj_anim_skip_interpolation](#obj_anim_skip_interpolation)
|
||||
|
||||
### Description
|
||||
Skips animation interpolation for a frame
|
||||
|
||||
### Lua Example
|
||||
`obj_anim_skip_interpolation(o)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| o | [Object](structs.md#Object) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void obj_anim_skip_interpolation(struct Object *o);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
---
|
||||
# functions from smlua_text_utils.h
|
||||
|
||||
|
|
|
|||
|
|
@ -763,6 +763,9 @@
|
|||
- [djui_hud_get_rotation](functions-3.md#djui_hud_get_rotation)
|
||||
- [djui_hud_set_rotation](functions-3.md#djui_hud_set_rotation)
|
||||
- [djui_hud_set_rotation_interpolated](functions-3.md#djui_hud_set_rotation_interpolated)
|
||||
- [djui_hud_get_text_alignment](functions-3.md#djui_hud_get_text_alignment)
|
||||
- [djui_hud_set_text_alignment](functions-3.md#djui_hud_set_text_alignment)
|
||||
- [djui_hud_set_text_alignment_interpolated](functions-3.md#djui_hud_set_text_alignment_interpolated)
|
||||
- [djui_hud_get_screen_width](functions-3.md#djui_hud_get_screen_width)
|
||||
- [djui_hud_get_screen_height](functions-3.md#djui_hud_get_screen_height)
|
||||
- [djui_hud_get_mouse_x](functions-3.md#djui_hud_get_mouse_x)
|
||||
|
|
@ -976,6 +979,7 @@
|
|||
- [le_set_tone_mapping](functions-4.md#le_set_tone_mapping)
|
||||
- [le_get_ambient_color](functions-4.md#le_get_ambient_color)
|
||||
- [le_set_ambient_color](functions-4.md#le_set_ambient_color)
|
||||
- [le_set_max_lights_per_vertex](functions-4.md#le_set_max_lights_per_vertex)
|
||||
- [le_calculate_lighting_color](functions-4.md#le_calculate_lighting_color)
|
||||
- [le_calculate_lighting_color_with_normal](functions-4.md#le_calculate_lighting_color_with_normal)
|
||||
- [le_calculate_lighting_dir](functions-4.md#le_calculate_lighting_dir)
|
||||
|
|
@ -996,6 +1000,11 @@
|
|||
|
||||
<br />
|
||||
|
||||
- load.h
|
||||
- [set_sound_bank_override](functions-4.md#set_sound_bank_override)
|
||||
|
||||
<br />
|
||||
|
||||
- mario.h
|
||||
- [is_anim_at_end](functions-4.md#is_anim_at_end)
|
||||
- [is_anim_past_end](functions-4.md#is_anim_past_end)
|
||||
|
|
@ -2047,6 +2056,7 @@
|
|||
- [set_override_envfx](functions-7.md#set_override_envfx)
|
||||
- [get_global_timer](functions-7.md#get_global_timer)
|
||||
- [get_dialog_response](functions-7.md#get_dialog_response)
|
||||
- [get_time_stop_flags](functions-7.md#get_time_stop_flags)
|
||||
- [get_local_discord_id](functions-7.md#get_local_discord_id)
|
||||
- [get_coopnet_id](functions-7.md#get_coopnet_id)
|
||||
- [get_volume_master](functions-7.md#get_volume_master)
|
||||
|
|
@ -2069,6 +2079,7 @@
|
|||
- [geo_get_current_perspective](functions-7.md#geo_get_current_perspective)
|
||||
- [geo_get_current_camera](functions-7.md#geo_get_current_camera)
|
||||
- [geo_get_current_held_object](functions-7.md#geo_get_current_held_object)
|
||||
- [geo_skip_interpolation](functions-7.md#geo_skip_interpolation)
|
||||
- [texture_to_lua_table](functions-7.md#texture_to_lua_table)
|
||||
- [get_texture_name](functions-7.md#get_texture_name)
|
||||
|
||||
|
|
@ -2130,6 +2141,8 @@
|
|||
- [obj_set_vel](functions-7.md#obj_set_vel)
|
||||
- [obj_move_xyz](functions-7.md#obj_move_xyz)
|
||||
- [set_whirlpools](functions-7.md#set_whirlpools)
|
||||
- [obj_skip_interpolation](functions-7.md#obj_skip_interpolation)
|
||||
- [obj_anim_skip_interpolation](functions-7.md#obj_anim_skip_interpolation)
|
||||
|
||||
<br />
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@
|
|||
- [GraphNodeSwitchCase](#GraphNodeSwitchCase)
|
||||
- [GraphNodeTranslation](#GraphNodeTranslation)
|
||||
- [GraphNodeTranslationRotation](#GraphNodeTranslationRotation)
|
||||
- [HudUtilsRotation](#HudUtilsRotation)
|
||||
- [InstantWarp](#InstantWarp)
|
||||
- [LakituState](#LakituState)
|
||||
- [LevelValues](#LevelValues)
|
||||
|
|
@ -1427,21 +1426,6 @@
|
|||
|
||||
<br />
|
||||
|
||||
## [HudUtilsRotation](#HudUtilsRotation)
|
||||
|
||||
| Field | Type | Access |
|
||||
| ----- | ---- | ------ |
|
||||
| rotation | `number` | |
|
||||
| rotationDiff | `number` | |
|
||||
| prevPivotX | `number` | |
|
||||
| prevPivotY | `number` | |
|
||||
| pivotX | `number` | |
|
||||
| pivotY | `number` | |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [InstantWarp](#InstantWarp)
|
||||
|
||||
| Field | Type | Access |
|
||||
|
|
|
|||
|
|
@ -557,7 +557,7 @@ enum BehaviorId get_id_from_vanilla_behavior(const BehaviorScript* behavior);
|
|||
const BehaviorScript* get_behavior_from_id(enum BehaviorId id);
|
||||
/* |description|Gets a behavior name from a behavior ID (bhvMyGreatMODCustom004)|descriptionEnd| */
|
||||
const char* get_behavior_name_from_id(enum BehaviorId id);
|
||||
/* |description|gets a behavior ID from a behavior name|descriptionEnd| */
|
||||
/* |description|Gets a behavior ID from a behavior name|descriptionEnd| */
|
||||
enum BehaviorId get_id_from_behavior_name(const char* name);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Binary file not shown.
93
mods/char-select-extra-chars-plus/!class-definitions.lua
Normal file
93
mods/char-select-extra-chars-plus/!class-definitions.lua
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
--- Don't add any functional code to this file ---
|
||||
--- @meta
|
||||
|
||||
--- @class LuigiState
|
||||
|
||||
--- @class ToadState
|
||||
|
||||
--- @class WarioState
|
||||
|
||||
--- @class WaluigiState
|
||||
|
||||
--- @class ToadetteState
|
||||
--- @field public averageForwardVel number
|
||||
|
||||
--- @class PeachState
|
||||
|
||||
--- @class DaisyState
|
||||
|
||||
--- @class YoshiState
|
||||
|
||||
--- @class BirdoState
|
||||
--- @field public spitTimer integer
|
||||
--- @field public framesSinceShoot integer
|
||||
--- @field public flameCharge integer
|
||||
|
||||
--- @class SpikeState
|
||||
|
||||
--- @class PaulineState
|
||||
|
||||
--- @class RosalinaState
|
||||
--- @field public canSpin boolean
|
||||
--- @field public orbitObjActive boolean
|
||||
--- @field public orbitObjDist number
|
||||
--- @field public orbitObjAngle integer
|
||||
|
||||
--- @class WapeachState
|
||||
|
||||
--- @class DonkeyKongState
|
||||
|
||||
--- @class SonicState
|
||||
--- @field public spinCharge integer
|
||||
--- @field public groundYVel integer
|
||||
--- @field public prevForwardVel integer
|
||||
--- @field public peakHeight integer
|
||||
--- @field public actionADone boolean
|
||||
--- @field public actionBDone boolean
|
||||
--- @field public bounced boolean
|
||||
--- @field public spindashState integer
|
||||
--- @field public instashieldTimer integer
|
||||
--- @field public oxygen integer
|
||||
--- @field public prevVelY number
|
||||
--- @field public prevHeight number
|
||||
--- @field public physTimer integer
|
||||
--- @field public lastforwardPos Vec3f
|
||||
--- @field public realFVel number
|
||||
|
||||
--- @class CharacterState
|
||||
--- @field public mario MarioState
|
||||
--- @field public luigi LuigiState
|
||||
--- @field public toad ToadState
|
||||
--- @field public wario WarioState
|
||||
--- @field public waluigi WaluigiState
|
||||
--- @field public toadette ToadetteState
|
||||
--- @field public peach PeachState
|
||||
--- @field public daisy DaisyState
|
||||
--- @field public yoshi YoshiState
|
||||
--- @field public birdo BirdoState
|
||||
--- @field public spike SpikeState
|
||||
--- @field public pauline PaulineState
|
||||
--- @field public rosalina RosalinaState
|
||||
--- @field public wapeach WapeachState
|
||||
--- @field public donkeyKong DonkeyKongState
|
||||
--- @field public sonic SonicState
|
||||
|
||||
--- @alias SonicMouthGSCId
|
||||
--- | `SONIC_MOUTH_NORMAL`
|
||||
--- | `SONIC_MOUTH_FROWN`
|
||||
--- | `SONIC_MOUTH_GRIMACING`
|
||||
--- | `SONIC_MOUTH_HAPPY`
|
||||
--- | `SONIC_MOUTH_GRIN`
|
||||
--- | `SONIC_MOUTH_ATTACKED`
|
||||
--- | `SONIC_MOUTH_SHOCKED`
|
||||
--- | `SONIC_MOUTH_SURPRISED`
|
||||
--- | `SONIC_MOUTH_NEUTRAL`
|
||||
|
||||
--- @alias SonicMouthSideGSCId
|
||||
--- | `SONIC_MOUTH_LEFT`
|
||||
--- | `SONIC_MOUTH_RIGHT`
|
||||
|
||||
--- @alias HandParam
|
||||
--- | `SONIC_HAND_RIGHT`
|
||||
--- | `SONIC_HAND_LEFT`
|
||||
--- | `WAPEACH_HAND_AXE`
|
||||
10
mods/char-select-extra-chars-plus/!environments.lua
Normal file
10
mods/char-select-extra-chars-plus/!environments.lua
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
-- Environment inclusions --
|
||||
--[[
|
||||
We only need to include character select rn
|
||||
]]
|
||||
|
||||
charSelect = charSelect
|
||||
|
||||
if not charSelect then return end
|
||||
_ENV = setmetatable(_G, { __index = charSelect })
|
||||
|
||||
31
mods/char-select-extra-chars-plus/!misc-functions.lua
Normal file
31
mods/char-select-extra-chars-plus/!misc-functions.lua
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
--- Misc Functions ---
|
||||
|
||||
--- @param m MarioState
|
||||
--- @param name string
|
||||
--- @param accel? number
|
||||
--- Plays a custom animation for MarioState `m`
|
||||
function play_custom_anim(m, name, accel)
|
||||
accel = accel or 0x10000
|
||||
|
||||
m.marioObj.header.gfx.animInfo.animAccel = accel
|
||||
|
||||
if (smlua_anim_util_get_current_animation_name(m.marioObj) ~= name or m.marioObj.header.gfx.animInfo.animID ~= -1) then
|
||||
m.marioObj.header.gfx.animInfo.animID = -1
|
||||
set_anim_to_frame(m, 0)
|
||||
end
|
||||
|
||||
smlua_anim_util_set_animation(m.marioObj, name)
|
||||
end
|
||||
|
||||
--- @param str string
|
||||
--- @param splitAt? string
|
||||
function string.split(str, splitAt)
|
||||
if splitAt == nil then
|
||||
splitAt = " "
|
||||
end
|
||||
local result = {}
|
||||
for match in str:gmatch(string.format("[^%s]+", splitAt)) do
|
||||
table.insert(result, match)
|
||||
end
|
||||
return result
|
||||
end
|
||||
148
mods/char-select-extra-chars-plus/a-hitboxes.lua
Normal file
148
mods/char-select-extra-chars-plus/a-hitboxes.lua
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
local colObjLists = { OBJ_LIST_GENACTOR, OBJ_LIST_PUSHABLE, OBJ_LIST_SURFACE, OBJ_LIST_DESTRUCTIVE }
|
||||
|
||||
local bhvBlacklist = {
|
||||
[id_bhvBowser] = true,
|
||||
[id_bhvDoor] = true,
|
||||
[id_bhvDoorWarp] = true,
|
||||
[id_bhvStarDoor] = true,
|
||||
[id_bhvUnlockDoorStar] = true,
|
||||
[id_bhvToadMessage] = true,
|
||||
[id_bhvFireSpitter] = true,
|
||||
[id_bhvExplosion] = true
|
||||
}
|
||||
|
||||
---@param o Object
|
||||
---@param o2 Object
|
||||
local function attack_bounce(o, o2)
|
||||
o2.oVelY = 15.0
|
||||
play_sound(SOUND_ACTION_BONK, o2.header.gfx.cameraToObject)
|
||||
end
|
||||
|
||||
---@param o Object
|
||||
---@param o2 Object
|
||||
local function attack_bully(o, o2)
|
||||
o2.oBullyLastNetworkPlayerIndex = o.globalPlayerIndex
|
||||
o2.oMoveAngleYaw = o.oMoveAngleYaw
|
||||
o2.oForwardVel = 30.0
|
||||
|
||||
o2.oInteractStatus = o2.oInteractStatus | ATTACK_FAST_ATTACK | INT_STATUS_WAS_ATTACKED | INT_STATUS_INTERACTED
|
||||
end
|
||||
|
||||
---@param o Object
|
||||
---@param o2 Object
|
||||
local function attack_bully_strong(o, o2)
|
||||
o2.oBullyLastNetworkPlayerIndex = o.globalPlayerIndex
|
||||
o2.oMoveAngleYaw = o.oMoveAngleYaw
|
||||
o2.oForwardVel = 50.0
|
||||
o2.oVelY = 30.0
|
||||
|
||||
o2.oInteractStatus = o2.oInteractStatus | ATTACK_FAST_ATTACK | INT_STATUS_WAS_ATTACKED | INT_STATUS_INTERACTED
|
||||
end
|
||||
|
||||
---@param o Object
|
||||
---@param o2 Object
|
||||
local function attack_mrblizzard(o, o2)
|
||||
if o2.prevObj then
|
||||
o2.prevObj.oAction = 2
|
||||
o2.prevObj = nil
|
||||
o2.oMrBlizzardHeldObj = nil
|
||||
end
|
||||
o2.oAction = MR_BLIZZARD_ACT_DEATH
|
||||
end
|
||||
|
||||
---@param o Object
|
||||
---@param o2 Object
|
||||
local function attack_bullet_bill(o, o2)
|
||||
spawn_mist_particles_with_sound(SOUND_GENERAL2_BOBOMB_EXPLOSION)
|
||||
o2.oAction = 4
|
||||
o2.oTimer = 0
|
||||
end
|
||||
|
||||
---@param o Object
|
||||
---@param o2 Object
|
||||
local function attack_chuckya(o, o2)
|
||||
o2.oAction = 2
|
||||
o2.oVelY = 30
|
||||
o2.oMoveAngleYaw = o.oMoveAngleYaw
|
||||
o2.oForwardVel = 25
|
||||
end
|
||||
|
||||
---@param o Object
|
||||
---@param o2 Object
|
||||
local function attack_whomp(o, o2)
|
||||
o2.oAction = 8
|
||||
end
|
||||
|
||||
---@param o Object
|
||||
---@param o2 Object
|
||||
local function attack_kingbobomb(o, o2)
|
||||
if o2.oFlags & OBJ_FLAG_HOLDABLE ~= 0 and o2.oAction ~= 8 then
|
||||
o2.oVelY = 30
|
||||
o2.oForwardVel = 30
|
||||
o2.oMoveAngleYaw = o.oMoveAngleYaw
|
||||
o2.oMoveFlags = 0
|
||||
o2.oAction = 4
|
||||
end
|
||||
end
|
||||
|
||||
---@param o Object
|
||||
---@param o2 Object
|
||||
local function attack_wooden_post(o, o2)
|
||||
o2.oWoodenPostMarioPounding = 1
|
||||
o2.oWoodenPostSpeedY = -100.0
|
||||
cur_obj_play_sound_2(SOUND_GENERAL_POUND_WOOD_POST)
|
||||
end
|
||||
|
||||
-- lists for edge case interactions
|
||||
|
||||
bhvWapeachAxeAttacks = {
|
||||
[id_bhvSmallBully] = attack_bully_strong,
|
||||
[id_bhvBigBully] = attack_bully_strong,
|
||||
[id_bhvBigBullyWithMinions] = attack_bully_strong,
|
||||
[id_bhvSmallChillBully] = attack_bully_strong,
|
||||
[id_bhvBigChillBully] = attack_bully_strong,
|
||||
[id_bhvMrBlizzard] = attack_mrblizzard,
|
||||
[id_bhvBulletBill] = attack_bullet_bill,
|
||||
[id_bhvSmallWhomp] = attack_whomp,
|
||||
[id_bhvChuckya] = attack_chuckya,
|
||||
[id_bhvWoodenPost] = attack_wooden_post,
|
||||
}
|
||||
|
||||
---@param o Object
|
||||
---@param spAttacksList table<BehaviorId,function>
|
||||
---@param getTarget? boolean
|
||||
function obj_process_attacks(o, spAttacksList, getTarget)
|
||||
-- players
|
||||
if o.oInteractType == 0 then
|
||||
local m = nearest_mario_state_to_object(o)
|
||||
if m and m.playerIndex == 0 and m.marioObj.globalPlayerIndex ~= o.globalPlayerIndex
|
||||
and m.action & (ACT_FLAG_INVULNERABLE | ACT_FLAG_INTANGIBLE) == 0 and m.invincTimer == 0
|
||||
and obj_check_hitbox_overlap(m.marioObj, o) then
|
||||
if spAttacksList[id_bhvMario] then
|
||||
spAttacksList[id_bhvMario](o, m)
|
||||
else
|
||||
take_damage_and_knock_back(m, o)
|
||||
end
|
||||
if getTarget then return m.marioObj end
|
||||
end
|
||||
end
|
||||
-- other objects
|
||||
for i, list in ipairs(colObjLists) do
|
||||
local o2 = obj_get_first(list)
|
||||
while o2 do
|
||||
if o ~= o2 and o2.oInteractStatus & INT_STATUS_INTERACTED == 0 and o2.oIntangibleTimer == 0 and obj_check_hitbox_overlap(o, o2) then
|
||||
local bhv = get_id_from_behavior(o2.behavior)
|
||||
if not bhvBlacklist[bhv] then
|
||||
if spAttacksList[bhv] then
|
||||
spAttacksList[bhv](o, o2)
|
||||
else
|
||||
o2.oInteractStatus = o2.oInteractStatus | ATTACK_FAST_ATTACK | INT_STATUS_WAS_ATTACKED |
|
||||
INT_STATUS_INTERACTED
|
||||
end
|
||||
if getTarget then return o2 end
|
||||
end
|
||||
end
|
||||
o2 = obj_get_next(o2)
|
||||
end
|
||||
end
|
||||
end
|
||||
52
mods/char-select-extra-chars-plus/a-movesets-vars.lua
Normal file
52
mods/char-select-extra-chars-plus/a-movesets-vars.lua
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
--- Vars that all movesets use --
|
||||
|
||||
--- @type CharacterState[]
|
||||
gCharacterStates = {}
|
||||
for i = 0, (MAX_PLAYERS - 1) do
|
||||
gCharacterStates[i] = {}
|
||||
local m = gMarioStates[i]
|
||||
local e = gCharacterStates[i]
|
||||
e.mario = m
|
||||
e.luigi = {}
|
||||
e.toad = {}
|
||||
e.wario = {}
|
||||
e.waluigi = {}
|
||||
e.toadette = {}
|
||||
e.peach = {}
|
||||
e.daisy = {}
|
||||
e.yoshi = {}
|
||||
e.birdo = {}
|
||||
e.spike = {}
|
||||
e.pauline = {}
|
||||
e.rosalina = {}
|
||||
e.wapeach = {}
|
||||
e.donkeyKong = {}
|
||||
e.sonic = {}
|
||||
|
||||
e.toadette.averageForwardVel = 0
|
||||
|
||||
e.birdo.spitTimer = 0
|
||||
e.birdo.framesSinceShoot = 255
|
||||
e.birdo.flameCharge = 0
|
||||
|
||||
e.rosalina.canSpin = true
|
||||
e.rosalina.orbitObjActive = false
|
||||
e.rosalina.orbitObjDist = 0
|
||||
e.rosalina.orbitObjAngle = 0
|
||||
|
||||
e.sonic.spinCharge = 0
|
||||
e.sonic.groundYVel = 0
|
||||
e.sonic.prevForwardVel = 0
|
||||
e.sonic.peakHeight = 0
|
||||
e.sonic.actionADone = false
|
||||
e.sonic.actionBDone = false
|
||||
e.sonic.bounced = false
|
||||
e.sonic.spindashState = 0
|
||||
e.sonic.instashieldTimer = 0
|
||||
e.sonic.oxygen = 900 -- 30 seconds
|
||||
e.sonic.prevVelY = 0
|
||||
e.sonic.prevHeight = 0
|
||||
e.sonic.physTimer = 0
|
||||
e.sonic.lastforwardPos = gVec3fZero()
|
||||
e.sonic.realFVel = 0
|
||||
end
|
||||
BIN
mods/char-select-extra-chars-plus/actors/dizzy_circle_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/dizzy_circle_geo.bin
Normal file
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/dk_cap_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/dk_cap_geo.bin
Normal file
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/dk_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/dk_geo.bin
Normal file
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/dk_metal_cap_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/dk_metal_cap_geo.bin
Normal file
Binary file not shown.
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/dk_wing_cap_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/dk_wing_cap_geo.bin
Normal file
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/foreman_spike_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/foreman_spike_geo.bin
Normal file
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/segasonic_cap_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/segasonic_cap_geo.bin
Normal file
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/segasonic_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/segasonic_geo.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/segasupersonic_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/segasupersonic_geo.bin
Normal file
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/spike_bomb_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/spike_bomb_geo.bin
Normal file
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/spike_hammer_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/spike_hammer_geo.bin
Normal file
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/wapeach_cap_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/wapeach_cap_geo.bin
Normal file
Binary file not shown.
BIN
mods/char-select-extra-chars-plus/actors/wapeach_geo.bin
Normal file
BIN
mods/char-select-extra-chars-plus/actors/wapeach_geo.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
18912
mods/char-select-extra-chars-plus/anims-donkey.lua
Normal file
18912
mods/char-select-extra-chars-plus/anims-donkey.lua
Normal file
File diff suppressed because it is too large
Load diff
3032
mods/char-select-extra-chars-plus/custom-anims-sonic.lua
Normal file
3032
mods/char-select-extra-chars-plus/custom-anims-sonic.lua
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1936
mods/char-select-extra-chars-plus/main.lua
Normal file
1936
mods/char-select-extra-chars-plus/main.lua
Normal file
File diff suppressed because it is too large
Load diff
843
mods/char-select-extra-chars-plus/moveset-birdo.lua
Normal file
843
mods/char-select-extra-chars-plus/moveset-birdo.lua
Normal file
|
|
@ -0,0 +1,843 @@
|
|||
-------------------
|
||||
-- Birdo Moveset --
|
||||
-------------------
|
||||
|
||||
if not charSelect then return end
|
||||
|
||||
local SOUND_SPIT = audio_sample_load("z_sfx_birdo_spit.ogg") -- Load audio sample
|
||||
|
||||
---------------
|
||||
-- Birdo Egg --
|
||||
---------------
|
||||
|
||||
_G.ACT_BIRDO_HOLD_WALKING = allocate_mario_action(ACT_FLAG_MOVING | ACT_GROUP_OBJECT)
|
||||
_G.ACT_SPIT_EGG = allocate_mario_action(ACT_FLAG_STATIONARY | ACT_FLAG_IDLE | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
_G.ACT_SPIT_EGG_WALK = allocate_mario_action(ACT_FLAG_MOVING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
_G.ACT_SPIT_EGG_AIR = allocate_mario_action(ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
|
||||
--- @param m MarioState
|
||||
local function act_birdo_hold_walking(m)
|
||||
local startYaw = m.faceAngle.y
|
||||
|
||||
if m.heldObj and m.heldObj.behavior == get_behavior_from_id(id_bhvJumpingBox) then
|
||||
return set_mario_action(m, ACT_CRAZY_BOX_BOUNCE, 0)
|
||||
end
|
||||
|
||||
if (m.marioObj.oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) ~= 0 then
|
||||
return drop_and_set_mario_action(m, ACT_WALKING, 0)
|
||||
end
|
||||
|
||||
if (should_begin_sliding(m)) ~= 0 then
|
||||
return set_mario_action(m, ACT_HOLD_BEGIN_SLIDING, 0)
|
||||
end
|
||||
|
||||
if (m.input & INPUT_B_PRESSED) ~= 0 then
|
||||
return set_mario_action(m, ACT_THROWING, 0)
|
||||
end
|
||||
|
||||
if (m.input & INPUT_A_PRESSED) ~= 0 then
|
||||
return set_jumping_action(m, ACT_HOLD_JUMP, 0)
|
||||
end
|
||||
|
||||
if (m.input & INPUT_ZERO_MOVEMENT) ~= 0 then
|
||||
return set_mario_action(m, ACT_HOLD_DECELERATING, 0)
|
||||
end
|
||||
|
||||
if (m.input & INPUT_Z_PRESSED) ~= 0 then
|
||||
return drop_and_set_mario_action(m, ACT_CROUCH_SLIDE, 0)
|
||||
end
|
||||
|
||||
update_walking_speed(m) -- normal walking speed
|
||||
|
||||
local result = perform_ground_step(m)
|
||||
if result == GROUND_STEP_LEFT_GROUND then
|
||||
set_mario_action(m, ACT_HOLD_FREEFALL, 0)
|
||||
elseif result == GROUND_STEP_HIT_WALL then
|
||||
if (m.forwardVel > 16) then
|
||||
mario_set_forward_vel(m, 16)
|
||||
end
|
||||
end
|
||||
|
||||
-- for the animation, temporarily read birdo's speed as lower so it looks less goofy
|
||||
local prevForwardVel = m.forwardVel
|
||||
local prevMag = m.intendedMag
|
||||
m.forwardVel = m.forwardVel * 0.6
|
||||
m.intendedMag = m.intendedMag * 0.6
|
||||
anim_and_audio_for_hold_walk(m)
|
||||
m.forwardVel = prevForwardVel
|
||||
m.intendedMag = prevMag
|
||||
|
||||
|
||||
-- tilt body
|
||||
local dYaw = m.faceAngle.y - startYaw
|
||||
local val02 = -(dYaw * m.forwardVel / 12)
|
||||
local val00 = (m.forwardVel * 170)
|
||||
|
||||
val02 = math.clamp(val02, -0x1555, 0x1555)
|
||||
val00 = math.clamp(val00, 0x0, 0x1555)
|
||||
|
||||
m.marioBodyState.allowPartRotation = true
|
||||
m.marioBodyState.torsoAngle.z = approach_s32(m.marioBodyState.torsoAngle.z, val02, 0x400, 0x400)
|
||||
m.marioBodyState.torsoAngle.x = approach_s32(m.marioBodyState.torsoAngle.x, val00, 0x400, 0x400)
|
||||
|
||||
if (0.4 * m.intendedMag - m.forwardVel > 10) then
|
||||
set_mario_particle_flags(m, PARTICLE_DUST, 0)
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
--- @param m MarioState
|
||||
local function act_spit_egg(m)
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
if (m.quicksandDepth > 30) then
|
||||
return set_mario_action(m, ACT_IN_QUICKSAND, 0)
|
||||
end
|
||||
|
||||
if m.actionState == 0 then
|
||||
play_custom_anim(m, "BIRDO_ANIM_IDLE_TO_AIM_IDLE")
|
||||
if is_anim_past_end(m) ~= 0 then
|
||||
m.actionState = 1
|
||||
end
|
||||
elseif e.birdo.flameCharge == 0 and e.birdo.framesSinceShoot > 10 then
|
||||
play_custom_anim(m, "BIRDO_ANIM_AIM_IDLE_TO_IDLE")
|
||||
if is_anim_past_end(m) ~= 0 then
|
||||
return set_mario_action(m, ACT_IDLE, 0)
|
||||
end
|
||||
else
|
||||
play_custom_anim(m, "BIRDO_ANIM_AIM_IDLE")
|
||||
end
|
||||
mario_drop_held_object(m)
|
||||
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
|
||||
local oldActTimer = m.actionTimer
|
||||
if (m.input & INPUT_NONZERO_ANALOG) ~= 0 then
|
||||
mario_set_forward_vel(m, 0)
|
||||
local result = set_mario_action(m, ACT_SPIT_EGG_WALK, 0)
|
||||
m.actionTimer = oldActTimer
|
||||
return result
|
||||
elseif (check_common_idle_cancels(m) ~= 0) then
|
||||
if m.action & ACT_FLAG_AIR ~= 0 then
|
||||
mario_set_forward_vel(m, 0)
|
||||
set_mario_action(m, ACT_SPIT_EGG_AIR, 1)
|
||||
if m.vel.y <= 0 then
|
||||
m.actionArg = 0
|
||||
end
|
||||
m.actionTimer = oldActTimer
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
mario_set_forward_vel(m, 0)
|
||||
perform_ground_step(m)
|
||||
return 0
|
||||
end
|
||||
|
||||
--- @param m MarioState
|
||||
local function act_spit_egg_walk(m)
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
local mBody = m.marioBodyState
|
||||
|
||||
mario_drop_held_object(m)
|
||||
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
if e.birdo.flameCharge == 0 and e.birdo.framesSinceShoot > 10 then
|
||||
if m.forwardVel < 0 then
|
||||
m.forwardVel = m.intendedMag
|
||||
m.faceAngle.y = m.intendedYaw
|
||||
return set_mario_action(m, ACT_FINISH_TURNING_AROUND, 0)
|
||||
end
|
||||
m.forwardVel = m.intendedMag
|
||||
m.faceAngle.y = m.intendedYaw
|
||||
return set_mario_action(m, ACT_WALKING, 0)
|
||||
end
|
||||
|
||||
if mario_floor_is_slippery(m) ~= 0 then
|
||||
return set_mario_action(m, ACT_WALKING, 0)
|
||||
end
|
||||
|
||||
if (should_begin_sliding(m)) ~= 0 then
|
||||
return set_mario_action(m, ACT_BEGIN_SLIDING, 0)
|
||||
end
|
||||
|
||||
if (m.input & INPUT_FIRST_PERSON) ~= 0 then
|
||||
m.intendedMag = 0
|
||||
if m.slideVelX == 0 and m.slideVelZ == 0 then
|
||||
return begin_braking_action(m)
|
||||
end
|
||||
end
|
||||
|
||||
if (m.input & INPUT_ZERO_MOVEMENT) ~= 0 and m.slideVelX == 0 and m.slideVelZ == 0 then
|
||||
local oldActTimer = m.actionTimer
|
||||
local result = set_mario_action(m, ACT_SPIT_EGG, 0)
|
||||
m.actionTimer = oldActTimer
|
||||
return result
|
||||
end
|
||||
|
||||
if (m.input & INPUT_Z_PRESSED) ~= 0 then
|
||||
return set_mario_action(m, ACT_CROUCH_SLIDE, 0)
|
||||
end
|
||||
|
||||
-- strafe movement
|
||||
local newVelX = sins(m.intendedYaw) * m.intendedMag
|
||||
local newVelZ = coss(m.intendedYaw) * m.intendedMag
|
||||
m.slideVelX = approach_f32(m.slideVelX, newVelX, 4, 4)
|
||||
m.slideVelZ = approach_f32(m.slideVelZ, newVelZ, 4, 4)
|
||||
m.vel.x, m.vel.z = m.slideVelX, m.slideVelZ
|
||||
m.forwardVel = math.sqrt(m.vel.x ^ 2 + m.vel.z ^ 2)
|
||||
|
||||
if (m.input & INPUT_A_PRESSED) ~= 0 then
|
||||
set_mario_y_vel_based_on_fspeed(m, 42, 0.25)
|
||||
m.slideVelX = m.slideVelX * 0.8
|
||||
m.slideVelZ = m.slideVelZ * 0.8
|
||||
m.vel.x, m.vel.z = m.slideVelX, m.slideVelZ
|
||||
m.forwardVel = m.forwardVel * 0.8
|
||||
local oldActTimer = m.actionTimer
|
||||
local result = set_mario_action(m, ACT_SPIT_EGG_AIR, 1)
|
||||
m.actionTimer = oldActTimer
|
||||
return result
|
||||
end
|
||||
|
||||
local result = (perform_ground_step(m))
|
||||
if result == GROUND_STEP_LEFT_GROUND then
|
||||
m.vel.y = 0
|
||||
local oldActTimer = m.actionTimer
|
||||
set_mario_action(m, ACT_SPIT_EGG_AIR, 0)
|
||||
m.actionTimer = oldActTimer
|
||||
--set_character_animation(m, CHAR_ANIM_GENERAL_FALL)
|
||||
elseif result == GROUND_STEP_NONE then
|
||||
--anim_and_audio_for_walk(m)
|
||||
play_step_sound(m, 10, 49)
|
||||
|
||||
local dYaw = math.s16(m.faceAngle.y - m.intendedYaw)
|
||||
play_custom_anim(m, "BIRDO_ANIM_AIM_WALK", m.forwardVel / 4 * 0x10000)
|
||||
|
||||
mBody.allowPartRotation = true
|
||||
m.marioObj.header.gfx.angle.y = m.intendedYaw
|
||||
local marioAnimInfo = m.marioObj.header.gfx.animInfo
|
||||
if math.abs(dYaw) > 0x4000 then
|
||||
m.marioObj.header.gfx.angle.y = m.intendedYaw - 0x8000
|
||||
marioAnimInfo.animAccel = -math.abs(marioAnimInfo.animAccel)
|
||||
else
|
||||
marioAnimInfo.animAccel = math.abs(marioAnimInfo.animAccel)
|
||||
end
|
||||
|
||||
-- Handle manually the loop points of the animation if moving backwards
|
||||
if marioAnimInfo.animAccel < 0 and marioAnimInfo.animFrame <= marioAnimInfo.curAnim.loopStart then
|
||||
marioAnimInfo.animFrame = marioAnimInfo.curAnim.loopEnd
|
||||
marioAnimInfo.animFrameAccelAssist = marioAnimInfo.animFrame << 16
|
||||
end
|
||||
|
||||
mBody.torsoAngle.y = math.s16(m.faceAngle.y - m.marioObj.header.gfx.angle.y) * 0.4
|
||||
mBody.headAngle.y = m.faceAngle.y - m.marioObj.header.gfx.angle.y - mBody.torsoAngle.y
|
||||
|
||||
if m.intendedMag - m.forwardVel > 16 then
|
||||
set_mario_particle_flags(m, PARTICLE_DUST, 0)
|
||||
end
|
||||
end
|
||||
|
||||
check_ledge_climb_down(m)
|
||||
return 0
|
||||
end
|
||||
|
||||
---@param m MarioState
|
||||
local function act_spit_egg_air(m)
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
|
||||
play_custom_anim(m, "BIRDO_ANIM_AIM_JUMP")
|
||||
if m.actionArg ~= 1 then
|
||||
set_anim_to_frame(m, m.marioObj.header.gfx.animInfo.curAnim.loopEnd)
|
||||
else
|
||||
play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0)
|
||||
end
|
||||
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
|
||||
if (m.input & INPUT_Z_PRESSED) ~= 0 then
|
||||
return set_mario_action(m, ACT_GROUND_POUND, 0)
|
||||
end
|
||||
|
||||
-- air strafe
|
||||
local newVelX = sins(m.intendedYaw) * m.intendedMag
|
||||
local newVelZ = coss(m.intendedYaw) * m.intendedMag
|
||||
m.slideVelX = approach_f32(m.slideVelX, newVelX, 1, 1)
|
||||
m.slideVelZ = approach_f32(m.slideVelZ, newVelZ, 1, 1)
|
||||
m.vel.x, m.vel.z = m.slideVelX, m.slideVelZ
|
||||
m.forwardVel = m.slideVelX * sins(m.faceAngle.y) + m.slideVelZ * coss(m.faceAngle.y)
|
||||
--local absSpeed = math.max(math.abs(m.slideVelX), math.abs(m.slideVelZ))
|
||||
|
||||
local result = (perform_air_step(m, 0))
|
||||
if result == AIR_STEP_LANDED then
|
||||
if check_fall_damage_or_get_stuck(m, ACT_HARD_BACKWARD_GROUND_KB) ~= 0 then
|
||||
return 1
|
||||
elseif e.birdo.flameCharge == 0 and e.birdo.framesSinceShoot > 10 then
|
||||
set_mario_action(m, ACT_FREEFALL_LAND, 0)
|
||||
else
|
||||
local oldActTimer = m.actionTimer
|
||||
set_mario_action(m, ACT_SPIT_EGG_WALK, 0)
|
||||
m.actionTimer = oldActTimer
|
||||
end
|
||||
return 1
|
||||
elseif result == AIR_STEP_HIT_WALL then
|
||||
mario_set_forward_vel(m, 0)
|
||||
elseif result == AIR_STEP_HIT_LAVA_WALL then
|
||||
lava_boost_on_wall(m)
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
-- Egg
|
||||
|
||||
local eggIntObjLists = {
|
||||
OBJ_LIST_GENACTOR,
|
||||
OBJ_LIST_PUSHABLE,
|
||||
OBJ_LIST_SURFACE,
|
||||
OBJ_LIST_PLAYER,
|
||||
}
|
||||
|
||||
E_MODEL_EGG = smlua_model_util_get_id("egg_geo")
|
||||
---@param o Object
|
||||
function bhv_birdo_egg_init(o)
|
||||
o.oFlags = (OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE | OBJ_FLAG_SET_FACE_YAW_TO_MOVE_YAW | OBJ_FLAG_HOLDABLE | OBJ_FLAG_COMPUTE_DIST_TO_MARIO)
|
||||
o.oFaceAngleRoll = 0
|
||||
o.oMoveAngleRoll = 0
|
||||
o.oGravity = 0
|
||||
o.oBounciness = 0
|
||||
o.oFriction = 1
|
||||
o.oDragStrength = 0
|
||||
o.oBuoyancy = 0
|
||||
o.oWallHitboxRadius = 60
|
||||
o.oVelY = 0
|
||||
|
||||
o.collisionData = smlua_collision_util_get("egg_collision")
|
||||
|
||||
local hitbox = get_temp_object_hitbox()
|
||||
hitbox.interactType = INTERACT_DAMAGE
|
||||
hitbox.hurtboxRadius = 60
|
||||
hitbox.hurtboxHeight = 80
|
||||
hitbox.downOffset = 80
|
||||
hitbox.radius = 60
|
||||
hitbox.height = 80
|
||||
hitbox.damageOrCoinValue = 1
|
||||
if o.oBehParams ~= 0 then
|
||||
-- similar hitbox to fire spitter flames
|
||||
hitbox.interactType = INTERACT_FLAME
|
||||
hitbox.radius = 10
|
||||
hitbox.height = 40
|
||||
hitbox.hurtboxRadius = 10
|
||||
hitbox.hurtboxHeight = 40
|
||||
hitbox.downOffset = 30
|
||||
obj_set_billboard(o)
|
||||
o.header.gfx.scale.x = 3
|
||||
o.header.gfx.scale.y = 3
|
||||
o.header.gfx.scale.z = 3
|
||||
end
|
||||
obj_set_hitbox(o, hitbox)
|
||||
o.oIntangibleTimer = 10
|
||||
|
||||
-- do manual shadow, otherwise the shadow renders on top of itself
|
||||
o.header.gfx.disableAutomaticShadowPos = true
|
||||
o.header.gfx.shadowPos.x = o.oPosX
|
||||
o.header.gfx.shadowPos.y = o.oPosY - 50
|
||||
o.header.gfx.shadowPos.z = o.oPosZ
|
||||
|
||||
network_init_object(o, true, { 'globalPlayerIndex' })
|
||||
end
|
||||
|
||||
---@param o Object
|
||||
function bhv_birdo_egg_loop(o)
|
||||
if o.oBehParams ~= 0 then
|
||||
o.oAnimState = o.oAnimState + 1
|
||||
end
|
||||
|
||||
if o.oHeldState == HELD_FREE then
|
||||
cur_obj_enable_rendering()
|
||||
if o.oAction == 0 then
|
||||
o.oGravity = 0
|
||||
else
|
||||
o.oMoveAnglePitch = 0
|
||||
o.oFaceAnglePitch = 0
|
||||
o.oGravity = -2
|
||||
end
|
||||
|
||||
cur_obj_update_floor_and_walls()
|
||||
local oldForwardVel = o.oForwardVel
|
||||
if o.oAction == 0 then
|
||||
obj_compute_vel_from_move_pitch(o.oForwardVel)
|
||||
end
|
||||
cur_obj_move_standard(60)
|
||||
o.oForwardVel = oldForwardVel
|
||||
|
||||
local defaultVel = 20
|
||||
if o.oBehParams ~= 0 then
|
||||
defaultVel = 40
|
||||
end
|
||||
if o.oAction == 0 and o.oForwardVel > defaultVel then
|
||||
o.oForwardVel = approach_f32(o.oForwardVel, defaultVel, 3, 3)
|
||||
end
|
||||
|
||||
-- manual object collision
|
||||
local dieFromCollision = false
|
||||
o.numCollidedObjs = obj_attack_collided_from_other_object(o)
|
||||
if o.numCollidedObjs ~= 0 and o.oBehParams == 0 then
|
||||
dieFromCollision = true
|
||||
end
|
||||
if o.oDistanceToMario < 2000 then
|
||||
for _, list in ipairs(eggIntObjLists) do
|
||||
local o2 = obj_get_first(list)
|
||||
while o2 and o.numCollidedObjs < 4 do
|
||||
if o ~= o2 then
|
||||
if list ~= OBJ_LIST_PLAYER and o2.oHeldState == HELD_FREE and detect_object_hitbox_overlap(o, o2) ~= 0 then
|
||||
o2.numCollidedObjs = o2.numCollidedObjs - 1 -- prevent game crash
|
||||
local doEggInteract = birdo_egg_interaction(o2, o)
|
||||
if o.oBehParams == 0 or doEggInteract then
|
||||
dieFromCollision = true
|
||||
end
|
||||
if doEggInteract or o2.oInteractType == INTERACT_BREAKABLE or obj_is_attackable(o2) then
|
||||
if obj_has_behavior_id(o2, id_bhvBowser) == 0 then
|
||||
o2.oInteractStatus = o2.oInteractStatus | ATTACK_PUNCH | INT_STATUS_WAS_ATTACKED |
|
||||
INT_STATUS_INTERACTED | INT_STATUS_TOUCHED_BOB_OMB
|
||||
end
|
||||
end
|
||||
elseif o.oBehParams ~= 0 and birdo_fire_is_targettable(o2, o) and dist_between_objects(o2, o) <= 700 then
|
||||
local angleToObject = obj_angle_to_object(o, o2)
|
||||
if abs_angle_diff(o.oMoveAngleYaw, angleToObject) <= 0x4000 then
|
||||
cur_obj_rotate_yaw_toward(angleToObject, 0x200)
|
||||
end
|
||||
end
|
||||
end
|
||||
o2 = obj_get_next(o2)
|
||||
end
|
||||
if o.numCollidedObjs >= 4 then break end
|
||||
end
|
||||
end
|
||||
|
||||
-- surface collision
|
||||
if o.oAction == 0 and o.oBehParams == 0 and o.oMoveFlags & OBJ_MOVE_MASK_IN_WATER == 0 then
|
||||
local m0 = gMarioStates[0]
|
||||
load_object_collision_model()
|
||||
if cur_obj_is_mario_on_platform() ~= 0 then
|
||||
if (m0.action == ACT_PUNCHING or m0.action == ACT_MOVE_PUNCHING) then
|
||||
-- pick up egg
|
||||
m0.heldObj = o
|
||||
m0.marioBodyState.grabPos = GRAB_POS_LIGHT_OBJ
|
||||
o.heldByPlayerIndex = 0
|
||||
o.oHeldState = HELD_HELD
|
||||
set_mario_action(m0, ACT_HOLD_FREEFALL, 0)
|
||||
if (o.oSyncID ~= 0) then network_send_object(o, false) end
|
||||
elseif (m0.prevAction & ACT_FLAG_AIR) ~= 0 then -- prevent falling off of egg easily
|
||||
m0.pos.x = o.oPosX
|
||||
m0.pos.z = o.oPosZ
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if dieFromCollision or o.oMoveFlags & (OBJ_MOVE_HIT_WALL | OBJ_MOVE_UNDERWATER_ON_GROUND | OBJ_MOVE_MASK_ON_GROUND) ~= 0 or o.oTimer > 120 then
|
||||
o.numCollidedObjs = 0
|
||||
spawn_mist_particles()
|
||||
obj_mark_for_deletion(o)
|
||||
end
|
||||
o.oInteractStatus = 0
|
||||
o.numCollidedObjs = 0
|
||||
elseif o.oHeldState == HELD_HELD then
|
||||
o.oFaceAnglePitch = 0
|
||||
o.oMoveAnglePitch = 0
|
||||
o.oInteractType = INTERACT_GRABBABLE
|
||||
cur_obj_disable_rendering_and_become_intangible(o)
|
||||
elseif o.oHeldState == HELD_THROWN then
|
||||
o.oFaceAnglePitch = 0
|
||||
o.oMoveAnglePitch = 0
|
||||
o.oInteractType = INTERACT_DAMAGE
|
||||
cur_obj_enable_rendering_and_become_tangible(o)
|
||||
cur_obj_change_action(1)
|
||||
local m = gMarioStates[o.heldByPlayerIndex]
|
||||
o.oForwardVel = math.max(m.forwardVel + 15, 40)
|
||||
o.oVelY = 10
|
||||
o.oTimer = 0
|
||||
o.oHeldState = HELD_FREE
|
||||
o.oIntangibleTimer = 10
|
||||
elseif o.oHeldState == HELD_DROPPED then
|
||||
spawn_mist_particles()
|
||||
obj_mark_for_deletion(o)
|
||||
end
|
||||
|
||||
-- do manual shadow, otherwise the shadow renders on top of itself
|
||||
if o.activeFlags ~= ACTIVE_FLAG_DEACTIVATED then
|
||||
o.header.gfx.disableAutomaticShadowPos = true
|
||||
o.header.gfx.shadowPos.x = o.oPosX
|
||||
o.header.gfx.shadowPos.y = o.oPosY - 50
|
||||
o.header.gfx.shadowPos.z = o.oPosZ
|
||||
else
|
||||
o.header.gfx.disableAutomaticShadowPos = false
|
||||
end
|
||||
end
|
||||
|
||||
-- lua recreation
|
||||
---@param a Object
|
||||
---@param b Object
|
||||
function detect_object_hitbox_overlap(a, b)
|
||||
if not (a and b) then return 0 end
|
||||
local sp3C = a.oPosY - a.hitboxDownOffset
|
||||
local sp38 = b.oPosY - b.hitboxDownOffset
|
||||
local dx = a.oPosX - b.oPosX
|
||||
local dz = a.oPosZ - b.oPosZ
|
||||
local collisionRadius = a.hitboxRadius + b.hitboxRadius
|
||||
local distance = math.floor(math.sqrt(dx * dx + dz * dz))
|
||||
|
||||
-- do not check for player interactions here
|
||||
if ((a.oInteractType & INTERACT_PLAYER) ~= 0 and (b.oInteractType & INTERACT_PLAYER) ~= 0) then
|
||||
return 0
|
||||
end
|
||||
|
||||
if (collisionRadius > distance) then
|
||||
local sp20 = a.hitboxHeight + sp3C
|
||||
local sp1C = b.hitboxHeight + sp38
|
||||
|
||||
if (sp3C > sp1C) then
|
||||
return 0
|
||||
end
|
||||
if (sp20 < sp38) then
|
||||
return 0
|
||||
end
|
||||
if (a.numCollidedObjs >= 4) then
|
||||
return 0
|
||||
end
|
||||
if (b.numCollidedObjs >= 4) then
|
||||
return 0
|
||||
end
|
||||
-- can't reference these fields in lua
|
||||
--a.collidedObjs[a.numCollidedObjs] = b
|
||||
--b.collidedObjs[b.numCollidedObjs] = a
|
||||
a.collidedObjInteractTypes = a.collidedObjInteractTypes | b.oInteractType
|
||||
b.collidedObjInteractTypes = b.collidedObjInteractTypes | a.oInteractType
|
||||
a.numCollidedObjs = a.numCollidedObjs + 1
|
||||
b.numCollidedObjs = b.numCollidedObjs + 1
|
||||
return 1
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
id_bhvBirdoEgg = hook_behavior(nil, OBJ_LIST_SURFACE, true, bhv_birdo_egg_init, bhv_birdo_egg_loop, "bhvBirdoEgg")
|
||||
|
||||
---@param m MarioState
|
||||
function birdo_update(m)
|
||||
-- spit egg
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
local inSpitAction = (m.action == ACT_SPIT_EGG or m.action == ACT_SPIT_EGG_WALK or m.action == ACT_SPIT_EGG_AIR or m.action == ACT_FIRST_PERSON or m.action == ACT_WATER_PUNCH or m.action == ACT_FLYING)
|
||||
local headRot = m.marioBodyState.headAngle
|
||||
|
||||
if m.controller.buttonPressed & B_BUTTON ~= 0 and inSpitAction then
|
||||
-- when mashing B, stay in spit action
|
||||
e.birdo.framesSinceShoot = 0
|
||||
if e.birdo.spitTimer == 0 then
|
||||
e.birdo.flameCharge = 0
|
||||
end
|
||||
else
|
||||
-- handle shooting repeatedly/charging
|
||||
if e.birdo.framesSinceShoot ~= 255 then
|
||||
e.birdo.framesSinceShoot = e.birdo.framesSinceShoot + 1
|
||||
end
|
||||
if m.controller.buttonDown & B_BUTTON ~= 0 then
|
||||
if inSpitAction then
|
||||
e.birdo.flameCharge = e.birdo.flameCharge + 1
|
||||
end
|
||||
elseif e.birdo.spitTimer < 25 then
|
||||
if e.birdo.flameCharge >= 30 then
|
||||
e.birdo.framesSinceShoot = 0 -- shoot fireball
|
||||
else
|
||||
e.birdo.flameCharge = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (e.birdo.framesSinceShoot <= 10 or e.birdo.flameCharge ~= 0) and not m.heldObj and inSpitAction then
|
||||
local canShoot = true
|
||||
local eggCount = 0
|
||||
local gIndex = network_global_index_from_local(m.playerIndex)
|
||||
local egg = obj_get_first_with_behavior_id(id_bhvBirdoEgg)
|
||||
while egg do
|
||||
if egg.oAction == 0 and egg.oHeldState == HELD_FREE and egg.globalPlayerIndex == gIndex then
|
||||
eggCount = eggCount + 1
|
||||
if eggCount >= 3 then -- max of 3 eggs/fireballs per player
|
||||
canShoot = false
|
||||
break
|
||||
end
|
||||
end
|
||||
egg = obj_get_next_with_same_behavior_id(egg)
|
||||
end
|
||||
|
||||
if e.birdo.spitTimer ~= 0 then
|
||||
e.birdo.spitTimer = e.birdo.spitTimer - 1
|
||||
m.marioBodyState.allowPartRotation = true
|
||||
if e.birdo.spitTimer > 24 then
|
||||
headRot.x = approach_f32(headRot.x, degrees_to_sm64(-30), degrees_to_sm64(10), degrees_to_sm64(10))
|
||||
else
|
||||
headRot.x = approach_f32(headRot.x, degrees_to_sm64(0), degrees_to_sm64(3.5), degrees_to_sm64(3.5))
|
||||
end
|
||||
end
|
||||
if e.birdo.spitTimer == 0 and canShoot and e.birdo.framesSinceShoot <= 10 then
|
||||
m.actionTimer = 0
|
||||
m.actionArg = 0
|
||||
end
|
||||
|
||||
local mouthPos = gVec3fZero()
|
||||
local yaw = m.faceAngle.y
|
||||
local pitch = 0
|
||||
if canShoot then
|
||||
-- when swimming, flying, or in first person, allow shooting in any direction
|
||||
if m.action == ACT_FIRST_PERSON then
|
||||
yaw = m.statusForCamera.headRotation.y + yaw
|
||||
pitch = m.statusForCamera.headRotation.x
|
||||
mouthPos.x = m.pos.x + sins(yaw) * 60 * coss(pitch)
|
||||
mouthPos.y = m.pos.y + 120 - sins(pitch) * 120
|
||||
mouthPos.z = m.pos.z + coss(yaw) * 60 * coss(pitch)
|
||||
elseif m.action & ACT_FLAG_SWIMMING_OR_FLYING ~= 0 then
|
||||
pitch = -m.faceAngle.x
|
||||
if pitch < 0 then
|
||||
mouthPos.x = m.pos.x + sins(yaw) * 80 * coss(pitch)
|
||||
mouthPos.y = m.pos.y + 120
|
||||
mouthPos.z = m.pos.z + coss(yaw) * 80 * coss(pitch)
|
||||
else
|
||||
mouthPos.x = m.pos.x + sins(yaw) * 80
|
||||
mouthPos.y = m.pos.y + 120 - sins(pitch) * 150
|
||||
mouthPos.z = m.pos.z + coss(yaw) * 80
|
||||
end
|
||||
else
|
||||
mouthPos.x = m.marioBodyState.headPos.x + sins(yaw + m.marioBodyState.headAngle.y) * 60
|
||||
mouthPos.y = m.marioBodyState.headPos.y + 20
|
||||
mouthPos.z = m.marioBodyState.headPos.z + coss(yaw + m.marioBodyState.headAngle.y) * 60
|
||||
end
|
||||
end
|
||||
|
||||
if canShoot and e.birdo.spitTimer == 0 and e.birdo.flameCharge >= 30 and m.action & ACT_FLAG_SWIMMING == 0 then
|
||||
spawn_non_sync_object(id_bhvKoopaShellFlame, E_MODEL_RED_FLAME,
|
||||
mouthPos.x,
|
||||
mouthPos.y,
|
||||
mouthPos.z,
|
||||
function(o)
|
||||
o.oKoopaShellFlameUnkF8 = 2
|
||||
o.oMoveAngleYaw = math.random(0, 0xFFFF)
|
||||
o.oVelY = math.random(10)
|
||||
o.oAnimState = math.random(10)
|
||||
o.oGravity = -4.0
|
||||
o.oTimer = 1
|
||||
o.oForwardVel = math.random(10)
|
||||
end)
|
||||
play_sound(SOUND_AIR_BLOW_FIRE, m.marioObj.header.gfx.cameraToObject)
|
||||
end
|
||||
|
||||
if canShoot and e.birdo.spitTimer == 0 and e.birdo.framesSinceShoot <= 10 then
|
||||
e.birdo.spitTimer = 30
|
||||
elseif e.birdo.spitTimer == 25 then
|
||||
local model = E_MODEL_EGG
|
||||
local isFireball = (e.birdo.flameCharge >= 30)
|
||||
if isFireball then
|
||||
model = E_MODEL_RED_FLAME
|
||||
e.birdo.flameCharge = 0
|
||||
end
|
||||
|
||||
if not isFireball then
|
||||
audio_sample_play(SOUND_SPIT, m.pos, 1) -- Play audio sample
|
||||
else
|
||||
play_sound(SOUND_AIR_BOWSER_SPIT_FIRE, m.marioObj.header.gfx.cameraToObject)
|
||||
end
|
||||
|
||||
if m.playerIndex == 0 then
|
||||
local eggVel = m.forwardVel * 2 + 25
|
||||
-- add double floor velocity to prevent being able to platform on eggs forever
|
||||
if m.floor and m.floor.object and m.floor.object.oForwardVel ~= 0 then
|
||||
eggVel = eggVel + m.floor.object.oForwardVel * 2
|
||||
end
|
||||
spawn_sync_object(id_bhvBirdoEgg, model, mouthPos.x + sins(yaw) * 40 * coss(pitch), mouthPos.y,
|
||||
mouthPos.z + coss(yaw) * 40 * coss(pitch), function(o)
|
||||
o.oForwardVel = math.max(eggVel, 40)
|
||||
o.oMoveAngleYaw = yaw
|
||||
o.oFaceAnglePitch = pitch
|
||||
o.oMoveAnglePitch = pitch
|
||||
o.oIntangibleTimer = 100
|
||||
o.globalPlayerIndex = gIndex
|
||||
o.oBehParams = (isFireball and 1) or 0
|
||||
spawn_mist_particles_variable(20, 120, 5)
|
||||
end)
|
||||
end
|
||||
end
|
||||
elseif e.birdo.spitTimer ~= 0 then
|
||||
e.birdo.spitTimer = e.birdo.spitTimer - 1
|
||||
m.marioBodyState.allowPartRotation = true
|
||||
if e.birdo.spitTimer > 24 then
|
||||
headRot.x = approach_f32(headRot.x, degrees_to_sm64(-30), degrees_to_sm64(10), degrees_to_sm64(10))
|
||||
else
|
||||
headRot.x = approach_f32(headRot.x, degrees_to_sm64(0), degrees_to_sm64(3.5), degrees_to_sm64(3.5))
|
||||
end
|
||||
end
|
||||
|
||||
-- throw objects instantly
|
||||
if m.action == ACT_THROWING then
|
||||
if m.actionTimer < 6 then
|
||||
m.actionTimer = 6
|
||||
set_anim_to_frame(m, 6)
|
||||
end
|
||||
elseif m.action == ACT_AIR_THROW or m.action == ACT_AIR_THROW_LAND then
|
||||
if m.actionTimer < 3 then
|
||||
m.actionTimer = 3
|
||||
set_anim_to_frame(m, 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function birdo_on_set_action(m)
|
||||
if m.action ~= ACT_SPIT_EGG and m.action ~= ACT_SPIT_EGG_WALK and m.action ~= ACT_SPIT_EGG_AIR then
|
||||
gCharacterStates[m.playerIndex].birdo.spitTimer = 0
|
||||
end
|
||||
if m.action == ACT_HOLD_WALKING then -- switch to custom hold action
|
||||
set_mario_action(m, ACT_BIRDO_HOLD_WALKING, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local shootActs = {
|
||||
[ACT_PUNCHING] = ACT_SPIT_EGG,
|
||||
[ACT_MOVE_PUNCHING] = ACT_SPIT_EGG_WALK,
|
||||
[ACT_JUMP_KICK] = ACT_SPIT_EGG_AIR,
|
||||
}
|
||||
|
||||
function birdo_before_action(m, action, actionArg)
|
||||
if m.playerIndex ~= 0 then return end
|
||||
if shootActs[action] and m.controller.buttonDown & A_BUTTON == 0 then
|
||||
if action == ACT_PUNCHING and actionArg == 9 then return end
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
e.birdo.framesSinceShoot = 0
|
||||
if e.birdo.spitTimer == 0 then
|
||||
e.birdo.flameCharge = 0
|
||||
end
|
||||
|
||||
local canShoot = true
|
||||
local eggCount = 0
|
||||
local gIndex = network_global_index_from_local(m.playerIndex)
|
||||
local egg = obj_get_first_with_behavior_id(id_bhvBirdoEgg)
|
||||
while egg do
|
||||
if egg.oAction == 0 and egg.oHeldState == HELD_FREE and egg.globalPlayerIndex == gIndex then
|
||||
eggCount = eggCount + 1
|
||||
if eggCount >= 3 then -- max of 3 eggs/fireballs per player
|
||||
canShoot = false
|
||||
break
|
||||
end
|
||||
end
|
||||
egg = obj_get_next_with_same_behavior_id(egg)
|
||||
end
|
||||
|
||||
if m.action ~= ACT_SPIT_EGG or e.birdo.spitTimer == 0 or canShoot then
|
||||
m.marioObj.header.gfx.animInfo.animFrame = 0
|
||||
return shootActs[action]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function birdo_on_interact(m, o, intType)
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
if intType == INTERACT_GRABBABLE and e.birdo.framesSinceShoot == 0 and e.birdo.flameCharge == 0 and (m.action == ACT_SPIT_EGG or m.action == ACT_SPIT_EGG_WALK) and o.oInteractionSubtype & INT_SUBTYPE_NOT_GRABBABLE == 0 then
|
||||
set_mario_action(m, ACT_MOVE_PUNCHING, 1)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function birdo_before_phys_step(m)
|
||||
local hScale = 1.0
|
||||
local vScale = 1.0
|
||||
|
||||
-- faster ground movement and slower, floaty air movement
|
||||
if (m.action & ACT_FLAG_MOVING) ~= 0 and m.action ~= ACT_BUBBLED then
|
||||
hScale = hScale * 1.12 -- not as fast as toad
|
||||
elseif m.action & ACT_FLAG_AIR ~= 0 then
|
||||
hScale = hScale * 0.94
|
||||
if m.vel.y < 0 then
|
||||
vScale = vScale * 0.98
|
||||
end
|
||||
end
|
||||
|
||||
m.vel.x = m.vel.x * hScale
|
||||
m.vel.y = m.vel.y * vScale
|
||||
m.vel.z = m.vel.z * hScale
|
||||
end
|
||||
|
||||
-- allow shooting in first person
|
||||
function birdo_before_update(m)
|
||||
if m.action == ACT_FIRST_PERSON and m.controller.buttonPressed & B_BUTTON ~= 0 then
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
e.birdo.framesSinceShoot = 0
|
||||
if e.birdo.spitTimer == 0 then
|
||||
e.birdo.flameCharge = 0
|
||||
end
|
||||
m.controller.buttonPressed = m.controller.buttonPressed & ~B_BUTTON
|
||||
end
|
||||
end
|
||||
|
||||
-- interactions for birdo's egg/fireball
|
||||
function birdo_egg_interaction(o, egg)
|
||||
if egg.oBehParams ~= 0 and obj_has_behavior_id(o, id_bhvMrBlizzard) ~= 0 then
|
||||
o.oFaceAngleRoll = 0x3000
|
||||
o.oMrBlizzardHeldObj = nil
|
||||
o.prevObj = o.oMrBlizzardHeldObj
|
||||
o.oAction = MR_BLIZZARD_ACT_DEATH
|
||||
o.oMrBlizzardDizziness = 0
|
||||
o.oMrBlizzardChangeInDizziness = 0
|
||||
o.oTimer = 30
|
||||
return true
|
||||
end
|
||||
|
||||
if egg.oBehParams ~= 0 and obj_has_behavior_id(o, id_bhvBowser) ~= 0 then
|
||||
if o.oAction ~= 4 and o.oAction ~= 5 and o.oAction ~= 6 and o.oAction ~= 12 and o.oAction ~= 19 and o.oAction ~= 20 and math.abs(o.oVelY) <= 2 then
|
||||
o.oAction = 1
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
if o.oInteractType == INTERACT_BULLY then
|
||||
o.oBullyLastNetworkPlayerIndex = egg.globalPlayerIndex
|
||||
o.oForwardVel = (egg.oBehParams ~= 0 and 50) or 25
|
||||
o.oMoveAngleYaw = egg.oMoveAngleYaw
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- prevent player interaction with Birdo's egg if player interaction is not pvp (owner still interacts)
|
||||
---@param m MarioState
|
||||
---@param o Object
|
||||
---@param type integer
|
||||
function player_egg_allow_interact(m, o, type)
|
||||
if obj_has_behavior_id(o, id_bhvBirdoEgg) ~= 0 then
|
||||
local m2 = gMarioStates[network_local_index_from_global(o.globalPlayerIndex)]
|
||||
if m.playerIndex ~= m2.playerIndex and gServerSettings.playerInteractions ~= PLAYER_INTERACTIONS_PVP then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
hook_event(HOOK_ALLOW_INTERACT, player_egg_allow_interact)
|
||||
|
||||
-- returns true if this object can be hit by birdo's fireball
|
||||
function birdo_fire_is_targettable(o, egg)
|
||||
if o.oInteractType == INTERACT_PLAYER then
|
||||
local m = gMarioStates[o.oBehParams - 1]
|
||||
if (not m) or is_player_active(m) == 0 then return false end
|
||||
local gIndex = network_global_index_from_local(m.playerIndex)
|
||||
return (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_PVP) and (egg.globalPlayerIndex ~= gIndex)
|
||||
end
|
||||
|
||||
return (obj_has_behavior_id(o, id_bhvMrBlizzard) ~= 0 or obj_has_behavior_id(o, id_bhvBowser) ~= 0
|
||||
or o.oInteractType == INTERACT_BULLY or o.oInteractType == INTERACT_BREAKABLE or obj_is_attackable(o))
|
||||
end
|
||||
|
||||
hook_mario_action(ACT_BIRDO_HOLD_WALKING, act_birdo_hold_walking)
|
||||
hook_mario_action(ACT_SPIT_EGG, act_spit_egg)
|
||||
hook_mario_action(ACT_SPIT_EGG_AIR, act_spit_egg_air)
|
||||
hook_mario_action(ACT_SPIT_EGG_WALK, act_spit_egg_walk)
|
||||
|
||||
-- Fix object shadows getting messed up. Base coop bug
|
||||
---@param o Object
|
||||
function on_obj_load(o)
|
||||
o.header.gfx.disableAutomaticShadowPos = false
|
||||
o.header.gfx.shadowInvisible = false
|
||||
end
|
||||
hook_event(HOOK_ON_OBJECT_LOAD, on_obj_load)
|
||||
55
mods/char-select-extra-chars-plus/moveset-daisy.lua
Normal file
55
mods/char-select-extra-chars-plus/moveset-daisy.lua
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
-------------------
|
||||
-- Daisy Moveset --
|
||||
-------------------
|
||||
|
||||
if not charSelect then return end
|
||||
|
||||
local midairJumpActs = {
|
||||
[ACT_JUMP] = true,
|
||||
[ACT_DOUBLE_JUMP] = true,
|
||||
[ACT_TRIPLE_JUMP] = true,
|
||||
[ACT_LONG_JUMP] = true,
|
||||
[ACT_BACKFLIP] = true,
|
||||
[ACT_SIDE_FLIP] = true,
|
||||
[ACT_WALL_KICK_AIR] = true,
|
||||
}
|
||||
|
||||
_G.ACT_MIDAIR_JUMP = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_MOVING)
|
||||
|
||||
--- @param m MarioState
|
||||
local function act_midair_jump(m)
|
||||
-- apply movement when using action
|
||||
common_air_action_step(m, ACT_JUMP_LAND, CHAR_ANIM_BEND_KNESS_RIDING_SHELL, AIR_STEP_NONE)
|
||||
|
||||
-- setup when action starts (vertical speed and voiceline)
|
||||
if m.actionTimer == 0 then
|
||||
m.vel.y = m.forwardVel * 0.3 + 40
|
||||
m.forwardVel = m.forwardVel * 0.7
|
||||
play_character_sound(m, CHAR_SOUND_HELLO)
|
||||
end
|
||||
|
||||
set_mario_particle_flags(m, PARTICLE_LEAF, 0)
|
||||
|
||||
-- avoid issue with flying and then make the hover end after 2 secs or when stopping holding the button
|
||||
if m.prevAction ~= ACT_TRIPLE_JUMP and (m.flags & MARIO_WING_CAP) ~= 0 then
|
||||
if m.actionTimer >= 10 or (m.controller.buttonDown & A_BUTTON) == 0 then
|
||||
set_mario_action(m, ACT_FREEFALL, 0)
|
||||
end
|
||||
else
|
||||
if m.actionTimer >= 10 or (m.controller.buttonDown & A_BUTTON) == 0 then
|
||||
set_mario_action(m, ACT_FREEFALL, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- increment the action timer to make the hover stop
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
end
|
||||
|
||||
--- @param m MarioState
|
||||
function daisy_update(m)
|
||||
if (m.input & INPUT_A_PRESSED) ~= 0 and m.vel.y < 10 and m.prevAction ~= ACT_MIDAIR_JUMP and midairJumpActs[m.action] then
|
||||
set_mario_action(m, ACT_MIDAIR_JUMP, 0)
|
||||
end
|
||||
end
|
||||
|
||||
hook_mario_action(ACT_MIDAIR_JUMP, act_midair_jump)
|
||||
955
mods/char-select-extra-chars-plus/moveset-donkey-kong.lua
Normal file
955
mods/char-select-extra-chars-plus/moveset-donkey-kong.lua
Normal file
|
|
@ -0,0 +1,955 @@
|
|||
-------------------------
|
||||
-- Donkey Kong Moveset --
|
||||
-------------------------
|
||||
|
||||
if not charSelect then return end
|
||||
|
||||
local DONKEY_KONG_ROLL_SPEED = 60
|
||||
local DONKEY_KONG_ROLL_DECAY_PERCENT = 0.98
|
||||
local DONKEY_KONG_ROLL_DECAY_TIME = 10
|
||||
local DONKEY_KONG_ROLL_STARTUP = 4
|
||||
local DONKEY_KONG_ROLL_END = 25
|
||||
local DONKEY_KONG_SLIP_TIME = 20
|
||||
local DONKEY_KONG_SLIDE_TIME = 40
|
||||
|
||||
----------------
|
||||
-- DK Gravity --
|
||||
----------------
|
||||
|
||||
--- @param m MarioState
|
||||
--- @param wall Surface
|
||||
--- @param intendedPos Vec3f
|
||||
--- @param nextPos Vec3f
|
||||
--- @return integer
|
||||
--- Checks ledge grab for donkey kong
|
||||
local function donkey_kong_check_ledge_grab(m, wall, intendedPos, nextPos)
|
||||
if not m then return 0 end
|
||||
local ledgeFloor
|
||||
local ledgePos = gVec3fZero()
|
||||
local displacementX
|
||||
local displacementZ
|
||||
|
||||
if m.vel.y > 0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
displacementX = nextPos.x - intendedPos.x
|
||||
displacementZ = nextPos.z - intendedPos.z
|
||||
|
||||
-- Only ledge grab if the wall displaced Mario in the opposite direction of
|
||||
-- his velocity.
|
||||
if displacementX * m.vel.x + displacementZ * m.vel.z > 0.0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
--! Since the search for floors starts at y + m.marioObj.hitboxHeight (160.0f), we will sometimes grab
|
||||
-- a higher ledge than expected (glitchy ledge grab)
|
||||
ledgePos.x = nextPos.x - wall.normal.x * 60.0
|
||||
ledgePos.z = nextPos.z - wall.normal.z * 60.0
|
||||
ledgePos.y, ledgeFloor = find_floor(ledgePos.x, nextPos.y + m.marioObj.hitboxHeight, ledgePos.z)
|
||||
if not ledgeFloor then return 0 end
|
||||
|
||||
if gLevelValues.fixCollisionBugs ~= 0 and gLevelValues.fixCollisionBugsFalseLedgeGrab ~= 0 then
|
||||
-- fix false ledge grabs
|
||||
if (not ledgeFloor or ledgeFloor.normal.y < 0.90630779) then
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
if ledgePos.y - nextPos.y <= 100.0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
vec3f_copy(m.pos, ledgePos)
|
||||
m.floor = ledgeFloor
|
||||
m.floorHeight = ledgePos.y
|
||||
|
||||
m.floorAngle = atan2s(ledgeFloor.normal.z, ledgeFloor.normal.x)
|
||||
|
||||
m.faceAngle.x = 0
|
||||
m.faceAngle.y = atan2s(wall.normal.z, wall.normal.x) + 0x8000
|
||||
return 1
|
||||
end
|
||||
|
||||
--- Turns a WallCollisionData object into a table
|
||||
--- @param wcd WallCollisionData
|
||||
--- @return table
|
||||
local function wcd_to_table(wcd)
|
||||
return {
|
||||
x = wcd.x, -- number
|
||||
y = wcd.y, -- number
|
||||
z = wcd.z, -- number
|
||||
offsetY = wcd.offsetY, -- number
|
||||
radius = wcd.radius, -- number
|
||||
unused = wcd.unused, -- integer
|
||||
numWalls = wcd.numWalls, -- integer
|
||||
walls = {
|
||||
wcd.walls[1],
|
||||
wcd.walls[2],
|
||||
wcd.walls[3],
|
||||
wcd.walls[4]
|
||||
} , -- Surface[]
|
||||
normalAddition = {
|
||||
x = wcd.normalAddition.x,
|
||||
y = wcd.normalAddition.y,
|
||||
z = wcd.normalAddition.z,
|
||||
}, -- Vec3f
|
||||
normalCount = wcd.normalCount, -- integer
|
||||
}
|
||||
end
|
||||
|
||||
--- Fills a WallCollisionData object from a table
|
||||
--- @param wcd WallCollisionData
|
||||
--- @param t table
|
||||
local function table_to_wcd(wcd, t)
|
||||
wcd.x = t.x
|
||||
wcd.y = t.y
|
||||
wcd.z = t.z
|
||||
wcd.offsetY = t.offsetY
|
||||
wcd.radius = t.radius
|
||||
wcd.unused = t.unused
|
||||
wcd.numWalls = t.numWalls
|
||||
wcd.walls[1] = t.walls[1]
|
||||
wcd.walls[2] = t.walls[2]
|
||||
wcd.walls[3] = t.walls[3]
|
||||
wcd.walls[4] = t.walls[4]
|
||||
wcd.normalAddition.x = t.normalAddition.x
|
||||
wcd.normalAddition.y = t.normalAddition.y
|
||||
wcd.normalAddition.z = t.normalAddition.z
|
||||
wcd.normalCount = t.normalCount
|
||||
end
|
||||
|
||||
--- @param m MarioState
|
||||
--- @param intendedPos Vec3f
|
||||
--- @param stepArg integer
|
||||
--- @return integer
|
||||
--- Performs an air quarter step for donkey kong
|
||||
local function perform_donkey_kong_air_quarter_step(m, intendedPos, stepArg)
|
||||
if not m then return 0 end
|
||||
local wallDYaw
|
||||
local nextPos = gVec3fZero()
|
||||
local ceil
|
||||
local floor
|
||||
local ceilHeight
|
||||
local floorHeight
|
||||
local waterLevel
|
||||
local tempWcd
|
||||
|
||||
vec3f_copy(nextPos, intendedPos)
|
||||
|
||||
-- Important note:
|
||||
-- The WallCollisionData pointer is always the same, meaning it cannot be used for both upperWcd and lowerWcd
|
||||
-- Fortunately, it's read-write, so we can turn it into a table for the Lua part of the function and
|
||||
-- turn it back into a WallCollisionData object for the C function calls
|
||||
|
||||
tempWcd = collision_get_temp_wall_collision_data()
|
||||
resolve_and_return_wall_collisions_data(nextPos, 150.0, 50.0, tempWcd)
|
||||
local upperWcd = wcd_to_table(tempWcd)
|
||||
|
||||
tempWcd = collision_get_temp_wall_collision_data()
|
||||
resolve_and_return_wall_collisions_data(nextPos, 30.0, 50.0, tempWcd)
|
||||
local lowerWcd = wcd_to_table(tempWcd)
|
||||
|
||||
floorHeight, floor = find_floor(nextPos.x, nextPos.y, nextPos.z)
|
||||
ceilHeight, ceil = vec3f_mario_ceil(nextPos, floorHeight)
|
||||
waterLevel = find_water_level(nextPos.x, nextPos.z)
|
||||
|
||||
m.wall = nil
|
||||
|
||||
--! The water pseudo floor is not referenced when your intended qstep is
|
||||
-- out of bounds, so it won't detect you as landing.
|
||||
|
||||
if not floor then
|
||||
if nextPos.y <= m.floorHeight then
|
||||
m.pos.y = m.floorHeight
|
||||
return AIR_STEP_LANDED
|
||||
end
|
||||
|
||||
m.pos.y = nextPos.y
|
||||
if gServerSettings.bouncyLevelBounds ~= BOUNCY_LEVEL_BOUNDS_OFF then
|
||||
m.faceAngle.y = m.faceAngle.y + 0x8000
|
||||
mario_set_forward_vel(m, gServerSettings.bouncyLevelBounds == BOUNCY_LEVEL_BOUNDS_ON_CAP and math.clamp(1.5 * m.forwardVel, -500, 500) or 1.5 * m.forwardVel)
|
||||
end
|
||||
return AIR_STEP_HIT_WALL
|
||||
end
|
||||
|
||||
if (m.action & ACT_FLAG_RIDING_SHELL) ~= 0 and floorHeight < waterLevel then
|
||||
local allowForceAction = TRIPLET_BUTTERFLY_ACT_ACTIVATE
|
||||
if allowForceAction then
|
||||
floorHeight = waterLevel
|
||||
floor = get_water_surface_pseudo_floor()
|
||||
floor.originOffset = floorHeight
|
||||
end
|
||||
end
|
||||
|
||||
--! This check uses f32, but findFloor uses short (overflow jumps)
|
||||
if nextPos.y <= floorHeight then
|
||||
if ceilHeight - floorHeight > m.marioObj.hitboxHeight then
|
||||
m.pos.x = nextPos.x
|
||||
m.pos.z = nextPos.z
|
||||
m.floor = floor
|
||||
m.floorHeight = floorHeight
|
||||
end
|
||||
|
||||
--! When ceilHeight - floorHeight <= m->marioObj->hitboxHeight (160.0f), the step result says that
|
||||
-- Mario landed, but his movement is cancelled and his referenced floor
|
||||
-- isn't updated (pedro spots)
|
||||
m.pos.y = floorHeight
|
||||
return AIR_STEP_LANDED
|
||||
end
|
||||
|
||||
if nextPos.y + m.marioObj.hitboxHeight > ceilHeight then
|
||||
if m.vel.y >= 0.0 then
|
||||
m.vel.y = 0.0
|
||||
|
||||
--! Uses referenced ceiling instead of ceil (ceiling hang upwarp)
|
||||
if (stepArg and (stepArg & AIR_STEP_CHECK_HANG) ~= 0) and m.ceil and m.ceil.type == SURFACE_HANGABLE then
|
||||
return AIR_STEP_GRABBED_CEILING
|
||||
end
|
||||
|
||||
return AIR_STEP_NONE
|
||||
end
|
||||
|
||||
if nextPos.y <= m.floorHeight then
|
||||
m.pos.y = m.floorHeight
|
||||
return AIR_STEP_LANDED
|
||||
end
|
||||
|
||||
m.pos.y = nextPos.y
|
||||
return AIR_STEP_HIT_WALL
|
||||
end
|
||||
|
||||
--! When the wall is not completely vertical or there is a slight wall
|
||||
-- misalignment, you can activate these conditions in unexpected situations
|
||||
if (stepArg and (stepArg & AIR_STEP_CHECK_LEDGE_GRAB) ~= 0) and upperWcd.numWalls == 0 and lowerWcd.numWalls > 0 then
|
||||
for i = 1, lowerWcd.numWalls do
|
||||
if gLevelValues.fixCollisionBugs == 0 then
|
||||
i = lowerWcd.numWalls
|
||||
end
|
||||
local wall = lowerWcd.walls[i]
|
||||
if donkey_kong_check_ledge_grab(m, wall, intendedPos, nextPos) ~= 0 then
|
||||
return AIR_STEP_GRABBED_LEDGE
|
||||
end
|
||||
end
|
||||
|
||||
vec3f_copy(m.pos, nextPos)
|
||||
m.floor = floor
|
||||
m.floorHeight = floorHeight
|
||||
return AIR_STEP_NONE
|
||||
end
|
||||
|
||||
vec3f_copy(m.pos, nextPos)
|
||||
m.floor = floor
|
||||
m.floorHeight = floorHeight
|
||||
|
||||
if upperWcd.numWalls > 0 then
|
||||
table_to_wcd(tempWcd, upperWcd)
|
||||
mario_update_wall(m, tempWcd)
|
||||
upperWcd = wcd_to_table(tempWcd)
|
||||
|
||||
for i = 1, upperWcd.numWalls do
|
||||
if gLevelValues.fixCollisionBugs == 0 then
|
||||
i = upperWcd.numWalls
|
||||
end
|
||||
|
||||
local wall = upperWcd.walls[i]
|
||||
wallDYaw = atan2s(wall.normal.z, wall.normal.x) - m.faceAngle.y
|
||||
|
||||
if wall.type == SURFACE_BURNING then
|
||||
m.wall = wall
|
||||
return AIR_STEP_HIT_LAVA_WALL
|
||||
end
|
||||
|
||||
if wallDYaw < -0x6000 or wallDYaw > 0x6000 then
|
||||
m.wall = wall
|
||||
m.flags = m.flags | MARIO_UNKNOWN_30
|
||||
return AIR_STEP_HIT_WALL
|
||||
end
|
||||
end
|
||||
elseif lowerWcd.numWalls > 0 then
|
||||
table_to_wcd(tempWcd, lowerWcd)
|
||||
mario_update_wall(m, tempWcd)
|
||||
lowerWcd = wcd_to_table(tempWcd)
|
||||
|
||||
for i = 1, lowerWcd.numWalls do
|
||||
if gLevelValues.fixCollisionBugs == 0 then
|
||||
i = lowerWcd.numWalls
|
||||
end
|
||||
|
||||
local wall = lowerWcd.walls[i]
|
||||
wallDYaw = atan2s(wall.normal.z, wall.normal.x) - m.faceAngle.y
|
||||
|
||||
if wall.type == SURFACE_BURNING then
|
||||
m.wall = wall
|
||||
return AIR_STEP_HIT_LAVA_WALL
|
||||
end
|
||||
|
||||
if wallDYaw < -0x6000 or wallDYaw > 0x6000 then
|
||||
m.wall = wall
|
||||
m.flags = m.flags | MARIO_UNKNOWN_30
|
||||
return AIR_STEP_HIT_WALL
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return AIR_STEP_NONE
|
||||
end
|
||||
|
||||
--- @param m MarioState
|
||||
--- Applies twirl gravity to donkey kong
|
||||
local function apply_donkey_kong_twirl_gravity(m)
|
||||
if not m then return end
|
||||
local terminalVelocity
|
||||
local heaviness = 1.0
|
||||
|
||||
if m.angleVel.y > 1024 then
|
||||
heaviness = 1024.0 / m.angleVel.y
|
||||
end
|
||||
|
||||
terminalVelocity = -75.0 * heaviness
|
||||
|
||||
m.vel.y = m.vel.y - 4.0 * heaviness
|
||||
if m.vel.y < terminalVelocity then
|
||||
m.vel.y = terminalVelocity
|
||||
end
|
||||
end
|
||||
|
||||
--- @param m MarioState
|
||||
--- @return integer
|
||||
--- Checks if gravity should be strengthen for donkey kong jump ascent
|
||||
local function should_strengthen_gravity_for_donkey_kong_jump_ascent(m)
|
||||
if not m then return 0 end
|
||||
if m.flags & MARIO_UNKNOWN_08 == 0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
if m.action & ACT_FLAG_INTANGIBLE ~= 0 or m.action & ACT_FLAG_INVULNERABLE ~= 0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
if m.input & INPUT_A_DOWN == 0 and m.vel.y > 20.0 then
|
||||
return m.action & ACT_FLAG_CONTROL_JUMP_HEIGHT ~= 0 and 1 or 0
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
--- @param m MarioState
|
||||
--- Applies gravity to donkey kong
|
||||
local function apply_donkey_kong_gravity(m)
|
||||
if m.action == ACT_TWIRLING and m.vel.y < 0.0 then
|
||||
apply_donkey_kong_twirl_gravity(m)
|
||||
elseif m.action == ACT_SHOT_FROM_CANNON then
|
||||
m.vel.y = math.max(-75, m.vel.y - 1)
|
||||
elseif m.action == ACT_LONG_JUMP or m.action == ACT_SLIDE_KICK or m.action == ACT_BBH_ENTER_SPIN then
|
||||
m.vel.y = math.max(-75, m.vel.y - 3.0)
|
||||
elseif m.action == ACT_LAVA_BOOST or m.action == ACT_FALL_AFTER_STAR_GRAB then
|
||||
m.vel.y = math.max(-65, m.vel.y - 4.8)
|
||||
elseif m.action == ACT_GETTING_BLOWN then
|
||||
m.vel.y = math.max(-75, m.vel.y - (1.5 * m.unkC4))
|
||||
elseif should_strengthen_gravity_for_donkey_kong_jump_ascent(m) ~= 0 then
|
||||
m.vel.y = m.vel.y / 4.0
|
||||
elseif m.action & ACT_FLAG_METAL_WATER ~= 0 then
|
||||
m.vel.y = math.max(-16, m.vel.y - 2.4)
|
||||
elseif m.flags & MARIO_WING_CAP ~= 0 and m.vel.y < 0.0 and m.input & INPUT_A_DOWN ~= 0 then
|
||||
m.marioBodyState.wingFlutter = 1
|
||||
|
||||
m.vel.y = m.vel.y - 3.0
|
||||
if m.vel.y < -37.5 then
|
||||
m.vel.y = math.min(-37.5, m.vel.y + 4)
|
||||
end
|
||||
else
|
||||
if m.vel.y < 0 then
|
||||
m.vel.y = math.max(-75, m.vel.y - 6)
|
||||
else
|
||||
m.vel.y = math.max(-75, m.vel.y - 4.25)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param m MarioState
|
||||
--- Applies vertical wind to donkey kong
|
||||
local function apply_donkey_kong_vertical_wind(m)
|
||||
if not m then return end
|
||||
local maxVelY
|
||||
local offsetY
|
||||
if m.action ~= ACT_GROUND_POUND then
|
||||
offsetY = m.pos.y - -1500.0
|
||||
|
||||
if m.floor and m.floor.type == SURFACE_VERTICAL_WIND and -3000.0 < offsetY and offsetY < 2000.0 then
|
||||
if offsetY >= 0.0 then
|
||||
maxVelY = 10000.0 / (offsetY + 200.0)
|
||||
else
|
||||
maxVelY = 50.0
|
||||
end
|
||||
|
||||
if m.vel.y < maxVelY then
|
||||
m.vel.y = (m.vel.y + maxVelY / 6.0) -- Bit stronger so DK doesn't fall through
|
||||
if m.vel.y > maxVelY then
|
||||
m.vel.y = maxVelY
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- @param m MarioState
|
||||
--- @param stepArg integer
|
||||
--- @return integer
|
||||
--- Performs an air step for donkey kong
|
||||
local function perform_donkey_kong_air_step(m, stepArg)
|
||||
local intendedPos = gVec3fZero()
|
||||
local quarterStepResult
|
||||
local stepResult = AIR_STEP_NONE
|
||||
|
||||
m.wall = nil
|
||||
|
||||
for i = 0, 3 do
|
||||
local step = gVec3fZero()
|
||||
step = {
|
||||
x = m.vel.x / 4.0,
|
||||
y = m.vel.y / 4.0,
|
||||
z = m.vel.z / 4.0,
|
||||
}
|
||||
|
||||
intendedPos.x = m.pos.x + step.x
|
||||
intendedPos.y = m.pos.y + step.y
|
||||
intendedPos.z = m.pos.z + step.z
|
||||
|
||||
vec3f_normalize(step)
|
||||
set_find_wall_direction(step, true, true)
|
||||
|
||||
quarterStepResult = perform_donkey_kong_air_quarter_step(m, intendedPos, stepArg)
|
||||
set_find_wall_direction(step, false, false)
|
||||
|
||||
--! On one qf, hit OOB/ceil/wall to store the 2 return value, and continue
|
||||
-- getting 0s until your last qf. Graze a wall on your last qf, and it will
|
||||
-- return the stored 2 with a sharply angled reference wall. (some gwks)
|
||||
|
||||
if (quarterStepResult ~= AIR_STEP_NONE) then
|
||||
stepResult = quarterStepResult
|
||||
end
|
||||
|
||||
if (quarterStepResult == AIR_STEP_LANDED or quarterStepResult == AIR_STEP_GRABBED_LEDGE
|
||||
or quarterStepResult == AIR_STEP_GRABBED_CEILING
|
||||
or quarterStepResult == AIR_STEP_HIT_LAVA_WALL) then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if (m.vel.y >= 0.0) then
|
||||
m.peakHeight = m.pos.y
|
||||
end
|
||||
|
||||
m.terrainSoundAddend = mario_get_terrain_sound_addend(m)
|
||||
|
||||
-- Start climbing
|
||||
if m.wall ~= nil and m.action ~= ACT_DONKEY_CLIMB and m.prevAction ~= ACT_DONKEY_CLIMB
|
||||
and (m.action & ACT_FLAG_INVULNERABLE == 0) and stepResult ~= AIR_STEP_HIT_LAVA_WALL
|
||||
and m.input & INPUT_A_DOWN ~= 0 and m.heldObj == nil then
|
||||
local wallangle = atan2s(m.wallNormal.z, m.wallNormal.x) + 0x8000
|
||||
-- Only grab wall if within certain angle of the wall
|
||||
if abs_angle_diff(wallangle, m.faceAngle.y) < 0x3000 then
|
||||
set_mario_action(m, ACT_DONKEY_CLIMB, 0)
|
||||
if stepResult == AIR_STEP_HIT_WALL then return 0 end
|
||||
return stepResult
|
||||
end
|
||||
end
|
||||
|
||||
if (m.action ~= ACT_FLYING and m.action ~= ACT_BUBBLED) then
|
||||
apply_donkey_kong_gravity(m)
|
||||
end
|
||||
apply_donkey_kong_vertical_wind(m)
|
||||
|
||||
vec3f_copy(m.marioObj.header.gfx.pos, m.pos)
|
||||
vec3s_set(m.marioObj.header.gfx.angle, 0, m.faceAngle.y, 0)
|
||||
|
||||
return stepResult
|
||||
end
|
||||
|
||||
function donkey_kong_before_phys_step(m, stepType, stepArg)
|
||||
if stepType == STEP_TYPE_GROUND then
|
||||
-- return perform_donkey_kong_ground_step(m) -- TBA
|
||||
elseif stepType == STEP_TYPE_AIR then
|
||||
return perform_donkey_kong_air_step(m, stepArg)
|
||||
elseif stepType == STEP_TYPE_WATER then
|
||||
-- return perform_donkey_kong_water_step(m) -- TBA
|
||||
elseif stepType == STEP_TYPE_HANG then
|
||||
-- return perform_donkey_kong_hanging_step(m) -- TBA
|
||||
end
|
||||
end
|
||||
|
||||
function donkey_kong_before_action(m, action, actionArg)
|
||||
if (action == ACT_DIVE or action == ACT_MOVE_PUNCHING) and m.action & ACT_FLAG_AIR == 0 and m.input & INPUT_A_DOWN == 0 and m.forwardVel >= 20 then
|
||||
m.vel.y = 20
|
||||
m.faceAngle.x = 0
|
||||
return ACT_DONKEY_KONG_ROLL
|
||||
elseif (action == ACT_PUNCHING and actionArg == 9) then
|
||||
return ACT_DONKEY_KONG_POUND
|
||||
end
|
||||
end
|
||||
|
||||
function donkey_kong_on_interact(m, o, type, value)
|
||||
-- allow donkey kong to grab objects with the roll
|
||||
if type == INTERACT_GRABBABLE and m.action == ACT_DONKEY_KONG_ROLL then
|
||||
if ((o.oInteractionSubtype & INT_SUBTYPE_NOT_GRABBABLE) == 0) then
|
||||
m.interactObj = o
|
||||
m.input = m.input | INPUT_INTERACT_OBJ_GRABBABLE
|
||||
if (o.oSyncID ~= 0) then network_send_object(o, false) end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function on_attack_object(m, o, interaction)
|
||||
-- speed up when hitting enemies with roll
|
||||
if (m.action == ACT_DONKEY_KONG_ROLL or m.action == ACT_DONKEY_KONG_ROLL_AIR) and (interaction & INT_FAST_ATTACK_OR_SHELL ~= 0) then
|
||||
if o.oInteractType == INTERACT_BULLY then
|
||||
mario_set_forward_vel(m, -25)
|
||||
m.actionTimer = DONKEY_KONG_ROLL_DECAY_TIME
|
||||
m.actionArg = 1
|
||||
else
|
||||
local newForwardVel = math.min(m.forwardVel * 1.1, 70)
|
||||
mario_set_forward_vel(m, newForwardVel)
|
||||
m.actionTimer = 0
|
||||
m.actionArg = 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Bounce code
|
||||
if (CT_DONKEY_KONG ~= _G.charSelect.character_get_current_number(m.playerIndex)) then return end
|
||||
if (_G.charSelect.get_options_status(6) ~= 0) then
|
||||
if (interaction == INT_HIT_FROM_ABOVE and m.framesSinceA < 5) then
|
||||
m.actionTimer = 0
|
||||
if (m.action == ACT_DONKEY_KONG_BOUNCE) then
|
||||
set_mario_action(m, ACT_DONKEY_KONG_BOUNCE, m.actionArg + 1)
|
||||
else
|
||||
set_mario_action(m, ACT_DONKEY_KONG_BOUNCE, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
hook_event(HOOK_ON_ATTACK_OBJECT, on_attack_object)
|
||||
|
||||
_G.ACT_DONKEY_KONG_ROLL = allocate_mario_action(ACT_GROUP_MOVING | ACT_FLAG_ATTACKING | ACT_FLAG_MOVING)
|
||||
_G.ACT_DONKEY_KONG_ROLL_AIR = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_ATTACKING | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
_G.ACT_DONKEY_KONG_POUND = allocate_mario_action(ACT_GROUP_STATIONARY | ACT_FLAG_ATTACKING)
|
||||
_G.ACT_DONKEY_KONG_POUND_HIT = allocate_mario_action(ACT_GROUP_STATIONARY | ACT_FLAG_ATTACKING)
|
||||
_G.ACT_DONKEY_KONG_BOUNCE = (ACT_GROUP_AIRBORNE | ACT_FLAG_MOVING | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
|
||||
---------------
|
||||
-- DK Bounce --
|
||||
---------------
|
||||
|
||||
--- SwagSkeleton95
|
||||
--- Allows the player to bounce across enemies with well-timed A presses. Spawns coins when chained across multiple enemies. Credit to baconator2558 for the vast majority of this code.
|
||||
--- action
|
||||
|
||||
local bounceSounds = {
|
||||
audio_sample_load("z_sfx_dk_bounce1.ogg"),
|
||||
audio_sample_load("z_sfx_dk_bounce2.ogg"),
|
||||
audio_sample_load("z_sfx_dk_bounce3.ogg")
|
||||
}
|
||||
|
||||
local coinObj = nil
|
||||
|
||||
function act_dk_bounce(m)
|
||||
if (m.actionTimer == 0) then
|
||||
set_character_animation(m, CHAR_ANIM_FORWARD_SPINNING)
|
||||
set_anim_to_frame(m, 0)
|
||||
m.forwardVel = 0
|
||||
m.vel.x = 0
|
||||
m.vel.y = 80
|
||||
play_character_sound(m, CHAR_SOUND_YAHOO_WAHA_YIPPEE)
|
||||
m.vel.z = 0
|
||||
m.slideVelX = 0
|
||||
m.slideVelZ = 0
|
||||
m.faceAngle.y = m.intendedYaw
|
||||
if (m.actionArg >= 3) then
|
||||
coinObj = spawn_non_sync_object(id_bhvBlueCoinJumping, E_MODEL_SPARKLES, m.pos.x, m.pos.y, m.pos.z, nil)
|
||||
end
|
||||
audio_sample_play(bounceSounds[math.min(m.actionArg,3)], m.pos, 0.5)
|
||||
-- plays a random sound from a table ('bounceSounds') of 3 sound files.
|
||||
-- I didn't include them here because I ripped them straight from DKCR myself
|
||||
-- and I'm under the impression that this mod mainly uses self-made sound effects
|
||||
set_mario_particle_flags(m, PARTICLE_HORIZONTAL_STAR, 0)
|
||||
end
|
||||
|
||||
if (m.actionTimer >= 1 and coinObj ~= nil) then
|
||||
coinObj.oPosX = m.pos.x
|
||||
coinObj.oPosY = m.pos.y
|
||||
coinObj.oPosZ = m.pos.z
|
||||
interact_coin(m, INTERACT_COIN, coinObj)
|
||||
coinObj = nil
|
||||
end
|
||||
|
||||
if (m.actionTimer > 5 and m.marioObj.header.gfx.animInfo.animID == CHAR_ANIM_FORWARD_SPINNING) then
|
||||
set_character_animation(m, CHAR_ANIM_TRIPLE_JUMP)
|
||||
set_anim_to_frame(m, 21)
|
||||
end
|
||||
|
||||
m.forwardVel = math.min(m.forwardVel, 95)
|
||||
|
||||
update_air_without_turn(m)
|
||||
if (m.actionTimer > 20) then
|
||||
update_air_without_turn(m)
|
||||
end
|
||||
|
||||
if (m.vel.y < 10) then
|
||||
update_air_without_turn(m)
|
||||
if (m.vel.y < -10) then
|
||||
update_air_without_turn(m)
|
||||
update_air_without_turn(m)
|
||||
update_air_without_turn(m)
|
||||
update_air_without_turn(m)
|
||||
update_air_without_turn(m)
|
||||
end
|
||||
end
|
||||
|
||||
local stepResult = perform_air_step(m, AIR_STEP_CHECK_HANG | AIR_STEP_CHECK_LEDGE_GRAB)
|
||||
|
||||
if (stepResult == AIR_STEP_LANDED) then
|
||||
set_character_animation(m, CHAR_ANIM_FORWARD_SPINNING)
|
||||
set_anim_to_frame(m, 0)
|
||||
return set_mario_action(m, ACT_DOUBLE_JUMP_LAND, 0)
|
||||
elseif (stepResult == AIR_STEP_GRABBED_LEDGE) then
|
||||
set_character_animation(m, CHAR_ANIM_IDLE_ON_LEDGE)
|
||||
return drop_and_set_mario_action(m, ACT_LEDGE_GRAB, 0)
|
||||
elseif (stepResult == AIR_STEP_GRABBED_CEILING) then
|
||||
return set_mario_action(m, ACT_START_HANGING, 0)
|
||||
end
|
||||
|
||||
m.faceAngle.y = approach_s16_symmetric(m.faceAngle.y, m.intendedYaw, (abs_angle_diff(m.faceAngle.y, m.intendedYaw) / (25 * m.actionTimer + 1)) + 750)
|
||||
update_air_without_turn(m)
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
if (check_kick_or_dive_in_air(m) ~= 0) then
|
||||
return 1
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
hook_mario_action(ACT_DONKEY_KONG_BOUNCE, act_dk_bounce, INT_HIT_FROM_ABOVE)
|
||||
|
||||
--- Roll
|
||||
|
||||
---@param m MarioState
|
||||
local function act_donkey_kong_roll(m)
|
||||
if (not m) then return 0 end
|
||||
|
||||
local isSliding = (mario_floor_is_slippery(m)) ~= 0
|
||||
if isSliding then
|
||||
if update_sliding(m, 4) ~= 0 or m.actionState == 0 then
|
||||
m.faceAngle.x = 0
|
||||
return set_mario_action(m, ACT_DECELERATING, 0)
|
||||
end
|
||||
end
|
||||
|
||||
if mario_check_object_grab(m) ~= 0 then
|
||||
m.faceAngle.x = 0
|
||||
set_character_animation(m, CHAR_ANIM_FIRST_PUNCH)
|
||||
set_anim_to_frame(m, 2)
|
||||
return 1
|
||||
end
|
||||
|
||||
if (m.input & INPUT_A_PRESSED) ~= 0 then
|
||||
m.faceAngle.x = 0
|
||||
m.marioObj.header.gfx.angle.x = m.faceAngle.x
|
||||
local result = set_jumping_action(m, ACT_JUMP, 0)
|
||||
if not isSliding then
|
||||
m.forwardVel = m.forwardVel / 0.8 - 5 -- conserve all jump momentum minus 5
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local doSpinAnim = true
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
|
||||
set_character_animation(m, CHAR_ANIM_START_CROUCHING)
|
||||
if m.actionState == 0 then
|
||||
doSpinAnim = false
|
||||
local newForwardVel = m.forwardVel
|
||||
newForwardVel = DONKEY_KONG_ROLL_SPEED * (m.actionTimer / DONKEY_KONG_ROLL_STARTUP)
|
||||
if m.actionTimer >= DONKEY_KONG_ROLL_STARTUP then
|
||||
newForwardVel = DONKEY_KONG_ROLL_SPEED
|
||||
m.actionState = 1
|
||||
end
|
||||
mario_set_forward_vel(m, newForwardVel)
|
||||
elseif m.actionTimer >= DONKEY_KONG_ROLL_DECAY_TIME and not isSliding then
|
||||
-- slow down after a time
|
||||
local newForwardVel = m.forwardVel
|
||||
newForwardVel = newForwardVel * DONKEY_KONG_ROLL_DECAY_PERCENT
|
||||
mario_set_forward_vel(m, newForwardVel)
|
||||
end
|
||||
|
||||
-- influence direction slightly
|
||||
m.marioObj.oMoveAngleYaw = m.faceAngle.y
|
||||
cur_obj_rotate_yaw_toward(m.intendedYaw, 0x100)
|
||||
m.faceAngle.y = m.marioObj.oMoveAngleYaw
|
||||
|
||||
local result = perform_ground_step(m)
|
||||
if result == GROUND_STEP_LEFT_GROUND then
|
||||
if m.actionState == 0 then
|
||||
mario_set_forward_vel(m, DONKEY_KONG_ROLL_SPEED)
|
||||
end
|
||||
return set_mario_action(m, ACT_DONKEY_KONG_ROLL_AIR, 0)
|
||||
elseif result == GROUND_STEP_HIT_WALL then
|
||||
if (m.wall or gServerSettings.bouncyLevelBounds == BOUNCY_LEVEL_BOUNDS_OFF) then
|
||||
m.faceAngle.x = 0
|
||||
set_mario_particle_flags(m, PARTICLE_VERTICAL_STAR, 0)
|
||||
slide_bonk(m, ACT_GROUND_BONK, ACT_WALKING)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if doSpinAnim then
|
||||
local prevFaceAngleX = m.faceAngle.x
|
||||
m.faceAngle.x = m.faceAngle.x + 0x60 * m.forwardVel
|
||||
m.marioObj.header.gfx.angle.x = m.faceAngle.x
|
||||
m.marioObj.header.gfx.pos.y = m.marioObj.header.gfx.pos.y + 50
|
||||
if prevFaceAngleX <= 0 and m.faceAngle.x > 0 then
|
||||
play_sound(SOUND_ACTION_SPIN, m.marioObj.header.gfx.cameraToObject)
|
||||
end
|
||||
end
|
||||
|
||||
-- end roll
|
||||
if m.actionTimer > DONKEY_KONG_ROLL_END then
|
||||
m.faceAngle.x = 0
|
||||
return set_mario_action(m, ACT_WALKING, 0)
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
hook_mario_action(ACT_DONKEY_KONG_ROLL, { every_frame = act_donkey_kong_roll }, INT_FAST_ATTACK_OR_SHELL)
|
||||
|
||||
---@param m MarioState
|
||||
local function act_donkey_kong_roll_air(m)
|
||||
if (not m) then return 0 end
|
||||
|
||||
if (m.input & INPUT_A_PRESSED) ~= 0 then
|
||||
m.terrainSoundAddend = 0
|
||||
m.faceAngle.x = 0
|
||||
m.marioObj.header.gfx.angle.x = m.faceAngle.x
|
||||
local result = set_mario_action(m, ACT_JUMP, 0)
|
||||
m.forwardVel = m.forwardVel / 0.8 - 5 -- conserve all jump momentum minus 5
|
||||
return result
|
||||
end
|
||||
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
|
||||
-- influence direction slightly
|
||||
m.marioObj.oMoveAngleYaw = m.faceAngle.y
|
||||
cur_obj_rotate_yaw_toward(m.intendedYaw, 0x100)
|
||||
m.faceAngle.y = m.marioObj.oMoveAngleYaw
|
||||
mario_set_forward_vel(m, m.forwardVel)
|
||||
|
||||
local result = perform_air_step(m, AIR_STEP_CHECK_LEDGE_GRAB)
|
||||
if result == AIR_STEP_LANDED then
|
||||
if (check_fall_damage_or_get_stuck(m, ACT_HARD_BACKWARD_GROUND_KB) == 0) then
|
||||
set_mario_action(m, ACT_DONKEY_KONG_ROLL, 0)
|
||||
m.actionState = 1
|
||||
return 1
|
||||
end
|
||||
elseif result == AIR_STEP_HIT_WALL then
|
||||
if (m.wall or gServerSettings.bouncyLevelBounds == BOUNCY_LEVEL_BOUNDS_OFF) then
|
||||
mario_bonk_reflection(m, 1)
|
||||
if (m.vel.y > 0) then m.vel.y = 0 end
|
||||
|
||||
set_mario_particle_flags(m, PARTICLE_VERTICAL_STAR, 0)
|
||||
drop_and_set_mario_action(m, ACT_BACKWARD_AIR_KB, 0)
|
||||
return 1
|
||||
end
|
||||
elseif result == AIR_STEP_HIT_LAVA_WALL then
|
||||
lava_boost_on_wall(m)
|
||||
return 1
|
||||
end
|
||||
|
||||
local prevFaceAngleX = m.faceAngle.x
|
||||
m.faceAngle.x = m.faceAngle.x + 0x60 * m.forwardVel
|
||||
m.marioObj.header.gfx.angle.x = m.faceAngle.x
|
||||
m.marioObj.header.gfx.pos.y = m.marioObj.header.gfx.pos.y + 50
|
||||
if prevFaceAngleX <= 0 and m.faceAngle.x > 0 then
|
||||
play_sound(SOUND_ACTION_SPIN, m.marioObj.header.gfx.cameraToObject)
|
||||
end
|
||||
|
||||
if m.actionTimer > DONKEY_KONG_ROLL_END then
|
||||
m.faceAngle.x = 0
|
||||
return set_mario_action(m, ACT_FREEFALL, 0)
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
hook_mario_action(ACT_DONKEY_KONG_ROLL_AIR, { every_frame = act_donkey_kong_roll_air }, INT_FAST_ATTACK_OR_SHELL)
|
||||
|
||||
local function act_donkey_kong_pound(m)
|
||||
if (not m) then return 0 end
|
||||
|
||||
mario_set_forward_vel(m, 0)
|
||||
if (mario_floor_is_slippery(m)) ~= 0 then
|
||||
return set_mario_action(m, ACT_BEGIN_SLIDING, 0)
|
||||
end
|
||||
|
||||
if (m.input & INPUT_A_PRESSED) ~= 0 then
|
||||
local result = set_jumping_action(m, ACT_JUMP, 0)
|
||||
return result
|
||||
elseif (m.input & INPUT_B_PRESSED) ~= 0 and m.actionTimer ~= 0 then
|
||||
m.actionState = 1
|
||||
end
|
||||
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
if m.actionTimer == 1 then
|
||||
play_mario_heavy_landing_sound(m, SOUND_ACTION_TERRAIN_HEAVY_LANDING)
|
||||
|
||||
-- Spawn particles at hand that hit ground
|
||||
local pos = {x = 0, y = 0, z = 0}
|
||||
if m.marioObj.header.gfx.animInfo.animFrame >= 8 then
|
||||
get_mario_anim_part_pos(m, MARIO_ANIM_PART_RIGHT_HAND, pos)
|
||||
else
|
||||
get_mario_anim_part_pos(m, MARIO_ANIM_PART_LEFT_HAND, pos)
|
||||
end
|
||||
pos.y = m.pos.y -- always appear on ground
|
||||
spawn_non_sync_object(id_bhvHorStarParticleSpawner, E_MODEL_NONE, pos.x, pos.y, pos.z, nil)
|
||||
spawn_non_sync_object(id_bhvMistCircParticleSpawner, E_MODEL_NONE, pos.x, pos.y, pos.z, nil)
|
||||
|
||||
m.action = ACT_DONKEY_KONG_POUND_HIT
|
||||
m.marioObj.hitboxRadius = 100 -- larger hitbox
|
||||
elseif m.action == ACT_DONKEY_KONG_POUND_HIT then
|
||||
m.action = ACT_DONKEY_KONG_POUND
|
||||
m.marioObj.hitboxRadius = 37 -- reset hitbox
|
||||
elseif m.actionTimer >= 8 then
|
||||
if m.actionState ~= 0 then
|
||||
-- pound again
|
||||
m.actionTimer = 0
|
||||
m.actionState = 0
|
||||
elseif m.input & INPUT_Z_DOWN ~= 0 then
|
||||
set_mario_action(m, ACT_START_CROUCHING, 0)
|
||||
else
|
||||
set_mario_action(m, ACT_IDLE, 0)
|
||||
end
|
||||
end
|
||||
|
||||
--set_character_anim_with_accel(m, CHAR_ANIM_PLACE_LIGHT_OBJ, 0x20000)
|
||||
-- 28 anim frames in 16 frames
|
||||
if m.marioObj.header.gfx.animInfo.animFrame > 15 and m.actionTimer == 0 then
|
||||
--djui_chat_message_create(tostring(m.marioObj.header.gfx.animInfo.animFrame))
|
||||
set_anim_to_frame(m, 0)
|
||||
end
|
||||
play_custom_anim(m, "donkey_ground_slap", 0x10000 * 28 // 16)
|
||||
--[[set_anim_to_frame(m, m.marioObj.header.gfx.animInfo.animFrame)
|
||||
if m.controller.buttonPressed & L_TRIG ~= 0 then
|
||||
set_anim_to_frame(m, m.marioObj.header.gfx.animInfo.animFrame + 1)
|
||||
end]]
|
||||
local result = perform_ground_step(m)
|
||||
if result == GROUND_STEP_LEFT_GROUND then
|
||||
return set_mario_action(m, ACT_FREEFALL, 0)
|
||||
end
|
||||
end
|
||||
hook_mario_action(ACT_DONKEY_KONG_POUND, { every_frame = act_donkey_kong_pound })
|
||||
|
||||
hook_mario_action(ACT_DONKEY_KONG_POUND_HIT, { every_frame = act_donkey_kong_pound }, INT_GROUND_POUND) -- same action but with ground pound interaction
|
||||
|
||||
-----------------------
|
||||
--- Donkey Climbing ---
|
||||
--- -------------------
|
||||
|
||||
DK_ANIM_CLIMBING = 'donkey_custom_climbing'
|
||||
|
||||
ACT_DONKEY_CLIMB = allocate_mario_action(ACT_FLAG_AIR | ACT_GROUP_AIRBORNE)
|
||||
|
||||
-- Climbing ability action
|
||||
--- @param m MarioState
|
||||
function act_donkey_climb(m)
|
||||
--No wall, no climb
|
||||
if m.wall == nil then
|
||||
set_mario_action(m, ACT_TRIPLE_JUMP, 0)
|
||||
mario_set_forward_vel(m, 10)
|
||||
return true
|
||||
|
||||
--Press A to jump off
|
||||
elseif (m.input & INPUT_A_PRESSED) ~= 0 then
|
||||
set_mario_action(m, ACT_JUMP, 0)
|
||||
m.faceAngle.y = m.faceAngle.y - 0x8000
|
||||
mario_set_forward_vel(m, 20)
|
||||
return true
|
||||
|
||||
--Press Z to just fall off
|
||||
elseif (m.input & INPUT_Z_PRESSED) ~= 0 then
|
||||
m.input = m.input &~ INPUT_Z_PRESSED
|
||||
play_character_sound(m, CHAR_SOUND_UH)
|
||||
|
||||
mario_set_forward_vel(m, -8)
|
||||
return set_mario_action(m, ACT_FREEFALL, 0)
|
||||
end
|
||||
|
||||
--Woah!
|
||||
if m.actionTimer == 0 then
|
||||
play_character_sound(m, CHAR_SOUND_WHOA)
|
||||
end
|
||||
|
||||
local climbAnimSpeed = m.intendedMag
|
||||
local wallangle = atan2s(m.wallNormal.z, m.wallNormal.x) + 0x8000
|
||||
local transwall
|
||||
if m.actionTimer >= 4 then
|
||||
--Face beside wall and move around it
|
||||
m.faceAngle.y = wallangle - 0x4000
|
||||
if m.actionTimer <= DONKEY_KONG_SLIP_TIME then
|
||||
mario_set_forward_vel(m, m.controller.stickX/3)
|
||||
m.vel.y = m.controller.stickY/3
|
||||
elseif m.actionTimer <= DONKEY_KONG_SLIDE_TIME then -- Slip on wall after some time
|
||||
climbAnimSpeed = 32
|
||||
m.vel.y = 0
|
||||
else
|
||||
climbAnimSpeed = 0
|
||||
m.vel.y = m.vel.y + 8 -- counteract gravity
|
||||
end
|
||||
|
||||
--Perform air step
|
||||
local air_step = perform_air_step(m, 0)
|
||||
transwall = m.wall
|
||||
if air_step == AIR_STEP_LANDED then
|
||||
return set_mario_action(m, ACT_FREEFALL_LAND, 0)
|
||||
end
|
||||
end
|
||||
|
||||
--Face directly towards wall to make sure we're latched on
|
||||
m.faceAngle.y = wallangle
|
||||
mario_set_forward_vel(m, 1)
|
||||
if m.actionTimer <= DONKEY_KONG_SLIP_TIME then
|
||||
m.vel.y = 0
|
||||
elseif m.actionTimer <= DONKEY_KONG_SLIDE_TIME then
|
||||
m.vel.y = 5
|
||||
end
|
||||
|
||||
--Perform air step
|
||||
air_step = perform_air_step(m, 0)
|
||||
if air_step == AIR_STEP_LANDED then
|
||||
return set_mario_action(m, ACT_FREEFALL_LAND, 0)
|
||||
elseif m.wall == nil then
|
||||
if transwall == nil then
|
||||
set_mario_action(m, ACT_TRIPLE_JUMP, 0)
|
||||
mario_set_forward_vel(m, 10)
|
||||
return true
|
||||
else
|
||||
m.wall = transwall
|
||||
end
|
||||
end
|
||||
|
||||
--Climbing animation
|
||||
play_custom_anim(m, "donkey_custom_climbing", climbAnimSpeed * 0x3000)
|
||||
if m.actionTimer < 8 or climbAnimSpeed == 0 then
|
||||
set_anim_to_frame(m, 0)
|
||||
else
|
||||
m.particleFlags = m.particleFlags | PARTICLE_DUST
|
||||
|
||||
m.terrainSoundAddend = SOUND_TERRAIN_SAND << 16
|
||||
play_step_sound(m, 26, 79)
|
||||
end
|
||||
local inward_offset = 25
|
||||
m.marioObj.header.gfx.pos.x = m.marioObj.header.gfx.pos.x + inward_offset * sins(m.faceAngle.y)
|
||||
m.marioObj.header.gfx.pos.z = m.marioObj.header.gfx.pos.z + inward_offset * coss(m.faceAngle.y)
|
||||
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
end
|
||||
hook_mario_action(ACT_DONKEY_CLIMB, {every_frame = act_donkey_climb, gravity = function() end})
|
||||
|
|
@ -1,4 +1,9 @@
|
|||
if not _G.charSelectExists then return end
|
||||
---------------------
|
||||
-- Pauline Moveset --
|
||||
---------------------
|
||||
|
||||
local OmmEnabled = OmmEnabled
|
||||
if not charSelect then return end
|
||||
|
||||
---------------
|
||||
-- Constants --
|
||||
|
|
@ -74,12 +79,12 @@ local CAPPY_EVENT_UNLOAD = 5
|
|||
local CAPPY_EVENT_BOUNCE = 6
|
||||
|
||||
-- Actions
|
||||
local ACT_CAPPY_THROW_GROUND = allocate_mario_action(ACT_GROUP_MOVING | ACT_FLAG_MOVING)
|
||||
local ACT_CAPPY_THROW_AIRBORNE = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR)
|
||||
local ACT_CAPPY_BOUNCE = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
local ACT_CAPPY_VAULT = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
local ACT_CAPPY_RAINBOW_SPIN = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_ATTACKING)
|
||||
local ACT_CAPPY_THROW_WATER = allocate_mario_action(ACT_GROUP_SUBMERGED | ACT_FLAG_SWIMMING)
|
||||
_G.ACT_CAPPY_THROW_GROUND = allocate_mario_action(ACT_GROUP_MOVING | ACT_FLAG_MOVING)
|
||||
_G.ACT_CAPPY_THROW_AIRBORNE = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR)
|
||||
_G.ACT_CAPPY_BOUNCE = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
_G.ACT_CAPPY_VAULT = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
_G.ACT_CAPPY_RAINBOW_SPIN = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_ATTACKING)
|
||||
_G.ACT_CAPPY_THROW_WATER = allocate_mario_action(ACT_GROUP_SUBMERGED | ACT_FLAG_SWIMMING)
|
||||
|
||||
-- Animations
|
||||
local MARIO_ANIM_PAULINE_CAPPY_VAULT = "anim_pauline_cappy_vault"
|
||||
|
|
@ -135,11 +140,10 @@ local function mario_anim_play_custom(m, animName, animAccel)
|
|||
m.marioObj.header.gfx.animInfo.animAccel = animAccel or 0x10000
|
||||
end
|
||||
|
||||
-- Hacky way to get Pauline
|
||||
local function get_pauline()
|
||||
for i = 1, #extraCharacters do
|
||||
local extraCharacter = extraCharacters[i]
|
||||
if extraCharacter.name == "Pauline" then
|
||||
if extraCharacter.tablePos == CT_PAULINE then
|
||||
return extraCharacter
|
||||
end
|
||||
end
|
||||
|
|
@ -147,7 +151,7 @@ local function get_pauline()
|
|||
end
|
||||
|
||||
local function is_pauline(m)
|
||||
return _G.charSelect.character_get_current_number(m.playerIndex) == get_pauline().tablePos
|
||||
return character_get_current_number(m.playerIndex) == CT_PAULINE
|
||||
end
|
||||
|
||||
-----------
|
||||
|
|
@ -172,7 +176,7 @@ local id_bhvCappy = hook_behavior(
|
|||
true,
|
||||
function (o) o.oFlags = o.oFlags | OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE end,
|
||||
function (o) bhv_cappy_loop(o) end,
|
||||
"bhvCappy"
|
||||
"bhvPaulineCappy"
|
||||
)
|
||||
|
||||
local function cappy_get_object(m)
|
||||
|
|
@ -897,7 +901,6 @@ local function cappy_process_mario_interactions(cappy)
|
|||
if cappy_mario_can_bounce() then
|
||||
local marioObj = m0.marioObj
|
||||
obj_set_pos(marioObj, m0.pos.x, m0.pos.y, m0.pos.z)
|
||||
marioObj.hitboxRadius = 50
|
||||
local obj = obj_get_first_with_behavior_id(id_bhvCappy)
|
||||
while obj ~= nil do
|
||||
if (obj.oSubAction == 1 and -- Cappy is spawned
|
||||
|
|
@ -913,7 +916,12 @@ local function cappy_process_mario_interactions(cappy)
|
|||
if (marioObj.oIntangibleTimer == 0 or mAction == ACT_BUBBLED) then
|
||||
|
||||
-- Check hitbox overlap
|
||||
if obj_check_hitbox_overlap(marioObj, obj) then
|
||||
local marioHitboxRadius = marioObj.hitboxRadius
|
||||
marioObj.hitboxRadius = 50
|
||||
local hitboxOverlap = obj_check_hitbox_overlap(marioObj, obj)
|
||||
marioObj.hitboxRadius = marioHitboxRadius
|
||||
|
||||
if hitboxOverlap then
|
||||
local marioGfx = marioObj.header.gfx
|
||||
|
||||
-- Pop bubble
|
||||
|
|
@ -1175,7 +1183,7 @@ end
|
|||
local function cappy_update(m, cappy)
|
||||
|
||||
-- Unload Cappy if...
|
||||
if (_G.OmmEnabled or -- OMM Rebirth is enabled
|
||||
if (OmmEnabled or -- OMM Rebirth is enabled
|
||||
not is_pauline(m) or -- Not Pauline
|
||||
not gNetworkPlayers[m.playerIndex].connected or -- Not connected
|
||||
not is_player_active(m) -- Not active
|
||||
|
|
@ -1296,7 +1304,6 @@ function pauline_update(m)
|
|||
end
|
||||
end
|
||||
cappy_process_mario_interactions(cappy)
|
||||
m.marioObj.hitboxRadius = 37
|
||||
end
|
||||
|
||||
-- Process Cappy events
|
||||
59
mods/char-select-extra-chars-plus/moveset-peach.lua
Normal file
59
mods/char-select-extra-chars-plus/moveset-peach.lua
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
-------------------
|
||||
-- Peach Moveset --
|
||||
-------------------
|
||||
|
||||
if not charSelect then return end
|
||||
|
||||
local floatActs = {
|
||||
[ACT_JUMP] = true,
|
||||
[ACT_DOUBLE_JUMP] = true,
|
||||
[ACT_TRIPLE_JUMP] = true,
|
||||
[ACT_LONG_JUMP] = true,
|
||||
[ACT_BACKFLIP] = true,
|
||||
[ACT_SIDE_FLIP] = true,
|
||||
[ACT_WALL_KICK_AIR] = true,
|
||||
}
|
||||
|
||||
_G.ACT_FLOAT = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_MOVING)
|
||||
|
||||
--- @param m MarioState
|
||||
local function act_float(m)
|
||||
-- apply movement when using action
|
||||
common_air_action_step(m, ACT_JUMP_LAND, CHAR_ANIM_BEND_KNESS_RIDING_SHELL, AIR_STEP_NONE)
|
||||
|
||||
-- setup when action starts (horizontal speed and voiceline)
|
||||
if m.actionTimer == 0 then
|
||||
play_character_sound(m, CHAR_SOUND_HELLO)
|
||||
end
|
||||
|
||||
if m.forwardVel > 20 then
|
||||
m.forwardVel = m.forwardVel - 0.5
|
||||
end
|
||||
|
||||
-- Slowly decend
|
||||
m.vel.y = -1
|
||||
set_mario_particle_flags(m, PARTICLE_SPARKLES, 0)
|
||||
|
||||
-- avoid issue with flying and then make the hover end after 2 secs or when stopping holding the button
|
||||
if m.prevAction ~= ACT_TRIPLE_JUMP and (m.flags & MARIO_WING_CAP) ~= 0 then
|
||||
if m.actionTimer >= 50 or (m.controller.buttonDown & A_BUTTON) == 0 then
|
||||
set_mario_action(m, ACT_FREEFALL, 0)
|
||||
end
|
||||
else
|
||||
if m.actionTimer >= 50 or (m.controller.buttonDown & A_BUTTON) == 0 then
|
||||
set_mario_action(m, ACT_FREEFALL, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- increment the action timer to make the hover stop
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
end
|
||||
|
||||
--- @param m MarioState
|
||||
function peach_update(m)
|
||||
if (m.input & INPUT_A_DOWN) ~= 0 and m.vel.y < -10 and m.prevAction ~= ACT_FLOAT and floatActs[m.action] then
|
||||
set_mario_action(m, ACT_FLOAT, 0)
|
||||
end
|
||||
end
|
||||
|
||||
hook_mario_action(ACT_FLOAT, act_float)
|
||||
203
mods/char-select-extra-chars-plus/moveset-rosalina.lua
Normal file
203
mods/char-select-extra-chars-plus/moveset-rosalina.lua
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
----------------------
|
||||
-- Rosalina Moveset --
|
||||
----------------------
|
||||
|
||||
if not charSelect then return end
|
||||
|
||||
_G.ACT_JUMP_TWIRL = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_ATTACKING)
|
||||
E_MODEL_TWIRL_EFFECT = smlua_model_util_get_id("spin_attack_geo")
|
||||
|
||||
---@param o Object
|
||||
local function bhv_spin_attack_init(o)
|
||||
o.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE -- Allows you to change the position and angle
|
||||
end
|
||||
|
||||
---@param o Object
|
||||
local function bhv_spin_attack_loop(o)
|
||||
|
||||
-- Retrieves the Mario state corresponding to its global index
|
||||
local m = gMarioStates[network_local_index_from_global(o.globalPlayerIndex)]
|
||||
if m == nil or m.marioObj == nil then
|
||||
obj_mark_for_deletion(o)
|
||||
return
|
||||
end
|
||||
|
||||
o.parentObj = m.marioObj -- Sets the Mario object as its parent
|
||||
cur_obj_set_pos_relative_to_parent(0, 20, 0) -- Makes it move to its parent's position
|
||||
|
||||
o.oFaceAngleYaw = o.oFaceAngleYaw + 0x2000 -- Rotates it
|
||||
|
||||
if m.action ~= ACT_JUMP_TWIRL or o.oTimer > 15 then -- Deletes itself once the action changes
|
||||
obj_mark_for_deletion(o)
|
||||
end
|
||||
end
|
||||
|
||||
local id_bhvTwirlEffect = hook_behavior(nil, OBJ_LIST_GENACTOR, true, bhv_spin_attack_init, bhv_spin_attack_loop,
|
||||
"bhvRosalinaTwirlEffect")
|
||||
|
||||
-- Spinable actions, these are actions you can spin out of that don't normally allow a kick/dive
|
||||
local extraSpinActs = {
|
||||
[ACT_LONG_JUMP] = true,
|
||||
[ACT_BACKFLIP] = true,
|
||||
}
|
||||
|
||||
-- Spin overridable actions, these are overriden instantly
|
||||
local spinOverrides = {
|
||||
[ACT_PUNCHING] = true,
|
||||
[ACT_MOVE_PUNCHING] = true,
|
||||
[ACT_JUMP_KICK] = true,
|
||||
[ACT_DIVE] = true
|
||||
}
|
||||
|
||||
local ROSALINA_SOUND_SPIN = audio_sample_load("z_sfx_rosalina_spinattack.ogg") -- Load audio sample
|
||||
|
||||
---@param m MarioState
|
||||
function act_jump_twirl(m)
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
|
||||
if m.actionTimer >= 15 then
|
||||
return set_mario_action(m, ACT_FREEFALL, 0) -- End the action
|
||||
end
|
||||
|
||||
if m.actionTimer == 0 then
|
||||
m.marioObj.header.gfx.animInfo.animID = -1
|
||||
play_character_sound(m, CHAR_SOUND_HELLO) -- Plays the character sound
|
||||
audio_sample_play(ROSALINA_SOUND_SPIN, m.pos, 1) -- Plays the spin sound sample
|
||||
m.particleFlags = m.particleFlags | ACTIVE_PARTICLE_SPARKLES -- Spawns sparkle particles
|
||||
|
||||
if e.rosalina.canSpin then
|
||||
m.vel.y = 30 -- Initial upward velocity
|
||||
e.rosalina.canSpin = false
|
||||
|
||||
-- Spawn the spin effect
|
||||
if m.playerIndex == 0 then
|
||||
spawn_sync_object(id_bhvTwirlEffect, E_MODEL_TWIRL_EFFECT, m.pos.x, m.pos.y, m.pos.z, function(o)
|
||||
o.globalPlayerIndex = m.marioObj.globalPlayerIndex
|
||||
end)
|
||||
end
|
||||
else
|
||||
m.vel.y = math.max(m.vel.y, 0)
|
||||
end
|
||||
m.marioObj.hitboxRadius = 100 -- Damage hitbox
|
||||
else
|
||||
m.marioObj.hitboxRadius = 37 -- Reset the hitbox after initial hit
|
||||
end
|
||||
|
||||
common_air_action_step(m, ACT_FREEFALL_LAND, CHAR_ANIM_BEND_KNESS_RIDING_SHELL, AIR_STEP_NONE)
|
||||
|
||||
m.marioBodyState.handState = MARIO_HAND_PEACE_SIGN -- Hand State
|
||||
|
||||
-- Increments the action timer
|
||||
m.actionTimer = m.actionTimer + 1
|
||||
end
|
||||
|
||||
---@param m MarioState
|
||||
---@param o Object
|
||||
---@param intType InteractionType
|
||||
function rosalina_allow_interact(m, o, intType)
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
if m.action == ACT_JUMP_TWIRL and intType == INTERACT_GRABBABLE and o.oInteractionSubtype & INT_SUBTYPE_NOT_GRABBABLE == 0 then
|
||||
local angleTo = mario_obj_angle_to_object(m, o)
|
||||
if (o.oInteractionSubtype & INT_SUBTYPE_GRABS_MARIO ~= 0 or obj_has_behavior_id(o, id_bhvBowser) ~= 0) then -- heavy grab objects
|
||||
if m.pos.y - m.floorHeight < 100 and abs_angle_diff(m.faceAngle.y, angleTo) < 0x4000 then
|
||||
m.action = ACT_MOVE_PUNCHING
|
||||
m.actionArg = 1
|
||||
end
|
||||
elseif not e.rosalina.orbitObjActive then -- light grab objects
|
||||
m.usedObj = o
|
||||
e.rosalina.orbitObjActive = true
|
||||
e.rosalina.orbitObjDist = 160 - m.actionTimer * 2
|
||||
e.rosalina.orbitObjAngle = angleTo
|
||||
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param m MarioState
|
||||
function rosalina_update(m)
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
|
||||
if m.controller.buttonPressed & B_BUTTON ~= 0 and extraSpinActs[m.action] then
|
||||
return set_mario_action(m, ACT_JUMP_TWIRL, 0)
|
||||
end
|
||||
|
||||
--if m.action & ACT_FLAG_AIR == 0 and m.playerIndex == 0 then
|
||||
-- e.rosalina.canSpin = true
|
||||
--end
|
||||
|
||||
if m.action ~= ACT_JUMP_TWIRL and m.marioObj.hitboxRadius ~= 37 then
|
||||
m.marioObj.hitboxRadius = 37
|
||||
end
|
||||
|
||||
if e.rosalina.orbitObjActive then
|
||||
local o = m.usedObj
|
||||
|
||||
if not o or o.activeFlags == ACTIVE_FLAG_DEACTIVATED then
|
||||
e.rosalina.orbitObjActive = false
|
||||
o.oIntangibleTimer = 0
|
||||
|
||||
if m.playerIndex == 0 then m.usedObj = nil end
|
||||
return
|
||||
end
|
||||
|
||||
e.rosalina.orbitObjDist = e.rosalina.orbitObjDist - 6
|
||||
if e.rosalina.orbitObjDist >= 90 then
|
||||
e.rosalina.orbitObjAngle = e.rosalina.orbitObjAngle + 0x1800
|
||||
else
|
||||
e.rosalina.orbitObjAngle = approach_s16_asymptotic(e.rosalina.orbitObjAngle, m.faceAngle.y, 4)
|
||||
end
|
||||
|
||||
o.oPosX = m.pos.x + sins(e.rosalina.orbitObjAngle) * e.rosalina.orbitObjDist
|
||||
o.oPosZ = m.pos.z + coss(e.rosalina.orbitObjAngle) * e.rosalina.orbitObjDist
|
||||
o.oPosY = approach_f32_asymptotic(o.oPosY, m.pos.y + 50, 0.25)
|
||||
|
||||
obj_set_vel(o, 0, 0, 0)
|
||||
o.oForwardVel = 0
|
||||
o.oIntangibleTimer = -1
|
||||
|
||||
if m.playerIndex == 0 and e.rosalina.orbitObjDist <= 80 then
|
||||
e.rosalina.orbitObjActive = false
|
||||
o.oIntangibleTimer = 0
|
||||
|
||||
if m.action & (ACT_FLAG_INVULNERABLE | ACT_FLAG_INTANGIBLE) ~= 0 or m.action & ACT_GROUP_MASK >= ACT_GROUP_SUBMERGED then
|
||||
m.usedObj = nil
|
||||
else
|
||||
o.oIntangibleTimer = 0
|
||||
m.interactObj = o
|
||||
m.usedObj = o
|
||||
if o.oSyncID ~= 0 then network_send_object(o, true) end
|
||||
|
||||
if m.action & ACT_FLAG_AIR == 0 then
|
||||
set_mario_action(m, ACT_HOLD_IDLE, 0)
|
||||
mario_grab_used_object(m)
|
||||
else
|
||||
set_mario_action(m, ACT_HOLD_FREEFALL, 0)
|
||||
mario_grab_used_object(m)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param m MarioState
|
||||
function rosalina_before_action(m, action)
|
||||
if not action then return end
|
||||
|
||||
local e = gCharacterStates[m.playerIndex]
|
||||
|
||||
if spinOverrides[action] and m.controller.buttonDown & (Z_TRIG | A_BUTTON) == 0 and m.action ~= ACT_STEEP_JUMP then
|
||||
return ACT_JUMP_TWIRL
|
||||
end
|
||||
|
||||
if action & ACT_FLAG_AIR == 0 and not e.rosalina.canSpin then
|
||||
play_sound_with_freq_scale(SOUND_GENERAL_COIN_SPURT_EU, m.marioObj.header.gfx.cameraToObject, 1.6)
|
||||
if m.playerIndex == 0 then
|
||||
spawn_sync_object(id_bhvSparkle, E_MODEL_SPARKLES_ANIMATION, m.pos.x, m.pos.y + 200, m.pos.z,
|
||||
function(o) obj_scale(o, 0.75) end)
|
||||
end
|
||||
e.rosalina.canSpin = true
|
||||
end
|
||||
end
|
||||
|
||||
hook_mario_action(ACT_JUMP_TWIRL, act_jump_twirl, INT_KICK)
|
||||
1975
mods/char-select-extra-chars-plus/moveset-sonic.lua
Normal file
1975
mods/char-select-extra-chars-plus/moveset-sonic.lua
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue