SyntaxGameServer/RCCService2020/ExtraContent/scripts/PlayerScripts/StarterPlayerScripts_NewStr.../PlayerModule.module/ControlModule/ClickToMoveDisplay.lua

484 lines
16 KiB
Lua

local ClickToMoveDisplay = {}
local FAILURE_ANIMATION_ID = "rbxassetid://2874840706"
local TrailDotIcon = "rbxasset://textures/ui/traildot.png"
local EndWaypointIcon = "rbxasset://textures/ui/waypoint.png"
local WaypointsAlwaysOnTop = false
local WAYPOINT_INCLUDE_FACTOR = 2
local LAST_DOT_DISTANCE = 3
local WAYPOINT_BILLBOARD_SIZE = UDim2.new(0, 1.68 * 25, 0, 2 * 25)
local ENDWAYPOINT_SIZE_OFFSET_MIN = Vector2.new(0, 0.5)
local ENDWAYPOINT_SIZE_OFFSET_MAX = Vector2.new(0, 1)
local FAIL_WAYPOINT_SIZE_OFFSET_CENTER = Vector2.new(0, 0.5)
local FAIL_WAYPOINT_SIZE_OFFSET_LEFT = Vector2.new(0.1, 0.5)
local FAIL_WAYPOINT_SIZE_OFFSET_RIGHT = Vector2.new(-0.1, 0.5)
local FAILURE_TWEEN_LENGTH = 0.125
local FAILURE_TWEEN_COUNT = 4
local TWEEN_WAYPOINT_THRESHOLD = 5
local TRAIL_DOT_PARENT_NAME = "ClickToMoveDisplay"
local TrailDotSize = Vector2.new(1.5, 1.5)
local TRAIL_DOT_MIN_SCALE = 1
local TRAIL_DOT_MIN_DISTANCE = 10
local TRAIL_DOT_MAX_SCALE = 2.5
local TRAIL_DOT_MAX_DISTANCE = 100
local PlayersService = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local LocalPlayer = PlayersService.LocalPlayer
local function CreateWaypointTemplates()
local TrailDotTemplate = Instance.new("Part")
TrailDotTemplate.Size = Vector3.new(1, 1, 1)
TrailDotTemplate.Anchored = true
TrailDotTemplate.CanCollide = false
TrailDotTemplate.Name = "TrailDot"
TrailDotTemplate.Transparency = 1
local TrailDotImage = Instance.new("ImageHandleAdornment")
TrailDotImage.Name = "TrailDotImage"
TrailDotImage.Size = TrailDotSize
TrailDotImage.SizeRelativeOffset = Vector3.new(0, 0, -0.1)
TrailDotImage.AlwaysOnTop = WaypointsAlwaysOnTop
TrailDotImage.Image = TrailDotIcon
TrailDotImage.Adornee = TrailDotTemplate
TrailDotImage.Parent = TrailDotTemplate
local EndWaypointTemplate = Instance.new("Part")
EndWaypointTemplate.Size = Vector3.new(2, 2, 2)
EndWaypointTemplate.Anchored = true
EndWaypointTemplate.CanCollide = false
EndWaypointTemplate.Name = "EndWaypoint"
EndWaypointTemplate.Transparency = 1
local EndWaypointImage = Instance.new("ImageHandleAdornment")
EndWaypointImage.Name = "TrailDotImage"
EndWaypointImage.Size = TrailDotSize
EndWaypointImage.SizeRelativeOffset = Vector3.new(0, 0, -0.1)
EndWaypointImage.AlwaysOnTop = WaypointsAlwaysOnTop
EndWaypointImage.Image = TrailDotIcon
EndWaypointImage.Adornee = EndWaypointTemplate
EndWaypointImage.Parent = EndWaypointTemplate
local EndWaypointBillboard = Instance.new("BillboardGui")
EndWaypointBillboard.Name = "EndWaypointBillboard"
EndWaypointBillboard.Size = WAYPOINT_BILLBOARD_SIZE
EndWaypointBillboard.LightInfluence = 0
EndWaypointBillboard.SizeOffset = ENDWAYPOINT_SIZE_OFFSET_MIN
EndWaypointBillboard.AlwaysOnTop = true
EndWaypointBillboard.Adornee = EndWaypointTemplate
EndWaypointBillboard.Parent = EndWaypointTemplate
local EndWaypointImageLabel = Instance.new("ImageLabel")
EndWaypointImageLabel.Image = EndWaypointIcon
EndWaypointImageLabel.BackgroundTransparency = 1
EndWaypointImageLabel.Size = UDim2.new(1, 0, 1, 0)
EndWaypointImageLabel.Parent = EndWaypointBillboard
local FailureWaypointTemplate = Instance.new("Part")
FailureWaypointTemplate.Size = Vector3.new(2, 2, 2)
FailureWaypointTemplate.Anchored = true
FailureWaypointTemplate.CanCollide = false
FailureWaypointTemplate.Name = "FailureWaypoint"
FailureWaypointTemplate.Transparency = 1
local FailureWaypointImage = Instance.new("ImageHandleAdornment")
FailureWaypointImage.Name = "TrailDotImage"
FailureWaypointImage.Size = TrailDotSize
FailureWaypointImage.SizeRelativeOffset = Vector3.new(0, 0, -0.1)
FailureWaypointImage.AlwaysOnTop = WaypointsAlwaysOnTop
FailureWaypointImage.Image = TrailDotIcon
FailureWaypointImage.Adornee = FailureWaypointTemplate
FailureWaypointImage.Parent = FailureWaypointTemplate
local FailureWaypointBillboard = Instance.new("BillboardGui")
FailureWaypointBillboard.Name = "FailureWaypointBillboard"
FailureWaypointBillboard.Size = WAYPOINT_BILLBOARD_SIZE
FailureWaypointBillboard.LightInfluence = 0
FailureWaypointBillboard.SizeOffset = FAIL_WAYPOINT_SIZE_OFFSET_CENTER
FailureWaypointBillboard.AlwaysOnTop = true
FailureWaypointBillboard.Adornee = FailureWaypointTemplate
FailureWaypointBillboard.Parent = FailureWaypointTemplate
local FailureWaypointFrame = Instance.new("Frame")
FailureWaypointFrame.BackgroundTransparency = 1
FailureWaypointFrame.Size = UDim2.new(0, 0, 0, 0)
FailureWaypointFrame.Position = UDim2.new(0.5, 0, 1, 0)
FailureWaypointFrame.Parent = FailureWaypointBillboard
local FailureWaypointImageLabel = Instance.new("ImageLabel")
FailureWaypointImageLabel.Image = EndWaypointIcon
FailureWaypointImageLabel.BackgroundTransparency = 1
FailureWaypointImageLabel.Position = UDim2.new(
0, -WAYPOINT_BILLBOARD_SIZE.X.Offset/2, 0, -WAYPOINT_BILLBOARD_SIZE.Y.Offset
)
FailureWaypointImageLabel.Size = WAYPOINT_BILLBOARD_SIZE
FailureWaypointImageLabel.Parent = FailureWaypointFrame
return TrailDotTemplate, EndWaypointTemplate, FailureWaypointTemplate
end
local TrailDotTemplate, EndWaypointTemplate, FailureWaypointTemplate = CreateWaypointTemplates()
local function getTrailDotParent()
local camera = Workspace.CurrentCamera
local trailParent = camera:FindFirstChild(TRAIL_DOT_PARENT_NAME)
if not trailParent then
trailParent = Instance.new("Model")
trailParent.Name = TRAIL_DOT_PARENT_NAME
trailParent.Parent = camera
end
return trailParent
end
local function placePathWaypoint(waypointModel, position)
local ray = Ray.new(position + Vector3.new(0, 2.5, 0), Vector3.new(0, -10, 0))
local hitPart, hitPoint, hitNormal = Workspace:FindPartOnRayWithIgnoreList(
ray,
{ Workspace.CurrentCamera, LocalPlayer.Character }
)
if hitPart then
waypointModel.CFrame = CFrame.new(hitPoint, hitPoint + hitNormal)
waypointModel.Parent = getTrailDotParent()
end
end
local TrailDot = {}
TrailDot.__index = TrailDot
function TrailDot:Destroy()
self.DisplayModel:Destroy()
end
function TrailDot:NewDisplayModel(position)
local newDisplayModel = TrailDotTemplate:Clone()
placePathWaypoint(newDisplayModel, position)
return newDisplayModel
end
function TrailDot.new(position, closestWaypoint)
local self = setmetatable({}, TrailDot)
self.DisplayModel = self:NewDisplayModel(position)
self.ClosestWayPoint = closestWaypoint
return self
end
local EndWaypoint = {}
EndWaypoint.__index = EndWaypoint
function EndWaypoint:Destroy()
self.Destroyed = true
self.Tween:Cancel()
self.DisplayModel:Destroy()
end
function EndWaypoint:NewDisplayModel(position)
local newDisplayModel = EndWaypointTemplate:Clone()
placePathWaypoint(newDisplayModel, position)
return newDisplayModel
end
function EndWaypoint:CreateTween()
local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Sine, Enum.EasingDirection.Out, -1, true)
local tween = TweenService:Create(
self.DisplayModel.EndWaypointBillboard,
tweenInfo,
{ SizeOffset = ENDWAYPOINT_SIZE_OFFSET_MAX }
)
tween:Play()
return tween
end
function EndWaypoint:TweenInFrom(originalPosition)
local currentPositon = self.DisplayModel.Position
local studsOffset = originalPosition - currentPositon
self.DisplayModel.EndWaypointBillboard.StudsOffset = Vector3.new(0, studsOffset.Y, 0)
local tweenInfo = TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.Out)
local tween = TweenService:Create(
self.DisplayModel.EndWaypointBillboard,
tweenInfo,
{ StudsOffset = Vector3.new(0, 0, 0) }
)
tween:Play()
return tween
end
function EndWaypoint.new(position, closestWaypoint, originalPosition)
local self = setmetatable({}, EndWaypoint)
self.DisplayModel = self:NewDisplayModel(position)
self.Destroyed = false
if originalPosition and (originalPosition - position).magnitude > TWEEN_WAYPOINT_THRESHOLD then
self.Tween = self:TweenInFrom(originalPosition)
coroutine.wrap(function()
self.Tween.Completed:Wait()
if not self.Destroyed then
self.Tween = self:CreateTween()
end
end)()
else
self.Tween = self:CreateTween()
end
self.ClosestWayPoint = closestWaypoint
return self
end
local FailureWaypoint = {}
FailureWaypoint.__index = FailureWaypoint
function FailureWaypoint:Hide()
self.DisplayModel.Parent = nil
end
function FailureWaypoint:Destroy()
self.DisplayModel:Destroy()
end
function FailureWaypoint:NewDisplayModel(position)
local newDisplayModel = FailureWaypointTemplate:Clone()
placePathWaypoint(newDisplayModel, position)
local ray = Ray.new(position + Vector3.new(0, 2.5, 0), Vector3.new(0, -10, 0))
local hitPart, hitPoint, hitNormal = Workspace:FindPartOnRayWithIgnoreList(
ray, { Workspace.CurrentCamera, LocalPlayer.Character }
)
if hitPart then
newDisplayModel.CFrame = CFrame.new(hitPoint, hitPoint + hitNormal)
newDisplayModel.Parent = getTrailDotParent()
end
return newDisplayModel
end
function FailureWaypoint:RunFailureTween()
wait(FAILURE_TWEEN_LENGTH) -- Delay one tween length betfore starting tweening
-- Tween out from center
local tweenInfo = TweenInfo.new(FAILURE_TWEEN_LENGTH/2, Enum.EasingStyle.Sine, Enum.EasingDirection.Out)
local tweenLeft = TweenService:Create(self.DisplayModel.FailureWaypointBillboard, tweenInfo,
{ SizeOffset = FAIL_WAYPOINT_SIZE_OFFSET_LEFT })
tweenLeft:Play()
local tweenLeftRoation = TweenService:Create(self.DisplayModel.FailureWaypointBillboard.Frame, tweenInfo,
{ Rotation = 10 })
tweenLeftRoation:Play()
tweenLeft.Completed:wait()
-- Tween back and forth
tweenInfo = TweenInfo.new(FAILURE_TWEEN_LENGTH, Enum.EasingStyle.Sine, Enum.EasingDirection.Out,
FAILURE_TWEEN_COUNT - 1, true)
local tweenSideToSide = TweenService:Create(self.DisplayModel.FailureWaypointBillboard, tweenInfo,
{ SizeOffset = FAIL_WAYPOINT_SIZE_OFFSET_RIGHT})
tweenSideToSide:Play()
-- Tween flash dark and roate left and right
tweenInfo = TweenInfo.new(FAILURE_TWEEN_LENGTH, Enum.EasingStyle.Sine, Enum.EasingDirection.Out,
FAILURE_TWEEN_COUNT - 1, true)
local tweenFlash = TweenService:Create(self.DisplayModel.FailureWaypointBillboard.Frame.ImageLabel, tweenInfo,
{ ImageColor3 = Color3.new(0.75, 0.75, 0.75)})
tweenFlash:Play()
local tweenRotate = TweenService:Create(self.DisplayModel.FailureWaypointBillboard.Frame, tweenInfo,
{ Rotation = -10 })
tweenRotate:Play()
tweenSideToSide.Completed:wait()
-- Tween back to center
tweenInfo = TweenInfo.new(FAILURE_TWEEN_LENGTH/2, Enum.EasingStyle.Sine, Enum.EasingDirection.Out)
local tweenCenter = TweenService:Create(self.DisplayModel.FailureWaypointBillboard, tweenInfo,
{ SizeOffset = FAIL_WAYPOINT_SIZE_OFFSET_CENTER })
tweenCenter:Play()
local tweenRoation = TweenService:Create(self.DisplayModel.FailureWaypointBillboard.Frame, tweenInfo,
{ Rotation = 0 })
tweenRoation:Play()
tweenCenter.Completed:wait()
wait(FAILURE_TWEEN_LENGTH) -- Delay one tween length betfore removing
end
function FailureWaypoint.new(position)
local self = setmetatable({}, FailureWaypoint)
self.DisplayModel = self:NewDisplayModel(position)
return self
end
local failureAnimation = Instance.new("Animation")
failureAnimation.AnimationId = FAILURE_ANIMATION_ID
local lastHumanoid = nil
local lastFailureAnimationTrack = nil
local function getFailureAnimationTrack(myHumanoid)
if myHumanoid == lastHumanoid then
return lastFailureAnimationTrack
end
lastFailureAnimationTrack = myHumanoid:LoadAnimation(failureAnimation)
lastFailureAnimationTrack.Priority = Enum.AnimationPriority.Action
lastFailureAnimationTrack.Looped = false
return lastFailureAnimationTrack
end
local function findPlayerHumanoid()
local character = LocalPlayer.Character
if character then
return character:FindFirstChildOfClass("Humanoid")
end
end
local function createTrailDots(wayPoints, originalEndWaypoint)
local newTrailDots = {}
local count = 1
for i = 1, #wayPoints - 1 do
local closeToEnd = (wayPoints[i].Position - wayPoints[#wayPoints].Position).magnitude < LAST_DOT_DISTANCE
local includeWaypoint = i % WAYPOINT_INCLUDE_FACTOR == 0 and not closeToEnd
if includeWaypoint then
local trailDot = TrailDot.new(wayPoints[i].Position, i)
newTrailDots[count] = trailDot
count = count + 1
end
end
local newEndWaypoint = EndWaypoint.new(wayPoints[#wayPoints].Position, #wayPoints, originalEndWaypoint)
table.insert(newTrailDots, newEndWaypoint)
local reversedTrailDots = {}
count = 1
for i = #newTrailDots, 1, -1 do
reversedTrailDots[count] = newTrailDots[i]
count = count + 1
end
return reversedTrailDots
end
local function getTrailDotScale(distanceToCamera, defaultSize)
local rangeLength = TRAIL_DOT_MAX_DISTANCE - TRAIL_DOT_MIN_DISTANCE
local inRangePoint = math.clamp(distanceToCamera - TRAIL_DOT_MIN_DISTANCE, 0, rangeLength)/rangeLength
local scale = TRAIL_DOT_MIN_SCALE + (TRAIL_DOT_MAX_SCALE - TRAIL_DOT_MIN_SCALE)*inRangePoint
return defaultSize * scale
end
local createPathCount = 0
-- originalEndWaypoint is optional, causes the waypoint to tween from that position.
function ClickToMoveDisplay.CreatePathDisplay(wayPoints, originalEndWaypoint)
createPathCount = createPathCount + 1
local trailDots = createTrailDots(wayPoints, originalEndWaypoint)
local function removePathBeforePoint(wayPointNumber)
-- kill all trailDots before and at wayPointNumber
for i = #trailDots, 1, -1 do
local trailDot = trailDots[i]
if trailDot.ClosestWayPoint <= wayPointNumber then
trailDot:Destroy()
trailDots[i] = nil
else
break
end
end
end
local reiszeTrailDotsUpdateName = "ClickToMoveResizeTrail" ..createPathCount
local function resizeTrailDots()
if #trailDots == 0 then
RunService:UnbindFromRenderStep(reiszeTrailDotsUpdateName)
return
end
local cameraPos = Workspace.CurrentCamera.CFrame.p
for i = 1, #trailDots do
local trailDotImage = trailDots[i].DisplayModel:FindFirstChild("TrailDotImage")
if trailDotImage then
local distanceToCamera = (trailDots[i].DisplayModel.Position - cameraPos).magnitude
trailDotImage.Size = getTrailDotScale(distanceToCamera, TrailDotSize)
end
end
end
RunService:BindToRenderStep(reiszeTrailDotsUpdateName, Enum.RenderPriority.Camera.Value - 1, resizeTrailDots)
local function removePath()
removePathBeforePoint(#wayPoints)
end
return removePath, removePathBeforePoint
end
local lastFailureWaypoint = nil
function ClickToMoveDisplay.DisplayFailureWaypoint(position)
if lastFailureWaypoint then
lastFailureWaypoint:Hide()
end
local failureWaypoint = FailureWaypoint.new(position)
lastFailureWaypoint = failureWaypoint
coroutine.wrap(function()
failureWaypoint:RunFailureTween()
failureWaypoint:Destroy()
failureWaypoint = nil
end)()
end
function ClickToMoveDisplay.CreateEndWaypoint(position)
return EndWaypoint.new(position)
end
function ClickToMoveDisplay.PlayFailureAnimation()
local myHumanoid = findPlayerHumanoid()
if myHumanoid then
local animationTrack = getFailureAnimationTrack(myHumanoid)
animationTrack:Play()
end
end
function ClickToMoveDisplay.CancelFailureAnimation()
if lastFailureAnimationTrack ~= nil and lastFailureAnimationTrack.IsPlaying then
lastFailureAnimationTrack:Stop()
end
end
function ClickToMoveDisplay.SetWaypointTexture(texture)
TrailDotIcon = texture
TrailDotTemplate, EndWaypointTemplate, FailureWaypointTemplate = CreateWaypointTemplates()
end
function ClickToMoveDisplay.GetWaypointTexture()
return TrailDotIcon
end
function ClickToMoveDisplay.SetWaypointRadius(radius)
TrailDotSize = Vector2.new(radius, radius)
TrailDotTemplate, EndWaypointTemplate, FailureWaypointTemplate = CreateWaypointTemplates()
end
function ClickToMoveDisplay.GetWaypointRadius()
return TrailDotSize.X
end
function ClickToMoveDisplay.SetEndWaypointTexture(texture)
EndWaypointIcon = texture
TrailDotTemplate, EndWaypointTemplate, FailureWaypointTemplate = CreateWaypointTemplates()
end
function ClickToMoveDisplay.GetEndWaypointTexture()
return EndWaypointIcon
end
function ClickToMoveDisplay.SetWaypointsAlwaysOnTop(alwaysOnTop)
WaypointsAlwaysOnTop = alwaysOnTop
TrailDotTemplate, EndWaypointTemplate, FailureWaypointTemplate = CreateWaypointTemplates()
end
function ClickToMoveDisplay.GetWaypointsAlwaysOnTop()
return WaypointsAlwaysOnTop
end
return ClickToMoveDisplay