From 8b9b33f0aff11d2a87a98cd862178956f491e791 Mon Sep 17 00:00:00 2001 From: Prince Frizzy Date: Wed, 20 Apr 2022 14:18:17 -0400 Subject: [PATCH 1/4] Some bug fixes. (#67) * Some bug fixes. Fix Bully Star Spawning Cutscene to be player dependent. Add missing line to Makefile. Fix compile error with Clang in save_file.c * Fix DDD Chests Star spawining in the wrong location. --- Makefile | 3 +- include/object_fields.h | 13 ++++---- src/game/behaviors/bully.inc.c | 41 +++++++++++++++++++------ src/game/behaviors/treasure_chest.inc.c | 4 +-- src/game/obj_behaviors.c | 4 ++- src/game/save_file.c | 4 +++ 6 files changed, 49 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 22030e7d..51b9cbe4 100644 --- a/Makefile +++ b/Makefile @@ -1496,7 +1496,8 @@ ifeq ($(TARGET_N64),1) $(OBJDUMP) -D $< > $@ else $(EXE): $(O_FILES) $(MIO0_FILES:.mio0=.o) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(BUILD_DIR)/$(RPC_LIBS) $(BUILD_DIR)/$(DISCORD_SDK_LIBS) $(BUILD_DIR)/$(MOD_DIR) - $(LD) $(PROF_FLAGS) -L $(BUILD_DIR) -o $@ $(O_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LDFLAGS) $(EXTRA_INCLUDES) + @$(PRINT) "$(GREEN)Linking executable: $(BLUE)$@ $(NO_COL)\n" + $(V)$(LD) $(PROF_FLAGS) -L $(BUILD_DIR) -o $@ $(O_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LDFLAGS) $(EXTRA_INCLUDES) endif diff --git a/include/object_fields.h b/include/object_fields.h index 0aecf1bf..f87b3574 100644 --- a/include/object_fields.h +++ b/include/object_fields.h @@ -316,12 +316,13 @@ #define /*0x0F8*/ oBulletBillInitialMoveYaw OBJECT_FIELD_S32(0x1C) /* Bully (all variants) */ -#define /*0x0F4*/ oBullySubtype OBJECT_FIELD_S32(0x1B) -#define /*0x0F8*/ oBullyPrevX OBJECT_FIELD_F32(0x1C) -#define /*0x0FC*/ oBullyPrevY OBJECT_FIELD_F32(0x1D) -#define /*0x100*/ oBullyPrevZ OBJECT_FIELD_F32(0x1E) -#define /*0x104*/ oBullyKBTimerAndMinionKOCounter OBJECT_FIELD_S32(0x1F) -#define /*0x108*/ oBullyMarioCollisionAngle OBJECT_FIELD_S32(0x20) +#define /*0x0F4*/ oBullySubtype OBJECT_FIELD_S32(0x1B) +#define /*0x0F8*/ oBullyPrevX OBJECT_FIELD_F32(0x1C) +#define /*0x0FC*/ oBullyPrevY OBJECT_FIELD_F32(0x1D) +#define /*0x100*/ oBullyPrevZ OBJECT_FIELD_F32(0x1E) +#define /*0x104*/ oBullyKBTimerAndMinionKOCounter OBJECT_FIELD_S32(0x1F) +#define /*0x108*/ oBullyMarioCollisionAngle OBJECT_FIELD_S32(0x20) +#define /*0x10C*/ oBullyLastNetworkPlayerIndex OBJECT_FIELD_S16(0x21, 0) /* Butterfly */ #define /*0x0F4*/ oButterflyYPhase OBJECT_FIELD_S32(0x1B) diff --git a/src/game/behaviors/bully.inc.c b/src/game/behaviors/bully.inc.c index 86160032..c13e7b70 100644 --- a/src/game/behaviors/bully.inc.c +++ b/src/game/behaviors/bully.inc.c @@ -47,6 +47,7 @@ static void bhv_bully_network_init(void) { network_init_object_field(o, &o->oBullyPrevY); network_init_object_field(o, &o->oBullyPrevZ); network_init_object_field(o, &o->oBullyMarioCollisionAngle); + network_init_object_field(o, &o->oBullyLastNetworkPlayerIndex); so->syncDeathEvent = FALSE; so->ignore_if_true = bhv_bully_ignore_if_true; so->override_ownership = bhv_bully_override_ownership; @@ -62,6 +63,11 @@ void bhv_small_bully_init(void) { o->oGravity = 4.0; o->oFriction = 0.91; o->oBuoyancy = 1.3; + + // We only set this here so it has a set value just in case. + // A mod may make a small bully spawn a star. + // For whatever reason that may be. + o->oBullyLastNetworkPlayerIndex = UNKNOWN_GLOBAL_INDEX; obj_set_hitbox(o, &sSmallBullyHitbox); bhv_bully_network_init(); @@ -77,6 +83,14 @@ void bhv_big_bully_init(void) { o->oGravity = 5.0; o->oFriction = 0.93; o->oBuoyancy = 1.3; + + // We haven't interacted with a player yet. + // We also don't sync this as not only is it not required + // but it also is only set for an interaction. + // Therefore this object must already be loaded for it to be set + // and if it wasn't. You couldn't of possibly been the one + // who last interacted to begin with. + o->oBullyLastNetworkPlayerIndex = UNKNOWN_GLOBAL_INDEX; obj_set_hitbox(o, &sBigBullyHitbox); bhv_bully_network_init(); @@ -94,16 +108,21 @@ void bully_check_mario_collision(void) { o->oAction != BULLY_ACT_LAVA_DEATH && o->oAction != BULLY_ACT_DEATH_PLANE_DEATH && #endif o->oInteractStatus & INT_STATUS_INTERACTED) { - if (o->oBehParams2ndByte == BULLY_BP_SIZE_SMALL) + if (o->oBehParams2ndByte == BULLY_BP_SIZE_SMALL) { cur_obj_play_sound_2(SOUND_OBJ2_BULLY_ATTACKED); - else + } else { cur_obj_play_sound_2(SOUND_OBJ2_LARGE_BULLY_ATTACKED); + } o->oInteractStatus &= ~INT_STATUS_INTERACTED; o->oAction = BULLY_ACT_KNOCKBACK; o->oFlags &= ~0x8; /* bit 3 */ cur_obj_init_animation(3); o->oBullyMarioCollisionAngle = o->oMoveAngleYaw; + + // Get the player who interacted with us. + struct MarioState *player = nearest_interacting_mario_state_to_object(o); + o->oBullyLastNetworkPlayerIndex = gNetworkPlayers[player->playerIndex].globalIndex; } } @@ -119,12 +138,14 @@ void bully_act_chase_mario(void) { obj_turn_toward_object(o, player, 16, 4096); } else if (o->oBehParams2ndByte == BULLY_BP_SIZE_SMALL) { o->oForwardVel = 20.0; - if (o->oTimer >= 31) + if (o->oTimer >= 31) { o->oTimer = 0; + } } else { o->oForwardVel = 30.0; - if (o->oTimer >= 36) + if (o->oTimer >= 36) { o->oTimer = 0; + } } if (!is_point_within_radius_of_mario(homeX, posY, homeZ, 1000)) { @@ -141,8 +162,9 @@ void bully_act_knockback(void) { o->oFlags |= 0x8; /* bit 3 */ o->oMoveAngleYaw = o->oFaceAngleYaw; obj_turn_toward_object(o, player, 16, 1280); - } else + } else { o->header.gfx.animInfo.animFrame = 0; + } if (o->oBullyKBTimerAndMinionKOCounter == 18) { o->oAction = BULLY_ACT_CHASE_MARIO; @@ -214,8 +236,9 @@ void bully_step(void) { obj_check_floor_death(collisionFlags, sObjFloor); if (o->oBullySubtype & BULLY_STYPE_CHILL) { - if (o->oPosY < 1030.0f) + if (o->oPosY < 1030.0f) { o->oAction = BULLY_ACT_LAVA_DEATH; + } } } @@ -246,10 +269,10 @@ void bully_act_level_death(void) { if (o->oBullySubtype == BULLY_STYPE_CHILL) { f32* starPos = gLevelValues.starPositions.ChillBullyStarPos; - spawn_default_star(starPos[0], starPos[1], starPos[2]); + spawn_networked_default_star(starPos[0], starPos[1], starPos[2], o->oBullyLastNetworkPlayerIndex); } else { f32* starPos = gLevelValues.starPositions.BigBullyTrioStarPos; - spawn_default_star(starPos[0], starPos[1], starPos[2]); + spawn_networked_default_star(starPos[0], starPos[1], starPos[2], o->oBullyLastNetworkPlayerIndex); struct Object* lllTumblingBridge = cur_obj_nearest_object_with_behavior(bhvLllTumblingBridge); if (lllTumblingBridge != NULL) { lllTumblingBridge->oIntangibleTimer = 0; @@ -341,7 +364,7 @@ void big_bully_spawn_star(void) { if (obj_lava_death() == 1) { spawn_mist_particles(); f32* starPos = gLevelValues.starPositions.BigBullyStarPos; - spawn_default_star(starPos[0], starPos[1], starPos[2]); + spawn_networked_default_star(starPos[0], starPos[1], starPos[2], o->oBullyLastNetworkPlayerIndex); } } diff --git a/src/game/behaviors/treasure_chest.inc.c b/src/game/behaviors/treasure_chest.inc.c index cf34f474..cc1e6f28 100644 --- a/src/game/behaviors/treasure_chest.inc.c +++ b/src/game/behaviors/treasure_chest.inc.c @@ -1,7 +1,5 @@ // treasure_chest.c.inc -#include "pc/network/network_player.h" - /** * Hitbox for treasure chest bottom. */ @@ -323,7 +321,7 @@ void bhv_treasure_chest_loop(void) { if (o->oTimer == 60) { spawn_mist_particles(); - f32* starPos = gLevelValues.starPositions.TreasureJrbStarPos; + f32* starPos = gLevelValues.starPositions.TreasureChestStarPos; spawn_networked_default_star(starPos[0], starPos[1], starPos[2], o->oTreasureChestLastNetworkPlayerIndex); o->oAction = 2; diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index fb81e5ac..54d16676 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -34,6 +34,7 @@ #include "hardcoded.h" #include "engine/surface_load.h" #include "pc/network/network.h" +#include "pc/network/network_player.h" #include "pc/network/reservation_area.h" #include "pc/lua/utils/smlua_model_utils.h" #include "game/rng_position.h" @@ -949,6 +950,8 @@ s8 UNUSED debug_sequence_tracker(s16 debugInputSequence[]) { return FALSE; } +// We need the spawn_star file first so the spawn_star functions can be accessed by below behaviors. +#include "behaviors/spawn_star.inc.c" #include "behaviors/moving_coin.inc.c" #include "behaviors/seaweed.inc.c" #include "behaviors/bobomb.inc.c" @@ -986,7 +989,6 @@ s8 UNUSED debug_sequence_tracker(s16 debugInputSequence[]) { #include "behaviors/snowman.inc.c" #include "behaviors/boulder.inc.c" #include "behaviors/cap.inc.c" -#include "behaviors/spawn_star.inc.c" #include "behaviors/red_coin.inc.c" #include "behaviors/hidden_star.inc.c" #include "behaviors/rolling_log.inc.c" diff --git a/src/game/save_file.c b/src/game/save_file.c index a51e7e8c..d54a113f 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -14,6 +14,10 @@ #include "pc/ini.h" #include "pc/network/network.h" +#ifndef bcopy +#define bcopy(b1,b2,len) (memmove((b2), (b1), (len)), (void) 0) +#endif + #define MENU_DATA_MAGIC 0x4849 #define SAVE_FILE_MAGIC 0x4441 From 950aeb0e2822332b0cc6a7ae506e755d1f029952 Mon Sep 17 00:00:00 2001 From: Isaac <62234577+Isaac0-dev@users.noreply.github.com> Date: Thu, 21 Apr 2022 04:19:00 +1000 Subject: [PATCH 2/4] update console help message (#68) --- src/pc/cliopts.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pc/cliopts.c b/src/pc/cliopts.c index 73e44650..6f076659 100644 --- a/src/pc/cliopts.c +++ b/src/pc/cliopts.c @@ -14,7 +14,7 @@ struct PCCLIOptions gCLIOpts; static void print_help(void) { - printf("Super Mario 64 PC Port\n"); + printf("\nsm64ex-coop\n"); printf("%-20s\tEnables the cheat menu.\n", "--cheats"); printf("%-20s\tSaves the configuration file as CONFIGNAME.\n", "--configfile CONFIGNAME"); printf("%-20s\tSets additional data directory name (only 'res' is used by default).\n", "--gamedir DIRNAME"); @@ -22,6 +22,9 @@ static void print_help(void) { printf("%-20s\tStarts the game in full screen mode.\n", "--fullscreen"); printf("%-20s\tSkips the Peach and Castle intro when starting a new game.\n", "--skip-intro"); printf("%-20s\tStarts the game in windowed mode.\n", "--windowed"); + printf("%-20s\tStarts the game and creates a new server.\n", "--server PORT"); + printf("%-20s\tStarts the game and joins an existing server.\n", "--client IP PORT"); + printf("%-20s\tStarts the game using a poolsize of your choice.\n", "--poolsize POOLSIZE"); } static inline int arg_string(const char *name, const char *value, char *target, int maxLength) { From 9e5a45ecddc83cac3b1cd8431777a85c7aa4db4b Mon Sep 17 00:00:00 2001 From: PeachyPeach <72323920+PeachyPeachSM64@users.noreply.github.com> Date: Wed, 20 Apr 2022 20:20:45 +0200 Subject: [PATCH 3/4] Added lua profiler; Added useful object functions; Bug fixes (#65) Added a basic lua profiler If the game is compiled with LUA_PROFILER=1, displays on screen the average execution time per frame of each active lua mod, in microseconds. Added object functions For some reasons, accessing the object fields obj.o* via lua is rather slow, and can drastically increase execution time of custom behaviors. For basic stuff like setting an object's velocity or moving it, some functions, missing from the original code, have been added: s32 obj_is_valid_for_interaction(struct Object *o): returns 1 if an object is valid for interaction, i.e. active, tangible and not interacted. s32 obj_check_hitbox_overlap(struct Object *o1, struct Object *o2): returns 1 if two objects hitboxes overlap. Doesn't check tangibility, only hitbox values. void obj_set_vel(struct Object *o, f32 vx, f32 vy, f32 vz): sets an object's velocity. void obj_move_xyz(struct Object *o, f32 dx, f32 dy, f32 dz): moves an object position by (dx, dy, dz). Bug fixes: Disable collisions with walls and ceilings after Mario exits a warp pipe to prevent softlocks in narrow places. Make the koopa shell exclamation box respawn after some time. Quicksand no longer downwarps and instant-kills Mario if he's shocked while being above it. --- Makefile | 9 +++ autogen/lua_definitions/functions.lua | 31 ++++++++ docs/lua/functions.md | 91 ++++++++++++++++++++++++ src/game/behaviors/exclamation_box.inc.c | 2 +- src/game/hud.c | 5 ++ src/game/mario_actions_cutscene.c | 33 ++++++++- src/pc/lua/smlua_functions_autogen.c | 62 ++++++++++++++++ src/pc/lua/smlua_hooks.c | 76 ++++++++++++++++++++ src/pc/lua/utils/smlua_obj_utils.c | 31 ++++++++ src/pc/lua/utils/smlua_obj_utils.h | 5 ++ 10 files changed, 343 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 51b9cbe4..ef19c9ee 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,9 @@ DEBUG ?= 0 # Enable development/testing flags DEVELOPMENT ?= 0 +# Enable lua profiler +LUA_PROFILER ?= 0 + # Build for the N64 (turn this off for ports) TARGET_N64 = 0 @@ -972,6 +975,12 @@ ifeq ($(DEVELOPMENT),1) CFLAGS += -DDEVELOPMENT endif +# Check for lua profiler option +ifeq ($(LUA_PROFILER),1) + CC_CHECK_CFLAGS += -DLUA_PROFILER + CFLAGS += -DLUA_PROFILER +endif + # Check for texture fix option ifeq ($(TEXTURE_FIX),1) CC_CHECK_CFLAGS += -DTEXTURE_FIX diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 21c793ed..44b33687 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -7176,6 +7176,13 @@ function get_trajectory(name) -- ... end +--- @param o1 Object +--- @param o2 Object +--- @return integer +function obj_check_hitbox_overlap(o1, o2) + -- ... +end + --- @param objList ObjectList --- @return Object function obj_get_first(objList) @@ -7252,6 +7259,21 @@ function obj_has_model_extended(o, modelId) -- ... end +--- @param o Object +--- @return integer +function obj_is_valid_for_interaction(o) + -- ... +end + +--- @param o Object +--- @param dx number +--- @param dy number +--- @param dz number +--- @return nil +function obj_move_xyz(o, dx, dy, dz) + -- ... +end + --- @param o Object --- @param modelId ModelExtendedId --- @return nil @@ -7259,6 +7281,15 @@ function obj_set_model_extended(o, modelId) -- ... end +--- @param o Object +--- @param vx number +--- @param vy number +--- @param vz number +--- @return nil +function obj_set_vel(o, vx, vy, vz) + -- ... +end + --- @param behaviorId BehaviorId --- @param modelId ModelExtendedId --- @param x number diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 4b3e461d..4df2b360 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1344,6 +1344,7 @@ - smlua_obj_utils.h - [get_temp_object_hitbox](#get_temp_object_hitbox) - [get_trajectory](#get_trajectory) + - [obj_check_hitbox_overlap](#obj_check_hitbox_overlap) - [obj_get_first](#obj_get_first) - [obj_get_first_with_behavior_id](#obj_get_first_with_behavior_id) - [obj_get_first_with_behavior_id_and_field_f32](#obj_get_first_with_behavior_id_and_field_f32) @@ -1355,7 +1356,10 @@ - [obj_get_temp_spawn_particles_info](#obj_get_temp_spawn_particles_info) - [obj_has_behavior_id](#obj_has_behavior_id) - [obj_has_model_extended](#obj_has_model_extended) + - [obj_is_valid_for_interaction](#obj_is_valid_for_interaction) + - [obj_move_xyz](#obj_move_xyz) - [obj_set_model_extended](#obj_set_model_extended) + - [obj_set_vel](#obj_set_vel) - [spawn_non_sync_object](#spawn_non_sync_object) - [spawn_sync_object](#spawn_sync_object) @@ -25086,6 +25090,27 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
+## [obj_check_hitbox_overlap](#obj_check_hitbox_overlap) + +### Lua Example +`local integerValue = obj_check_hitbox_overlap(o1, o2)` + +### Parameters +| Field | Type | +| ----- | ---- | +| o1 | [Object](structs.md#Object) | +| o2 | [Object](structs.md#Object) | + +### Returns +- `integer` + +### C Prototype +`s32 obj_check_hitbox_overlap(struct Object *o1, struct Object *o2);` + +[:arrow_up_small:](#) + +
+ ## [obj_get_first](#obj_get_first) ### Lua Example @@ -25316,6 +25341,49 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
+## [obj_is_valid_for_interaction](#obj_is_valid_for_interaction) + +### Lua Example +`local integerValue = obj_is_valid_for_interaction(o)` + +### Parameters +| Field | Type | +| ----- | ---- | +| o | [Object](structs.md#Object) | + +### Returns +- `integer` + +### C Prototype +`s32 obj_is_valid_for_interaction(struct Object *o);` + +[:arrow_up_small:](#) + +
+ +## [obj_move_xyz](#obj_move_xyz) + +### Lua Example +`obj_move_xyz(o, dx, dy, dz)` + +### Parameters +| Field | Type | +| ----- | ---- | +| o | [Object](structs.md#Object) | +| dx | `number` | +| dy | `number` | +| dz | `number` | + +### Returns +- None + +### C Prototype +`void obj_move_xyz(struct Object *o, f32 dx, f32 dy, f32 dz);` + +[:arrow_up_small:](#) + +
+ ## [obj_set_model_extended](#obj_set_model_extended) ### Lua Example @@ -25337,6 +25405,29 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
+## [obj_set_vel](#obj_set_vel) + +### Lua Example +`obj_set_vel(o, vx, vy, vz)` + +### Parameters +| Field | Type | +| ----- | ---- | +| o | [Object](structs.md#Object) | +| vx | `number` | +| vy | `number` | +| vz | `number` | + +### Returns +- None + +### C Prototype +`void obj_set_vel(struct Object *o, f32 vx, f32 vy, f32 vz);` + +[:arrow_up_small:](#) + +
+ ## [spawn_non_sync_object](#spawn_non_sync_object) ### Lua Example diff --git a/src/game/behaviors/exclamation_box.inc.c b/src/game/behaviors/exclamation_box.inc.c index 25d97b44..30e46db6 100644 --- a/src/game/behaviors/exclamation_box.inc.c +++ b/src/game/behaviors/exclamation_box.inc.c @@ -167,7 +167,7 @@ void exclamation_box_act_4(void) { spawn_mist_particles_variable(0, 0, 46.0f); spawn_triangle_break_particles(20, 139, 0.3f, o->oAnimState); create_sound_spawner(SOUND_GENERAL_BREAK_BOX); - if (o->oBehParams2ndByte < 3) { + if (o->oBehParams2ndByte <= 3) { o->oAction = 5; cur_obj_hide(); } else { diff --git a/src/game/hud.c b/src/game/hud.c index 90e0d289..1f4263e8 100644 --- a/src/game/hud.c +++ b/src/game/hud.c @@ -535,5 +535,10 @@ void render_hud(void) { { print_text(10, 60, "SURFACE NODE POOL FULL"); } + +#if defined(LUA_PROFILER) + extern void lua_profiler_update_counters(); + lua_profiler_update_counters(); +#endif } } diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index dcdb0c0f..eafe1ddc 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -1103,6 +1103,27 @@ s32 act_warp_door_spawn(struct MarioState *m) { return FALSE; } +static s32 launch_mario_until_land_no_collision(struct MarioState *m, s32 endAction, s32 animation, f32 forwardVel) { + mario_set_forward_vel(m, forwardVel); + set_mario_animation(m, animation); + m->pos[0] += m->vel[0]; + m->pos[1] += m->vel[1]; + m->pos[2] += m->vel[2]; + m->vel[1] -= 4.f; + if (m->vel[1] < -75.f) { + m->vel[1] = -75.f; + } + f32 floorHeight = find_floor_height(m->pos[0], m->pos[1], m->pos[2]); + s32 landed = floorHeight >= m->pos[1]; + if (landed) { + m->pos[1] = floorHeight; + set_mario_action(m, endAction, 0); + } + vec3f_copy(m->marioObj->header.gfx.pos, m->pos); + vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0); + return landed; +} + s32 act_emerge_from_pipe(struct MarioState *m) { struct Object *marioObj = m->marioObj; @@ -1123,6 +1144,16 @@ s32 act_emerge_from_pipe(struct MarioState *m) { } } + // After Mario has exited the pipe, disable wall and ceiling collision until Mario lands + // Fix softlocks in narrow places + if (m->actionTimer > 15) { + if (launch_mario_until_land_no_collision(m, ACT_JUMP_LAND_STOP, MARIO_ANIM_SINGLE_JUMP, 8.0f)) { + mario_set_forward_vel(m, 0.0f); + play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING); + } + return FALSE; + } + if (launch_mario_until_land(m, ACT_JUMP_LAND_STOP, MARIO_ANIM_SINGLE_JUMP, 8.0f)) { mario_set_forward_vel(m, 0.0f); play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING); @@ -2894,7 +2925,7 @@ static s32 check_for_instant_quicksand(struct MarioState *m) { if (m->action == ACT_BUBBLED) { return FALSE; } if (m->floor->type == SURFACE_INSTANT_QUICKSAND && m->action & ACT_FLAG_INVULNERABLE - && m->action != ACT_QUICKSAND_DEATH) { + && m->action != ACT_QUICKSAND_DEATH && m->action != ACT_SHOCKED) { update_mario_sound_and_camera(m); return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0); } diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 95913fdc..aae414dd 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -14928,6 +14928,19 @@ int smlua_func_get_trajectory(lua_State* L) { return 1; } +int smlua_func_obj_check_hitbox_overlap(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 2)) { return 0; } + + struct Object* o1 = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT); + if (!gSmLuaConvertSuccess) { return 0; } + struct Object* o2 = (struct Object*)smlua_to_cobject(L, 2, LOT_OBJECT); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, obj_check_hitbox_overlap(o1, o2)); + + return 1; +} + int smlua_func_obj_get_first(lua_State* L) { if(!smlua_functions_valid_param_count(L, 1)) { return 0; } @@ -15069,6 +15082,34 @@ int smlua_func_obj_has_model_extended(lua_State* L) { return 1; } +int smlua_func_obj_is_valid_for_interaction(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, obj_is_valid_for_interaction(o)); + + return 1; +} + +int smlua_func_obj_move_xyz(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 4)) { return 0; } + + struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT); + if (!gSmLuaConvertSuccess) { return 0; } + f32 dx = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + f32 dy = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + f32 dz = smlua_to_number(L, 4); + if (!gSmLuaConvertSuccess) { return 0; } + + obj_move_xyz(o, dx, dy, dz); + + return 1; +} + int smlua_func_obj_set_model_extended(lua_State* L) { if(!smlua_functions_valid_param_count(L, 2)) { return 0; } @@ -15082,6 +15123,23 @@ int smlua_func_obj_set_model_extended(lua_State* L) { return 1; } +int smlua_func_obj_set_vel(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 4)) { return 0; } + + struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT); + if (!gSmLuaConvertSuccess) { return 0; } + f32 vx = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + f32 vy = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + f32 vz = smlua_to_number(L, 4); + if (!gSmLuaConvertSuccess) { return 0; } + + obj_set_vel(o, vx, vy, vz); + + return 1; +} + int smlua_func_spawn_non_sync_object(lua_State* L) { if(!smlua_functions_valid_param_count(L, 6)) { return 0; } @@ -17002,6 +17060,7 @@ void smlua_bind_functions_autogen(void) { // smlua_obj_utils.h smlua_bind_function(L, "get_temp_object_hitbox", smlua_func_get_temp_object_hitbox); smlua_bind_function(L, "get_trajectory", smlua_func_get_trajectory); + smlua_bind_function(L, "obj_check_hitbox_overlap", smlua_func_obj_check_hitbox_overlap); smlua_bind_function(L, "obj_get_first", smlua_func_obj_get_first); smlua_bind_function(L, "obj_get_first_with_behavior_id", smlua_func_obj_get_first_with_behavior_id); smlua_bind_function(L, "obj_get_first_with_behavior_id_and_field_f32", smlua_func_obj_get_first_with_behavior_id_and_field_f32); @@ -17013,7 +17072,10 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "obj_get_temp_spawn_particles_info", smlua_func_obj_get_temp_spawn_particles_info); smlua_bind_function(L, "obj_has_behavior_id", smlua_func_obj_has_behavior_id); smlua_bind_function(L, "obj_has_model_extended", smlua_func_obj_has_model_extended); + smlua_bind_function(L, "obj_is_valid_for_interaction", smlua_func_obj_is_valid_for_interaction); + smlua_bind_function(L, "obj_move_xyz", smlua_func_obj_move_xyz); smlua_bind_function(L, "obj_set_model_extended", smlua_func_obj_set_model_extended); + smlua_bind_function(L, "obj_set_vel", smlua_func_obj_set_vel); smlua_bind_function(L, "spawn_non_sync_object", smlua_func_spawn_non_sync_object); smlua_bind_function(L, "spawn_sync_object", smlua_func_spawn_sync_object); diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c index b69f6060..bea50c2b 100644 --- a/src/pc/lua/smlua_hooks.c +++ b/src/pc/lua/smlua_hooks.c @@ -3,6 +3,76 @@ #include "pc/djui/djui_chat_message.h" #include "pc/crash_handler.h" +#if defined(LUA_PROFILER) +#include "../mods/mods.h" +#include "game/print.h" +#include "gfx_dimensions.h" + +extern u64 SDL_GetPerformanceCounter(void); +extern u64 SDL_GetPerformanceFrequency(void); + +#define MAX_PROFILED_MODS 16 +#define REFRESH_RATE 15 + +static struct { + f64 start; + f64 end; + f64 sum; + f64 disp; +} sLuaProfilerCounters[MAX_PROFILED_MODS]; + +static void lua_profiler_start_counter(struct Mod *mod) { + for (s32 i = 0; i != MIN(MAX_PROFILED_MODS, gActiveMods.entryCount); ++i) { + if (gActiveMods.entries[i] == mod) { + f64 freq = SDL_GetPerformanceFrequency(); + f64 curr = SDL_GetPerformanceCounter(); + sLuaProfilerCounters[i].start = curr / freq; + return; + } + } +} + +static void lua_profiler_stop_counter(struct Mod *mod) { + for (s32 i = 0; i != MIN(MAX_PROFILED_MODS, gActiveMods.entryCount); ++i) { + if (gActiveMods.entries[i] == mod) { + f64 freq = SDL_GetPerformanceFrequency(); + f64 curr = SDL_GetPerformanceCounter(); + sLuaProfilerCounters[i].end = curr / freq; + sLuaProfilerCounters[i].sum += sLuaProfilerCounters[i].end - sLuaProfilerCounters[i].start; + return; + } + } +} + +void lua_profiler_update_counters() { + if (gGlobalTimer % REFRESH_RATE == 0) { + for (s32 i = 0; i != MIN(MAX_PROFILED_MODS, gActiveMods.entryCount); ++i) { + sLuaProfilerCounters[i].disp = sLuaProfilerCounters[i].sum / (f64) REFRESH_RATE; + sLuaProfilerCounters[i].sum = 0; + } + } + for (s32 i = 0, y = SCREEN_HEIGHT - 60; i != MIN(MAX_PROFILED_MODS, gActiveMods.entryCount); ++i, y -= 18) { + const char *modName = gActiveMods.entries[i]->relativePath; + s32 modCounterUs = (s32) (sLuaProfilerCounters[i].disp * 1000000.0); + char text[256]; + snprintf(text, 256, " %05d", modCounterUs); + memcpy(text, modName, MIN(12, strlen(modName) - (gActiveMods.entries[i]->isDirectory ? 0 : 4))); + for (s32 j = 0; j != 12; ++j) { + char c = text[j]; + if (c >= 'a' && c <= 'z') c -= ('a' - 'A'); + if (c == 'J') c = 'I'; + if (c == 'Q') c = 'O'; + if (c == 'V') c = 'U'; + if (c == 'X') c = '*'; + if (c == 'Z') c = '2'; + if ((c < '0' || c > '9') && (c < 'A' || c > 'Z')) c = ' '; + text[j] = c; + } + print_text(GFX_DIMENSIONS_FROM_LEFT_EDGE(4), y, text); + } +} +#endif + #define MAX_HOOKED_REFERENCES 64 #define LUA_BEHAVIOR_FLAG (1 << 15) @@ -20,7 +90,13 @@ static int smlua_call_hook(lua_State* L, int nargs, int nresults, int errfunc, s struct Mod* prev = gLuaActiveMod; gLuaActiveMod = activeMod; gLuaLastHookMod = activeMod; +#if defined(LUA_PROFILER) + lua_profiler_start_counter(activeMod); +#endif int rc = lua_pcall(L, nargs, nresults, errfunc); +#if defined(LUA_PROFILER) + lua_profiler_stop_counter(activeMod); +#endif gLuaActiveMod = prev; return rc; } diff --git a/src/pc/lua/utils/smlua_obj_utils.c b/src/pc/lua/utils/smlua_obj_utils.c index e8de9d24..712e1480 100644 --- a/src/pc/lua/utils/smlua_obj_utils.c +++ b/src/pc/lua/utils/smlua_obj_utils.c @@ -2,6 +2,8 @@ #include "object_constants.h" #include "object_fields.h" #include "src/game/object_helpers.h" +#include "src/game/interaction.h" +#include "engine/math_util.h" #include "pc/lua/smlua.h" #include "smlua_obj_utils.h" @@ -219,3 +221,32 @@ struct ObjectHitbox* get_temp_object_hitbox(void) { memset(&sTmpHitbox, 0, sizeof(struct ObjectHitbox)); return &sTmpHitbox; } + +s32 obj_is_valid_for_interaction(struct Object *o) { + return o->activeFlags != ACTIVE_FLAG_DEACTIVATED && o->oIntangibleTimer == 0 && (o->oInteractStatus & INT_STATUS_INTERACTED) == 0; +} + +s32 obj_check_hitbox_overlap(struct Object *o1, struct Object *o2) { + f32 r2 = sqr(max(o1->hitboxRadius, o1->hurtboxRadius) + max(o2->hitboxRadius, o2->hurtboxRadius)); + f32 d2 = sqr(o1->oPosX - o2->oPosX) + sqr(o1->oPosZ - o2->oPosZ); + if (d2 > r2) return FALSE; + f32 hb1lb = o1->oPosY - o1->hitboxDownOffset; + f32 hb1ub = hb1lb + max(o1->hitboxHeight, o1->hurtboxHeight); + f32 hb2lb = o2->oPosY - o2->hitboxDownOffset; + f32 hb2ub = hb2lb + max(o2->hitboxHeight, o2->hurtboxHeight); + f32 hbsoh = max(o1->hitboxHeight, o1->hurtboxHeight) + max(o2->hitboxHeight, o2->hurtboxHeight); + if (hb2ub - hb1lb > hbsoh || hb1ub - hb2lb > hbsoh) return FALSE; + return TRUE; +} + +void obj_set_vel(struct Object *o, f32 vx, f32 vy, f32 vz) { + o->oVelX = vx; + o->oVelY = vy; + o->oVelZ = vz; +} + +void obj_move_xyz(struct Object *o, f32 dx, f32 dy, f32 dz) { + o->oPosX += dx; + o->oPosY += dy; + o->oPosZ += dz; +} diff --git a/src/pc/lua/utils/smlua_obj_utils.h b/src/pc/lua/utils/smlua_obj_utils.h index d9c268d6..76996633 100644 --- a/src/pc/lua/utils/smlua_obj_utils.h +++ b/src/pc/lua/utils/smlua_obj_utils.h @@ -33,4 +33,9 @@ struct Object *obj_get_next_with_same_behavior_id_and_field_f32(struct Object *o struct SpawnParticlesInfo* obj_get_temp_spawn_particles_info(enum ModelExtendedId modelId); struct ObjectHitbox* get_temp_object_hitbox(void); +s32 obj_is_valid_for_interaction(struct Object *o); +s32 obj_check_hitbox_overlap(struct Object *o1, struct Object *o2); +void obj_set_vel(struct Object *o, f32 vx, f32 vy, f32 vz); +void obj_move_xyz(struct Object *o, f32 dx, f32 dy, f32 dz); + #endif From 8e75268c0421f83c89e225b63125e1ffa8834485 Mon Sep 17 00:00:00 2001 From: 137329506980462592 <102286152+137329506980462592@users.noreply.github.com> Date: Wed, 20 Apr 2022 14:21:11 -0400 Subject: [PATCH 4/4] Ice color palettes (#66) Ice color palettes Co-authored-by: MysteryMeatwad <61129329+MysteryMeatwad@users.noreply.github.com> --- src/game/characters.h | 2 +- src/game/mario_misc.c | 6 +++++- src/pc/djui/djui_panel_player.c | 2 ++ src/pc/lua/smlua_constants_autogen.c | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/game/characters.h b/src/game/characters.h index 40c109f6..05c97d63 100644 --- a/src/game/characters.h +++ b/src/game/characters.h @@ -4,7 +4,7 @@ #include "types.h" // NOTE: do not include any additional headers -#define PALETTE_MAX 30 +#define PALETTE_MAX 32 enum CharacterType { CT_MARIO, diff --git a/src/game/mario_misc.c b/src/game/mario_misc.c index 48a1b700..acd42447 100644 --- a/src/game/mario_misc.c +++ b/src/game/mario_misc.c @@ -114,17 +114,21 @@ struct PlayerColor gPlayerColors[PALETTE_MAX] = { DEFINE_PLAYER_COLOR(0x37, 0x32, 0x42, /**/ 0xe6, 0xe3, 0xff), DEFINE_PLAYER_COLOR(0xff, 0x8a, 0x00, /**/ 0x00, 0x51, 0x10), DEFINE_PLAYER_COLOR(0x65, 0xfa, 0xff, /**/ 0x4c, 0x1e, 0x3f), + DEFINE_PLAYER_COLOR(0xe6, 0xe6, 0xe6, /**/ 0xb2, 0x28, 0x18), DEFINE_PLAYER_COLOR(0xe6, 0xe6, 0xe6, /**/ 0x00, 0x98, 0x00), DEFINE_PLAYER_COLOR(0xe6, 0xe6, 0xe6, /**/ 0x6d, 0x3c, 0x9a), DEFINE_PLAYER_COLOR(0xe6, 0xe6, 0xe6, /**/ 0xf9, 0xeb, 0x30), - + DEFINE_PLAYER_COLOR(0xe7, 0xe7, 0x21, /**/ 0x17, 0x18, 0x15), DEFINE_PLAYER_COLOR(0xaa, 0x27, 0x31, /**/ 0xf7, 0x9a, 0x47), DEFINE_PLAYER_COLOR(0x55, 0x92, 0xb2, /**/ 0xf7, 0xc2, 0x45), DEFINE_PLAYER_COLOR(0x10, 0x1b, 0x2e, /**/ 0xeb, 0x8a, 0x4b), DEFINE_PLAYER_COLOR(0x3b, 0x8f, 0xf7, /**/ 0xd6, 0x35, 0x4d), DEFINE_PLAYER_COLOR(0xff, 0x8e, 0xb2, /**/ 0xd6, 0x35, 0x4d), + + DEFINE_PLAYER_COLOR(0x47, 0xc5, 0xff, /**/ 0xb2, 0x28, 0x18), + DEFINE_PLAYER_COLOR(0x47, 0xc5, 0xff, /**/ 0x00, 0x98, 0x00), }; const size_t gNumPlayerColors = sizeof(gPlayerColors) / sizeof(*gPlayerColors); diff --git a/src/pc/djui/djui_panel_player.c b/src/pc/djui/djui_panel_player.c index aa09ac48..2814dc6f 100644 --- a/src/pc/djui/djui_panel_player.c +++ b/src/pc/djui/djui_panel_player.c @@ -124,6 +124,8 @@ void djui_panel_player_create(struct DjuiBase* caller) { "Blueberry Pie", "Raspberry", "Bubblegum", + "Ice Mario", + "Ice Luigi", }; struct DjuiSelectionbox* selectionbox2 = djui_selectionbox_create(&body->base, "Palette", paletteChoices, PALETTE_MAX, &configPlayerPalette); djui_base_set_size_type(&selectionbox2->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 797dec22..93407df0 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1022,7 +1022,7 @@ char gSmluaConstants[] = "" "CAM_EVENT_START_ENDING = 11\n" "CAM_EVENT_START_END_WAVING = 12\n" "CAM_EVENT_START_CREDITS = 13\n" -"PALETTE_MAX = 30\n" +"PALETTE_MAX = 32\n" "CT_MARIO = 0\n" "CT_LUIGI = 1\n" "CT_TOAD = 2\n"