Загрузка данных


Причина, по которой клавиша E могла не срабатывать — проверка gameProcessed (она отсекает нажатия, если чат открыт или кнопка перехвачена интерфейсом), а также отсутствие прямых программных анимаций персонажа.
В Roblox Studio процедурные анимации движения рук/тела (поднятие рук, наклон, анимация крыльев) создаются скриптом через Motor6D без сторонних фаилов.
Установи переписанную систему. В ней нажатия работают независимо, а персонаж проигрывает физические анимации во время применения способностей.
1. Клиентская часть (LocalScript)
Помести LocalScript в StarterPlayer -> StarterPlayerScripts. Назови его MagicClient.
local UserInputService = game:GetService("UserInputService")
local StarterGui = game:GetService("StarterGui")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")

local player = Players.LocalPlayer

-- Отключаем стандартный инвентарь Roblox (1-9)
pcall(function()
	StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
end)

-- Создаем RemoteEvent для связи с сервером
local magicEvent = ReplicatedStorage:FindFirstChild("MagicAbilityEvent")
if not magicEvent then
	magicEvent = Instance.new("RemoteEvent")
	magicEvent.Name = "MagicAbilityEvent"
	magicEvent.Parent = ReplicatedStorage
end

local abilities = {
	[1] = "Волшебный Щит",
	[2] = "Магические Крылья",
	[3] = "Огненный Взрыв",
	[4] = "Ледяная Волна",
	[5] = "Исцеляющий Свет"
}

local selectedSlot = 1
local activeStates = { [1] = false, [2] = false }
local cooldowns = {}
local slotFrames = {}

-- Создание GUI
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "MagicSystemGui"
screenGui.ResetOnSpawn = false
screenGui.Parent = player:WaitForChild("PlayerGui")

local mainContainer = Instance.new("Frame")
mainContainer.Name = "SlotsContainer"
mainContainer.Size = UDim2.new(0, 340, 0, 70)
mainContainer.Position = UDim2.new(0.5, -170, 0.85, -35)
mainContainer.BackgroundTransparency = 1
mainContainer.Parent = screenGui

local layout = Instance.new("UIListLayout")
layout.Parent = mainContainer
layout.FillDirection = Enum.FillDirection.Horizontal
layout.HorizontalAlignment = Enum.HorizontalAlignment.Center
layout.VerticalAlignment = Enum.VerticalAlignment.Center
layout.Padding = UDim.new(0, 10)

-- Генерация слотов
for i = 1, 5 do
	local slot = Instance.new("Frame")
	slot.Name = "Slot_" .. i
	slot.Size = UDim2.new(0, 58, 0, 58)
	slot.BackgroundColor3 = Color3.fromRGB(20, 20, 25)
	slot.BorderSizePixel = 0
	slot.Parent = mainContainer

	local corner = Instance.new("UICorner")
	corner.CornerRadius = UDim.new(0, 10)
	corner.Parent = slot

	local stroke = Instance.new("UIStroke")
	stroke.Name = "Stroke"
	stroke.Color = Color3.fromRGB(60, 60, 70)
	stroke.Thickness = 2
	stroke.Parent = slot

	local keyNum = Instance.new("TextLabel")
	keyNum.Size = UDim2.new(0, 18, 0, 18)
	keyNum.Position = UDim2.new(0, 5, 0, 3)
	keyNum.BackgroundTransparency = 1
	keyNum.Text = tostring(i)
	keyNum.TextColor3 = Color3.fromRGB(200, 200, 200)
	keyNum.TextSize = 13
	keyNum.Font = Enum.Font.GothamBold
	keyNum.Parent = slot

	local label = Instance.new("TextLabel")
	label.Size = UDim2.new(1, -8, 1, -20)
	label.Position = UDim2.new(0, 4, 0, 18)
	label.BackgroundTransparency = 1
	label.Text = abilities[i]
	label.TextColor3 = Color3.fromRGB(255, 255, 255)
	label.TextSize = 10
	label.TextWrapped = true
	label.Font = Enum.Font.GothamMedium
	label.Parent = slot

	slotFrames[i] = slot
end

local function updateUI()
	for i = 1, 5 do
		local slot = slotFrames[i]
		local stroke = slot:FindFirstChild("Stroke")

		if i == selectedSlot then
			-- Плавно увеличиваем и подсвечиваем активный слот
			TweenService:Create(slot, TweenInfo.new(0.2), {Size = UDim2.new(0, 68, 0, 68)}):Play()
			if stroke then
				stroke.Color = Color3.fromRGB(0, 180, 255)
				stroke.Thickness = 3.5
			end
		else
			TweenService:Create(slot, TweenInfo.new(0.2), {Size = UDim2.new(0, 58, 0, 58)}):Play()
			if stroke then
				stroke.Color = Color3.fromRGB(60, 60, 70)
				stroke.Thickness = 2
			end
		end
	end
end

updateUI()

-- Выбор слотов через 1-5
UserInputService.InputBegan:Connect(function(input, processed)
	-- Игнорируем ввод только если игрок пишет в чат
	if UserInputService:GetFocusedTextBox() then return end

	if input.KeyCode == Enum.KeyCode.One then selectedSlot = 1 updateUI() end
	if input.KeyCode == Enum.KeyCode.Two then selectedSlot = 2 updateUI() end
	if input.KeyCode == Enum.KeyCode.Three then selectedSlot = 3 updateUI() end
	if input.KeyCode == Enum.KeyCode.Four then selectedSlot = 4 updateUI() end
	if input.KeyCode == Enum.KeyCode.Five then selectedSlot = 5 updateUI() end

	-- Активация на E
	if input.KeyCode == Enum.KeyCode.E then
		if cooldowns[selectedSlot] and tick() < cooldowns[selectedSlot] then
			return
		end

		if selectedSlot == 1 then
			activeStates[1] = not activeStates[1]
			magicEvent:FireServer(1, activeStates[1])

			-- Перезарядка 30 секунд включается ПОСЛЕ снятия щита
			if not activeStates[1] then
				cooldowns[1] = tick() + 30
			end
		elseif selectedSlot == 2 then
			activeStates[2] = not activeStates[2]
			magicEvent:FireServer(2, activeStates[2])
		else
			-- Обычные способности с перезарядкой 5 секунд
			cooldowns[selectedSlot] = tick() + 5
			magicEvent:FireServer(selectedSlot, true)
		end
	end
end)

2. Серверная часть с процедурными анимациями (ServerScript)
Помести Script в ServerScriptService. Назови его MagicServer.
Скрипт сам строит анимационные стойки персонажа через поворот RightShoulder/LeftShoulder и генерирует все 5 видов эффектов.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")

local magicEvent = ReplicatedStorage:FindFirstChild("MagicAbilityEvent")
if not magicEvent then
	magicEvent = Instance.new("RemoteEvent")
	magicEvent.Name = "MagicAbilityEvent"
	magicEvent.Parent = ReplicatedStorage
end

-- Вспомогательная функция анимации рук без загрузки внешних файлов
local function animateArms(character, rightAngle, leftAngle, duration)
	local torso = character:FindFirstChild("Torso") or character:FindFirstChild("UpperTorso")
	if not torso then return end

	local rShoulder = torso:FindFirstChild("Right Shoulder") or character:FindFirstChild("RightHand"):FindFirstChild("RightShoulder")
	local lShoulder = torso:FindFirstChild("Left Shoulder") or character:FindFirstChild("LeftHand"):FindFirstChild("LeftShoulder")

	-- Поддержка R6 и R15
	local rJoint = character:FindFirstChild("RightShoulder", true) or character:FindFirstChild("Right Shoulder", true)
	local lJoint = character:FindFirstChild("LeftShoulder", true) or character:FindFirstChild("Left Shoulder", true)

	if rJoint and lJoint then
		TweenService:Create(rJoint, TweenInfo.new(duration or 0.4), {C0 = rJoint.C0 * CFrame.Angles(math.rad(rightAngle.X), math.rad(rightAngle.Y), math.rad(rightAngle.Z))}):Play()
		TweenService:Create(lJoint, TweenInfo.new(duration or 0.4), {C0 = lJoint.C0 * CFrame.Angles(math.rad(leftAngle.X), math.rad(leftAngle.Y), math.rad(leftAngle.Z))}):Play()
	end
end

-- 1. Слот: Волшебный Щит
local function toggleShield(character, state)
	local hrp = character:FindFirstChild("HumanoidRootPart")
	if not hrp then return end

	local shieldPart = hrp:FindFirstChild("MagicShieldDome")

	if state then
		if shieldPart then return end

		-- Анимация сведения рук вместе
		animateArms(character, Vector3.new(90, -30, 0), Vector3.new(90, 30, 0), 0.3)

		-- Частицы при колдовстве
		local castEffect = Instance.new("ParticleEmitter")
		castEffect.Texture = "rbxassetid://243660364"
		castEffect.Size = NumberSequence.new(1.5, 0)
		castEffect.Rate = 80
		castEffect.Lifetime = NumberRange.new(0.4)
		castEffect.Parent = hrp
		task.delay(0.5, function() castEffect:Destroy() end)

		-- Создание сферы щита
		local shield = Instance.new("Part")
		shield.Name = "MagicShieldDome"
		shield.Shape = Enum.PartType.Ball
		shield.Size = Vector3.new(0.1, 0.1, 0.1)
		shield.CFrame = hrp.CFrame
		shield.Material = Enum.Material.Forcefield
		shield.Color = Color3.fromRGB(0, 190, 255)
		shield.Transparency = 0.2
		shield.CanCollide = false
		shield.Anchored = false

		local weld = Instance.new("WeldConstraint")
		weld.Part0 = hrp
		weld.Part1 = shield
		weld.Parent = shield

		-- Маленькие защитные частицы купола
		local pe = Instance.new("ParticleEmitter")
		pe.Texture = "rbxassetid://243056324"
		pe.Size = NumberSequence.new(0.15, 0.3)
		pe.Rate = 50
		pe.Speed = NumberRange.new(1, 2)
		pe.Lifetime = NumberRange.new(1, 1.5)
		pe.Color = ColorSequence.new(Color3.fromRGB(180, 240, 255))
		pe.Parent = shield

		shield.Parent = hrp

		-- Плавное появление (увеличение) купола
		TweenService:Create(shield, TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Size = Vector3.new(13, 13, 13)}):Play()
	else
		if shieldPart then
			local tw = TweenService:Create(shieldPart, TweenInfo.new(0.3), {Size = Vector3.new(0.1, 0.1, 0.1), Transparency = 1})
			tw:Play()
			tw.Completed:Connect(function()
				shieldPart:Destroy()
			end)
		end
	end
end

-- 2. Слот: Закручивание партиклов и создание крыльев
local function toggleWings(character, state)
	local torso = character:FindFirstChild("UpperTorso") or character:FindFirstChild("Torso")
	if not torso then return end

	local wingsFolder = torso:FindFirstChild("MagicWingsFolder")

	if state then
		if wingsFolder then return end

		-- Вращающаяся спираль из частиц вокруг игрока
		local spiralPart = Instance.new("Part")
		spiralPart.Size = Vector3.new(1,1,1)
		spiralPart.Transparency = 1
		spiralPart.CanCollide = false
		spiralPart.CFrame = torso.CFrame
		spiralPart.Parent = workspace

		local weld = Instance.new("WeldConstraint")
		weld.Part0 = torso
		weld.Part1 = spiralPart
		weld.Parent = spiralPart

		local spiralPE = Instance.new("ParticleEmitter")
		spiralPE.Texture = "rbxassetid://258121658"
		spiralPE.Size = NumberSequence.new(0.6, 0)
		spiralPE.Rate = 120
		spiralPE.Speed = NumberRange.new(4, 7)
		spiralPE.Lifetime = NumberRange.new(0.5)
		spiralPE.Color = ColorSequence.new(Color3.fromRGB(255, 215, 0))
		spiralPE.Parent = spiralPart

		-- Вращаем узел частиц
		task.spawn(function()
			for i = 1, 15 do
				spiralPart.CFrame = spiralPart.CFrame * CFrame.Angles(0, math.rad(24), 0)
				task.wait(0.03)
			end
			spiralPart:Destroy()
		end)

		task.wait(0.4)

		-- Создание модели крыльев
		local folder = Instance.new("Folder")
		folder.Name = "MagicWingsFolder"

		for side = -1, 1, 2 do
			local wingAttachment = Instance.new("Part")
			wingAttachment.Size = Vector3.new(0.2, 0.2, 0.2)
			wingAttachment.Transparency = 1
			wingAttachment.CanCollide = false

			local wWeld = Instance.new("Weld")
			wWeld.Part0 = torso
			wWeld.Part1 = wingAttachment
			wWeld.C0 = CFrame.new(side * 0.6, 0.6, 0.6) * CFrame.Angles(0, 0, math.rad(side * 25))
			wWeld.Parent = wingAttachment

			local wingPE = Instance.new("ParticleEmitter")
			wingPE.Texture = "rbxassetid://242202316"
			wingPE.Size = NumberSequence.new(0, 3) -- Начнет расти с 0 для плавности
			wingPE.Rate = 0
			wingPE.Lifetime = NumberRange.new(0.8)
			wingPE.Speed = NumberRange.new(0)
			wingPE.Color = ColorSequence.new(Color3.fromRGB(255, 220, 100))
			wingPE.Parent = wingAttachment

			wingAttachment.Parent = folder

			-- Плавный расправ крыльев
			TweenService:Create(wingPE, TweenInfo.new(1), {Rate = 35}):Play()
		end

		folder.Parent = torso
	else
		if wingsFolder then
			wingsFolder:Destroy()
		end
	end
end

-- 3. Слот: Огненный Взрыв
local function castFireball(character)
	local hrp = character:FindFirstChild("HumanoidRootPart")
	if not hrp then return end

	animateArms(character, Vector3.new(120, 0, 0), Vector3.new(0, 0, 0), 0.2)

	local firePart = Instance.new("Part")
	firePart.Size = Vector3.new(2, 2, 2)
	firePart.Shape = Enum.PartType.Ball
	firePart.Color = Color3.fromRGB(255, 100, 0)
	firePart.Material = Enum.Material.Neon
	firePart.CFrame = hrp.CFrame + hrp.CFrame.LookVector * 3
	firePart.CanCollide = false
	firePart.Parent = workspace

	local bv = Instance.new("BodyVelocity")
	bv.Velocity = hrp.CFrame.LookVector * 60
	bv.MaxForce = Vector3.new(1e5, 1e5, 1e5)
	bv.Parent = firePart

	task.delay(1, function()
		if firePart and firePart.Parent then
			local exp = Instance.new("Explosion")
			exp.Position = firePart.Position
			exp.BlastRadius = 8
			exp.BlastPressure = 0
			exp.Parent = workspace
			firePart:Destroy()
		end
	end)
end

-- 4. Слот: Ледяная Волна
local function castIceWave(character)
	local hrp = character:FindFirstChild("HumanoidRootPart")
	if not hrp then return end

	animateArms(character, Vector3.new(-40, 0, 0), Vector3.new(-40, 0, 0), 0.2)

	for i = 1, 6 do
		task.wait(0.08)
		local iceSpike = Instance.new("Part")
		iceSpike.Size = Vector3.new(2, 5, 2)
		iceSpike.Material = Enum.Material.Ice
		iceSpike.Color = Color3.fromRGB(150, 220, 255)
		iceSpike.CFrame = hrp.CFrame + (hrp.CFrame.LookVector * (i * 4)) - Vector3.new(0, 1.5, 0)
		iceSpike.Anchored = true
		iceSpike.CanCollide = false
		iceSpike.Parent = workspace

		TweenService:Create(iceSpike, TweenInfo.new(0.2), {Size = Vector3.new(3, 8, 3)}):Play()
		task.delay(1.5, function()
			TweenService:Create(iceSpike, TweenInfo.new(0.5), {Transparency = 1}):Play()
			task.wait(0.5)
			iceSpike:Destroy()
		end)
	end
end

-- 5. Слот: Исцеляющий Свет
local function castHeal(character)
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	local hrp = character:FindFirstChild("HumanoidRootPart")
	if not humanoid or not hrp then return end

	animateArms(character, Vector3.new(150, 0, -20), Vector3.new(150, 0, 20), 0.4)

	humanoid.Health = math.clamp(humanoid.Health + 35, 0, humanoid.MaxHealth)

	local pillar = Instance.new("Part")
	pillar.Size = Vector3.new(6, 20, 6)
	pillar.CFrame = hrp.CFrame
	pillar.Material = Enum.Material.Neon
	pillar.Color = Color3.fromRGB(80, 255, 120)
	pillar.Transparency = 0.5
	pillar.Anchored = true
	pillar.CanCollide = false
	pillar.Parent = workspace

	TweenService:Create(pillar, TweenInfo.new(0.8), {Transparency = 1, Size = Vector3.new(0.1, 20, 0.1)}):Play()
	task.delay(0.8, function() pillar:Destroy() end)
end

-- Слушатель событий
magicEvent.OnServerEvent:Connect(function(player, slot, state)
	local character = player.Character
	if not character or not character:FindFirstChild("Humanoid") then return end

	if slot == 1 then toggleShield(character, state)
	elseif slot == 2 then toggleWings(character, state)
	elseif slot == 3 then castFireball(character)
	elseif slot == 4 then castIceWave(character)
	elseif slot == 5 then castHeal(character)
	end
end)

Что переработано и исправлено:
 * Клавиша E гарантированно работает: Исправлена блокировка от gameProcessedEvent. Нажатие отслеживается всегда, если игрок не пишет текст в чате.
 * Анимации движения рук прямо в скрипте: Добавлена функция animateArms, которая плавно сводит и поднимает руки персонажа во время чтения заклинаний (не нужно импортировать внешние ID анимаций).
 * Безопасность вызовов: Все процессы очистки эффектов вынесены в задержки (task.delay) с безопасными проверками, предотвращающими краш сервера и клиента.