I am trying to optimize a tool script that is called Levitation and Force tool. It’s based off the 4 seasons show Stranger things and I need help. Here’s what I listed everything to optimize the tools.
What I need to add…
- Add a Blood decal face to the character wait 2-3 seconds and goes back to the players’ avatar regular face.
Things inside the tool…
-
Inside Levitation tool…
→ Three Remote Events
→ three scripts (client, server, and a module script called Configuration) -
Inside Force tool…
→ One Remote event
→ three scripts (client, server, and a module script called Configuration)
Levitation tool Client script…
local UserInputService = game:GetService("UserInputService")
local animation = script.Parent.Animation
local localPlayer = Players.LocalPlayer
local char = localPlayer.Character or localPlayer.CharacterAdded:Wait()
local hum = char:WaitForChild("Humanoid")
local tool = script.Parent
local Configuration = require(tool:WaitForChild("Configuration"))
local startForce = tool:WaitForChild("StartForce")
local endForce = tool:WaitForChild("EndForce")
local updateForcePosition = tool:WaitForChild("UpdateForcePosition")
--Constants
local INPUT_HIT_RAY_LENGTH = Configuration.INPUT_HIT_RAY_LENGTH
local TOOL_USE_COOLDOWN = Configuration.TOOL_USE_COOLDOWN
local FORCE_TIME = Configuration.FORCE_TIME
local FORCE_INFLUENCE_DISTANCE = Configuration.FORCE_INFLUENCE_DISTANCE
local PLAYER_EXCLUSIVE = Configuration.PLAYER_EXCLUSIVE
--Misc Vars
local activationDebounce = true
local forcingPlayerPosition = false
local forcing
local function isPlayer(obj)
if obj == nil then return false end
if Players:GetPlayerFromCharacter(obj) then
return true
elseif Players:GetPlayerFromCharacter(obj.Parent) then
return true
elseif Players:GetPlayerFromCharacter(obj.Parent.Parent) then
return true
else
return false
end
end
local function findInputHit(x, y, length)
local INPUT_HIT_RAY_IGNORE_LIST = {localPlayer.Character, forcing}
if length == nil then length = INPUT_HIT_RAY_LENGTH end
local unitRay = workspace.CurrentCamera:ViewportPointToRay(x, y)
local ray = Ray.new(unitRay.Origin, unitRay.Direction * length)
local part, pos = workspace:FindPartOnRayWithIgnoreList(ray, INPUT_HIT_RAY_IGNORE_LIST,true, true)
return part, pos, ray.Origin, ray.Direction
end
local updateForcePosition = coroutine.create(function()
while true do
local timeDegrade = 0.1
local timePassed = 0
print(forcingPlayerPosition)
repeat
local inputPos = UserInputService:GetMouseLocation()
local part, pos, origin, direction = findInputHit(inputPos.X, inputPos.Y)
local characterPosition = localPlayer.Character.PrimaryPart.Position
local dist
local finalPos
if pos ~= nil then
dist = (characterPosition - pos).Magnitude
if dist > FORCE_INFLUENCE_DISTANCE then
dist = FORCE_INFLUENCE_DISTANCE
else
finalPos = pos
end
end
if finalPos == nil then
if part == nil then
dist = FORCE_INFLUENCE_DISTANCE
else
dist = (characterPosition - pos).Magnitude
if dist > FORCE_INFLUENCE_DISTANCE then
dist = FORCE_INFLUENCE_DISTANCE
end
end
local goalPos = CFrame.new(direction * FORCE_INFLUENCE_DISTANCE, origin).Position
finalPos = CFrame.new(characterPosition, goalPos)
finalPos = finalPos * CFrame.new(0, 0, -dist)
finalPos = finalPos.Position
end
updateForcePosition:FireServer(finalPos)
wait(timeDegrade)
timePassed = timePassed + timeDegrade
if timePassed > FORCE_TIME then
forcingPlayerPosition = false
end
until forcingPlayerPosition == false
coroutine.yield()
end
end)
function getDecal()
local decals = {5818582212}
for i, child in pairs(script.Parent:GetChildren()) do
if child.ClassName == "Decal" then
table.insert(decals, child)
end
end
if decals ~= 0 then
return decals[math.random(1, #decals)]
end
return nil
end
function toolActivationEvent()
local inputPos = UserInputService:GetMouseLocation()
local inputHit = findInputHit(inputPos.X, inputPos.Y)
local animationTrack = hum:LoadAnimation(animation)
if inputHit == nil then return end
local isInputPlayer = isPlayer(inputHit)
if not isInputPlayer and PLAYER_EXCLUSIVE then return end
local head = char:WaitForChild("Head")
if head ~= nil then
local face = head:FindFirstChild("face")
if face.Texture ~= getDecal().Texture then
face.Texture = getDecal().Texture
wait(2.5)
face:Destroy()
end
end
animationTrack:Play()
hum.Health = hum.Health - 5
--[[
Debounce is placed below the code from above to prevent a instance where
if a player clicks on a part, there would be a unneccessary cooldown
--]]
if activationDebounce == false then return end
activationDebounce = false
if inputHit.Parent:IsA("Model") then
forcing = inputHit.Parent
else
forcing = inputHit
end
forcingPlayerPosition = true
startForce:FireServer(inputHit)
coroutine.resume(updateForcePosition)
wait(TOOL_USE_COOLDOWN)
activationDebounce = true
end
function disableForcing()
forcing = nil
forcingPlayerPosition = false
end
function toolDeactivatedEvent()
disableForcing()
endForce:FireServer()
end
endForce.OnClientEvent:Connect(function()
disableForcing()
end)
tool.Activated:Connect(toolActivationEvent)
tool.Deactivated:Connect(toolDeactivatedEvent)
Force tool Client script…
local UserInputService = game:GetService("UserInputService")
local localPlayer = Players.LocalPlayer
local tool = script.Parent
local Configuration = require(tool:WaitForChild("Configuration"))
local luanchObject = tool:WaitForChild("LuanchObject")
local whitelist = {"Usename1", "Username2", "Username3"}
local animation = script.Parent.Animation
-- Player/Character Variables
local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
-- Define Humanoid
local hum = char:WaitForChild("Humanoid")
--Constants
local INPUT_HIT_RAY_LENGTH = Configuration.INPUT_HIT_RAY_LENGTH
local INPUT_HIT_RAY_IGNORE_LIST = {localPlayer.Character}
local TOOL_USE_COOLDOWN = Configuration.TOOL_USE_COOLDOWN
local FORCE_TIME = Configuration.FORCE_TIME
local PLAYER_EXCLUSIVE = Configuration.PLAYER_EXCLUSIVE
--Misc Vars
local activationDebounce = true
local storedInputObject
if whitelist then
tool:Clone()
end
local function isPlayer(obj)
if obj == nil then return false end
if Players:GetPlayerFromCharacter(obj) then
return true
elseif Players:GetPlayerFromCharacter(obj.Parent) then
return true
elseif Players:GetPlayerFromCharacter(obj.Parent.Parent) then
return true
else
return false
end
end
local function findInputHit(x, y)
local unitRay = workspace.CurrentCamera:ViewportPointToRay(x, y)
local ray = Ray.new(unitRay.Origin, unitRay.Direction * INPUT_HIT_RAY_LENGTH)
local part, pos = workspace:FindPartOnRayWithIgnoreList(ray, INPUT_HIT_RAY_IGNORE_LIST,true, true)
return part, pos
end
function getDecal()
local decals = {5818582212}
for i, child in pairs(script.Parent:GetChildren()) do
if child.ClassName == "Decal" then
table.insert(decals, child)
end
end
if decals ~= 0 then
return decals[math.random(1, #decals)]
end
return nil
end
function toolActivationEvent()
local inputPos = UserInputService:GetMouseLocation()
local inputHit = findInputHit(inputPos.X, inputPos.Y)
local animationTrack = hum:LoadAnimation(animation)
if inputHit == nil then return end
local isInputPlayer = isPlayer(inputHit)
if not isInputPlayer and PLAYER_EXCLUSIVE then return end
--[[
Blood Texture will be included with the animation
--]]
local head = character:WaitForChild("Head")
if head ~= nil then
local face = head:FindFirstChild("face")
if face.Texture ~= getDecal().Texture then
face.Texture = getDecal().Texture
wait(2.5)
face:Destroy()
end
end
animationTrack:Play()
hum.Health = hum.Health - 5
--[[
Debounce is placed below the code from above to prevent a instance where
if a player clicks on a part, there would be a unneccessary cooldown
--]]
if activationDebounce == false then return end
activationDebounce = false
luanchObject:FireServer(inputHit)
wait(TOOL_USE_COOLDOWN)
activationDebounce = true
end
tool.Activated:Connect(toolActivationEvent)
What gives me in the output…
Any solution to fixing this?