25faa67878
Still not being used atm.
857 lines
20 KiB
Lua
857 lines
20 KiB
Lua
local System = require(script.Parent)
|
|
local Animations = System.Animations
|
|
local Sounds = System.Sounds
|
|
local Enums = System.Enums
|
|
local Util = System.Util
|
|
|
|
local Action = Enums.Action
|
|
local AirStep = Enums.AirStep
|
|
local WaterStep = Enums.WaterStep
|
|
local GroundStep = Enums.GroundStep
|
|
local InputFlags = Enums.InputFlags
|
|
local MarioFlags = Enums.MarioFlags
|
|
local ActionFlags = Enums.ActionFlags
|
|
local ParticleFlags = Enums.ParticleFlags
|
|
|
|
local MIN_SWIM_STRENGTH = 160
|
|
local MIN_SWIM_SPEED = 16
|
|
|
|
local sWasAtSurface = false
|
|
local sSwimStrength = MIN_SWIM_STRENGTH
|
|
|
|
local sBobTimer = 0
|
|
local sBobIncrement = 0
|
|
local sBobHeight = 0
|
|
|
|
type Mario = System.Mario
|
|
|
|
local function setSwimmingAtSurfaceParticles(m: Mario, particleFlag: number)
|
|
local atSurface = m.Position.Y >= m.WaterLevel - 130
|
|
|
|
if atSurface then
|
|
m.ParticleFlags:Add(particleFlag)
|
|
|
|
if atSurface ~= sWasAtSurface then
|
|
m:PlaySound(Sounds.ACTION_UNKNOWN431)
|
|
end
|
|
end
|
|
|
|
sWasAtSurface = atSurface
|
|
end
|
|
|
|
local function swimmingNearSurface(m: Mario)
|
|
if m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return false
|
|
end
|
|
|
|
return (m.WaterLevel - 80) - m.Position.Y < 400
|
|
end
|
|
|
|
local function getBuoyancy(m: Mario)
|
|
local buoyancy = 0
|
|
|
|
if m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
if m.Action:Has(ActionFlags.INVULNERABLE) then
|
|
buoyancy = -2
|
|
else
|
|
buoyancy = -18
|
|
end
|
|
elseif swimmingNearSurface(m) then
|
|
buoyancy = 1.25
|
|
elseif not m.Action:Has(ActionFlags.MOVING) then
|
|
buoyancy = -2
|
|
end
|
|
|
|
return buoyancy
|
|
end
|
|
|
|
local function performWaterFullStep(m: Mario, nextPos: Vector3)
|
|
local adjusted, wall = Util.FindWallCollisions(nextPos, 10, 110)
|
|
nextPos = adjusted
|
|
|
|
local floorHeight, floor = Util.FindFloor(nextPos)
|
|
local ceilHeight = Util.FindCeil(nextPos, floorHeight)
|
|
|
|
if floor == nil then
|
|
return WaterStep.CANCELLED
|
|
end
|
|
|
|
if nextPos.Y >= floorHeight then
|
|
if ceilHeight - nextPos.Y >= 160 then
|
|
m.Position = nextPos
|
|
m.Floor = floor
|
|
m.FloorHeight = floorHeight
|
|
|
|
if wall then
|
|
return WaterStep.HIT_WALL
|
|
else
|
|
return WaterStep.NONE
|
|
end
|
|
end
|
|
|
|
if ceilHeight - floorHeight < 160 then
|
|
return WaterStep.CANCELLED
|
|
end
|
|
|
|
--! Water ceiling downwarp
|
|
m.Position = Util.SetY(nextPos, ceilHeight - 160)
|
|
m.Floor = floor
|
|
m.FloorHeight = floorHeight
|
|
return WaterStep.HIT_CEILING
|
|
else
|
|
if ceilHeight - floorHeight < 160 then
|
|
return WaterStep.CANCELLED
|
|
end
|
|
|
|
m.Position = Util.SetY(nextPos, floorHeight)
|
|
m.Floor = floor
|
|
m.FloorHeight = floorHeight
|
|
return WaterStep.HIT_FLOOR
|
|
end
|
|
end
|
|
|
|
local function applyWaterCurrent(m: Mario, step: Vector3): Vector3
|
|
-- TODO: Implement if actually needed.
|
|
-- This normally handles whirlpools and moving
|
|
-- water, neither of which I think I'll be using.
|
|
|
|
return step
|
|
end
|
|
|
|
local function performWaterStep(m: Mario)
|
|
local nextPos = m.Position
|
|
local step = m.Velocity
|
|
|
|
if m.Action:Has(ActionFlags.SWIMMING) then
|
|
step = applyWaterCurrent(m, step)
|
|
end
|
|
|
|
nextPos += step
|
|
|
|
if nextPos.Y > m.WaterLevel - 80 then
|
|
nextPos = Util.SetY(nextPos, m.WaterLevel - 80)
|
|
m.Velocity *= Vector3.new(1, 0, 1)
|
|
end
|
|
|
|
local stepResult = performWaterFullStep(m, nextPos)
|
|
m.GfxAngle = m.FaceAngle * Vector3int16.new(-1, 1, 1)
|
|
m.GfxPos = m.Position
|
|
|
|
return stepResult
|
|
end
|
|
|
|
local function updateWaterPitch(m: Mario)
|
|
local gfxAngle = m.GfxAngle
|
|
|
|
if gfxAngle.X > 0 then
|
|
local angle = 60 * Util.Sins(gfxAngle.X) * Util.Sins(gfxAngle.X)
|
|
m.GfxPos += Vector3.new(0, angle, 0)
|
|
end
|
|
|
|
if gfxAngle.X < 0 then
|
|
local x = gfxAngle.X * 6 / 10
|
|
gfxAngle = Util.SetX(gfxAngle, x)
|
|
end
|
|
|
|
if gfxAngle.X > 0 then
|
|
local x = gfxAngle.X * 10 / 8
|
|
gfxAngle = Util.SetX(gfxAngle, x)
|
|
end
|
|
|
|
m.GfxAngle = gfxAngle
|
|
end
|
|
|
|
local function stationarySlowDown(m: Mario)
|
|
local buoyancy = getBuoyancy(m)
|
|
m.AngleVel *= Vector3int16.new(0, 0, 1)
|
|
m.ForwardVel = Util.ApproachFloat(m.ForwardVel, 0, 1, 1)
|
|
|
|
local faceY = m.FaceAngle.Y
|
|
local faceX = Util.ApproachInt(m.FaceAngle.X, 0, 0x200, 0x200)
|
|
local faceZ = Util.ApproachInt(m.FaceAngle.Z, 0, 0x100, 0x100)
|
|
|
|
local velY = Util.ApproachFloat(m.Velocity.Y, buoyancy, 2, 1)
|
|
local velX = m.ForwardVel * Util.Coss(faceX) * Util.Sins(faceY)
|
|
local velZ = m.ForwardVel * Util.Coss(faceX) * Util.Coss(faceY)
|
|
|
|
m.FaceAngle = Vector3int16.new(faceX, faceY, faceZ)
|
|
m.Velocity = Vector3.new(velX, velY, velZ)
|
|
end
|
|
|
|
local function updateSwimmingSpeed(m: Mario, maybeDecelThreshold: number?)
|
|
local buoyancy = getBuoyancy(m)
|
|
local decelThreshold = maybeDecelThreshold or MIN_SWIM_SPEED
|
|
|
|
if m.Action:Has(ActionFlags.STATIONARY) then
|
|
m.ForwardVel -= 2
|
|
end
|
|
|
|
m.ForwardVel = math.clamp(m.ForwardVel, 0, 28)
|
|
|
|
if m.ForwardVel > decelThreshold then
|
|
m.ForwardVel -= 0.5
|
|
end
|
|
|
|
m.Velocity = Vector3.new(
|
|
m.ForwardVel * Util.Coss(m.FaceAngle.X) * Util.Sins(m.FaceAngle.Y),
|
|
m.ForwardVel * Util.Sins(m.FaceAngle.X) + buoyancy,
|
|
m.ForwardVel * Util.Coss(m.FaceAngle.X) * Util.Coss(m.FaceAngle.Y)
|
|
)
|
|
end
|
|
|
|
local function updateSwimmingYaw(m: Mario)
|
|
local targetYawVel = -Util.SignedShort(10 * m.Controller.StickX)
|
|
|
|
if targetYawVel > 0 then
|
|
if m.AngleVel.Y < 0 then
|
|
m.AngleVel += Vector3int16.new(0, 0x40, 0)
|
|
|
|
if m.AngleVel.Y > 0x10 then
|
|
m.AngleVel = Util.SetY(m.AngleVel, 0x10)
|
|
end
|
|
else
|
|
local velY = Util.ApproachInt(m.AngleVel.Y, targetYawVel, 0x10, 0x20)
|
|
m.AngleVel = Util.SetY(m.AngleVel, velY)
|
|
end
|
|
elseif targetYawVel < 0 then
|
|
if m.AngleVel.Y > 0 then
|
|
m.AngleVel -= Vector3int16.new(0, 0x40, 0)
|
|
|
|
if m.AngleVel.Y < -0x10 then
|
|
m.AngleVel = Util.SetY(m.AngleVel, -0x10)
|
|
end
|
|
else
|
|
local velY = Util.ApproachInt(m.AngleVel.Y, targetYawVel, 0x20, 0x10)
|
|
m.AngleVel = Util.SetY(m.AngleVel, velY)
|
|
end
|
|
else
|
|
local velY = Util.ApproachInt(m.AngleVel.Y, 0, 0x40, 0x40)
|
|
m.AngleVel = Util.SetY(m.AngleVel, velY)
|
|
end
|
|
|
|
m.FaceAngle += Vector3int16.new(0, m.AngleVel.Y, 0)
|
|
m.FaceAngle = Util.SetZ(m.FaceAngle, -m.AngleVel.Y * 8)
|
|
end
|
|
|
|
local function updateSwimmingPitch(m: Mario)
|
|
local targetPitch = -Util.SignedShort(252 * m.Controller.StickY)
|
|
|
|
-- stylua: ignore
|
|
local pitchVel = if m.FaceAngle.X < 0
|
|
then 0x100
|
|
else 0x200
|
|
|
|
if m.FaceAngle.X < targetPitch then
|
|
m.FaceAngle += Vector3int16.new(pitchVel, 0, 0)
|
|
|
|
if m.FaceAngle.X > targetPitch then
|
|
m.FaceAngle = Util.SetX(m.FaceAngle, targetPitch)
|
|
end
|
|
elseif m.FaceAngle.X > targetPitch then
|
|
m.FaceAngle -= Vector3int16.new(pitchVel, 0, 0)
|
|
|
|
if m.FaceAngle.X < targetPitch then
|
|
m.FaceAngle = Util.SetX(m.FaceAngle, targetPitch)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function commonIdleStep(m: Mario, anim: Animation, maybeAccel: number?)
|
|
local accel = maybeAccel or 0
|
|
local bodyState = m.BodyState
|
|
local headAngleX = bodyState.HeadAngle.X
|
|
|
|
updateSwimmingYaw(m)
|
|
updateSwimmingPitch(m)
|
|
updateSwimmingSpeed(m)
|
|
performWaterStep(m)
|
|
updateWaterPitch(m)
|
|
|
|
if m.FaceAngle.X > 0 then
|
|
headAngleX = Util.ApproachInt(headAngleX, m.FaceAngle.X / 2, 0x80, 0x200)
|
|
else
|
|
headAngleX = Util.ApproachInt(headAngleX, 0, 0x200, 0x200)
|
|
end
|
|
|
|
if accel == 0 then
|
|
m:SetAnimation(anim)
|
|
else
|
|
m:SetAnimationWithAccel(anim, accel)
|
|
end
|
|
|
|
setSwimmingAtSurfaceParticles(m, ParticleFlags.IDLE_WATER_WAVE)
|
|
end
|
|
|
|
local function resetBobVariables(m: Mario)
|
|
sBobTimer = 0
|
|
sBobIncrement = 0x800
|
|
sBobHeight = m.FaceAngle.X / 256 + 20
|
|
end
|
|
|
|
local function surfaceSwimBob(m: Mario)
|
|
if sBobIncrement ~= 0 and m.Position.Y > m.WaterLevel - 85 and m.FaceAngle.Y >= 0 then
|
|
sBobTimer += sBobIncrement
|
|
|
|
if sBobTimer >= 0 then
|
|
m.GfxPos += Vector3.new(0, sBobHeight * Util.Sins(sBobTimer), 0)
|
|
return
|
|
end
|
|
end
|
|
|
|
sBobIncrement = 0
|
|
end
|
|
|
|
local function commonSwimmingStep(m: Mario, swimStrength: number)
|
|
local waterStep
|
|
updateSwimmingYaw(m)
|
|
updateSwimmingPitch(m)
|
|
updateSwimmingSpeed(m, swimStrength / 10)
|
|
|
|
-- do water step
|
|
waterStep = performWaterStep(m)
|
|
|
|
if waterStep == WaterStep.HIT_FLOOR then
|
|
local floorPitch = -m:FindFloorSlope(-0x8000)
|
|
|
|
if m.FaceAngle.X < floorPitch then
|
|
m.FaceAngle = Util.SetX(m.FaceAngle, floorPitch)
|
|
end
|
|
elseif waterStep == WaterStep.HIT_CEILING then
|
|
if m.FaceAngle.Y > -0x3000 then
|
|
m.FaceAngle -= Vector3int16.new(0, 0x100, 0)
|
|
end
|
|
elseif waterStep == WaterStep.HIT_WALL then
|
|
if m.Controller.StickY == 0 then
|
|
if m.FaceAngle.X > 0 then
|
|
m.FaceAngle += Vector3int16.new(0x200, 0, 0)
|
|
|
|
if m.FaceAngle.X > 0x3F00 then
|
|
m.FaceAngle = Util.SetX(m.FaceAngle, 0x3F00)
|
|
end
|
|
else
|
|
m.FaceAngle -= Vector3int16.new(0x200, 0, 0)
|
|
|
|
if m.FaceAngle.X < -0x3F00 then
|
|
m.FaceAngle = Util.SetX(m.FaceAngle, -0x3F00)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local headAngle = m.BodyState.HeadAngle
|
|
updateWaterPitch(m)
|
|
|
|
local angleX = Util.ApproachInt(headAngle.X, 0, 0x200, 0x200)
|
|
m.BodyState.HeadAngle = Util.SetX(headAngle, angleX)
|
|
|
|
surfaceSwimBob(m)
|
|
setSwimmingAtSurfaceParticles(m, ParticleFlags.WAVE_TRAIL)
|
|
end
|
|
|
|
local function playSwimmingNoise(m: Mario)
|
|
local animFrame = m.AnimFrame
|
|
|
|
if animFrame == 0 or animFrame == 12 then
|
|
m:PlaySound(Sounds.ACTION_SWIM_KICK)
|
|
end
|
|
end
|
|
|
|
local function checkWaterJump(m: Mario)
|
|
local probe = Util.SignedInt(m.Position.Y + 1.5)
|
|
|
|
if m.Input:Has(InputFlags.A_PRESSED) then
|
|
if probe >= m.WaterLevel - 80 and m.FaceAngle.X >= 0 and m.Controller.StickY < -60 then
|
|
m.AngleVel = Vector3int16.new()
|
|
m.Velocity = Util.SetY(m.Velocity, 62)
|
|
|
|
return m:SetAction(Action.WATER_JUMP)
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
local function playMetalWaterJumpingSound(m: Mario, landing: boolean)
|
|
if not m.Flags:Has(MarioFlags.ACTION_SOUND_PLAYED) then
|
|
m.ParticleFlags:Add(ParticleFlags.MIST_CIRCLE)
|
|
end
|
|
|
|
m:PlaySoundIfNoFlag(
|
|
landing and Sounds.ACTION_METAL_LAND_WATER or Sounds.ACTION_METAL_JUMP_WATER,
|
|
MarioFlags.ACTION_SOUND_PLAYED
|
|
)
|
|
end
|
|
|
|
local function playMetalWaterWalkingSound(m: Mario)
|
|
if m:IsAnimPastFrame(10) or m:IsAnimPastFrame(49) then
|
|
m:PlaySound(Sounds.ACTION_METAL_STEP_WATER)
|
|
m.ParticleFlags:Add(ParticleFlags.DUST)
|
|
end
|
|
end
|
|
|
|
local function updateMetalWaterWalkingSpeed(m: Mario)
|
|
local val = m.IntendedMag / 1.5
|
|
local floor = m.Floor
|
|
|
|
if m.ForwardVel <= 0 then
|
|
m.ForwardVel += 1.1
|
|
elseif m.ForwardVel <= val then
|
|
m.ForwardVel += 1.1 - m.ForwardVel / 43
|
|
elseif floor and floor.Normal.Y >= 0.95 then
|
|
m.ForwardVel -= 1
|
|
end
|
|
|
|
if m.ForwardVel > 32 then
|
|
m.ForwardVel = 32
|
|
end
|
|
|
|
local faceY = m.IntendedYaw - Util.ApproachInt(Util.SignedShort(m.IntendedYaw - m.FaceAngle.Y), 0, 0x800, 0x800)
|
|
m.FaceAngle = Util.SetY(m.FaceAngle, faceY)
|
|
|
|
m.SlideVelX = m.ForwardVel * Util.Sins(faceY)
|
|
m.SlideVelZ = m.ForwardVel * Util.Coss(faceY)
|
|
|
|
m.Velocity = Vector3.new(m.SlideVelX, 0, m.SlideVelZ)
|
|
end
|
|
|
|
local function updateMetalWaterJumpSpeed(m: Mario)
|
|
local waterSurface = m.WaterLevel - 100
|
|
|
|
if m.Velocity.Y > 0 and m.Position.Y > waterSurface then
|
|
return true
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.NONZERO_ANALOG) then
|
|
local intendedDYaw = Util.SignedShort(m.IntendedYaw - m.FaceAngle.Y)
|
|
m.ForwardVel += 0.8 * Util.Coss(intendedDYaw)
|
|
m.FaceAngle += Vector3int16.new(0, 0x200 * Util.Sins(intendedDYaw), 0)
|
|
else
|
|
m.ForwardVel = Util.ApproachFloat(m.ForwardVel, 0, 0.25, 0.25)
|
|
end
|
|
|
|
if m.ForwardVel > 16 then
|
|
m.ForwardVel -= 1
|
|
end
|
|
|
|
if m.ForwardVel < 0 then
|
|
m.ForwardVel += 2
|
|
end
|
|
|
|
local velY = m.Velocity.Y
|
|
local velX = m.ForwardVel * Util.Sins(m.FaceAngle.Y)
|
|
local velZ = m.ForwardVel * Util.Coss(m.FaceAngle.Y)
|
|
|
|
m.SlideVelX = velX
|
|
m.SlideVelZ = velZ
|
|
m.Velocity = Vector3.new(velX, velY, velZ)
|
|
|
|
return false
|
|
end
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
local DEF_ACTION: (number, (Mario) -> boolean) -> () = System.RegisterAction
|
|
|
|
DEF_ACTION(Action.WATER_IDLE, function(m: Mario)
|
|
local val = 0x10000
|
|
|
|
if m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.METAL_WATER_FALLING, 1)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.B_PRESSED) then
|
|
return m:SetAction(Action.WATER_PUNCH)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.A_PRESSED) then
|
|
return m:SetAction(Action.BREASTSTROKE)
|
|
end
|
|
|
|
if m.FaceAngle.X < -0x1000 then
|
|
val = 0x30000
|
|
end
|
|
|
|
commonIdleStep(m, Animations.WATER_IDLE, val)
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.WATER_ACTION_END, function(m: Mario)
|
|
if m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.METAL_WATER_FALLING, 1)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.B_PRESSED) then
|
|
return m:SetAction(Action.WATER_PUNCH)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.A_PRESSED) then
|
|
return m:SetAction(Action.BREASTSTROKE)
|
|
end
|
|
|
|
commonIdleStep(m, Animations.WATER_ACTION_END)
|
|
|
|
if m:IsAnimAtEnd() then
|
|
m:SetAction(Action.WATER_IDLE)
|
|
end
|
|
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.BREASTSTROKE, function(m: Mario)
|
|
if m.ActionArg == 0 then
|
|
sSwimStrength = MIN_SWIM_STRENGTH
|
|
end
|
|
|
|
if m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.METAL_WATER_FALLING, 1)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.B_PRESSED) then
|
|
return m:SetAction(Action.WATER_PUNCH)
|
|
end
|
|
|
|
m.ActionTimer += 1
|
|
|
|
if m.ActionTimer == 14 then
|
|
return m:SetAction(Action.FLUTTER_KICK)
|
|
end
|
|
|
|
if checkWaterJump(m) then
|
|
return true
|
|
end
|
|
|
|
if m.ActionTimer < 6 then
|
|
m.ForwardVel += 0.5
|
|
end
|
|
|
|
if m.ActionTimer >= 9 then
|
|
m.ForwardVel += 1.5
|
|
end
|
|
|
|
if m.ActionTimer >= 2 then
|
|
if m.ActionTimer < 6 and m.Input:Has(InputFlags.A_PRESSED) then
|
|
m.ActionState = 1
|
|
end
|
|
|
|
if m.ActionTimer == 9 and m.ActionState == 1 then
|
|
m:SetAnimToFrame(0)
|
|
m.ActionState = 0
|
|
m.ActionTimer = 1
|
|
sSwimStrength = MIN_SWIM_STRENGTH
|
|
end
|
|
end
|
|
|
|
if m.ActionTimer == 1 then
|
|
m:PlaySound(sSwimStrength == MIN_SWIM_STRENGTH and Sounds.ACTION_SWIM or Sounds.ACTION_SWIM_FAST)
|
|
resetBobVariables(m)
|
|
end
|
|
|
|
m:SetAnimation(Animations.SWIM_PART1)
|
|
commonSwimmingStep(m, sSwimStrength)
|
|
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.SWIMMING_END, function(m: Mario)
|
|
if m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.METAL_WATER_FALLING, 1)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.B_PRESSED) then
|
|
return m:SetAction(Action.WATER_PUNCH)
|
|
end
|
|
|
|
if m.ActionTimer >= 15 then
|
|
return m:SetAction(Action.WATER_ACTION_END)
|
|
end
|
|
|
|
if checkWaterJump(m) then
|
|
return true
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.A_DOWN) and m.ActionTimer >= 7 then
|
|
if m.ActionTimer == 7 and sSwimStrength < 280 then
|
|
sSwimStrength += 10
|
|
end
|
|
|
|
return m:SetAction(Action.BREASTSTROKE, 1)
|
|
end
|
|
|
|
if m.ActionTimer >= 7 then
|
|
sSwimStrength = MIN_SWIM_STRENGTH
|
|
end
|
|
|
|
m.ActionTimer += 1
|
|
m.ForwardVel -= 0.25
|
|
|
|
m:SetAnimation(Animations.SWIM_PART2)
|
|
commonSwimmingStep(m, sSwimStrength)
|
|
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.FLUTTER_KICK, function(m: Mario)
|
|
if m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.METAL_WATER_FALLING, 1)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.B_PRESSED) then
|
|
return m:SetAction(Action.WATER_PUNCH)
|
|
end
|
|
|
|
if not m.Input:Has(InputFlags.A_DOWN) then
|
|
if m.ActionTimer == 0 and sSwimStrength < 280 then
|
|
sSwimStrength += 10
|
|
end
|
|
|
|
return m:SetAction(Action.SWIMMING_END)
|
|
end
|
|
|
|
m.ForwardVel = Util.ApproachFloat(m.ForwardVel, 12, 0.1, 0.15)
|
|
m.ActionTimer = 1
|
|
sSwimStrength = MIN_SWIM_STRENGTH
|
|
|
|
if m.ForwardVel < 14 then
|
|
playSwimmingNoise(m)
|
|
m:SetAnimation(Animations.FLUTTERKICK)
|
|
end
|
|
|
|
commonSwimmingStep(m, sSwimStrength)
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.WATER_PUNCH, function(m: Mario)
|
|
if m.ForwardVel < 7 then
|
|
m.ForwardVel += 1
|
|
end
|
|
|
|
updateSwimmingYaw(m)
|
|
updateSwimmingPitch(m)
|
|
updateSwimmingSpeed(m)
|
|
performWaterStep(m)
|
|
updateWaterPitch(m)
|
|
|
|
local headAngle = m.BodyState.HeadAngle
|
|
local angleX = Util.ApproachInt(headAngle.X, 0, 0x200, 0x200)
|
|
|
|
m.BodyState.HeadAngle = Util.SetX(headAngle, angleX)
|
|
m:PlaySoundIfNoFlag(Sounds.ACTION_SWIM, MarioFlags.ACTION_SOUND_PLAYED)
|
|
|
|
if m.ActionState == 0 then
|
|
m:SetAnimation(Animations.WATER_GRAB_OBJ_PART1)
|
|
|
|
if m:IsAnimAtEnd() then
|
|
m.ActionState = 1
|
|
end
|
|
elseif m.ActionState == 1 then
|
|
m:SetAnimation(Animations.WATER_GRAB_OBJ_PART2)
|
|
|
|
if m:IsAnimAtEnd() then
|
|
m:SetAction(Action.WATER_ACTION_END)
|
|
end
|
|
end
|
|
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.WATER_PLUNGE, function(m: Mario)
|
|
local stepResult
|
|
local endVSpeed = swimmingNearSurface(m) and 0 or -5
|
|
|
|
local hasMetalCap = m.Flags:Has(MarioFlags.METAL_CAP)
|
|
local isDiving = m.PrevAction:Has(ActionFlags.DIVING) or m.Input:Has(InputFlags.A_DOWN)
|
|
|
|
m.ActionTimer += 1
|
|
stationarySlowDown(m)
|
|
stepResult = performWaterStep(m)
|
|
|
|
if m.ActionState == 0 then
|
|
m:PlaySound(Sounds.ACTION_WATER_ENTER)
|
|
|
|
if m.PeakHeight - m.Position.Y > 1150 then
|
|
m:PlaySound(Sounds.MARIO_HAHA)
|
|
end
|
|
|
|
m.ParticleFlags:Add(ParticleFlags.WATER_SPLASH)
|
|
m.ActionState = 1
|
|
end
|
|
|
|
if stepResult == WaterStep.HIT_FLOOR or m.Velocity.Y >= endVSpeed or m.ActionTimer > 20 then
|
|
if hasMetalCap then
|
|
m:SetAction(Action.METAL_WATER_FALLING)
|
|
elseif isDiving then
|
|
m:SetAction(Action.FLUTTER_KICK)
|
|
else
|
|
m:SetAction(Action.WATER_ACTION_END)
|
|
end
|
|
|
|
sBobIncrement = 0
|
|
end
|
|
|
|
if hasMetalCap then
|
|
m:SetAnimation(Animations.GENERAL_FALL)
|
|
elseif isDiving then
|
|
m:SetAnimation(Animations.FLUTTERKICK)
|
|
else
|
|
m:SetAnimation(Animations.WATER_ACTION_END)
|
|
end
|
|
|
|
m.Flags:Add(ParticleFlags.PLUNGE_BUBBLE)
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.METAL_WATER_STANDING, function(m: Mario)
|
|
if not m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.WATER_IDLE)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.A_PRESSED) then
|
|
return m:SetAction(Action.METAL_WATER_JUMP)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.NONZERO_ANALOG) then
|
|
return m:SetAction(Action.METAL_WATER_WALKING)
|
|
end
|
|
|
|
if m.ActionState == 0 then
|
|
m:SetAnimation(Animations.IDLE_HEAD_LEFT)
|
|
elseif m.ActionState == 1 then
|
|
m:SetAnimation(Animations.IDLE_HEAD_RIGHT)
|
|
elseif m.ActionState == 2 then
|
|
m:SetAnimation(Animations.IDLE_HEAD_CENTER)
|
|
end
|
|
|
|
if m:IsAnimAtEnd() then
|
|
m.ActionState += 1
|
|
|
|
if m.ActionState == 3 then
|
|
m.ActionState = 0
|
|
end
|
|
end
|
|
|
|
m:StopAndSetHeightToFloor()
|
|
|
|
if m.Position.Y >= m.WaterLevel - 150 then
|
|
m.ParticleFlags:Add(ParticleFlags.IDLE_WATER_WAVE)
|
|
end
|
|
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.METAL_WATER_WALKING, function(m: Mario)
|
|
if not m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.WATER_IDLE)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.A_PRESSED) then
|
|
return m:SetAction(Action.METAL_WATER_JUMP)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.NO_MOVEMENT) then
|
|
return m:SetAction(Action.METAL_WATER_STANDING)
|
|
end
|
|
|
|
local accel = Util.SignedInt(m.ForwardVel / 4 * 0x10000)
|
|
local groundStep
|
|
|
|
if accel < 0x1000 then
|
|
accel = 0x1000
|
|
end
|
|
|
|
m:SetAnimationWithAccel(Animations.WALKING, accel)
|
|
playMetalWaterWalkingSound(m)
|
|
updateMetalWaterWalkingSpeed(m)
|
|
groundStep = m:PerformGroundStep()
|
|
|
|
if groundStep == GroundStep.LEFT_GROUND then
|
|
m:SetAction(Action.METAL_WATER_FALLING, 1)
|
|
elseif groundStep == GroundStep.HIT_WALL then
|
|
m.ForwardVel = 0
|
|
end
|
|
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.METAL_WATER_JUMP, function(m: Mario)
|
|
local airStep
|
|
|
|
if not m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.WATER_IDLE)
|
|
end
|
|
|
|
if updateMetalWaterJumpSpeed(m) then
|
|
return m:SetAction(Action.WATER_JUMP, 1)
|
|
end
|
|
|
|
playMetalWaterJumpingSound(m, false)
|
|
m:SetAnimation(Animations.SINGLE_JUMP)
|
|
airStep = m:PerformAirStep()
|
|
|
|
if airStep == AirStep.LANDED then
|
|
m:SetAction(Action.METAL_WATER_JUMP_LAND)
|
|
elseif airStep == AirStep.HIT_WALL then
|
|
m.ForwardVel = 0
|
|
end
|
|
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.METAL_WATER_FALLING, function(m: Mario)
|
|
if not m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.WATER_IDLE)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.NONZERO_ANALOG) then
|
|
m.FaceAngle += Vector3int16.new(0, 0x400 * Util.Sins(m.IntendedYaw - m.FaceAngle.Y), 0)
|
|
end
|
|
|
|
m:SetAnimation(m.ActionArg == 0 and Animations.GENERAL_FALL or Animations.FALL_FROM_WATER)
|
|
stationarySlowDown(m)
|
|
|
|
if bit32.btest(performWaterStep(m), WaterStep.HIT_FLOOR) then
|
|
m:SetAction(Action.METAL_WATER_FALL_LAND)
|
|
end
|
|
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.METAL_WATER_JUMP_LAND, function(m: Mario)
|
|
playMetalWaterJumpingSound(m, true)
|
|
|
|
if not m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.WATER_IDLE)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.NONZERO_ANALOG) then
|
|
return m:SetAction(Action.METAL_WATER_WALKING)
|
|
end
|
|
|
|
m:StopAndSetHeightToFloor()
|
|
m:SetAnimation(Animations.LAND_FROM_SINGLE_JUMP)
|
|
|
|
if m:IsAnimAtEnd() then
|
|
return m:SetAction(Action.METAL_WATER_STANDING)
|
|
end
|
|
|
|
return false
|
|
end)
|
|
|
|
DEF_ACTION(Action.METAL_WATER_FALL_LAND, function(m: Mario)
|
|
playMetalWaterJumpingSound(m, true)
|
|
|
|
if not m.Flags:Has(MarioFlags.METAL_CAP) then
|
|
return m:SetAction(Action.WATER_IDLE)
|
|
end
|
|
|
|
if m.Input:Has(InputFlags.NONZERO_ANALOG) then
|
|
return m:SetAction(Action.METAL_WATER_WALKING)
|
|
end
|
|
|
|
m:StopAndSetHeightToFloor()
|
|
m:SetAnimation(Animations.GENERAL_LAND)
|
|
|
|
if m:IsAnimAtEnd() then
|
|
return m:SetAction(Action.METAL_WATER_STANDING)
|
|
end
|
|
|
|
return false
|
|
end)
|