Weapon randomly one shots. Not sure why. This isnt a tool but a model attached to player via motor 6d. I have posted about this before, yet i have changed my script so i thought i should ask again. Please any ideas?
local function stopSwing()
task.wait(.2)
swingCheck = false
debounce = false
damageCount = 0
hitboxTrue = false
hitBoxCount = 0
end
script.Parent.SwordCombatRemote.OnServerEvent:Connect(function(player)
if swingCheck then return end
swingCheck = true
local character = player.Character
if character.IsRagdoll.Value then
swingCheck = false
return
end
local Hum = character:WaitForChild("Humanoid")
if Combo == 1 then
playAnim = Hum:LoadAnimation(anim)
playAnim:Play()
Combo = 2
elseif Combo == 2 then
playAnim = Hum:LoadAnimation(anim2)
playAnim:Play()
Combo = 1
end
task.wait(0.25)
sound:Play()
if hitboxTrue == false then
hitboxTrue = true
hitBoxCount += 1
print(hitBoxCount)
if hitBoxCount < 2 then
print("made", character.Name)
local physicalBox = Instance.new("Part", character)
physicalBox.Name = "Hitbox"
physicalBox.Transparency = 0.6
physicalBox.Anchored = false
physicalBox.CanCollide = false
physicalBox.Size = Vector3.new(5.5, 2.5, 5.5)
physicalBox.Massless = true
physicalBox.CFrame = character.HumanoidRootPart.CFrame * CFrame.new(0, 0, -3.5)
physicalBox.Parent = character.HumanoidRootPart
local weld = Instance.new("WeldConstraint")
weld.Part0 = character.HumanoidRootPart
weld.Part1 = physicalBox
weld.Parent = character.HumanoidRootPart
game.Debris:AddItem(weld, 0.5)
game.Debris:AddItem(physicalBox, 0.5)
local affected = {}
local TouchEvent
task.wait()
TouchEvent = physicalBox.Touched:Connect(function(hit)
if debounce == true then
return
else
debounce = true
end
if hit.Parent:FindFirstChild("Humanoid") ~= nil then
if hit.Parent ~= character then
if character:FindFirstChild("IsRagdoll").Value == false then
if game.Players:GetPlayerFromCharacter(hit.Parent):WaitForChild("Bool").Invincible.Value == false then
if not table.find(affected, hit.Parent) then
table.insert(affected, hit.Parent)
if damageCount < 2 then
TouchEvent:Disconnect()
physicalBox:Destroy()
damageCount += 1
print(damageCount, "player hit.")
hit.Parent:FindFirstChild("Humanoid"):TakeDamage(12)
swordRagdoll(hit.Parent, character)
local attacker = game.Players:GetPlayerFromCharacter(character)
if attacker and attacker:FindFirstChild("leaderstats") then
attacker.leaderstats.Hits.Value += 1
end
end
end
end
end
end
end
debounce = false
end)
end
end
playAnim.Stopped:Connect(stopSwing)
end)
I recommend debugging your script and checking the scope of your variables. Itâs likely that you are setting them but when you go to read them itâs reading a different version of them. I donât recommend storing variables in a function nor having a function in a function. Instead have the touch function edit a variable and then when your event is called check the variable. Also for the debounces I recommend adding a delay even just a task.wait(0.1) and you will see a noticeable difference.
local function stopSwing()
task.wait(.2)
swingCheck = false
found = false
end
function hit(hitbox, character)
while found == false do
wait(.1)
local foundparts = workspace:GetPartsInPart(hitbox)
for i, part in ipairs(foundparts) do
if found == true then return end
if part.Parent:FindFirstChild("Humanoid") then
if part.Parent ~= character then
found = true
print("fOUND")
end
end
end
end
end
function newHitBox(character, playAnim)
local physicalBox = Instance.new("Part", character)
physicalBox.Name = "Hitbox"
physicalBox.Transparency = 0.6
physicalBox.Anchored = false
physicalBox.CanCollide = false
physicalBox.Size = Vector3.new(5.5, 2.5, 5.5)
physicalBox.Massless = true
physicalBox.CFrame = character.HumanoidRootPart.CFrame * CFrame.new(0, 0, -3.5)
physicalBox.Parent = character.HumanoidRootPart
local weld = Instance.new("WeldConstraint")
weld.Part0 = character.HumanoidRootPart
weld.Part1 = physicalBox
weld.Parent = character.HumanoidRootPart
game.Debris:AddItem(weld, 0.5)
game.Debris:AddItem(physicalBox, 0.5)
playAnim.Stopped:Connect(function()
physicalBox:Destroy()
end)
hit(physicalBox, character)
end
script.Parent.SwordCombatRemote.OnServerEvent:Connect(function(player)
print("got here")
print(swingCheck)
if swingCheck then return end
swingCheck = true
local character = player.Character
if character.IsRagdoll.Value then
swingCheck = false
return
end
local Hum = character:WaitForChild("Humanoid")
if Combo == 1 then
playAnim = Hum:LoadAnimation(anim)
playAnim:Play()
Combo = 2
elseif Combo == 2 then
playAnim = Hum:LoadAnimation(anim2)
playAnim:Play()
Combo = 1
end
playAnim.Stopped:Connect(function()
stopSwing()
end)
task.wait(0.2)
newHitBox(character, playAnim)
sound:Play()
end)
emphasized text
This would be creating multiple loops, good you worked it out though. And if you want to know what a âscopeâ is, go to a part of your script and click right next to the numbers on the left, it will activate debugging and when that part of the script runs open âwatchâ. It will tell you the scope of all your variables at that part of the script. You should look it up as it can affect performance and cause issues down the line.
General gist of it though is a âscopeâ is where certain variables/functions can be accessed and sometimes certain scopes only allow reading of variables but not writing of variables and if you do try it only affects that particular scope.
As an example when you create and then run a function, that function has itâs own scope which is why you have to define parameters, it can only use itâs own local variables, upvalues and globals. (Upvalues are variables defined in the upper scope such as the start of the script.)
Hope I was helpful!
The one shot still happens even with the module, so this leads me to believe itâs part of the event activating weirdly, like activating multiple swings at once, because thereâs no way the module is also having the same error as me. Iâm still using the same animation and on event loop, is there something wrong with that bit?
You shouldnât have any loops at all other than iterating over any candidate parts. As soon as a part is found you need to break the loop or check if youâve already damaged that player. If multiple parts of the same player are found in the loop it will damage them multiple times. Since youâre raycasting now though, you shouldnât have any loops at all.
Any âhitboxesâ should already exist, creating and destroying them repeatedly is bad for performance. Since youâve moved to raycasting I imagine you donât need this anymore though.
Since youâre raycasting it should simply be:
script.Parent.SwordCombatRemote.OnServerEvent:Connect(function(player)
if swingCheck then return end
swingCheck = true
local Ray = game.Workspace:Raycast(rayOrigin, rayDirection, Params) -- Or whatever
local character = Ray.Instance.Parent
if not character:FindFirstChild("Humanoid") then return end
if Ray.Instance.Parent.IsRagdoll.Value then -- Checking Result
swingCheck = false
return
end
local Hum = character.Humanoid
if Combo == 1 then
playAnim = Hum:LoadAnimation(anim)
playAnim:Play()
Combo = 2
elseif Combo == 2 then
playAnim = Hum:LoadAnimation(anim2)
playAnim:Play()
Combo = 1
end
playAnim.Stopped:Connect(function()
stopSwing()
end)
task.wait(0.2)
hum.Health -= damage -- Whatever your damage value is here
sound:Play()
end)
This is just an example of what it should look like. Donât copy it 1:1 unless you want to but basically it should just be a straight, loopless script. Have any important values in this like swingCheck an upvalue, use the debugger if you come across any issues.
If you donât know how to use the debugger heres a random youtube video I found:
It could be the ragdoll breaking your character. Have you tried setting the Humanoidâs RequiresNeck property to false? If you are using the Perfect Ragdoll module (which also uses IsRagdoll so thats why I am assuming) they have a setting in their script to disable that property.