Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Weapon script dosn't deflect damage, why?

I'm trying to make a weapon, it swings but it doesn't do any damage,when I had the script print what the argument was, it said terrain.

console

Terrain 18:33:52.341 - Humanoid is not a valid member of Workspace 18:33:52.342 - Stack Begin 18:33:52.343 - Script 'Players.Player2.Backpack.axe.damage', Line 5 18:33:52.344 - Stack End

script

script.Parent.hitbox.Touched:connect(function(p)
	if script.Parent.CanDamage.Value == true then
		print(p)
		script.Parent.CanDamage.Value = false
		p.Parent.Humanoid:TakeDamage(20)
	end
end)

local script

local CanAttack = true

script.Parent.Activated:connect(function()

local attack = script.Parent.Parent.Humanoid:LoadAnimation(script.Attack)

if CanAttack == true then
script.Parent.CanDamage.Value = true
game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 0
attack:Play()

CanAttack = false

wait(0.4)

attack:Stop()
game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 16
CanAttack = true

script.Parent.CanDamage.Value = false

end

end)

welding script (in case)

local NEVER_BREAK_JOINTS = false

local function CallOnChildren(Instance, FunctionToCall)

	FunctionToCall(Instance)

	for _, Child in next, Instance:GetChildren() do
		CallOnChildren(Child, FunctionToCall)
	end
end

local function GetNearestParent(Instance, ClassName)

	local Ancestor = Instance
	repeat
		Ancestor = Ancestor.Parent
		if Ancestor == nil then
			return nil
		end
	until Ancestor:IsA(ClassName)

	return Ancestor
end

local function GetBricks(StartInstance)
	local List = {}

	CallOnChildren(StartInstance, function(Item)
		if Item:IsA("BasePart") then
			List[#List+1] = Item;
		end
	end)

	return List
end

local function Modify(Instance, Values)

	assert(type(Values) == "table", "Values is not a table");

	for Index, Value in next, Values do
		if type(Index) == "number" then
			Value.Parent = Instance
		else
			Instance[Index] = Value
		end
	end
	return Instance
end

local function Make(ClassType, Properties)
	-- Using a syntax hack to create a nice way to Make new items.  

	return Modify(Instance.new(ClassType), Properties)
end

local Surfaces = {"TopSurface", "BottomSurface", "LeftSurface", "RightSurface", "FrontSurface", "BackSurface"}
local HingSurfaces = {"Hinge", "Motor", "SteppingMotor"}

local function HasWheelJoint(Part)
	for _, SurfaceName in pairs(Surfaces) do
		for _, HingSurfaceName in pairs(HingSurfaces) do
			if Part[SurfaceName].Name == HingSurfaceName then
				return true
			end
		end
	end
	
	return false
end

local function ShouldBreakJoints(Part)
	--- We do not want to break joints of wheels/hinges. This takes the utmost care to not do this. There are
	--  definitely some edge cases. 

	if NEVER_BREAK_JOINTS then
		return false
	end
	
	if HasWheelJoint(Part) then
		return false
	end
	
	local Connected = Part:GetConnectedParts()
	
	if #Connected == 1 then
		return false
	end
	
	for _, Item in pairs(Connected) do
		if HasWheelJoint(Item) then
			return false
		elseif not Item:IsDescendantOf(script.Parent) then
			return false
		end
	end
	
	return true
end

local function WeldTogether(Part0, Part1, JointType, WeldParent)

	JointType = JointType or "Weld"
	local RelativeValue = Part1:FindFirstChild("qRelativeCFrameWeldValue")
	
	local NewWeld = Part1:FindFirstChild("qCFrameWeldThingy") or Instance.new(JointType)
	Modify(NewWeld, {
		Name = "qCFrameWeldThingy";
		Part0  = Part0;
		Part1  = Part1;
		C0     = CFrame.new();--Part0.CFrame:inverse();
		C1     = RelativeValue and RelativeValue.Value or Part1.CFrame:toObjectSpace(Part0.CFrame); --Part1.CFrame:inverse() * Part0.CFrame;-- Part1.CFrame:inverse();
		Parent = Part1;
	})

	if not RelativeValue then
		RelativeValue = Make("CFrameValue", {
			Parent     = Part1;
			Name       = "qRelativeCFrameWeldValue";
			Archivable = true;
			Value      = NewWeld.C1;
		})
	end

	return NewWeld
end

local function WeldParts(Parts, MainPart, JointType, DoNotUnanchor)
	
	for _, Part in pairs(Parts) do
		if ShouldBreakJoints(Part) then
			Part:BreakJoints()
		end
	end
	
	for _, Part in pairs(Parts) do
		if Part ~= MainPart then
			WeldTogether(MainPart, Part, JointType, MainPart)
		end
	end

	if not DoNotUnanchor then
		for _, Part in pairs(Parts) do
			Part.Anchored = false
		end
		MainPart.Anchored = false
	end
end

local function PerfectionWeld()	
	local Tool = GetNearestParent(script, "Tool")

	local Parts = GetBricks(script.Parent)
	local PrimaryPart = Tool and Tool:FindFirstChild("Handle") and Tool.Handle:IsA("BasePart") and Tool.Handle or script.Parent:IsA("Model") and script.Parent.PrimaryPart or Parts[1]

	if PrimaryPart then
		WeldParts(Parts, PrimaryPart, "Weld", false)
	else
		warn("qWeld - Unable to weld part")
	end
	
	return Tool
end

local Tool = PerfectionWeld()


if Tool and script.ClassName == "Script" then
	--- Don't bother with local scripts

	script.Parent.AncestryChanged:connect(function()
		PerfectionWeld()
	end)
end

1 comment

0

Error messages explain a lot most of the time. 

2 answers

I think there are two possibilities,

One possibility is that it's actually hitting the terrain in your map, and therefore it's not able to find a humanoid in the workspace which is Hit.Parent

I'm not exactly sure but when the touched function fires, I think it reads the entire model (the character). So when you said p.Parent, the character models Parent is a obviously the workspace. My point is, take out the Parent part so it is p.Humanoid:TakeDamage(20)

2 comments

0

Depends what hit it in the first place

0

it is now saying terrain, and btw, it never hits the physical ground, I have the axe go inside the player with no animation and it still says terrain 19:37:52.412 - Humanoid is not a valid member of Terrain 19:37:52.413 - Stack Begin | 19:37:52.414 - Script 'Players.Player1.Backpack.axe.damage', Line 7 | 19:37:52.415 - Stack End

This discussion is preserved as it was. New answers, comments, and votes are closed.