Rewrote the script because why not
If you wanna use it, put it in ServerScriptService.
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local BloodLocation = workspace.GFX
local BloodSize = {3, 4.5}
local BloodTextures = {
"rbxassetid://119810117710356",
"rbxassetid://115394637191321",
"rbxassetid://72028379167893",
"rbxassetid://122801970062010",
"rbxassetid://75231418139407"
}
local function spawner(func)
local wrap = coroutine.wrap(func)
wrap()
end
local function GetNormal(Part, Position)
local Shape = nil
if Part:IsA("Part") then
Shape = Part.Shape.Value
elseif Part:IsA("WedgePart") then
Shape = 3
elseif Part:IsA("CornerWedgePart") then
Shape = 4
else
Shape = 5
end
if Shape == 0 then
return (Position - Part.Position).Unit, "curve", Position
elseif Shape == 1 or Shape == 3 then
local r = Part.CFrame:pointToObjectSpace(Position) / Part.Size
local Rotation = Part.CFrame - Part.Position
if r.x > 0.4999 then
return Rotation * Vector3.new(1, 0, 0), "right", Position
elseif r.x < -0.4999 then
return Rotation * Vector3.new(-1, 0, 0), "left", Position
elseif r.y > 0.4999 then
return Rotation * Vector3.new(0, 1, 0), "top", Position
elseif r.y < -0.4999 then
return Rotation * Vector3.new(0, -1, 0), "bottom", Position
elseif r.z > 0.4999 then
return Rotation * Vector3.new(0, 0, 1), "back", Position
elseif r.z < -0.4999 then
return Rotation * Vector3.new(0, 0, -1), "front", Position
end
return Rotation * Vector3.new(0, Part.Size.Z, -Part.Size.Y).Unit, "ramp", Position
elseif Shape == 2 then
return (Position - Part.Position).Unit, "curve", Position
elseif Shape == 4 then
local r = Part.CFrame:pointToObjectSpace(Position) / Part.Size
local Rotation = Part.CFrame - Part.Position
if r.x > 0.4999 then
return Rotation * Vector3.new(1, 0, 0), "right", Position
elseif r.y < -0.4999 then
return Rotation * Vector3.new(0, -1, 0), "bottom", Position
elseif r.z < -0.4999 then
return Rotation * Vector3.new(0, 0, -1), "front", Position
elseif r.Unit:Dot(Vector3.new(1, 0, 1).Unit) > 0 then
return Rotation * Vector3.new(0, Part.Size.Z, Part.Size.Y).Unit, "lslope", Position
end
return Rotation * Vector3.new(-Part.Size.Y, Part.Size.X,0).Unit, "rslope", Position
else
return Vector3.new(0, 1, 0), "unknown", Position
end
end
local function EmitBlood(HumanoidRootpart, Part)
local RandomBloodSize = math.random(BloodSize[1], BloodSize[2])
local BloodPart = Instance.new("Part")
BloodPart.Name = "BloodPart"
BloodPart.CanCollide = false
BloodPart.CanQuery = false
BloodPart.CanTouch = false
BloodPart.Anchored = true
BloodPart.Material = Enum.Material.Glass
BloodPart.Size = Vector3.new(RandomBloodSize, 0, RandomBloodSize)
BloodPart.CastShadow = false
BloodPart.Transparency = 1
BloodPart.Parent = workspace.GFX
local BloodDecal = Instance.new("Decal")
BloodDecal.Texture = BloodTextures[math.random(1, #BloodTextures)]
BloodDecal.Face = Enum.NormalId.Top
BloodDecal.Parent = BloodPart
local Normal = GetNormal(Part, HumanoidRootpart.Position)
local Parameters = RaycastParams.new()
Parameters.FilterDescendantsInstances = {HumanoidRootpart.Parent, BloodLocation}
local Origin = HumanoidRootpart.Position
local Direction = -Normal * 20
local RaycastResult = workspace:Raycast(Origin, Direction, Parameters)
if RaycastResult then
if RaycastResult.Instance then
local Change = false
if Normal == Vector3.new(0, 1, 0) then
Normal = Vector3.new(0.01, 0.9, 0)
Change = true
end
local Right = -Vector3.yAxis:Cross(Normal)
if not Change then
BloodPart.CFrame = CFrame.fromMatrix(RaycastResult.Position, Right, Normal)
else
BloodPart.CFrame = CFrame.fromMatrix(RaycastResult.Position, Right, Normal)
BloodPart.Orientation = Vector3.new(0, 90, 0)
end
end
end
spawner(function()
task.wait(45)
local BloodSize = TweenService:Create(BloodDecal, TweenInfo.new(5), {Transparency = 1}, true)
local BloodTransparency = TweenService:Create(BloodPart, TweenInfo.new(5), {Size = Vector3.zero}, true)
BloodSize:Play()
BloodTransparency:Play()
task.wait(5)
BloodPart:Destroy()
end)
end
Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
local Humanoid = Character:FindFirstChildOfClass("Humanoid")
local HumanoidRootPart = Character:FindFirstChild("HumanoidRootPart")
if Humanoid and HumanoidRootPart then
local Bleeding = false
local LastHealth = Humanoid.Health
task.wait() --// added a wait because my character wasn't spawning properly. you can probably remove this
for i, child in Character:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(function(TouchedPart)
if Bleeding or Humanoid.Health <= 0 then
if not TouchedPart:FindFirstAncestor(Character.Name) and TouchedPart.Parent.Name ~= "Blood" and TouchedPart.Anchored then
EmitBlood(HumanoidRootPart, TouchedPart)
end
end
end)
end
end
Humanoid.HealthChanged:Connect(function(NewHealth)
LastHealth = NewHealth
if NewHealth > LastHealth then return end
local Parameters = RaycastParams.new()
Parameters.FilterDescendantsInstances = {Character, BloodLocation}
local Origin = HumanoidRootPart.Position
local Direction = Vector3.new(0, -20, 0) * 20
local RaycastResult = workspace:Raycast(Origin, Direction, Parameters)
if RaycastResult then
if RaycastResult.Instance then
spawner(function()
for i = 1, 3 do
EmitBlood(HumanoidRootPart, RaycastResult.Instance)
EmitBlood(HumanoidRootPart, RaycastResult.Instance)
task.wait(1 / 3)
end
end)
end
end
spawner(function()
Bleeding = true
task.wait(1)
Bleeding = false
end)
end)
end
end)
end)
Works so well with ragdolls. I love it.