From 6d6d94fcde85af4ee17aa9f9b45ffd5c0ac0b5a4 Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 14 Feb 2022 18:26:44 -0800 Subject: [PATCH] Add Wario's moveset based on steven's mod --- autogen/convert_constants.py | 3 + autogen/lua_constants/built-in.lua | 15 + docs/lua/constants.md | 22 ++ docs/lua/hooks.md | 1 + mods/character-movesets.lua | 494 ++++++++++++++++++++++++++- src/game/interaction.c | 27 +- src/pc/lua/smlua_constants_autogen.c | 26 ++ src/pc/lua/smlua_functions.c | 10 + src/pc/lua/smlua_functions.h | 1 + src/pc/lua/smlua_hooks.c | 32 ++ src/pc/lua/smlua_hooks.h | 1 + 11 files changed, 608 insertions(+), 24 deletions(-) diff --git a/autogen/convert_constants.py b/autogen/convert_constants.py index 6048b8d6..f036c9b2 100644 --- a/autogen/convert_constants.py +++ b/autogen/convert_constants.py @@ -16,6 +16,7 @@ in_files = [ "src/game/characters.h", "src/pc/network/network_player.h", "include/PR/os_cont.h", + "src/game/interaction.c", ] exclude_constants = [ @@ -23,6 +24,8 @@ exclude_constants = [ '^LEVEL_.*', '^AREA_.*', '^CONT_ERR.*', + '^READ_MASK$', + '^SIGN_RANGE$', ] pretend_find = [ diff --git a/autogen/lua_constants/built-in.lua b/autogen/lua_constants/built-in.lua index 322130b6..7a05988a 100644 --- a/autogen/lua_constants/built-in.lua +++ b/autogen/lua_constants/built-in.lua @@ -130,6 +130,21 @@ function approach_f32(current, target, inc, dec) return current; end +function approach_s32(current, target, inc, dec) + if current < target then + current = current + inc + if current > target then + current = target + end + else + current = current - dec + if current < target then + current = target + end + end + return current; +end + function SOUND_ARG_LOAD(bank, playFlags, soundID, priority, flags2) return ((bank << 28) | (playFlags << 24) | (soundID << 16) | (priority << 8) | (flags2 << 4) | 1) end diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 2daf1126..a81c4fe4 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -6,6 +6,8 @@ - [characters.h](#characters.h) - [CharacterSound](#CharacterSound) - [CharacterType](#CharacterType) +- [interaction.c](#interaction.c) + - [InteractionFlag](#InteractionFlag) - [mario_animation_ids.h](#mario_animation_ids.h) - [MarioAnimID](#MarioAnimID) - [network_player.h](#network_player.h) @@ -740,6 +742,26 @@
+## [interaction.c](#interaction.c) +- INT_ANY_ATTACK +- INT_ATTACK_NOT_FROM_BELOW +- INT_ATTACK_NOT_WEAK_FROM_ABOVE +- INT_ATTACK_SLIDE + +### [enum InteractionFlag](#InteractionFlag) +| Identifier | Value | +| :--------- | :---- | +| INT_GROUND_POUND_OR_TWIRL | (1 << 0) | +| INT_PUNCH | (1 << 1) | +| INT_KICK | (1 << 2) | +| INT_TRIP | (1 << 3) | +| INT_SLIDE_KICK | (1 << 4) | +| INT_FAST_ATTACK_OR_SHELL | (1 << 5) | +| INT_HIT_FROM_ABOVE | (1 << 6) | +| INT_HIT_FROM_BELOW | (1 << 7) | + +
+ ## [mario_animation_ids.h](#mario_animation_ids.h) ### [enum MarioAnimID](#MarioAnimID) diff --git a/docs/lua/hooks.md b/docs/lua/hooks.md index 85cb941f..cf597c31 100644 --- a/docs/lua/hooks.md +++ b/docs/lua/hooks.md @@ -84,6 +84,7 @@ hook_event(HOOK_MARIO_UPDATE, mario_update) | ----- | ---- | | action_id | integer | | func | Lua Function | +| interaction_type | [enum InteractionFlag](constants.md#InteractionFlag) | ### Lua Example diff --git a/mods/character-movesets.lua b/mods/character-movesets.lua index f890a286..a7ed9780 100644 --- a/mods/character-movesets.lua +++ b/mods/character-movesets.lua @@ -2,11 +2,22 @@ -- incompatible: moveset -- description: Gives each character unique abilities and stats. +ANGLE_QUEUE_SIZE = 9 +SPIN_TIMER_SUCCESSFUL_INPUT = 4 + +gEventTable = {} + gStateExtras = {} for i=0,(MAX_PLAYERS-1) do gStateExtras[i] = {} local m = gMarioStates[i] local e = gStateExtras[i] + e.prevPos = {} + e.prevPos.x = 0 + e.prevPos.y = 0 + e.prevPos.z = 0 + e.angleDeltaQueue = {} + for j=0,(ANGLE_QUEUE_SIZE-1) do e.angleDeltaQueue[j] = 0 end e.lastAction = m.action e.animFrame = 0 e.scuttle = 0 @@ -14,18 +25,20 @@ for i=0,(MAX_PLAYERS-1) do e.boostTimer = 0 e.rotAngle = 0 e.lastHurtCounter = 0 + e.stickLastAngle = 0 + e.spinDirection = 0 + e.spinBufferTimer = 0 + e.spinInput = 0 + e.lastIntendedMag = 0 end -gEventTable = {} - - -ACT_SPIN_POUND_LAND = (0x037 | ACT_FLAG_STATIONARY | ACT_FLAG_ATTACKING) -ACT_SPIN_POUND = (0x08F | ACT_FLAG_AIR | ACT_FLAG_ATTACKING) - ----------- -- luigi -- ----------- +ACT_SPIN_POUND_LAND = (0x037 | ACT_FLAG_STATIONARY | ACT_FLAG_ATTACKING) +ACT_SPIN_POUND = (0x08F | ACT_FLAG_AIR | ACT_FLAG_ATTACKING) + function act_spin_pound(m) local e = gStateExtras[m.playerIndex] if m.actionTimer == 0 then @@ -303,6 +316,8 @@ end function toad_update(m) local e = gStateExtras[m.playerIndex] + + -- track average forward velocity if e.averageForwardVel > m.forwardVel then e.averageForwardVel = e.averageForwardVel * 0.93 + m.forwardVel * 0.07 else @@ -331,9 +346,9 @@ gEventTable[CT_TOAD] = { update = toad_update, } ------------ +------------- -- waluigi -- ------------ +------------- ACT_WALL_SLIDE = (0x0BF | ACT_FLAG_AIR | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION) @@ -453,6 +468,439 @@ gEventTable[CT_WALUIGI] = { update = waluigi_update, } +----------- +-- wario -- +----------- + +ACT_WARIO_DASH = (0x05B | ACT_FLAG_MOVING | ACT_FLAG_ATTACKING) +ACT_WARIO_AIR_DASH = (0x05B | ACT_FLAG_AIR | ACT_FLAG_ATTACKING) +ACT_CORKSCREW_CONK = (0x05D | ACT_FLAG_AIR | ACT_FLAG_ATTACKING | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION) +ACT_WARIO_SPINNING_OBJ = (0x05B | ACT_FLAG_STATIONARY) + +function act_corkscrew_conk(m) + local e = gStateExtras[m.playerIndex] + m.particleFlags = m.particleFlags | PARTICLE_DUST + + common_air_action_step(m, ACT_JUMP_LAND, MARIO_ANIM_FORWARD_SPINNING, AIR_STEP_NONE) + set_anim_to_frame(m, e.animFrame) + + if e.animFrame >= m.marioObj.header.gfx.animInfo.curAnim.loopEnd then + e.animFrame = e.animFrame - m.marioObj.header.gfx.animInfo.curAnim.loopEnd + end + + if (m.input & INPUT_Z_PRESSED) ~= 0 then + local rc = set_mario_action(m, ACT_GROUND_POUND, 0) + m.actionTimer = 5 + return rc + end + + m.actionTimer = m.actionTimer + 1 + e.animFrame = e.animFrame + 1 + + return 0 +end + +function act_wario_dash(m) + local e = gStateExtras[m.playerIndex] + + -- when hitting wall, stay dashing for an extra frame + if m.actionArg == 99 then + m.actionTimer = m.actionTimer + 1 + if m.actionTimer > 2 then + return set_mario_action(m, ACT_WALKING, 0) + end + return 0 + end + + -- make sound + if m.actionTimer == 0 then + m.actionState = m.actionArg + play_character_sound(m, CHAR_SOUND_YAHOO) + end + + -- walk once dash is up + if m.actionTimer > 15 then + return set_mario_action(m, ACT_WALKING, 0) + end + + -- slide and set animation + common_slide_action(m, ACT_DIVE, ACT_MOVE_PUNCHING, MARIO_ANIM_FIRST_PUNCH) + set_anim_to_frame(m, 25) + + -- set dash speed + local speed = 100 + if m.actionTimer > 8 then + speed = speed - (m.actionTimer - 8) * 11 + end + mario_set_forward_vel(m, speed) + + -- corkscrew conk + if (m.input & INPUT_A_PRESSED) ~= 0 then + set_jumping_action(m, ACT_CORKSCREW_CONK, 0) + play_character_sound(m, CHAR_SOUND_YAHOO) + end + + -- slide kick + if (m.input & INPUT_Z_PRESSED) ~= 0 then + return set_mario_action(m, ACT_SLIDE_KICK, 0) + end + + m.actionTimer = m.actionTimer + 1 + return 0 +end + +function act_wario_air_dash(m) + local e = gStateExtras[m.playerIndex] + + -- walk once dash is up + if m.actionTimer > 15 then + return set_mario_action(m, ACT_JUMP_LAND, 0) + end + + -- slide and set animation + common_air_action_step(m, ACT_JUMP_LAND, MARIO_ANIM_FIRST_PUNCH, AIR_STEP_NONE) + set_anim_to_frame(m, 25) + + -- set dash speed + local speed = 100 + if m.actionTimer > 8 then + speed = speed - (m.actionTimer - 8) * 11 + end + mario_set_forward_vel(m, speed) + + -- corkscrew conk + if (m.input & INPUT_A_PRESSED) ~= 0 then + set_jumping_action(m, ACT_CORKSCREW_CONK, 0) + play_character_sound(m, CHAR_SOUND_YAHOO) + end + + -- slide kick + if (m.input & INPUT_Z_PRESSED) ~= 0 then + return set_mario_action(m, ACT_SLIDE_KICK, 0) + end + + m.actionTimer = m.actionTimer + 1 + return 0 +end + +function act_wario_spinning_obj(m) + local spin = 0 + + -- throw object + if m.playerIndex == 0 and (m.input & INPUT_B_PRESSED) ~= 0 then + play_character_sound_if_no_flag(m, CHAR_SOUND_WAH2, MARIO_MARIO_SOUND_PLAYED) + play_sound_if_no_flag(m, SOUND_ACTION_THROW, MARIO_ACTION_SOUND_PLAYED) + return set_mario_action(m, ACT_RELEASING_BOWSER, 0) + end + + -- set animation + if m.playerIndex == 0 and m.angleVel.y == 0 then + m.actionTimer = m.actionTimer + 1 + if m.actionTimer > 120 then + return set_mario_action(m, ACT_RELEASING_BOWSER, 1) + end + + set_mario_animation(m, MARIO_ANIM_HOLDING_BOWSER) + else + m.actionTimer = 0 + set_mario_animation(m, MARIO_ANIM_SWINGING_BOWSER) + end + + -- spin + if m.intendedMag > 20.0 then + -- spin = acceleration + spin = (m.intendedYaw - m.twirlYaw) / 0x20 + + if spin < -0x80 then + spin = -0x80 + end + if spin > 0x80 then + spin = 0x80 + end + + m.twirlYaw = m.intendedYaw + m.angleVel.y = m.angleVel.y + spin + + if m.angleVel.y > 0x1000 then + m.angleVel.y = 0x1000 + end + if m.angleVel.y < -0x1000 then + m.angleVel.y = -0x1000 + end + elseif m.angleVel.y > -0x750 and m.angleVel.y < 0x750 then + -- go back to walking + return set_mario_action(m, ACT_HOLD_IDLE, 0) + else + -- slow down spin + m.angleVel.y = approach_s32(m.angleVel.y, 0, 128, 128); + end + + -- apply spin + spin = m.faceAngle.y + m.faceAngle.y = m.faceAngle.y + m.angleVel.y + + -- play sound on overflow + if m.angleVel.y <= -0x100 and spin < m.faceAngle.y then + queue_rumble_data_mario(m, 4, 20) + play_sound(SOUND_OBJ_BOWSER_SPINNING, m.marioObj.header.gfx.cameraToObject) + end + if m.angleVel.y >= 0x100 and spin > m.faceAngle.y then + queue_rumble_data_mario(m, 4, 20) + play_sound(SOUND_OBJ_BOWSER_SPINNING, m.marioObj.header.gfx.cameraToObject) + end + + stationary_ground_step(m) + + if m.angleVel.y >= 0 then + m.marioObj.header.gfx.angle.x = -m.angleVel.y + else + m.marioObj.header.gfx.angle.x = m.angleVel.y + end + + return false +end + +function wario_update_spin_input(m) + local e = gStateExtras[m.playerIndex] + local rawAngle = atan2s(-m.controller.stickY, m.controller.stickX) + e.spinInput = 0 + + -- prevent issues due to the frame going out of the dead zone registering the last angle as 0 + if e.lastIntendedMag > 0.5 and m.intendedMag > 0.5 then + local angleOverFrames = 0 + local thisFrameDelta = 0 + local i = 0 + + local newDirection = e.spinDirection + local signedOverflow = 0 + + if rawAngle < e.stickLastAngle then + if (e.stickLastAngle - rawAngle) > 0x8000 then + signedOverflow = 1 + end + if signedOverflow ~= 0 then + newDirection = 1 + else + newDirection = -1 + end + elseif rawAngle > e.stickLastAngle then + if (rawAngle - e.stickLastAngle) > 0x8000 then + signedOverflow = 1 + end + if signedOverflow ~= 0 then + newDirection = -1 + else + newDirection = 1 + end + end + + if e.spinDirection ~= newDirection then + for i=0,(ANGLE_QUEUE_SIZE-1) do + e.angleDeltaQueue[i] = 0 + end + e.spinDirection = newDirection + else + for i=(ANGLE_QUEUE_SIZE-1),1,-1 do + e.angleDeltaQueue[i] = e.angleDeltaQueue[i-1] + angleOverFrames = angleOverFrames + e.angleDeltaQueue[i] + end + end + + if e.spinDirection < 0 then + if signedOverflow ~= 0 then + thisFrameDelta = math.floor((1.0*e.stickLastAngle + 0x10000) - rawAngle) + else + thisFrameDelta = e.stickLastAngle - rawAngle + end + elseif e.spinDirection > 0 then + if signedOverflow ~= 0 then + thisFrameDelta = math.floor(1.0*rawAngle + 0x10000 - e.stickLastAngle) + else + thisFrameDelta = rawAngle - e.stickLastAngle + end + end + + e.angleDeltaQueue[0] = thisFrameDelta + angleOverFrames = angleOverFrames + thisFrameDelta + + if angleOverFrames >= 0xA000 then + e.spinBufferTimer = SPIN_TIMER_SUCCESSFUL_INPUT + end + + + -- allow a buffer after a successful input so that you can switch directions + if e.spinBufferTimer > 0 then + e.spinInput = 1 + e.spinBufferTimer = e.spinBufferTimer - 1 + end + else + e.spinDirection = 0 + e.spinBufferTimer = 0 + end + + e.stickLastAngle = rawAngle + e.lastIntendedMag = m.intendedMag +end + +function wario_before_phys_step(m) + local hScale = 1.0 + + -- slower on ground + if (m.action & ACT_FLAG_MOVING) ~= 0 then + hScale = hScale * 0.9 + end + + -- make wario sink + if (m.action & ACT_FLAG_SWIMMING) ~= 0 then + if m.action ~= ACT_WATER_PLUNGE then + m.vel.y = m.vel.y - 3 + end + end + + -- faster holding item + if m.heldObj ~= nil then + m.vel.y = m.vel.y - 1 + hScale = hScale * 1.3 + if (m.action & ACT_FLAG_AIR) ~= 0 then + hScale = hScale * 1.3 + end + end + + m.vel.x = m.vel.x * hScale + m.vel.z = m.vel.z * hScale +end + +function wario_on_set_action(m) + local e = gStateExtras[m.playerIndex] + + -- air dash + if m.action == ACT_MOVE_PUNCHING and m.prevAction == ACT_WARIO_DASH then + local actionTimer = m.actionTimer + set_mario_action(m, ACT_WARIO_AIR_DASH, 0) + m.actionTimer = actionTimer + m.vel.x = 0 + m.vel.y = 0 + m.vel.z = 0 + return + end + + -- slow down when dash/conk ends + if (m.prevAction == ACT_WARIO_DASH) or (m.prevAction == ACT_WARIO_AIR_DASH) or (m.prevAction == ACT_CORKSCREW_CONK) then + if m.action == ACT_CORKSCREW_CONK then + mario_set_forward_vel(m, 60) + m.vel.x = 0 + m.vel.y = 70.0 + m.vel.z = 0 + elseif (m.action == ACT_SLIDE_KICK) then + mario_set_forward_vel(m, 70) + m.vel.x = 0 + m.vel.y = 30.0 + m.vel.z = 0 + elseif m.forwardVel > 20 then + mario_set_forward_vel(m, 20) + end + end + + -- when hitting a wall which dashing, have one more single frame of dash + if m.action == ACT_GROUND_BONK and m.prevAction == ACT_WARIO_DASH then + set_mario_action(m, ACT_WARIO_DASH, 99) + mario_set_forward_vel(m, 1) + m.vel.x = 0 + m.vel.y = 0 + m.vel.z = 0 + end + + -- more height on triple jump + if m.action == ACT_TRIPLE_JUMP or m.action == ACT_SPECIAL_TRIPLE_JUMP then + m.vel.y = m.vel.y * 1.15 + end + + -- less height on other jumps + if m.action == ACT_JUMP or m.action == ACT_DOUBLE_JUMP or m.action == ACT_STEEP_JUMP or m.action == ACT_RIDING_SHELL_JUMP or m.action == ACT_BACKFLIP or m.action == ACT_LONG_JUMP then + m.vel.y = m.vel.y * 0.8 + + -- prevent from getting stuck on platform + if m.marioObj.platform ~= nil then + m.pos.y = m.pos.y + 10 + end + elseif m.action == ACT_SIDE_FLIP then + m.vel.y = m.vel.y * 0.86 + + -- prevent from getting stuck on platform + if m.marioObj.platform ~= nil then + m.pos.y = m.pos.y + 10 + end + end + e.lastAction = action +end + +function wario_update(m) + local hScale = 1.0 + local e = gStateExtras[m.playerIndex] + + wario_update_spin_input(m) + + -- spin around objects + if m.action == ACT_HOLD_IDLE or m.action == ACT_HOLD_WALKING then + if e.spinInput ~= 0 then + m.twirlYaw = m.intendedYaw + if e.spinDirection == 1 then + m.angleVel.y = 1500 + else + m.angleVel.y = -1500 + end + m.intendedMag = 21 + return set_mario_action(m, ACT_WARIO_SPINNING_OBJ, 1) + end + end + + -- turn heavy objects into light + if m.action == ACT_HOLD_HEAVY_IDLE then + return set_mario_action(m, ACT_HOLD_IDLE, 0) + end + + -- turn dive into dash + if m.action == ACT_DIVE and m.prevAction == ACT_WALKING then + if (m.controller.buttonPressed & B_BUTTON) ~= 0 then + m.actionTimer = 0 + return set_mario_action(m, ACT_WARIO_DASH, 0) + end + end + + -- shake cmaera + if m.action == ACT_GROUND_POUND_LAND then + set_camera_shake_from_hit(SHAKE_MED_DAMAGE) + end + + -- faster ground pound + if m.action == ACT_GROUND_POUND then + m.vel.y = m.vel.y * 1.3 + end + + -- more gravity + if (m.action & ACT_FLAG_AIR) ~= 0 then + m.vel.y = m.vel.y - 1.15 + end + + -- takes less damage + if m.action ~= ACT_LAVA_BOOST then + m.hurtCounter = m.hurtCounter * 0.5 + end + + m.vel.x = m.vel.x * hScale + m.vel.z = m.vel.z * hScale + + e.prevPos.x = m.pos.x + e.prevPos.y = m.pos.y + e.prevPos.z = m.pos.z +end + +gEventTable[CT_WARIO] = { + before_phys_step = wario_before_phys_step, + on_set_action = wario_on_set_action, + update = wario_update, +} + ---------- -- main -- ---------- @@ -462,9 +910,10 @@ function mario_before_phys_step(m) return end - if gEventTable[m.character.type] == nil then + if gEventTable[m.character.type] == nil or gEventTable[m.character.type].before_phys_step == nil then return end + gEventTable[m.character.type].before_phys_step(m) end @@ -473,20 +922,34 @@ function mario_on_set_action(m) return end - if gEventTable[m.character.type] == nil then + if gEventTable[m.character.type] == nil or gEventTable[m.character.type].on_set_action == nil then return end + gEventTable[m.character.type].on_set_action(m) end +function mario_before_update(m) + if m.action == ACT_BUBBLED then + return + end + + if gEventTable[m.character.type] == nil or gEventTable[m.character.type].before_update == nil then + return + end + + gEventTable[m.character.type].before_update(m) +end + function mario_update(m) if m.action == ACT_BUBBLED then return end - if gEventTable[m.character.type] == nil then + if gEventTable[m.character.type] == nil or gEventTable[m.character.type].update == nil then return end + gEventTable[m.character.type].update(m) end @@ -494,10 +957,15 @@ end -- hooks -- ----------- +hook_event(HOOK_BEFORE_MARIO_UPDATE, mario_before_update) hook_event(HOOK_MARIO_UPDATE, mario_update) hook_event(HOOK_ON_SET_MARIO_ACTION, mario_on_set_action) hook_event(HOOK_BEFORE_PHYS_STEP, mario_before_phys_step) hook_mario_action(ACT_WALL_SLIDE, act_wall_slide) -hook_mario_action(ACT_SPIN_POUND, act_spin_pound) -hook_mario_action(ACT_SPIN_POUND_LAND, act_spin_pound_land) +hook_mario_action(ACT_SPIN_POUND, act_spin_pound, INT_GROUND_POUND_OR_TWIRL) +hook_mario_action(ACT_SPIN_POUND_LAND, act_spin_pound_land, INT_GROUND_POUND_OR_TWIRL) +hook_mario_action(ACT_WARIO_DASH, act_wario_dash, INT_PUNCH) +hook_mario_action(ACT_WARIO_AIR_DASH, act_wario_air_dash, INT_PUNCH) +hook_mario_action(ACT_CORKSCREW_CONK, act_corkscrew_conk, INT_FAST_ATTACK_OR_SHELL) +hook_mario_action(ACT_WARIO_SPINNING_OBJ, act_wario_spinning_obj) diff --git a/src/game/interaction.c b/src/game/interaction.c index 1eea2092..e4994cd2 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -29,14 +29,16 @@ #include "pc/network/network.h" #include "pc/lua/smlua_hooks.h" -#define INT_GROUND_POUND_OR_TWIRL (1 << 0) // 0x01 -#define INT_PUNCH (1 << 1) // 0x02 -#define INT_KICK (1 << 2) // 0x04 -#define INT_TRIP (1 << 3) // 0x08 -#define INT_SLIDE_KICK (1 << 4) // 0x10 -#define INT_FAST_ATTACK_OR_SHELL (1 << 5) // 0x20 -#define INT_HIT_FROM_ABOVE (1 << 6) // 0x40 -#define INT_HIT_FROM_BELOW (1 << 7) // 0x80 +enum InteractionFlag { + INT_GROUND_POUND_OR_TWIRL = (1 << 0), // 0x01 + INT_PUNCH = (1 << 1), // 0x02 + INT_KICK = (1 << 2), // 0x04 + INT_TRIP = (1 << 3), // 0x08 + INT_SLIDE_KICK = (1 << 4), // 0x10 + INT_FAST_ATTACK_OR_SHELL = (1 << 5), // 0x20 + INT_HIT_FROM_ABOVE = (1 << 6), // 0x40 + INT_HIT_FROM_BELOW = (1 << 7), // 0x80 +}; #define INT_ATTACK_NOT_FROM_BELOW \ (INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_SLIDE_KICK \ @@ -192,15 +194,17 @@ u32 determine_interaction(struct MarioState *m, struct Object *o) { u32 interaction = 0; u32 action = m->action; + interaction = smlua_get_action_interaction_type(m); + // hack: make water punch actually do something - if (m->action == ACT_WATER_PUNCH && o->oInteractType & INTERACT_PLAYER) { + if (interaction == 0 && m->action == ACT_WATER_PUNCH && o->oInteractType & INTERACT_PLAYER) { s16 dYawToObject = mario_obj_angle_to_object(m, o) - m->faceAngle[1]; if (-0x2AAA <= dYawToObject && dYawToObject <= 0x2AAA) { - return INT_PUNCH; + interaction = INT_PUNCH; } } - if (action & ACT_FLAG_ATTACKING) { + if (interaction == 0 && action & ACT_FLAG_ATTACKING) { if (action == ACT_PUNCHING || action == ACT_MOVE_PUNCHING || action == ACT_JUMP_KICK) { s16 dYawToObject = mario_obj_angle_to_object(m, o) - m->faceAngle[1]; @@ -1347,6 +1351,7 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object u8 isAttackerInvulnerable = (m->action & ACT_FLAG_INVULNERABLE) || m->invincTimer != 0 || m->hurtCounter != 0; u8 isInvulnerable = (m2->action & ACT_FLAG_INVULNERABLE) || m2->invincTimer != 0 || m2->hurtCounter != 0 || isInCutscene; u8 isIgnoredAttack = (m->action == ACT_JUMP || m->action == ACT_DOUBLE_JUMP); + if ((interaction & INT_ANY_ATTACK) && !(interaction & INT_HIT_FROM_ABOVE) && !isInvulnerable && !isIgnoredAttack && !isAttackerInvulnerable) { // determine if slide attack should be ignored diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 4fcfdca0..e7e58bbc 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -115,6 +115,20 @@ char gSmluaConstants[] = "" " end\n" " return current;\n" "end\n" +"function approach_s32(current, target, inc, dec)\n" +" if current < target then\n" +" current = current + inc\n" +" if current > target then\n" +" current = target\n" +" end\n" +" else\n" +" current = current - dec\n" +" if current < target then\n" +" current = target\n" +" end\n" +" end\n" +" return current;\n" +"end\n" "function SOUND_ARG_LOAD(bank, playFlags, soundID, priority, flags2)\n" " return ((bank << 28) | (playFlags << 24) | (soundID << 16) | (priority << 8) | (flags2 << 4) | 1)\n" "end\n" @@ -818,6 +832,18 @@ char gSmluaConstants[] = "" "CHAR_SOUND_SO_LONGA_BOWSER = 40\n" "CHAR_SOUND_IMA_TIRED = 41\n" "CHAR_SOUND_MAX = 42\n" +"INT_GROUND_POUND_OR_TWIRL = (1 << 0)\n" +"INT_PUNCH = (1 << 1)\n" +"INT_KICK = (1 << 2)\n" +"INT_TRIP = (1 << 3)\n" +"INT_SLIDE_KICK = (1 << 4)\n" +"INT_FAST_ATTACK_OR_SHELL = (1 << 5)\n" +"INT_HIT_FROM_ABOVE = (1 << 6)\n" +"INT_HIT_FROM_BELOW = (1 << 7)\n" +"INT_ATTACK_NOT_FROM_BELOW = (INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_SLIDE_KICK | INT_FAST_ATTACK_OR_SHELL | INT_HIT_FROM_ABOVE)\n" +"INT_ANY_ATTACK = (INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_SLIDE_KICK | INT_FAST_ATTACK_OR_SHELL | INT_HIT_FROM_ABOVE | INT_HIT_FROM_BELOW)\n" +"INT_ATTACK_NOT_WEAK_FROM_ABOVE = (INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_HIT_FROM_BELOW)\n" +"INT_ATTACK_SLIDE = (INT_SLIDE_KICK | INT_FAST_ATTACK_OR_SHELL)\n" "MARIO_ANIM_SLOW_LEDGE_GRAB = 0\n" "MARIO_ANIM_FALL_OVER_BACKWARDS = 1\n" "MARIO_ANIM_BACKWARD_AIR_KB = 2\n" diff --git a/src/pc/lua/smlua_functions.c b/src/pc/lua/smlua_functions.c index 4801aa08..01eea5c4 100644 --- a/src/pc/lua/smlua_functions.c +++ b/src/pc/lua/smlua_functions.c @@ -19,6 +19,16 @@ bool smlua_functions_valid_param_count(lua_State* L, int expected) { return true; } +bool smlua_functions_valid_param_range(lua_State* L, int min, int max) { + int top = lua_gettop(L); + if (top < min || top > max) { + LOG_LUA("improper param count: expected (%u - %u), received %u", min, max, top); + smlua_logline(); + return false; + } + return true; +} + ////////// // misc // ////////// diff --git a/src/pc/lua/smlua_functions.h b/src/pc/lua/smlua_functions.h index 60f0d69d..29116859 100644 --- a/src/pc/lua/smlua_functions.h +++ b/src/pc/lua/smlua_functions.h @@ -2,6 +2,7 @@ #define SMLUA_FUNCTIONS_H bool smlua_functions_valid_param_count(lua_State* L, int expected); +bool smlua_functions_valid_param_range(lua_State* L, int min, int max); void smlua_bind_functions(void); #endif \ No newline at end of file diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c index 83dfc025..652a4263 100644 --- a/src/pc/lua/smlua_hooks.c +++ b/src/pc/lua/smlua_hooks.c @@ -12,6 +12,8 @@ static struct LuaHookedEvent sHookedEvents[HOOK_MAX] = { 0 }; int smlua_hook_event(lua_State* L) { if (L == NULL) { return 0; } + if (!smlua_functions_valid_param_count(L, 2)) { return 0; } + u16 hookType = smlua_to_integer(L, -2); if (!gSmLuaConvertSuccess) { return 0; } @@ -139,6 +141,7 @@ void smlua_call_event_hooks_network_player_param(enum LuaHookedEventType hookTyp struct LuaHookedMarioAction { u32 action; + u32 interactionType; int reference; }; @@ -149,6 +152,9 @@ static int sHookedMarioActionsCount = 0; int smlua_hook_mario_action(lua_State* L) { if (L == NULL) { return 0; } + if (!smlua_functions_valid_param_range(L, 2, 3)) { return 0; } + int paramCount = lua_gettop(L); + if (sHookedMarioActionsCount >= MAX_HOOKED_ACTIONS) { LOG_LUA("Hooked mario actions exceeded maximum references!"); smlua_logline(); @@ -162,6 +168,7 @@ int smlua_hook_mario_action(lua_State* L) { return 0; } + lua_pushvalue(L, 2); int ref = luaL_ref(L, LUA_REGISTRYINDEX); if (ref == -1) { @@ -170,8 +177,19 @@ int smlua_hook_mario_action(lua_State* L) { return 0; } + lua_Integer interactionType = 0; + if (paramCount >= 3) { + interactionType = smlua_to_integer(L, 3); + if (interactionType == 0 || !gSmLuaConvertSuccess) { + LOG_LUA("Hook Action: tried to hook invalid interactionType: %lld, %u", interactionType, gSmLuaConvertSuccess); + smlua_logline(); + return 0; + } + } + struct LuaHookedMarioAction* hooked = &sHookedMarioActions[sHookedMarioActionsCount]; hooked->action = action; + hooked->interactionType = interactionType; hooked->reference = ref; if (!gSmLuaConvertSuccess) { return 0; } @@ -213,6 +231,18 @@ bool smlua_call_action_hook(struct MarioState* m, s32* returnValue) { return false; } +u32 smlua_get_action_interaction_type(struct MarioState* m) { + u32 interactionType = 0; + lua_State* L = gLuaState; + if (L == NULL) { return false; } + for (int i = 0; i < sHookedMarioActionsCount; i++) { + if (sHookedMarioActions[i].action == m->action) { + interactionType |= sHookedMarioActions[i].interactionType; + } + } + return interactionType; +} + ///////////////////////// // hooked chat command // ///////////////////////// @@ -230,6 +260,8 @@ static int sHookedChatCommandsCount = 0; int smlua_hook_chat_command(lua_State* L) { if (L == NULL) { return 0; } + if (!smlua_functions_valid_param_count(L, 3)) { return 0; } + if (sHookedChatCommandsCount >= MAX_HOOKED_CHAT_COMMANDS) { LOG_LUA("Hooked chat command exceeded maximum references!"); smlua_logline(); diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h index 0d459f7d..87824e79 100644 --- a/src/pc/lua/smlua_hooks.h +++ b/src/pc/lua/smlua_hooks.h @@ -32,6 +32,7 @@ void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct void smlua_call_event_hooks_mario_params(enum LuaHookedEventType hookType, struct MarioState* m1, struct MarioState* m2); bool smlua_call_action_hook(struct MarioState* m, s32* returnValue); +u32 smlua_get_action_interaction_type(struct MarioState* m); bool smlua_call_chat_command_hook(char* command); void smlua_display_chat_commands(void);