File size: 3,729 Bytes
0712d5f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | -- src/StarterPlayer/StarterCharacterScripts/AxeController.client.lua
-- Handles both fist punching and axe chopping
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local player = Players.LocalPlayer
local mouse = player:GetMouse()
local character = player.Character or player.CharacterAdded:Wait()
local ChoppingConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("ChoppingConfig"))
local CraftingConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("CraftingConfig"))
local ChopEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("ChopEvent")
local canSwing = true
local function getCurrentWeapon()
local axeType = nil
if character then
axeType = character:GetAttribute("EquippedAxe")
end
if not axeType or axeType == "" then
axeType = player:GetAttribute("EquippedAxe")
end
-- No axe = use fists
if not axeType or axeType == "" or axeType == "None" then
return CraftingConfig.Fist, "Fist"
end
local stats = ChoppingConfig.AxeTypes[axeType]
if stats then
return stats, axeType
end
return CraftingConfig.Fist, "Fist"
end
local function playSwingAnimation(weaponType)
local humanoid = character:FindFirstChildOfClass("Humanoid")
if not humanoid then return end
local camera = workspace.CurrentCamera
if camera then
task.spawn(function()
local shake = weaponType == "Fist" and 1 or 2
for i = 1, 3 do
camera.CFrame = camera.CFrame * CFrame.Angles(0, 0, math.rad(-shake + i * (shake * 0.6)))
task.wait(0.03)
end
end)
end
end
local function createHitEffect(position, weaponType)
local part = Instance.new("Part")
part.Size = Vector3.new(0.4, 0.4, 0.4)
part.Position = position
part.Anchored = true
part.CanCollide = false
part.Material = Enum.Material.Neon
part.Shape = Enum.PartType.Ball
part.Parent = workspace.Terrain
if weaponType == "Fist" then
part.BrickColor = BrickColor.new("Bright orange")
else
part.BrickColor = BrickColor.new("Bright yellow")
end
task.spawn(function()
for i = 1, 5 do
part.Size = part.Size * 1.3
part.Transparency = i / 5
task.wait(0.03)
end
part:Destroy()
end)
end
local function onInputBegan(input, gameProcessed)
if gameProcessed then return end
if input.UserInputType == Enum.UserInputType.MouseButton1 then
if not canSwing then return end
if not character or not character:FindFirstChild("Head") then return end
local weaponStats, weaponType = getCurrentWeapon()
local rayOrigin = character.Head.Position
local rayDirection = (mouse.Hit.Position - rayOrigin).Unit * weaponStats.Range
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {character}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
if raycastResult and raycastResult.Instance then
local hitPart = raycastResult.Instance
-- Only chop tree segments
if CollectionService:HasTag(hitPart, "TreeSegment") then
playSwingAnimation(weaponType)
createHitEffect(raycastResult.Position, weaponType)
ChopEvent:FireServer(hitPart, raycastResult.Position)
end
end
-- Cooldown applies even on miss (animation commitment)
canSwing = false
task.wait(weaponStats.SwingCooldown)
canSwing = true
end
end
player.CharacterAdded:Connect(function(char)
character = char
end)
UserInputService.InputBegan:Connect(onInputBegan)
|