Merge branch 'dev' into screen-shader-effects

This commit is contained in:
Agent X 2026-04-08 22:56:08 -04:00
commit a194f4eaa1
876 changed files with 791 additions and 68644 deletions

View file

@ -118,6 +118,7 @@ override_disallowed_functions = {
"src/game/mario.h": [ " init_mario" ],
"src/pc/djui/djui_console.h": [ " djui_console_create", "djui_console_message_create", "djui_console_message_dequeue" ],
"src/pc/djui/djui_chat_message.h": [ "create_from" ],
"src/pc/djui/djui_hud_utils.h": [ "djui_hud_clear_interp_data" ],
"src/game/interaction.h": [ "process_interaction", "_handle_" ],
"src/game/sound_init.h": [ "_loop_", "thread4_", "set_sound_mode" ],
"src/pc/network/network_utils.h": [ "network_get_player_text_color[^_]" ],

View file

@ -3837,7 +3837,7 @@ function djui_hud_set_font(fontType)
end
--- @return DjuiColor
--- Gets the current DJUI HUD color
--- Gets the current DJUI HUD global color
function djui_hud_get_color()
-- ...
end
@ -3846,16 +3846,36 @@ end
--- @param g integer
--- @param b integer
--- @param a integer
--- Sets the current DJUI HUD color
--- Sets the current DJUI HUD global color
function djui_hud_set_color(r, g, b, a)
-- ...
end
--- Resets the current DJUI HUD color
--- Resets the current DJUI HUD global color
function djui_hud_reset_color()
-- ...
end
--- @return DjuiColor
--- Gets the current DJUI HUD text default color. This color is overridden by color codes
function djui_hud_get_text_color()
-- ...
end
--- @param r integer
--- @param g integer
--- @param b integer
--- @param a integer
--- Sets the current DJUI HUD text default color. This color is overridden by color codes
function djui_hud_set_text_color(r, g, b, a)
-- ...
end
--- Resets the current DJUI HUD text default color. This color is overridden by color codes
function djui_hud_reset_text_color()
-- ...
end
--- @return integer rotation
--- @return number pivotX
--- @return number pivotY
@ -4013,8 +4033,9 @@ function djui_hud_reset_scissor()
end
--- @param message string
--- @return number
--- Measures the length of `message` in the current font
--- @return number width
--- @return number height
--- Measures the width and height of `message` in the current font
function djui_hud_measure_text(message)
-- ...
end
@ -7762,10 +7783,18 @@ function mod_storage_save(key, value)
-- ...
end
--- @param key string
--- @param value integer
--- @return boolean
--- Saves a `key` corresponding to an integer `value` to mod storage
function mod_storage_save_integer(key, value)
-- ...
end
--- @param key string
--- @param value number
--- @return boolean
--- Saves a `key` corresponding to a float `value` to mod storage
--- Saves a `key` corresponding to a number `value` to mod storage
function mod_storage_save_number(key, value)
-- ...
end
@ -7785,9 +7814,16 @@ function mod_storage_load(key)
-- ...
end
--- @param key string
--- @return integer
--- Loads an integer `value` from a `key` in mod storage
function mod_storage_load_integer(key)
-- ...
end
--- @param key string
--- @return number
--- Loads a float `value` from a `key` in mod storage
--- Loads a number `value` from a `key` in mod storage
function mod_storage_load_number(key)
-- ...
end
@ -9077,12 +9113,6 @@ function cur_obj_check_anim_frame_in_range(startFrame, rangeLength)
-- ...
end
--- @param a0 Pointer_integer
--- @return integer
function cur_obj_check_frame_prior_current_frame(a0)
-- ...
end
--- @param m MarioState
--- @return integer
function mario_is_in_air_action(m)

View file

@ -3,7 +3,9 @@
extern "C" {
#include "include/surface_terrains.h"
#include "include/level_misc_macros.h"
#include "include/special_presets.h"
#include "include/special_preset_names.h"
#include "src/engine/surface_load.h"
}
// Free data pointers, but keep nodes and tokens intact
@ -34,12 +36,32 @@ struct CollisionValidationData {
u32 vtxCount;
u32 triAlloc;
u32 triCount;
s16 surfaceType;
u32 specialAlloc;
u32 specialCount;
u32 waterBoxAlloc;
u32 waterBoxCount;
};
static u8 GetSpecialObjectType(u8 preset) {
for (s32 i = 0; i < ARRAY_COUNT(SpecialObjectPresets); ++i) {
if (SpecialObjectPresets[i].preset_id == preset) {
return SpecialObjectPresets[i].type;
}
}
return SPTYPE_UNKNOWN;
}
static const char *GetCorrectSpecialObjectCommand(u8 presetType) {
switch (presetType) {
case SPTYPE_NO_YROT_OR_PARAMS: return "SPECIAL_OBJECT";
case SPTYPE_YROT_NO_PARAMS: return "SPECIAL_OBJECT_WITH_YAW";
case SPTYPE_PARAMS_AND_YROT: return "SPECIAL_OBJECT_WITH_YAW_AND_PARAM";
case SPTYPE_DEF_PARAM_AND_YROT: return "SPECIAL_OBJECT_WITH_YAW";
default: return "";
}
}
static void ValidateColSectionChange(GfxData* aGfxData, struct CollisionValidationData& aColValData, u8 section) {
if (aColValData.section == COL_SECTION_END) {
PrintDataError("Found new col section after COL_END");
@ -67,51 +89,70 @@ static void ValidateColInit(GfxData* aGfxData, struct CollisionValidationData& a
ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_VTX);
}
static void ValidateColVertexInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0) {
static void ValidateColVertexInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 vertexCount) {
if (strcmp(aColValData.lastSymbol, "COL_INIT") != 0) {
PrintDataError("COL_VERTEX_INIT found outside of vertex section");
}
if (arg0 < 0) {
PrintDataError("COL_VERTEX_INIT with a negative count: %d", arg0);
if (vertexCount < 0) {
PrintDataError("COL_VERTEX_INIT with a negative count: %d", vertexCount);
}
aColValData.vtxAlloc = arg0;
aColValData.vtxAlloc = vertexCount;
aColValData.vtxCount = 0;
}
static void ValidateColVertex(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2) {
static void ValidateColVertex(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 x, s16 y, s16 z) {
if (aColValData.section != COL_SECTION_VTX) {
PrintDataError("COL_VERTEX found outside of vertex section");
}
aColValData.vtxCount++;
}
static void ValidateColTriInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1) {
if (arg1 < 0) {
PrintDataError("COL_TRI_INIT with a negative count: %d", arg1);
static void ValidateColTriInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 surfaceType, s16 triangleCount) {
if (triangleCount < 0) {
PrintDataError("COL_TRI_INIT with a negative count: %d", triangleCount);
}
ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_TRI);
aColValData.triAlloc = arg1;
aColValData.triAlloc = triangleCount;
aColValData.triCount = 0;
aColValData.surfaceType = surfaceType;
}
static void ValidateColTri(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2) {
static void ValidateColTri(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 vertex0, s16 vertex1, s16 vertex2) {
if (aColValData.section != COL_SECTION_TRI) {
PrintDataError("COL_TRI found outside of triangle section");
}
if (arg0 < 0 || arg0 > aColValData.vtxCount) {
PrintDataError("COL_TRI used vertex outside of known range for first param: %d", arg0);
if (surface_has_force(aColValData.surfaceType)) {
PrintDataError("COL_TRI cannot be used by surface types with a force parameter: %d (use COL_TRI_SPECIAL instead)", aColValData.surfaceType);
}
if (arg1 < 0 || arg1 > aColValData.vtxCount) {
PrintDataError("COL_TRI used vertex outside of known range for second param: %d", arg1);
if (vertex0 < 0 || vertex0 > aColValData.vtxCount) {
PrintDataError("COL_TRI used vertex outside of known range for first param: %d", vertex0);
}
if (arg2 < 0 || arg2 > aColValData.vtxCount) {
PrintDataError("COL_TRI used vertex outside of known range for third param: %d", arg2);
if (vertex1 < 0 || vertex1 > aColValData.vtxCount) {
PrintDataError("COL_TRI used vertex outside of known range for second param: %d", vertex1);
}
if (vertex2 < 0 || vertex2 > aColValData.vtxCount) {
PrintDataError("COL_TRI used vertex outside of known range for third param: %d", vertex2);
}
aColValData.triCount++;
}
static void ValidateColTriSpecial(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3) {
ValidateColTri(aGfxData, aColValData, arg0, arg1, arg2);
static void ValidateColTriSpecial(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 vertex0, s16 vertex1, s16 vertex2, s16 force) {
if (aColValData.section != COL_SECTION_TRI) {
PrintDataError("COL_TRI_SPECIAL found outside of triangle section");
}
if (!surface_has_force(aColValData.surfaceType)) {
PrintDataError("COL_TRI_SPECIAL cannot be used by surface types with no force parameter: %d (use COL_TRI instead)", aColValData.surfaceType);
}
if (vertex0 < 0 || vertex0 > aColValData.vtxCount) {
PrintDataError("COL_TRI_SPECIAL used vertex outside of known range for first param: %d", vertex0);
}
if (vertex1 < 0 || vertex1 > aColValData.vtxCount) {
PrintDataError("COL_TRI_SPECIAL used vertex outside of known range for second param: %d", vertex1);
}
if (vertex2 < 0 || vertex2 > aColValData.vtxCount) {
PrintDataError("COL_TRI_SPECIAL used vertex outside of known range for third param: %d", vertex2);
}
aColValData.triCount++;
}
static void ValidateColStop(GfxData* aGfxData, struct CollisionValidationData& aColValData) {
@ -122,49 +163,70 @@ static void ValidateColEnd(GfxData* aGfxData, struct CollisionValidationData& aC
ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_END);
}
static void ValidateColSpecialInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0) {
if (arg0 < 0) {
PrintDataError("COL_SPECIAL_INIT with a negative count: %d", arg0);
static void ValidateColSpecialInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 specialCount) {
if (specialCount < 0) {
PrintDataError("COL_SPECIAL_INIT with a negative count: %d", specialCount);
}
ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_SPECIAL);
aColValData.specialAlloc = arg0;
aColValData.specialAlloc = specialCount;
aColValData.specialCount = 0;
}
static void ValidateColWaterBoxInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0) {
if (arg0 < 0) {
PrintDataError("COL_WATER_BOX_INIT with a negative count: %d", arg0);
static void ValidateColWaterBoxInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 waterBoxCount) {
if (waterBoxCount < 0) {
PrintDataError("COL_WATER_BOX_INIT with a negative count: %d", waterBoxCount);
}
ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_WATER_BOX);
aColValData.waterBoxAlloc = arg0;
aColValData.waterBoxAlloc = waterBoxCount;
aColValData.waterBoxCount = 0;
}
static void ValidateColWaterBox(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4, s16 arg5) {
static void ValidateColWaterBox(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 id, s16 x1, s16 z1, s16 x2, s16 z2, s16 y) {
if (aColValData.section != COL_SECTION_WATER_BOX) {
PrintDataError("COL_WATER_BOX found outside of water box section");
}
aColValData.waterBoxCount++;
}
static void ValidateColSpecialObject(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3) {
static void ValidateColSpecialObject(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 preset, s16 posX, s16 posY, s16 posZ) {
if (aColValData.section != COL_SECTION_SPECIAL) {
PrintDataError("SPECIAL_OBJECT found outside of special section");
}
u8 presetType = GetSpecialObjectType(preset);
if (presetType == SPTYPE_UNKNOWN) {
PrintDataError("SPECIAL_OBJECT has invalid preset: %d", preset);
}
if (presetType != SPTYPE_NO_YROT_OR_PARAMS) {
PrintDataError("SPECIAL_OBJECT cannot be used with preset: %d (use %s instead)", preset, GetCorrectSpecialObjectCommand(presetType));
}
aColValData.specialCount++;
}
static void ValidateColSpecialObjectWithYaw(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4) {
static void ValidateColSpecialObjectWithYaw(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 preset, s16 posX, s16 posY, s16 posZ, s16 yaw) {
if (aColValData.section != COL_SECTION_SPECIAL) {
PrintDataError("SPECIAL_OBJECT_WITH_YAW found outside of special section");
}
u8 presetType = GetSpecialObjectType(preset);
if (presetType == SPTYPE_UNKNOWN) {
PrintDataError("SPECIAL_OBJECT_WITH_YAW has invalid preset: %d", preset);
}
if (presetType != SPTYPE_YROT_NO_PARAMS && presetType != SPTYPE_DEF_PARAM_AND_YROT) {
PrintDataError("SPECIAL_OBJECT_WITH_YAW cannot be used with preset: %d (use %s instead)", preset, GetCorrectSpecialObjectCommand(presetType));
}
aColValData.specialCount++;
}
static void ValidateColSpecialObjectWithYawAndParam(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4, s16 arg5) {
static void ValidateColSpecialObjectWithYawAndParam(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 preset, s16 posX, s16 posY, s16 posZ, s16 yaw, s16 param) {
if (aColValData.section != COL_SECTION_SPECIAL) {
PrintDataError("SPECIAL_OBJECT_WITH_YAW_AND_PARAM found outside of special section");
}
u8 presetType = GetSpecialObjectType(preset);
if (presetType == SPTYPE_UNKNOWN) {
PrintDataError("SPECIAL_OBJECT_WITH_YAW_AND_PARAM has invalid preset: %d", preset);
}
if (presetType != SPTYPE_PARAMS_AND_YROT) {
PrintDataError("SPECIAL_OBJECT_WITH_YAW_AND_PARAM cannot be used with preset: %d (use %s instead)", preset, GetCorrectSpecialObjectCommand(presetType));
}
aColValData.specialCount++;
}

View file

@ -8,7 +8,7 @@ extern "C" {
#include "behavior_data.h"
#include "pc/lua/smlua_hooks.h"
s8 geo_get_processing_mario_index(void);
s8 geo_get_processing_mario_index(struct Object *obj);
}
//
@ -77,7 +77,7 @@ void DynOS_Anim_Swap(void *aPtr) {
// Animation index
s32 _AnimIndex = -1;
s8 index = geo_get_processing_mario_index();
s8 index = geo_get_processing_mario_index(_Object);
if (index != -1) {
_AnimIndex = RetrieveCurrentMarioAnimationIndex(index);

View file

@ -2037,6 +2037,7 @@ static const DynosBuiltinFunction sDynosBuiltinFuncs[] = {
define_builtin_function(bhv_ambient_light_update, FUNCTION_BHV),
define_builtin_function(bhv_point_light_init, FUNCTION_BHV),
define_builtin_function(bhv_point_light_loop, FUNCTION_BHV),
define_builtin_function(geo_switch_character_type_ext, FUNCTION_GEO),
};
static const char *sDynosBuiltinFuncTypeNames[] = {

View file

@ -151,7 +151,7 @@ PackData* DynOS_Pack_Add(const SysPath& aPath) {
const char* displayName = aPath.c_str();
const char* ctoken = displayName;
while (*ctoken != '\0') {
if (*ctoken == '/' || *ctoken == '\\') {
if (*ctoken == *PATH_SEPARATOR || *ctoken == *PATH_SEPARATOR_ALT) {
if (*(ctoken + 1) != '\0') {
displayName = (ctoken + 1);
}

View file

@ -2858,7 +2858,7 @@ Sets the current DJUI HUD font
## [djui_hud_get_color](#djui_hud_get_color)
### Description
Gets the current DJUI HUD color
Gets the current DJUI HUD global color
### Lua Example
`local djuiColorValue = djui_hud_get_color()`
@ -2879,7 +2879,7 @@ Gets the current DJUI HUD color
## [djui_hud_set_color](#djui_hud_set_color)
### Description
Sets the current DJUI HUD color
Sets the current DJUI HUD global color
### Lua Example
`djui_hud_set_color(r, g, b, a)`
@ -2905,7 +2905,7 @@ Sets the current DJUI HUD color
## [djui_hud_reset_color](#djui_hud_reset_color)
### Description
Resets the current DJUI HUD color
Resets the current DJUI HUD global color
### Lua Example
`djui_hud_reset_color()`
@ -2923,6 +2923,74 @@ Resets the current DJUI HUD color
<br />
## [djui_hud_get_text_color](#djui_hud_get_text_color)
### Description
Gets the current DJUI HUD text default color. This color is overridden by color codes
### Lua Example
`local djuiColorValue = djui_hud_get_text_color()`
### Parameters
- None
### Returns
- [DjuiColor](structs.md#DjuiColor)
### C Prototype
`struct DjuiColor* djui_hud_get_text_color(void);`
[:arrow_up_small:](#)
<br />
## [djui_hud_set_text_color](#djui_hud_set_text_color)
### Description
Sets the current DJUI HUD text default color. This color is overridden by color codes
### Lua Example
`djui_hud_set_text_color(r, g, b, a)`
### Parameters
| Field | Type |
| ----- | ---- |
| r | `integer` |
| g | `integer` |
| b | `integer` |
| a | `integer` |
### Returns
- None
### C Prototype
`void djui_hud_set_text_color(u8 r, u8 g, u8 b, u8 a);`
[:arrow_up_small:](#)
<br />
## [djui_hud_reset_text_color](#djui_hud_reset_text_color)
### Description
Resets the current DJUI HUD text default color. This color is overridden by color codes
### Lua Example
`djui_hud_reset_text_color()`
### Parameters
- None
### Returns
- None
### C Prototype
`void djui_hud_reset_text_color(void);`
[:arrow_up_small:](#)
<br />
## [djui_hud_get_rotation](#djui_hud_get_rotation)
### Description
@ -3443,10 +3511,10 @@ Resets the scissor rectangle to a fullscreen state
## [djui_hud_measure_text](#djui_hud_measure_text)
### Description
Measures the length of `message` in the current font
Measures the width and height of `message` in the current font
### Lua Example
`local numberValue = djui_hud_measure_text(message)`
`local width, height = djui_hud_measure_text(message)`
### Parameters
| Field | Type |
@ -3455,9 +3523,10 @@ Measures the length of `message` in the current font
### Returns
- `number`
- `number`
### C Prototype
`f32 djui_hud_measure_text(const char* message);`
`void djui_hud_measure_text(const char* message, RET f32 *width, RET f32 *height);`
[:arrow_up_small:](#)

View file

@ -2191,10 +2191,34 @@ Saves a `key` corresponding to a string `value` to mod storage
<br />
## [mod_storage_save_integer](#mod_storage_save_integer)
### Description
Saves a `key` corresponding to an integer `value` to mod storage
### Lua Example
`local booleanValue = mod_storage_save_integer(key, value)`
### Parameters
| Field | Type |
| ----- | ---- |
| key | `string` |
| value | `integer` |
### Returns
- `boolean`
### C Prototype
`bool mod_storage_save_integer(const char* key, lua_Integer value);`
[:arrow_up_small:](#)
<br />
## [mod_storage_save_number](#mod_storage_save_number)
### Description
Saves a `key` corresponding to a float `value` to mod storage
Saves a `key` corresponding to a number `value` to mod storage
### Lua Example
`local booleanValue = mod_storage_save_number(key, value)`
@ -2209,7 +2233,7 @@ Saves a `key` corresponding to a float `value` to mod storage
- `boolean`
### C Prototype
`bool mod_storage_save_number(const char* key, f32 value);`
`bool mod_storage_save_number(const char* key, lua_Number value);`
[:arrow_up_small:](#)
@ -2262,10 +2286,33 @@ Loads a string `value` from a `key` in mod storage
<br />
## [mod_storage_load_integer](#mod_storage_load_integer)
### Description
Loads an integer `value` from a `key` in mod storage
### Lua Example
`local integerValue = mod_storage_load_integer(key)`
### Parameters
| Field | Type |
| ----- | ---- |
| key | `string` |
### Returns
- `integer`
### C Prototype
`lua_Integer mod_storage_load_integer(const char* key);`
[:arrow_up_small:](#)
<br />
## [mod_storage_load_number](#mod_storage_load_number)
### Description
Loads a float `value` from a `key` in mod storage
Loads a number `value` from a `key` in mod storage
### Lua Example
`local numberValue = mod_storage_load_number(key)`
@ -2279,7 +2326,7 @@ Loads a float `value` from a `key` in mod storage
- `number`
### C Prototype
`f32 mod_storage_load_number(const char* key);`
`lua_Number mod_storage_load_number(const char* key);`
[:arrow_up_small:](#)

View file

@ -1615,26 +1615,6 @@ Multiplies a vector by the transpose of a matrix of the form: `| ? ? ? 0 |` `| ?
<br />
## [cur_obj_check_frame_prior_current_frame](#cur_obj_check_frame_prior_current_frame)
### Lua Example
`local integerValue = cur_obj_check_frame_prior_current_frame(a0)`
### Parameters
| Field | Type |
| ----- | ---- |
| a0 | `Pointer` <`integer`> |
### Returns
- `integer`
### C Prototype
`s32 cur_obj_check_frame_prior_current_frame(s16 *a0);`
[:arrow_up_small:](#)
<br />
## [mario_is_in_air_action](#mario_is_in_air_action)
### Lua Example

View file

@ -760,6 +760,9 @@
- [djui_hud_get_color](functions-3.md#djui_hud_get_color)
- [djui_hud_set_color](functions-3.md#djui_hud_set_color)
- [djui_hud_reset_color](functions-3.md#djui_hud_reset_color)
- [djui_hud_get_text_color](functions-3.md#djui_hud_get_text_color)
- [djui_hud_set_text_color](functions-3.md#djui_hud_set_text_color)
- [djui_hud_reset_text_color](functions-3.md#djui_hud_reset_text_color)
- [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)
@ -1403,9 +1406,11 @@
- mod_storage.h
- [mod_storage_save](functions-5.md#mod_storage_save)
- [mod_storage_save_integer](functions-5.md#mod_storage_save_integer)
- [mod_storage_save_number](functions-5.md#mod_storage_save_number)
- [mod_storage_save_bool](functions-5.md#mod_storage_save_bool)
- [mod_storage_load](functions-5.md#mod_storage_load)
- [mod_storage_load_integer](functions-5.md#mod_storage_load_integer)
- [mod_storage_load_number](functions-5.md#mod_storage_load_number)
- [mod_storage_load_bool](functions-5.md#mod_storage_load_bool)
- [mod_storage_load_all](functions-5.md#mod_storage_load_all)
@ -1609,7 +1614,6 @@
- [cur_obj_check_if_at_animation_end](functions-6.md#cur_obj_check_if_at_animation_end)
- [cur_obj_check_anim_frame](functions-6.md#cur_obj_check_anim_frame)
- [cur_obj_check_anim_frame_in_range](functions-6.md#cur_obj_check_anim_frame_in_range)
- [cur_obj_check_frame_prior_current_frame](functions-6.md#cur_obj_check_frame_prior_current_frame)
- [mario_is_in_air_action](functions-6.md#mario_is_in_air_action)
- [mario_is_dive_sliding](functions-6.md#mario_is_dive_sliding)
- [cur_obj_set_y_vel_and_animation](functions-6.md#cur_obj_set_y_vel_and_animation)

View file

@ -100,6 +100,7 @@ N64_BINDS = "N64 Ovládání"
EXTRA_BINDS = "Extra Ovládání"
BACKGROUND_GAMEPAD = "Ovladač v pozadí"
DISABLE_GAMEPADS = "Zakažte gamepady"
EXTENDED_REPORTS = "Rozšířené zprávy"
GAMEPAD = "Použít ovladač"
DEADZONE = "Deadzone"
RUMBLE_STRENGTH = "Síla vibrace"

View file

@ -100,6 +100,7 @@ N64_BINDS = "N64 Toetsen"
EXTRA_BINDS = "Extra Toetsen"
BACKGROUND_GAMEPAD = "Achtergrond Gamepad"
DISABLE_GAMEPADS = "Gamepads uitschakelen"
EXTENDED_REPORTS = "Uitgebreide rapporten"
GAMEPAD = "Gamepad"
DEADZONE = "Doode-zone"
RUMBLE_STRENGTH = "Rommel Kracht"

View file

@ -100,6 +100,7 @@ N64_BINDS = "N64 Binds"
EXTRA_BINDS = "Extra Binds"
BACKGROUND_GAMEPAD = "Background Gamepad"
DISABLE_GAMEPADS = "Disable Gamepads"
EXTENDED_REPORTS = "Extended Reports"
GAMEPAD = "Gamepad"
DEADZONE = "Deadzone"
RUMBLE_STRENGTH = "Rumble Strength"

View file

@ -100,6 +100,7 @@ N64_BINDS = "Touches N64"
EXTRA_BINDS = "Touches Supplémentaires"
BACKGROUND_GAMEPAD = "Manette en arrière plan"
DISABLE_GAMEPADS = "Désactiver les manettes de jeu"
EXTENDED_REPORTS = "Rapports détaillés"
GAMEPAD = "Manette"
DEADZONE = "Zone Morte"
RUMBLE_STRENGTH = "Vibrations"

View file

@ -99,6 +99,7 @@ CONTROLS = "STEUERUNG"
N64_BINDS = "N64-Einstellungen"
EXTRA_BINDS = "Zusätzliche Einstellungen"
BACKGROUND_GAMEPAD = "Hintergrund-Gamepad"
EXTENDED_REPORTS = "Erweiterte Berichte"
DISABLE_GAMEPADS = "Gamepads deaktivieren"
GAMEPAD = "Gamepad"
DEADZONE = "Tote Zone"

View file

@ -98,6 +98,7 @@ CONTROLS = "CONTROLLI"
N64_BINDS = "Comandi N64"
EXTRA_BINDS = "Comandi Extra"
BACKGROUND_GAMEPAD = "Attivi in Background"
EXTENDED_REPORTS = "Rapporti estesi"
DISABLE_GAMEPADS = "Disabilita i Gamepad"
GAMEPAD = "Controller"
DEADZONE = "Zona Morta"

View file

@ -99,6 +99,7 @@ CONTROLS = "CONTROLS"
N64_BINDS = "ニンテンドウ64のボタン割り当て"
EXTRA_BINDS = "追加のボタン割り当て"
BACKGROUND_GAMEPAD = "バックグラウンドでのコントローラー認識"
EXTENDED_REPORTS = "拡張レポート"
DISABLE_GAMEPADS = "コントローラーを無効化"
GAMEPAD = "コントローラー"
DEADZONE = "デッドゾーン"

View file

@ -99,6 +99,7 @@ CONTROLS = "STEROWANIE"
N64_BINDS = "Przypisania N64"
EXTRA_BINDS = "Dodatkowe Przypisania"
BACKGROUND_GAMEPAD = "Gamepad w Tle"
EXTENDED_REPORTS = "Rozszerzone raporty"
DISABLE_GAMEPADS = "Wyłącz Gamepady"
GAMEPAD = "Gamepad"
DEADZONE = "Martwa Strefa"

View file

@ -99,6 +99,7 @@ CONTROLS = "CONTROLES"
N64_BINDS = "N64"
EXTRA_BINDS = "Outros"
BACKGROUND_GAMEPAD = "Controle de fundo"
EXTENDED_REPORTS = "Relatórios detalhados"
DISABLE_GAMEPADS = "Desativar controles"
GAMEPAD = "Controle"
DEADZONE = "Zona morta"

View file

@ -98,6 +98,7 @@ CONTROLS = "CONTROLS"
N64_BINDS = "Кнопки N64"
EXTRA_BINDS = "Дополнительные кнопки"
BACKGROUND_GAMEPAD = "Фоновый ввод"
EXTENDED_REPORTS = "Расширенные отчеты"
DISABLE_GAMEPADS = "Отключить геймпады"
GAMEPAD = "Геймпад"
DEADZONE = "Mёртвая зона"

View file

@ -100,6 +100,7 @@ N64_BINDS = "Botones de N64"
EXTRA_BINDS = "Botones Adicionales"
BACKGROUND_GAMEPAD = "Mando en segundo plano"
DISABLE_GAMEPADS = "Desactivar mandos"
EXTENDED_REPORTS = "Informes ampliados"
GAMEPAD = "Mando"
DEADZONE = "Zona muerta"
RUMBLE_STRENGTH = "Intensidad de vibración"

View file

@ -1,93 +0,0 @@
--- 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`

View file

@ -1,10 +0,0 @@
-- Environment inclusions --
--[[
We only need to include character select rn
]]
charSelect = charSelect
if not charSelect then return end
_ENV = setmetatable(_G, { __index = charSelect })

View file

@ -1,31 +0,0 @@
--- 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

View file

@ -1,148 +0,0 @@
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

View file

@ -1,52 +0,0 @@
--- 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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,843 +0,0 @@
-------------------
-- 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)

View file

@ -1,55 +0,0 @@
-------------------
-- 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)

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