I’m currently in the process of making a melee weapon from scratch, and I thought there would be no better reference for how to do that than the most popular sword on Roblox, the Linked Sword. For that reason, I’ve been pouring through the code of the sword in Studio attempting to figure out how it works, and I’d say I’ve gotten 90% of the way there. There are several parts, however, that I need help understanding:
- At the top of the script there is a “BaseUrl” variable that seems to be meant to used to concatenate URLs, but that is never used in the script. Why is it there?
- In the script, there are two functions for “tagging” and “untagging” the humanoid of the player being attacked. It’s not clear to me why this is in the script, though I think it might have to do something with awarding kills because it places the attacker’s player in the humanoid via an ObjectValue.
- During the two functions which spell out what happens when the player slashes and lunges respectively, they create a StringValue called “toolanim” and place it inside the tool. I have no idea what this does.
- There is a “RightGrip” that is made reference to during the function for dealing damage, but I can’t figure out where it’s initialized. Is this just something that is automatically placed into the right arm whenever any tool is equipped?
Below is the commented code. Let me know what those problem areas could mean, or if I misunderstood a different part of the code.
--Rescripted by Luckymaxer
Tool = script.Parent -- assigning the tool to a variable
Handle = Tool:WaitForChild("Handle") -- grabbing the handle
Mesh = Handle:WaitForChild("Mesh") -- grabbing the mesh of the handle
Players = game:GetService("Players") -- retrieving players service
Debris = game:GetService("Debris") -- retrieving debris service
RunService = game:GetService("RunService") -- retrieving run service
BaseUrl = "http://www.roblox.com/asset/?id=" -- assigning a placeholder string for creating urls (???)
Grips = { -- assigning the grips to different positions
Up = CFrame.new(0, 0, -1.5, 0, 0, 1, 1, 0, 0, 0, 1, 0),
Out = CFrame.new(0, 0, -1.5, 0, -1, -0, -1, 0, -0, 0, 0, -1),
}
DamageValues = { -- assigning the damage dealt by different attacks to different values
BaseDamage = 5,
SlashDamage = 10,
LungeDamage = 30,
}
Damage = DamageValues.BaseDamage -- setting a placeholder damage value as the base damage
Sounds = { -- assigning all the sounds to a table
Slash = Handle:WaitForChild("Slash"),
Lunge = Handle:WaitForChild("Lunge"),
Unsheath = Handle:WaitForChild("Unsheath"),
}
LastAttack = 0 -- initializes the time of the last attack
ToolEquipped = false -- creates a placeholder variable to determine whether or not the tool is equipped
Tool.Enabled = true -- sets the tool as enabled by default (debounce)
function SwordUp() -- function for setting the sword into the upright position
Tool.Grip = Grips.Up
end
function SwordOut() -- function for setting the sword into the outward (lunging) position
Tool.Grip = Grips.Out
end
function IsTeamMate(Player1, Player2) -- function for determining whether or not the target being attacked is on the same team as the attacker
return (Player1 and Player2 and not Player1.Neutral and not Player2.Neutral and Player1.TeamColor == Player2.TeamColor) -- if player one and two exist, are both not neutral, and their team colors are the same, return true
end
function TagHumanoid(humanoid, player) -- function for tagging a humanoid (???)
local Creator_Tag = Instance.new("ObjectValue") -- creates a new object value
Creator_Tag.Name = "creator" -- names it "creator"
Creator_Tag.Value = player -- gives it a value of the passed-in player
Debris:AddItem(Creator_Tag, 2) -- sets it up for deletion in 2 seconds
Creator_Tag.Parent = humanoid -- parents it to the passed-in humanoid
end
function UntagHumanoid(humanoid) -- function for removing a tag from a humanoid (???)
for i, v in pairs(humanoid:GetChildren()) do -- for all of the objects in the humanoid
if v:IsA("ObjectValue") and v.Name == "creator" then -- if the object is the tag created in the previous function...
v:Destroy() -- destroy it
end
end
end
function Attack() -- function for slashing
Damage = DamageValues.SlashDamage -- sets the damage to slash damage
Sounds.Slash:Play() -- plays the slash sound
local Anim = Instance.new("StringValue") -- creates a new string value (???)
Anim.Name = "toolanim" -- names it "toolanim" (???)
Anim.Value = "Slash" -- sets its value to "slash" (???)
Anim.Parent = Tool -- parents it to the tool (???)
end
function Lunge() -- function for lunging
Damage = DamageValues.LungeDamage -- sets the damage to lunge damage
Sounds.Lunge:Play() -- plays the lunge sound
local Anim = Instance.new("StringValue") -- creates a new string value (???)
Anim.Name = "toolanim" -- names it "toolanim" (???)
Anim.Value = "Lunge" -- sets its value to "lunge" (???)
Anim.Parent = Tool -- parents it to the tool (???)
local Force = Instance.new("BodyVelocity") -- creates a new bodyvelocity (force)
Force.velocity = Vector3.new(0, 10, 0) -- sets the velocity to a slight upwards velocity
Force.maxForce = Vector3.new(0, 4000, 0) -- sets the max force to 4000 upwards
Debris:AddItem(Force, 0.5) -- sets it up for deletion in half a second
Force.Parent = RootPart -- parents it to the humanoidrootpart of the attacker
wait(0.25) -- waits a quarter of a second
SwordOut() -- sets the sword position to be out
wait(0.25) -- waits another quarter of a second
if Force and Force.Parent then -- if the force still exists and the the force has a parent...
Force:Destroy() -- destroy it
end
wait(0.5) -- waits half a second
SwordUp() --sets the sword position to be up
end
function Blow(Hit) -- function for dealing damage
if not Hit or not Hit.Parent or not CheckIfAlive() then -- if hit is nil or it's not parented to anything or the attacker isn't alive...
return -- exit out
end
local RightArm = (Character:FindFirstChild("Right Arm") or Character:FindFirstChild("RightHand")) -- find the right arm or hand of the attacker
if not RightArm then -- if it doesn't exist...
return -- exit out
end
local RightGrip = RightArm:FindFirstChild("RightGrip") -- find the right grip in the right arm (???)
if not RightGrip or (RightGrip.Part0 ~= RightArm and RightGrip.Part1 ~= RightArm) or (RightGrip.Part0 ~= Handle and RightGrip.Part1 ~= Handle) then -- if it doesn't exist or the two parts being linked aren't the right arm and the tool handle...
return -- exit out
end
local character = Hit.Parent -- assign the parent of the hit part to a variable
local humanoid = character:FindFirstChild("Humanoid") -- find its humanoid
if not humanoid then -- if the humanoid doesn't exist...
return -- exit out
end
local player = Players:GetPlayerFromCharacter(character) -- get the target's player from players service
if player and (player == Player or IsTeamMate(Player, player)) then -- if the target's player exists and it's the same as the attacker's or the target is on the same team as the attacker...
return -- exit out
end
UntagHumanoid(humanoid) -- delete the tag in the humanoid (???)
TagHumanoid(humanoid, Player) -- create a new tag in the humanoid (???)
humanoid:TakeDamage(Damage) -- deal the appropriate damage
end
function Activated() -- function that plays when the tool is activated
if not Tool.Enabled or not ToolEquipped or not CheckIfAlive() then -- if the tool isn't enabled, equipped, or the attacker isn't alive...
return -- exit out
end
Tool.Enabled = false -- disable the tool (debounce)
local Tick = RunService.Stepped:wait() -- assigns the amount of time passed since the start of the game
if (Tick - LastAttack) < 0.2 then -- if the difference in time between the current and last attack is less than 0.2 seconds...
Lunge() -- lunge
else -- otherwise...
Attack() -- perform a normal attack
end
Damage = DamageValues.BaseDamage -- reset the damage value to the base damage
LastAttack = Tick -- set the last attack time to the current attack time
Tool.Enabled = true -- enable the tool (end debounce)
end
function CheckIfAlive() -- function for determining whether or not the attacker is alive
return (((Character and Character.Parent and Humanoid and Humanoid.Parent and Humanoid.Health > 0 and RootPart and RootPart.Parent and Player and Player.Parent) and true) or false) -- if the attacker's character exists, it's in the workspace, the attacker's humanoid exists and it's in the character, the humanoid's health is greater than 0, and the rootpart and player both exist and have parents that aren't nil, then return true, else return false
end
function Equipped() -- function that plays when the tool is equipped
Character = Tool.Parent -- assigns the attacker to the character variable
Player = Players:GetPlayerFromCharacter(Character) -- assigns the player of the attacker to the player variable
Humanoid = Character:FindFirstChild("Humanoid") -- assigns the humanoid of the attacker to the humanoid variable
RootPart = Character:FindFirstChild("HumanoidRootPart") -- assigns the rootpart of the attacker to the rootpart variable
if not CheckIfAlive() then -- if the attacker is not alive...
return -- exit out
end
ToolEquipped = true -- sets the toolequipped boolean to true
Sounds.Unsheath:Play() -- plays the unsheathing sound
end
function Unequipped() -- function that plays when the tool is unequipped
ToolEquipped = false -- sets the toolequipped boolean to false
end
SwordUp() -- sets the default pose of the sword in the up position
Handle.Touched:connect(Blow) -- when the handle is touched, run the appropriate function
Tool.Activated:connect(Activated) -- when the tool is activated, run the appropriate function
Tool.Equipped:connect(Equipped) -- when the tool is equipped, run the appropriate function
Tool.Unequipped:connect(Unequipped) -- when the tool is unequipped, run the appropriate function