mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-22 20:15:17 +00:00
d87dd73db1
* Allow Lua action hooks to specify custom functions for more behavior ...like gravity, and update all current mods to match. Spin jump and wall slide from the Extended Moveset mod now have gravity code basically matching the original mod. Currently, any place you'd want to use one of these new action hooks still requires an O(n) check through all action hook per call. This should probably be changed. * Fix some remaining issues with Extended Moveset Lua port - Remove divergent spin jump code - Remove divergent roll code - Remap roll button to Y - Reimplement dive slide to make dive hop work like the original - Allow spin from double jump, backflip, side flip * Fix more issues with Extended Moveset Lua port - Reimplement all users of update_walking_speed to incorporate the Tight Controls edits and modified speed caps - Fix instances of angle arithmetic to wrap properly across the mod * Don't chop off group bits of custom action flags; assign missing groups in mods This fixes the Extended Moveset's underwater actions. Chopping off those bits was making the game consider the underwater actions to be a part of the Stationary group, which caused `check_common_stationary_cancels`, which upwarps Mario to the surface. * Tweak roll sliding angle tendency Rolling will now gradually (but fairly quckly) try to tend Mario's facing angle down the slope. This is cleaner than my old method that tries to flip Mario's angle (wrongly) when he begins moving downward, having that logic coexist with the logic for normal sliding actions that can also tend Mario to face backward down the slope. Just looks ugly now by comparison. * Disallow spin jump on slides in Extended Moveset port This matches the original mod * Extended Moveset: Crazy Box Bounce check * Extended Moveset: Fix hugging the wall when spin jumping after wall kick * Extended Moveset: Fix ledge drop snapping up to ground Just reimplement `act_air_hit_wall` ourselves. * Extended Moveset: Add Kaze's walking speed fix * smlua_hooks.c: Restore option to use old API for hook_mario_action The intent is to allow mods outside of this repo to continue working. Co-authored-by: djoslin0 <djoslin0@users.noreply.github.com>
1018 lines
30 KiB
Lua
1018 lines
30 KiB
Lua
-- name: Character Movesets
|
|
-- incompatible: moveset
|
|
-- description: Gives each character unique abilities and stats.\n\nContributors: djoslin0, TheGag96, Draco, steven.
|
|
|
|
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
|
|
e.averageForwardVel = 0
|
|
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
|
|
|
|
-----------
|
|
-- luigi --
|
|
-----------
|
|
|
|
ACT_SPIN_POUND_LAND = allocate_mario_action(ACT_GROUP_STATIONARY | ACT_FLAG_STATIONARY | ACT_FLAG_ATTACKING)
|
|
ACT_SPIN_POUND = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_ATTACKING)
|
|
|
|
function act_spin_pound(m)
|
|
local e = gStateExtras[m.playerIndex]
|
|
if m.actionTimer == 0 then
|
|
m.actionState = m.actionArg
|
|
end
|
|
|
|
local spinDirFactor = 1 -- negative for clockwise, positive for counter-clockwise
|
|
if m.actionState == 1 then spinDirFactor = -1 end
|
|
|
|
set_mario_animation(m, MARIO_ANIM_TWIRL)
|
|
|
|
m.particleFlags = m.particleFlags | PARTICLE_DUST
|
|
|
|
if (m.controller.buttonDown & Z_TRIG) == 0 then
|
|
set_mario_action(m, ACT_TWIRLING, 5)
|
|
end
|
|
|
|
local stepResult = perform_air_step(m, 0)
|
|
if stepResult == AIR_STEP_LANDED then
|
|
if should_get_stuck_in_ground(m) ~= 0 then
|
|
queue_rumble_data_mario(m, 5, 80)
|
|
play_character_sound(m, CHAR_SOUND_OOOF2)
|
|
m.particleFlags = m.particleFlags | PARTICLE_MIST_CIRCLE
|
|
set_mario_action(m, ACT_BUTT_STUCK_IN_GROUND, 0)
|
|
else
|
|
play_mario_heavy_landing_sound(m, SOUND_ACTION_TERRAIN_HEAVY_LANDING)
|
|
if check_fall_damage(m, ACT_HARD_BACKWARD_GROUND_KB) == 0 then
|
|
m.particleFlags = m.particleFlags | PARTICLE_MIST_CIRCLE | PARTICLE_HORIZONTAL_STAR
|
|
set_mario_action(m, ACT_SPIN_POUND_LAND, 0)
|
|
end
|
|
end
|
|
set_camera_shake_from_hit(SHAKE_GROUND_POUND)
|
|
elseif stepResult == AIR_STEP_HIT_WALL then
|
|
mario_set_forward_vel(m, -16.0)
|
|
if m.vel.y > 0.0 then
|
|
m.vel.y = 0.0
|
|
end
|
|
|
|
m.particleFlags = m.particleFlags | PARTICLE_VERTICAL_STAR
|
|
set_mario_action(m, ACT_BACKWARD_AIR_KB, 0)
|
|
end
|
|
|
|
-- set facing direction
|
|
-- not part of original Extended Moveset
|
|
local yawDiff = m.faceAngle.y - m.intendedYaw
|
|
e.rotAngle = e.rotAngle + yawDiff
|
|
m.faceAngle.y = m.intendedYaw
|
|
|
|
e.rotAngle = e.rotAngle + 0x3053
|
|
if e.rotAngle > 0x10000 then e.rotAngle = e.rotAngle - 0x10000 end
|
|
if e.rotAngle < -0x10000 then e.rotAngle = e.rotAngle + 0x10000 end
|
|
m.marioObj.header.gfx.angle.y = m.marioObj.header.gfx.angle.y + e.rotAngle * spinDirFactor
|
|
m.marioBodyState.handState = MARIO_HAND_OPEN
|
|
|
|
m.actionTimer = m.actionTimer + 1
|
|
|
|
return 0
|
|
end
|
|
|
|
function act_spin_pound_land(m)
|
|
m.actionState = 1
|
|
|
|
if m.actionTimer <= 8 then
|
|
if (m.input & INPUT_UNKNOWN_10) ~= 0 then
|
|
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0)
|
|
end
|
|
|
|
if (m.input & INPUT_OFF_FLOOR) ~= 0 then
|
|
return set_mario_action(m, ACT_FREEFALL, 0)
|
|
end
|
|
|
|
if (m.input & INPUT_ABOVE_SLIDE) ~= 0 then
|
|
return set_mario_action(m, ACT_BUTT_SLIDE, 0)
|
|
end
|
|
|
|
stationary_ground_step(m)
|
|
set_mario_animation(m, MARIO_ANIM_LAND_FROM_DOUBLE_JUMP)
|
|
else
|
|
if (m.input & INPUT_UNKNOWN_10) ~= 0 then
|
|
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0)
|
|
end
|
|
|
|
if (m.input & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE)) ~= 0 then
|
|
return check_common_action_exits(m)
|
|
end
|
|
|
|
stopping_step(m, MARIO_ANIM_LAND_FROM_DOUBLE_JUMP, ACT_IDLE)
|
|
end
|
|
|
|
m.actionTimer = m.actionTimer + 1
|
|
|
|
return 0
|
|
end
|
|
|
|
function luigi_before_phys_step(m)
|
|
local e = gStateExtras[m.playerIndex]
|
|
|
|
local floorClass = mario_get_floor_class(m)
|
|
local hScale = 1.0
|
|
local vScale = 1.0
|
|
|
|
-- faster swimming
|
|
if (m.action & ACT_FLAG_SWIMMING) ~= 0 then
|
|
if m.action ~= ACT_BACKWARD_WATER_KB and m.action ~= ACT_FORWARD_WATER_KB then
|
|
hScale = hScale * 1.5
|
|
if m.action ~= ACT_WATER_PLUNGE then
|
|
vScale = vScale * 1.5
|
|
end
|
|
end
|
|
end
|
|
|
|
-- slower holding item
|
|
if m.heldObj ~= nil then
|
|
m.vel.y = m.vel.y - 1.0
|
|
hScale = hScale * 0.9
|
|
if (m.action & ACT_FLAG_AIR) ~= 0 then
|
|
hScale = hScale * 0.9
|
|
end
|
|
end
|
|
|
|
-- acceleration
|
|
if (m.action == ACT_WALKING) then
|
|
if (floorClass == 19 or floorClass == 20) then
|
|
hScale = -(m.forwardVel / 64) + 1.5
|
|
else
|
|
hScale = (m.forwardVel / 64) + 0.5
|
|
end
|
|
end
|
|
|
|
-- friction
|
|
if (m.action == ACT_BRAKING or m.action == ACT_TURNING_AROUND) then
|
|
if (floorClass == 19 or floorClass == 20) then
|
|
m.forwardVel = m.forwardVel - 3
|
|
elseif (floorClass == 21) then
|
|
hScale = hScale * 1.5
|
|
m.forwardVel = m.forwardVel + (hScale * 2)
|
|
else
|
|
hScale = hScale * 1.4
|
|
m.forwardVel = m.forwardVel + hScale
|
|
end
|
|
if (m.forwardVel < 0) then
|
|
m.forwardVel = 0
|
|
end
|
|
end
|
|
|
|
m.vel.x = m.vel.x * hScale
|
|
m.vel.y = m.vel.y * vScale
|
|
m.vel.z = m.vel.z * hScale
|
|
end
|
|
|
|
function luigi_on_set_action(m)
|
|
local e = gStateExtras[m.playerIndex]
|
|
|
|
-- extra height to the backflip
|
|
if m.action == ACT_BACKFLIP then
|
|
m.vel.y = m.vel.y + 18
|
|
|
|
-- nerf wall kicks
|
|
elseif m.action == ACT_WALL_KICK_AIR and m.prevAction ~= ACT_HOLDING_POLE and m.prevAction ~= ACT_CLIMBING_POLE then
|
|
if m.vel.y > 56 then m.vel.y = 56 end
|
|
return
|
|
|
|
-- turn dive into kick when holding jump
|
|
elseif m.action == ACT_DIVE and (m.controller.buttonDown & A_BUTTON) ~= 0 and e.scuttle > 0 then
|
|
return set_mario_action(m, ACT_JUMP_KICK, 0)
|
|
|
|
-- extra height on jumps
|
|
elseif m.action == ACT_JUMP or m.action == ACT_DOUBLE_JUMP or m.action == ACT_TRIPLE_JUMP or m.action == ACT_SPECIAL_TRIPLE_JUMP or m.action == ACT_STEEP_JUMP or m.action == ACT_SIDE_FLIP or m.action == ACT_RIDING_SHELL_JUMP then
|
|
m.vel.y = m.vel.y + 6
|
|
|
|
end
|
|
|
|
e.lastAction = action
|
|
end
|
|
|
|
function luigi_update(m)
|
|
local e = gStateExtras[m.playerIndex]
|
|
|
|
-- increase player damage
|
|
if (m.hurtCounter > e.lastHurtCounter) then
|
|
m.hurtCounter = m.hurtCounter + 4
|
|
end
|
|
e.lastHurtCounter = m.hurtCounter
|
|
|
|
-- air scuttle
|
|
e.scuttle = 0
|
|
local shouldScuttle = (m.action == ACT_JUMP or m.action == ACT_DOUBLE_JUMP) and ((m.controller.buttonDown & A_BUTTON) ~= 0 and m.vel.y < -5)
|
|
if shouldScuttle then
|
|
-- prevent wing flutter from glitching out while scuttling
|
|
if m.marioBodyState.wingFlutter == 1 then
|
|
m.vel.y = m.vel.y + 1
|
|
else
|
|
m.vel.y = m.vel.y + 3
|
|
set_mario_animation(m, MARIO_ANIM_RUNNING_UNUSED)
|
|
set_anim_to_frame(m, e.animFrame)
|
|
e.animFrame = e.animFrame + 13
|
|
if e.animFrame >= m.marioObj.header.gfx.animInfo.curAnim.loopEnd then
|
|
e.animFrame = e.animFrame - m.marioObj.header.gfx.animInfo.curAnim.loopEnd
|
|
end
|
|
e.scuttle = 1
|
|
end
|
|
end
|
|
|
|
-- twirl pound
|
|
if m.action == ACT_TWIRLING and (m.controller.buttonDown & Z_TRIG) ~= 0 then
|
|
set_mario_action(m, ACT_SPIN_POUND, 0)
|
|
end
|
|
|
|
-- backflip turns into twirl
|
|
if m.action == ACT_BACKFLIP and m.marioObj.header.gfx.animInfo.animFrame > 18 then
|
|
m.angleVel.y = 0x1800
|
|
set_mario_action(m, ACT_TWIRLING, 1)
|
|
end
|
|
end
|
|
|
|
gEventTable[CT_LUIGI] = {
|
|
before_phys_step = luigi_before_phys_step,
|
|
on_set_action = luigi_on_set_action,
|
|
update = luigi_update,
|
|
}
|
|
|
|
-----------
|
|
-- toad --
|
|
-----------
|
|
|
|
function toad_before_phys_step(m)
|
|
local e = gStateExtras[m.playerIndex]
|
|
|
|
local hScale = 1.0
|
|
local vScale = 1.0
|
|
|
|
-- faster ground movement
|
|
if (m.action & ACT_FLAG_MOVING) ~= 0 then
|
|
hScale = hScale * 1.19
|
|
end
|
|
|
|
-- slower holding item
|
|
if m.heldObj ~= nil then
|
|
m.vel.y = m.vel.y - 2.0
|
|
hScale = hScale * 0.9
|
|
if (m.action & ACT_FLAG_AIR) ~= 0 then
|
|
hScale = hScale * 0.9
|
|
end
|
|
end
|
|
|
|
m.vel.x = m.vel.x * hScale
|
|
m.vel.y = m.vel.y * vScale
|
|
m.vel.z = m.vel.z * hScale
|
|
end
|
|
|
|
function toad_on_set_action(m)
|
|
local e = gStateExtras[m.playerIndex]
|
|
|
|
-- wall kick height based on how fast toad is going
|
|
if m.action == ACT_WALL_KICK_AIR and m.prevAction ~= ACT_HOLDING_POLE and m.prevAction ~= ACT_CLIMBING_POLE then
|
|
m.vel.y = m.vel.y * 0.5
|
|
m.vel.y = m.vel.y + e.averageForwardVel * 0.7
|
|
return
|
|
end
|
|
|
|
-- more distance on dive and long jump
|
|
if m.action == ACT_DIVE or m.action == ACT_LONG_JUMP then
|
|
m.forwardVel = m.forwardVel * 1.35
|
|
end
|
|
|
|
-- less height on jumps
|
|
if m.action == ACT_JUMP or m.action == ACT_DOUBLE_JUMP or m.action == ACT_TRIPLE_JUMP or m.action == ACT_SPECIAL_TRIPLE_JUMP or m.action == ACT_STEEP_JUMP or m.action == ACT_RIDING_SHELL_JUMP or m.action == ACT_BACKFLIP or m.action == ACT_WALL_KICK_AIR 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 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
|
|
e.averageForwardVel = m.forwardVel
|
|
end
|
|
|
|
-- faster flip during ground pound
|
|
if m.action == ACT_GROUND_POUND then
|
|
if m.actionTimer < 10 then
|
|
m.actionTimer = m.actionTimer + 1
|
|
end
|
|
end
|
|
|
|
-- ground pound jump
|
|
if m.action == ACT_GROUND_POUND_LAND and (m.input & INPUT_A_PRESSED) ~= 0 then
|
|
set_mario_action(m, ACT_TRIPLE_JUMP, 0)
|
|
m.vel.y = m.vel.y + 18
|
|
m.forwardVel = m.forwardVel + 10
|
|
end
|
|
|
|
end
|
|
|
|
gEventTable[CT_TOAD] = {
|
|
before_phys_step = toad_before_phys_step,
|
|
on_set_action = toad_on_set_action,
|
|
update = toad_update,
|
|
}
|
|
|
|
-------------
|
|
-- waluigi --
|
|
-------------
|
|
|
|
ACT_WALL_SLIDE = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
|
|
|
function act_wall_slide(m)
|
|
if (m.input & INPUT_A_PRESSED) ~= 0 then
|
|
local rc = set_mario_action(m, ACT_TRIPLE_JUMP, 0)
|
|
m.vel.y = 72.0
|
|
|
|
if m.forwardVel < 20.0 then
|
|
m.forwardVel = 20.0
|
|
end
|
|
m.wallKickTimer = 0
|
|
return rc
|
|
end
|
|
|
|
-- attempt to stick to the wall a bit. if it's 0, sometimes you'll get kicked off of slightly sloped walls
|
|
mario_set_forward_vel(m, -1.0)
|
|
|
|
m.particleFlags = m.particleFlags | PARTICLE_DUST
|
|
|
|
play_sound(SOUND_MOVING_TERRAIN_SLIDE + m.terrainSoundAddend, m.marioObj.header.gfx.cameraToObject)
|
|
set_mario_animation(m, MARIO_ANIM_START_WALLKICK)
|
|
|
|
if perform_air_step(m, 0) == AIR_STEP_LANDED then
|
|
mario_set_forward_vel(m, 0.0)
|
|
if check_fall_damage_or_get_stuck(m, ACT_HARD_BACKWARD_GROUND_KB) == 0 then
|
|
return set_mario_action(m, ACT_FREEFALL_LAND, 0)
|
|
end
|
|
end
|
|
|
|
m.actionTimer = m.actionTimer + 1
|
|
if m.wall == nil and m.actionTimer > 2 then
|
|
mario_set_forward_vel(m, 0.0)
|
|
return set_mario_action(m, ACT_FREEFALL, 0)
|
|
end
|
|
|
|
-- gravity
|
|
m.vel.y = m.vel.y + 2
|
|
|
|
return 0
|
|
end
|
|
|
|
function waluigi_before_phys_step(m)
|
|
local e = gStateExtras[m.playerIndex]
|
|
|
|
local hScale = 1.0
|
|
local vScale = 1.0
|
|
|
|
-- faster ground movement
|
|
if (m.action & ACT_FLAG_MOVING) ~= 0 then
|
|
hScale = hScale * 1.085
|
|
end
|
|
|
|
m.vel.x = m.vel.x * hScale
|
|
m.vel.y = m.vel.y * vScale
|
|
m.vel.z = m.vel.z * hScale
|
|
|
|
if m.action == ACT_TRIPLE_JUMP and m.prevAction == ACT_DOUBLE_JUMP and m.actionTimer < 6 then
|
|
m.particleFlags = m.particleFlags | PARTICLE_DUST
|
|
m.actionTimer = m.actionTimer + 1
|
|
end
|
|
end
|
|
|
|
function waluigi_on_set_action(m)
|
|
local e = gStateExtras[m.playerIndex]
|
|
|
|
-- wall slide
|
|
if m.action == ACT_SOFT_BONK then
|
|
m.faceAngle.y = m.faceAngle.y + 0x8000
|
|
set_mario_action(m, ACT_WALL_SLIDE, 0)
|
|
m.vel.x = 0
|
|
m.vel.y = 0
|
|
m.vel.z = 0
|
|
|
|
-- turn wall kick into flip
|
|
elseif m.action == ACT_WALL_KICK_AIR and m.prevAction ~= ACT_HOLDING_POLE and m.prevAction ~= ACT_CLIMBING_POLE then
|
|
local rc = set_mario_action(m, ACT_TRIPLE_JUMP, 0)
|
|
m.vel.y = 60.0
|
|
|
|
if m.forwardVel < 20.0 then
|
|
m.forwardVel = 20.0
|
|
end
|
|
m.wallKickTimer = 0
|
|
return rc
|
|
|
|
-- less height on jumps
|
|
elseif m.action == ACT_JUMP or m.action == ACT_DOUBLE_JUMP or m.action == ACT_TRIPLE_JUMP or m.action == ACT_SPECIAL_TRIPLE_JUMP or m.action == ACT_STEEP_JUMP or m.action == ACT_SIDE_FLIP or m.action == ACT_RIDING_SHELL_JUMP or m.action == ACT_BACKFLIP or m.action == ACT_WALL_KICK_AIR or m.action == ACT_LONG_JUMP then
|
|
m.vel.y = m.vel.y * 0.91
|
|
end
|
|
|
|
e.lastAction = action
|
|
end
|
|
|
|
function waluigi_update(m)
|
|
local e = gStateExtras[m.playerIndex]
|
|
|
|
-- increase player damage
|
|
if m.hurtCounter > e.lastHurtCounter then
|
|
m.hurtCounter = m.hurtCounter * 2
|
|
end
|
|
e.lastHurtCounter = m.hurtCounter
|
|
|
|
-- double jump
|
|
if m.action == ACT_DOUBLE_JUMP and m.actionTimer > 0 and (m.controller.buttonPressed & A_BUTTON) ~= 0 then
|
|
set_mario_action(m, ACT_TRIPLE_JUMP, 0)
|
|
m.vel.y = m.vel.y * 0.8
|
|
end
|
|
if m.action == ACT_DOUBLE_JUMP then
|
|
m.actionTimer = m.actionTimer + 1
|
|
end
|
|
|
|
end
|
|
|
|
gEventTable[CT_WALUIGI] = {
|
|
before_phys_step = waluigi_before_phys_step,
|
|
on_set_action = waluigi_on_set_action,
|
|
update = waluigi_update,
|
|
}
|
|
|
|
-----------
|
|
-- wario --
|
|
-----------
|
|
|
|
ACT_WARIO_DASH = allocate_mario_action(ACT_GROUP_MOVING | ACT_FLAG_MOVING | ACT_FLAG_ATTACKING)
|
|
ACT_WARIO_AIR_DASH = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_ATTACKING)
|
|
ACT_CORKSCREW_CONK = allocate_mario_action(ACT_GROUP_AIRBORNE | ACT_FLAG_AIR | ACT_FLAG_ATTACKING | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
|
ACT_WARIO_SPINNING_OBJ = allocate_mario_action(ACT_GROUP_OBJECT | ACT_FLAG_STATIONARY)
|
|
|
|
function act_corkscrew_conk(m)
|
|
local e = gStateExtras[m.playerIndex]
|
|
|
|
-- visuals
|
|
m.particleFlags = m.particleFlags | PARTICLE_DUST
|
|
|
|
-- physics
|
|
common_air_action_step(m, ACT_JUMP_LAND, MARIO_ANIM_FORWARD_SPINNING, AIR_STEP_NONE)
|
|
|
|
-- animation
|
|
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
|
|
|
|
-- fast ground pound out of it
|
|
if (m.input & INPUT_Z_PRESSED) ~= 0 then
|
|
local rc = set_mario_action(m, ACT_GROUND_POUND, 0)
|
|
m.actionTimer = 5
|
|
return rc
|
|
end
|
|
|
|
-- timers
|
|
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, knock Wario backwards and thrust him upwards
|
|
if m.actionArg == 99 then
|
|
m.actionTimer = m.actionTimer + 1
|
|
if m.actionTimer > 2 then
|
|
mario_set_forward_vel(m, -30)
|
|
m.vel.y = 40
|
|
return set_mario_action(m, ACT_FREEFALL, 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 = 60
|
|
if m.actionTimer > 8 then
|
|
speed = speed - (m.actionTimer - 8)
|
|
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]
|
|
|
|
-- when hitting wall, knock Wario backwards and thrust him upwards
|
|
if m.actionArg == 99 then
|
|
m.actionTimer = m.actionTimer + 1
|
|
if m.actionTimer > 2 then
|
|
m.particleFlags = m.particleFlags | PARTICLE_VERTICAL_STAR
|
|
mario_set_forward_vel(m, -30)
|
|
m.vel.y = 40
|
|
return set_mario_action(m, ACT_FREEFALL, 0)
|
|
end
|
|
return 0
|
|
end
|
|
|
|
-- 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 = 60
|
|
if m.actionTimer > 8 then
|
|
speed = speed - (m.actionTimer - 8)
|
|
end
|
|
mario_set_forward_vel(m, speed)
|
|
|
|
-- corkscrew conk
|
|
if (m.input & INPUT_A_PRESSED) ~= 0 then
|
|
m.particleFlags = m.particleFlags | PARTICLE_MIST_CIRCLE
|
|
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_WALKING then
|
|
hScale = hScale * 0.9
|
|
end
|
|
|
|
-- make wario sink
|
|
if (m.action & ACT_FLAG_SWIMMING) ~= 0 then
|
|
if m.action ~= ACT_BACKWARD_WATER_KB and
|
|
m.action ~= ACT_FORWARD_WATER_KB and
|
|
m.action ~= ACT_WATER_PLUNGE then
|
|
m.vel.y = m.vel.y - 3
|
|
end
|
|
end
|
|
|
|
-- fixes the momentum bug
|
|
if (m.action & ACT_HOLD_WATER_JUMP) then
|
|
return
|
|
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
|
|
-- nerf the conk when executed in the air
|
|
if (m.prevAction == ACT_WARIO_DASH) then
|
|
m.vel.y = 70.0
|
|
elseif (m.prevAction == ACT_WARIO_AIR_DASH) then
|
|
m.vel.y = 60.0
|
|
end
|
|
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
|
|
|
|
-- when hitting a wall which dashing, have one more single frame of dash
|
|
if m.action == ACT_AIR_HIT_WALL and m.prevAction == ACT_WARIO_AIR_DASH then
|
|
set_mario_action(m, ACT_WARIO_AIR_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 or
|
|
m.action == ACT_SIDE_FLIP then
|
|
|
|
m.vel.y = m.vel.y * 0.9
|
|
|
|
-- 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 camera
|
|
if m.action == ACT_GROUND_POUND_LAND then
|
|
set_camera_shake_from_point(SHAKE_POS_MEDIUM, m.pos.x, m.pos.y, m.pos.z)
|
|
end
|
|
|
|
-- faster ground pound
|
|
if m.action == ACT_GROUND_POUND then
|
|
m.vel.y = m.vel.y * 1.3
|
|
end
|
|
|
|
-- decrease player damage
|
|
if m.hurtCounter > e.lastHurtCounter and m.action ~= ACT_LAVA_BOOST then
|
|
m.hurtCounter = math.max(3, m.hurtCounter - 4)
|
|
end
|
|
e.lastHurtCounter = m.hurtCounter
|
|
|
|
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 --
|
|
----------
|
|
|
|
function mario_before_phys_step(m)
|
|
if m.action == ACT_BUBBLED then
|
|
return
|
|
end
|
|
|
|
if gEventTable[m.character.type] == nil then
|
|
return
|
|
end
|
|
|
|
if gEventTable[m.character.type].before_phys_step == nil then
|
|
return
|
|
end
|
|
|
|
gEventTable[m.character.type].before_phys_step(m)
|
|
end
|
|
|
|
function mario_on_set_action(m)
|
|
if m.action == ACT_BUBBLED then
|
|
return
|
|
end
|
|
|
|
if gEventTable[m.character.type] == nil then
|
|
return
|
|
end
|
|
|
|
if gEventTable[m.character.type].on_set_action == nil then
|
|
return
|
|
end
|
|
|
|
gEventTable[m.character.type].on_set_action(m)
|
|
end
|
|
|
|
function mario_update(m)
|
|
if m.action == ACT_BUBBLED then
|
|
return
|
|
end
|
|
|
|
if gEventTable[m.character.type] == nil then
|
|
return
|
|
end
|
|
|
|
if gEventTable[m.character.type].update == nil then
|
|
return
|
|
end
|
|
|
|
gEventTable[m.character.type].update(m)
|
|
end
|
|
|
|
-----------
|
|
-- hooks --
|
|
-----------
|
|
|
|
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, { every_frame = act_wall_slide })
|
|
hook_mario_action(ACT_SPIN_POUND, { every_frame = act_spin_pound }, INT_GROUND_POUND_OR_TWIRL)
|
|
hook_mario_action(ACT_SPIN_POUND_LAND, { every_frame = act_spin_pound_land }, INT_GROUND_POUND_OR_TWIRL)
|
|
hook_mario_action(ACT_WARIO_DASH, { every_frame = act_wario_dash }, INT_PUNCH)
|
|
hook_mario_action(ACT_WARIO_AIR_DASH, { every_frame = act_wario_air_dash }, INT_PUNCH)
|
|
hook_mario_action(ACT_CORKSCREW_CONK, { every_frame = act_corkscrew_conk }, INT_FAST_ATTACK_OR_SHELL)
|
|
hook_mario_action(ACT_WARIO_SPINNING_OBJ, { every_frame = act_wario_spinning_obj })
|