So basically i’am making a Ro-Soccer game, I’ve made multiple tools (For now only dribble work), I’ve started Shoot tool to kick the ball with an Angle bar & a Power bar, Those aren’t the problem but When i try to touch the ball I get this error
here is the modules “Functionings”
local Functionings = {}
-- [{ Main Module Requirements }]
local TS = game:GetService("TweenService")
local Client = game.Players.LocalPlayer
local Character = Client.Character
-- [{ Service Requirements }]
local RStorage = game:GetService("ReplicatedStorage")
local Remotes = RStorage.Remotes
local RunService = game:GetService("RunService")
--- [{ Variable Requirements }]
local UsingTool = false
local FootType = "R"
--- [{ Module Requirements }]
local StateManager = require(RStorage.Modules.StateManager)
local GarbageCollector = require(RStorage.Modules.GarbageCollector).new()
local ParametersModule = require(RStorage.Modules.ParametersModule)
-- [{ Function Gameplay }]
function Functionings.Hitbox(Information)
RunService.Stepped:Wait()
for Index, Limb in Information.Limbs do
task.spawn(function()
GarbageCollector:GiveTask(Limb.Touched:Connect(function(HitPart)
if HitPart:HasTag("Ball") then
Information.ReactFunction(HitPart, Limb)
end
end))
GarbageCollector:GiveTask(RunService.Stepped:Connect(function()
local Parts = workspace:GetPartsInPart(Limb, ParametersModule:GetBallParameters())
for Index, Ball in Parts do
Information.ReactFunction(Ball, Limb)
end
end))
end)
end
end
function Functionings.ClientReact(Ball, MaxForce, Velocity, Cooldown, DebrisTime)
if Ball.Anchored == true then
return
end
if Ball.Values.OnCoolDown.Value == true then
warn("yh")
return
end
for Index, CorrespondingValue in ipairs( Ball:GetChildren() ) do
if CorrespondingValue.Name == "BodyVelocity" or CorrespondingValue.Name == "Curve" then
CorrespondingValue:Remove()
end
end
for Index, CorrespondingValue in ipairs( Character.Torso:GetChildren() ) do
if CorrespondingValue.Name == "BodyVelocity" then
CorrespondingValue:Destroy()
end
end
if DebrisTime == nil then
DebrisTime = 0.3
end
if Cooldown == nil then
Cooldown = 0.6
end
Remotes.Gameplay.OutfieldReactOwnership:FireServer(
Ball,
Ball.Position,
Cooldown
)
local ClientSideReactBodyVelocity = Instance.new("BodyVelocity")
ClientSideReactBodyVelocity.Velocity = Velocity
ClientSideReactBodyVelocity.MaxForce = MaxForce
ClientSideReactBodyVelocity.Velocity = Velocity
ClientSideReactBodyVelocity.Parent = Ball
game.Debris:AddItem(ClientSideReactBodyVelocity, DebrisTime)
end
return Functionings
Here is my LocalScript “Initializer” Under Shoot Tool.
task.wait()
local RepStorage = game:GetService("ReplicatedStorage")
local Funcs = require(RepStorage.Modules.CoreGameplay.Functionings)
local State = require(RepStorage.Modules.StateManager)
local ContextAction = game:GetService("ContextActionService")
local Visuals = require(RepStorage.Modules.VectorViz)
local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
player.CharacterAdded:Connect(function(c) char = c end)
local pdata = RepStorage.ClientData:WaitForChild(tostring(player.UserId))
local globalCd = .2
local okPower, PowerBar = pcall(function() return require(RepStorage.Modules.PowerBar) end)
local okAngle, AngleBarModule = pcall(function() return require(RepStorage.Modules.AngleBar) end)
if not okPower then warn("PowerBar require failed:", PowerBar) end
if not okAngle then warn("AngleBar require failed:", AngleBarModule) end
local tool = script.Parent
local active = {}
local animCache = {}
local inputHistory = {}
local isHolding = false
local boundActions = {}
local Equipped = false
local globalCdActive = false
tool.Equipped:Connect(function()
Equipped = true
State.SetState(player, "EquippedTool", true)
end)
tool.Unequipped:Connect(function()
Equipped = false
for mod, _ in pairs(active) do
pcall(function() releaseAction(mod) end)
end
State.SetState(player, "EquippedTool", false)
State.SetState(player, "Using", false)
end)
local function playAnimation(animFolder, animName, mod)
local hum = char and char:FindFirstChildOfClass("Humanoid")
if not hum then return nil end
local anim
local suffix = ""
if mod and mod.ReliesOnFoot then
local leg = State.GetState(player, "Leg")
suffix = (leg == "Right" and "_R") or "_L"
anim = animFolder and (animFolder:FindFirstChild(animName .. suffix) or animFolder:FindFirstChild(animName)) or nil
else
anim = animFolder and animFolder:FindFirstChild(animName) or nil
end
if not anim then return nil end
local cacheKey = animName .. suffix
if not animCache[cacheKey] then
animCache[cacheKey] = hum:LoadAnimation(anim)
end
local track = animCache[cacheKey]
if track then
if track.IsPlaying then pcall(function() track:Stop() end) end
pcall(function() track:Play() end)
end
return track, cacheKey
end
local function pressAction(mod, keyVal)
if mod and type(mod.react) == "function" then
local animFolder = RepStorage.Animations.Tools:FindFirstChild(tool.Name) or RepStorage.Animations.Tools
local track = playAnimation(animFolder, keyVal.Name, mod)
active[mod] = true
State.SetState(player, "Using", true)
globalCdActive = true
task.delay(globalCd, function() globalCdActive = false end)
task.delay(mod.ReactTime, function()
if track and track.IsPlaying then track:Stop() end
State.SetState(player, "Using", false)
active[mod] = nil
inputHistory = {}
end)
end
end
local function startHold(keyVal, mod)
inputHistory = {}
isHolding = true
State.SetState(player, "Using", true)
local animFolder = RepStorage.Animations.Tools.Shoot:FindFirstChild(keyVal.Name) or RepStorage.Animations.Tools.Shoot
local holdTrack, cacheKey = playAnimation(animFolder, "HoldUp", mod)
active[mod] = { track = holdTrack, cacheKey = cacheKey, charging = true }
pcall(function() if okPower then PowerBar.Start() end end)
end
function releaseAction(mod, keyVal)
local keyName = nil
if keyVal and keyVal.Name then
keyName = keyVal.Name
else
local kv = pdata.Keybinds:FindFirstChild("Shoot") and pdata.Keybinds.Shoot:FindFirstChild(mod.Name)
if kv then keyName = kv.Name keyVal = kv end
end
if not isHolding and not active[mod] then
return
end
local stored = active[mod]
if stored and type(stored) == "table" then
if stored.track then pcall(function() if stored.track.IsPlaying then stored.track:Stop() end end) end
if stored.cacheKey and animCache[stored.cacheKey] then
pcall(function()
local ct = animCache[stored.cacheKey]
if ct and ct.IsPlaying then ct:Stop() end
end)
end
end
isHolding = false
local lastKey = nil
if type(mod.Check) == "function" then lastKey = mod.Check(inputHistory) end
local MaxForce, F, Cooldown, DebrisTime, animName
if type(mod.Release) == "function" then
if mod.HoldAble then
local powerValue = 0
local angleValue = (okAngle and AngleBarModule.GetAngle and AngleBarModule.GetAngle()) or 50
local ok, res = pcall(function() if okPower and PowerBar.Stop then return PowerBar.Stop() end return 0 end)
if ok and type(res) == "number" then powerValue = res else powerValue = 0 end
MaxForce, F, Cooldown, DebrisTime, animName = mod.Release(lastKey, powerValue, angleValue)
else
MaxForce, F, Cooldown, DebrisTime, animName = mod.Release(lastKey)
end
end
local animFolder
if keyName then
animFolder = RepStorage.Animations.Tools.Shoot:FindFirstChild(keyName) or RepStorage.Animations.Tools.Shoot
else
animFolder = RepStorage.Animations.Tools.Shoot:FindFirstChild(mod.Name) or RepStorage.Animations.Tools.Shoot
end
local releaseTrack, releaseCacheKey
if animFolder then
releaseTrack, releaseCacheKey = playAnimation(animFolder, animName or "Release", mod)
active[mod] = active[mod] or {}
active[mod].releaseTrack = releaseTrack
active[mod].releaseCacheKey = releaseCacheKey
end
globalCdActive = true
task.delay(globalCd or 0.2, function() globalCdActive = false end)
if releaseTrack then
local len = (releaseTrack.Length and releaseTrack.Length > 0) and releaseTrack.Length or (mod.TimeAfterRelease or 1)
task.delay(len + 0.05, function()
pcall(function() if releaseTrack.IsPlaying then releaseTrack:Stop() end end)
active[mod] = nil
State.SetState(player, "Using", false)
inputHistory = {}
end)
else
task.delay(mod.TimeAfterRelease or 1, function()
active[mod] = nil
State.SetState(player, "Using", false)
inputHistory = {}
end)
end
return MaxForce, F, Cooldown, DebrisTime
end
local function onHit(hit, limb)
if not hit or hit.Name ~= "Ball" then return end
if not limb then return end
local selectedLeg = State.GetState(player, "Leg")
local limbLeg = (limb == char["Right Leg"] and "Right") or (limb == char["Left Leg"] and "Left") or nil
if limbLeg == nil then return end
for mod, _ in pairs(active) do
local footPref = mod.Foot
local forceFoot = mod.ForceFoot
local allow = false
if footPref then
if forceFoot then
if limbLeg == footPref then allow = true end
else
if selectedLeg == footPref and limbLeg == footPref then allow = true end
end
else
if limbLeg == selectedLeg then allow = true end
end
if allow then
local MaxForce, F, Cooldown, DebrisTime
if mod.HoldAble then
local keyVal = pdata.Keybinds.Shoot:FindFirstChild(mod.Name)
if keyVal then MaxForce, F, Cooldown, DebrisTime = releaseAction(mod, keyVal) end
else
MaxForce, F, Cooldown, DebrisTime = mod.react(hit, limb)
end
if MaxForce and F then
if Visuals and type(Visuals.CreateVisualiser) == "function" then
pcall(function()
Visuals:CreateVisualiser("ForceViz", hit.Position, F, {Colour = Color3.fromRGB(165, 21, 255), Scale = 1, Width = 0.15})
end)
task.delay(1, function() pcall(function() Visuals:DestroyVisualiser("ForceViz") end) end)
end
Funcs.ClientReact(hit, MaxForce, F, Cooldown, DebrisTime)
end
end
end
end
Funcs.Hitbox({
Limbs = { char["Right Leg"], char["Left Leg"] },
ReactFunction = onHit
})
local function getInputId(inputObject)
if not inputObject then return nil end
local uit = inputObject.UserInputType
if uit == Enum.UserInputType.MouseButton1 or uit == Enum.UserInputType.MouseButton2 then return uit.Name end
local kc = inputObject.KeyCode
if kc and kc ~= Enum.KeyCode.Unknown then return kc.Name end
return tostring((uit and uit.Name) or "")
end
local function bindKey(keyVal)
if not keyVal:IsA("StringValue") or keyVal.Value == "" then return end
local kv = keyVal
local keyValue = kv.Value
local actionName = "Shoot_" .. kv.Name
if boundActions[actionName] then ContextAction:UnbindAction(actionName) boundActions[actionName] = nil end
local enumArg
if keyValue == "MouseButton1" or keyValue == "MouseButton2" then enumArg = Enum.UserInputType[keyValue] else enumArg = Enum.KeyCode[keyValue] end
local function actionCallback(name, inputState, inputObject)
if not tool or not tool.Parent or tool.Parent ~= char then return Enum.ContextActionResult.Pass end
if inputState == Enum.UserInputState.Begin and globalCdActive then return Enum.ContextActionResult.Sink end
if inputState == Enum.UserInputState.Begin then
if State.GetState(player, "Using") and isHolding then return Enum.ContextActionResult.Sink end
local id = getInputId(inputObject)
if id then table.insert(inputHistory, id) end
local modScript = script:FindFirstChild(kv.Name)
if not modScript then return Enum.ContextActionResult.Pass end
local mod = require(modScript)
if mod.HoldAble then startHold(kv, mod) else pressAction(mod, kv) end
return Enum.ContextActionResult.Sink
elseif inputState == Enum.UserInputState.End or inputState == Enum.UserInputState.Cancel then
local modScript = script:FindFirstChild(kv.Name)
if not modScript then return Enum.ContextActionResult.Pass end
local mod = require(modScript)
if mod.HoldAble then releaseAction(mod, kv) return Enum.ContextActionResult.Sink end
end
return Enum.ContextActionResult.Pass
end
if enumArg then ContextAction:BindAction(actionName, actionCallback, false, enumArg) else ContextAction:BindAction(actionName, actionCallback, false) end
boundActions[actionName] = true
end
local shootKeybinds = pdata.Keybinds:FindFirstChild("Shoot")
if shootKeybinds then
for _, keyVal in ipairs(shootKeybinds:GetChildren()) do bindKey(keyVal) end
else
warn("[Startup] pdata.Keybinds.Shoot not found")
end
pdata.Keybinds.Shoot.ChildAdded:Connect(function(child) bindKey(child) end)
pdata.Keybinds.Shoot.ChildRemoved:Connect(function(child)
local actionName = "Shoot_" .. tostring(child.Name)
if boundActions[actionName] then ContextAction:UnbindAction(actionName) boundActions[actionName] = nil end
end)
