DISCLAIMER: THIS IS NOTHING TO DO WITH THE ROBLOX STUDIO WORKSPACE. I OWN AN EXPERIENCE CALLED WORKSPACE AND THIS IS FOR THAT.
No. I’m not the best scripter; I used AI for half of the code.
Yes this is technically a “tutorial” since I’m uhhhhh helping people make uh fighting games…
The actual experience isn’t uncopylocked, but you can download an outdated version here:
Workspace - Download the place file here! (2.2 MB)
If you wish to play the real game, you can play it here:
Workspace - Play the official game here!
Please do not reupload the game and claim ownership.
Nobody helped me with this except one person who did nothing except decorate the grocery store
They may add more in the future. And if they request, I will remove their grocery store build from the game.
Anybody else was just not developing the game, but instead giving me ideas (AS OF WRITING THIS).
The whole point of workspace is the legacy roblox style, not classic Roblox or new Roblox.
I’d rather people not use my work but… Hey, if it helps people make FPS and TPS games, sure, go for it.
I don’t care much about credit if you use something from the game, but you can credit me if you wish.
Workspace uses some customized classic/new meshes such as the Dynamic Man Head and some asset’s from The Mystery of Duvall Drive.
Workspace is an R6 experience about killing NPCS with very unfinished guns… Enemies are randomly chosen from a folder, while being easy to add/remove them, and change their code. if you wish to change an enemy’s size, put a script in their folder saying;
task.wait(0.1)
script.Parent:ScaleTo(2)
If you’re gonna resize an enemy, check the attacking script inside
game.ReplicatedStorage.Assets.Rigs.Enemy.
You must change the range for that enemy by giving an object in the enemy folder a specific name that the Attacking script can recognize, same with damage if you’re gonna do that.
Every Halloween, Christmas, and April Fools, the enemies will change their looks.
That’s all, please reply with reviews, or ideas for things to add.
The gun system system has 3 scripts, or 4 if you include the npc code.
I’ll paste the GunSystem ModuleScript below this line.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local TweenService = game:GetService("TweenService")
local Debris = game:GetService("Debris")
local Players = game:GetService("Players")
local GunSystem = {}
local BulletHoles = ReplicatedStorage:WaitForChild("Assets"):WaitForChild("BulletHoles")
local Bullets = ReplicatedStorage:WaitForChild("Assets"):WaitForChild("Bullets")
local Particles = ReplicatedStorage:WaitForChild("Assets"):WaitForChild("Particles")
local FireGun = ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("FireGun")
local BulletFolder = workspace:FindFirstChild("Bullets") or Instance.new("Folder")
BulletFolder.Name = "Bullets"
BulletFolder.Parent = workspace
local killstreaks = {}
local triggeredExplosives = {}
local lastShot = {}
local beam = nil
Players.PlayerAdded:Connect(function(player)
killstreaks[player] = 0
player.CharacterAdded:Connect(function(char)
local hum = char:WaitForChild("Humanoid")
killstreaks[player] = 0
hum.Died:Connect(function()
killstreaks[player] = 0
end)
end)
end)
Players.PlayerRemoving:Connect(function(player)
killstreaks[player] = nil
end)
local function hasBlockingConstraint(part)
for _, d in ipairs(part:GetDescendants()) do
if d:IsA("BallSocketConstraint") then
if not string.find(d.Name, "Ragdoll_Socket") then
return true
end
elseif d:IsA("Constraint")
and not d:IsA("NoCollisionConstraint")
and not d:IsA("UIAspectRatioConstraint")
and not d:IsA("UISizeConstraint")
and not d:IsA("Motor6D")
and not d:IsA("UITextSizeConstraint") then
return true
elseif d:IsA("Attachment") then
if string.find(d.Name, "Custom_Attachment") or string.find(d.Name, "Tool_Attachment") then
return true
end
end
end
return false
end
local function limb(hitPart)
if math.random(1, 2) == 1 then return end
local character = hitPart.Parent
if not character then return end
local clone = character:Clone()
clone.Parent = workspace
clone:PivotTo(hitPart.Parent:GetPivot())
clone.PrimaryPart = nil
for _, d in ipairs(clone:GetDescendants()) do
if d:IsA("Script") or d:IsA("LocalScript") or d:IsA("ModuleScript") then
d:Destroy()
end
end
for _, name in ipairs({"HumanoidRootPart", "Head", "Torso"}) do
local p = clone:FindFirstChild(name)
if p then
p:Destroy()
end
end
for _, d in ipairs(clone:GetDescendants()) do
if d:IsA("BasePart") then
d.CanCollide = false
d.Anchored = true
d.CanQuery = false
d.CanTouch = false
d.Transparency = 1
end
end
hitPart.CanQuery = false
hitPart.CanTouch = false
hitPart.Transparency = 1
local limbClone = clone:FindFirstChild(hitPart.Name)
if not limbClone or not limbClone:IsA("BasePart") then return end
limbClone:BreakJoints()
for _, d in ipairs(limbClone:GetChildren()) do
if not d:IsA("Decal") and not d:IsA("Texture") and not d:IsA("SpecialMesh") then
d:Destroy()
end
end
limbClone.CanCollide = true
limbClone.Transparency = 0
limbClone.CanQuery = true
limbClone.CanTouch = true
limbClone.Anchored = false
limbClone.CFrame = hitPart.CFrame
end
local function teamSafeRaycast(origin, direction, shooterModel)
if not game:GetService("RunService"):IsServer() then return end
local dir = direction.Magnitude > 0 and direction.Unit or Vector3.new(0,0,-1)
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Blacklist
params.IgnoreWater = true
local ignore = { shooterModel }
for _ = 1, 8 do
params.FilterDescendantsInstances = ignore
local result = workspace:Raycast(origin, dir * 1999, params)
if not result then
return origin + dir * 1999, nil, nil
end
local hitModel = result.Instance:FindFirstAncestorOfClass("Model")
if hitModel then
local hum = hitModel:FindFirstChild("Humanoid")
local shooter = Players:GetPlayerFromCharacter(shooterModel)
local shooterTeam = shooter and shooter.Team
local hitPlayer = Players:GetPlayerFromCharacter(hitModel)
local hitTeam = hitPlayer and hitPlayer.Team
local hitIsFriendly = CollectionService:HasTag(hitModel, "Friendly")
local shooterIsEnemy = CollectionService:HasTag(shooterModel, "Enemy")
if hum and shooterTeam and hitTeam and shooterTeam == hitTeam and shooterTeam.Name ~= "Human" then
table.insert(ignore, hitModel)
continue
elseif hitIsFriendly and not shooterIsEnemy then
table.insert(ignore, hitModel)
continue
end
end
return result.Position, result.Instance, result.Normal
end
return origin + dir * 1999, nil, nil
end
function GunSystem.Fire(user, originPos, direction, tool)
if not game:GetService("RunService"):IsServer() then return end
if game:GetService("RunService"):IsRunMode() then return end
local shootFunc = tool:GetAttribute("ShootFunction")
if shootFunc == "Ghost" then
local character = user.Character
if not character then return end
local player = Players:GetPlayerFromCharacter(character)
local handle = tool:FindFirstChild("Handle")
if not handle then return end
local projectile = Instance.new("Part")
projectile.Name = "GhostProjectile"
projectile.Size = Vector3.new(2.5,2.5,2.5)
projectile.Shape = Enum.PartType.Ball
projectile.CanCollide = false
projectile.Transparency = 1
projectile.Anchored = true
projectile.CFrame = CFrame.new(handle.Position)
projectile.Parent = workspace:FindFirstChild("BulletHoles") or workspace
local fire = Instance.new("Fire")
fire.Color = Color3.new(1,1,1)
fire.SecondaryColor = Color3.new(0,0,0)
fire.Heat = 2
fire.Size = 3
fire.Parent = projectile
local creatorVal = Instance.new("ObjectValue")
creatorVal.Name = "creator"
creatorVal.Value = player
creatorVal.Parent = projectile
Debris:AddItem(projectile,25)
local baseDir = (direction.Magnitude > 0 and direction.Unit or Vector3.new(0,0,1))
local startPos = projectile.Position
local timeElapsed = 0
task.spawn(function()
while projectile.Parent do
task.wait(0.03)
timeElapsed += 0.03
local riseSpeed = math.clamp(timeElapsed*3,0,31)
local targetPos = startPos + baseDir*345*timeElapsed + Vector3.new(0,riseSpeed*timeElapsed,0)
local tween = TweenService:Create(projectile,TweenInfo.new(0.03,Enum.EasingStyle.Linear),{CFrame=CFrame.new(targetPos,targetPos+baseDir)})
tween:Play()
end
end)
projectile.Touched:Connect(function(hit)
if not hit then return end
local hum = hit.Parent:FindFirstChildOfClass("Humanoid")
if hum and hum.Health > 0 and hum.Parent.Name ~= user.Name and not CollectionService:HasTag(hum.Parent, "Ghost") and not CollectionService:HasTag(hum.Parent, "Friendly") then
projectile:Destroy()
hum:TakeDamage(tool:GetAttribute("Damage") or 100)
local hrp = hum.Parent:FindFirstChild("HumanoidRootPart")
if hrp then
local bv = Instance.new("BodyVelocity")
bv.Velocity = Vector3.new(0,150,0)
bv.MaxForce = Vector3.new(0,math.huge,0)
bv.P = 1250
bv.Parent = hrp
Debris:AddItem(bv,0.3)
end
if hum.Health <= 1 then
local ghost = game:GetService("ReplicatedStorage"):WaitForChild("Assets"):WaitForChild("Rigs"):WaitForChild("Ghost"):Clone()
--ghost:AddTag("Ghost")
ghost.Name = "Ghost"
ghost.Parent = workspace:WaitForChild("NPCS")
ghost:MoveTo(projectile.Position)
ghost:ScaleTo(hit.Parent:GetScale() or 1)
for i,v in ipairs(hit.Parent:GetChildren()) do
if v:IsA("CharacterMesh") then
local vclone=v:Clone()
vclone.BaseTextureId=0
vclone.OverlayTextureId=0
vclone.Parent=ghost
end
end
for i,v in ipairs(hit.Parent:WaitForChild("Head"):GetChildren()) do
if v:IsA("Decal") then
local xclone=v:Clone()
xclone.Parent=ghost:WaitForChild("Head")
end
end
for i,v in ipairs(hit.Parent:GetChildren()) do
if v:IsA("Accessory") then
local zclone=v:Clone()
zclone.Parent=ghost
end
end
for i,v in ipairs(ghost:GetChildren()) do
if v:IsA("Accessory") then
for i,z in ipairs(v:GetChildren()) do
if z:IsA("BasePart") then
z.Transparency=0.5
z.CanCollide = false
for i,n in ipairs(z:GetChildren()) do
if n:IsA("SpecialMesh") then
n.TextureId = ""
end
end
end
end
end
end
task.delay(25, function()
local startScale = 1
local endScale = 1.4
local duration = 0.11
local steps = 23
local stepTime = duration / steps
for i = 1, steps do
local scale = startScale + (endScale - startScale) * (i / steps)
ghost:ScaleTo(scale)
task.wait(stepTime)
end
task.wait(0.1)
ghost:Destroy()
end)
end
end
end)
game:GetService("Debris"):AddItem(projectile, 30)
return
end
if tool:FindFirstChild("End") and tool.End:FindFirstChild("End") then
ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("FireParticle"):FireAllClients(tool)
end
if tool:FindFirstChild("End") and tool.End:FindFirstChild("End") then
ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("BulletTrail"):FireAllClients(tool, hitPos, shooter, direction)
end
local character = user:IsA("Player") and user.Character or user
if not character then return end
local hitPos, hitPart, hitNormal = teamSafeRaycast(originPos, direction, character)
if tool:FindFirstChild("Handle") and tool.Handle:FindFirstChild("Fire") then
local fire = tool.Handle.Fire:Clone()
fire.Parent = tool.Handle
fire:Play()
task.delay(fire.TimeLength + 0.4, function()
fire:Destroy()
end)
end
local damage = tool:GetAttribute("Damage") or 10
if hitPart then
local hitModel = hitPart:FindFirstAncestorOfClass("Model")
local hum = hitModel and hitModel:FindFirstChild("Humanoid")
local shooter = Players:GetPlayerFromCharacter(character)
local shooterTeam = shooter and shooter.Team
local hitPlayer = Players:GetPlayerFromCharacter(hitModel)
local hitTeam = hitPlayer and hitPlayer.Team
local hitIsFriendly = CollectionService:HasTag(hitModel, "Friendly")
local shooterIsEnemy = CollectionService:HasTag(character, "Enemy")
if hitIsFriendly and not shooterIsEnemy then return end
if shooterTeam and hitTeam and shooterTeam == hitTeam and shooterTeam.Name ~= "Human" then return end
local bulletRandom = math.random(1, 3)
local realDamage = damage
if shooterTeam and (shooterTeam.Name == "Resistance" or shooterTeam.Name == "Military") then
realDamage *= 1.3
end
if character:FindFirstChild("OminousDragonHelmet") then
realDamage *= 1.2
end
if character:FindFirstChild("hestaresinthedarkness") and character:FindFirstChild("hestaresinthedarkness"):FindFirstChildOfClass("Configuration") and character:FindFirstChild("hestaresinthedarkness"):IsA("Accessory") then
realDamage *= 2
end
if shooter and shooter:IsA("Player") and character.Name == "DumpWanderer" or character.Name == "DumpWandererAlt" then
realDamage += 5
end
if shooter and shooter:IsA("Player") then
if shooter:IsFriendsWithAsync(6164835582) then
realDamage += 1
end
end
if math.random(1, 15000) == 1 then
print("bro 1 in 15k chance the bullet doesnt do damage...")
else
if hum and hum.Health ~= 0 and not hitPart:HasTag("Unattached") then
hum:TakeDamage(realDamage + bulletRandom)
end
end
local hole
local lifetime
local dust
if hitPart.MaterialVariant == "Leaves" then
hole = BulletHoles.Leaves:Clone()
hole.Decal.Color3 = hitPart.Color
lifetime = 10
elseif hum then
hole = BulletHoles.Blood:Clone()
CollectionService:AddTag(hole, "Blood")
lifetime = 6.7
elseif CollectionService:HasTag(hitPart, "OxygenTank") then
if math.random(1, 5) == 1 then
hole = BulletHoles.AirTank2:Clone()
else
hole = BulletHoles.AirTank1:Clone()
end
lifetime = 11
elseif (hitPart.Material == Enum.Material.Glass and hitPart.Transparency ~= 0) or (hitPart.Transparency > 0.03 and hitPart.Transparency ~= 0) or hitPart.Name == "Glass" then
hole = BulletHoles.Glass:Clone()
hole.Decal.Color3 = hitPart.Color
lifetime = 160
else
hole = BulletHoles.Concrete:Clone()
if hitPart.Color ~= Color3.fromRGB(39,132,53)
and hitPart.Color ~= Color3.fromRGB(255,140,1)
and hitPart.Color ~= Color3.fromRGB(255,105,180)
and hitPart.Color ~= Color3.fromRGB(34,139,34)
and hitPart.Color ~= Color3.fromRGB(16,145,134) then
hole.Transparency = 1
end
hole.Decal.Color3 = hitPart.Color
lifetime = 190
if hitPart.Material == Enum.Material.DiamondPlate or hitPart.Material == Enum.Material.Metal or hitPart.Material == Enum.Material.CorrodedMetal then
dust = Particles.MetalHitDust:Clone()
elseif hitPart.MaterialVariant == "Leaves" then
dust = Particles:WaitForChild("LeavesHit"):Clone()
else
if math.random(1, 2) == 1 then
dust = Particles.HitDustNew:Clone()
else
dust = Particles.HitDust:Clone()
end
end
dust.Parent = hole
dust.Enabled = true
if hitPart.Color == Color3.fromRGB(165,166,166) then
dust.Color = ColorSequence.new(Color3.fromRGB(81, 60, 46))
elseif hitPart.Material == Enum.Material.DiamondPlate or hitPart.Material == Enum.Material.Metal or hitPart.Material == Enum.Material.CorrodedMetal then
dust.Color = ColorSequence.new(Color3.fromRGB(255, 204, 0))
else
dust.Color = ColorSequence.new(hitPart.Color)
end
if hitPart.Material == Enum.Material.DiamondPlate or hitPart.Material == Enum.Material.Metal or hitPart.Material == Enum.Material.CorrodedMetal then
task.delay(0.39, function()
if dust then dust.Enabled = false end
end)
else
task.delay(0.7, function()
if dust then dust.Enabled = false end
end)
end
Debris:AddItem(dust, 10)
end
if hitPart and CollectionService:HasTag(hitPart, "DestroyOnShoot") then
hitPart:Destroy()
elseif hitPart and CollectionService:HasTag(hitPart, "DestroyParentOnShoot") then
if hitPart:HasTag("ExplodeOnShoot") then
task.wait(0.1)
hitPart.Parent:Destroy()
else
hitPart.Parent:Destroy()
end
elseif hitPart and CollectionService:HasTag(hitPart, "ExplodeOnShoot") then
local pos = hitPart.Position
local e = Instance.new("Explosion")
e.BlastPressure = 5
e.BlastRadius = 0
e.DestroyJointRadiusPercent = 0
e.Parent = workspace
e.Position = hitPart.Position
local radius = 25
local maxDamage = 150
for _, plr in pairs(Players:GetPlayers()) do
local char = plr.Character
if char then
local hrp = char:FindFirstChild("HumanoidRootPart")
local hum = char:FindFirstChild("Humanoid")
if hrp and hum and hum.Health > 0 then
local dist = (hrp.Position - pos).Magnitude
if dist <= radius then
if triggeredExplosives[hitPart] then return end
triggeredExplosives[hitPart] = true
local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances = {hitPart, char}
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.IgnoreWater = true
local result = workspace:Raycast(pos, hrp.Position - pos, rayParams)
local chainRadius = 30
for _, p in pairs(CollectionService:GetTagged("ExplodeOnShoot")) do
if p ~= hitPart and p:IsA("BasePart") and p.Parent then
if not triggeredExplosives[p] then
if (p.Position - pos).Magnitude <= chainRadius then
task.spawn(function()
p:Destroy()
end)
end
end
end
end
local protectionMultiplier = 1
if result then
local mat = result.Instance.Material
if mat == Enum.Material.Wood or mat == Enum.Material.WoodPlanks or mat == Enum.Material.Cardboard then
protectionMultiplier = 0.85
elseif mat == Enum.Material.CorrodedMetal then
protectionMultiplier = 0.6
elseif mat == Enum.Material.Metal then
protectionMultiplier = 0.25
elseif mat == Enum.Material.DiamondPlate then
protectionMultiplier = 0.15
end
end
local falloff = 1 - (dist / radius)
local damage = math.clamp(maxDamage * falloff * protectionMultiplier, 0, maxDamage)
if damage > 0 then
hum:TakeDamage(damage)
end
end
end
end
end
task.wait()
hitPart.Parent:Destroy()
elseif hitPart and hitPart.Parent and CollectionService:HasTag(hitPart.Parent, "Target") then
print(character.Name.. " hit a moving training dummy target")
if Players:GetPlayerFromCharacter(character or shooter) then
if not game:GetService("BadgeService"):UserHasBadgeAsync(Players:GetPlayerFromCharacter(character).UserId or shooter.UserId, 2511480778492588) then
game:GetService("BadgeService"):AwardBadgeAsync(Players:GetPlayerFromCharacter(character or shooter).UserId, 2511480778492588)
end
ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("HitTarget"):FireClient(Players:GetPlayerFromCharacter(character or shooter))
end
elseif hitPart and hitPart.Parent and hitPart.Parent:HasTag("Enemy") and hitPart.Name == "Left Leg" and hitPart.Parent:FindFirstChild("Right Leg") and not hitPart.Parent:FindFirstChild("Right Leg"):HasTag("Unattached") and hitPart.Parent:FindFirstChildOfClass("Humanoid") and hitPart.Parent:FindFirstChildOfClass("Humanoid").Health ~= 0 and hitPart.Parent:GetScale() == 1 then
limb(hitPart)
elseif hitPart and hitPart.Parent and hitPart.Parent:HasTag("Enemy") and hitPart.Name == "Right Leg" and hitPart.Parent:FindFirstChild("Right Leg") and not hitPart.Parent:FindFirstChild("Left Leg"):HasTag("Unattached") and hitPart.Parent:FindFirstChildOfClass("Humanoid") and hitPart.Parent:FindFirstChildOfClass("Humanoid").Health ~= 0 and hitPart.Parent:GetScale() == 1 then
limb(hitPart)
elseif hitPart and hitPart.Parent and hitPart.Parent:HasTag("Enemy") and hitPart.Name == "Left Arm" and hitPart.Parent:FindFirstChild("Right Leg") and not hitPart.Parent:FindFirstChild("Right Arm"):HasTag("Unattached") and hitPart.Parent:FindFirstChildOfClass("Humanoid") and hitPart.Parent:FindFirstChildOfClass("Humanoid").Health ~= 0 and hitPart.Parent:GetScale() == 1 then
limb(hitPart)
elseif hitPart and hitPart.Parent and hitPart.Parent:HasTag("Enemy") and hitPart.Name == "Right Arm" and hitPart.Parent:FindFirstChild("Right Leg") and not hitPart.Parent:FindFirstChild("Left Arm"):HasTag("Unattached") and hitPart.Parent:FindFirstChildOfClass("Humanoid") and hitPart.Parent:FindFirstChildOfClass("Humanoid").Health ~= 0 and hitPart.Parent:GetScale() == 1 then
limb(hitPart)
end
if hole then
hole.CFrame = CFrame.lookAt(hitPos, hitPos + (hitNormal or Vector3.new(0,1,0)))
if CollectionService:HasTag(hole, "Blood") then
if hitPart and CollectionService:HasTag(hitPart.Parent.Parent, "Doll") then
print("shot doll")
else
hole.Parent = hitPart or workspace:WaitForChild("BulletHoles", 5) or game:GetService("ServerStorage")
end
else
hole.Parent = hitPart
end
local weld = Instance.new("WeldConstraint")
weld.Part0 = hole
weld.Part1 = hitPart
weld.Parent = hole
local decal = hole:FindFirstChildWhichIsA("Decal", true)
if decal then
decal.Transparency = 0
task.wait(5)
TweenService:Create(decal, TweenInfo.new(lifetime), {Transparency = 1}):Play()
end
Debris:AddItem(hole, lifetime)
end
--tool.Equipped:Connect(function()
-- local leftarm = character:WaitForChild("Left Arm") or character:WaitForChild("LeftArm")
-- local rightarm = character:WaitForChild("Right Arm") or character:WaitForChild("RightArm")
-- local grip = rightarm:WaitForChild("RightGrip", 60) or rightarm:WaitForChild("Right Grip", 60) or nil
-- grip.Part0 = rightarm
--end)
end
end
FireGun.OnServerEvent:Connect(function(player, originPos, direction, tool)
if not tool then return end
local now = os.clock()
local cd = tool:GetAttribute("Cooldown") or 0.1
local last = lastShot[player]
if last and (now - last) < cd then
return
end
lastShot[player] = now
GunSystem.Fire(player, originPos, direction, tool)
end)
return GunSystem
It’s really a big system. Obviously theres 2 more scripts too, here’s the GunClient modulescript;
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local module = {}
local activeSessions = {}
local REMOTES = ReplicatedStorage:WaitForChild("Remotes")
local ChangeGunSide = REMOTES:WaitForChild("ChangeGunSide")
local RequestGunSide = REMOTES:WaitForChild("RequestGunSide")
local windowFocused = true
function module.init(tool)
if activeSessions[tool] then
activeSessions[tool].cleanup()
end
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local root = character:WaitForChild("HumanoidRootPart")
local MAX_LENGTH = 900000
local ENABLED_OFFSET = Vector3.new(1.967, 0.67, 0.67)
local CAMERA_TWEEN_TIME = 0.01
local DEFAULT_FOV = 70
local ZOOM_FOV = tool:GetAttribute("Zoom") or 67
local ZOOM_SPEED = tool:GetAttribute("ZoomSpeed") or 18
local zooming = false
local active = false
local frameMouselock = false
local connections = {}
local gunName = tool.Name
local currentSide = 1
local endTransparency = tool:WaitForChild("End").Transparency
local leftArmTransparency = character:FindFirstChild("Left Arm").Transparency or character:WaitForChild("LeftArm", 3).Transparency
local rightArmTransparency = character:FindFirstChild("Right Arm").Transparency or character:WaitForChild("RightArm", 3).Transparency
UserInputService.WindowFocused:Connect(function()
windowFocused = true
end)
UserInputService.WindowFocusReleased:Connect(function()
windowFocused = false
end)
local function bind(signal, fn)
local c = signal:Connect(fn)
table.insert(connections, c)
return c
end
local function cleanup()
for _, c in connections do
c:Disconnect()
end
connections = {}
humanoid.CameraOffset = Vector3.zero
camera.FieldOfView = DEFAULT_FOV
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
UserInputService.MouseIconEnabled = true
end
activeSessions[tool] = { cleanup = cleanup }
local function playerCamOffset()
return Vector3.new(ENABLED_OFFSET.X * currentSide, ENABLED_OFFSET.Y, ENABLED_OFFSET.Z)
end
local realCamTweenInfo = TweenInfo.new(CAMERA_TWEEN_TIME, Enum.EasingStyle.Circular, Enum.EasingDirection.Out)
if tool.Name == "Sniper" then
local camTweenInfo1 = TweenInfo.new(CAMERA_TWEEN_TIME, Enum.EasingStyle.Quint, Enum.EasingDirection.Out)
realCamTweenInfo = camTweenInfo1
else
local camTweenInfo2 = TweenInfo.new(CAMERA_TWEEN_TIME, Enum.EasingStyle.Circular, Enum.EasingDirection.Out)
realCamTweenInfo = camTweenInfo2
end
local function TweenCameraOffset(targetOffset)
TweenService:Create(humanoid, realCamTweenInfo, {CameraOffset = targetOffset}):Play()
end
local function UpdateCamera(dt)
local lookVec = camera.CFrame.LookVector
task.delay(0.01, function()
if not character:FindFirstChildOfClass("Tool") then return end
root.CFrame = CFrame.new(root.Position, root.Position + Vector3.new(lookVec.X * MAX_LENGTH, 0, lookVec.Z * MAX_LENGTH))
end)
if zooming then
camera.FieldOfView += (ZOOM_FOV - camera.FieldOfView) * math.min(ZOOM_SPEED * dt, 1)
if tool:GetAttribute("Scope") == true then
player.PlayerGui.MainGui.Sniper.Visible = true
UserInputService.MouseIconEnabled = false
tool:WaitForChild("End").Transparency = 1
local zoom = tonumber(tool:GetAttribute("Zoom"))
local speed = tonumber(tool:GetAttribute("ZoomSpeed"))
if zoom and speed
and zoom <= 11
and speed >= 13
and game.ReplicatedStorage.Settings.IgnoreHideArmScopeStatements.Value == false then
local leftArm = character:FindFirstChild("Left Arm") or character:FindFirstChild("LeftArm")
if leftArm then
leftArm.Transparency = 1
end
local rightArm = character:FindFirstChild("Right Arm") or character:FindFirstChild("RightArm")
if rightArm then
rightArm.Transparency = 1
end
end
end
else
camera.FieldOfView += (DEFAULT_FOV - camera.FieldOfView) * math.min(ZOOM_SPEED * dt, 1)
player.PlayerGui.MainGui.Sniper.Visible = false
UserInputService.MouseIconEnabled = true
tool:WaitForChild("End").Transparency = endTransparency
local leftArm = character:FindFirstChild("Left Arm") or character:FindFirstChild("LeftArm")
if leftArm then
leftArm.Transparency = 0
end
local rightArm = character:FindFirstChild("Right Arm") or character:FindFirstChild("RightArm")
if rightArm then
rightArm.Transparency = 0
end
end
end
local function Enable()
if active then return end
active = true
humanoid.AutoRotate = false
TweenCameraOffset(playerCamOffset())
if character:FindFirstChildOfClass("Tool") then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
end
bind(RunService.RenderStepped, UpdateCamera)
frameMouselock = true
if tool:GetAttribute("MobileForceZoom") == true and UserInputService.TouchEnabled == true and not UserInputService.MouseEnabled then
zooming = true
end
end
local function Disable()
active = false
humanoid.AutoRotate = true
TweenCameraOffset(Vector3.zero)
cleanup()
frameMouselock = false
if UserInputService.TouchEnabled == true then
zooming = false
end
end
local function Shoot()
local at = tool:GetAttribute("ShootFunction")
if typeof(at) == "string" then
at = at:lower()
if at == "unzoom" then
if UserInputService.TouchEnabled == false then
zooming = false
end
elseif at == "die" then
task.wait(tool:GetAttribute("DieFunctionWait"))
local chance = tool:GetAttribute("DieChance") or 5
if math.random(1, chance) == 1 then
REMOTES:WaitForChild("KillPlayer"):FireServer()
else
REMOTES:WaitForChild("KillPlayer"):FireServer()
end
end
end
end
RequestGunSide.OnClientEvent:Connect(function(gun, side)
if gun == gunName then
currentSide = side
TweenCameraOffset(playerCamOffset())
end
end)
bind(tool.Equipped, function()
character = player.Character or player.CharacterAdded:Wait()
humanoid = character:WaitForChild("Humanoid")
root = character:WaitForChild("HumanoidRootPart")
RequestGunSide:FireServer(gunName)
Enable()
local leftArm = character:FindFirstChild("Left Arm") or character:FindFirstChild("LeftArm")
if leftArm then leftArm.Transparency = 0 end
local rightArm = character:FindFirstChild("Right Arm") or character:FindFirstChild("RightArm")
if rightArm then rightArm.Transparency = 0 end
end)
bind(tool.Unequipped, function()
Disable()
player.PlayerGui.MainGui.Sniper.Visible = false
local leftArm = character:FindFirstChild("Left Arm") or character:FindFirstChild("LeftArm")
if leftArm then leftArm.Transparency = 0 end
local rightArm = character:FindFirstChild("Right Arm") or character:FindFirstChild("RightArm")
if rightArm then rightArm.Transparency = 0 end
end)
bind(UserInputService.InputBegan, function(input, gpe)
if gpe then return end
if input.KeyCode == Enum.KeyCode.Q and active then
--currentSide = -currentSide
--TweenCameraOffset(playerCamOffset())
--ChangeGunSide:FireServer(gunName, currentSide)
if currentSide == -1 then
-- left handed
--game.ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("LeftSide"):FireServer()
elseif currentSide == 1 then
-- right handed
--game.ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("RightSide"):FireServer()
else
-- unknown
print("neither??")
--player:Kick("please report this as a bug. tell the developers 'shiftlock was neither left or right'. thanks")
end
elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
zooming = true
elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
Shoot()
end
end)
bind(UserInputService.InputEnded, function(input)
if input.UserInputType == Enum.UserInputType.MouseButton2 then
zooming = false
end
end)
bind(humanoid.Died, function()
Disable()
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
UserInputService.MouseIconEnabled = true
player.PlayerGui.MainGui.Sniper.Visible = false
end)
if player.PlayerGui:FindFirstChild("MainGui") and player.PlayerGui.MainGui:FindFirstChild("FireButton1") then
bind(player.PlayerGui.MainGui.FireButton1.MouseButton1Up, Shoot)
end
end
return module
And finally, the last script; GunLocal, which has been placed in StarterGui since it doesn’t seem to work anywhere else:
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local Debris = game:GetService("Debris")
local Bullets = ReplicatedStorage:WaitForChild("Assets"):WaitForChild("Bullets")
local BulletFolder = workspace
local BulletHoles = workspace:WaitForChild("BulletHoles") or game:GetService("ServerStorage")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait() or script.Parent.Parent.Character
local root = character:WaitForChild("HumanoidRootPart")
local humanoid = character:WaitForChild("Humanoid")
local camera = workspace.CurrentCamera
local FireGunRemote = ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("FireGun")
local equippedGun
local holdingClick = false
local MAX_LENGTH = 900000
local ENABLED_OFFSET = CFrame.new(1.7,0,0)
local DISABLED_OFFSET = CFrame.new(-1.7,0,0)
local GUN_OFFSET = CFrame.new(0,0.15,0)
local active = false
local windowFocused = true
local fireButton = player:WaitForChild("PlayerGui"):WaitForChild("MainGui"):WaitForChild("FireButton1")
local function UpdateAutoRotate(val)
humanoid.AutoRotate = not val
end
local function GetCameraCFrame()
return CFrame.new(root.Position, Vector3.new(camera.CFrame.LookVector.X * MAX_LENGTH, root.Position.Y, camera.CFrame.LookVector.Z * MAX_LENGTH))
end
UserInputService.WindowFocused:Connect(function()
windowFocused = true
end)
UserInputService.WindowFocusReleased:Connect(function()
windowFocused = false
end)
local function EnableShiftlock()
UpdateAutoRotate(false)
root.CFrame = GetCameraCFrame()
camera.CFrame = camera.CFrame * ENABLED_OFFSET
end
local function DisableShiftlock()
UpdateAutoRotate(true)
camera.CFrame = camera.CFrame * DISABLED_OFFSET
end
local function ShiftLockToggle()
if not active then
active = RunService.RenderStepped:Connect(EnableShiftlock)
else
active:Disconnect()
active = nil
DisableShiftlock()
end
end
local function beam(shooter, hitPos, tool, direction)
local isClim = false
if shooter and shooter:IsA("Player") then
local plr = game.Players:FindFirstChild(shooter.Name)
if shooter.Name:lower():find("clim") or shooter.Name == "Ihatemilasomuch" then
isClim = true
else
isClim = false
end
end
local startAttachment = Instance.new("Attachment")
--startAttachment.WorldPosition = originPos
--startAttachment.WorldPosition = tool:FindFirstChild("End").Position or tool.Handle.Position
startAttachment.Name = "StartPoint"
if CollectionService:HasTag(tool:FindFirstChild("End"), "Unused") then
startAttachment.Parent = tool:FindFirstChild("End2")
else
startAttachment.Parent = tool:FindFirstChild("End")
end
local endAttachment = Instance.new("Attachment")
endAttachment.Name = "EndPoint"
endAttachment.WorldPosition = hitPos or (tool:FindFirstChild("End").Position + direction*1000)
endAttachment.Parent = BulletFolder
local beam
if windowFocused == true then
if math.random(1, 1000) == 1 or isClim == true then
beam = Bullets:WaitForChild("Rare"):Clone()
elseif math.random(1, 670000) == 1 or tool:GetAttribute("RainbowBullets") == true then
local randomColor = Color3.fromRGB(255, 244, 93)
if tool:GetAttribute("RainbowType") == "Light" then
randomColor = Color3.fromRGB(
math.random(134, 255),
math.random(134, 255),
math.random(124, 255)
)
else
randomColor = Color3.fromRGB(
math.random(1, 255),
math.random(1, 255),
math.random(1, 255)
)
end
beam = Bullets:WaitForChild("Normal"):Clone()
beam.Color = ColorSequence.new(randomColor)
beam.Transparency = NumberSequence.new(0.67)
elseif shooter and shooter:IsA("Player") and shooter.Name:lower() == "thegoodscripter" or math.random(1, 100000) == 1 then
beam = Bullets:WaitForChild("Blood"):Clone()
else
beam = Bullets:WaitForChild("Normal"):Clone()
end
if beam then
beam.Attachment0 = startAttachment
beam.Attachment1 = endAttachment
beam.Parent = BulletFolder
task.delay(0.3, function()
task.spawn(function()
local t = 0.84
while t < 1 do
t += 0.01
if t > 1 then t = 1 end
beam.Transparency = NumberSequence.new(t)
task.wait(0.01)
end
end)
end)
Debris:AddItem(beam, 0.34)
end
if startAttachment then
Debris:AddItem(startAttachment, 10)
end
if endAttachment then
Debris:AddItem(endAttachment, 23)
end
else
print("there cant be bullet beam trails when the player isnt focused into the roblox window.")
end
end
local function onShoot()
if not equippedGun then return end
if equippedGun:GetAttribute("CanFire") == false then return end
local fireMode = equippedGun:GetAttribute("FireMode") or "Single"
equippedGun:SetAttribute("CanFire", false)
local cooldown = equippedGun:GetAttribute("Cooldown") or 0.3
local spread = equippedGun:GetAttribute("Spread") or 0.01
local gunEnd = equippedGun:FindFirstChild("End") and equippedGun.End:FindFirstChild("End")
if not gunEnd then return end
local originCF = gunEnd.WorldCFrame
local originPos = originCF.Position
local camCF = camera.CFrame
local spreadVec = (camCF.RightVector * math.random(-spread*1000, spread*1000)/1000) +
(camCF.UpVector * math.random(-spread*1000, spread*1000)/1000)
local direction
if UserInputService.TouchEnabled == true or UserInputService.GamepadEnabled == true then
direction = (camCF.LookVector + spreadVec).Unit
else
local mouse = player:GetMouse()
local toMouse = mouse.Hit.Position - originPos
direction = (toMouse + spreadVec * toMouse.Magnitude).Unit
end
if fireMode == "Flamethrower" then
FireGunRemote:FireServer(originPos, direction, equippedGun, holdingClick)
else
FireGunRemote:FireServer(originPos, direction, equippedGun)
end
local recoil = equippedGun:GetAttribute("Recoil") or 0
camera.CFrame = camera.CFrame * CFrame.Angles(math.rad(recoil), 0, 0) * GUN_OFFSET
local shakeAmt = 0.02
for i=1,2 do
camera.CFrame = camera.CFrame * CFrame.Angles(math.rad(math.random(-shakeAmt,shakeAmt)), math.rad(math.random(-shakeAmt,shakeAmt)), 0)
RunService.RenderStepped:Wait()
end
task.delay(cooldown, function()
if equippedGun then
equippedGun:SetAttribute("CanFire", true)
if holdingClick and fireMode == "Automatic" then
onShoot()
elseif holdingClick and fireMode == "Flamethrower" then
onShoot()
end
end
end)
end
local function isFirstPerson()
local head = character:FindFirstChild("Head")
if not head then return false end
local camDist = (workspace.CurrentCamera.CFrame.Position - head.Position).Magnitude
return camDist < 1.5
end
local function equipGun(tool)
if CollectionService:HasTag(tool, "Gun") then
if math.random(1, 2) == 1 then
game:GetService('SoundService'):WaitForChild("Sounds"):WaitForChild("EquipGun1"):Play()
end
equippedGun = tool
require(game:GetService("ReplicatedStorage"):WaitForChild("Modules"):WaitForChild("GunClient")).init(tool)
if UserInputService.TouchEnabled == true and character:WaitForChild("Humanoid").Health ~= 0 then
game.Players.LocalPlayer.PlayerGui.MainGui.FireButton1.Visible = true
end
if UserInputService.TouchEnabled == true or UserInputService.GamepadEnabled == true then
game.Players.LocalPlayer.PlayerGui.MainGui.MobileCursor.Visible = true
end
if equippedGun:GetAttribute("CanFire") == nil then
equippedGun:SetAttribute("CanFire", true)
end
if not isFirstPerson() then
camera.CFrame = camera.CFrame * GUN_OFFSET
end
tool.Unequipped:Connect(function()
if equippedGun then
equippedGun:SetAttribute("CanFire", true)
end
equippedGun = nil
game.Players.LocalPlayer.PlayerGui.MainGui.FireButton1.Visible = false
game.Players.LocalPlayer.PlayerGui.MainGui.MobileCursor.Visible = false
end)
end
end
local function onCharacterAdded(char)
char.ChildAdded:Connect(function(child)
if child:IsA("Tool") then
equipGun(child)
end
end)
for _, tool in ipairs(char:GetChildren()) do
if tool:IsA("Tool") and CollectionService:HasTag(tool, "Gun") then
equipGun(tool)
break
end
end
end
if player.Character then
onCharacterAdded(player.Character)
end
player.CharacterAdded:Connect(onCharacterAdded)
UserInputService.InputBegan:Connect(function(input, processed)
if processed then return end
if input.UserInputType == Enum.UserInputType.MouseButton1 then
holdingClick = true
if equippedGun and humanoid.Health ~= 0 then
onShoot()
end
elseif input.KeyCode == Enum.KeyCode.ButtonX then
--ShiftLockToggle()
elseif input.KeyCode == Enum.KeyCode.ButtonR2 then
holdingClick = true
end
end)
UserInputService.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
holdingClick = false
elseif input.KeyCode == Enum.KeyCode.ButtonR2 then
holdingClick = false
end
end)
fireButton.MouseEnter:Connect(function()
holdingClick = true
if equippedGun and humanoid.Health ~= 0 then
onShoot()
end
end)
fireButton.MouseLeave:Connect(function()
holdingClick = false
end)
character.Humanoid.Died:Connect(function()
game.Players.LocalPlayer.PlayerGui.MainGui.FireButton1.Visible = false
game.Players.LocalPlayer.PlayerGui.MainGui.MobileCursor.Visible = false
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end)
player.CharacterAdded:Connect(function()
game.Players.LocalPlayer.PlayerGui.MainGui.FireButton1.Visible = false
game.Players.LocalPlayer.PlayerGui.MainGui.MobileCursor.Visible = false
end)
game:GetService("ReplicatedStorage"):WaitForChild("Remotes"):WaitForChild("FireParticle").OnClientEvent:Connect(function(tool)
local fpcooldown = false
if windowFocused == true then
if fpcooldown == true then return end
if windowFocused == false then return end
fpcooldown = true
local fx = game:GetService("ReplicatedStorage"):WaitForChild("Assets"):WaitForChild("Particles"):WaitForChild("FireGun"):Clone()
fx.Parent = tool:WaitForChild("End"):WaitForChild("End", 5) or tool:FindFirstChild("End")
fx:Emit()
game:GetService("Debris"):AddItem(fx, 0.2)
task.delay(0.02, function()
fpcooldown = false
end)
else
if windowFocused == false then
print("there cant be any fire particles if the user isnt focused on the roblox window")
elseif fpcooldown == true then
print("there cant be any fire particles if the fire particles are on cooldown obviously")
end
end
end)
game:GetService("ReplicatedStorage"):WaitForChild("Remotes"):WaitForChild("BulletTrail").OnClientEvent:Connect(function(tool, hitPos, shooter, direction)
beam(shooter, hitPos, tool, direction)
end)
local function fixCharacterMeshes(model)
for _, descendant in ipairs(model:GetDescendants()) do
if descendant:IsA("CharacterMesh") and descendant.OverlayTextureId == 193346779 then
descendant.OverlayTextureId = 92812880889460
end
end
end
local function familyfriendly()
BulletHoles.ChildAdded:Connect(function(child)
if child.Name == "Blood" or child.Name == "Gore" then
child:Destroy()
end
end)
for _, child in ipairs(workspace:WaitForChild("BulletHoles")) do
if child.Name == "Blood" or child.Name == "Gore" then
child:Destroy()
end
end
if not game:GetService("TextChatService"):CanUserChatAsync(player.UserId) then
workspace:WaitForChild("NPCS").ChildAdded:Connect(function(enemy)
if enemy:IsA("Model") then
fixCharacterMeshes(enemy)
end
end)
for _, enemy in ipairs(workspace:WaitForChild("NPCS"):GetChildren()) do
if enemy:IsA("Model") then
fixCharacterMeshes(enemy)
end
end
end
end
if UserInputService.GamepadEnabled == true or RunService:IsStudio() then
familyfriendly()
end
--player.Character.Died:Connect(function)
Yeah, I know family-friendly mode is really badly made and may not work every time…
Workspace has systems which are based off things from other experiences, most notible ones are;
Zombie Survival Tycoon
The entire art style of the game is inspired by the map from this experience. I originally found the day music songs Crystal Clear and I’m Gonna Get Up, and for the night music, Night Vision, Last Man Standing, Rocket. Also Crystal Clear and I’m Gonna Get Up are used for both day and night music.
I also used the dev-console > memory > sounds trick to use the same audio as Zombie Survival Tycoon
Ultimate Town Multiplayer
I experimented with Ultimate Town Multiplayer’s weapon system while making Workspaces guns.
I also used the dev-console > memory > sounds trick to use the same audio as Ultimate Town Multiplayer
Build Defense
The idea of enemies is really good, all my games with enemies such as zombies and skeletons was always inspired by Build Defense, Also I originally found the songs Stealth Mode and Start the Echo in this game. Workspace shares many features with Build Defense such as sentries, natural disasters like floods and tsunamis.
Moving on, what are the similarities between Ultimate Town Multiplayer and Workspace?
Well, nothing except the gun system, the comparisons are below.
They both look completely different; however, they are both very similar. The bottom one (Workspace) is supposed to have a mouse cursor in the middle, but since screenshotting disables the cursor, I wasn’t able to catch it.
The bullet holes are similar to the ones in Ultimate Town Multiplayer
Hit dust effects are nearly identicle to the ones in Zombie Survival Tycoon, but we’re talking about Ultimate Town Multiplayer, so what makes workspace similar to Ultimate Town Multiplayer? Weapons.
Many workspace weapons are originally from Ultimate Town Multiplayer, (NOT DECOMPILED, BUT INSTEAD REMADE USING DIFFERENT ASSETS!)
How are the hit-dust particles in Workspace similar to Zombie Survival Tycoon?
In Zombie Survival Tycoon, the dust seems to float up, then fade away instead of going back down. But Workspace is more complicated. Workspace has a 50/50 chance of which hit-dust particle to use, one looking normal, and the other looking more like regular household dust. Neither behaving like Zombie Survival Tycoon’s hit-dust particles.
What about the trees? how were the trees made? The pine tree leaves were not originally a mesh. They were used in many official Roblox games such as Suburban. But Workspace uses the mesh version of the tree leaves! How is it possible? Where was the mesh from? Since nobody even knows how blender works, of course it’s a free model, which was uploaded by MrBbolt




