treePart.CFrame:PointToObjectSpace(mouseClickPos gives the position of the mouse hit relative to the tree part (the tree part is kind of treated as the center of the world).
If your tree part has other tree parts connected to it, this might work, if their size is biggest on their y axis and they are positioned and oriented so that connectedTreePart.CFrame*Vector.new(0, -connectedTreePart.Size.Y/2, 0) is closer to the tree part’s CFrame on the tree part’s CFrame’s x and z axis than connectedTreePart.CFrame*Vector.new(0, connectedTreePart.Size.Y/2, 0) is.
local function createWeldConstraint(part0, part1)
local weldConstr = Instance.new("WeldConstraint")
weldConstr.Part0, weldConstr.Part1 = part0, part1
weldConstr.Parent = part0
end
local function makeTreeFall(treePart, hitPos)
local treePartCf = treePart.CFrame
local relY = treePartCf:PointToObjectSpace(hitPos).Y
local upperParts, lowerParts = {}, {}
for i, v in ipairs(treePart:GetConnectedParts()) do
if v ~= treePart then
if treePart.CFrame:PointToObjectSpace(v.CFrame*Vector3.new(0, -v.Size.Y/2, 0).Y > relY then
upperParts[#upperParts+1] = v
else lowerParts[#lowerParts+1] = v
end
end
for i, child in ipairs(v:GetChildren()) do
if child:IsA("WeldConstraint") and (child.Part0 == treePart or child.Part1 = treePart) then
child:Destroy()
end
end
local orgSize = treePart.Size
treePart.Size = Vector3.new(orgSize.X, orgSize.Y/2+relY, orgSize.Z)
local newTreePartSize = orgSize-Vector3.new(0, treePart.Size.Y, 0)
treePart.Position = treePartCf*Vector3.new(0, -newTreePartSize.Y/2, 0)
local newTreePart = treePart:Clone()
newTreePart.Size = newTreePartSize
newTreePart.Position = treePart.CFrame*Vector3.new(0, newTreePartSize.Y/2+treePart.Size.Y/2, 0)
-- new welds
for i, upperPart in ipairs(upperParts()) do
createWeldConstraint(newTreePart, upperPart)
end
newTreePart.Parent = treePart.Parent
for i, lowerPart in ipairs(lowerParts) do
createWeldConstraint(treePart, lowerPart)
end
end
To do the axe thing, raycasting might be useful. When the axe is swinging, you could cast a ray from where the ax blade starts to the end of the ax blade every frame to detect when it hits a tree part. Then give the position and the part of the raycastresult to the makeTreeFall function if the part is a tree part.
local RunService = game:GetService("RunService")
local function makeParams(char)
local params = RaycastParams.new()
params.FilterType =
Enum.RaycastFilterType.Blacklist
params.FilterDescendantsInstances = {char}
end
local function isTreePart(part)
-- your logic here (maybe check the name or parent)
-- return true if it is a tree part
end
local function detectHits(axe, animTrack)
local char = axe.Parent
local params = makeParams(char)
while animTrack.IsPlaying do
local startPos = -- where the ray should start
local endPos = -- where the ray should end
local rayDirection = endPos-StartPos
local raycastResult = workspace:Raycast(startPos, rayDirection, params)
local hitPart = rayCastResult and raycastResult.Instance
if hitPart and isTreePart(hitPart) then
makeTreeFall(raycastResult.Position, hitPart)
return
end
RunService.Heartbeat:Wait()
end
end