366 lines
11 KiB
Plaintext
366 lines
11 KiB
Plaintext
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
|
|
<External>null</External>
|
|
<External>nil</External>
|
|
<Item class="Script" referent="RBXf11428b7b777457c8d872c64386aa070">
|
|
<Properties>
|
|
<bool name="Disabled">false</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">Sound</string>
|
|
<string name="ScriptGuid"></string>
|
|
<ProtectedString name="Source"><![CDATA[--[[
|
|
Author: @spotco
|
|
This script creates sounds which are placed under the character head.
|
|
These sounds are used by the "LocalSound" script.
|
|
|
|
To modify this script, copy it to your "StarterPlayer/StarterCharacterScripts" folder keeping the same script name ("Sound").
|
|
The default Sound script loaded for every character will then be replaced with your copy of the script.
|
|
]]--
|
|
|
|
function CreateNewSound(name, id, looped, pitch, parent)
|
|
local sound = Instance.new("Sound")
|
|
sound.SoundId = id
|
|
sound.Name = name
|
|
sound.archivable = false
|
|
sound.Parent = parent
|
|
sound.Pitch = pitch
|
|
sound.Looped = looped
|
|
|
|
sound.MinDistance = 5
|
|
sound.MaxDistance = 150
|
|
sound.Volume = 0.65
|
|
|
|
return sound
|
|
end
|
|
|
|
local head = script.Parent:FindFirstChild("Head")
|
|
if head == nil then
|
|
error("Sound script parent has no child Head.")
|
|
return
|
|
end
|
|
|
|
|
|
CreateNewSound("GettingUp", "rbxasset://sounds/action_get_up.mp3", false, 1, head)
|
|
CreateNewSound("Died", "rbxasset://sounds/uuhhh.mp3", false, 1, head)
|
|
CreateNewSound("FreeFalling", "rbxasset://sounds/action_falling.mp3", true, 1, head)
|
|
CreateNewSound("Jumping", "rbxasset://sounds/action_jump.mp3", false, 1, head)
|
|
CreateNewSound("Landing", "rbxasset://sounds/action_jump_land.mp3", false, 1, head)
|
|
CreateNewSound("Splash", "rbxasset://sounds/impact_water.mp3", false, 1, head)
|
|
CreateNewSound("Running", "rbxasset://sounds/action_footsteps_plastic.mp3", true, 1.85, head)
|
|
CreateNewSound("Swimming", "rbxasset://sounds/action_swim.mp3", true, 1.6, head)
|
|
CreateNewSound("Climbing", "rbxasset://sounds/action_footsteps_plastic.mp3", true, 1, head)]]></ProtectedString>
|
|
</Properties>
|
|
<Item class="LocalScript" referent="RBXcf674087fdd94888aaa89ff050d72c40">
|
|
<Properties>
|
|
<bool name="Disabled">false</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">LocalSound</string>
|
|
<string name="ScriptGuid"></string>
|
|
<ProtectedString name="Source"><![CDATA[--[[
|
|
Author: @spotco
|
|
This script runs locally for the player of the given humanoid.
|
|
This script triggers humanoid sound play/pause actions locally.
|
|
|
|
The Playing/TimePosition properties of Sound objects bypass FilteringEnabled, so this triggers the sound
|
|
immediately for the player and is replicated to all other players.
|
|
|
|
This script is optimized to reduce network traffic through minimizing the amount of property replication.
|
|
]]--
|
|
|
|
--All sounds are referenced by this ID
|
|
local SFX = {
|
|
Died = 0;
|
|
Running = 1;
|
|
Swimming = 2;
|
|
Climbing = 3,
|
|
Jumping = 4;
|
|
GettingUp = 5;
|
|
FreeFalling = 6;
|
|
FallingDown = 7;
|
|
Landing = 8;
|
|
Splash = 9;
|
|
}
|
|
|
|
local Humanoid = nil
|
|
local Head = nil
|
|
|
|
--SFX ID to Sound object
|
|
local Sounds = {}
|
|
|
|
do
|
|
local Figure = script.Parent.Parent
|
|
Head = Figure:WaitForChild("Head")
|
|
while not Humanoid do
|
|
for _,NewHumanoid in pairs(Figure:GetChildren()) do
|
|
if NewHumanoid:IsA("Humanoid") then
|
|
Humanoid = NewHumanoid
|
|
break
|
|
end
|
|
end
|
|
Figure.ChildAdded:wait()
|
|
end
|
|
|
|
Sounds[SFX.Died] = Head:WaitForChild("Died")
|
|
Sounds[SFX.Running] = Head:WaitForChild("Running")
|
|
Sounds[SFX.Swimming] = Head:WaitForChild("Swimming")
|
|
Sounds[SFX.Climbing] = Head:WaitForChild("Climbing")
|
|
Sounds[SFX.Jumping] = Head:WaitForChild("Jumping")
|
|
Sounds[SFX.GettingUp] = Head:WaitForChild("GettingUp")
|
|
Sounds[SFX.FreeFalling] = Head:WaitForChild("FreeFalling")
|
|
Sounds[SFX.Landing] = Head:WaitForChild("Landing")
|
|
Sounds[SFX.Splash] = Head:WaitForChild("Splash")
|
|
end
|
|
|
|
local Util
|
|
Util = {
|
|
|
|
--Define linear relationship between (pt1x,pt2x) and (pt2x,pt2y). Evaluate this at x.
|
|
YForLineGivenXAndTwoPts = function(x,pt1x,pt1y,pt2x,pt2y)
|
|
--(y - y1)/(x - x1) = m
|
|
local m = (pt1y - pt2y) / (pt1x - pt2x)
|
|
--float b = pt1.y - m * pt1.x;
|
|
local b = (pt1y - m * pt1x)
|
|
return m * x + b
|
|
end;
|
|
|
|
--Clamps the value of "val" between the "min" and "max"
|
|
Clamp = function(val,min,max)
|
|
return math.min(max,math.max(min,val))
|
|
end;
|
|
|
|
--Gets the horizontal (x,z) velocity magnitude of the given part
|
|
HorizontalSpeed = function(Head)
|
|
local hVel = Head.Velocity + Vector3.new(0,-Head.Velocity.Y,0)
|
|
return hVel.magnitude
|
|
end;
|
|
|
|
--Gets the vertical (y) velocity magnitude of the given part
|
|
VerticalSpeed = function(Head)
|
|
return math.abs(Head.Velocity.Y)
|
|
end;
|
|
|
|
--Setting Playing/TimePosition values directly result in less network traffic than Play/Pause/Resume/Stop
|
|
--If these properties are enabled, use them.
|
|
Play = function(sound)
|
|
if sound.TimePosition ~= 0 then
|
|
sound.TimePosition = 0
|
|
end
|
|
if not sound.IsPlaying then
|
|
sound.Playing = true
|
|
end
|
|
end;
|
|
Pause = function(sound)
|
|
if sound.IsPlaying then
|
|
sound.Playing = false
|
|
end
|
|
end;
|
|
Resume = function(sound)
|
|
if not sound.IsPlaying then
|
|
sound.Playing = true
|
|
end
|
|
end;
|
|
Stop = function(sound)
|
|
if sound.IsPlaying then
|
|
sound.Playing = false
|
|
end
|
|
if sound.TimePosition ~= 0 then
|
|
sound.TimePosition = 0
|
|
end
|
|
end;
|
|
}
|
|
|
|
do
|
|
-- List of all active Looped sounds
|
|
local playingLoopedSounds = {}
|
|
|
|
-- Last seen Enum.HumanoidStateType
|
|
local activeState = nil
|
|
|
|
-- Verify and set that "sound" is in "playingLoopedSounds".
|
|
function setSoundInPlayingLoopedSounds(sound)
|
|
for i=1, #playingLoopedSounds do
|
|
if playingLoopedSounds[i] == sound then
|
|
return
|
|
end
|
|
end
|
|
table.insert(playingLoopedSounds,sound)
|
|
end
|
|
|
|
-- Stop all active looped sounds except parameter "except". If "except" is not passed, all looped sounds will be stopped.
|
|
function stopPlayingLoopedSoundsExcept(except)
|
|
for i=#playingLoopedSounds,1,-1 do
|
|
if playingLoopedSounds[i] ~= except then
|
|
Util.Pause(playingLoopedSounds[i])
|
|
table.remove(playingLoopedSounds,i)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Table of Enum.HumanoidStateType to handling function
|
|
local stateUpdateHandler = {
|
|
[Enum.HumanoidStateType.Dead] = function()
|
|
stopPlayingLoopedSoundsExcept()
|
|
local sound = Sounds[SFX.Died]
|
|
Util.Play(sound)
|
|
end;
|
|
|
|
[Enum.HumanoidStateType.RunningNoPhysics] = function()
|
|
stateUpdated(Enum.HumanoidStateType.Running)
|
|
end;
|
|
|
|
[Enum.HumanoidStateType.Running] = function()
|
|
local sound = Sounds[SFX.Running]
|
|
stopPlayingLoopedSoundsExcept(sound)
|
|
|
|
if Util.HorizontalSpeed(Head) > 0.5 then
|
|
Util.Resume(sound)
|
|
setSoundInPlayingLoopedSounds(sound)
|
|
else
|
|
stopPlayingLoopedSoundsExcept()
|
|
end
|
|
end;
|
|
|
|
[Enum.HumanoidStateType.Swimming] = function()
|
|
if activeState ~= Enum.HumanoidStateType.Swimming and Util.VerticalSpeed(Head) > 0.1 then
|
|
local splashSound = Sounds[SFX.Splash]
|
|
splashSound.Volume = Util.Clamp(
|
|
Util.YForLineGivenXAndTwoPts(
|
|
Util.VerticalSpeed(Head),
|
|
100, 0.28,
|
|
350, 1),
|
|
0,1)
|
|
Util.Play(splashSound)
|
|
end
|
|
|
|
do
|
|
local sound = Sounds[SFX.Swimming]
|
|
stopPlayingLoopedSoundsExcept(sound)
|
|
Util.Resume(sound)
|
|
setSoundInPlayingLoopedSounds(sound)
|
|
end
|
|
end;
|
|
|
|
[Enum.HumanoidStateType.Climbing] = function()
|
|
local sound = Sounds[SFX.Climbing]
|
|
if Util.VerticalSpeed(Head) > 0.1 then
|
|
Util.Resume(sound)
|
|
stopPlayingLoopedSoundsExcept(sound)
|
|
else
|
|
stopPlayingLoopedSoundsExcept()
|
|
end
|
|
setSoundInPlayingLoopedSounds(sound)
|
|
end;
|
|
|
|
[Enum.HumanoidStateType.Jumping] = function()
|
|
if activeState == Enum.HumanoidStateType.Jumping then
|
|
return
|
|
end
|
|
stopPlayingLoopedSoundsExcept()
|
|
local sound = Sounds[SFX.Jumping]
|
|
Util.Play(sound)
|
|
end;
|
|
|
|
[Enum.HumanoidStateType.GettingUp] = function()
|
|
stopPlayingLoopedSoundsExcept()
|
|
local sound = Sounds[SFX.GettingUp]
|
|
Util.Play(sound)
|
|
end;
|
|
|
|
[Enum.HumanoidStateType.Freefall] = function()
|
|
if activeState == Enum.HumanoidStateType.Freefall then
|
|
return
|
|
end
|
|
local sound = Sounds[SFX.FreeFalling]
|
|
sound.Volume = 0
|
|
stopPlayingLoopedSoundsExcept()
|
|
end;
|
|
|
|
[Enum.HumanoidStateType.FallingDown] = function()
|
|
stopPlayingLoopedSoundsExcept()
|
|
end;
|
|
|
|
[Enum.HumanoidStateType.Landed] = function()
|
|
stopPlayingLoopedSoundsExcept()
|
|
if Util.VerticalSpeed(Head) > 75 then
|
|
local landingSound = Sounds[SFX.Landing]
|
|
landingSound.Volume = Util.Clamp(
|
|
Util.YForLineGivenXAndTwoPts(
|
|
Util.VerticalSpeed(Head),
|
|
50, 0,
|
|
100, 1),
|
|
0,1)
|
|
Util.Play(landingSound)
|
|
end
|
|
end;
|
|
|
|
[Enum.HumanoidStateType.Seated] = function()
|
|
stopPlayingLoopedSoundsExcept()
|
|
end;
|
|
}
|
|
|
|
-- Handle state event fired or OnChange fired
|
|
function stateUpdated(state)
|
|
if stateUpdateHandler[state] ~= nil then
|
|
stateUpdateHandler[state]()
|
|
end
|
|
activeState = state
|
|
end
|
|
|
|
Humanoid.Died:connect( function() stateUpdated(Enum.HumanoidStateType.Dead) end)
|
|
Humanoid.Running:connect( function() stateUpdated(Enum.HumanoidStateType.Running) end)
|
|
Humanoid.Swimming:connect( function() stateUpdated(Enum.HumanoidStateType.Swimming) end)
|
|
Humanoid.Climbing:connect( function() stateUpdated(Enum.HumanoidStateType.Climbing) end)
|
|
Humanoid.Jumping:connect( function() stateUpdated(Enum.HumanoidStateType.Jumping) end)
|
|
Humanoid.GettingUp:connect( function() stateUpdated(Enum.HumanoidStateType.GettingUp) end)
|
|
Humanoid.FreeFalling:connect( function() stateUpdated(Enum.HumanoidStateType.Freefall) end)
|
|
Humanoid.FallingDown:connect( function() stateUpdated(Enum.HumanoidStateType.FallingDown) end)
|
|
|
|
-- required for proper handling of Landed event
|
|
Humanoid.StateChanged:connect(function(old, new)
|
|
stateUpdated(new)
|
|
end)
|
|
|
|
|
|
function onUpdate(stepDeltaSeconds, tickSpeedSeconds)
|
|
local stepScale = stepDeltaSeconds / tickSpeedSeconds
|
|
do
|
|
local sound = Sounds[SFX.FreeFalling]
|
|
if activeState == Enum.HumanoidStateType.Freefall then
|
|
if Head.Velocity.Y < 0 and Util.VerticalSpeed(Head) > 75 then
|
|
Util.Resume(sound)
|
|
|
|
--Volume takes 1.1 seconds to go from volume 0 to 1
|
|
local ANIMATION_LENGTH_SECONDS = 1.1
|
|
|
|
local normalizedIncrement = tickSpeedSeconds / ANIMATION_LENGTH_SECONDS
|
|
sound.Volume = Util.Clamp(sound.Volume + normalizedIncrement * stepScale, 0, 1)
|
|
else
|
|
sound.Volume = 0
|
|
end
|
|
else
|
|
Util.Pause(sound)
|
|
end
|
|
end
|
|
|
|
do
|
|
local sound = Sounds[SFX.Running]
|
|
if activeState == Enum.HumanoidStateType.Running then
|
|
if Util.HorizontalSpeed(Head) < 0.5 then
|
|
Util.Pause(sound)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local lastTick = tick()
|
|
local TICK_SPEED_SECONDS = 0.25
|
|
while true do
|
|
onUpdate(tick() - lastTick,TICK_SPEED_SECONDS)
|
|
lastTick = tick()
|
|
wait(TICK_SPEED_SECONDS)
|
|
end
|
|
end
|
|
]]></ProtectedString>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</roblox> |