-- =============================================== -- MERGED BLOOD SYSTEM — ULTIMATE v12.4 (BRUTAL BLOOD) -- =============================================== local Players = game:GetService("Players") local Debris = game:GetService("Debris") local TweenService = game:GetService("TweenService") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local PhysicsService = game:GetService("PhysicsService") local player = Players.LocalPlayer local RAGDOLL_ENABLED = false local NO_PLAYER_LIMITS = true local unlimitedMode = NO_PLAYER_LIMITS local DEBUG_MODE = false local debugEnabled = DEBUG_MODE local DEBUG_UPDATE_INTERVAL = 0.5 local BLOOD_COLOR = Color3.fromRGB(130, 0, 0) local BLOOD_PARTICLE_HI = Color3.fromRGB(160, 15, 15) local BLOOD_PARTICLE_LO = Color3.fromRGB(90, 0, 0) local BLOOD_MIST = Color3.fromRGB(120, 5, 5) local BLOOD_IMPACT_HI = Color3.fromRGB(170, 15, 15) local BLOOD_IMPACT_LO = Color3.fromRGB(80, 0, 0) local GORE_COLOR = Color3.fromRGB(140, 10, 10) local BLOOD_TEXTURE = "rbxassetid://867743272" local GORE_TEXTURE = "rbxassetid://243664672" local BLOOD_RATE = 30 local BLOOD_LIFETIME = 0.5 local DROPLET_LIFETIME = 1.5 local SPLAT_LIFETIME = 20 local PUDDLE_FADE_IN_TIME = 0.4 local PUDDLE_HOLD_TIME = 12 local PUDDLE_FADE_OUT_TIME = 1.5 local BLOODSIDS = { "12483962943","1927066326","9893638760","107953383542820","7276344647", "15712100172","1930718631","5303324133","87804017763851","944421458","5563242059", } local SPLATIDS = { "15712100172","90715094260706","87804017763851","9893638773","944421458","12946485799","1253120826","76280946" } local SOUNDS = { "140325083438865","132151829764277","5507830073", "3739363791" } local TORSO_SOUNDS = { "8164951181","132080416777849" } local HEADSHOT_SOUND = "132110078840319" local HEADSHOT_KILL_SOUNDS = { "119851057500597","133002449941130" } local EXPLOSION_DEATH_SOUND= "113697743345102" local SCREAM_SOUNDS = { "140729021718836","136401198004658","112398446636056","6108565657","3607577766" } local CHOKE_SOUNDS = { "418658161","82687386744947","9113800060" } local DEATH_FACE_IDS = { "515628541","5065838007","476060646" } local BONE_CRUNCH_SOUNDS = { "132151829764277","5507830073","9113800060" } local MEAT_TEAR_SOUNDS = { "140325083438865","132080416777849" } local SQUELCH_SOUNDS = { "8164951181","132080416777849" } local GURGLE_SOUNDS = { "6108565657","3607577766" } local HEARTBEAT_SOUND = "rbxassetid://102690042774375" local MAX_POOL_SIZE = 100 local HEAVY_HIT_THRESHOLD = 15 local RAGDOLL_SETTLE_DELAY = 0.35 local FLYING_SPLAT_MIN_SIZE = 1.6 local FLYING_SPLAT_MAX_SIZE = 2.8 local PUDDLE_MIN_SIZE = 0.9 local PUDDLE_MAX_SIZE = 2.3 local MICRO_PUDDLES_ENABLED = true local SCREEN_BLOOD_ENABLED = false local CAMERA_SHAKE_ENABLED = true local GIBS_ENABLED = true local BASE_MAX_GENERATED_OBJECTS = 350 local BASE_MAX_ACTIVE_BLOOD_DROPS = 25 local BASE_BLOOD_DECAL_LIMIT_PER_PART = 6 local BASE_MAX_RAGDOLLS = 20 local BASE_VISUAL_BUDGET_PER_SECOND = 55 local BASE_MIN_SPAWN_INTERVAL = 0.28 local BASE_IMPACT_PARTICLES_MIN = 6 local BASE_IMPACT_PARTICLES_MAX = 12 local BASE_HEAVY_IMPACT_PARTICLES_MIN = 12 local BASE_HEAVY_IMPACT_PARTICLES_MAX = 20 local BASE_HEAVY_CHAR_THRESHOLD = 12 local newPartsFolder = workspace:FindFirstChild("BloodParticles") if not newPartsFolder then newPartsFolder = Instance.new("Folder") newPartsFolder.Name = "BloodParticles" newPartsFolder.Parent = workspace end local dynamic = {} local function computeScale(playerCount) if playerCount <= 1 then return 1.6 elseif playerCount <= 3 then return 1.3 elseif playerCount <= 6 then return 1.0 elseif playerCount <= 10 then return 0.7 elseif playerCount <= 16 then return 0.5 elseif playerCount <= 25 then return 0.35 elseif playerCount <= 30 then return 0.22 elseif playerCount <= 40 then return 0.16 elseif playerCount <= 50 then return 0.12 else return 0.08 end end local lastScale = -1 local lastPlayerCount = -1 local function refreshDynamicLimits(silent) local n = #Players:GetPlayers() local scale = unlimitedMode and 1.6 or computeScale(n) dynamic.playerCount = n dynamic.scale = scale if unlimitedMode then dynamic.MAX_GENERATED_OBJECTS = 1000000000 dynamic.MAX_ACTIVE_BLOOD_DROPS = 1000000000 dynamic.BLOOD_DECAL_LIMIT_PER_PART = 1000000000 dynamic.MAX_RAGDOLLS = 1000000000 dynamic.VISUAL_BUDGET_PER_SECOND = 1000000000 dynamic.MIN_SPAWN_INTERVAL = 0 dynamic.MIN_SPAWN_INTERVAL_HEAVY = 0 dynamic.IMPACT_PARTICLES_MIN = BASE_IMPACT_PARTICLES_MIN dynamic.IMPACT_PARTICLES_MAX = BASE_IMPACT_PARTICLES_MAX dynamic.HEAVY_IMPACT_PARTICLES_MIN = BASE_HEAVY_IMPACT_PARTICLES_MIN dynamic.HEAVY_IMPACT_PARTICLES_MAX = BASE_HEAVY_IMPACT_PARTICLES_MAX dynamic.HEAVY_CHAR_THRESHOLD = 1000000000 dynamic.MAX_EFFECT_DISTANCE = 1000000000 dynamic.MAX_EFFECT_DISTANCE_SQ = 1e18 dynamic.V4_RAY_BUDGET = 1000000000 dynamic.V4_SCAN_BUDGET = 1000000000 dynamic.DROP_RAY_BUDGET = 1000000000 else dynamic.MAX_GENERATED_OBJECTS = math.floor(BASE_MAX_GENERATED_OBJECTS * scale + 60) dynamic.MAX_ACTIVE_BLOOD_DROPS = math.max(4, math.floor(BASE_MAX_ACTIVE_BLOOD_DROPS * scale + 5)) dynamic.BLOOD_DECAL_LIMIT_PER_PART = math.max(2, math.floor(BASE_BLOOD_DECAL_LIMIT_PER_PART * scale + 1)) dynamic.MAX_RAGDOLLS = math.max(4, math.floor(BASE_MAX_RAGDOLLS * scale + 4)) dynamic.VISUAL_BUDGET_PER_SECOND = math.floor(BASE_VISUAL_BUDGET_PER_SECOND * scale + 15) dynamic.MIN_SPAWN_INTERVAL = math.max(0.12, BASE_MIN_SPAWN_INTERVAL / math.max(scale, 0.5)) dynamic.MIN_SPAWN_INTERVAL_HEAVY = dynamic.MIN_SPAWN_INTERVAL * 2 dynamic.IMPACT_PARTICLES_MIN = math.max(3, math.floor(BASE_IMPACT_PARTICLES_MIN * scale)) dynamic.IMPACT_PARTICLES_MAX = math.max(5, math.floor(BASE_IMPACT_PARTICLES_MAX * scale)) dynamic.HEAVY_IMPACT_PARTICLES_MIN = math.max(5, math.floor(BASE_HEAVY_IMPACT_PARTICLES_MIN * scale)) dynamic.HEAVY_IMPACT_PARTICLES_MAX = math.max(8, math.floor(BASE_HEAVY_IMPACT_PARTICLES_MAX * scale)) dynamic.HEAVY_CHAR_THRESHOLD = math.max(6, math.floor(BASE_HEAVY_CHAR_THRESHOLD * math.min(scale, 1.5))) dynamic.MAX_EFFECT_DISTANCE = math.floor(70 + 80 * math.min(scale, 1.6)) dynamic.MAX_EFFECT_DISTANCE_SQ = dynamic.MAX_EFFECT_DISTANCE * dynamic.MAX_EFFECT_DISTANCE if n <= 25 then dynamic.V4_RAY_BUDGET = 48 dynamic.V4_SCAN_BUDGET = 96 dynamic.DROP_RAY_BUDGET = 30 else dynamic.V4_RAY_BUDGET = math.max(10, math.floor(48 * scale / 0.35)) dynamic.V4_SCAN_BUDGET = math.max(32, math.floor(96 * scale / 0.35)) dynamic.DROP_RAY_BUDGET = math.max(12, math.floor(30 * scale / 0.35)) end end if not silent and (lastScale ~= scale or lastPlayerCount ~= n) then lastScale = scale lastPlayerCount = n print(string.format("[BloodFX] players=%d scale=%.2f | objects=%d drops=%d decals=%d ragdolls=%d budget=%d distance=%d interval=%.2f", n, scale, dynamic.MAX_GENERATED_OBJECTS, dynamic.MAX_ACTIVE_BLOOD_DROPS, dynamic.BLOOD_DECAL_LIMIT_PER_PART, dynamic.MAX_RAGDOLLS, dynamic.VISUAL_BUDGET_PER_SECOND, dynamic.MAX_EFFECT_DISTANCE, dynamic.MIN_SPAWN_INTERVAL)) end end refreshDynamicLimits(true) Players.PlayerAdded:Connect(function() task.defer(refreshDynamicLimits) end) Players.PlayerRemoving:Connect(function() task.defer(refreshDynamicLimits) end) task.spawn(function() while true do task.wait(3) refreshDynamicLimits() end end) local visualBudget = dynamic.VISUAL_BUDGET_PER_SECOND local lastBudgetReset = os.clock() local function refreshBudgetIfNeeded() local now = os.clock() if now - lastBudgetReset >= 1 then lastBudgetReset = now visualBudget = dynamic.VISUAL_BUDGET_PER_SECOND end end local function consumeBudget(n) if unlimitedMode then return true end n = n or 1 refreshBudgetIfNeeded() if visualBudget < n then return false end visualBudget -= n return true end local cachedCameraPosition = nil local cachedCameraTime = 0 local CACHE_CAMERA_INTERVAL = 0.08 local function getCachedCameraPosition() local now = os.clock() if cachedCameraPosition and (now - cachedCameraTime) < CACHE_CAMERA_INTERVAL then return cachedCameraPosition end local cam = workspace.CurrentCamera if not cam then cachedCameraPosition = nil return nil end cachedCameraPosition = cam.CFrame.Position cachedCameraTime = now return cachedCameraPosition end local function isFarFromCamera(pos) if unlimitedMode then return false end local camPos = getCachedCameraPosition() if not camPos then return false end return (camPos - pos).Magnitude > dynamic.MAX_EFFECT_DISTANCE end local bloodSettings = { Duration = 20, MaxDecals = 90 } local characterModels = setmetatable({}, {__mode = "k"}) local ragdollModels = setmetatable({}, {__mode = "k"}) local characterModelListCache = {} local characterModelListDirty = true local modelPartsCache = setmetatable({}, {__mode = "k"}) local modelPartsCacheDirty = setmetatable({}, {__mode = "k"}) local function invalidateCharacterModelList() characterModelListDirty = true end local function registerCharacterModelCached(model) if model then characterModels[model] = true invalidateCharacterModelList() modelPartsCacheDirty[model] = true end end local function unregisterCharacterModelCached(model) if model then characterModels[model] = nil invalidateCharacterModelList() modelPartsCache[model] = nil modelPartsCacheDirty[model] = nil end end local function registerRagdollCached(model) if model then ragdollModels[model] = true modelPartsCacheDirty[model] = true end end local function unregisterRagdollCached(model) if model then ragdollModels[model] = nil modelPartsCache[model] = nil modelPartsCacheDirty[model] = nil end end local function getCachedModelParts(model) if not model then return {} end if not modelPartsCacheDirty[model] and modelPartsCache[model] then return modelPartsCache[model] end local parts = {} for _, obj in ipairs(model:GetDescendants()) do if obj:IsA("BasePart") then parts[#parts + 1] = obj end end modelPartsCache[model] = parts modelPartsCacheDirty[model] = false return parts end local function invalidateModelPartsCache(model) if model then modelPartsCacheDirty[model] = true end end local COLLISION_GROUP_CHARACTER = "BloodCharacter" local COLLISION_GROUP_RAGDOLL = "BloodRagdoll" local function setupCollisionGroups() pcall(function() PhysicsService:RegisterCollisionGroup(COLLISION_GROUP_CHARACTER) end) pcall(function() PhysicsService:RegisterCollisionGroup(COLLISION_GROUP_RAGDOLL) end) pcall(function() PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP_CHARACTER, COLLISION_GROUP_CHARACTER, true) end) pcall(function() PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP_RAGDOLL, COLLISION_GROUP_RAGDOLL, true) end) pcall(function() PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP_RAGDOLL, COLLISION_GROUP_CHARACTER, true) end) pcall(function() PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP_CHARACTER, COLLISION_GROUP_RAGDOLL, true) end) pcall(function() PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP_RAGDOLL, "Default", true) end) pcall(function() PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP_CHARACTER, "Default", true) end) end setupCollisionGroups() local function setCollisionGroupSafe(part, group) if not part or not part:IsA("BasePart") then return end pcall(function() part.CollisionGroup = group end) end local function applyCharacterCollisionGroup(inst) if not inst then return end if inst:IsA("BasePart") then setCollisionGroupSafe(inst, COLLISION_GROUP_CHARACTER) end for _, d in ipairs(getCachedModelParts(inst)) do setCollisionGroupSafe(d, COLLISION_GROUP_CHARACTER) end end local function applyRagdollCollisionGroup(inst) if not inst then return end if inst:IsA("BasePart") then setCollisionGroupSafe(inst, COLLISION_GROUP_RAGDOLL) end for _, d in ipairs(getCachedModelParts(inst)) do setCollisionGroupSafe(d, COLLISION_GROUP_RAGDOLL) end end local generatedObjectCount = #newPartsFolder:GetChildren() newPartsFolder.ChildAdded:Connect(function() generatedObjectCount += 1 end) newPartsFolder.ChildRemoved:Connect(function() generatedObjectCount = math.max(0, generatedObjectCount - 1) end) local function countWorkspaceParts() return generatedObjectCount end local function isWorkspaceSaturated() if unlimitedMode then return false end return countWorkspaceParts() >= dynamic.MAX_GENERATED_OBJECTS end local getAllCharacterModels local function isHeavyLoad() if unlimitedMode then return false end if countWorkspaceParts() > dynamic.MAX_GENERATED_OBJECTS * 0.5 then return true end if getAllCharacterModels and #getAllCharacterModels() >= dynamic.HEAVY_CHAR_THRESHOLD then return true end return false end local recentExplosions = {} workspace.DescendantAdded:Connect(function(obj) if obj:IsA("Explosion") then local cam = workspace.CurrentCamera if cam and (cam.CFrame.Position - obj.Position).Magnitude > dynamic.MAX_EFFECT_DISTANCE + 30 then return end local expData = {position = obj.Position, radius = obj.BlastRadius} table.insert(recentExplosions, expData) task.delay(2, function() for i, v in ipairs(recentExplosions) do if v == expData then table.remove(recentExplosions, i) break end end end) end end) -- =============================================== -- АКСЕССУАРЫ: фильтр на пропуск кровяных эффектов -- =============================================== local function isAccessoryOrToolPart(inst) if not inst then return false end local current = inst while current and current ~= workspace do if current:IsA("Accessory") or current:IsA("Tool") then return true end current = current.Parent end return false end -- =============================================== -- HIDE HEAD ACCESSORIES — новая функция -- Делает прозрачными аксессуары, привязанные к голове -- =============================================== local function isAccessoryAttachedToHead(accessory, head) if not accessory or not head then return false end local handle = accessory:FindFirstChild("Handle") if not handle or not handle:IsA("BasePart") then return false end for _, w in ipairs(handle:GetChildren()) do if w:IsA("Weld") or w:IsA("Motor6D") or w:IsA("WeldConstraint") then if w.Part0 == head or w.Part1 == head then return true end end end if (handle.Position - head.Position).Magnitude < 1.5 then return true end return false end local function hideAccessoriesOnHead(character) if not character then return end local head = character:FindFirstChild("Head") if not head then return end local function hideAccessoryInstance(acc) if not acc then return end for _, d in ipairs(acc:GetDescendants()) do if d:IsA("BasePart") then d.Transparency = 1 d.CanCollide = false d.CanQuery = false d.CanTouch = false elseif d:IsA("Decal") or d:IsA("Texture") then d.Transparency = 1 elseif d:IsA("ParticleEmitter") then d.Enabled = false elseif d:IsA("Trail") then d.Enabled = false elseif d:IsA("BillboardGui") or d:IsA("SurfaceGui") then d.Enabled = false end end end for _, obj in ipairs(character:GetDescendants()) do if obj:IsA("Accessory") then if isAccessoryAttachedToHead(obj, head) then hideAccessoryInstance(obj) end end end -- На случай, если аксессуары лежат прямо под Head for _, child in ipairs(head:GetChildren()) do if child:IsA("Accessory") then hideAccessoryInstance(child) end end end -- =============================================== -- v12.4: аксессуары не свариваются к телу -- =============================================== local function preserveAccessoriesOnDeath(char) return end -- Прячет ТОЛЬКО голову (её декали/партиклы/части) И аксессуары на голове local function hideHeadAndItsAccessories(char) if not char or not char.Parent then return end local head = char:FindFirstChild("Head") if not head then return end head.Transparency = 1 head.CanCollide = false head.CanQuery = false head.CanTouch = false for _, child in ipairs(head:GetDescendants()) do if child:IsA("Decal") or child:IsA("Texture") then child.Transparency = 1 elseif child:IsA("ParticleEmitter") then if child.Name ~= "NeckBloodEmitter" then child.Enabled = false end elseif child:IsA("BasePart") then if not isAccessoryOrToolPart(child) then child.Transparency = 1 child.CanCollide = false child.CanQuery = false child.CanTouch = false end end end -- НОВОЕ: скрываем аксессуары на голове hideAccessoriesOnHead(char) end -- =============================================== -- NECK STUMP BLOOD — декали + эмиттер на ВЕРХУ торса -- =============================================== local function spawnNeckStumpBlood(char) if not char or not char.Parent then return end local torso = char:FindFirstChild("UpperTorso") or char:FindFirstChild("Torso") if not torso or not torso:IsA("BasePart") then return end local numDecals = math.random(4, 6) for i = 1, numDecals do local decal = Instance.new("Decal") decal.Name = "BloodDecal" decal.Texture = "rbxassetid://" .. BLOODSIDS[math.random(1, #BLOODSIDS)] decal.Face = Enum.NormalId.Top decal.Transparency = 1 decal.Color3 = Color3.new(1, 1, 1) decal.Parent = torso TweenService:Create(decal, TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Transparency = 0}):Play() end if not torso:FindFirstChild("NeckStumpBleed") then local emitter = Instance.new("ParticleEmitter") emitter.Name = "NeckStumpBleed" emitter.Texture = BLOOD_TEXTURE emitter.Color = ColorSequence.new(BLOOD_PARTICLE_HI, BLOOD_PARTICLE_LO) emitter.Lifetime = NumberRange.new(0.35, 0.85) emitter.Rate = 5 emitter.Speed = NumberRange.new(2, 8) emitter.SpreadAngle = Vector2.new(70, 70) emitter.Rotation = NumberRange.new(0, 360) emitter.RotSpeed = NumberRange.new(-140, 140) emitter.LightEmission = 0 emitter.Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.1), NumberSequenceKeypoint.new(0.7, 0.35), NumberSequenceKeypoint.new(1, 1), }) emitter.Size = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.14), NumberSequenceKeypoint.new(0.5, 0.07), NumberSequenceKeypoint.new(1, 0.01), }) emitter.Drag = 3 emitter.Acceleration = Vector3.new(0, -28, 0) emitter.VelocityInheritance = 0.15 emitter.Parent = torso end end local function isPartOfCharacter(part) if not part then return false end local current = part while current do if current:IsA("Humanoid") then return true end if current:IsA("Model") and current:FindFirstChildOfClass("Humanoid") then if characterModels[current] then return true end if not ragdollModels[current] and not current:GetAttribute("IsClientRagdoll") then return true end end if current:IsA("Tool") or current:IsA("Accessory") then return true end current = current.Parent end return false end getAllCharacterModels = function() if not characterModelListDirty then return characterModelListCache end table.clear(characterModelListCache) for char in pairs(characterModels) do if char and char.Parent then characterModelListCache[#characterModelListCache + 1] = char end end characterModelListDirty = false return characterModelListCache end local function setupSound(sound, maxDistance) sound.RollOffMode = Enum.RollOffMode.InverseTapered sound.MaxDistance = maxDistance or 250 sound.Volume = 1.2 end local function playScream(character, soundId, volumeOverride) if not character then return end local head = character:FindFirstChild("Head") if not head then return end if isFarFromCamera(head.Position) then return end local existing = head:FindFirstChild("ScreamSound") if existing then local playedAt = existing:GetAttribute("PlayedAt") if playedAt and (os.clock() - playedAt) < 0.15 then return end existing:Destroy() end local crySound = Instance.new("Sound") crySound.Name = "ScreamSound" setupSound(crySound, 80) crySound.Volume = volumeOverride or 1.0 crySound.PlaybackSpeed = 0.9 + math.random() * 0.25 crySound.SoundId = "rbxassetid://" .. soundId crySound.Parent = head crySound:SetAttribute("PlayedAt", os.clock()) crySound:Play() Debris:AddItem(crySound, 5) end local function playHitSoundOn(part, soundId, volumeOverride, pitchOverride) if not part or not part.Parent then return end if isAccessoryOrToolPart(part) then return end if isFarFromCamera(part.Position) then return end local s = Instance.new("Sound") s.Name = "HitSound" setupSound(s) if volumeOverride then s.Volume = volumeOverride end if pitchOverride then s.PlaybackSpeed = pitchOverride end s.SoundId = "rbxassetid://" .. soundId s.Parent = part s:Play() Debris:AddItem(s, 5) end local function playGoreSound(part, heavy) if not part or not part.Parent then return end if isAccessoryOrToolPart(part) then return end if isFarFromCamera(part.Position) then return end for _, child in ipairs(part:GetChildren()) do if child:IsA("Sound") and string.sub(child.Name, 1, 9) == "GoreLayer" then child:Destroy() end end if math.random() > 0.6 then return end local layers = {} if heavy then if math.random() < 0.7 then table.insert(layers, {id = BONE_CRUNCH_SOUNDS[math.random(1, #BONE_CRUNCH_SOUNDS)], vol = 1.4, pitch = 0.85 + math.random() * 0.35}) end if math.random() < 0.8 then table.insert(layers, {id = MEAT_TEAR_SOUNDS[math.random(1, #MEAT_TEAR_SOUNDS)], vol = 1.2, pitch = 1.0 + math.random() * 0.35}) end end if math.random() < 0.5 then table.insert(layers, {id = SQUELCH_SOUNDS[math.random(1, #SQUELCH_SOUNDS)], vol = 1.0, pitch = 1.1 + math.random() * 0.4}) end if #layers == 0 then return end for i, layer in ipairs(layers) do local s = Instance.new("Sound") s.Name = "GoreLayer" .. i setupSound(s, 150) s.Volume = layer.vol s.PlaybackSpeed = layer.pitch s.SoundId = "rbxassetid://" .. layer.id s.Parent = part s:Play() Debris:AddItem(s, 3) end end local DEATH_VOICE_POOL = {} for _, id in ipairs(SCREAM_SOUNDS) do table.insert(DEATH_VOICE_POOL, {id = id, weight = 5}) end for _, id in ipairs(CHOKE_SOUNDS) do table.insert(DEATH_VOICE_POOL, {id = id, weight = 2}) end for _, id in ipairs(GURGLE_SOUNDS) do table.insert(DEATH_VOICE_POOL, {id = id, weight = 2}) end local function pickDeathVoiceId() local totalWeight = 0 for _, entry in ipairs(DEATH_VOICE_POOL) do totalWeight += entry.weight end if totalWeight <= 0 then return SCREAM_SOUNDS[1] end local r = math.random() * totalWeight for _, entry in ipairs(DEATH_VOICE_POOL) do r -= entry.weight if r <= 0 then return entry.id end end return DEATH_VOICE_POOL[1].id end local function playDeathVoice(character) if not character then return end local head = character:FindFirstChild("Head") if not head then return end if isFarFromCamera(head.Position) then return end local existing = head:FindFirstChild("ScreamSound") if existing then existing:Destroy() end local soundId = pickDeathVoiceId() local crySound = Instance.new("Sound") crySound.Name = "ScreamSound" setupSound(crySound, 100) crySound.Volume = 1.3 crySound.PlaybackSpeed = 0.85 + math.random() * 0.3 crySound.SoundId = "rbxassetid://" .. soundId crySound.Parent = head crySound:SetAttribute("PlayedAt", os.clock()) crySound:Play() Debris:AddItem(crySound, 5) if math.random() < 0.35 then task.delay(0.12, function() if not head or not head.Parent then return end local layerId = CHOKE_SOUNDS[math.random(1, #CHOKE_SOUNDS)] local layer = Instance.new("Sound") layer.Name = "DeathLayer" setupSound(layer, 80) layer.Volume = 0.85 layer.PlaybackSpeed = 0.85 + math.random() * 0.3 layer.SoundId = "rbxassetid://" .. layerId layer.Parent = head layer:Play() Debris:AddItem(layer, 5) end) end end local function hasDynamicFace(character) local head = character and character:FindFirstChild("Head") if not head then return false end if head:FindFirstChildOfClass("FaceControls") then return true end for _, child in ipairs(head:GetChildren()) do if child:IsA("Script") or child:IsA("LocalScript") then if string.find(string.lower(child.Name), "face") then return true end end end return false end local function changeFace(character) if hasDynamicFace(character) then return end local head = character:FindFirstChild("Head") if not head then return end if head:GetAttribute("DeadFaceApplied") then return end head:SetAttribute("DeadFaceApplied", true) local faceId = DEATH_FACE_IDS[math.random(1, #DEATH_FACE_IDS)] local texture = "rbxassetid://" .. faceId local faceDecal = head:FindFirstChild("face") or head:FindFirstChild("Face") if faceDecal and faceDecal:IsA("Decal") then faceDecal.Texture = texture else local newDecal = Instance.new("Decal") newDecal.Name = "face" newDecal.Face = Enum.NormalId.Front newDecal.Texture = texture newDecal.Parent = head end end local function getTorsoPart(char) if not char then return nil end return char:FindFirstChild("Torso") or char:FindFirstChild("UpperTorso") or char:FindFirstChild("HumanoidRootPart") or char:FindFirstChild("Head") end local function getFallbackHitPart(char) if not char then return nil end return char:FindFirstChild("Torso") or char:FindFirstChild("UpperTorso") or char:FindFirstChild("HumanoidRootPart") or char:FindFirstChild("Head") end local function findNearestVisibleBodyPart(charModel, worldPos) if not charModel or not worldPos then return nil end local bestPart, bestDist = nil, math.huge for _, limb in ipairs(getCachedModelParts(charModel)) do if limb.Name ~= "HumanoidRootPart" and limb.Transparency < 1 and not isAccessoryOrToolPart(limb) then local dist = (limb.Position - worldPos).Magnitude if dist < bestDist then bestDist = dist bestPart = limb end end end return bestPart end local screenBloodGui local function ensureScreenBloodGui() if not SCREEN_BLOOD_ENABLED then return nil end if screenBloodGui and screenBloodGui.Parent then return screenBloodGui end local gui = player:WaitForChild("PlayerGui") local existing = gui:FindFirstChild("BloodScreenGui") if existing then existing:Destroy() end screenBloodGui = Instance.new("ScreenGui") screenBloodGui.Name = "BloodScreenGui" screenBloodGui.ResetOnSpawn = false screenBloodGui.IgnoreGuiInset = true screenBloodGui.DisplayOrder = 50 screenBloodGui.Parent = gui return screenBloodGui end local function spawnScreenBlood(intensity) if not SCREEN_BLOOD_ENABLED then return end local gui = ensureScreenBloodGui() if not gui then return end local frame = Instance.new("Frame") frame.Name = "BloodSplat" frame.Size = UDim2.new(0.4 + math.random() * 0.4, 0, 0.4 + math.random() * 0.4, 0) frame.Position = UDim2.new(math.random() * 0.6, 0, math.random() * 0.6, 0) frame.BackgroundColor3 = Color3.fromRGB(120, 0, 0) frame.BackgroundTransparency = 0.5 frame.BorderSizePixel = 0 frame.ZIndex = 51 frame.Rotation = math.random(-45, 45) frame.Parent = gui local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(1, 0) corner.Parent = frame local gradient = Instance.new("UIGradient") gradient.Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.3), NumberSequenceKeypoint.new(0.7, 0.7), NumberSequenceKeypoint.new(1, 1), }) gradient.Parent = frame TweenService:Create(frame, TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {BackgroundTransparency = 0.15}):Play() task.delay(2 + math.random() * 2, function() if frame and frame.Parent then TweenService:Create(frame, TweenInfo.new(1.5), {BackgroundTransparency = 1}):Play() task.wait(1.6) if frame.Parent then frame:Destroy() end end end) end local function shakeCamera(intensity, duration) if not CAMERA_SHAKE_ENABLED then return end local cam = workspace.CurrentCamera if not cam then return end task.spawn(function() local elapsed = 0 local baseCFrame = cam.CFrame while elapsed < duration do local dt = RunService.RenderStepped:Wait() elapsed = elapsed + dt local fade = 1 - (elapsed / duration) local offset = Vector3.new( (math.random() - 0.5) * intensity * fade, (math.random() - 0.5) * intensity * fade, (math.random() - 0.5) * intensity * fade ) cam.CFrame = baseCFrame + offset end if cam then cam.CFrame = baseCFrame end end) end local Pool = {} local ActiveDrops = {} local ActiveBloodDropCount = 0 local ActiveDecalsTrack = {} local ActiveDecalSet = setmetatable({}, {__mode = "k"}) local tweenInfoIn = TweenInfo.new(0.2, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out) local tweenInfoOut = TweenInfo.new(1.5, Enum.EasingStyle.Linear, Enum.EasingDirection.Out) local function createProjectilePart() local p = Instance.new("Part") p.Name = "BlPart" p.Shape = Enum.PartType.Block p.Size = Vector3.new(0.2, 0.2, 0.2) p.Transparency = 1 p.CanCollide = false p.Massless = true p.Material = Enum.Material.SmoothPlastic p.Anchored = false p.CastShadow = false local decal = Instance.new("Decal") decal.Name = "Splatter" decal.Face = Enum.NormalId.Top decal.Transparency = 1 decal.Color3 = Color3.new(1, 1, 1) decal.Parent = p local bgui = Instance.new("BillboardGui") bgui.Name = "FlyingImage" bgui.Size = UDim2.new(2.4, 0, 2.4, 0) bgui.AlwaysOnTop = false bgui.LightInfluence = 0.5 bgui.Parent = p local img = Instance.new("ImageLabel") img.Name = "Img" img.Size = UDim2.new(1, 0, 1, 0) img.BackgroundTransparency = 1 img.ImageColor3 = Color3.new(1, 1, 1) img.Parent = bgui return p end local function GetPart() if #Pool > 0 then return table.remove(Pool) end return createProjectilePart() end local function ReturnPart(part) if not part then return end ActiveDrops[part] = nil ActiveDecalSet[part] = nil part.Anchored = false part.Transparency = 1 part.CanCollide = false part.Massless = true part.Parent = nil part.Size = Vector3.new(0.2, 0.2, 0.2) part.AssemblyLinearVelocity = Vector3.zero part.AssemblyAngularVelocity = Vector3.zero for _, child in ipairs(part:GetChildren()) do if child:IsA("WeldConstraint") then child:Destroy() end end local decal = part:FindFirstChild("Splatter") if decal then decal.Transparency = 1 decal.Color3 = Color3.new(1, 1, 1) end local bgui = part:FindFirstChild("FlyingImage") if bgui then bgui.Enabled = false end local maxPool = unlimitedMode and 1000000 or MAX_POOL_SIZE if #Pool < maxPool then table.insert(Pool, part) else part:Destroy() end end local function RegisterNewDecal(part) if ActiveDecalSet[part] then return end ActiveDecalSet[part] = true table.insert(ActiveDecalsTrack, part) if not unlimitedMode and #ActiveDecalsTrack > bloodSettings.MaxDecals then local oldestPart = table.remove(ActiveDecalsTrack, 1) ActiveDecalSet[oldestPart] = nil if oldestPart and oldestPart.Parent then if oldestPart.Name == "BlPart" then ReturnPart(oldestPart) else oldestPart:Destroy() end end end end local function createBloodMist(position, heavy) if isWorkspaceSaturated() then return end if isFarFromCamera(position) then return end if not consumeBudget(1) then return end local mistPart = Instance.new("Part") mistPart.Name = "BloodMist" mistPart.Size = Vector3.new(0.1, 0.1, 0.1) mistPart.Position = position mistPart.Anchored = true mistPart.Transparency = 1 mistPart.CanCollide = false mistPart.CanQuery = false mistPart.CanTouch = false mistPart.Parent = newPartsFolder local pe = Instance.new("ParticleEmitter") pe.Color = ColorSequence.new(BLOOD_MIST) pe.Size = NumberSequence.new({ NumberSequenceKeypoint.new(0, heavy and 0.3 or 0.2), NumberSequenceKeypoint.new(0.35, heavy and 0.55 or 0.38), NumberSequenceKeypoint.new(1, 0), }) pe.Texture = GORE_TEXTURE pe.Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.55), NumberSequenceKeypoint.new(0.35, 0.35), NumberSequenceKeypoint.new(1, 1), }) pe.Lifetime = NumberRange.new(0.25, heavy and 0.7 or 0.5) pe.Rate = 0 pe.Speed = NumberRange.new(2, heavy and 11 or 7) pe.SpreadAngle = Vector2.new(180, 180) pe.Drag = 2 pe.Parent = mistPart pe:Emit(heavy and 8 or 5) Debris:AddItem(mistPart, 1) end local function spawnGib(position, direction, size) if not GIBS_ENABLED then return end if isWorkspaceSaturated() then return end if isFarFromCamera(position) then return end if not consumeBudget(1) then return end local gib = Instance.new("Part") gib.Name = "BloodGib" gib.Shape = Enum.PartType.Ball gib.Size = Vector3.new(size, size, size) gib.Position = position gib.Color = GORE_COLOR gib.Material = Enum.Material.SmoothPlastic gib.CanCollide = false gib.CanTouch = false gib.CanQuery = false gib.Parent = newPartsFolder local dir = direction and direction.Magnitude > 0.01 and direction.Unit or Vector3.new(0,1,0) gib.AssemblyLinearVelocity = dir * math.random(20, 45) + Vector3.new( math.random(-15,15), math.random(5,20), math.random(-15,15) ) gib.AssemblyAngularVelocity = Vector3.new(math.random(-30,30), math.random(-30,30), math.random(-30,30)) Debris:AddItem(gib, 4) end local function spawnImpactBurst(position, normal, heavy, direction) if not position or isWorkspaceSaturated() then return end if isFarFromCamera(position) then return end if not consumeBudget(1) then return end local burst = Instance.new("Part") burst.Name = "BloodImpact" burst.Size = Vector3.new(0.1, 0.1, 0.1) burst.CFrame = CFrame.new(position) burst.Transparency = 1 burst.Anchored = true burst.CanCollide = false burst.CanQuery = false burst.CanTouch = false burst.Parent = newPartsFolder local emitter = Instance.new("ParticleEmitter") emitter.Name = "ImpactDroplets" emitter.Texture = BLOOD_TEXTURE emitter.Color = ColorSequence.new(BLOOD_PARTICLE_HI, BLOOD_PARTICLE_LO) emitter.LightEmission = 0 emitter.Brightness = 1 emitter.Rate = 0 emitter.Lifetime = NumberRange.new(0.2, heavy and 0.65 or 0.45) emitter.Speed = NumberRange.new(heavy and 15 or 10, heavy and 34 or 22) emitter.SpreadAngle = Vector2.new(180, 180) emitter.Drag = 3 emitter.Acceleration = Vector3.new(0, -32, 0) emitter.VelocityInheritance = 0.05 emitter.Rotation = NumberRange.new(0, 360) emitter.RotSpeed = NumberRange.new(-260, 260) emitter.Size = NumberSequence.new({ NumberSequenceKeypoint.new(0, heavy and 0.06 or 0.04), NumberSequenceKeypoint.new(0.45, heavy and 0.032 or 0.022), NumberSequenceKeypoint.new(1, 0.008), }) emitter.Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.05), NumberSequenceKeypoint.new(0.75, 0.25), NumberSequenceKeypoint.new(1, 1), }) emitter.Parent = burst if direction and direction.Magnitude > 0.01 then emitter.EmissionDirection = Enum.NormalId.Front burst.CFrame = CFrame.lookAt(position, position + direction.Unit) end local pMin, pMax if heavy then pMin, pMax = dynamic.HEAVY_IMPACT_PARTICLES_MIN, dynamic.HEAVY_IMPACT_PARTICLES_MAX pMin = pMin * 2 pMax = pMax * 2 else pMin, pMax = dynamic.IMPACT_PARTICLES_MIN, dynamic.IMPACT_PARTICLES_MAX end emitter:Emit(math.random(pMin, pMax)) Debris:AddItem(burst, 1.5) createBloodMist(position, heavy) if heavy then local gibCount = math.random(2, 4) for _ = 1, gibCount do spawnGib(position + Vector3.new(math.random(-1,1), math.random(-1,1), math.random(-1,1)), direction, math.random(15, 25) / 100) end end end local V4_HIT_WINDOW = 0.4 local HIT_WINDOW = 0.4 local Trk = {} Trk.dSet = setmetatable({}, {__mode = "k"}) Trk.dList = {} Trk.dListDirty = true Trk.dCursor = 1 Trk.dLastPos = setmetatable({}, {__mode = "k"}) Trk.dParams = setmetatable({}, {__mode = "k"}) Trk.dOwner = setmetatable({}, {__mode = "k"}) local v4HitRecords = setmetatable({}, {__mode = "k"}) local function registerDmgPoint(obj) if obj:IsA("Attachment") and obj.Name == "DmgPoint" then if not Trk.dSet[obj] then Trk.dSet[obj] = true Trk.dListDirty = true end end end for _, obj in ipairs(workspace:GetDescendants()) do registerDmgPoint(obj) end workspace.DescendantAdded:Connect(registerDmgPoint) local function getV4OwnerRoot(attachment) local current = attachment while current and current ~= workspace do if current:IsA("Tool") then return current end if current:IsA("Model") and current:FindFirstChildOfClass("Humanoid") then return current end current = current.Parent end return nil end local function getV4Params(att) local owner = getV4OwnerRoot(att) local cached = Trk.dParams[att] if cached and Trk.dOwner[att] == owner then return cached end local exclude = {newPartsFolder} if owner then table.insert(exclude, owner) end local params = RaycastParams.new() params.FilterType = Enum.RaycastFilterType.Exclude params.FilterDescendantsInstances = exclude params.IgnoreWater = true Trk.dParams[att] = params Trk.dOwner[att] = owner return params end local function recordV4Hit(result, directionUnit, now) local hitPart = result.Instance if not hitPart or not hitPart:IsA("BasePart") then return end local recordPart = hitPart if isAccessoryOrToolPart(hitPart) then local current = hitPart while current and current ~= workspace do if characterModels[current] then local mapped = findNearestVisibleBodyPart(current, result.Position) if mapped then recordPart = mapped end break end current = current.Parent end if recordPart == hitPart then return end end if recordPart.Name == "HumanoidRootPart" then local current = recordPart while current and current ~= workspace do if characterModels[current] then local mapped = findNearestVisibleBodyPart(current, result.Position) if mapped then recordPart = mapped end break end current = current.Parent end end local current = recordPart while current and current ~= workspace do if characterModels[current] then if not v4HitRecords[current] then v4HitRecords[current] = {} end local records = v4HitRecords[current] records[#records + 1] = { part = recordPart, pos = result.Position, normal = result.Normal, dir = directionUnit, time = now, } while #records > 8 do table.remove(records, 1) end return end current = current.Parent end end Trk.tSet = setmetatable({}, {__mode = "k"}) Trk.tList = {} Trk.tListDirty = true Trk.tCursor = 1 Trk.tLastPos = setmetatable({}, {__mode = "k"}) Trk.tParams = setmetatable({}, {__mode = "k"}) Trk.tOwner = setmetatable({}, {__mode = "k"}) local function registerToolPart(obj) if not obj:IsA("BasePart") then return end local current = obj while current and current ~= workspace do if current:IsA("Tool") then if not Trk.tSet[obj] then Trk.tSet[obj] = true Trk.tListDirty = true end return end current = current.Parent end end for _, obj in ipairs(workspace:GetDescendants()) do registerToolPart(obj) end workspace.DescendantAdded:Connect(registerToolPart) Trk.TRACK_TIME = 3 Trk.MIN_SPEED = 25 Trk.MAX_SIZE = 4 Trk.pSet = setmetatable({}, {__mode = "k"}) Trk.pList = {} Trk.pListDirty = true Trk.pCursor = 1 Trk.pLastPos = setmetatable({}, {__mode = "k"}) Trk.pDeadline = setmetatable({}, {__mode = "k"}) Trk.pParams = setmetatable({}, {__mode = "k"}) Trk.IGNORE_NAMES = { ["Blood"] = true, ["BloodPuddle"] = true, ["BloodDrop"] = true, ["BloodSplat"] = true, ["BlPart"] = true, ["BloodPool"] = true, ["CP"] = true, ["BloodMist"] = true, ["BloodImpact"] = true, ["BloodMicroPuddle"] = true, ["BloodGib"] = true, ["ArterialSpray"] = true, ["Collision"] = true, ["Baseplate"] = true, } local function registerProjectile(obj) if not obj or not obj:IsA("BasePart") then return end if obj.Anchored then return end if Trk.IGNORE_NAMES[obj.Name] then return end if obj.Size.X > Trk.MAX_SIZE or obj.Size.Y > Trk.MAX_SIZE or obj.Size.Z > Trk.MAX_SIZE then return end if Trk.pSet[obj] then return end Trk.pSet[obj] = true Trk.pLastPos[obj] = obj.Position Trk.pDeadline[obj] = os.clock() + Trk.TRACK_TIME Trk.pListDirty = true end local function unregisterProjectile(obj) Trk.pSet[obj] = nil Trk.pLastPos[obj] = nil Trk.pDeadline[obj] = nil Trk.pParams[obj] = nil Trk.pListDirty = true end workspace.DescendantAdded:Connect(registerProjectile) workspace.DescendantRemoving:Connect(function(obj) if not Trk.pSet[obj] then return end if not obj:IsA("BasePart") then return end local origin = Trk.pLastPos[obj] if origin then local direction = obj.Position - origin if direction.Magnitude > 0.05 then local params = Trk.pParams[obj] if not params then params = RaycastParams.new() params.FilterType = Enum.RaycastFilterType.Exclude params.FilterDescendantsInstances = {newPartsFolder} params.IgnoreWater = true Trk.pParams[obj] = params end local result = workspace:Raycast(origin, direction, params) if result then recordV4Hit(result, direction.Unit, os.clock()) end end end unregisterProjectile(obj) end) task.spawn(function() while true do task.wait(0.5) for _, obj in ipairs(workspace:GetChildren()) do if obj:IsA("BasePart") then registerProjectile(obj) elseif obj:IsA("Folder") then for _, child in ipairs(obj:GetChildren()) do if child:IsA("BasePart") then registerProjectile(child) end end end end end end) RunService.Heartbeat:Connect(function() local now = os.clock() local rayBudget = dynamic.V4_RAY_BUDGET if Trk.pListDirty then table.clear(Trk.pList) for obj in pairs(Trk.pSet) do if obj and obj.Parent then Trk.pList[#Trk.pList + 1] = obj end end Trk.pListDirty = false Trk.pCursor = math.min(Trk.pCursor, math.max(1, #Trk.pList)) end local count = #Trk.pList if count == 0 then return end local scanned = 0 while scanned < math.min(dynamic.V4_SCAN_BUDGET, count) and rayBudget > 0 do if Trk.pCursor > count then Trk.pCursor = 1 end local obj = Trk.pList[Trk.pCursor] Trk.pCursor += 1 scanned += 1 if obj and obj.Parent then if now > (Trk.pDeadline[obj] or 0) or obj.Anchored then unregisterProjectile(obj) else local origin = Trk.pLastPos[obj] if origin then local currentPos = obj.Position local vel = obj.AssemblyLinearVelocity local direction = currentPos - origin + vel * 0.05 if direction.Magnitude > 0.05 then local speed = vel.Magnitude if speed >= Trk.MIN_SPEED then local params = Trk.pParams[obj] if not params then params = RaycastParams.new() params.FilterType = Enum.RaycastFilterType.Exclude params.FilterDescendantsInstances = {newPartsFolder} params.IgnoreWater = true Trk.pParams[obj] = params end rayBudget -= 1 local result = workspace:Raycast(origin, direction, params) if result then recordV4Hit(result, direction.Unit, now) end end Trk.pLastPos[obj] = currentPos end else Trk.pLastPos[obj] = obj.Position end end else unregisterProjectile(obj) end end end) local function processV4TrackerList(list, cursor, kind, now, rayBudget) local count = #list if count == 0 then if kind == "dmg" then Trk.dCursor = 1 else Trk.tCursor = 1 end return 1, rayBudget end if rayBudget <= 0 then return cursor, rayBudget end local scanned = 0 while scanned < math.min(dynamic.V4_SCAN_BUDGET, count) and rayBudget > 0 do if cursor > count then cursor = 1 end local obj = list[cursor] cursor += 1 scanned += 1 if obj and obj.Parent then local origin = kind == "dmg" and obj.WorldPosition or obj.Position local lastPos = kind == "dmg" and Trk.dLastPos[obj] or Trk.tLastPos[obj] if not lastPos then lastPos = origin end local direction = origin - lastPos if direction.Magnitude > 0.1 then rayBudget -= 1 local params if kind == "dmg" then params = getV4Params(obj) else local owner = getV4OwnerRoot(obj) params = Trk.tParams[obj] if not params or Trk.tOwner[obj] ~= owner then local exclude = {newPartsFolder} if owner then table.insert(exclude, owner) end params = RaycastParams.new() params.FilterType = Enum.RaycastFilterType.Exclude params.FilterDescendantsInstances = exclude params.IgnoreWater = true Trk.tParams[obj] = params Trk.tOwner[obj] = owner end end local result = workspace:Raycast(origin, direction, params) if result then recordV4Hit(result, direction.Unit, now) end end if kind == "dmg" then Trk.dLastPos[obj] = origin else Trk.tLastPos[obj] = origin end else if kind == "dmg" then Trk.dSet[obj] = nil Trk.dLastPos[obj] = nil Trk.dParams[obj] = nil Trk.dOwner[obj] = nil Trk.dListDirty = true else Trk.tSet[obj] = nil Trk.tLastPos[obj] = nil Trk.tParams[obj] = nil Trk.tOwner[obj] = nil Trk.tListDirty = true end end end return cursor, rayBudget end RunService.Heartbeat:Connect(function() local now = os.clock() local rayBudget = dynamic.V4_RAY_BUDGET if Trk.dListDirty then table.clear(Trk.dList) for att in pairs(Trk.dSet) do if att and att.Parent then Trk.dList[#Trk.dList + 1] = att end end Trk.dListDirty = false Trk.dCursor = math.min(Trk.dCursor, math.max(1, #Trk.dList)) end if Trk.tListDirty then table.clear(Trk.tList) for part in pairs(Trk.tSet) do if part and part.Parent then Trk.tList[#Trk.tList + 1] = part end end Trk.tListDirty = false Trk.tCursor = math.min(Trk.tCursor, math.max(1, #Trk.tList)) end Trk.dCursor, rayBudget = processV4TrackerList(Trk.dList, Trk.dCursor, "dmg", now, rayBudget) Trk.tCursor, rayBudget = processV4TrackerList(Trk.tList, Trk.tCursor, "tool", now, rayBudget) end) RunService.Heartbeat:Connect(function(dt) local toRemove = {} local rayBudget = dynamic.DROP_RAY_BUDGET for part, data in pairs(ActiveDrops) do if rayBudget <= 0 then break end local ok = pcall(function() if not part or not part.Parent then toRemove[part] = true return end local currentPos = part.Position local displacement = currentPos - data.lastPos local dist = displacement.Magnitude if dist > 0.05 then rayBudget -= 1 local raycast = workspace:Raycast(data.lastPos, displacement, data.params) if raycast then data:Impact(raycast) toRemove[part] = true else data.lastPos = currentPos end end if not toRemove[part] and part.AssemblyLinearVelocity.Magnitude < 0.1 then local downRay = workspace:Raycast(part.Position, Vector3.new(0, -1, 0), data.params) if downRay then data:Impact(downRay) else ReturnPart(part) end toRemove[part] = true end end) if not ok then pcall(ReturnPart, part) toRemove[part] = true end end for part in pairs(toRemove) do ActiveDrops[part] = nil end end) local bloodService = {} function bloodService.CreateBlood(anchorPart, parent, rate, particles, hitDirection, spawnMist) if not anchorPart or not anchorPart:IsA("BasePart") or not particles then return end if isAccessoryOrToolPart(anchorPart) then return end if isWorkspaceSaturated() then return end if isFarFromCamera(anchorPart.Position) then return end local heavy = isHeavyLoad() particles = math.clamp(particles, 1, heavy and 3 or 6) local excluded = {parent, newPartsFolder} for _, c in ipairs(getAllCharacterModels()) do table.insert(excluded, c) end for ragdoll in pairs(ragdollModels) do if ragdoll and ragdoll.Parent then table.insert(excluded, ragdoll) end end local rayParams = RaycastParams.new() rayParams.FilterType = Enum.RaycastFilterType.Exclude rayParams.FilterDescendantsInstances = excluded rayParams.IgnoreWater = true rayParams.RespectCanCollide = true local rng = Random.new() if spawnMist then createBloodMist(anchorPart.Position, particles >= 4) end for i = 1, particles do if isWorkspaceSaturated() then break end if not consumeBudget(1) then break end local baseDir = hitDirection or (-anchorPart.CFrame.LookVector + Vector3.new(0, 0.5, 0)) if baseDir.Magnitude < 0.01 then baseDir = Vector3.new(0, 1, 0) end local speed = rng:NextNumber(15, 45) local spread = Vector3.new(rng:NextNumber(-10, 10), rng:NextNumber(-2, 12), rng:NextNumber(-10, 10)) local velocity = (baseDir.Unit * speed) + spread local bloodDrop = GetPart() bloodDrop.Parent = newPartsFolder local startPos = anchorPart.Position + Vector3.new(0, 0.3, 0) bloodDrop.CFrame = CFrame.new(startPos) bloodDrop.AssemblyLinearVelocity = velocity local randomTextureId = "rbxassetid://" .. SPLATIDS[rng:NextInteger(1, #SPLATIDS)] local decal = bloodDrop:FindFirstChild("Splatter") if decal then decal.Texture = randomTextureId decal.Color3 = Color3.new(1, 1, 1) end local bgui = bloodDrop:FindFirstChild("FlyingImage") if bgui then bgui.Enabled = true local img = bgui:FindFirstChild("Img") if img then img.Image = randomTextureId img.ImageColor3 = Color3.new(1, 1, 1) end end ActiveDrops[bloodDrop] = { part = bloodDrop, lastPos = startPos, params = rayParams, Impact = function(self, raycast) local part = self.part local hitPart = raycast.Instance if not part or not part.Parent then return end if not hitPart or not hitPart:IsA("BasePart") then ReturnPart(part) return end if isPartOfCharacter(hitPart) then ReturnPart(part) return end if isAccessoryOrToolPart(hitPart) then ReturnPart(part) return end if hitPart.Transparency >= 1 and hitPart.Name ~= "HumanoidRootPart" then ReturnPart(part) return end spawnImpactBurst(raycast.Position + raycast.Normal * 0.02, raycast.Normal, false, velocity) local sizeX = rng:NextNumber(FLYING_SPLAT_MIN_SIZE, FLYING_SPLAT_MAX_SIZE) local sizeZ = rng:NextNumber(FLYING_SPLAT_MIN_SIZE * 0.7, FLYING_SPLAT_MAX_SIZE * 0.9) part.Anchored = false part.CanCollide = false part.Massless = true part.Transparency = 1 local bguiChild = part:FindFirstChild("FlyingImage") if bguiChild then bguiChild.Enabled = false end local decalChild = part:FindFirstChild("Splatter") if decalChild then decalChild.Transparency = 0 decalChild.Color3 = Color3.new(1, 1, 1) end local normal = raycast.Normal if normal.Magnitude < 0.01 then normal = Vector3.new(0, 1, 0) end part.CFrame = CFrame.lookAt(raycast.Position, raycast.Position + normal) * CFrame.Angles(math.rad(-90), 0, 0) * CFrame.Angles(0, rng:NextNumber(0, math.pi * 2), 0) local weld = Instance.new("WeldConstraint") weld.Name = "BloodWeld" weld.Part0 = part weld.Part1 = hitPart weld.Parent = part TweenService:Create(part, tweenInfoIn, { Size = Vector3.new(sizeX, 0.05, sizeZ) }):Play() RegisterNewDecal(part) task.delay(bloodSettings.Duration, function() if not part or not part.Parent then return end if decalChild then local tween = TweenService:Create(decalChild, tweenInfoOut, {Transparency = 1}) tween:Play() tween.Completed:Wait() end ReturnPart(part) end) end } task.delay(3, function() if bloodDrop and ActiveDrops[bloodDrop] then ReturnPart(bloodDrop) end end) if rate and rate > 0 then task.wait(rate) end end end local function createBodyPool(char) if not char then return end local root = char.PrimaryPart or char:FindFirstChild("HumanoidRootPart") or char:FindFirstChild("Torso") if not root then return end if isWorkspaceSaturated() then return end if isFarFromCamera(root.Position) then return end local excl = {char, newPartsFolder} for _, c in ipairs(getAllCharacterModels()) do table.insert(excl, c) end local rayParams = RaycastParams.new() rayParams.FilterType = Enum.RaycastFilterType.Exclude rayParams.FilterDescendantsInstances = excl rayParams.RespectCanCollide = true local raycast = workspace:Raycast(root.Position, Vector3.new(0, -8, 0), rayParams) if not raycast then return end local hitPart = raycast.Instance if not hitPart or hitPart.Transparency >= 1 then return end if isPartOfCharacter(hitPart) then return end if isAccessoryOrToolPart(hitPart) then return end local poolPart = Instance.new("Part") poolPart.Name = "BloodPool" poolPart.Size = Vector3.new(0.2, 0.05, 0.2) poolPart.Anchored = false poolPart.CanCollide = false poolPart.CanQuery = false poolPart.CanTouch = false poolPart.Massless = true poolPart.Transparency = 1 poolPart.CFrame = CFrame.lookAt(raycast.Position, raycast.Position + raycast.Normal) * CFrame.Angles(math.rad(-90), 0, 0) poolPart.Parent = newPartsFolder local weld = Instance.new("WeldConstraint") weld.Part0 = poolPart weld.Part1 = hitPart weld.Parent = poolPart local decal = Instance.new("Decal") decal.Texture = "rbxassetid://" .. SPLATIDS[1] decal.Face = Enum.NormalId.Top decal.Color3 = Color3.new(1, 1, 1) decal.Parent = poolPart local targetSize = math.random(10, 16) TweenService:Create(poolPart, TweenInfo.new(3, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), { Size = Vector3.new(targetSize, 0.05, targetSize) }):Play() RegisterNewDecal(poolPart) task.delay(bloodSettings.Duration, function() if poolPart and poolPart.Parent then local tw = TweenService:Create(decal, tweenInfoOut, {Transparency = 1}) tw:Play() tw.Completed:Wait() if poolPart and poolPart.Parent then poolPart:Destroy() end end end) end local function createPuddle(Character, position, normal, attachPart, customSizeMultiplier) if not position then return end if attachPart and (isPartOfCharacter(attachPart) or isAccessoryOrToolPart(attachPart)) then return end if isWorkspaceSaturated() then return end if isFarFromCamera(position) then return end if not consumeBudget(1) then return end local sizeMult = customSizeMultiplier or 1 local targetSize = Vector3.new(math.random(10,22)/10 * sizeMult, 0.08, math.random(10,22)/10 * sizeMult) targetSize = Vector3.new( math.clamp(targetSize.X, PUDDLE_MIN_SIZE, PUDDLE_MAX_SIZE * sizeMult), targetSize.Y, math.clamp(targetSize.Z, PUDDLE_MIN_SIZE, PUDDLE_MAX_SIZE * sizeMult) ) local puddle = Instance.new("Part") puddle.Name = "BloodPuddle" puddle.Size = Vector3.new(0.1, 0.08, 0.1) puddle.Anchored = false puddle.CanCollide = false puddle.CanTouch = false puddle.CanQuery = false puddle.Material = Enum.Material.SmoothPlastic puddle.Color = BLOOD_COLOR puddle.Transparency = 1 local attachValid = attachPart and attachPart:IsA("BasePart") and attachPart.Parent if attachValid and Character then local ok, result = pcall(function() return attachPart:IsDescendantOf(Character) end) if ok and result then attachValid = false end end if attachValid and isAccessoryOrToolPart(attachPart) then attachValid = false end if attachValid then if normal and normal.Magnitude > 0.01 then local up = normal.Unit local right = up:Cross(Vector3.new(0,0,1)) if right.Magnitude < 0.01 then right = up:Cross(Vector3.new(1,0,0)) end right = right.Unit local back = right:Cross(up).Unit puddle.CFrame = CFrame.fromMatrix(position + up*0.025, right, up, back) else puddle.CFrame = CFrame.new(position + Vector3.new(0,0.025,0)) end puddle.Parent = newPartsFolder local weld = Instance.new("WeldConstraint") weld.Name = "BloodPuddleWeld" weld.Part0 = attachPart weld.Part1 = puddle weld.Parent = puddle else puddle.Anchored = true puddle.CFrame = CFrame.new(position + Vector3.new(0, 0.05, 0)) puddle.Parent = newPartsFolder end local mesh = Instance.new("CylinderMesh") mesh.Scale = Vector3.new(1, 0.1, 1) mesh.Parent = puddle TweenService:Create(puddle, TweenInfo.new(PUDDLE_FADE_IN_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), { Transparency = 0, Size = targetSize }):Play() if MICRO_PUDDLES_ENABLED and math.random() < 0.35 and sizeMult >= 0.9 and not attachPart then local offset = Vector3.new(math.random(-14, 14) / 10, 0.025, math.random(-14, 14) / 10) local mini = Instance.new("Part") mini.Name = "BloodMicroPuddle" mini.Size = Vector3.new(0.05, 0.04, 0.05) mini.Anchored = true mini.CanCollide = false mini.CanTouch = false mini.CanQuery = false mini.Material = Enum.Material.SmoothPlastic mini.Color = BLOOD_COLOR mini.Transparency = 0.05 mini.CFrame = CFrame.new(position + offset) mini.Parent = newPartsFolder local miniMesh = Instance.new("CylinderMesh") miniMesh.Scale = Vector3.new(1, 0.08, 1) miniMesh.Parent = mini local miniSize = math.random(3, 8) / 10 * sizeMult TweenService:Create(mini, TweenInfo.new(0.25, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Size = Vector3.new(miniSize, 0.04, miniSize)}):Play() task.delay(PUDDLE_FADE_IN_TIME + PUDDLE_HOLD_TIME * 0.7, function() if mini.Parent then local fade = TweenService:Create(mini, TweenInfo.new(PUDDLE_FADE_OUT_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {Transparency = 1}) fade:Play() fade.Completed:Wait() if mini.Parent then mini:Destroy() end end end) end task.delay(PUDDLE_FADE_IN_TIME + PUDDLE_HOLD_TIME, function() if not puddle.Parent then return end local tweenOut = TweenService:Create(puddle, TweenInfo.new(PUDDLE_FADE_OUT_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In), { Transparency = 1, Size = Vector3.new(0.1, 0.08, 0.1) }) tweenOut:Play() tweenOut.Completed:Wait() if puddle and puddle.Parent then puddle:Destroy() end end) end local function createBloodDrop(Character, bodyPart, hitPosition, hitDirection) if not bodyPart or not bodyPart:IsA("BasePart") or not bodyPart.Parent then return end if isAccessoryOrToolPart(bodyPart) then return end if isWorkspaceSaturated() then return end if isFarFromCamera(hitPosition or bodyPart.Position) then return end if not unlimitedMode and ActiveBloodDropCount >= dynamic.MAX_ACTIVE_BLOOD_DROPS then return end if not consumeBudget(1) then return end ActiveBloodDropCount += 1 local blood = Instance.new("Part") blood.Name = "Blood" blood.Size = Vector3.new(0.2, 0.2, 0.2) blood.Shape = Enum.PartType.Ball blood.Transparency = 1 blood.Color = BLOOD_COLOR blood.Material = Enum.Material.SmoothPlastic blood.CanCollide = false blood.CanTouch = true blood.CanQuery = false blood.CFrame = CFrame.new(hitPosition or bodyPart.Position) blood.Parent = newPartsFolder local emitter = Instance.new("ParticleEmitter") emitter.Name = "BloodEffect" emitter.Color = ColorSequence.new(BLOOD_COLOR) emitter.Texture = BLOOD_TEXTURE emitter.Size = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.08), NumberSequenceKeypoint.new(1, 0.08)}) emitter.Lifetime = NumberRange.new(BLOOD_LIFETIME) emitter.Rate = BLOOD_RATE emitter.LockedToPart = true emitter.Speed = NumberRange.new(0, 2) emitter.Parent = blood local dir if hitDirection and hitDirection.Magnitude > 0.01 then dir = hitDirection.Unit else dir = bodyPart.CFrame.UpVector end local spread = Vector3.new(math.random(-10,10)/10, math.random(0,10)/10, math.random(-10,10)/10) blood.AssemblyLinearVelocity = dir * math.random(8, 18) + spread local touched = false local counted = true local function releaseCount() if counted then counted = false ActiveBloodDropCount = math.max(0, ActiveBloodDropCount - 1) end end local connection connection = blood.Touched:Connect(function(hit) if touched then return end if not hit or not hit:IsA("BasePart") then return end if Character and hit:IsDescendantOf(Character) then return end local n = hit.Name if n == "Blood" or n == "BloodPuddle" or n == "BloodDrop" or n == "BloodSplat" or n == "BlPart" or n == "BloodPool" or n == "CP" or n == "BloodGib" or n == "BloodMicroPuddle" or n == "Collision" then return end if isPartOfCharacter(hit) or isAccessoryOrToolPart(hit) then touched = true if connection then connection:Disconnect() end releaseCount() if blood.Parent then blood:Destroy() end return end touched = true if connection then connection:Disconnect() end releaseCount() createPuddle(Character, blood.Position, Vector3.new(0, 1, 0), hit, 1) if blood.Parent then blood:Destroy() end end) task.delay(DROPLET_LIFETIME, releaseCount) Debris:AddItem(blood, DROPLET_LIFETIME) end local function makeBlood(Character, bodyPart, hitPosition, hitDirection, amount) if not bodyPart then return end if isAccessoryOrToolPart(bodyPart) then return end local heavy = isHeavyLoad() amount = math.clamp(amount or 3, 1, heavy and 3 or 6) for i = 1, amount do task.spawn(function() if isWorkspaceSaturated() then return end local offset = Vector3.new(math.random(-15,15)/100, math.random(-15,15)/100, math.random(-15,15)/100) local spawnPosition = hitPosition or bodyPart.Position createBloodDrop(Character, bodyPart, spawnPosition + offset, hitDirection) end) task.wait(0.03) end end local function getFace(part, hitPos) if not part or not hitPos then return Enum.NormalId.Front end local localPos = part.CFrame:PointToObjectSpace(hitPos) local absX, absY, absZ = math.abs(localPos.X), math.abs(localPos.Y), math.abs(localPos.Z) if absX >= absY and absX >= absZ then return localPos.X >= 0 and Enum.NormalId.Right or Enum.NormalId.Left elseif absY >= absX and absY >= absZ then return localPos.Y >= 0 and Enum.NormalId.Top or Enum.NormalId.Bottom else return localPos.Z >= 0 and Enum.NormalId.Back or Enum.NormalId.Front end end local function startBleeding(part) if not part then return end if isAccessoryOrToolPart(part) then return end if part:FindFirstChild("BleedEffect") then return end local emitter = Instance.new("ParticleEmitter") emitter.Name = "BleedEffect" emitter.Color = ColorSequence.new(BLOOD_PARTICLE_HI, BLOOD_PARTICLE_LO) emitter.Lifetime = NumberRange.new(0.4, 0.9) emitter.Rate = 8 emitter.Speed = NumberRange.new(2, 7) emitter.Rotation = NumberRange.new(0, 360) emitter.RotSpeed = NumberRange.new(-140, 140) emitter.LightEmission = 0 emitter.SpreadAngle = Vector2.new(360, 360) emitter.VelocityInheritance = 0.2 emitter.Transparency = NumberSequence.new(0, 1) emitter.Size = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.24), NumberSequenceKeypoint.new(0.45, 0.12), NumberSequenceKeypoint.new(1, 0.02)}) emitter.Drag = 4 emitter.Acceleration = Vector3.new(0, -25, 0) emitter.Enabled = true emitter.Parent = part end local function splatFilter(Character, instance) if isPartOfCharacter(instance) then return false end if isAccessoryOrToolPart(instance) then return false end return true end local function fadeDecal(decal, fadeInTime, holdTime, fadeOutTime) if not decal or not decal.Parent then return end decal.Transparency = 1 local fadeIn = TweenService:Create(decal, TweenInfo.new(fadeInTime, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Transparency = 0}) fadeIn:Play() pcall(function() fadeIn.Completed:Wait() end) if not decal or not decal.Parent then return end task.wait(holdTime) if not decal or not decal.Parent then return end local fadeOut = TweenService:Create(decal, TweenInfo.new(fadeOutTime, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {Transparency = 1}) fadeOut:Play() pcall(function() fadeOut.Completed:Wait() end) end local function spawnBloodDrip(part, hitPos) if not part or not part:IsA("BasePart") or not part.Parent then return end if isAccessoryOrToolPart(part) then return end if math.random() > 0.45 then return end if isFarFromCamera(part.Position) then return end if isPartOfCharacter(part) == false then return end local localPos = part.CFrame:PointToObjectSpace(hitPos or part.Position) local a0 = Instance.new("Attachment") a0.Name = "BloodDripA0" a0.Position = localPos a0.Parent = part local a1 = Instance.new("Attachment") a1.Name = "BloodDripA1" a1.Position = localPos a1.Parent = part local trail = Instance.new("Trail") trail.Name = "BloodDrip" trail.Attachment0 = a0 trail.Attachment1 = a1 trail.Texture = BLOOD_TEXTURE trail.Color = ColorSequence.new(BLOOD_PARTICLE_HI, BLOOD_PARTICLE_LO) trail.Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.1), NumberSequenceKeypoint.new(0.7, 0.25), NumberSequenceKeypoint.new(1, 1), }) trail.WidthScale = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.25), NumberSequenceKeypoint.new(0.65, 0.1), NumberSequenceKeypoint.new(1, 0), }) trail.Lifetime = 0.25 trail.FaceCamera = true trail.Parent = part local distance = math.random(25, 55) / 100 local target = localPos + Vector3.new(math.random(-8, 8) / 100, -distance, math.random(-8, 8) / 100) TweenService:Create(a1, TweenInfo.new(math.random(25, 45) / 100, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {Position = target}):Play() task.delay(0.7, function() if trail and trail.Parent then trail:Destroy() end if a0 and a0.Parent then a0:Destroy() end if a1 and a1.Parent then a1:Destroy() end end) end local function stopBleedingIfNoDecals(part) if not part or not part.Parent then return end local hasDecal = false for _, child in ipairs(part:GetChildren()) do if child:IsA("Decal") and child.Name == "BloodDecal" then hasDecal = true break end end if not hasDecal then local bleed = part:FindFirstChild("BleedEffect") if bleed then bleed:Destroy() end end end local function fadeOutDecal(decal) if not decal or not decal.Parent then return end local part = decal.Parent local tween = TweenService:Create(decal, TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {Transparency = 1}) tween:Play() pcall(function() tween.Completed:Wait() end) if decal and decal.Parent then decal:Destroy() stopBleedingIfNoDecals(part) else stopBleedingIfNoDecals(part) end end local function getBloodDecals(char) local decals = {} if not char then return decals end for _, obj in ipairs(char:GetDescendants()) do if obj:IsA("Decal") and obj.Name == "BloodDecal" then local parent = obj.Parent if parent and parent:IsA("BasePart") and not isAccessoryOrToolPart(parent) then table.insert(decals, obj) end end end return decals end local function getRelativePath(root, instance) if not root or not instance then return nil end local chain = {} local current = instance while current and current ~= root do table.insert(chain, 1, current.Name) current = current.Parent end if current ~= root then return nil end return chain end local function findByRelativePath(root, path) if not root or not path then return nil end local current = root for _, name in ipairs(path) do local nextObject = current:FindFirstChild(name) if not nextObject then return nil end current = nextObject end return current end local function resolveCorpseTarget(clone, path) if not clone or not path or #path == 0 then return nil end local target = findByRelativePath(clone, path) if target and target:IsA("BasePart") then return target end local lastName = path[#path] for _, obj in ipairs(clone:GetDescendants()) do if obj:IsA("BasePart") and obj.Name == lastName and not isAccessoryOrToolPart(obj) then return obj end end return nil end local function removeBloodDecals(char, count) local decals = getBloodDecals(char) if #decals == 0 then return end local toRemove = math.min(count, #decals) for i = #decals, 2, -1 do local j = math.random(1, i) decals[i], decals[j] = decals[j], decals[i] end for i = 1, toRemove do local decal = decals[i] if decal and decal.Parent then task.spawn(function() fadeOutDecal(decal) end) end end end local movingSplats = {} local function trackSplat(splat, targetPart) if not splat or not targetPart or not targetPart:IsA("BasePart") then return end if targetPart:IsDescendantOf(newPartsFolder) then return end if isAccessoryOrToolPart(targetPart) then return end local ok, localCFrame = pcall(function() return targetPart.CFrame:ToObjectSpace(splat.CFrame) end) if not ok then return end movingSplats[splat] = { part = targetPart, localCFrame = localCFrame, } end local function untrackSplat(splat) movingSplats[splat] = nil end RunService.Heartbeat:Connect(function() for splat, data in pairs(movingSplats) do if not splat or not splat.Parent or not data or not data.part or not data.part.Parent then movingSplats[splat] = nil else local ok = pcall(function() splat.CFrame = data.part.CFrame * data.localCFrame end) if not ok then movingSplats[splat] = nil end end end end) local function spawnSplats(Character, hitPos) if not hitPos then return end if isWorkspaceSaturated() then return end if isFarFromCamera(hitPos) then return end local heavy = isHeavyLoad() local splatCount = heavy and 2 or 3 local params = RaycastParams.new() params.FilterType = Enum.RaycastFilterType.Exclude local list = {} for i, v in ipairs(getAllCharacterModels()) do list[i] = v end table.insert(list, newPartsFolder) params.FilterDescendantsInstances = list params.IgnoreWater = true local fadeInTime = 0.3 local fadeOutTime = 1.5 local holdTime = math.max(0, SPLAT_LIFETIME - fadeInTime - fadeOutTime) for i = 1, splatCount do if isWorkspaceSaturated() then break end if not consumeBudget(1) then break end local splat = Instance.new("Part") splat.Name = "BloodSplat" splat.Size = Vector3.new(math.random(4,8), math.random(4,8), 0.05) splat.Transparency = 1 splat.CanCollide = false splat.CanTouch = false splat.CanQuery = false splat.Anchored = false local decal = Instance.new("Decal") decal.Name = "BloodDecal" decal.Texture = "rbxassetid://" .. SPLATIDS[math.random(1, #SPLATIDS)] decal.Color3 = Color3.new(1, 1, 1) decal.Parent = splat local randomDirection = Vector3.new(math.random(-80,80), math.random(-60,60), math.random(-80,80)) if randomDirection.Magnitude < 0.01 then randomDirection = Vector3.new(0,1,0) end local direction = randomDirection.Unit * 8 local origin = hitPos + direction.Unit * 0.5 local result = workspace:Raycast(origin, direction, params) if result and result.Instance and splatFilter(Character, result.Instance) and not isAccessoryOrToolPart(result.Instance) then splat.CFrame = CFrame.new(result.Position, result.Position + result.Normal) splat.Anchored = true splat.Massless = true splat.CanCollide = false splat.CanTouch = false splat.CanQuery = false splat.Parent = newPartsFolder trackSplat(splat, result.Instance) task.spawn(fadeDecal, decal, fadeInTime, holdTime, fadeOutTime) task.delay(SPLAT_LIFETIME, function() untrackSplat(splat) end) Debris:AddItem(splat, SPLAT_LIFETIME) else splat:Destroy() end end end local function checkExplosionNear(char) local root = char:FindFirstChild("HumanoidRootPart") or char:FindFirstChild("Torso") or char:FindFirstChild("UpperTorso") if not root then return false end for _, exp in ipairs(recentExplosions) do if (exp.position - root.Position).Magnitude <= (exp.radius + 12) then return true end end return false end local function spawnArterialSpray(part, direction) if not part or not part.Parent then return end if isAccessoryOrToolPart(part) then return end if isWorkspaceSaturated() then return end if isFarFromCamera(part.Position) then return end if not consumeBudget(1) then return end local spray = Instance.new("Part") spray.Name = "ArterialSpray" spray.Size = Vector3.new(0.05, 0.05, 0.05) spray.CFrame = part.CFrame spray.Transparency = 1 spray.Anchored = false spray.CanCollide = false spray.CanQuery = false spray.CanTouch = false spray.Massless = true spray.Parent = newPartsFolder local a0 = Instance.new("Attachment") a0.Name = "SprayA0" a0.Parent = spray local a1 = Instance.new("Attachment") a1.Name = "SprayA1" a1.Position = Vector3.new(0, 0.1, 0) a1.Parent = spray local trail = Instance.new("Trail") trail.Attachment0 = a0 trail.Attachment1 = a1 trail.Texture = BLOOD_TEXTURE trail.Color = ColorSequence.new(BLOOD_PARTICLE_HI, BLOOD_PARTICLE_LO) trail.Lifetime = 0.4 trail.WidthScale = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.5), NumberSequenceKeypoint.new(1, 0), }) trail.FaceCamera = true trail.Parent = spray local dir = direction and direction.Magnitude > 0.01 and direction.Unit or Vector3.new(0,1,0) spray.AssemblyLinearVelocity = dir * math.random(30, 55) + Vector3.new( math.random(-10,10), math.random(0,15), math.random(-10,10) ) Debris:AddItem(spray, 1.2) end local RAGDOLL_CLEANUP_TIME = 240 local saveAllCharacterBloodData local applyAllEffectsToCorpseClone local function createJoint(j_type, p0, p1, c0, c1) local nj = Instance.new(j_type) nj.Part0 = p0 nj.Part1 = p1 if c0 ~= nil then nj.C0 = c0 end if c1 ~= nil then nj.C1 = c1 end nj.Parent = p0 end local R15_JOINT_PROPS = { waist = {{"LimitsEnabled", true}, {"UpperAngle", 5}, {"Radius", 5}}, neck = {{"LimitsEnabled", true}, {"UpperAngle", 50}, {"LowerAngle", -50}}, hand = {{"LimitsEnabled", true}, {"UpperAngle", 0}, {"LowerAngle", 0}}, shin = {{"LimitsEnabled", true}, {"UpperAngle", 0}, {"LowerAngle", -75}}, foot = {{"LimitsEnabled", true}, {"UpperAngle", 15}, {"LowerAngle", -45}}, } local function resetRagdollAttachments(model) for _, obj in ipairs(model:GetDescendants()) do if obj:IsA("Attachment") and obj.Parent and obj.Parent.Name ~= "ayybleed" then obj.Axis = Vector3.new(0, 1, 0) obj.SecondaryAxis = Vector3.new(0, 0, 1) obj.Rotation = Vector3.new(0, 0, 0) end end end local function createR15RagdollJoint(ragdoll, part0, part1, attachmentName, className, properties) if not ragdoll or not part0 or not part1 then return end if ragdoll:FindFirstChild("RagdollConstraint"..part1.Name) then return end local motor = part1:FindFirstChildOfClass("Motor6D") if motor then motor:Destroy() end local fullAttName = attachmentName if attachmentName ~= "NeckAttachment" then fullAttName = attachmentName.."RigAttachment" end local att0 = part0:FindFirstChild(fullAttName) or part0:FindFirstChild(attachmentName) local att1 = part1:FindFirstChild(fullAttName) or part1:FindFirstChild(attachmentName) if not att0 or not att1 then return end local constraint = Instance.new(className.."Constraint") constraint.Attachment0 = att0 constraint.Attachment1 = att1 constraint.Name = "RagdollConstraint"..part1.Name local collidepart = Instance.new("Part") collidepart.Size = part1.Size / 2 local lname = string.lower(part1.Name) if string.find(lname, "upper") then if string.find(lname, "leg") then collidepart.Size = part1.Size / 3 else collidepart.Size = part1.Size / 2.5 end end collidepart.CanCollide = true collidepart.Name = "Collision" collidepart.Anchored = false collidepart.Transparency = 1 collidepart.CFrame = part1.CFrame collidepart.CanQuery = false collidepart.CanTouch = false setCollisionGroupSafe(collidepart, COLLISION_GROUP_RAGDOLL) collidepart.Parent = ragdoll setCollisionGroupSafe(collidepart, COLLISION_GROUP_RAGDOLL) local att_c0 = Instance.new("Attachment", part1) local att_c1 = Instance.new("Attachment", collidepart) if string.find(lname, "upper") then if string.find(lname, "leg") then att_c0.Position = Vector3.new(0, 0.01, 0) else att_c0.Position = Vector3.new(0, 0.25, 0) end else att_c0.Position = Vector3.new(0, -0.1, 0) end local hinge = Instance.new("HingeConstraint") hinge.Attachment0 = att_c0 hinge.Attachment1 = att_c1 hinge.LimitsEnabled = true hinge.UpperAngle = 0 hinge.LowerAngle = 0 hinge.Parent = part1 for _, prop in ipairs(properties or {}) do constraint[prop[1]] = prop[2] end constraint.Parent = ragdoll end local function sanitizeRagdollClone(ragdoll) if not ragdoll then return end local partsToAnchor = {} for _, obj in ipairs(ragdoll:GetDescendants()) do if obj:IsA("Model") and obj ~= ragdoll then if not obj:IsA("Accessory") then obj:Destroy() end elseif obj:IsA("Tool") or obj:IsA("Script") or obj:IsA("LocalScript") or obj:IsA("ModuleScript") then if not isAccessoryOrToolPart(obj) then obj:Destroy() end elseif obj:IsA("Sound") or obj:IsA("ForceField") then if not isAccessoryOrToolPart(obj) then obj:Destroy() end elseif obj:IsA("BasePart") then if not isAccessoryOrToolPart(obj) then partsToAnchor[#partsToAnchor + 1] = obj end end end for _, obj in ipairs(partsToAnchor) do obj.Anchored = true obj.CanTouch = false obj.CanQuery = false obj.CanCollide = false obj.AssemblyLinearVelocity = Vector3.zero obj.AssemblyAngularVelocity = Vector3.zero end end local function hideRagdollPartsNearCamera(ragdoll) if not ragdoll or not ragdoll.Parent then return end local camera = workspace.CurrentCamera if not camera then return end local camPos = camera.CFrame.Position local camLook = camera.CFrame.LookVector local parts = getCachedModelParts(ragdoll) if #parts == 0 then return end local root = parts[1] if not root or not root.Parent then return end if (root.Position - camPos).Magnitude > 12 then return end for _, part in ipairs(parts) do if part and part.Parent and part:IsA("BasePart") then if isAccessoryOrToolPart(part) then part.LocalTransparencyModifier = 0 else local offset = part.Position - camPos local distance = offset.Magnitude if distance > 3.5 then if part.LocalTransparencyModifier ~= 0 then part.LocalTransparencyModifier = 0 end elseif distance < 1.15 then part.LocalTransparencyModifier = 1 elseif distance < 2.0 and distance > 0.01 then local dot = offset.Unit:Dot(camLook) if dot > 0.35 then part.LocalTransparencyModifier = math.clamp(1 - (distance - 1.15) / 0.85, 0, 1) else part.LocalTransparencyModifier = 0 end else part.LocalTransparencyModifier = 0 end end end end end local R6_AttachmentData = { ["RA"] = {"Right Arm", CFrame.new(0, 0.5, 0), CFrame.new(1.5, 0.5, 0)}, ["LA"] = {"Left Arm", CFrame.new(0, 0.5, 0), CFrame.new(-1.5, 0.5, 0)}, ["RL"] = {"Right Leg", CFrame.new(0, 0.5, 0), CFrame.new(0.5, -1.5, 0)}, ["LL"] = {"Left Leg", CFrame.new(0, 0.5, 0), CFrame.new(-0.5, -1.5, 0)}, } local function countActiveRagdolls() local count = 0 for model in pairs(ragdollModels) do if model and model.Parent then count = count + 1 end end return count end local function ragdollCharacter(char, humanoid, savedDataOverride) if not char or not humanoid then return end if not RAGDOLL_ENABLED then return end if char:GetAttribute("ClientRagdolled") then return end if not unlimitedMode and countActiveRagdolls() >= dynamic.MAX_RAGDOLLS then return end char:SetAttribute("ClientRagdolled", true) local camera = workspace.CurrentCamera local savedData = savedDataOverride or (saveAllCharacterBloodData and saveAllCharacterBloodData(char)) or {} char.Archivable = true local ragdoll = char:Clone() char.Archivable = false if not ragdoll then return end ragdoll:SetAttribute("BuildingRagdoll", true) sanitizeRagdollClone(ragdoll) task.wait() registerRagdollCached(ragdoll) ragdoll:SetAttribute("IsClientRagdoll", true) -- Скрываем тело оригинального персонажа. -- Аксессуары на голове тоже скрываем (голова невидима). local headHidden = false do local head = char:FindFirstChild("Head") if head and head.Transparency >= 1 then headHidden = true end end for _, obj in ipairs(char:GetChildren()) do if not obj:IsA("Humanoid") and not obj:IsA("Accessory") then if obj:IsA("BasePart") then obj.Transparency = 1 obj.CanCollide = false obj.CanQuery = false obj.CanTouch = false obj.AssemblyLinearVelocity = Vector3.zero obj.AssemblyAngularVelocity = Vector3.zero obj.Anchored = true for _, child in ipairs(obj:GetChildren()) do if child:IsA("Decal") or child:IsA("Texture") then child.Transparency = 1 elseif child:IsA("ParticleEmitter") then child.Enabled = false end end end Debris:AddItem(obj, 6) end end -- Если голова скрыта — прячем и аксессуары на ней if headHidden then hideAccessoriesOnHead(char) end -- Очистка клона: не заходим внутрь Accessory do local queue = {ragdoll} local head = 1 while head <= #queue do local ch = queue[head] head += 1 if ch and ch.Parent and not ch:IsA("Accessory") then for _, obj in ipairs(ch:GetChildren()) do local isAccessoryWeld = obj:IsA("Weld") and obj.Parent and obj.Parent:IsA("Accessory") if obj:IsA("Model") or obj:IsA("Tool") then obj:Destroy() elseif (obj:IsA("Script") or obj:IsA("LocalScript") or obj:IsA("ModuleScript")) or ((obj:IsA("Weld") or obj:IsA("Motor6D")) and obj.Name ~= "HeadWeld" and obj.Name ~= "AttachementWeld" and not isAccessoryWeld) or obj:IsA("ForceField") or (obj:IsA("ParticleEmitter") and obj.Name ~= "BleedEffect" and obj.Name ~= "BloodEffect" and obj.Name ~= "NeckStumpBleed") or obj:IsA("Sound") then obj:Destroy() else queue[#queue + 1] = obj if obj:IsA("BasePart") and not isAccessoryOrToolPart(obj) then obj.AssemblyLinearVelocity = Vector3.zero obj.AssemblyAngularVelocity = Vector3.zero end end end end end end for _, obj in ipairs(ragdoll:GetDescendants()) do if isAccessoryOrToolPart(obj) then -- Скипаем содержимое аксессуаров elseif obj:IsA("Decal") and (obj.Name == "BloodDecal" or obj.Name == "face" or obj.Name == "Face") then obj:Destroy() elseif obj:IsA("ParticleEmitter") and (obj.Name == "BleedEffect" or obj.Name == "BloodEffect" or obj.Name == "NeckStumpBleed") then obj:Destroy() elseif obj:IsA("Trail") and (obj.Name == "BloodDrip" or obj.Name == "BloodTrail") then obj:Destroy() elseif obj:IsA("Attachment") and (obj.Name == "BloodDripA0" or obj.Name == "BloodDripA1") then obj:Destroy() end end local decalsRestored, emittersRestored, trailsRestored, faceRestored = 0, 0, 0, false if applyAllEffectsToCorpseClone then decalsRestored, emittersRestored, trailsRestored, faceRestored = applyAllEffectsToCorpseClone(ragdoll, savedData) end ragdoll:SetAttribute("TransferredBloodDecals", decalsRestored) ragdoll:SetAttribute("TransferredEmitters", emittersRestored) ragdoll:SetAttribute("TransferredTrails", trailsRestored) ragdoll:SetAttribute("TransferredFace", faceRestored) local ragRoot = ragdoll:FindFirstChild("HumanoidRootPart") if ragRoot then ragRoot:Destroy() end local fhum = ragdoll:FindFirstChildOfClass("Humanoid") if fhum then fhum.HealthDisplayType = Enum.HumanoidHealthDisplayType.AlwaysOff fhum.PlatformStand = true fhum.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None fhum.BreakJointsOnDeath = false fhum.RequiresNeck = false fhum.Name = "RagdollHumanoid" end local isR15 = ragdoll:FindFirstChild("UpperTorso") ~= nil local torso = ragdoll:FindFirstChild("Torso") or ragdoll:FindFirstChild("UpperTorso") local lowerTorso = ragdoll:FindFirstChild("LowerTorso") if torso then torso.AssemblyLinearVelocity = Vector3.new(math.random(-1,1), 0.0000001, math.random(-1,1)).Unit * 8 + Vector3.new(0, 0.3, 0) local head = ragdoll:FindFirstChild("Head") if head then if not isR15 then createJoint("Weld", torso, head, CFrame.new(0, 1.5, 0)) end if Players:GetPlayerFromCharacter(char) == player and camera then camera.CameraSubject = head end end if isR15 then resetRagdollAttachments(ragdoll) local headPart = ragdoll:FindFirstChild("Head") local leftUpperArm = ragdoll:FindFirstChild("LeftUpperArm") local rightUpperArm = ragdoll:FindFirstChild("RightUpperArm") local leftLowerArm = ragdoll:FindFirstChild("LeftLowerArm") local rightLowerArm = ragdoll:FindFirstChild("RightLowerArm") local leftHand = ragdoll:FindFirstChild("LeftHand") local rightHand = ragdoll:FindFirstChild("RightHand") local leftUpperLeg = ragdoll:FindFirstChild("LeftUpperLeg") local rightUpperLeg = ragdoll:FindFirstChild("RightUpperLeg") local leftLowerLeg = ragdoll:FindFirstChild("LeftLowerLeg") local rightLowerLeg = ragdoll:FindFirstChild("RightLowerLeg") local leftFoot = ragdoll:FindFirstChild("LeftFoot") local rightFoot = ragdoll:FindFirstChild("RightFoot") if lowerTorso and torso then createR15RagdollJoint(ragdoll, lowerTorso, torso, "Waist", "BallSocket", R15_JOINT_PROPS.waist) end if torso and headPart then createR15RagdollJoint(ragdoll, torso, headPart, "Neck", "Hinge", R15_JOINT_PROPS.neck) end if leftLowerArm and leftHand then createR15RagdollJoint(ragdoll, leftLowerArm, leftHand, "LeftWrist", "Hinge", R15_JOINT_PROPS.hand) end if rightLowerArm and rightHand then createR15RagdollJoint(ragdoll, rightLowerArm, rightHand, "RightWrist", "Hinge", R15_JOINT_PROPS.hand) end if leftUpperLeg and leftLowerLeg then createR15RagdollJoint(ragdoll, leftUpperLeg, leftLowerLeg, "LeftKnee", "Hinge", R15_JOINT_PROPS.shin) end if rightUpperLeg and rightLowerLeg then createR15RagdollJoint(ragdoll, rightUpperLeg, rightLowerLeg, "RightKnee", "Hinge", R15_JOINT_PROPS.shin) end if leftLowerLeg and leftFoot then createR15RagdollJoint(ragdoll, leftLowerLeg, leftFoot, "LeftAnkle", "Hinge", R15_JOINT_PROPS.foot) end if rightLowerLeg and rightFoot then createR15RagdollJoint(ragdoll, rightLowerLeg, rightFoot, "RightAnkle", "Hinge", R15_JOINT_PROPS.foot) end if torso and leftUpperArm then createR15RagdollJoint(ragdoll, torso, leftUpperArm, "LeftShoulder", "BallSocket") end if torso and rightUpperArm then createR15RagdollJoint(ragdoll, torso, rightUpperArm, "RightShoulder", "BallSocket") end if leftUpperArm and leftLowerArm then createR15RagdollJoint(ragdoll, leftUpperArm, leftLowerArm, "LeftElbow", "BallSocket") end if rightUpperArm and rightLowerArm then createR15RagdollJoint(ragdoll, rightUpperArm, rightLowerArm, "RightElbow", "BallSocket") end if lowerTorso and leftUpperLeg then createR15RagdollJoint(ragdoll, lowerTorso, leftUpperLeg, "LeftHip", "BallSocket") end if lowerTorso and rightUpperLeg then createR15RagdollJoint(ragdoll, lowerTorso, rightUpperLeg, "RightHip", "BallSocket") end task.wait() else for att_tag, att_data in pairs(R6_AttachmentData) do local get_limb = ragdoll:FindFirstChild(att_data[1]) if get_limb then local att1 = Instance.new("Attachment") att1.Name = att_tag att1.CFrame = att_data[2] att1.Parent = get_limb local att2 = Instance.new("Attachment") att2.Name = att_tag att2.CFrame = att_data[3] att2.Parent = torso local socket = Instance.new("BallSocketConstraint") socket.Name = att_tag .. "_SOCKET" socket.Attachment0 = att2 socket.Attachment1 = att1 socket.Radius = 0 socket.Parent = torso get_limb.CanCollide = false local cp = Instance.new("Part") cp.Name = "CP" cp.TopSurface = Enum.SurfaceType.Smooth cp.BottomSurface = Enum.SurfaceType.Smooth cp.Size = Vector3.new(1, 1.5, 1) cp.Transparency = 1 cp.CanCollide = true cp.CanQuery = false local cp_weld = Instance.new("Weld") cp_weld.C0 = CFrame.new(0, -0.25, 0) cp_weld.Part0 = get_limb cp_weld.Part1 = cp cp_weld.Parent = cp cp.Parent = ragdoll setCollisionGroupSafe(cp, COLLISION_GROUP_RAGDOLL) end end if torso then torso.CanCollide = false end local r6head = ragdoll:FindFirstChild("Head") if r6head then r6head.CanCollide = false end end end applyRagdollCollisionGroup(ragdoll) ragdoll.DescendantAdded:Connect(function(d) invalidateModelPartsCache(ragdoll) if d:IsA("BasePart") and not isAccessoryOrToolPart(d) then setCollisionGroupSafe(d, COLLISION_GROUP_RAGDOLL) if d.Name == "Collision" or d.Name == "CP" then d.CanCollide = true end end end) ragdoll.Parent = workspace Debris:AddItem(ragdoll, RAGDOLL_CLEANUP_TIME) for _, obj in ipairs(ragdoll:GetDescendants()) do if obj:IsA("ParticleEmitter") then if obj.Name == "BleedEffect" or obj.Name == "NeckStumpBleed" then obj.Enabled = true elseif obj.Name == "BloodEffect" then obj:Destroy() end end end if fhum then fhum.MaxHealth = 100 fhum.Health = fhum.MaxHealth end ragdoll:SetAttribute("BuildingRagdoll", false) task.delay(RAGDOLL_SETTLE_DELAY, function() if not ragdoll or not ragdoll.Parent then return end for _, part in ipairs(ragdoll:GetDescendants()) do if part:IsA("BasePart") then part.Anchored = false part.CanQuery = false part.CanTouch = false end end applyRagdollCollisionGroup(ragdoll) end) local cleanupConn cleanupConn = char.AncestryChanged:Connect(function(_, parent) if not parent then if ragdoll and ragdoll.Parent then ragdoll:Destroy() end unregisterRagdollCached(ragdoll) if cleanupConn then cleanupConn:Disconnect() end end end) end local localHeartbeatSound local function updateHeartbeat(humanoid) if not humanoid then return end local hp = humanoid.Health / humanoid.MaxHealth if hp > 0 and hp < 0.3 then if not localHeartbeatSound or not localHeartbeatSound.Parent then local head = humanoid.Parent and humanoid.Parent:FindFirstChild("Head") if head then localHeartbeatSound = Instance.new("Sound") localHeartbeatSound.Name = "BloodHeartbeat" localHeartbeatSound.SoundId = HEARTBEAT_SOUND localHeartbeatSound.Looped = true localHeartbeatSound.Volume = 0.4 localHeartbeatSound.Parent = head localHeartbeatSound:Play() end end else if localHeartbeatSound and localHeartbeatSound.Parent then localHeartbeatSound:Destroy() localHeartbeatSound = nil end end end local processedModels = setmetatable({}, {__mode = "k"}) local function immediatelyApplyCharacterCollision(char) if not char or not char:IsA("Model") then return end for _, d in ipairs(char:GetDescendants()) do if d:IsA("BasePart") and not isAccessoryOrToolPart(d) then setCollisionGroupSafe(d, COLLISION_GROUP_CHARACTER) end end char.DescendantAdded:Connect(function(d) if d:IsA("BasePart") and not isAccessoryOrToolPart(d) then setCollisionGroupSafe(d, COLLISION_GROUP_CHARACTER) end end) end function saveAllCharacterBloodData(char) local data = { Decals = {}, Emitters = {}, Trails = {}, Attachments = {}, Face = nil, } if not char or not char.Parent then return data end for _, obj in ipairs(char:GetDescendants()) do if isAccessoryOrToolPart(obj) then -- Скипаем содержимое аксессуаров elseif obj:IsA("Decal") and obj.Name == "BloodDecal" then local part = obj.Parent if part and part:IsA("BasePart") and not isAccessoryOrToolPart(part) then local path = getRelativePath(char, part) if path then table.insert(data.Decals, { Path = path, Texture = obj.Texture, Face = obj.Face, Color3 = obj.Color3, Transparency = obj.Transparency, Name = obj.Name, }) end end elseif obj:IsA("Decal") and (obj.Name == "face" or obj.Name == "Face") and obj.Parent and obj.Parent.Name == "Head" then data.Face = { Texture = obj.Texture, Face = obj.Face, Color3 = obj.Color3, Transparency = obj.Transparency, Name = obj.Name, } elseif obj:IsA("ParticleEmitter") and (obj.Name == "BleedEffect" or obj.Name == "BloodEffect" or obj.Name == "NeckStumpBleed") then local part = obj.Parent if part and part:IsA("BasePart") and not isAccessoryOrToolPart(part) then local path = getRelativePath(char, part) if path then table.insert(data.Emitters, { Path = path, Name = obj.Name, Color = obj.Color, Brightness = obj.Brightness, LightEmission = obj.LightEmission, Lifetime = obj.Lifetime, Rate = obj.Rate, Speed = obj.Speed, SpreadAngle = obj.SpreadAngle, Rotation = obj.Rotation, RotSpeed = obj.RotSpeed, Size = obj.Size, Transparency = obj.Transparency, VelocityInheritance = obj.VelocityInheritance, Acceleration = obj.Acceleration, Drag = obj.Drag, Texture = obj.Texture, LockedToPart = obj.LockedToPart, EmissionDirection = obj.EmissionDirection, Enabled = obj.Enabled, }) end end elseif obj:IsA("Trail") then local part = obj.Parent if part and part:IsA("BasePart") and not isAccessoryOrToolPart(part) then local path = getRelativePath(char, part) if path then table.insert(data.Trails, { Path = path, Name = obj.Name, Texture = obj.Texture, Color = obj.Color, Transparency = obj.Transparency, WidthScale = obj.WidthScale, Lifetime = obj.Lifetime, FaceCamera = obj.FaceCamera, }) end end elseif obj:IsA("Attachment") and (obj.Name == "BloodDripA0" or obj.Name == "BloodDripA1") then local part = obj.Parent if part and part:IsA("BasePart") and not isAccessoryOrToolPart(part) then local path = getRelativePath(char, part) if path then table.insert(data.Attachments, { Path = path, Name = obj.Name, Position = obj.Position, Orientation = obj.Orientation, }) end end end end local head = char:FindFirstChild("Head") if head then data.HeadTransparency = head.Transparency end return data end local function applyFaceToCorpseClone(clone, faceData) if not clone or not faceData then return false end local head = clone:FindFirstChild("Head") if not head then return false end for _, child in ipairs(head:GetChildren()) do if child:IsA("Decal") and (child.Name == "face" or child.Name == "Face") then child:Destroy() end end local newDecal = Instance.new("Decal") newDecal.Name = faceData.Name or "face" newDecal.Texture = faceData.Texture newDecal.Face = faceData.Face newDecal.Color3 = faceData.Color3 or Color3.new(1, 1, 1) newDecal.Transparency = math.clamp(faceData.Transparency or 0, 0, 1) newDecal.Parent = head return true end local function applyEmitterData(emitter, src) pcall(function() emitter.Color = src.Color end) pcall(function() emitter.Brightness = src.Brightness end) pcall(function() emitter.LightEmission = src.LightEmission end) pcall(function() emitter.Lifetime = src.Lifetime end) pcall(function() emitter.Rate = src.Rate end) pcall(function() emitter.Speed = src.Speed end) pcall(function() emitter.SpreadAngle = src.SpreadAngle end) pcall(function() emitter.Rotation = src.Rotation end) pcall(function() emitter.RotSpeed = src.RotSpeed end) pcall(function() emitter.Size = src.Size end) pcall(function() emitter.Transparency = src.Transparency end) pcall(function() emitter.VelocityInheritance = src.VelocityInheritance end) pcall(function() emitter.Acceleration = src.Acceleration end) pcall(function() emitter.Drag = src.Drag end) pcall(function() emitter.Texture = src.Texture end) pcall(function() emitter.LockedToPart = src.LockedToPart end) pcall(function() emitter.EmissionDirection = src.EmissionDirection end) pcall(function() emitter.Enabled = src.Enabled end) end function applyAllEffectsToCorpseClone(clone, savedData) if not clone or not savedData then return 0, 0, 0, false end if clone:GetAttribute("CorpseBloodRestored") then return 0, 0, 0, false end clone:SetAttribute("CorpseBloodRestored", true) clone:SetAttribute("BloodDecalsRestored", true) clone:SetAttribute("BloodEffectsRestored", true) local decalsRestored = 0 local emittersRestored = 0 local trailsRestored = 0 local faceRestored = false for _, a in ipairs(savedData.Attachments or {}) do local target = resolveCorpseTarget(clone, a.Path) if target and target:IsA("BasePart") and not isAccessoryOrToolPart(target) then local existing = target:FindFirstChild(a.Name) if existing then existing:Destroy() end local att = Instance.new("Attachment") att.Name = a.Name att.Position = a.Position att.Orientation = a.Orientation att.Parent = target end end for _, d in ipairs(savedData.Decals or {}) do local target = resolveCorpseTarget(clone, d.Path) if target and target:IsA("BasePart") and not isAccessoryOrToolPart(target) then local newDecal = Instance.new("Decal") newDecal.Name = d.Name or "BloodDecal" newDecal.Texture = d.Texture newDecal.Face = d.Face newDecal.Color3 = d.Color3 newDecal.Transparency = math.clamp(d.Transparency or 0, 0, 1) newDecal.Parent = target decalsRestored += 1 end end for _, e in ipairs(savedData.Emitters or {}) do local target = resolveCorpseTarget(clone, e.Path) if target and target:IsA("BasePart") and not isAccessoryOrToolPart(target) then local existing = target:FindFirstChild(e.Name) if existing then existing:Destroy() end local emitter = Instance.new("ParticleEmitter") emitter.Name = e.Name applyEmitterData(emitter, e) emitter.Parent = target emittersRestored += 1 end end for _, t in ipairs(savedData.Trails or {}) do local target = resolveCorpseTarget(clone, t.Path) if target and target:IsA("BasePart") and not isAccessoryOrToolPart(target) then local existing = target:FindFirstChild(t.Name) if existing then existing:Destroy() end local a0 = target:FindFirstChild("BloodDripA0") local a1 = target:FindFirstChild("BloodDripA1") if a0 and a1 then local trail = Instance.new("Trail") trail.Name = t.Name trail.Attachment0 = a0 trail.Attachment1 = a1 trail.Texture = t.Texture trail.Color = t.Color trail.Transparency = t.Transparency trail.WidthScale = t.WidthScale trail.Lifetime = t.Lifetime trail.FaceCamera = t.FaceCamera trail.Parent = target trailsRestored += 1 end end end if savedData.Face then faceRestored = applyFaceToCorpseClone(clone, savedData.Face) end if savedData.HeadTransparency and savedData.HeadTransparency >= 1 then local cloneHead = clone:FindFirstChild("Head") if cloneHead then cloneHead.Transparency = 1 cloneHead.CanCollide = false cloneHead.CanQuery = false cloneHead.CanTouch = false for _, ch in ipairs(cloneHead:GetDescendants()) do if isAccessoryOrToolPart(ch) then -- не трогаем — обработаем ниже через hideAccessoriesOnHead elseif ch:IsA("Decal") or ch:IsA("Texture") then ch.Transparency = 1 elseif ch:IsA("ParticleEmitter") then if ch.Name ~= "NeckBloodEmitter" then ch.Enabled = false end elseif ch:IsA("BasePart") then ch.Transparency = 1 ch.CanCollide = false end end end -- НОВОЕ: прячем аксессуары на голове клона-трупа hideAccessoriesOnHead(clone) end if debugEnabled then print(string.format("[BloodFX] corpse clone transfer: decals=%d emitters=%d trails=%d face=%s", decalsRestored, emittersRestored, trailsRestored, tostring(faceRestored))) end return decalsRestored, emittersRestored, trailsRestored, faceRestored end local function watchForCorpseClone(deadChar, savedData, snapshot) if not deadChar or not savedData then return end local hasAnything = (#savedData.Decals > 0) or (#savedData.Emitters > 0) or (#savedData.Trails > 0) or (#savedData.Attachments > 0) or savedData.Face ~= nil or (savedData.HeadTransparency and savedData.HeadTransparency >= 1) if not hasAnything then return end local deadPlayer = Players:GetPlayerFromCharacter(deadChar) local known = snapshot if not known then known = {} for _, plr in ipairs(Players:GetPlayers()) do if plr.Character then known[plr.Character] = true end end for _, obj in ipairs(workspace:GetChildren()) do if obj:IsA("Model") then known[obj] = true end end end known[deadChar] = true local expiresAt = os.clock() + 25 local applied = false local connDesc, connChild local function disconnectAll() if connDesc then connDesc:Disconnect() connDesc = nil end if connChild then connChild:Disconnect() connChild = nil end end local function isCorpseLike(model) if not model or not model:IsA("Model") then return false end if model == deadChar then return false end if known[model] then return false end if model:GetAttribute("CorpseBloodRestored") then return false end if model:GetAttribute("IsClientRagdoll") then return false end local hum = model:FindFirstChildOfClass("Humanoid") if not hum then return false end local hasTorso = model:FindFirstChild("Torso") or model:FindFirstChild("UpperTorso") local hasHead = model:FindFirstChild("Head") if not (hasTorso and hasHead) then return false end local owner = Players:GetPlayerFromCharacter(model) if owner and owner ~= deadPlayer then return false end return true end local function tryApply(model) if applied then return end if isCorpseLike(model) then applied = true disconnectAll() if debugEnabled then print("[BloodFX] corpse clone detected:", model:GetFullName()) end task.defer(applyAllEffectsToCorpseClone, model, savedData) end end for _, obj in ipairs(workspace:GetChildren()) do if isCorpseLike(obj) then tryApply(obj) if applied then return end end end connDesc = workspace.DescendantAdded:Connect(function(obj) if applied or os.clock() > expiresAt then disconnectAll() return end if obj:IsA("Model") then tryApply(obj) end end) connChild = workspace.ChildAdded:Connect(function(obj) if applied or os.clock() > expiresAt then disconnectAll() return end if obj:IsA("Model") then tryApply(obj) end end) task.delay(1, function() if applied or os.clock() > expiresAt then return end for _, obj in ipairs(workspace:GetChildren()) do if isCorpseLike(obj) then tryApply(obj) if applied then return end end end end) task.delay(25, disconnectAll) end local function setupEntity(char) if not char then return end if processedModels[char] then return end if char:GetAttribute("IsClientRagdoll") or char:GetAttribute("ClientRagdolled") then return end local humanoid = char:FindFirstChildOfClass("Humanoid") if not humanoid then return end processedModels[char] = true registerCharacterModelCached(char) applyCharacterCollisionGroup(char) char.DescendantAdded:Connect(function(d) invalidateModelPartsCache(char) if d:IsA("BasePart") and not isAccessoryOrToolPart(d) then setCollisionGroupSafe(d, COLLISION_GROUP_CHARACTER) end end) humanoid.BreakJointsOnDeath = not RAGDOLL_ENABLED humanoid.RequiresNeck = not RAGDOLL_ENABLED local lastHealth = humanoid.Health local recentTouches = {} local accumulatedHeal = 0 local healThreshold = 5 local isRemovingFull = false local lastSpawnTime = 0 local connections = {} local corpseSnapshot = nil local accessoryPreservedEarly = false table.insert(connections, humanoid.HealthChanged:Connect(function(newHealth) if newHealth <= 0 then if not corpseSnapshot then corpseSnapshot = {} for _, plr in ipairs(Players:GetPlayers()) do if plr.Character then corpseSnapshot[plr.Character] = true end end for _, obj in ipairs(workspace:GetChildren()) do if obj:IsA("Model") then corpseSnapshot[obj] = true end end end accessoryPreservedEarly = true end end)) local function pushRecentTouch(part, other) if not part then return end local snapshot = nil if other and other:IsA("BasePart") then snapshot = {position = other.Position, velocity = other.AssemblyLinearVelocity} end table.insert(recentTouches, {part = part, other = other, time = os.clock(), snapshot = snapshot}) while #recentTouches > 12 do table.remove(recentTouches, 1) end end local IGNORE_TOUCH_NAMES = { ["Baseplate"] = true, ["Blood"] = true, ["BloodPuddle"] = true, ["BloodDrop"] = true, ["BloodSplat"] = true, ["BlPart"] = true, ["BloodPool"] = true, ["CP"] = true, ["BloodMist"] = true, ["BloodImpact"] = true, ["BloodMicroPuddle"] = true, ["BloodGib"] = true, ["ArterialSpray"] = true, ["Collision"] = true, } local function onPartTouched(child, other) if not other or not other:IsA("BasePart") then return end if other:IsDescendantOf(char) then return end if IGNORE_TOUCH_NAMES[other.Name] then return end registerProjectile(other) pushRecentTouch(child, other) end local touchedConnections = {} local KEY_PARTS = { Head = true, Torso = true, UpperTorso = true, LowerTorso = true, HumanoidRootPart = true, LeftUpperArm = true, LeftLowerArm = true, LeftHand = true, RightUpperArm = true, RightLowerArm = true, RightHand = true, LeftUpperLeg = true, LeftLowerLeg = true, LeftFoot = true, RightUpperLeg = true, RightLowerLeg = true, RightFoot = true, ["Right Arm"] = true, ["Left Arm"] = true, ["Right Leg"] = true, ["Left Leg"] = true, } local function hookPart(part) if not part or not part:IsA("BasePart") then return end if not KEY_PARTS[part.Name] then return end if part:GetAttribute("BloodTouchedHooked") then return end local current = part while current do if current:IsA("Tool") or current:IsA("Accessory") then return end current = current.Parent end part:SetAttribute("BloodTouchedHooked", true) local c = part.Touched:Connect(function(other) onPartTouched(part, other) end) table.insert(touchedConnections, c) end for _, d in ipairs(char:GetDescendants()) do if d:IsA("BasePart") and not isAccessoryOrToolPart(d) then hookPart(d) end end table.insert(connections, char.DescendantAdded:Connect(function(child) if child:IsA("BasePart") and not isAccessoryOrToolPart(child) then hookPart(child) end end)) local function getAttackerRoot(attackerPart) local current = attackerPart while current and current ~= workspace do if current:IsA("Tool") then return current end if current:IsA("Model") and current:FindFirstChildOfClass("Humanoid") then return current end current = current.Parent end return attackerPart end local raycastResolveParams = nil local raycastResolveParamsKey = nil local refineParamsCache = nil local function raycastResolve(attackerPart, snapshot, targetPos) if not attackerPart or not attackerPart.Parent or not attackerPart:IsA("BasePart") then return nil end local origin = (snapshot and snapshot.position) or attackerPart.Position local dir = targetPos - origin if dir.Magnitude < 0.01 then return nil end local attackerRoot = getAttackerRoot(attackerPart) if not raycastResolveParams or raycastResolveParamsKey ~= attackerRoot then local excludeList = {attackerRoot, newPartsFolder} for _, c in ipairs(getAllCharacterModels()) do if c ~= char then table.insert(excludeList, c) end end raycastResolveParams = RaycastParams.new() raycastResolveParams.FilterType = Enum.RaycastFilterType.Exclude raycastResolveParams.FilterDescendantsInstances = excludeList raycastResolveParams.IgnoreWater = true raycastResolveParamsKey = attackerRoot end local bestPart, bestPos, bestDir, bestScore = nil, nil, nil, math.huge local fastVelocity = snapshot and snapshot.velocity or nil local fastSpeed = fastVelocity and fastVelocity.Magnitude or 0 local velDir = nil if fastVelocity and fastVelocity.Magnitude > 10 then velDir = fastVelocity.Unit elseif attackerPart.AssemblyLinearVelocity.Magnitude > 10 then velDir = attackerPart.AssemblyLinearVelocity.Unit end if velDir then local rootPart = char:FindFirstChild("HumanoidRootPart") or char.PrimaryPart if rootPart then local rayLen = (rootPart.Position - origin).Magnitude + 8 local shot = workspace:Raycast(origin, velDir * rayLen, raycastResolveParams) if shot then local inst = shot.Instance local cur, inChar = inst, false while cur and cur ~= workspace do if cur == char then inChar = true break end cur = cur.Parent end if inChar and inst:IsA("BasePart") and inst.Name ~= "HumanoidRootPart" and inst.Transparency < 1 and not isAccessoryOrToolPart(inst) then return inst, shot.Position, velDir end end end end for _, limb in ipairs(getCachedModelParts(char)) do if limb.Name ~= "HumanoidRootPart" and limb.Transparency < 1 and not isAccessoryOrToolPart(limb) then local limbDir = limb.Position - origin local dist = limbDir.Magnitude if dist > 0.01 then local result = workspace:Raycast(origin, limbDir, raycastResolveParams) if result and result.Instance == limb then local proxToTarget = targetPos and (limb.Position - targetPos).Magnitude or 0 local score = dist + proxToTarget * 0.5 if fastSpeed > 30 then local along = fastVelocity.Unit:Dot(limbDir.Unit) score = score * (1.6 - math.clamp(along, 0, 1) * 0.6) end if score < bestScore then bestScore = score bestPart = result.Instance bestPos = result.Position bestDir = limbDir.Unit end end end end end if bestPart then return bestPart, bestPos, bestDir end return nil end -- =============================================== -- v12.5: УМНОЕ ОПРЕДЕЛЕНИЕ МЕСТА УРОНА -- Если прежние методы (рейкасты, касания, скан окрестностей) -- не сработали — НЕ откатываемся сразу на торс, а пытаемся -- вычислить повреждённую конечность по физике. -- =============================================== local limbVelSnapshot = setmetatable({}, {__mode = "k"}) local rootVelSnapshot = nil table.insert(connections, RunService.Heartbeat:Connect(function() local rootPart = char:FindFirstChild("HumanoidRootPart") or char.PrimaryPart if rootPart then rootVelSnapshot = rootPart.AssemblyLinearVelocity end for _, limb in ipairs(getCachedModelParts(char)) do if limb ~= rootPart and limb.Name ~= "HumanoidRootPart" and limb.Transparency < 1 and not isAccessoryOrToolPart(limb) then limbVelSnapshot[limb] = limb.AssemblyLinearVelocity end end end)) -- Анализ импульса: конечность, чья скорость сильнее всего изменилась -- относительно общего движения тела — та, по которой пришёлся удар. local function resolveHitByImpulseSnapshot() local rootPart = char:FindFirstChild("HumanoidRootPart") or char.PrimaryPart if not rootPart then return nil end local rootDelta = rootPart.AssemblyLinearVelocity - (rootVelSnapshot or rootPart.AssemblyLinearVelocity) local bestPart, bestScore = nil, 2.5 for limb, prevVel in pairs(limbVelSnapshot) do if limb and limb.Parent and limb:IsA("BasePart") and limb.Name ~= "HumanoidRootPart" and limb.Transparency < 1 and not isAccessoryOrToolPart(limb) then local limbDelta = limb.AssemblyLinearVelocity - prevVel - rootDelta local score = limbDelta.Magnitude if score > bestScore then bestScore = score bestPart = limb end end end if bestPart then local dir = bestPart.AssemblyLinearVelocity if dir.Magnitude > 0.01 then dir = dir.Unit else dir = Vector3.new(0, 1, 0) end return bestPart, bestPart.Position, dir end return nil end -- Сканирование геометрии вокруг КАЖДОЙ конечности (а не только рута): -- если рядом с рукой/ногой/головой вплотную лежит объект — скорее всего удар туда. local function resolveHitByLimbProximity() local rootPart = char:FindFirstChild("HumanoidRootPart") or char.PrimaryPart if not rootPart then return nil end local overlapParams = OverlapParams.new() overlapParams.FilterType = Enum.RaycastFilterType.Exclude overlapParams.FilterDescendantsInstances = {char, newPartsFolder} local bestPart, bestDist = nil, 3.5 for _, limb in ipairs(getCachedModelParts(char)) do if limb.Name ~= "HumanoidRootPart" and limb.Transparency < 1 and not isAccessoryOrToolPart(limb) then local nearby = workspace:GetPartBoundsInRadius(limb.Position, 2, overlapParams) for _, p in ipairs(nearby) do if p:IsA("BasePart") and not isPartOfCharacter(p) and not isAccessoryOrToolPart(p) and p.Transparency < 1 and p.CanCollide then local dist = (p.Position - limb.Position).Magnitude if dist < bestDist then bestDist = dist bestPart = limb end end end end end if bestPart then local dir = rootPart.Position - bestPart.Position if dir.Magnitude > 0.01 then dir = dir.Unit else dir = Vector3.new(0, 1, 0) end return bestPart, bestPart.Position, dir end return nil end -- Урон от падения: если персонаж падал/приземлялся — кровь на ноги, а не на торс. local function resolveHitByFall() local rootPart = char:FindFirstChild("HumanoidRootPart") or char.PrimaryPart if not rootPart then return nil end local state = humanoid:GetState() local isFalling = state == Enum.HumanoidStateType.Freefall or state == Enum.HumanoidStateType.Landed or state == Enum.HumanoidStateType.FallingDown local wasFallingFast = rootVelSnapshot and rootVelSnapshot.Y < -25 if not isFalling and not wasFallingFast then return nil end local legNames = {"LeftFoot", "RightFoot", "LeftLowerLeg", "RightLowerLeg", "LeftLeg", "Right Leg"} for _, name in ipairs(legNames) do local leg = char:FindFirstChild(name) if leg and leg:IsA("BasePart") and leg.Transparency < 1 and not isAccessoryOrToolPart(leg) then return leg, leg.Position, Vector3.new(0, 1, 0) end end return nil end local function resolveHitInfo() local now = os.clock() local v4list = v4HitRecords[char] if v4list then for i = #v4list, 1, -1 do local record = v4list[i] if record.part and record.part.Parent and (now - record.time) <= V4_HIT_WINDOW then local hitPart, hitPos, hitDir = record.part, record.pos, record.dir local drift = (hitPart.Position - hitPos).Magnitude if drift > 0.05 then if not refineParamsCache then refineParamsCache = RaycastParams.new() refineParamsCache.FilterType = Enum.RaycastFilterType.Exclude local excludeList = {char, newPartsFolder} for _, c in ipairs(getAllCharacterModels()) do if c ~= char then table.insert(excludeList, c) end end refineParamsCache.FilterDescendantsInstances = excludeList refineParamsCache.IgnoreWater = true end local refine = workspace:Raycast(hitPos - hitDir * 0.2, hitDir * (drift + 0.5), refineParamsCache) if refine and refine.Instance == hitPart then hitPos = refine.Position end end return hitPart, hitPos, hitDir end end end local root = char:FindFirstChild("HumanoidRootPart") or char:FindFirstChild("Torso") or char:FindFirstChild("UpperTorso") or char.PrimaryPart local resolvedPart, resolvedPos, resolvedDir, resolvedScore = nil, nil, nil, math.huge local exactTouchParams local staticPart, staticPos, staticDir, staticScore = nil, nil, nil, math.huge for i = #recentTouches, 1, -1 do local entry = recentTouches[i] if entry.part and entry.part.Parent and (now - entry.time) <= HIT_WINDOW then local attacker = entry.other if attacker and attacker.Parent and attacker:IsA("BasePart") then local age = now - entry.time local touchedPart = entry.part if touchedPart.Transparency < 1 and touchedPart.Name ~= "HumanoidRootPart" and not isAccessoryOrToolPart(touchedPart) then local vel = (entry.snapshot and entry.snapshot.velocity) or attacker.AssemblyLinearVelocity local isStaticAttacker = attacker.Anchored and vel.Magnitude <= 4 local origin = (entry.snapshot and entry.snapshot.position) or attacker.Position local dir = touchedPart.Position - origin local pos = nil local hitDir = dir.Magnitude > 0.01 and dir.Unit or Vector3.new(0, 1, 0) if dir.Magnitude > 0.05 then if not exactTouchParams then local excludeList = {newPartsFolder} for _, c in ipairs(getAllCharacterModels()) do if c ~= char then table.insert(excludeList, c) end end exactTouchParams = RaycastParams.new() exactTouchParams.FilterType = Enum.RaycastFilterType.Exclude exactTouchParams.FilterDescendantsInstances = excludeList exactTouchParams.IgnoreWater = true end local exact = workspace:Raycast(origin, dir, exactTouchParams) if exact and exact.Instance == touchedPart then pos = exact.Position hitDir = dir.Unit end end if isStaticAttacker then if age < staticScore then staticScore = age staticPart, staticPos, staticDir = touchedPart, pos, hitDir end elseif age < resolvedScore then resolvedScore = age resolvedPart, resolvedPos, resolvedDir = touchedPart, pos, hitDir end end end end end if resolvedPart then return resolvedPart, resolvedPos, resolvedDir end if root then local overlapParams = OverlapParams.new() overlapParams.FilterType = Enum.RaycastFilterType.Exclude overlapParams.FilterDescendantsInstances = {char, newPartsFolder} local nearby = workspace:GetPartBoundsInRadius(root.Position, 14, overlapParams) local best, bestScore = nil, math.huge for _, p in ipairs(nearby) do if p:IsA("BasePart") and not isPartOfCharacter(p) and not isAccessoryOrToolPart(p) then local toChar = root.Position - p.Position local dist = toChar.Magnitude if dist > 0.01 then local vel = p.AssemblyLinearVelocity local movingToward = vel.Magnitude > 4 and vel.Unit:Dot(toChar.Unit) > 0.4 local isStaticGeometry = p.Anchored and vel.Magnitude <= 4 local visible = p.Transparency < 1 if not isStaticGeometry and (visible or movingToward) then local score = dist * (movingToward and 0.2 or 1) if score < bestScore then bestScore = score best = p end end end end end if best then local hitPart, hitPos, hitDir = raycastResolve(best, nil, root.Position) if hitPart then return hitPart, hitPos, hitDir end end end if staticPart then return staticPart, staticPos, staticDir end -- v12.5: умные фолбэки вместо мгновенного отката на торс local impulsePart, impulsePos, impulseDir = resolveHitByImpulseSnapshot() if impulsePart then return impulsePart, impulsePos, impulseDir end local proximityPart, proximityPos, proximityDir = resolveHitByLimbProximity() if proximityPart then return proximityPart, proximityPos, proximityDir end local fallPart, fallPos, fallDir = resolveHitByFall() if fallPart then return fallPart, fallPos, fallDir end return getFallbackHitPart(char), nil, Vector3.new(0, 1, 0) end table.insert(connections, humanoid.HealthChanged:Connect(function(newHealth) local damage = lastHealth - newHealth lastHealth = newHealth if char == player.Character then updateHeartbeat(humanoid) if damage > 0 and SCREEN_BLOOD_ENABLED then spawnScreenBlood(damage) end end if damage < 0 then local healAmount = -damage if healAmount > 10 then removeBloodDecals(char, math.random(3, 6)) accumulatedHeal = 0 else accumulatedHeal = accumulatedHeal + healAmount while accumulatedHeal >= healThreshold do removeBloodDecals(char, math.random(1, 2)) accumulatedHeal = accumulatedHeal - healThreshold end end end if newHealth >= humanoid.MaxHealth and not isRemovingFull then isRemovingFull = true task.spawn(function() while char and char.Parent do local decals = getBloodDecals(char) if #decals == 0 then break end local decal = decals[math.random(1, #decals)] if decal and decal.Parent then fadeOutDecal(decal) end task.wait(3) end isRemovingFull = false end) end if damage > 0 then if char:GetAttribute("ClientRagdolled") or char:GetAttribute("IsClientRagdoll") then table.clear(recentTouches) return end local now = os.clock() local isKill = newHealth <= 0 local heavyLoad = isHeavyLoad() local interval = heavyLoad and dynamic.MIN_SPAWN_INTERVAL_HEAVY or dynamic.MIN_SPAWN_INTERVAL local canSpawnVisuals = unlimitedMode or isKill or (now - lastSpawnTime >= interval) local hitPart, exactHitPos, exactHitDir = resolveHitInfo() v4HitRecords[char] = nil if hitPart and isAccessoryOrToolPart(hitPart) then local mapped = findNearestVisibleBodyPart(char, exactHitPos or hitPart.Position) hitPart = mapped or getFallbackHitPart(char) if not mapped then exactHitPos = nil exactHitDir = nil end end if hitPart and isAccessoryOrToolPart(hitPart) then hitPart = getFallbackHitPart(char) exactHitPos = nil exactHitDir = nil end if hitPart and hitPart.Name == "HumanoidRootPart" then local mapped = findNearestVisibleBodyPart(char, exactHitPos or hitPart.Position) if mapped then hitPart = mapped end end local hitPos = exactHitPos or (hitPart and hitPart.Position or char:GetPivot().Position) local hitDir = exactHitDir or Vector3.new(0, 1, 0) local tooFar = isFarFromCamera(hitPos) local isExplosionDeath = (newHealth <= 0 and checkExplosionNear(char)) if isExplosionDeath then local soundPart = hitPart or getTorsoPart(char) if soundPart and not tooFar then local s = Instance.new("Sound") s.Name = "ExplosionDeathSound" setupSound(s) s.SoundId = "rbxassetid://" .. EXPLOSION_DEATH_SOUND s.Parent = soundPart s:Play() Debris:AddItem(s, 5) end if canSpawnVisuals and not tooFar then lastSpawnTime = now local explosionFaces = { Enum.NormalId.Front, Enum.NormalId.Back, Enum.NormalId.Left, Enum.NormalId.Right, Enum.NormalId.Top, Enum.NormalId.Bottom, } for _, part in ipairs(char:GetChildren()) do if part:IsA("BasePart") and part.Name ~= "HumanoidRootPart" and part.Name ~= "Head" and not isAccessoryOrToolPart(part) then local existingDecals = {} for _, child in ipairs(part:GetChildren()) do if child:IsA("Decal") and child.Name == "BloodDecal" then table.insert(existingDecals, child) end end for _, face in ipairs(explosionFaces) do local decal = Instance.new("Decal") decal.Name = "BloodDecal" decal.Texture = "rbxassetid://" .. BLOODSIDS[math.random(1, #BLOODSIDS)] decal.Face = face decal.Transparency = 0 decal.Color3 = Color3.new(1, 1, 1) decal.Parent = part end for _, child in ipairs(part:GetChildren()) do if child:IsA("Decal") and child.Name == "BloodDecal" then table.insert(existingDecals, child) end end while not unlimitedMode and #existingDecals > dynamic.BLOOD_DECAL_LIMIT_PER_PART do local oldest = table.remove(existingDecals, 1) if oldest and oldest.Parent then oldest:Destroy() end end end end local pParams = RaycastParams.new() pParams.FilterType = Enum.RaycastFilterType.Exclude pParams.FilterDescendantsInstances = getAllCharacterModels() pParams.IgnoreWater = true local floorRes = workspace:Raycast(hitPos, Vector3.new(0, -12, 0), pParams) if floorRes and floorRes.Instance and not isPartOfCharacter(floorRes.Instance) and not isAccessoryOrToolPart(floorRes.Instance) then createPuddle(char, floorRes.Position + floorRes.Normal*0.02, floorRes.Normal, floorRes.Instance, 2) end local explosionAnchor = hitPart or getTorsoPart(char) if explosionAnchor and not isAccessoryOrToolPart(explosionAnchor) then task.spawn(function() pcall(function() bloodService.CreateBlood(explosionAnchor, char, 0.02, 6, hitDir, true) end) end) end if GIBS_ENABLED then for _ = 1, 8 do spawnGib(hitPos + Vector3.new(math.random(-2,2), math.random(0,2), math.random(-2,2)), Vector3.new(math.random(-1,1), math.random(0,1), math.random(-1,1)), math.random(15, 30) / 100) end end end changeFace(char) else if hitPart and canSpawnVisuals then lastSpawnTime = now local isHeadshot = (hitPart.Name == "Head") local killed = (newHealth <= 0) local isRootPart = (hitPart.Name == "HumanoidRootPart") local willHideHead = isHeadshot and killed if not willHideHead then if killed or damage >= HEAVY_HIT_THRESHOLD then playGoreSound(hitPart, killed) end end if char == player.Character and killed and CAMERA_SHAKE_ENABLED then shakeCamera(2.5, 0.4) end if not isRootPart and not tooFar then if not isAccessoryOrToolPart(hitPart) then local decalTarget = hitPart local forceFace = nil if willHideHead then local torsoForDecal = char:FindFirstChild("UpperTorso") or char:FindFirstChild("Torso") if torsoForDecal and torsoForDecal:IsA("BasePart") then decalTarget = torsoForDecal forceFace = Enum.NormalId.Top end end local decalCount = heavyLoad and 2 or 3 for k = 1, decalCount do local offsetPos = hitPos + Vector3.new(math.random(-5,5)/100, math.random(-5,5)/100, math.random(-5,5)/100) local face if forceFace then face = forceFace else face = getFace(decalTarget, offsetPos) if decalTarget.Name == "Head" then face = Enum.NormalId.Front end end local decal = Instance.new("Decal") decal.Name = "BloodDecal" decal.Texture = "rbxassetid://" .. BLOODSIDS[math.random(1, #BLOODSIDS)] decal.Face = face decal.Transparency = 1 decal.Color3 = Color3.new(1, 1, 1) decal.Parent = decalTarget local bloodDecalsOnPart = {} for _, child in ipairs(decalTarget:GetChildren()) do if child:IsA("Decal") and child.Name == "BloodDecal" then table.insert(bloodDecalsOnPart, child) end end while not unlimitedMode and #bloodDecalsOnPart > dynamic.BLOOD_DECAL_LIMIT_PER_PART do local oldest = table.remove(bloodDecalsOnPart, 1) if oldest and oldest.Parent then oldest:Destroy() end end TweenService:Create(decal, TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Transparency = 0}):Play() end startBleeding(hitPart) spawnBloodDrip(hitPart, hitPos) task.spawn(makeBlood, char, hitPart, hitPos, hitDir, math.clamp(math.ceil(damage/8), 1, 4)) spawnSplats(char, hitPos or hitPart.Position) if killed or damage >= HEAVY_HIT_THRESHOLD then spawnArterialSpray(hitPart, hitDir) end if killed or damage >= HEAVY_HIT_THRESHOLD then local projectileCount = killed and 4 or 2 local bloodAnchor = hitPart task.spawn(function() pcall(function() bloodService.CreateBlood(bloodAnchor, char, 0.02, projectileCount, hitDir, killed) end) end) end local pParams = RaycastParams.new() pParams.FilterType = Enum.RaycastFilterType.Exclude pParams.FilterDescendantsInstances = getAllCharacterModels() pParams.IgnoreWater = true local floorRes = workspace:Raycast(hitPos, Vector3.new(0, -12, 0), pParams) if floorRes and floorRes.Instance and not isPartOfCharacter(floorRes.Instance) and not isAccessoryOrToolPart(floorRes.Instance) then createPuddle(char, floorRes.Position + floorRes.Normal*0.02, floorRes.Normal, floorRes.Instance, math.clamp(damage/20, 0.8, 1.6)) end if consumeBudget(1) then local emitter = Instance.new("ParticleEmitter") emitter.Name = "BloodEffect" emitter.Color = ColorSequence.new(BLOOD_IMPACT_HI, BLOOD_IMPACT_LO) emitter.Lifetime = NumberRange.new(0.5, 1.0) emitter.Rate = 0 emitter.Speed = NumberRange.new(5, 15) emitter.SpreadAngle = Vector2.new(360, 360) emitter.VelocityInheritance = 0.1 emitter.Texture = BLOOD_TEXTURE emitter.Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.05), NumberSequenceKeypoint.new(0.7, 0.3), NumberSequenceKeypoint.new(1, 1)}) local impactScale = math.clamp(damage / 15, 0.7, 1.8) emitter.Size = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.12 * impactScale), NumberSequenceKeypoint.new(0.5, 0.05 * impactScale), NumberSequenceKeypoint.new(1, 0.01)}) emitter.Rotation = NumberRange.new(0, 360) emitter.RotSpeed = NumberRange.new(-220, 220) emitter.Drag = 3 emitter.Acceleration = Vector3.new(0, -28, 0) emitter.Parent = hitPart emitter:Emit(math.clamp(10 + math.ceil(damage * 0.5), 10, 22)) task.delay(3, function() if emitter and emitter.Parent then emitter:Destroy() end end) end spawnImpactBurst(hitPos, Vector3.new(0, 1, 0), damage >= HEAVY_HIT_THRESHOLD or killed, hitDir) if killed and GIBS_ENABLED then for _ = 1, math.random(4, 7) do spawnGib(hitPos, hitDir, math.random(15, 28) / 100) end end end end local isTorso = (hitPart.Name == "Torso" or hitPart.Name == "UpperTorso" or hitPart.Name == "LowerTorso") if isHeadshot then if willHideHead then changeFace(char) local head = char:FindFirstChild("Head") if head then local snd = Instance.new("Sound") snd.SoundId = "rbxassetid://89882424353628" snd.Volume = 1 snd.Parent = head snd:Play() Debris:AddItem(snd, 10) local torso = char:FindFirstChild("UpperTorso") or char:FindFirstChild("Torso") local neckAtt = head:FindFirstChild("NeckAttachment") or head:FindFirstChild("Neck") or (torso and torso:FindFirstChild("NeckAttachment")) or (torso and torso:FindFirstChild("Neck")) local neckPos if neckAtt and neckAtt:IsA("Attachment") then local ok, wp = pcall(function() return neckAtt.WorldPosition end) if ok and wp then neckPos = wp end end if not neckPos then if torso then neckPos = torso.Position + Vector3.new(0, torso.Size.Y * 0.5, 0) else neckPos = head.Position end end local emitterParent if neckAtt and neckAtt:IsA("Attachment") then emitterParent = neckAtt else local neckPart = Instance.new("Part") neckPart.Name = "NeckBloodSpray" neckPart.Size = Vector3.new(0.1, 0.1, 0.1) neckPart.Transparency = 1 neckPart.Anchored = true neckPart.CanCollide = false neckPart.CanQuery = false neckPart.CanTouch = false neckPart.CFrame = CFrame.new(neckPos) neckPart.Parent = newPartsFolder emitterParent = neckPart Debris:AddItem(neckPart, 3) end local neckEmitter = Instance.new("ParticleEmitter") neckEmitter.Name = "NeckBloodEmitter" neckEmitter.Texture = BLOOD_TEXTURE neckEmitter.Color = ColorSequence.new(BLOOD_PARTICLE_HI, BLOOD_PARTICLE_LO) neckEmitter.Lifetime = NumberRange.new(0.3, 0.9) neckEmitter.Rate = 0 neckEmitter.Speed = NumberRange.new(6, 14) neckEmitter.SpreadAngle = Vector2.new(140, 140) neckEmitter.Rotation = NumberRange.new(0, 360) neckEmitter.RotSpeed = NumberRange.new(-180, 180) neckEmitter.Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.1), NumberSequenceKeypoint.new(0.7, 0.4), NumberSequenceKeypoint.new(1, 1), }) neckEmitter.Size = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.11), NumberSequenceKeypoint.new(0.5, 0.06), NumberSequenceKeypoint.new(1, 0.008), }) neckEmitter.Drag = 3 neckEmitter.Acceleration = Vector3.new(0, -30, 0) neckEmitter.VelocityInheritance = 0.1 neckEmitter.Parent = emitterParent neckEmitter:Emit(15) task.spawn(function() for _ = 1, 10 do if not neckEmitter or not neckEmitter.Parent then break end neckEmitter:Emit(math.random(1, 2)) task.wait(0.09) end end) if emitterParent == neckAtt then task.delay(3, function() if neckEmitter and neckEmitter.Parent then neckEmitter:Destroy() end end) end for _ = 1, 4 do local offset = Vector3.new( math.random(-15, 15) / 100, math.random(-5, 5) / 100, math.random(-15, 15) / 100 ) local dir = Vector3.new( math.random(-10, 10) / 10, math.random(6, 12) / 10, math.random(-10, 10) / 10 ) task.spawn(function() createBloodDrop(char, torso or head, neckPos + offset, dir) end) end -- hideHeadAndItsAccessories теперь также прячет аксессуары на голове hideHeadAndItsAccessories(char) pcall(spawnNeckStumpBlood, char) end else local targetSoundId = killed and HEADSHOT_KILL_SOUNDS[math.random(1, #HEADSHOT_KILL_SOUNDS)] or HEADSHOT_SOUND playHitSoundOn(hitPart, targetSoundId, 1.4) if killed then changeFace(char) playDeathVoice(char) end end else if isTorso then local torsoSoundId = TORSO_SOUNDS[math.random(1, #TORSO_SOUNDS)] playHitSoundOn(hitPart, torsoSoundId, 1.3) else if math.random(1, 3) == 1 and #SCREAM_SOUNDS > 0 then local screamId = SCREAM_SOUNDS[math.random(1, #SCREAM_SOUNDS)] playScream(char, screamId, 1.5) else playHitSoundOn(hitPart, SOUNDS[math.random(1, #SOUNDS)], 1.2) end end if killed then changeFace(char) playDeathVoice(char) end end end end table.clear(recentTouches) end end)) table.insert(connections, humanoid.Died:Connect(function() task.spawn(function() task.wait(0.4) if char and char.Parent then pcall(createBodyPool, char) end end) if RAGDOLL_ENABLED then local savedData = saveAllCharacterBloodData(char) task.wait(0.3) if not char or not char.Parent then return end pcall(ragdollCharacter, char, humanoid, savedData) else task.wait(0.05) local savedData = saveAllCharacterBloodData(char) local hasAnything = (#savedData.Decals > 0) or (#savedData.Emitters > 0) or (#savedData.Trails > 0) or (#savedData.Attachments > 0) or savedData.Face ~= nil or (savedData.HeadTransparency and savedData.HeadTransparency >= 1) if hasAnything then watchForCorpseClone(char, savedData, corpseSnapshot) end end end)) local ancestryConn ancestryConn = char.AncestryChanged:Connect(function(_, parent) if not parent then for _, conn in ipairs(connections) do pcall(function() conn:Disconnect() end) end for _, conn in ipairs(touchedConnections) do pcall(function() conn:Disconnect() end) end ancestryConn:Disconnect() processedModels[char] = nil unregisterCharacterModelCached(char) end end) end local function trySetupModel(model) if not model or not model:IsA("Model") then return end if processedModels[model] then return end if model:GetAttribute("IsClientRagdoll") or model:GetAttribute("ClientRagdolled") then return end if Players:GetPlayerFromCharacter(model) then return end local humanoid = model:FindFirstChildOfClass("Humanoid") if humanoid then task.spawn(function() task.wait(0.5) setupEntity(model) end) else local connection connection = model.DescendantAdded:Connect(function(child) if child:IsA("Humanoid") and not processedModels[model] then connection:Disconnect() task.spawn(function() task.wait(0.5) setupEntity(model) end) end end) local ancConn ancConn = model.AncestryChanged:Connect(function() if not model.Parent then if connection then connection:Disconnect() end if ancConn then ancConn:Disconnect() end end end) end end for _, obj in ipairs(workspace:GetDescendants()) do if obj:IsA("Model") and obj:FindFirstChildOfClass("Humanoid") then registerCharacterModelCached(obj) end end for _, plr in ipairs(Players:GetPlayers()) do if plr.Character then registerCharacterModelCached(plr.Character) setupEntity(plr.Character) end plr.CharacterAdded:Connect(function(char) immediatelyApplyCharacterCollision(char) registerCharacterModelCached(char) task.wait(1) setupEntity(char) end) end Players.PlayerAdded:Connect(function(plr) plr.CharacterAdded:Connect(function(char) immediatelyApplyCharacterCollision(char) registerCharacterModelCached(char) task.wait(1) setupEntity(char) end) end) if player.Character then immediatelyApplyCharacterCollision(player.Character) registerCharacterModelCached(player.Character) end for _, obj in ipairs(workspace:GetDescendants()) do if obj:IsA("Model") and obj:FindFirstChildOfClass("Humanoid") then if not Players:GetPlayerFromCharacter(obj) then trySetupModel(obj) end end end workspace.DescendantAdded:Connect(function(obj) if obj:IsA("Model") then if not Players:GetPlayerFromCharacter(obj) then trySetupModel(obj) end elseif obj:IsA("Humanoid") then local model = obj.Parent if model and model:IsA("Model") and not Players:GetPlayerFromCharacter(model) then if not processedModels[model] then task.spawn(function() task.wait(0.5) setupEntity(model) end) end end end end) local collisionWatchdogAccum = 0 local WATCHDOG_INTERVAL = 1.5 local cameraProtectAccum = 0 local CAMERA_PROTECT_INTERVAL = 0.08 RunService.Heartbeat:Connect(function(dt) cameraProtectAccum += dt if cameraProtectAccum >= CAMERA_PROTECT_INTERVAL then cameraProtectAccum = 0 for model in pairs(ragdollModels) do if model and model.Parent then hideRagdollPartsNearCamera(model) end end end collisionWatchdogAccum += dt if collisionWatchdogAccum < WATCHDOG_INTERVAL then return end collisionWatchdogAccum = 0 pcall(function() PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP_RAGDOLL, COLLISION_GROUP_CHARACTER, true) end) pcall(function() PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP_CHARACTER, COLLISION_GROUP_RAGDOLL, true) end) pcall(function() PhysicsService:CollisionGroupSetCollidable(COLLISION_GROUP_RAGDOLL, COLLISION_GROUP_RAGDOLL, true) end) local lpChar = player.Character if lpChar then for _, d in ipairs(getCachedModelParts(lpChar)) do if d.Parent and d.CollisionGroup ~= COLLISION_GROUP_CHARACTER and not isAccessoryOrToolPart(d) then setCollisionGroupSafe(d, COLLISION_GROUP_CHARACTER) end end end for model in pairs(ragdollModels) do if model and model.Parent then for _, d in ipairs(getCachedModelParts(model)) do if d.Parent and d:IsA("BasePart") and not isAccessoryOrToolPart(d) then if d.CollisionGroup ~= COLLISION_GROUP_RAGDOLL then setCollisionGroupSafe(d, COLLISION_GROUP_RAGDOLL) end if d.Name == "Collision" or d.Name == "CP" then if d.CanCollide ~= true then d.CanCollide = true end else if d.CanCollide ~= false then d.CanCollide = false end end end end end end end) print("blood system v12.4 — head accessories become transparent when head is hidden") local function initUI() local ragdollButton, statusDot, buttonLabel, buttonStroke local breathingTween local function pulseDot(dot) local grow = TweenService:Create(dot, TweenInfo.new(0.12, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Size = UDim2.new(0, 16, 0, 16)}) local shrink = TweenService:Create(dot, TweenInfo.new(0.25, Enum.EasingStyle.Back, Enum.EasingDirection.Out), {Size = UDim2.new(0, 12, 0, 12)}) grow:Play() grow.Completed:Connect(function() shrink:Play() end) end local function setBreathing(enabled) if breathingTween then breathingTween:Cancel() breathingTween = nil end if not statusDot then return end if enabled then breathingTween = TweenService:Create(statusDot, TweenInfo.new(0.9, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, -1, true), {BackgroundTransparency = 0.55}) breathingTween:Play() else statusDot.BackgroundTransparency = 0 end end local function createRagdollButton() local gui = player:WaitForChild("PlayerGui") local existing = gui:FindFirstChild("RagdollButtonGui") if existing then existing:Destroy() end local screenGui = Instance.new("ScreenGui") screenGui.Name = "RagdollButtonGui" screenGui.ResetOnSpawn = false screenGui.IgnoreGuiInset = true screenGui.Parent = gui local shadow = Instance.new("Frame") shadow.Name = "Shadow" shadow.AnchorPoint = Vector2.new(1, 1) shadow.Position = UDim2.new(1, -21, 1, -17) shadow.Size = UDim2.new(0, 200, 0, 56) shadow.BackgroundColor3 = Color3.new(0, 0, 0) shadow.BackgroundTransparency = 0.55 shadow.BorderSizePixel = 0 shadow.ZIndex = 1 shadow.Parent = screenGui local shadowCorner = Instance.new("UICorner") shadowCorner.CornerRadius = UDim.new(0, 16) shadowCorner.Parent = shadow local button = Instance.new("TextButton") button.Name = "ToggleButton" button.AnchorPoint = Vector2.new(1, 1) button.Position = UDim2.new(1, -24, 1, -24) button.Size = UDim2.new(0, 200, 0, 56) button.AutoButtonColor = false button.Text = "" button.BackgroundColor3 = Color3.fromRGB(30, 34, 40) button.BorderSizePixel = 0 button.ZIndex = 2 button.Parent = screenGui local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 16) corner.Parent = button local gradient = Instance.new("UIGradient") gradient.Color = ColorSequence.new({ ColorSequenceKeypoint.new(0, Color3.fromRGB(44, 49, 57)), ColorSequenceKeypoint.new(1, Color3.fromRGB(22, 25, 30)), }) gradient.Rotation = 90 gradient.Parent = button local stroke = Instance.new("UIStroke") stroke.Color = Color3.fromRGB(80, 255, 120) stroke.Thickness = 1.5 stroke.Transparency = 0.35 stroke.Parent = button local dot = Instance.new("Frame") dot.Name = "StatusDot" dot.AnchorPoint = Vector2.new(0, 0.5) dot.Position = UDim2.new(0, 18, 0.5, 0) dot.Size = UDim2.new(0, 12, 0, 12) dot.BackgroundColor3 = Color3.fromRGB(80, 255, 120) dot.BorderSizePixel = 0 dot.ZIndex = 3 dot.Parent = button local dotCorner = Instance.new("UICorner") dotCorner.CornerRadius = UDim.new(1, 0) dotCorner.Parent = dot local label = Instance.new("TextLabel") label.Name = "Label" label.AnchorPoint = Vector2.new(0, 0.5) label.Position = UDim2.new(0, 42, 0.5, -9) label.Size = UDim2.new(1, -55, 0, 18) label.BackgroundTransparency = 1 label.Font = Enum.Font.GothamBold label.TextSize = 15 label.TextXAlignment = Enum.TextXAlignment.Left label.TextColor3 = Color3.fromRGB(235, 235, 240) label.Text = "RAGDOLL: OFF" label.ZIndex = 3 label.Parent = button local sub = Instance.new("TextLabel") sub.Name = "Sub" sub.AnchorPoint = Vector2.new(0, 0.5) sub.Position = UDim2.new(0, 42, 0.5, 11) sub.Size = UDim2.new(1, -55, 0, 14) sub.BackgroundTransparency = 1 sub.Font = Enum.Font.Gotham sub.TextSize = 11 sub.TextXAlignment = Enum.TextXAlignment.Left sub.TextColor3 = Color3.fromRGB(150, 155, 165) sub.Text = "Click or F2" sub.ZIndex = 3 sub.Parent = button button.Size = UDim2.new(0, 0, 0, 0) shadow.Size = UDim2.new(0, 0, 0, 0) TweenService:Create(button, TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.Out), {Size = UDim2.new(0, 200, 0, 56)}):Play() TweenService:Create(shadow, TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.Out), {Size = UDim2.new(0, 200, 0, 56)}):Play() button.MouseEnter:Connect(function() local hoverSound = Instance.new("Sound") hoverSound.SoundId = "rbxassetid://88442833509532" hoverSound.Volume = 0.5 hoverSound.Parent = button hoverSound:Play() Debris:AddItem(hoverSound, 2) TweenService:Create(button, TweenInfo.new(0.18, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Size = UDim2.new(0, 210, 0, 60), BackgroundColor3 = Color3.fromRGB(38, 43, 50)}):Play() TweenService:Create(shadow, TweenInfo.new(0.18, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Size = UDim2.new(0, 210, 0, 60)}):Play() TweenService:Create(stroke, TweenInfo.new(0.18), {Transparency = 0}):Play() end) button.MouseLeave:Connect(function() TweenService:Create(button, TweenInfo.new(0.18, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Size = UDim2.new(0, 200, 0, 56), BackgroundColor3 = Color3.fromRGB(30, 34, 40)}):Play() TweenService:Create(shadow, TweenInfo.new(0.18, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Size = UDim2.new(0, 200, 0, 56)}):Play() TweenService:Create(stroke, TweenInfo.new(0.18), {Transparency = 0.35}):Play() end) button.MouseButton1Down:Connect(function() TweenService:Create(button, TweenInfo.new(0.08, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Size = UDim2.new(0, 194, 0, 53)}):Play() end) button.MouseButton1Up:Connect(function() TweenService:Create(button, TweenInfo.new(0.18, Enum.EasingStyle.Back, Enum.EasingDirection.Out), {Size = UDim2.new(0, 210, 0, 60)}):Play() end) return button, dot, label, stroke end local debugGui, debugLabel local debugFps = 0 local debugFrameCount = 0 local debugFpsTime = 0 local function debugColorHex(color) return string.format("#%02X%02X%02X", math.floor(color.R * 255 + 0.5), math.floor(color.G * 255 + 0.5), math.floor(color.B * 255 + 0.5)) end local DEBUG_COLOR_NORMAL = Color3.fromRGB(80, 220, 120) local DEBUG_COLOR_WARNING = Color3.fromRGB(255, 205, 70) local DEBUG_COLOR_CRITICAL = Color3.fromRGB(255, 75, 75) local DEBUG_COLOR_WHITE = Color3.fromRGB(240, 240, 245) local DEBUG_HEX_NORMAL = debugColorHex(DEBUG_COLOR_NORMAL) local DEBUG_HEX_WARNING = debugColorHex(DEBUG_COLOR_WARNING) local DEBUG_HEX_CRITICAL = debugColorHex(DEBUG_COLOR_CRITICAL) local DEBUG_HEX_WHITE = debugColorHex(DEBUG_COLOR_WHITE) local function debugSpan(text, colorHex) return '' .. text .. '' end local function createDebugHud() if not debugEnabled then return end local gui = player:WaitForChild("PlayerGui") local old = gui:FindFirstChild("BloodSystemDebugGui") if old then old:Destroy() end debugGui = Instance.new("ScreenGui") debugGui.Name = "BloodSystemDebugGui" debugGui.ResetOnSpawn = false debugGui.IgnoreGuiInset = true debugGui.DisplayOrder = 999 debugGui.Parent = gui local panel = Instance.new("Frame") panel.AnchorPoint = Vector2.new(1, 0) panel.Position = UDim2.new(1, -10, 0, 10) panel.Size = UDim2.new(0, 330, 0, 285) panel.BackgroundColor3 = Color3.fromRGB(12, 14, 18) panel.BackgroundTransparency = 0.12 panel.BorderSizePixel = 0 panel.Parent = debugGui local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 8) corner.Parent = panel local stroke = Instance.new("UIStroke") stroke.Color = Color3.fromRGB(90, 95, 105) stroke.Transparency = 0.35 stroke.Thickness = 1 stroke.Parent = panel debugLabel = Instance.new("TextLabel") debugLabel.Position = UDim2.new(0, 10, 0, 8) debugLabel.Size = UDim2.new(1, -20, 1, -16) debugLabel.BackgroundTransparency = 1 debugLabel.Font = Enum.Font.Code debugLabel.TextSize = 14 debugLabel.TextXAlignment = Enum.TextXAlignment.Left debugLabel.TextYAlignment = Enum.TextYAlignment.Top debugLabel.RichText = true debugLabel.TextColor3 = DEBUG_COLOR_WHITE debugLabel.Text = "Blood System DEBUG v12.4\nЗапуск..." debugLabel.Parent = panel end local function collectDebugStats() if not debugEnabled or not debugLabel or not debugLabel.Parent then return end local bloodDrops, bloodSplats, bloodPuddles = 0, 0, 0 local bloodMicroPuddles, bloodPools, bloodMist, bloodGibs = 0, 0, 0, 0 for _, obj in ipairs(newPartsFolder:GetChildren()) do local name = obj.Name if name == "Blood" then bloodDrops += 1 elseif name == "BloodSplat" then bloodSplats += 1 elseif name == "BloodPuddle" then bloodPuddles += 1 elseif name == "BloodMicroPuddle" then bloodMicroPuddles += 1 elseif name == "BloodPool" then bloodPools += 1 elseif name == "BloodMist" then bloodMist += 1 elseif name == "BloodGib" then bloodGibs += 1 end end local bloodDecals, ragdolls, characterCount = 0, 0, 0 for _, model in ipairs(getAllCharacterModels()) do if model and model.Parent then characterCount += 1 for _, obj in ipairs(model:GetDescendants()) do if obj:IsA("Decal") and obj.Name == "BloodDecal" then bloodDecals += 1 end end end end for model in pairs(ragdollModels) do if model and model.Parent then ragdolls += 1 end end local fps = math.floor(debugFps + 0.5) local playersNow = #Players:GetPlayers() local scale = dynamic.scale or 0 local text = debugSpan("BLOOD SYSTEM DEBUG v12.4", DEBUG_HEX_WHITE) .. "\n" .. "Mode: " .. debugSpan(unlimitedMode and "UNLIMITED" or "DYNAMIC", unlimitedMode and DEBUG_HEX_WARNING or DEBUG_HEX_NORMAL) .. "\n" .. "FPS: " .. debugSpan(tostring(fps), fps < 30 and DEBUG_HEX_CRITICAL or (fps < 50 and DEBUG_HEX_WARNING or DEBUG_HEX_NORMAL)) .. "\n" .. "Players: " .. debugSpan(tostring(playersNow), DEBUG_HEX_NORMAL) .. " | Scale: " .. debugSpan(string.format("%.2f", scale), scale <= 0.12 and DEBUG_HEX_CRITICAL or (scale <= 0.22 and DEBUG_HEX_WARNING or DEBUG_HEX_NORMAL)) .. "\n" .. "Generated: " .. debugSpan(tostring(generatedObjectCount or 0), DEBUG_HEX_NORMAL) .. "\n" .. "Blood decals: " .. debugSpan(tostring(bloodDecals), DEBUG_HEX_NORMAL) .. "\n" .. "Blood drops: " .. debugSpan(tostring(bloodDrops), DEBUG_HEX_NORMAL) .. "\n" .. "Blood splats: " .. debugSpan(tostring(bloodSplats), DEBUG_HEX_NORMAL) .. "\n" .. "Blood puddles: " .. debugSpan(tostring(bloodPuddles), DEBUG_HEX_NORMAL) .. "\n" .. "Micro puddles: " .. debugSpan(tostring(bloodMicroPuddles), DEBUG_HEX_NORMAL) .. "\n" .. "Blood pools: " .. debugSpan(tostring(bloodPools), DEBUG_HEX_NORMAL) .. "\n" .. "Blood mist: " .. debugSpan(tostring(bloodMist), DEBUG_HEX_NORMAL) .. "\n" .. "Blood gibs: " .. debugSpan(tostring(bloodGibs), DEBUG_HEX_NORMAL) .. "\n" .. "Ragdolls: " .. debugSpan(tostring(ragdolls), DEBUG_HEX_NORMAL) .. "\n" .. "Characters cached: " .. debugSpan(tostring(characterCount), DEBUG_HEX_NORMAL) if debugLabel and debugLabel.Parent then debugLabel.Text = text end end local debugFpsConnection local debugHudThreadRunning = false local function startDebugHud() if not debugEnabled then return end createDebugHud() if not debugFpsConnection then debugFpsConnection = RunService.Heartbeat:Connect(function(dt) debugFrameCount += 1 debugFpsTime += dt if debugFpsTime >= 0.5 then debugFps = debugFrameCount / debugFpsTime debugFrameCount = 0 debugFpsTime = 0 end end) end if debugHudThreadRunning then return end debugHudThreadRunning = true task.spawn(function() while debugEnabled do if not debugGui or not debugGui.Parent then createDebugHud() end collectDebugStats() task.wait(DEBUG_UPDATE_INTERVAL) end debugHudThreadRunning = false end) end local function setDebugMode(enabled) debugEnabled = enabled if debugEnabled then startDebugHud() else if debugGui then debugGui:Destroy() debugGui = nil end debugLabel = nil if debugFpsConnection then debugFpsConnection:Disconnect() debugFpsConnection = nil end end end local function createToggleMessage(text, color, enabled) local gui = player:WaitForChild("PlayerGui") local existing = gui:FindFirstChild("RagdollToggleMsg") if existing then existing:Destroy() end local screenGui = Instance.new("ScreenGui") screenGui.Name = "RagdollToggleMsg" screenGui.IgnoreGuiInset = true screenGui.ResetOnSpawn = false screenGui.DisplayOrder = 10 screenGui.Parent = gui local card = Instance.new("Frame") card.AnchorPoint = Vector2.new(0.5, 0) card.Position = UDim2.new(0.5, 0, 0, -90) card.Size = UDim2.new(0, 340, 0, 64) card.BackgroundColor3 = Color3.fromRGB(26, 28, 33) card.BackgroundTransparency = 1 card.BorderSizePixel = 0 card.Parent = screenGui local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 14) corner.Parent = card local stroke = Instance.new("UIStroke") stroke.Color = color stroke.Thickness = 1 stroke.Transparency = 1 stroke.Parent = card local accent = Instance.new("Frame") accent.Size = UDim2.new(0, 5, 1, 0) accent.BackgroundColor3 = color accent.BackgroundTransparency = 1 accent.BorderSizePixel = 0 accent.Parent = card local accentCorner = Instance.new("UICorner") accentCorner.CornerRadius = UDim.new(0, 14) accentCorner.Parent = accent local iconBg = Instance.new("Frame") iconBg.AnchorPoint = Vector2.new(0, 0.5) iconBg.Position = UDim2.new(0, 20, 0.5, 0) iconBg.Size = UDim2.new(0, 34, 0, 34) iconBg.BackgroundColor3 = color iconBg.BackgroundTransparency = 1 iconBg.BorderSizePixel = 0 iconBg.Parent = card local iconCorner = Instance.new("UICorner") iconCorner.CornerRadius = UDim.new(1, 0) iconCorner.Parent = iconBg local icon = Instance.new("TextLabel") icon.AnchorPoint = Vector2.new(0.5, 0.5) icon.Position = UDim2.new(0.5, 0, 0.5, 0) icon.Size = UDim2.new(1, 0, 1, 0) icon.BackgroundTransparency = 1 icon.Font = Enum.Font.GothamBold icon.TextSize = 18 icon.TextColor3 = color icon.TextTransparency = 1 icon.Text = enabled and "OK" or "X" icon.Parent = iconBg local label = Instance.new("TextLabel") label.AnchorPoint = Vector2.new(0, 0.5) label.Position = UDim2.new(0, 68, 0.5, -9) label.Size = UDim2.new(1, -85, 0, 20) label.BackgroundTransparency = 1 label.Font = Enum.Font.GothamBold label.TextSize = 16 label.TextXAlignment = Enum.TextXAlignment.Left label.TextColor3 = Color3.fromRGB(240, 240, 245) label.TextTransparency = 1 label.Text = text label.Parent = card local sub = Instance.new("TextLabel") sub.AnchorPoint = Vector2.new(0, 0.5) sub.Position = UDim2.new(0, 68, 0.5, 11) sub.Size = UDim2.new(1, -85, 0, 14) sub.BackgroundTransparency = 1 sub.Font = Enum.Font.Gotham sub.TextSize = 12 sub.TextXAlignment = Enum.TextXAlignment.Left sub.TextColor3 = Color3.fromRGB(160, 163, 170) sub.TextTransparency = 1 sub.Text = "Key F2" sub.Parent = card TweenService:Create(card, TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.Out), {Position = UDim2.new(0.5, 0, 0, 30), BackgroundTransparency = 0}):Play() TweenService:Create(stroke, TweenInfo.new(0.35), {Transparency = 0.5}):Play() TweenService:Create(accent, TweenInfo.new(0.35), {BackgroundTransparency = 0}):Play() TweenService:Create(iconBg, TweenInfo.new(0.35), {BackgroundTransparency = 0.85}):Play() TweenService:Create(icon, TweenInfo.new(0.35), {TextTransparency = 0}):Play() TweenService:Create(label, TweenInfo.new(0.35), {TextTransparency = 0}):Play() TweenService:Create(sub, TweenInfo.new(0.35), {TextTransparency = 0}):Play() task.delay(2.2, function() if not screenGui.Parent then return end local slideOut = TweenService:Create(card, TweenInfo.new(0.35, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {Position = UDim2.new(0.5, 0, 0, -90), BackgroundTransparency = 1}) TweenService:Create(stroke, TweenInfo.new(0.3), {Transparency = 1}):Play() TweenService:Create(accent, TweenInfo.new(0.3), {BackgroundTransparency = 1}):Play() TweenService:Create(iconBg, TweenInfo.new(0.3), {BackgroundTransparency = 1}):Play() TweenService:Create(icon, TweenInfo.new(0.25), {TextTransparency = 1}):Play() TweenService:Create(label, TweenInfo.new(0.25), {TextTransparency = 1}):Play() TweenService:Create(sub, TweenInfo.new(0.25), {TextTransparency = 1}):Play() slideOut:Play() slideOut.Completed:Wait() if screenGui.Parent then screenGui:Destroy() end end) end local function setRagdollEnabled(enabled, showToast) RAGDOLL_ENABLED = enabled local function syncHumanoid(hum) if hum and hum.Parent then hum.BreakJointsOnDeath = not enabled hum.RequiresNeck = not enabled end end for _, plr in ipairs(Players:GetPlayers()) do if plr.Character then syncHumanoid(plr.Character:FindFirstChildOfClass("Humanoid")) end end for _, model in ipairs(getAllCharacterModels()) do if model and model.Parent then syncHumanoid(model:FindFirstChildOfClass("Humanoid")) end end local color = enabled and Color3.fromRGB(80, 255, 120) or Color3.fromRGB(255, 90, 90) if statusDot and buttonLabel and buttonStroke then TweenService:Create(statusDot, TweenInfo.new(0.25), {BackgroundColor3 = color}):Play() TweenService:Create(buttonStroke, TweenInfo.new(0.25), {Color = color}):Play() buttonLabel.Text = enabled and "RAGDOLL: ON" or "RAGDOLL: OFF" pulseDot(statusDot) setBreathing(enabled) end if showToast then createToggleMessage(enabled and "Ragdoll enabled" or "Ragdoll disabled", color, enabled) end end local settingsGui local settingsPanel local function makeSettingsToggle(parent, y, title, getter, setter) local row = Instance.new("Frame") row.Position = UDim2.new(0, 14, 0, y) row.Size = UDim2.new(1, -28, 0, 42) row.BackgroundTransparency = 1 row.Parent = parent local label = Instance.new("TextLabel") label.Size = UDim2.new(1, -82, 1, 0) label.BackgroundTransparency = 1 label.Font = Enum.Font.GothamMedium label.TextSize = 14 label.TextXAlignment = Enum.TextXAlignment.Left label.TextColor3 = Color3.fromRGB(235, 235, 240) label.Text = title label.Parent = row local button = Instance.new("TextButton") button.AnchorPoint = Vector2.new(1, 0.5) button.Position = UDim2.new(1, 0, 0.5, 0) button.Size = UDim2.new(0, 68, 0, 28) button.AutoButtonColor = false button.Font = Enum.Font.GothamBold button.TextSize = 12 button.TextColor3 = Color3.fromRGB(255,255,255) button.BorderSizePixel = 0 button.Parent = row local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 8) corner.Parent = button local function refresh() local on = getter() button.Text = on and "ON" or "OFF" button.BackgroundColor3 = on and Color3.fromRGB(55, 155, 85) or Color3.fromRGB(95, 55, 60) end button.MouseButton1Click:Connect(function() setter(not getter()) refresh() end) refresh() return row end local function closeSettingsMenu() if not settingsGui then return end settingsGui:Destroy() settingsGui = nil settingsPanel = nil end local function openSettingsMenu() if settingsGui and settingsGui.Parent then closeSettingsMenu() return end local gui = player:WaitForChild("PlayerGui") settingsGui = Instance.new("ScreenGui") settingsGui.Name = "BloodSystemSettingsGui" settingsGui.ResetOnSpawn = false settingsGui.IgnoreGuiInset = true settingsGui.DisplayOrder = 1001 settingsGui.Parent = gui local backdrop = Instance.new("TextButton") backdrop.Size = UDim2.fromScale(1, 1) backdrop.BackgroundColor3 = Color3.fromRGB(0, 0, 0) backdrop.BackgroundTransparency = 0.55 backdrop.Text = "" backdrop.AutoButtonColor = false backdrop.Parent = settingsGui backdrop.MouseButton1Click:Connect(closeSettingsMenu) settingsPanel = Instance.new("Frame") settingsPanel.AnchorPoint = Vector2.new(0.5, 0.5) settingsPanel.Position = UDim2.fromScale(0.5, 0.5) settingsPanel.Size = UDim2.new(0, 430, 0, 380) settingsPanel.BackgroundColor3 = Color3.fromRGB(16, 18, 23) settingsPanel.BorderSizePixel = 0 settingsPanel.Parent = settingsGui local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 14) corner.Parent = settingsPanel local stroke = Instance.new("UIStroke") stroke.Color = Color3.fromRGB(100, 105, 120) stroke.Transparency = 0.3 stroke.Thickness = 1 stroke.Parent = settingsPanel local title = Instance.new("TextLabel") title.Position = UDim2.new(0, 18, 0, 14) title.Size = UDim2.new(1, -36, 0, 28) title.BackgroundTransparency = 1 title.Font = Enum.Font.GothamBold title.TextSize = 20 title.TextXAlignment = Enum.TextXAlignment.Left title.TextColor3 = Color3.fromRGB(245, 245, 250) title.Text = "Blood System — BRUTAL Settings" title.Parent = settingsPanel local hint = Instance.new("TextLabel") hint.Position = UDim2.new(0, 18, 0, 44) hint.Size = UDim2.new(1, -36, 0, 18) hint.BackgroundTransparency = 1 hint.Font = Enum.Font.Gotham hint.TextSize = 12 hint.TextXAlignment = Enum.TextXAlignment.Left hint.TextColor3 = Color3.fromRGB(155, 160, 170) hint.Text = "F3 — open / close menu" hint.Parent = settingsPanel makeSettingsToggle(settingsPanel, 78, "Ragdoll", function() return RAGDOLL_ENABLED end, function(v) setRagdollEnabled(v, false) end) makeSettingsToggle(settingsPanel, 126, "NO PLAYER LIMITS", function() return unlimitedMode end, function(v) unlimitedMode = v refreshDynamicLimits(true) visualBudget = dynamic.VISUAL_BUDGET_PER_SECOND lastBudgetReset = os.clock() end) makeSettingsToggle(settingsPanel, 174, "Debug HUD", function() return debugEnabled end, function(v) setDebugMode(v) end) makeSettingsToggle(settingsPanel, 222, "Micro puddles", function() return MICRO_PUDDLES_ENABLED end, function(v) MICRO_PUDDLES_ENABLED = v end) makeSettingsToggle(settingsPanel, 270, "Screen blood", function() return SCREEN_BLOOD_ENABLED end, function(v) SCREEN_BLOOD_ENABLED = v end) makeSettingsToggle(settingsPanel, 318, "Camera shake", function() return CAMERA_SHAKE_ENABLED end, function(v) CAMERA_SHAKE_ENABLED = v end) local close = Instance.new("TextButton") close.AnchorPoint = Vector2.new(1, 1) close.Position = UDim2.new(1, -16, 1, -14) close.Size = UDim2.new(0, 90, 0, 32) close.BackgroundColor3 = Color3.fromRGB(42, 45, 52) close.TextColor3 = Color3.fromRGB(235,235,240) close.Font = Enum.Font.GothamBold close.TextSize = 13 close.Text = "CLOSE" close.BorderSizePixel = 0 close.Parent = settingsPanel local closeCorner = Instance.new("UICorner") closeCorner.CornerRadius = UDim.new(0, 8) closeCorner.Parent = close close.MouseButton1Click:Connect(closeSettingsMenu) end if debugEnabled then startDebugHud() end ragdollButton, statusDot, buttonLabel, buttonStroke = createRagdollButton() setRagdollEnabled(RAGDOLL_ENABLED, false) local isDragging = false local dragStartPos, buttonStartPos, shadowStartPos ragdollButton.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then isDragging = true dragStartPos = UserInputService:GetMouseLocation() buttonStartPos = ragdollButton.Position shadowStartPos = ragdollButton.Parent:FindFirstChild("Shadow") and ragdollButton.Parent.Shadow.Position or nil end end) ragdollButton.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then isDragging = false end end) UserInputService.InputChanged:Connect(function(input) if isDragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then local delta = UserInputService:GetMouseLocation() - dragStartPos ragdollButton.Position = UDim2.new( buttonStartPos.X.Scale, buttonStartPos.X.Offset + delta.X, buttonStartPos.Y.Scale, buttonStartPos.Y.Offset + delta.Y ) local shadow = ragdollButton.Parent:FindFirstChild("Shadow") if shadow and shadowStartPos then shadow.Position = UDim2.new( shadowStartPos.X.Scale, shadowStartPos.X.Offset + delta.X, shadowStartPos.Y.Scale, shadowStartPos.Y.Offset + delta.Y ) end end end) ragdollButton.MouseButton1Click:Connect(function() local clickSound = Instance.new("Sound") clickSound.SoundId = "rbxassetid://88442833509532" clickSound.Volume = 0.8 clickSound.Parent = ragdollButton clickSound:Play() Debris:AddItem(clickSound, 2) setRagdollEnabled(not RAGDOLL_ENABLED, true) end) UserInputService.InputBegan:Connect(function(input, gameProcessed) if input.KeyCode == Enum.KeyCode.F3 then openSettingsMenu() return end if gameProcessed then return end if input.KeyCode == Enum.KeyCode.F2 then setRagdollEnabled(not RAGDOLL_ENABLED, true) end end) end initUI()